github.com/loggregator/cli@v6.33.1-0.20180224010324-82334f081791+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.SpaceRelationship: 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.StopApplication(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.StartApplication(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 }