github.com/mook-as/cf-cli@v7.0.0-beta.28.0.20200120190804-b91c115fae48+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/ccv3" 8 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" 9 ) 10 11 // Application represents a V3 actor application. 12 type Application struct { 13 Name string 14 GUID string 15 StackName string 16 State constant.ApplicationState 17 LifecycleType constant.AppLifecycleType 18 LifecycleBuildpacks []string 19 SpaceGUID 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 // GetApplicationsByGUIDs returns all applications with the provided GUIDs. 86 func (actor Actor) GetApplicationsByGUIDs(appGUIDs ...string) ([]Application, Warnings, error) { 87 ccApps, warnings, err := actor.CloudControllerClient.GetApplications( 88 ccv3.Query{Key: ccv3.GUIDFilter, Values: appGUIDs}, 89 ) 90 91 if err != nil { 92 return []Application{}, Warnings(warnings), err 93 } 94 95 var apps []Application 96 for _, ccApp := range ccApps { 97 apps = append(apps, actor.convertCCToActorApplication(ccApp)) 98 } 99 return apps, Warnings(warnings), nil 100 } 101 102 // CreateApplicationInSpace creates and returns the application with the given 103 // name in the given space. 104 func (actor Actor) CreateApplicationInSpace(app Application, spaceGUID string) (Application, Warnings, error) { 105 createdApp, warnings, err := actor.CloudControllerClient.CreateApplication( 106 ccv3.Application{ 107 LifecycleType: app.LifecycleType, 108 LifecycleBuildpacks: app.LifecycleBuildpacks, 109 StackName: app.StackName, 110 Name: app.Name, 111 Relationships: ccv3.Relationships{ 112 constant.RelationshipTypeSpace: ccv3.Relationship{GUID: spaceGUID}, 113 }, 114 }) 115 116 if err != nil { 117 return Application{}, Warnings(warnings), err 118 } 119 120 return actor.convertCCToActorApplication(createdApp), Warnings(warnings), nil 121 } 122 123 // StopApplication stops an application. 124 func (actor Actor) StopApplication(appGUID string) (Warnings, error) { 125 _, warnings, err := actor.CloudControllerClient.UpdateApplicationStop(appGUID) 126 127 return Warnings(warnings), err 128 } 129 130 // StartApplication starts an application. 131 func (actor Actor) StartApplication(appGUID string) (Warnings, error) { 132 _, warnings, err := actor.CloudControllerClient.UpdateApplicationStart(appGUID) 133 if err != nil { 134 return Warnings(warnings), err 135 } 136 137 return Warnings(warnings), nil 138 } 139 140 // RestartApplication restarts an application. 141 func (actor Actor) RestartApplication(appGUID string) (Warnings, error) { 142 _, warnings, err := actor.CloudControllerClient.UpdateApplicationRestart(appGUID) 143 144 return Warnings(warnings), err 145 } 146 147 func (actor Actor) PollStart(appGUID string, warningsChannel chan<- Warnings) error { 148 processes, warnings, err := actor.CloudControllerClient.GetApplicationProcesses(appGUID) 149 warningsChannel <- Warnings(warnings) 150 if err != nil { 151 return err 152 } 153 154 timeout := time.Now().Add(actor.Config.StartupTimeout()) 155 for time.Now().Before(timeout) { 156 readyProcs := 0 157 for _, process := range processes { 158 ready, err := actor.processStatus(process, warningsChannel) 159 if err != nil { 160 return err 161 } 162 163 if ready { 164 readyProcs++ 165 } 166 } 167 168 if readyProcs == len(processes) { 169 return nil 170 } 171 time.Sleep(actor.Config.PollingInterval()) 172 } 173 174 return actionerror.StartupTimeoutError{} 175 } 176 177 // UpdateApplication updates the buildpacks on an application 178 func (actor Actor) UpdateApplication(app Application) (Application, Warnings, error) { 179 ccApp := ccv3.Application{ 180 GUID: app.GUID, 181 StackName: app.StackName, 182 LifecycleType: app.LifecycleType, 183 LifecycleBuildpacks: app.LifecycleBuildpacks, 184 } 185 186 updatedApp, warnings, err := actor.CloudControllerClient.UpdateApplication(ccApp) 187 if err != nil { 188 return Application{}, Warnings(warnings), err 189 } 190 191 return actor.convertCCToActorApplication(updatedApp), Warnings(warnings), nil 192 } 193 194 func (Actor) convertCCToActorApplication(app ccv3.Application) Application { 195 return Application{ 196 GUID: app.GUID, 197 StackName: app.StackName, 198 LifecycleType: app.LifecycleType, 199 LifecycleBuildpacks: app.LifecycleBuildpacks, 200 Name: app.Name, 201 State: app.State, 202 SpaceGUID: app.Relationships[constant.RelationshipTypeSpace].GUID, 203 } 204 } 205 206 func (actor Actor) processStatus(process ccv3.Process, warningsChannel chan<- Warnings) (bool, error) { 207 instances, warnings, err := actor.CloudControllerClient.GetProcessInstances(process.GUID) 208 warningsChannel <- Warnings(warnings) 209 if err != nil { 210 return false, err 211 } 212 if len(instances) == 0 { 213 return true, nil 214 } 215 216 for _, instance := range instances { 217 if instance.State == constant.ProcessInstanceRunning { 218 return true, nil 219 } 220 } 221 222 for _, instance := range instances { 223 if instance.State != constant.ProcessInstanceCrashed { 224 return false, nil 225 } 226 } 227 228 // all of the instances are crashed at this point 229 return true, nil 230 }