github.com/jenspinney/cli@v6.42.1-0.20190207184520-7450c600020e+incompatible/api/cloudcontroller/ccv3/application.go (about) 1 package ccv3 2 3 import ( 4 "bytes" 5 "encoding/json" 6 7 "code.cloudfoundry.org/cli/api/cloudcontroller" 8 "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" 9 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" 10 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" 11 ) 12 13 // Application represents a Cloud Controller V3 Application. 14 type Application struct { 15 // GUID is the unique application identifier. 16 GUID string 17 // StackName is the name of the stack on which the application runs. 18 StackName string 19 // LifecycleBuildpacks is a list of the names of buildpacks. 20 LifecycleBuildpacks []string 21 // LifecycleType is the type of the lifecycle. 22 LifecycleType constant.AppLifecycleType 23 // Name is the name given to the application. 24 Name string 25 // Relationships list the relationships to the application. 26 Relationships Relationships 27 // State is the desired state of the application. 28 State constant.ApplicationState 29 } 30 31 // MarshalJSON converts an Application into a Cloud Controller Application. 32 func (a Application) MarshalJSON() ([]byte, error) { 33 ccApp := ccApplication{ 34 Name: a.Name, 35 Relationships: a.Relationships, 36 } 37 38 if a.LifecycleType == constant.AppLifecycleTypeDocker { 39 ccApp.setDockerLifecycle() 40 } else if a.LifecycleType == constant.AppLifecycleTypeBuildpack { 41 if len(a.LifecycleBuildpacks) > 0 || a.StackName != "" { 42 if a.hasAutodetectedBuildpack() { 43 ccApp.setAutodetectedBuildpackLifecycle(a) 44 } else { 45 ccApp.setBuildpackLifecycle(a) 46 } 47 } 48 } 49 50 return json.Marshal(ccApp) 51 } 52 53 // UnmarshalJSON helps unmarshal a Cloud Controller Application response. 54 func (a *Application) UnmarshalJSON(data []byte) error { 55 lifecycle := ccLifecycle{} 56 ccApp := ccApplication{ 57 Lifecycle: &lifecycle, 58 } 59 60 err := cloudcontroller.DecodeJSON(data, &ccApp) 61 if err != nil { 62 return err 63 } 64 65 a.GUID = ccApp.GUID 66 a.StackName = lifecycle.Data.Stack 67 a.LifecycleBuildpacks = lifecycle.Data.Buildpacks 68 a.LifecycleType = lifecycle.Type 69 a.Name = ccApp.Name 70 a.Relationships = ccApp.Relationships 71 a.State = ccApp.State 72 73 return nil 74 } 75 76 func (a Application) hasAutodetectedBuildpack() bool { 77 if len(a.LifecycleBuildpacks) == 0 { 78 return false 79 } 80 return a.LifecycleBuildpacks[0] == constant.AutodetectBuildpackValueDefault || a.LifecycleBuildpacks[0] == constant.AutodetectBuildpackValueNull 81 } 82 83 type ccLifecycle struct { 84 Type constant.AppLifecycleType `json:"type,omitempty"` 85 Data struct { 86 Buildpacks []string `json:"buildpacks,omitempty"` 87 Stack string `json:"stack,omitempty"` 88 } `json:"data"` 89 } 90 91 type ccApplication struct { 92 Name string `json:"name,omitempty"` 93 Relationships Relationships `json:"relationships,omitempty"` 94 Lifecycle interface{} `json:"lifecycle,omitempty"` 95 GUID string `json:"guid,omitempty"` 96 State constant.ApplicationState `json:"state,omitempty"` 97 } 98 99 func (ccApp *ccApplication) setAutodetectedBuildpackLifecycle(a Application) { 100 var nullBuildpackLifecycle struct { 101 Type constant.AppLifecycleType `json:"type,omitempty"` 102 Data struct { 103 Buildpacks []string `json:"buildpacks"` 104 Stack string `json:"stack,omitempty"` 105 } `json:"data"` 106 } 107 nullBuildpackLifecycle.Type = constant.AppLifecycleTypeBuildpack 108 nullBuildpackLifecycle.Data.Stack = a.StackName 109 ccApp.Lifecycle = nullBuildpackLifecycle 110 } 111 112 func (ccApp *ccApplication) setBuildpackLifecycle(a Application) { 113 var lifecycle ccLifecycle 114 lifecycle.Type = a.LifecycleType 115 lifecycle.Data.Buildpacks = a.LifecycleBuildpacks 116 lifecycle.Data.Stack = a.StackName 117 ccApp.Lifecycle = lifecycle 118 } 119 120 func (ccApp *ccApplication) setDockerLifecycle() { 121 ccApp.Lifecycle = ccLifecycle{ 122 Type: constant.AppLifecycleTypeDocker, 123 } 124 } 125 126 // CreateApplication creates an application with the given settings. 127 func (client *Client) CreateApplication(app Application) (Application, Warnings, error) { 128 bodyBytes, err := json.Marshal(app) 129 if err != nil { 130 return Application{}, nil, err 131 } 132 133 request, err := client.newHTTPRequest(requestOptions{ 134 RequestName: internal.PostApplicationRequest, 135 Body: bytes.NewReader(bodyBytes), 136 }) 137 if err != nil { 138 return Application{}, nil, err 139 } 140 141 var responseApp Application 142 response := cloudcontroller.Response{ 143 DecodeJSONResponseInto: &responseApp, 144 } 145 err = client.connection.Make(request, &response) 146 147 return responseApp, response.Warnings, err 148 } 149 150 // GetApplications lists applications with optional queries. 151 func (client *Client) GetApplications(query ...Query) ([]Application, Warnings, error) { 152 request, err := client.newHTTPRequest(requestOptions{ 153 RequestName: internal.GetApplicationsRequest, 154 Query: query, 155 }) 156 if err != nil { 157 return nil, nil, err 158 } 159 160 var fullAppsList []Application 161 warnings, err := client.paginate(request, Application{}, func(item interface{}) error { 162 if app, ok := item.(Application); ok { 163 fullAppsList = append(fullAppsList, app) 164 } else { 165 return ccerror.UnknownObjectInListError{ 166 Expected: Application{}, 167 Unexpected: item, 168 } 169 } 170 return nil 171 }) 172 173 return fullAppsList, warnings, err 174 } 175 176 // UpdateApplication updates an application with the given settings. 177 func (client *Client) UpdateApplication(app Application) (Application, Warnings, error) { 178 bodyBytes, err := json.Marshal(app) 179 if err != nil { 180 return Application{}, nil, err 181 } 182 183 request, err := client.newHTTPRequest(requestOptions{ 184 RequestName: internal.PatchApplicationRequest, 185 Body: bytes.NewReader(bodyBytes), 186 URIParams: map[string]string{"app_guid": app.GUID}, 187 }) 188 if err != nil { 189 return Application{}, nil, err 190 } 191 192 var responseApp Application 193 response := cloudcontroller.Response{ 194 DecodeJSONResponseInto: &responseApp, 195 } 196 err = client.connection.Make(request, &response) 197 198 return responseApp, response.Warnings, err 199 } 200 201 // UpdateApplicationRestart restarts the given application. 202 func (client *Client) UpdateApplicationRestart(appGUID string) (Application, Warnings, error) { 203 request, err := client.newHTTPRequest(requestOptions{ 204 RequestName: internal.PostApplicationActionRestartRequest, 205 URIParams: map[string]string{"app_guid": appGUID}, 206 }) 207 if err != nil { 208 return Application{}, nil, err 209 } 210 211 var responseApp Application 212 response := cloudcontroller.Response{ 213 DecodeJSONResponseInto: &responseApp, 214 } 215 err = client.connection.Make(request, &response) 216 217 return responseApp, response.Warnings, err 218 } 219 220 // UpdateApplicationStart starts the given application. 221 func (client *Client) UpdateApplicationStart(appGUID string) (Application, Warnings, error) { 222 request, err := client.newHTTPRequest(requestOptions{ 223 RequestName: internal.PostApplicationActionStartRequest, 224 URIParams: map[string]string{"app_guid": appGUID}, 225 }) 226 if err != nil { 227 return Application{}, nil, err 228 } 229 230 var responseApp Application 231 response := cloudcontroller.Response{ 232 DecodeJSONResponseInto: &responseApp, 233 } 234 err = client.connection.Make(request, &response) 235 236 return responseApp, response.Warnings, err 237 } 238 239 // UpdateApplicationStop stops the given application. 240 func (client *Client) UpdateApplicationStop(appGUID string) (Application, Warnings, error) { 241 request, err := client.newHTTPRequest(requestOptions{ 242 RequestName: internal.PostApplicationActionStopRequest, 243 URIParams: map[string]string{"app_guid": appGUID}, 244 }) 245 if err != nil { 246 return Application{}, nil, err 247 } 248 249 var responseApp Application 250 response := cloudcontroller.Response{ 251 DecodeJSONResponseInto: &responseApp, 252 } 253 err = client.connection.Make(request, &response) 254 255 return responseApp, response.Warnings, err 256 }