1package cfclient
2
3import (
4	"bytes"
5	"encoding/json"
6	"fmt"
7	"io/ioutil"
8	"net/http"
9	"net/url"
10
11	"github.com/pkg/errors"
12)
13
14type UserProvidedServiceInstancesResponse struct {
15	Count     int                                   `json:"total_results"`
16	Pages     int                                   `json:"total_pages"`
17	NextUrl   string                                `json:"next_url"`
18	Resources []UserProvidedServiceInstanceResource `json:"resources"`
19}
20
21type UserProvidedServiceInstanceResource struct {
22	Meta   Meta                        `json:"metadata"`
23	Entity UserProvidedServiceInstance `json:"entity"`
24}
25
26type UserProvidedServiceInstance struct {
27	Guid               string                 `json:"guid"`
28	Name               string                 `json:"name"`
29	CreatedAt          string                 `json:"created_at"`
30	UpdatedAt          string                 `json:"updated_at"`
31	Credentials        map[string]interface{} `json:"credentials"`
32	SpaceGuid          string                 `json:"space_guid"`
33	Type               string                 `json:"type"`
34	Tags               []string               `json:"tags"`
35	SpaceUrl           string                 `json:"space_url"`
36	ServiceBindingsUrl string                 `json:"service_bindings_url"`
37	RoutesUrl          string                 `json:"routes_url"`
38	RouteServiceUrl    string                 `json:"route_service_url"`
39	SyslogDrainUrl     string                 `json:"syslog_drain_url"`
40	c                  *Client
41}
42
43type UserProvidedServiceInstanceRequest struct {
44	Name            string                 `json:"name"`
45	Credentials     map[string]interface{} `json:"credentials"`
46	SpaceGuid       string                 `json:"space_guid"`
47	Tags            []string               `json:"tags"`
48	RouteServiceUrl string                 `json:"route_service_url"`
49	SyslogDrainUrl  string                 `json:"syslog_drain_url"`
50}
51
52func (c *Client) ListUserProvidedServiceInstancesByQuery(query url.Values) ([]UserProvidedServiceInstance, error) {
53	var instances []UserProvidedServiceInstance
54
55	requestUrl := "/v2/user_provided_service_instances?" + query.Encode()
56	for {
57		var sir UserProvidedServiceInstancesResponse
58		r := c.NewRequest("GET", requestUrl)
59		resp, err := c.DoRequest(r)
60		if err != nil {
61			return nil, errors.Wrap(err, "Error requesting user provided service instances")
62		}
63		resBody, err := ioutil.ReadAll(resp.Body)
64		if err != nil {
65			return nil, errors.Wrap(err, "Error reading user provided service instances request:")
66		}
67
68		err = json.Unmarshal(resBody, &sir)
69		if err != nil {
70			return nil, errors.Wrap(err, "Error unmarshaling user provided service instances")
71		}
72		for _, instance := range sir.Resources {
73			instance.Entity.Guid = instance.Meta.Guid
74			instance.Entity.CreatedAt = instance.Meta.CreatedAt
75			instance.Entity.UpdatedAt = instance.Meta.UpdatedAt
76			instance.Entity.c = c
77			instances = append(instances, instance.Entity)
78		}
79
80		requestUrl = sir.NextUrl
81		if requestUrl == "" {
82			break
83		}
84	}
85	return instances, nil
86}
87
88func (c *Client) ListUserProvidedServiceInstances() ([]UserProvidedServiceInstance, error) {
89	return c.ListUserProvidedServiceInstancesByQuery(nil)
90}
91
92func (c *Client) GetUserProvidedServiceInstanceByGuid(guid string) (UserProvidedServiceInstance, error) {
93	var sir UserProvidedServiceInstanceResource
94	req := c.NewRequest("GET", "/v2/user_provided_service_instances/"+guid)
95	res, err := c.DoRequest(req)
96	if err != nil {
97		return UserProvidedServiceInstance{}, errors.Wrap(err, "Error requesting user provided service instance")
98	}
99
100	data, err := ioutil.ReadAll(res.Body)
101	if err != nil {
102		return UserProvidedServiceInstance{}, errors.Wrap(err, "Error reading user provided service instance response")
103	}
104	err = json.Unmarshal(data, &sir)
105	if err != nil {
106		return UserProvidedServiceInstance{}, errors.Wrap(err, "Error JSON parsing user provided service instance response")
107	}
108	sir.Entity.Guid = sir.Meta.Guid
109	sir.Entity.CreatedAt = sir.Meta.CreatedAt
110	sir.Entity.UpdatedAt = sir.Meta.UpdatedAt
111	sir.Entity.c = c
112	return sir.Entity, nil
113}
114
115func (c *Client) UserProvidedServiceInstanceByGuid(guid string) (UserProvidedServiceInstance, error) {
116	return c.GetUserProvidedServiceInstanceByGuid(guid)
117}
118
119func (c *Client) CreateUserProvidedServiceInstance(req UserProvidedServiceInstanceRequest) (*UserProvidedServiceInstance, error) {
120	buf := bytes.NewBuffer(nil)
121	err := json.NewEncoder(buf).Encode(req)
122	if err != nil {
123		return nil, err
124	}
125	r := c.NewRequestWithBody("POST", "/v2/user_provided_service_instances", buf)
126	resp, err := c.DoRequest(r)
127	if err != nil {
128		return nil, err
129	}
130	if resp.StatusCode != http.StatusCreated {
131		return nil, fmt.Errorf("CF API returned with status code %d", resp.StatusCode)
132	}
133
134	return c.handleUserProvidedServiceInstanceResp(resp)
135}
136
137func (c *Client) DeleteUserProvidedServiceInstance(guid string) error {
138	resp, err := c.DoRequest(c.NewRequest("DELETE", fmt.Sprintf("/v2/user_provided_service_instances/%s", guid)))
139	if err != nil {
140		return err
141	}
142	if resp.StatusCode != http.StatusNoContent {
143		return errors.Wrapf(err, "Error deleting user provided service instance %s, response code %d", guid, resp.StatusCode)
144	}
145	return nil
146}
147
148func (c *Client) UpdateUserProvidedServiceInstance(guid string, req UserProvidedServiceInstanceRequest) (*UserProvidedServiceInstance, error) {
149	buf := bytes.NewBuffer(nil)
150	err := json.NewEncoder(buf).Encode(req)
151	if err != nil {
152		return nil, err
153	}
154	r := c.NewRequestWithBody("PUT", fmt.Sprintf("/v2/user_provided_service_instances/%s", guid), buf)
155	resp, err := c.DoRequest(r)
156	if err != nil {
157		return nil, err
158	}
159	if resp.StatusCode != http.StatusCreated {
160		return nil, fmt.Errorf("CF API returned with status code %d", resp.StatusCode)
161	}
162	return c.handleUserProvidedServiceInstanceResp(resp)
163}
164
165func (c *Client) handleUserProvidedServiceInstanceResp(resp *http.Response) (*UserProvidedServiceInstance, error) {
166	body, err := ioutil.ReadAll(resp.Body)
167	defer resp.Body.Close()
168	if err != nil {
169		return nil, err
170	}
171	var upsResource UserProvidedServiceInstanceResource
172	err = json.Unmarshal(body, &upsResource)
173	if err != nil {
174		return nil, err
175	}
176	return c.mergeUserProvidedServiceInstanceResource(upsResource), nil
177}
178
179func (c *Client) mergeUserProvidedServiceInstanceResource(ups UserProvidedServiceInstanceResource) *UserProvidedServiceInstance {
180	ups.Entity.Guid = ups.Meta.Guid
181	ups.Entity.CreatedAt = ups.Meta.CreatedAt
182	ups.Entity.UpdatedAt = ups.Meta.UpdatedAt
183	ups.Entity.c = c
184	return &ups.Entity
185}
186