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  }