github.com/randomtask1155/cli@v6.41.1-0.20181227003417-a98eed78cbde+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/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  // StopApplication stops an application.
   110  func (actor Actor) StopApplication(appGUID string) (Warnings, error) {
   111  	_, warnings, err := actor.CloudControllerClient.UpdateApplicationStop(appGUID)
   112  
   113  	return Warnings(warnings), err
   114  }
   115  
   116  // StartApplication starts an application.
   117  func (actor Actor) StartApplication(appGUID string) (Application, Warnings, error) {
   118  	updatedApp, warnings, err := actor.CloudControllerClient.UpdateApplicationStart(appGUID)
   119  	if err != nil {
   120  		return Application{}, Warnings(warnings), err
   121  	}
   122  
   123  	return actor.convertCCToActorApplication(updatedApp), Warnings(warnings), nil
   124  }
   125  
   126  // RestartApplication restarts an application.
   127  func (actor Actor) RestartApplication(appGUID string) (Warnings, error) {
   128  	_, warnings, err := actor.CloudControllerClient.UpdateApplicationRestart(appGUID)
   129  
   130  	return Warnings(warnings), err
   131  }
   132  
   133  func (actor Actor) PollStart(appGUID string, warningsChannel chan<- Warnings) error {
   134  	processes, warnings, err := actor.CloudControllerClient.GetApplicationProcesses(appGUID)
   135  	warningsChannel <- Warnings(warnings)
   136  	if err != nil {
   137  		return err
   138  	}
   139  
   140  	timeout := time.Now().Add(actor.Config.StartupTimeout())
   141  	for time.Now().Before(timeout) {
   142  		readyProcs := 0
   143  		for _, process := range processes {
   144  			ready, err := actor.processStatus(process, warningsChannel)
   145  			if err != nil {
   146  				return err
   147  			}
   148  
   149  			if ready {
   150  				readyProcs++
   151  			}
   152  		}
   153  
   154  		if readyProcs == len(processes) {
   155  			return nil
   156  		}
   157  		time.Sleep(actor.Config.PollingInterval())
   158  	}
   159  
   160  	return actionerror.StartupTimeoutError{}
   161  }
   162  
   163  // UpdateApplication updates the buildpacks on an application
   164  func (actor Actor) UpdateApplication(app Application) (Application, Warnings, error) {
   165  	ccApp := ccv3.Application{
   166  		GUID:                app.GUID,
   167  		StackName:           app.StackName,
   168  		LifecycleType:       app.LifecycleType,
   169  		LifecycleBuildpacks: app.LifecycleBuildpacks,
   170  	}
   171  
   172  	updatedApp, warnings, err := actor.CloudControllerClient.UpdateApplication(ccApp)
   173  	if err != nil {
   174  		return Application{}, Warnings(warnings), err
   175  	}
   176  
   177  	return actor.convertCCToActorApplication(updatedApp), Warnings(warnings), nil
   178  }
   179  
   180  func (Actor) convertCCToActorApplication(app ccv3.Application) Application {
   181  	return Application{
   182  		GUID:                app.GUID,
   183  		StackName:           app.StackName,
   184  		LifecycleType:       app.LifecycleType,
   185  		LifecycleBuildpacks: app.LifecycleBuildpacks,
   186  		Name:                app.Name,
   187  		State:               app.State,
   188  	}
   189  }
   190  
   191  func (actor Actor) processStatus(process ccv3.Process, warningsChannel chan<- Warnings) (bool, error) {
   192  	instances, warnings, err := actor.CloudControllerClient.GetProcessInstances(process.GUID)
   193  	warningsChannel <- Warnings(warnings)
   194  	if err != nil {
   195  		return false, err
   196  	}
   197  	if len(instances) == 0 {
   198  		return true, nil
   199  	}
   200  
   201  	for _, instance := range instances {
   202  		if instance.State == constant.ProcessInstanceRunning {
   203  			return true, nil
   204  		}
   205  	}
   206  
   207  	for _, instance := range instances {
   208  		if instance.State != constant.ProcessInstanceCrashed {
   209  			return false, nil
   210  		}
   211  	}
   212  
   213  	// all of the instances are crashed at this point
   214  	return true, nil
   215  }