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 }