github.com/mook-as/cf-cli@v7.0.0-beta.28.0.20200120190804-b91c115fae48+incompatible/api/cloudcontroller/ccv2/service_instance.go (about)

     1  package ccv2
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"net/url"
     7  
     8  	"code.cloudfoundry.org/cli/api/cloudcontroller"
     9  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccerror"
    10  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv2/constant"
    11  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv2/internal"
    12  )
    13  
    14  // ServiceInstance represents a Cloud Controller Service Instance.
    15  type ServiceInstance struct {
    16  	// GUID is the unique service instance identifier.
    17  	GUID string
    18  
    19  	// Name is the name given to the service instance.
    20  	Name string
    21  
    22  	// SpaceGUID is the unique identifier of the space that this service instance
    23  	// belongs to.
    24  	SpaceGUID string
    25  
    26  	// ServiceGUID is the unique identifier of the service that this service
    27  	// instance belongs to.
    28  	ServiceGUID string
    29  
    30  	// ServicePlanGUID is the unique identifier of the service plan that this
    31  	// service instance belongs to.
    32  	ServicePlanGUID string
    33  
    34  	// Type is the type of service instance.
    35  	Type constant.ServiceInstanceType
    36  
    37  	// Tags is a list of all tags for the service instance.
    38  	Tags []string
    39  
    40  	// DashboardURL is the service-broker provided URL to access administrative
    41  	// features of the service instance.
    42  	DashboardURL string
    43  
    44  	// RouteServiceURL is the URL of the user-provided service to which requests
    45  	// for bound routes will be forwarded.
    46  	RouteServiceURL string
    47  
    48  	// LastOperation is the status of the last operation requested on the service
    49  	// instance.
    50  	LastOperation LastOperation
    51  
    52  	// MaintenanceInfo is the maintenance version of this service instance
    53  	MaintenanceInfo MaintenanceInfo
    54  }
    55  
    56  // Managed returns true if the Service Instance is a managed service.
    57  func (serviceInstance ServiceInstance) Managed() bool {
    58  	return serviceInstance.Type == constant.ManagedService
    59  }
    60  
    61  // UnmarshalJSON helps unmarshal a Cloud Controller Service Instance response.
    62  func (serviceInstance *ServiceInstance) UnmarshalJSON(data []byte) error {
    63  	var ccServiceInstance struct {
    64  		Metadata internal.Metadata
    65  		Entity   struct {
    66  			Name            string          `json:"name"`
    67  			SpaceGUID       string          `json:"space_guid"`
    68  			ServiceGUID     string          `json:"service_guid"`
    69  			ServicePlanGUID string          `json:"service_plan_guid"`
    70  			Type            string          `json:"type"`
    71  			Tags            []string        `json:"tags"`
    72  			DashboardURL    string          `json:"dashboard_url"`
    73  			RouteServiceURL string          `json:"route_service_url"`
    74  			LastOperation   LastOperation   `json:"last_operation"`
    75  			MaintenanceInfo MaintenanceInfo `json:"maintenance_info"`
    76  		}
    77  	}
    78  	err := cloudcontroller.DecodeJSON(data, &ccServiceInstance)
    79  	if err != nil {
    80  		return err
    81  	}
    82  
    83  	serviceInstance.GUID = ccServiceInstance.Metadata.GUID
    84  	serviceInstance.Name = ccServiceInstance.Entity.Name
    85  	serviceInstance.SpaceGUID = ccServiceInstance.Entity.SpaceGUID
    86  	serviceInstance.ServiceGUID = ccServiceInstance.Entity.ServiceGUID
    87  	serviceInstance.ServicePlanGUID = ccServiceInstance.Entity.ServicePlanGUID
    88  	serviceInstance.Type = constant.ServiceInstanceType(ccServiceInstance.Entity.Type)
    89  	serviceInstance.Tags = ccServiceInstance.Entity.Tags
    90  	serviceInstance.DashboardURL = ccServiceInstance.Entity.DashboardURL
    91  	serviceInstance.RouteServiceURL = ccServiceInstance.Entity.RouteServiceURL
    92  	serviceInstance.LastOperation = ccServiceInstance.Entity.LastOperation
    93  	serviceInstance.MaintenanceInfo = ccServiceInstance.Entity.MaintenanceInfo
    94  	return nil
    95  }
    96  
    97  // UserProvided returns true if the Service Instance is a user provided
    98  // service.
    99  func (serviceInstance ServiceInstance) UserProvided() bool {
   100  	return serviceInstance.Type == constant.UserProvidedService
   101  }
   102  
   103  type createServiceInstanceRequestBody struct {
   104  	Name            string                 `json:"name"`
   105  	ServicePlanGUID string                 `json:"service_plan_guid"`
   106  	SpaceGUID       string                 `json:"space_guid"`
   107  	Parameters      map[string]interface{} `json:"parameters,omitempty"`
   108  	Tags            []string               `json:"tags,omitempty"`
   109  }
   110  
   111  // CreateServiceInstance posts a service instance resource with the provided
   112  // attributes to the api and returns the result.
   113  func (client *Client) CreateServiceInstance(spaceGUID, servicePlanGUID, serviceInstance string, parameters map[string]interface{}, tags []string) (ServiceInstance, Warnings, error) {
   114  	requestBody := createServiceInstanceRequestBody{
   115  		Name:            serviceInstance,
   116  		ServicePlanGUID: servicePlanGUID,
   117  		SpaceGUID:       spaceGUID,
   118  		Parameters:      parameters,
   119  		Tags:            tags,
   120  	}
   121  
   122  	bodyBytes, err := json.Marshal(requestBody)
   123  	if err != nil {
   124  		return ServiceInstance{}, nil, err
   125  	}
   126  
   127  	request, err := client.newHTTPRequest(requestOptions{
   128  		RequestName: internal.PostServiceInstancesRequest,
   129  		Body:        bytes.NewReader(bodyBytes),
   130  		Query:       url.Values{"accepts_incomplete": {"true"}},
   131  	})
   132  	if err != nil {
   133  		return ServiceInstance{}, nil, err
   134  	}
   135  
   136  	var instance ServiceInstance
   137  	response := cloudcontroller.Response{
   138  		DecodeJSONResponseInto: &instance,
   139  	}
   140  
   141  	err = client.connection.Make(request, &response)
   142  	return instance, response.Warnings, err
   143  }
   144  
   145  // GetServiceInstance returns the service instance with the given GUID. This
   146  // service can be either a managed or user provided.
   147  func (client *Client) GetServiceInstance(serviceInstanceGUID string) (ServiceInstance, Warnings, error) {
   148  	request, err := client.newHTTPRequest(requestOptions{
   149  		RequestName: internal.GetServiceInstanceRequest,
   150  		URIParams:   Params{"service_instance_guid": serviceInstanceGUID},
   151  	})
   152  	if err != nil {
   153  		return ServiceInstance{}, nil, err
   154  	}
   155  
   156  	var serviceInstance ServiceInstance
   157  	response := cloudcontroller.Response{
   158  		DecodeJSONResponseInto: &serviceInstance,
   159  	}
   160  
   161  	err = client.connection.Make(request, &response)
   162  	return serviceInstance, response.Warnings, err
   163  }
   164  
   165  // GetServiceInstances returns back a list of *managed* Service Instances based
   166  // off of the provided filters.
   167  func (client *Client) GetServiceInstances(filters ...Filter) ([]ServiceInstance, Warnings, error) {
   168  	request, err := client.newHTTPRequest(requestOptions{
   169  		RequestName: internal.GetServiceInstancesRequest,
   170  		Query:       ConvertFilterParameters(filters),
   171  	})
   172  	if err != nil {
   173  		return nil, nil, err
   174  	}
   175  
   176  	var fullInstancesList []ServiceInstance
   177  	warnings, err := client.paginate(request, ServiceInstance{}, func(item interface{}) error {
   178  		if instance, ok := item.(ServiceInstance); ok {
   179  			fullInstancesList = append(fullInstancesList, instance)
   180  		} else {
   181  			return ccerror.UnknownObjectInListError{
   182  				Expected:   ServiceInstance{},
   183  				Unexpected: item,
   184  			}
   185  		}
   186  		return nil
   187  	})
   188  
   189  	return fullInstancesList, warnings, err
   190  }
   191  
   192  // GetSpaceServiceInstances returns back a list of Service Instances based off
   193  // of the space and filters provided. User provided services will be included
   194  // if includeUserProvidedServices is set to true.
   195  func (client *Client) GetSpaceServiceInstances(spaceGUID string, includeUserProvidedServices bool, filters ...Filter) ([]ServiceInstance, Warnings, error) {
   196  	query := ConvertFilterParameters(filters)
   197  
   198  	if includeUserProvidedServices {
   199  		query.Add("return_user_provided_service_instances", "true")
   200  	}
   201  
   202  	request, err := client.newHTTPRequest(requestOptions{
   203  		RequestName: internal.GetSpaceServiceInstancesRequest,
   204  		URIParams:   map[string]string{"guid": spaceGUID},
   205  		Query:       query,
   206  	})
   207  
   208  	if err != nil {
   209  		return nil, nil, err
   210  	}
   211  
   212  	var fullInstancesList []ServiceInstance
   213  	warnings, err := client.paginate(request, ServiceInstance{}, func(item interface{}) error {
   214  		if instance, ok := item.(ServiceInstance); ok {
   215  			fullInstancesList = append(fullInstancesList, instance)
   216  		} else {
   217  			return ccerror.UnknownObjectInListError{
   218  				Expected:   ServiceInstance{},
   219  				Unexpected: item,
   220  			}
   221  		}
   222  		return nil
   223  	})
   224  
   225  	return fullInstancesList, warnings, err
   226  }
   227  
   228  type MaintenanceInfo struct {
   229  	Version     string `json:"version,omitempty"`
   230  	Description string `json:"description,omitempty"`
   231  }
   232  
   233  type updateServiceInstanceRequestBody struct {
   234  	MaintenanceInfo MaintenanceInfo `json:"maintenance_info"`
   235  }
   236  
   237  func (client *Client) UpdateServiceInstanceMaintenanceInfo(serviceInstanceGUID string, maintenanceInfo MaintenanceInfo) (Warnings, error) {
   238  	requestBody := updateServiceInstanceRequestBody{
   239  		MaintenanceInfo: maintenanceInfo,
   240  	}
   241  
   242  	bodyBytes, err := json.Marshal(requestBody)
   243  	if err != nil {
   244  		return nil, err
   245  	}
   246  
   247  	request, err := client.newHTTPRequest(requestOptions{
   248  		RequestName: internal.PutServiceInstanceRequest,
   249  		URIParams:   Params{"service_instance_guid": serviceInstanceGUID},
   250  		Body:        bytes.NewReader(bodyBytes),
   251  		Query:       url.Values{"accepts_incomplete": {"true"}},
   252  	})
   253  	if err != nil {
   254  		return nil, err
   255  	}
   256  
   257  	response := cloudcontroller.Response{}
   258  
   259  	err = client.connection.Make(request, &response)
   260  	return response.Warnings, err
   261  }