github.com/arunkumar7540/cli@v6.45.0+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  	Metadata            *Metadata
    21  }
    22  
    23  func (app Application) Started() bool {
    24  	return app.State == constant.ApplicationStarted
    25  }
    26  
    27  func (app Application) Stopped() bool {
    28  	return app.State == constant.ApplicationStopped
    29  }
    30  
    31  func (actor Actor) DeleteApplicationByNameAndSpace(name string, spaceGUID string) (Warnings, error) {
    32  	var allWarnings Warnings
    33  
    34  	app, getAppWarnings, err := actor.GetApplicationByNameAndSpace(name, spaceGUID)
    35  	allWarnings = append(allWarnings, getAppWarnings...)
    36  	if err != nil {
    37  		return allWarnings, err
    38  	}
    39  
    40  	jobURL, deleteAppWarnings, err := actor.CloudControllerClient.DeleteApplication(app.GUID)
    41  	allWarnings = append(allWarnings, deleteAppWarnings...)
    42  	if err != nil {
    43  		return allWarnings, err
    44  	}
    45  
    46  	pollWarnings, err := actor.CloudControllerClient.PollJob(jobURL)
    47  	allWarnings = append(allWarnings, pollWarnings...)
    48  	return allWarnings, err
    49  }
    50  
    51  func (actor Actor) GetApplicationsByNamesAndSpace(appNames []string, spaceGUID string) ([]Application, Warnings, error) {
    52  	apps, warnings, err := actor.CloudControllerClient.GetApplications(
    53  		ccv3.Query{Key: ccv3.NameFilter, Values: appNames},
    54  		ccv3.Query{Key: ccv3.SpaceGUIDFilter, Values: []string{spaceGUID}},
    55  	)
    56  
    57  	if err != nil {
    58  		return nil, Warnings(warnings), err
    59  	}
    60  
    61  	if len(apps) < len(appNames) {
    62  		return nil, Warnings(warnings), actionerror.ApplicationsNotFoundError{}
    63  	}
    64  
    65  	actorApps := []Application{}
    66  	for _, a := range apps {
    67  		actorApps = append(actorApps, actor.convertCCToActorApplication(a))
    68  	}
    69  	return actorApps, Warnings(warnings), nil
    70  }
    71  
    72  // GetApplicationByNameAndSpace returns the application with the given
    73  // name in the given space.
    74  func (actor Actor) GetApplicationByNameAndSpace(appName string, spaceGUID string) (Application, Warnings, error) {
    75  	apps, warnings, err := actor.GetApplicationsByNamesAndSpace([]string{appName}, spaceGUID)
    76  
    77  	if err != nil {
    78  		if _, ok := err.(actionerror.ApplicationsNotFoundError); ok {
    79  			return Application{}, warnings, actionerror.ApplicationNotFoundError{Name: appName}
    80  		}
    81  		return Application{}, warnings, err
    82  	}
    83  
    84  	return apps[0], warnings, nil
    85  }
    86  
    87  // GetApplicationsBySpace returns all applications in a space.
    88  func (actor Actor) GetApplicationsBySpace(spaceGUID string) ([]Application, Warnings, error) {
    89  	ccApps, warnings, err := actor.CloudControllerClient.GetApplications(
    90  		ccv3.Query{Key: ccv3.SpaceGUIDFilter, Values: []string{spaceGUID}},
    91  	)
    92  
    93  	if err != nil {
    94  		return []Application{}, Warnings(warnings), err
    95  	}
    96  
    97  	var apps []Application
    98  	for _, ccApp := range ccApps {
    99  		apps = append(apps, actor.convertCCToActorApplication(ccApp))
   100  	}
   101  	return apps, Warnings(warnings), nil
   102  }
   103  
   104  // CreateApplicationInSpace creates and returns the application with the given
   105  // name in the given space.
   106  func (actor Actor) CreateApplicationInSpace(app Application, spaceGUID string) (Application, Warnings, error) {
   107  	createdApp, warnings, err := actor.CloudControllerClient.CreateApplication(
   108  		ccv3.Application{
   109  			LifecycleType:       app.LifecycleType,
   110  			LifecycleBuildpacks: app.LifecycleBuildpacks,
   111  			StackName:           app.StackName,
   112  			Name:                app.Name,
   113  			Relationships: ccv3.Relationships{
   114  				constant.RelationshipTypeSpace: ccv3.Relationship{GUID: spaceGUID},
   115  			},
   116  		})
   117  
   118  	if err != nil {
   119  		if _, ok := err.(ccerror.NameNotUniqueInSpaceError); ok {
   120  			return Application{}, Warnings(warnings), actionerror.ApplicationAlreadyExistsError{Name: app.Name}
   121  		}
   122  		return Application{}, Warnings(warnings), err
   123  	}
   124  
   125  	return actor.convertCCToActorApplication(createdApp), Warnings(warnings), nil
   126  }
   127  
   128  // SetApplicationProcessHealthCheckTypeByNameAndSpace sets the health check
   129  // information of the provided processType for an application with the given
   130  // name and space GUID.
   131  func (actor Actor) SetApplicationProcessHealthCheckTypeByNameAndSpace(
   132  	appName string,
   133  	spaceGUID string,
   134  	healthCheckType constant.HealthCheckType,
   135  	httpEndpoint string,
   136  	processType string,
   137  	invocationTimeout int64,
   138  ) (Application, Warnings, error) {
   139  
   140  	app, getWarnings, err := actor.GetApplicationByNameAndSpace(appName, spaceGUID)
   141  	if err != nil {
   142  		return Application{}, getWarnings, err
   143  	}
   144  
   145  	setWarnings, err := actor.UpdateProcessByTypeAndApplication(
   146  		processType,
   147  		app.GUID,
   148  		Process{
   149  			HealthCheckType:              healthCheckType,
   150  			HealthCheckEndpoint:          httpEndpoint,
   151  			HealthCheckInvocationTimeout: invocationTimeout,
   152  		})
   153  	return app, append(getWarnings, setWarnings...), err
   154  }
   155  
   156  // StopApplication stops an application.
   157  func (actor Actor) StopApplication(appGUID string) (Warnings, error) {
   158  	_, warnings, err := actor.CloudControllerClient.UpdateApplicationStop(appGUID)
   159  
   160  	return Warnings(warnings), err
   161  }
   162  
   163  // StartApplication starts an application.
   164  func (actor Actor) StartApplication(appGUID string) (Application, Warnings, error) {
   165  	updatedApp, warnings, err := actor.CloudControllerClient.UpdateApplicationStart(appGUID)
   166  	if err != nil {
   167  		return Application{}, Warnings(warnings), err
   168  	}
   169  
   170  	return actor.convertCCToActorApplication(updatedApp), Warnings(warnings), nil
   171  }
   172  
   173  // RestartApplication restarts an application and waits for it to start.
   174  func (actor Actor) RestartApplication(appGUID string) (Warnings, error) {
   175  	var allWarnings Warnings
   176  	_, warnings, err := actor.CloudControllerClient.UpdateApplicationRestart(appGUID)
   177  	allWarnings = append(allWarnings, warnings...)
   178  	if err != nil {
   179  		return allWarnings, err
   180  	}
   181  
   182  	pollingWarnings, err := actor.PollStart(appGUID)
   183  	allWarnings = append(allWarnings, pollingWarnings...)
   184  	return allWarnings, err
   185  }
   186  
   187  func (actor Actor) PollStart(appGUID string) (Warnings, error) {
   188  	var allWarnings Warnings
   189  	processes, warnings, err := actor.CloudControllerClient.GetApplicationProcesses(appGUID)
   190  	allWarnings = append(allWarnings, warnings...)
   191  	if err != nil {
   192  		return allWarnings, err
   193  	}
   194  
   195  	timeout := time.Now().Add(actor.Config.StartupTimeout())
   196  	for time.Now().Before(timeout) {
   197  		allProcessesDone := true
   198  		for _, process := range processes {
   199  			shouldContinuePolling, warnings, err := actor.shouldContinuePollingProcessStatus(process)
   200  			allWarnings = append(allWarnings, warnings...)
   201  			if err != nil {
   202  				return allWarnings, err
   203  			}
   204  
   205  			if shouldContinuePolling {
   206  				allProcessesDone = false
   207  				break
   208  			}
   209  		}
   210  
   211  		if allProcessesDone {
   212  			return allWarnings, nil
   213  		}
   214  		time.Sleep(actor.Config.PollingInterval())
   215  	}
   216  
   217  	return allWarnings, actionerror.StartupTimeoutError{}
   218  }
   219  
   220  // UpdateApplication updates the buildpacks on an application
   221  func (actor Actor) UpdateApplication(app Application) (Application, Warnings, error) {
   222  	ccApp := ccv3.Application{
   223  		GUID:                app.GUID,
   224  		StackName:           app.StackName,
   225  		LifecycleType:       app.LifecycleType,
   226  		LifecycleBuildpacks: app.LifecycleBuildpacks,
   227  		Metadata:            (*ccv3.Metadata)(app.Metadata),
   228  	}
   229  
   230  	updatedApp, warnings, err := actor.CloudControllerClient.UpdateApplication(ccApp)
   231  	if err != nil {
   232  		return Application{}, Warnings(warnings), err
   233  	}
   234  
   235  	return actor.convertCCToActorApplication(updatedApp), Warnings(warnings), nil
   236  }
   237  
   238  func (Actor) convertCCToActorApplication(app ccv3.Application) Application {
   239  	return Application{
   240  		GUID:                app.GUID,
   241  		StackName:           app.StackName,
   242  		LifecycleType:       app.LifecycleType,
   243  		LifecycleBuildpacks: app.LifecycleBuildpacks,
   244  		Name:                app.Name,
   245  		State:               app.State,
   246  		Metadata:            (*Metadata)(app.Metadata),
   247  	}
   248  }
   249  
   250  func (actor Actor) shouldContinuePollingProcessStatus(process ccv3.Process) (bool, Warnings, error) {
   251  	ccInstances, ccWarnings, err := actor.CloudControllerClient.GetProcessInstances(process.GUID)
   252  	instances := ProcessInstances(ccInstances)
   253  	warnings := Warnings(ccWarnings)
   254  	if err != nil {
   255  		return true, warnings, err
   256  	}
   257  
   258  	if instances.Empty() || instances.AnyRunning() {
   259  		return false, warnings, nil
   260  	} else if instances.AllCrashed() {
   261  		return false, warnings, actionerror.AllInstancesCrashedError{}
   262  	}
   263  
   264  	return true, warnings, nil
   265  }