github.com/mook-as/cf-cli@v7.0.0-beta.28.0.20200120190804-b91c115fae48+incompatible/api/cloudcontroller/ccv3/process.go (about) 1 package ccv3 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 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 "code.cloudfoundry.org/cli/api/cloudcontroller" 13 "code.cloudfoundry.org/cli/types" 14 ) 15 16 type Process struct { 17 GUID string 18 Type string 19 // Command is the process start command. Note: This value will be obfuscated when obtained from listing. 20 Command types.FilteredString 21 HealthCheckType constant.HealthCheckType 22 HealthCheckEndpoint string 23 HealthCheckInvocationTimeout int64 24 HealthCheckTimeout int64 25 Instances types.NullInt 26 MemoryInMB types.NullUint64 27 DiskInMB types.NullUint64 28 } 29 30 func (p Process) MarshalJSON() ([]byte, error) { 31 var ccProcess marshalProcess 32 33 marshalCommand(p, &ccProcess) 34 marshalInstances(p, &ccProcess) 35 marshalMemory(p, &ccProcess) 36 marshalDisk(p, &ccProcess) 37 marshalHealthCheck(p, &ccProcess) 38 39 return json.Marshal(ccProcess) 40 } 41 42 func (p *Process) UnmarshalJSON(data []byte) error { 43 var ccProcess struct { 44 Command types.FilteredString `json:"command"` 45 DiskInMB types.NullUint64 `json:"disk_in_mb"` 46 GUID string `json:"guid"` 47 Instances types.NullInt `json:"instances"` 48 MemoryInMB types.NullUint64 `json:"memory_in_mb"` 49 Type string `json:"type"` 50 51 HealthCheck struct { 52 Type constant.HealthCheckType `json:"type"` 53 Data struct { 54 Endpoint string `json:"endpoint"` 55 InvocationTimeout int64 `json:"invocation_timeout"` 56 Timeout int64 `json:"timeout"` 57 } `json:"data"` 58 } `json:"health_check"` 59 } 60 61 err := cloudcontroller.DecodeJSON(data, &ccProcess) 62 if err != nil { 63 return err 64 } 65 66 p.Command = ccProcess.Command 67 p.DiskInMB = ccProcess.DiskInMB 68 p.GUID = ccProcess.GUID 69 p.HealthCheckEndpoint = ccProcess.HealthCheck.Data.Endpoint 70 p.HealthCheckInvocationTimeout = ccProcess.HealthCheck.Data.InvocationTimeout 71 p.HealthCheckTimeout = ccProcess.HealthCheck.Data.Timeout 72 p.HealthCheckType = ccProcess.HealthCheck.Type 73 p.Instances = ccProcess.Instances 74 p.MemoryInMB = ccProcess.MemoryInMB 75 p.Type = ccProcess.Type 76 77 return nil 78 } 79 80 // CreateApplicationProcessScale updates process instances count, memory or disk 81 func (client *Client) CreateApplicationProcessScale(appGUID string, process Process) (Process, Warnings, error) { 82 body, err := json.Marshal(process) 83 if err != nil { 84 return Process{}, nil, err 85 } 86 87 request, err := client.newHTTPRequest(requestOptions{ 88 RequestName: internal.PostApplicationProcessActionScaleRequest, 89 Body: bytes.NewReader(body), 90 URIParams: internal.Params{"app_guid": appGUID, "type": process.Type}, 91 }) 92 if err != nil { 93 return Process{}, nil, err 94 } 95 96 var responseProcess Process 97 response := cloudcontroller.Response{ 98 DecodeJSONResponseInto: &responseProcess, 99 } 100 err = client.connection.Make(request, &response) 101 return responseProcess, response.Warnings, err 102 } 103 104 // GetApplicationProcessByType returns application process of specified type 105 func (client *Client) GetApplicationProcessByType(appGUID string, processType string) (Process, Warnings, error) { 106 request, err := client.newHTTPRequest(requestOptions{ 107 RequestName: internal.GetApplicationProcessRequest, 108 URIParams: map[string]string{ 109 "app_guid": appGUID, 110 "type": processType, 111 }, 112 }) 113 if err != nil { 114 return Process{}, nil, err 115 } 116 var process Process 117 response := cloudcontroller.Response{ 118 DecodeJSONResponseInto: &process, 119 } 120 121 err = client.connection.Make(request, &response) 122 return process, response.Warnings, err 123 } 124 125 // GetApplicationProcesses lists processes for a given application. **Note**: 126 // Due to security, the API obfuscates certain values such as `command`. 127 func (client *Client) GetApplicationProcesses(appGUID string) ([]Process, Warnings, error) { 128 request, err := client.newHTTPRequest(requestOptions{ 129 RequestName: internal.GetApplicationProcessesRequest, 130 URIParams: map[string]string{"app_guid": appGUID}, 131 }) 132 if err != nil { 133 return nil, nil, err 134 } 135 136 var fullProcessesList []Process 137 warnings, err := client.paginate(request, Process{}, func(item interface{}) error { 138 if process, ok := item.(Process); ok { 139 fullProcessesList = append(fullProcessesList, process) 140 } else { 141 return ccerror.UnknownObjectInListError{ 142 Expected: Process{}, 143 Unexpected: item, 144 } 145 } 146 return nil 147 }) 148 149 return fullProcessesList, warnings, err 150 } 151 152 // GetNewApplicationProcesses gets processes for an application in the middle of a deployment. 153 // The app's processes will include a web process that will be removed when the deployment completes, 154 // so exclude that soon-to-be-removed process from the result. 155 func (client *Client) GetNewApplicationProcesses(appGUID string, deploymentGUID string) ([]Process, Warnings, error) { 156 var allWarnings Warnings 157 158 deployment, warnings, err := client.GetDeployment(deploymentGUID) 159 allWarnings = append(allWarnings, warnings...) 160 if err != nil { 161 return nil, allWarnings, err 162 } 163 164 allProcesses, warnings, err := client.GetApplicationProcesses(appGUID) 165 allWarnings = append(allWarnings, warnings...) 166 if err != nil { 167 return nil, allWarnings, err 168 } 169 170 var newWebProcessGUID string 171 for _, process := range deployment.NewProcesses { 172 if process.Type == constant.ProcessTypeWeb { 173 newWebProcessGUID = process.GUID 174 } 175 } 176 177 var processesList []Process 178 for _, process := range allProcesses { 179 if process.Type == constant.ProcessTypeWeb { 180 if process.GUID == newWebProcessGUID { 181 processesList = append(processesList, process) 182 } 183 } else { 184 processesList = append(processesList, process) 185 } 186 } 187 188 return processesList, allWarnings, nil 189 } 190 191 // GetProcess returns a process with the given guid 192 func (client *Client) GetProcess(processGUID string) (Process, Warnings, error) { 193 request, err := client.newHTTPRequest(requestOptions{ 194 RequestName: internal.GetProcessRequest, 195 URIParams: map[string]string{ 196 "process_guid": processGUID, 197 }, 198 }) 199 200 if err != nil { 201 return Process{}, nil, err 202 } 203 204 var process Process 205 response := cloudcontroller.Response{ 206 DecodeJSONResponseInto: &process, 207 } 208 209 err = client.connection.Make(request, &response) 210 return process, response.Warnings, err 211 } 212 213 // UpdateProcess updates the process's command or health check settings. GUID 214 // is always required; HealthCheckType is only required when updating health 215 // check settings. 216 func (client *Client) UpdateProcess(process Process) (Process, Warnings, error) { 217 body, err := json.Marshal(Process{ 218 Command: process.Command, 219 HealthCheckType: process.HealthCheckType, 220 HealthCheckEndpoint: process.HealthCheckEndpoint, 221 HealthCheckTimeout: process.HealthCheckTimeout, 222 HealthCheckInvocationTimeout: process.HealthCheckInvocationTimeout, 223 }) 224 if err != nil { 225 return Process{}, nil, err 226 } 227 228 request, err := client.newHTTPRequest(requestOptions{ 229 RequestName: internal.PatchProcessRequest, 230 Body: bytes.NewReader(body), 231 URIParams: internal.Params{"process_guid": process.GUID}, 232 }) 233 if err != nil { 234 return Process{}, nil, err 235 } 236 237 var responseProcess Process 238 response := cloudcontroller.Response{ 239 DecodeJSONResponseInto: &responseProcess, 240 } 241 err = client.connection.Make(request, &response) 242 return responseProcess, response.Warnings, err 243 } 244 245 type healthCheck struct { 246 Type constant.HealthCheckType `json:"type,omitempty"` 247 Data struct { 248 Endpoint interface{} `json:"endpoint,omitempty"` 249 InvocationTimeout int64 `json:"invocation_timeout,omitempty"` 250 Timeout int64 `json:"timeout,omitempty"` 251 } `json:"data"` 252 } 253 254 type marshalProcess struct { 255 Command interface{} `json:"command,omitempty"` 256 Instances json.Number `json:"instances,omitempty"` 257 MemoryInMB json.Number `json:"memory_in_mb,omitempty"` 258 DiskInMB json.Number `json:"disk_in_mb,omitempty"` 259 260 HealthCheck *healthCheck `json:"health_check,omitempty"` 261 } 262 263 func marshalCommand(p Process, ccProcess *marshalProcess) { 264 if p.Command.IsSet { 265 ccProcess.Command = &p.Command 266 } 267 } 268 269 func marshalDisk(p Process, ccProcess *marshalProcess) { 270 if p.DiskInMB.IsSet { 271 ccProcess.DiskInMB = json.Number(fmt.Sprint(p.DiskInMB.Value)) 272 } 273 } 274 275 func marshalHealthCheck(p Process, ccProcess *marshalProcess) { 276 if p.HealthCheckType != "" || p.HealthCheckEndpoint != "" || p.HealthCheckInvocationTimeout != 0 || p.HealthCheckTimeout != 0 { 277 ccProcess.HealthCheck = new(healthCheck) 278 ccProcess.HealthCheck.Type = p.HealthCheckType 279 ccProcess.HealthCheck.Data.InvocationTimeout = p.HealthCheckInvocationTimeout 280 ccProcess.HealthCheck.Data.Timeout = p.HealthCheckTimeout 281 if p.HealthCheckEndpoint != "" { 282 ccProcess.HealthCheck.Data.Endpoint = p.HealthCheckEndpoint 283 } 284 } 285 } 286 287 func marshalInstances(p Process, ccProcess *marshalProcess) { 288 if p.Instances.IsSet { 289 ccProcess.Instances = json.Number(fmt.Sprint(p.Instances.Value)) 290 } 291 } 292 293 func marshalMemory(p Process, ccProcess *marshalProcess) { 294 if p.MemoryInMB.IsSet { 295 ccProcess.MemoryInMB = json.Number(fmt.Sprint(p.MemoryInMB.Value)) 296 } 297 }