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 }