github.com/nimakaviani/cli@v6.37.1-0.20180619223813-e734901a73fa+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  	State               constant.ApplicationState
    17  	LifecycleType       constant.AppLifecycleType
    18  	LifecycleBuildpacks []string
    19  }
    20  
    21  func (app Application) Started() bool {
    22  	return app.State == constant.ApplicationStarted
    23  }
    24  
    25  func (actor Actor) DeleteApplicationByNameAndSpace(name string, spaceGUID string) (Warnings, error) {
    26  	var allWarnings Warnings
    27  
    28  	app, getAppWarnings, err := actor.GetApplicationByNameAndSpace(name, spaceGUID)
    29  	allWarnings = append(allWarnings, getAppWarnings...)
    30  	if err != nil {
    31  		return allWarnings, err
    32  	}
    33  
    34  	jobURL, deleteAppWarnings, err := actor.CloudControllerClient.DeleteApplication(app.GUID)
    35  	allWarnings = append(allWarnings, deleteAppWarnings...)
    36  	if err != nil {
    37  		return allWarnings, err
    38  	}
    39  
    40  	pollWarnings, err := actor.CloudControllerClient.PollJob(jobURL)
    41  	allWarnings = append(allWarnings, pollWarnings...)
    42  	return allWarnings, err
    43  }
    44  
    45  // GetApplicationByNameAndSpace returns the application with the given
    46  // name in the given space.
    47  func (actor Actor) GetApplicationByNameAndSpace(appName string, spaceGUID string) (Application, Warnings, error) {
    48  	apps, warnings, err := actor.CloudControllerClient.GetApplications(
    49  		ccv3.Query{Key: ccv3.NameFilter, Values: []string{appName}},
    50  		ccv3.Query{Key: ccv3.SpaceGUIDFilter, Values: []string{spaceGUID}},
    51  	)
    52  	if err != nil {
    53  		return Application{}, Warnings(warnings), err
    54  	}
    55  
    56  	if len(apps) == 0 {
    57  		return Application{}, Warnings(warnings), actionerror.ApplicationNotFoundError{Name: appName}
    58  	}
    59  
    60  	return actor.convertCCToActorApplication(apps[0]), Warnings(warnings), nil
    61  }
    62  
    63  // GetApplicationsBySpace returns all applications in a space.
    64  func (actor Actor) GetApplicationsBySpace(spaceGUID string) ([]Application, Warnings, error) {
    65  	ccApps, warnings, err := actor.CloudControllerClient.GetApplications(
    66  		ccv3.Query{Key: ccv3.SpaceGUIDFilter, Values: []string{spaceGUID}},
    67  	)
    68  
    69  	if err != nil {
    70  		return []Application{}, Warnings(warnings), err
    71  	}
    72  
    73  	var apps []Application
    74  	for _, ccApp := range ccApps {
    75  		apps = append(apps, actor.convertCCToActorApplication(ccApp))
    76  	}
    77  	return apps, Warnings(warnings), nil
    78  }
    79  
    80  // CreateApplicationInSpace creates and returns the application with the given
    81  // name in the given space.
    82  func (actor Actor) CreateApplicationInSpace(app Application, spaceGUID string) (Application, Warnings, error) {
    83  	createdApp, warnings, err := actor.CloudControllerClient.CreateApplication(
    84  		ccv3.Application{
    85  			LifecycleType:       app.LifecycleType,
    86  			LifecycleBuildpacks: app.LifecycleBuildpacks,
    87  			Name:                app.Name,
    88  			Relationships: ccv3.Relationships{
    89  				constant.RelationshipTypeSpace: ccv3.Relationship{GUID: spaceGUID},
    90  			},
    91  		})
    92  
    93  	if err != nil {
    94  		if _, ok := err.(ccerror.NameNotUniqueInSpaceError); ok {
    95  			return Application{}, Warnings(warnings), actionerror.ApplicationAlreadyExistsError{Name: app.Name}
    96  		}
    97  		return Application{}, Warnings(warnings), err
    98  	}
    99  
   100  	return actor.convertCCToActorApplication(createdApp), Warnings(warnings), nil
   101  }
   102  
   103  // StopApplication stops an application.
   104  func (actor Actor) StopApplication(appGUID string) (Warnings, error) {
   105  	_, warnings, err := actor.CloudControllerClient.UpdateApplicationStop(appGUID)
   106  
   107  	return Warnings(warnings), err
   108  }
   109  
   110  // StartApplication starts an application.
   111  func (actor Actor) StartApplication(appGUID string) (Application, Warnings, error) {
   112  	updatedApp, warnings, err := actor.CloudControllerClient.UpdateApplicationStart(appGUID)
   113  	if err != nil {
   114  		return Application{}, Warnings(warnings), err
   115  	}
   116  
   117  	return actor.convertCCToActorApplication(updatedApp), Warnings(warnings), nil
   118  }
   119  
   120  func (actor Actor) PollStart(appGUID string, warningsChannel chan<- Warnings) error {
   121  	processes, warnings, err := actor.CloudControllerClient.GetApplicationProcesses(appGUID)
   122  	warningsChannel <- Warnings(warnings)
   123  	if err != nil {
   124  		return err
   125  	}
   126  
   127  	timeout := time.Now().Add(actor.Config.StartupTimeout())
   128  	for time.Now().Before(timeout) {
   129  		readyProcs := 0
   130  		for _, process := range processes {
   131  			ready, err := actor.processStatus(process, warningsChannel)
   132  			if err != nil {
   133  				return err
   134  			}
   135  
   136  			if ready {
   137  				readyProcs++
   138  			}
   139  		}
   140  
   141  		if readyProcs == len(processes) {
   142  			return nil
   143  		}
   144  		time.Sleep(actor.Config.PollingInterval())
   145  	}
   146  
   147  	return actionerror.StartupTimeoutError{}
   148  }
   149  
   150  // UpdateApplication updates the buildpacks on an application
   151  func (actor Actor) UpdateApplication(app Application) (Application, Warnings, error) {
   152  	ccApp := ccv3.Application{
   153  		GUID:                app.GUID,
   154  		LifecycleType:       app.LifecycleType,
   155  		LifecycleBuildpacks: app.LifecycleBuildpacks,
   156  	}
   157  
   158  	updatedApp, warnings, err := actor.CloudControllerClient.UpdateApplication(ccApp)
   159  	if err != nil {
   160  		return Application{}, Warnings(warnings), err
   161  	}
   162  
   163  	return actor.convertCCToActorApplication(updatedApp), Warnings(warnings), nil
   164  }
   165  
   166  func (Actor) convertCCToActorApplication(app ccv3.Application) Application {
   167  	return Application{
   168  		GUID:                app.GUID,
   169  		LifecycleType:       app.LifecycleType,
   170  		LifecycleBuildpacks: app.LifecycleBuildpacks,
   171  		Name:                app.Name,
   172  		State:               app.State,
   173  	}
   174  }
   175  
   176  func (actor Actor) processStatus(process ccv3.Process, warningsChannel chan<- Warnings) (bool, error) {
   177  	instances, warnings, err := actor.CloudControllerClient.GetProcessInstances(process.GUID)
   178  	warningsChannel <- Warnings(warnings)
   179  	if err != nil {
   180  		return false, err
   181  	}
   182  	if len(instances) == 0 {
   183  		return true, nil
   184  	}
   185  
   186  	for _, instance := range instances {
   187  		if instance.State == constant.ProcessInstanceRunning {
   188  			return true, nil
   189  		}
   190  	}
   191  
   192  	for _, instance := range instances {
   193  		if instance.State != constant.ProcessInstanceCrashed {
   194  			return false, nil
   195  		}
   196  	}
   197  
   198  	// all of the instances are crashed at this point
   199  	return true, nil
   200  }