github.com/cloudfoundry-attic/cli-with-i18n@v6.32.1-0.20171002233121-7401370d3b85+incompatible/api/cloudcontroller/ccv2/application.go (about) 1 package ccv2 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "time" 8 9 "code.cloudfoundry.org/cli/api/cloudcontroller" 10 "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" 11 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv2/internal" 12 "code.cloudfoundry.org/cli/types" 13 ) 14 15 // ApplicationState is the running state of an application. 16 type ApplicationState string 17 18 const ( 19 ApplicationStarted ApplicationState = "STARTED" 20 ApplicationStopped ApplicationState = "STOPPED" 21 ) 22 23 // ApplicationPackageState is the staging state of application bits. 24 type ApplicationPackageState string 25 26 const ( 27 ApplicationPackageStaged ApplicationPackageState = "STAGED" 28 ApplicationPackagePending ApplicationPackageState = "PENDING" 29 ApplicationPackageFailed ApplicationPackageState = "FAILED" 30 ApplicationPackageUnknown ApplicationPackageState = "UNKNOWN" 31 ) 32 33 // ApplicationHealthCheckType is the method to reach the applications health check 34 type ApplicationHealthCheckType string 35 36 const ( 37 ApplicationHealthCheckPort ApplicationHealthCheckType = "port" 38 ApplicationHealthCheckHTTP ApplicationHealthCheckType = "http" 39 ApplicationHealthCheckProcess ApplicationHealthCheckType = "process" 40 ) 41 42 // Application represents a Cloud Controller Application. 43 type Application struct { 44 // Buildpack is the buildpack set by the user. 45 Buildpack types.FilteredString 46 47 // Command is the user specified start command. 48 Command types.FilteredString 49 50 // DetectedBuildpack is the buildpack automatically detected. 51 DetectedBuildpack types.FilteredString 52 53 // DetectedStartCommand is the command used to start the application. 54 DetectedStartCommand types.FilteredString 55 56 // DiskQuota is the disk given to each instance, in megabytes. 57 DiskQuota uint64 58 59 // DockerCredentials is the authentication information for the provided 60 // DockerImage. 61 DockerCredentials DockerCredentials 62 63 // DockerImage is the docker image location. 64 DockerImage string 65 66 // EnvironmentVariables are the environment variables passed to the app. 67 EnvironmentVariables map[string]string 68 69 // GUID is the unique application identifier. 70 GUID string 71 72 // HealthCheckTimeout is the number of seconds for health checking of an 73 // staged app when starting up. 74 HealthCheckTimeout int 75 76 // HealthCheckType is the type of health check that will be done to the app. 77 HealthCheckType ApplicationHealthCheckType 78 79 // HealthCheckHTTPEndpoint is the url of the http health check endpoint. 80 HealthCheckHTTPEndpoint string 81 82 // Instances is the total number of app instances. 83 Instances types.NullInt 84 85 // Memory is the memory given to each instance, in megabytes. 86 Memory uint64 87 88 // Name is the name given to the application. 89 Name string 90 91 // PackageState represents the staging state of the application bits. 92 PackageState ApplicationPackageState 93 94 // PackageUpdatedAt is the last time the app bits were updated. In RFC3339. 95 PackageUpdatedAt time.Time 96 97 // SpaceGUID is the GUID of the app's space. 98 SpaceGUID string 99 100 // StackGUID is the GUID for the Stack the application is running on. 101 StackGUID string 102 103 // StagingFailedDescription is the verbose description of why the package 104 // failed to stage. 105 StagingFailedDescription string 106 107 // StagingFailedReason is the reason why the package failed to stage. 108 StagingFailedReason string 109 110 // State is the desired state of the application. 111 State ApplicationState 112 } 113 114 // DockerCredentials are the authentication credentials to pull a docker image 115 // from it's repository. 116 type DockerCredentials struct { 117 // Username is the username for a user that has access to a given docker 118 // image. 119 Username string `json:"username,omitempty"` 120 121 // Password is the password for the user. 122 Password string `json:"password,omitempty"` 123 } 124 125 // MarshalJSON converts an application into a Cloud Controller Application. 126 func (application Application) MarshalJSON() ([]byte, error) { 127 ccApp := struct { 128 Buildpack *string `json:"buildpack,omitempty"` 129 Command *string `json:"command,omitempty"` 130 DiskQuota uint64 `json:"disk_quota,omitempty"` 131 DockerCredentials *DockerCredentials `json:"docker_credentials,omitempty"` 132 DockerImage string `json:"docker_image,omitempty"` 133 EnvironmentVariables map[string]string `json:"environment_json,omitempty"` 134 HealthCheckHTTPEndpoint string `json:"health_check_http_endpoint,omitempty"` 135 HealthCheckTimeout int `json:"health_check_timeout,omitempty"` 136 HealthCheckType ApplicationHealthCheckType `json:"health_check_type,omitempty"` 137 Instances *int `json:"instances,omitempty"` 138 Memory uint64 `json:"memory,omitempty"` 139 Name string `json:"name,omitempty"` 140 SpaceGUID string `json:"space_guid,omitempty"` 141 StackGUID string `json:"stack_guid,omitempty"` 142 State ApplicationState `json:"state,omitempty"` 143 }{ 144 DiskQuota: application.DiskQuota, 145 DockerImage: application.DockerImage, 146 EnvironmentVariables: application.EnvironmentVariables, 147 HealthCheckHTTPEndpoint: application.HealthCheckHTTPEndpoint, 148 HealthCheckTimeout: application.HealthCheckTimeout, 149 HealthCheckType: application.HealthCheckType, 150 Memory: application.Memory, 151 Name: application.Name, 152 SpaceGUID: application.SpaceGUID, 153 StackGUID: application.StackGUID, 154 State: application.State, 155 } 156 157 if application.Buildpack.IsSet { 158 ccApp.Buildpack = &application.Buildpack.Value 159 } 160 161 if application.Command.IsSet { 162 ccApp.Command = &application.Command.Value 163 } 164 165 if application.DockerCredentials.Username != "" || application.DockerCredentials.Password != "" { 166 ccApp.DockerCredentials = &DockerCredentials{ 167 Username: application.DockerCredentials.Username, 168 Password: application.DockerCredentials.Password, 169 } 170 } 171 172 if application.Instances.IsSet { 173 ccApp.Instances = &application.Instances.Value 174 } 175 176 return json.Marshal(ccApp) 177 } 178 179 // UnmarshalJSON helps unmarshal a Cloud Controller Application response. 180 func (application *Application) UnmarshalJSON(data []byte) error { 181 var ccApp struct { 182 Metadata internal.Metadata `json:"metadata"` 183 Entity struct { 184 Buildpack string `json:"buildpack"` 185 Command string `json:"command"` 186 DetectedBuildpack string `json:"detected_buildpack"` 187 DetectedStartCommand string `json:"detected_start_command"` 188 DiskQuota uint64 `json:"disk_quota"` 189 DockerImage string `json:"docker_image"` 190 DockerCredentials DockerCredentials `json:"docker_credentials"` 191 // EnvironmentVariables' values can be any type, so we must accept 192 // interface{}, but we convert to string. 193 EnvironmentVariables map[string]interface{} `json:"environment_json"` 194 HealthCheckHTTPEndpoint string `json:"health_check_http_endpoint"` 195 HealthCheckTimeout int `json:"health_check_timeout"` 196 HealthCheckType string `json:"health_check_type"` 197 Instances json.Number `json:"instances"` 198 Memory uint64 `json:"memory"` 199 Name string `json:"name"` 200 PackageState string `json:"package_state"` 201 PackageUpdatedAt *time.Time `json:"package_updated_at"` 202 StackGUID string `json:"stack_guid"` 203 StagingFailedDescription string `json:"staging_failed_description"` 204 StagingFailedReason string `json:"staging_failed_reason"` 205 State string `json:"state"` 206 } `json:"entity"` 207 } 208 209 decoder := json.NewDecoder(bytes.NewBuffer(data)) 210 decoder.UseNumber() 211 err := decoder.Decode(&ccApp) 212 if err != nil { 213 return err 214 } 215 216 application.DiskQuota = ccApp.Entity.DiskQuota 217 application.DockerImage = ccApp.Entity.DockerImage 218 application.DockerCredentials = ccApp.Entity.DockerCredentials 219 application.GUID = ccApp.Metadata.GUID 220 application.HealthCheckHTTPEndpoint = ccApp.Entity.HealthCheckHTTPEndpoint 221 application.HealthCheckTimeout = ccApp.Entity.HealthCheckTimeout 222 application.HealthCheckType = ApplicationHealthCheckType(ccApp.Entity.HealthCheckType) 223 application.Memory = ccApp.Entity.Memory 224 application.Name = ccApp.Entity.Name 225 application.PackageState = ApplicationPackageState(ccApp.Entity.PackageState) 226 application.StackGUID = ccApp.Entity.StackGUID 227 application.StagingFailedDescription = ccApp.Entity.StagingFailedDescription 228 application.StagingFailedReason = ccApp.Entity.StagingFailedReason 229 application.State = ApplicationState(ccApp.Entity.State) 230 231 application.Buildpack.ParseValue(ccApp.Entity.Buildpack) 232 application.DetectedBuildpack.ParseValue(ccApp.Entity.DetectedBuildpack) 233 234 application.Command.ParseValue(ccApp.Entity.Command) 235 application.DetectedStartCommand.ParseValue(ccApp.Entity.DetectedStartCommand) 236 237 if len(ccApp.Entity.EnvironmentVariables) > 0 { 238 envVariableValues := map[string]string{} 239 for key, value := range ccApp.Entity.EnvironmentVariables { 240 envVariableValues[key] = fmt.Sprint(value) 241 } 242 application.EnvironmentVariables = envVariableValues 243 } 244 245 err = application.Instances.ParseStringValue(ccApp.Entity.Instances.String()) 246 if err != nil { 247 return err 248 } 249 250 if ccApp.Entity.PackageUpdatedAt != nil { 251 application.PackageUpdatedAt = *ccApp.Entity.PackageUpdatedAt 252 } 253 return nil 254 } 255 256 // CreateApplication creates a cloud controller application in with the given 257 // settings. SpaceGUID and Name are the only required fields. 258 func (client *Client) CreateApplication(app Application) (Application, Warnings, error) { 259 body, err := json.Marshal(app) 260 if err != nil { 261 return Application{}, nil, err 262 } 263 264 request, err := client.newHTTPRequest(requestOptions{ 265 RequestName: internal.PostAppRequest, 266 Body: bytes.NewReader(body), 267 }) 268 if err != nil { 269 return Application{}, nil, err 270 } 271 272 var updatedApp Application 273 response := cloudcontroller.Response{ 274 Result: &updatedApp, 275 } 276 277 err = client.connection.Make(request, &response) 278 return updatedApp, response.Warnings, err 279 } 280 281 // GetApplication returns back an Application. 282 func (client *Client) GetApplication(guid string) (Application, Warnings, error) { 283 request, err := client.newHTTPRequest(requestOptions{ 284 RequestName: internal.GetAppRequest, 285 URIParams: Params{"app_guid": guid}, 286 }) 287 if err != nil { 288 return Application{}, nil, err 289 } 290 291 var app Application 292 response := cloudcontroller.Response{ 293 Result: &app, 294 } 295 296 err = client.connection.Make(request, &response) 297 return app, response.Warnings, err 298 } 299 300 // GetApplications returns back a list of Applications based off of the 301 // provided queries. 302 func (client *Client) GetApplications(queries ...Query) ([]Application, Warnings, error) { 303 request, err := client.newHTTPRequest(requestOptions{ 304 RequestName: internal.GetAppsRequest, 305 Query: FormatQueryParameters(queries), 306 }) 307 if err != nil { 308 return nil, nil, err 309 } 310 311 var fullAppsList []Application 312 warnings, err := client.paginate(request, Application{}, func(item interface{}) error { 313 if app, ok := item.(Application); ok { 314 fullAppsList = append(fullAppsList, app) 315 } else { 316 return ccerror.UnknownObjectInListError{ 317 Expected: Application{}, 318 Unexpected: item, 319 } 320 } 321 return nil 322 }) 323 324 return fullAppsList, warnings, err 325 } 326 327 // UpdateApplication updates the application with the given GUID. Note: Sending 328 // DockerImage and StackGUID at the same time will result in an API error. 329 func (client *Client) UpdateApplication(app Application) (Application, Warnings, error) { 330 body, err := json.Marshal(app) 331 if err != nil { 332 return Application{}, nil, err 333 } 334 335 request, err := client.newHTTPRequest(requestOptions{ 336 RequestName: internal.PutAppRequest, 337 URIParams: Params{"app_guid": app.GUID}, 338 Body: bytes.NewReader(body), 339 }) 340 if err != nil { 341 return Application{}, nil, err 342 } 343 344 var updatedApp Application 345 response := cloudcontroller.Response{ 346 Result: &updatedApp, 347 } 348 349 err = client.connection.Make(request, &response) 350 return updatedApp, response.Warnings, err 351 } 352 353 // RestageApplication restages the application with the given GUID. 354 func (client *Client) RestageApplication(app Application) (Application, Warnings, error) { 355 request, err := client.newHTTPRequest(requestOptions{ 356 RequestName: internal.PostAppRestageRequest, 357 URIParams: Params{"app_guid": app.GUID}, 358 }) 359 if err != nil { 360 return Application{}, nil, err 361 } 362 363 var restagedApp Application 364 response := cloudcontroller.Response{ 365 Result: &restagedApp, 366 } 367 368 err = client.connection.Make(request, &response) 369 return restagedApp, response.Warnings, err 370 } 371 372 // GetRouteApplications returns a list of Applications associated with a route 373 // GUID, filtered by provided queries. 374 func (client *Client) GetRouteApplications(routeGUID string, queryParams ...Query) ([]Application, Warnings, error) { 375 request, err := client.newHTTPRequest(requestOptions{ 376 RequestName: internal.GetRouteAppsRequest, 377 URIParams: map[string]string{"route_guid": routeGUID}, 378 Query: FormatQueryParameters(queryParams), 379 }) 380 if err != nil { 381 return nil, nil, err 382 } 383 384 var fullAppsList []Application 385 warnings, err := client.paginate(request, Application{}, func(item interface{}) error { 386 if app, ok := item.(Application); ok { 387 fullAppsList = append(fullAppsList, app) 388 } else { 389 return ccerror.UnknownObjectInListError{ 390 Expected: Application{}, 391 Unexpected: item, 392 } 393 } 394 return nil 395 }) 396 397 return fullAppsList, warnings, err 398 }