github.com/randomtask1155/cli@v6.41.1-0.20181227003417-a98eed78cbde+incompatible/actor/v7action/application.go (about)

     1  package v7action
     2  
     3  import (
     4  	"time"
     5  
     6  	"code.cloudfoundry.org/cli/actor/actionerror"
     7  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccerror"
     8  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3"
     9  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant"
    10  )
    11  
    12  // Application represents a V3 actor application.
    13  type Application struct {
    14  	Name                string
    15  	GUID                string
    16  	StackName           string
    17  	State               constant.ApplicationState
    18  	LifecycleType       constant.AppLifecycleType
    19  	LifecycleBuildpacks []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  // CreateApplicationInSpace creates and returns the application with the given
    86  // name in the given space.
    87  func (actor Actor) CreateApplicationInSpace(app Application, spaceGUID string) (Application, Warnings, error) {
    88  	createdApp, warnings, err := actor.CloudControllerClient.CreateApplication(
    89  		ccv3.Application{
    90  			LifecycleType:       app.LifecycleType,
    91  			LifecycleBuildpacks: app.LifecycleBuildpacks,
    92  			StackName:           app.StackName,
    93  			Name:                app.Name,
    94  			Relationships: ccv3.Relationships{
    95  				constant.RelationshipTypeSpace: ccv3.Relationship{GUID: spaceGUID},
    96  			},
    97  		})
    98  
    99  	if err != nil {
   100  		if _, ok := err.(ccerror.NameNotUniqueInSpaceError); ok {
   101  			return Application{}, Warnings(warnings), actionerror.ApplicationAlreadyExistsError{Name: app.Name}
   102  		}
   103  		return Application{}, Warnings(warnings), err
   104  	}
   105  
   106  	return actor.convertCCToActorApplication(createdApp), Warnings(warnings), nil
   107  }
   108  
   109  // SetApplicationProcessHealthCheckTypeByNameAndSpace sets the health check
   110  // information of the provided processType for an application with the given
   111  // name and space GUID.
   112  func (actor Actor) SetApplicationProcessHealthCheckTypeByNameAndSpace(
   113  	appName string,
   114  	spaceGUID string,
   115  	healthCheckType constant.HealthCheckType,
   116  	httpEndpoint string,
   117  	processType string,
   118  	invocationTimeout int,
   119  ) (Application, Warnings, error) {
   120  
   121  	app, getWarnings, err := actor.GetApplicationByNameAndSpace(appName, spaceGUID)
   122  	if err != nil {
   123  		return Application{}, getWarnings, err
   124  	}
   125  
   126  	setWarnings, err := actor.UpdateProcessByTypeAndApplication(
   127  		processType,
   128  		app.GUID,
   129  		Process{
   130  			HealthCheckType:              healthCheckType,
   131  			HealthCheckEndpoint:          httpEndpoint,
   132  			HealthCheckInvocationTimeout: invocationTimeout,
   133  		})
   134  	return app, append(getWarnings, setWarnings...), err
   135  }
   136  
   137  // StopApplication stops an application.
   138  func (actor Actor) StopApplication(appGUID string) (Warnings, error) {
   139  	_, warnings, err := actor.CloudControllerClient.UpdateApplicationStop(appGUID)
   140  
   141  	return Warnings(warnings), err
   142  }
   143  
   144  // StartApplication starts an application.
   145  func (actor Actor) StartApplication(appGUID string) (Application, Warnings, error) {
   146  	updatedApp, warnings, err := actor.CloudControllerClient.UpdateApplicationStart(appGUID)
   147  	if err != nil {
   148  		return Application{}, Warnings(warnings), err
   149  	}
   150  
   151  	return actor.convertCCToActorApplication(updatedApp), Warnings(warnings), nil
   152  }
   153  
   154  // RestartApplication restarts an application and waits for it to start.
   155  func (actor Actor) RestartApplication(appGUID string) (Warnings, error) {
   156  	var allWarnings Warnings
   157  	_, warnings, err := actor.CloudControllerClient.UpdateApplicationRestart(appGUID)
   158  	allWarnings = append(allWarnings, warnings...)
   159  	if err != nil {
   160  		return allWarnings, err
   161  	}
   162  
   163  	pollingWarnings, err := actor.PollStart(appGUID)
   164  	allWarnings = append(allWarnings, pollingWarnings...)
   165  	return allWarnings, err
   166  }
   167  
   168  func (actor Actor) PollStart(appGUID string) (Warnings, error) {
   169  	var allWarnings Warnings
   170  	processes, warnings, err := actor.CloudControllerClient.GetApplicationProcesses(appGUID)
   171  	allWarnings = append(allWarnings, warnings...)
   172  	if err != nil {
   173  		return allWarnings, err
   174  	}
   175  
   176  	timeout := time.Now().Add(actor.Config.StartupTimeout())
   177  	for time.Now().Before(timeout) {
   178  		allProcessesDone := true
   179  		for _, process := range processes {
   180  			shouldContinuePolling, warnings, err := actor.shouldContinuePollingProcessStatus(process)
   181  			allWarnings = append(allWarnings, warnings...)
   182  			if err != nil {
   183  				return allWarnings, err
   184  			}
   185  
   186  			if shouldContinuePolling {
   187  				allProcessesDone = false
   188  				break
   189  			}
   190  		}
   191  
   192  		if allProcessesDone {
   193  			return allWarnings, nil
   194  		}
   195  		time.Sleep(actor.Config.PollingInterval())
   196  	}
   197  
   198  	return allWarnings, actionerror.StartupTimeoutError{}
   199  }
   200  
   201  // UpdateApplication updates the buildpacks on an application
   202  func (actor Actor) UpdateApplication(app Application) (Application, Warnings, error) {
   203  	ccApp := ccv3.Application{
   204  		GUID:                app.GUID,
   205  		StackName:           app.StackName,
   206  		LifecycleType:       app.LifecycleType,
   207  		LifecycleBuildpacks: app.LifecycleBuildpacks,
   208  	}
   209  
   210  	updatedApp, warnings, err := actor.CloudControllerClient.UpdateApplication(ccApp)
   211  	if err != nil {
   212  		return Application{}, Warnings(warnings), err
   213  	}
   214  
   215  	return actor.convertCCToActorApplication(updatedApp), Warnings(warnings), nil
   216  }
   217  
   218  func (Actor) convertCCToActorApplication(app ccv3.Application) Application {
   219  	return Application{
   220  		GUID:                app.GUID,
   221  		StackName:           app.StackName,
   222  		LifecycleType:       app.LifecycleType,
   223  		LifecycleBuildpacks: app.LifecycleBuildpacks,
   224  		Name:                app.Name,
   225  		State:               app.State,
   226  	}
   227  }
   228  
   229  func (actor Actor) shouldContinuePollingProcessStatus(process ccv3.Process) (bool, Warnings, error) {
   230  	ccInstances, ccWarnings, err := actor.CloudControllerClient.GetProcessInstances(process.GUID)
   231  	instances := ProcessInstances(ccInstances)
   232  	warnings := Warnings(ccWarnings)
   233  	if err != nil {
   234  		return true, warnings, err
   235  	}
   236  
   237  	if instances.Empty() || instances.AnyRunning() {
   238  		return false, warnings, nil
   239  	} else if instances.AllCrashed() {
   240  		return false, warnings, actionerror.AllInstancesCrashedError{}
   241  	}
   242  
   243  	return true, warnings, nil
   244  }