github.com/mook-as/cf-cli@v7.0.0-beta.28.0.20200120190804-b91c115fae48+incompatible/actor/v3action/application.go (about)

     1  package v3action
     2  
     3  import (
     4  	"time"
     5  
     6  	"code.cloudfoundry.org/cli/actor/actionerror"
     7  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3"
     8  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant"
     9  )
    10  
    11  // Application represents a V3 actor application.
    12  type Application struct {
    13  	Name                string
    14  	GUID                string
    15  	StackName           string
    16  	State               constant.ApplicationState
    17  	LifecycleType       constant.AppLifecycleType
    18  	LifecycleBuildpacks []string
    19  	SpaceGUID           string
    20  }
    21  
    22  func (app Application) Started() bool {
    23  	return app.State == constant.ApplicationStarted
    24  }
    25  
    26  func (app Application) Stopped() bool {
    27  	return app.State == constant.ApplicationStopped
    28  }
    29  
    30  func (actor Actor) DeleteApplicationByNameAndSpace(name string, spaceGUID string) (Warnings, error) {
    31  	var allWarnings Warnings
    32  
    33  	app, getAppWarnings, err := actor.GetApplicationByNameAndSpace(name, spaceGUID)
    34  	allWarnings = append(allWarnings, getAppWarnings...)
    35  	if err != nil {
    36  		return allWarnings, err
    37  	}
    38  
    39  	jobURL, deleteAppWarnings, err := actor.CloudControllerClient.DeleteApplication(app.GUID)
    40  	allWarnings = append(allWarnings, deleteAppWarnings...)
    41  	if err != nil {
    42  		return allWarnings, err
    43  	}
    44  
    45  	pollWarnings, err := actor.CloudControllerClient.PollJob(jobURL)
    46  	allWarnings = append(allWarnings, pollWarnings...)
    47  	return allWarnings, err
    48  }
    49  
    50  // GetApplicationByNameAndSpace returns the application with the given
    51  // name in the given space.
    52  func (actor Actor) GetApplicationByNameAndSpace(appName string, spaceGUID string) (Application, Warnings, error) {
    53  	apps, warnings, err := actor.CloudControllerClient.GetApplications(
    54  		ccv3.Query{Key: ccv3.NameFilter, Values: []string{appName}},
    55  		ccv3.Query{Key: ccv3.SpaceGUIDFilter, Values: []string{spaceGUID}},
    56  	)
    57  	if err != nil {
    58  		return Application{}, Warnings(warnings), err
    59  	}
    60  
    61  	if len(apps) == 0 {
    62  		return Application{}, Warnings(warnings), actionerror.ApplicationNotFoundError{Name: appName}
    63  	}
    64  
    65  	return actor.convertCCToActorApplication(apps[0]), Warnings(warnings), nil
    66  }
    67  
    68  // GetApplicationsBySpace returns all applications in a space.
    69  func (actor Actor) GetApplicationsBySpace(spaceGUID string) ([]Application, Warnings, error) {
    70  	ccApps, warnings, err := actor.CloudControllerClient.GetApplications(
    71  		ccv3.Query{Key: ccv3.SpaceGUIDFilter, Values: []string{spaceGUID}},
    72  	)
    73  
    74  	if err != nil {
    75  		return []Application{}, Warnings(warnings), err
    76  	}
    77  
    78  	var apps []Application
    79  	for _, ccApp := range ccApps {
    80  		apps = append(apps, actor.convertCCToActorApplication(ccApp))
    81  	}
    82  	return apps, Warnings(warnings), nil
    83  }
    84  
    85  // GetApplicationsByGUIDs returns all applications with the provided GUIDs.
    86  func (actor Actor) GetApplicationsByGUIDs(appGUIDs ...string) ([]Application, Warnings, error) {
    87  	ccApps, warnings, err := actor.CloudControllerClient.GetApplications(
    88  		ccv3.Query{Key: ccv3.GUIDFilter, Values: appGUIDs},
    89  	)
    90  
    91  	if err != nil {
    92  		return []Application{}, Warnings(warnings), err
    93  	}
    94  
    95  	var apps []Application
    96  	for _, ccApp := range ccApps {
    97  		apps = append(apps, actor.convertCCToActorApplication(ccApp))
    98  	}
    99  	return apps, Warnings(warnings), nil
   100  }
   101  
   102  // CreateApplicationInSpace creates and returns the application with the given
   103  // name in the given space.
   104  func (actor Actor) CreateApplicationInSpace(app Application, spaceGUID string) (Application, Warnings, error) {
   105  	createdApp, warnings, err := actor.CloudControllerClient.CreateApplication(
   106  		ccv3.Application{
   107  			LifecycleType:       app.LifecycleType,
   108  			LifecycleBuildpacks: app.LifecycleBuildpacks,
   109  			StackName:           app.StackName,
   110  			Name:                app.Name,
   111  			Relationships: ccv3.Relationships{
   112  				constant.RelationshipTypeSpace: ccv3.Relationship{GUID: spaceGUID},
   113  			},
   114  		})
   115  
   116  	if err != nil {
   117  		return Application{}, Warnings(warnings), err
   118  	}
   119  
   120  	return actor.convertCCToActorApplication(createdApp), Warnings(warnings), nil
   121  }
   122  
   123  // StopApplication stops an application.
   124  func (actor Actor) StopApplication(appGUID string) (Warnings, error) {
   125  	_, warnings, err := actor.CloudControllerClient.UpdateApplicationStop(appGUID)
   126  
   127  	return Warnings(warnings), err
   128  }
   129  
   130  // StartApplication starts an application.
   131  func (actor Actor) StartApplication(appGUID string) (Warnings, error) {
   132  	_, warnings, err := actor.CloudControllerClient.UpdateApplicationStart(appGUID)
   133  	if err != nil {
   134  		return Warnings(warnings), err
   135  	}
   136  
   137  	return Warnings(warnings), nil
   138  }
   139  
   140  // RestartApplication restarts an application.
   141  func (actor Actor) RestartApplication(appGUID string) (Warnings, error) {
   142  	_, warnings, err := actor.CloudControllerClient.UpdateApplicationRestart(appGUID)
   143  
   144  	return Warnings(warnings), err
   145  }
   146  
   147  func (actor Actor) PollStart(appGUID string, warningsChannel chan<- Warnings) error {
   148  	processes, warnings, err := actor.CloudControllerClient.GetApplicationProcesses(appGUID)
   149  	warningsChannel <- Warnings(warnings)
   150  	if err != nil {
   151  		return err
   152  	}
   153  
   154  	timeout := time.Now().Add(actor.Config.StartupTimeout())
   155  	for time.Now().Before(timeout) {
   156  		readyProcs := 0
   157  		for _, process := range processes {
   158  			ready, err := actor.processStatus(process, warningsChannel)
   159  			if err != nil {
   160  				return err
   161  			}
   162  
   163  			if ready {
   164  				readyProcs++
   165  			}
   166  		}
   167  
   168  		if readyProcs == len(processes) {
   169  			return nil
   170  		}
   171  		time.Sleep(actor.Config.PollingInterval())
   172  	}
   173  
   174  	return actionerror.StartupTimeoutError{}
   175  }
   176  
   177  // UpdateApplication updates the buildpacks on an application
   178  func (actor Actor) UpdateApplication(app Application) (Application, Warnings, error) {
   179  	ccApp := ccv3.Application{
   180  		GUID:                app.GUID,
   181  		StackName:           app.StackName,
   182  		LifecycleType:       app.LifecycleType,
   183  		LifecycleBuildpacks: app.LifecycleBuildpacks,
   184  	}
   185  
   186  	updatedApp, warnings, err := actor.CloudControllerClient.UpdateApplication(ccApp)
   187  	if err != nil {
   188  		return Application{}, Warnings(warnings), err
   189  	}
   190  
   191  	return actor.convertCCToActorApplication(updatedApp), Warnings(warnings), nil
   192  }
   193  
   194  func (Actor) convertCCToActorApplication(app ccv3.Application) Application {
   195  	return Application{
   196  		GUID:                app.GUID,
   197  		StackName:           app.StackName,
   198  		LifecycleType:       app.LifecycleType,
   199  		LifecycleBuildpacks: app.LifecycleBuildpacks,
   200  		Name:                app.Name,
   201  		State:               app.State,
   202  		SpaceGUID:           app.Relationships[constant.RelationshipTypeSpace].GUID,
   203  	}
   204  }
   205  
   206  func (actor Actor) processStatus(process ccv3.Process, warningsChannel chan<- Warnings) (bool, error) {
   207  	instances, warnings, err := actor.CloudControllerClient.GetProcessInstances(process.GUID)
   208  	warningsChannel <- Warnings(warnings)
   209  	if err != nil {
   210  		return false, err
   211  	}
   212  	if len(instances) == 0 {
   213  		return true, nil
   214  	}
   215  
   216  	for _, instance := range instances {
   217  		if instance.State == constant.ProcessInstanceRunning {
   218  			return true, nil
   219  		}
   220  	}
   221  
   222  	for _, instance := range instances {
   223  		if instance.State != constant.ProcessInstanceCrashed {
   224  			return false, nil
   225  		}
   226  	}
   227  
   228  	// all of the instances are crashed at this point
   229  	return true, nil
   230  }