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 ServiceBrokerResponse struct {
15	Count     int                     `json:"total_results"`
16	Pages     int                     `json:"total_pages"`
17	NextUrl   string                  `json:"next_url"`
18	Resources []ServiceBrokerResource `json:"resources"`
19}
20
21type ServiceBrokerResource struct {
22	Meta   Meta          `json:"metadata"`
23	Entity ServiceBroker `json:"entity"`
24}
25
26type UpdateServiceBrokerRequest struct {
27	Name      string `json:"name"`
28	BrokerURL string `json:"broker_url"`
29	Username  string `json:"auth_username"`
30	Password  string `json:"auth_password"`
31}
32
33type CreateServiceBrokerRequest struct {
34	Name      string `json:"name"`
35	BrokerURL string `json:"broker_url"`
36	Username  string `json:"auth_username"`
37	Password  string `json:"auth_password"`
38	SpaceGUID string `json:"space_guid,omitempty"`
39}
40
41type ServiceBroker struct {
42	Guid      string `json:"guid"`
43	Name      string `json:"name"`
44	CreatedAt string `json:"created_at"`
45	UpdatedAt string `json:"updated_at"`
46	BrokerURL string `json:"broker_url"`
47	Username  string `json:"auth_username"`
48	Password  string `json:"auth_password"`
49	SpaceGUID string `json:"space_guid,omitempty"`
50	c         *Client
51}
52
53func (c *Client) DeleteServiceBroker(guid string) error {
54	requestUrl := fmt.Sprintf("/v2/service_brokers/%s", guid)
55	r := c.NewRequest("DELETE", requestUrl)
56	resp, err := c.DoRequest(r)
57	if err != nil {
58		return err
59	}
60	if resp.StatusCode != http.StatusNoContent {
61		return errors.Wrapf(err, "Error deleteing service broker %s, response code: %d", guid, resp.StatusCode)
62	}
63	return nil
64
65}
66
67func (c *Client) UpdateServiceBroker(guid string, usb UpdateServiceBrokerRequest) (ServiceBroker, error) {
68	var serviceBrokerResource ServiceBrokerResource
69
70	buf := bytes.NewBuffer(nil)
71	err := json.NewEncoder(buf).Encode(usb)
72	if err != nil {
73		return ServiceBroker{}, err
74	}
75	req := c.NewRequestWithBody("PUT", fmt.Sprintf("/v2/service_brokers/%s", guid), buf)
76	resp, err := c.DoRequest(req)
77	if err != nil {
78		return ServiceBroker{}, err
79	}
80	if resp.StatusCode != http.StatusOK {
81		return ServiceBroker{}, fmt.Errorf("CF API returned with status code %d", resp.StatusCode)
82	}
83
84	body, err := ioutil.ReadAll(resp.Body)
85	defer resp.Body.Close()
86	if err != nil {
87		return ServiceBroker{}, err
88	}
89	err = json.Unmarshal(body, &serviceBrokerResource)
90	if err != nil {
91		return ServiceBroker{}, err
92	}
93	serviceBrokerResource.Entity.Guid = serviceBrokerResource.Meta.Guid
94	return serviceBrokerResource.Entity, nil
95}
96
97func (c *Client) CreateServiceBroker(csb CreateServiceBrokerRequest) (ServiceBroker, error) {
98	var serviceBrokerResource ServiceBrokerResource
99
100	buf := bytes.NewBuffer(nil)
101	err := json.NewEncoder(buf).Encode(csb)
102	if err != nil {
103		return ServiceBroker{}, err
104	}
105	req := c.NewRequestWithBody("POST", "/v2/service_brokers", buf)
106	resp, err := c.DoRequest(req)
107	if err != nil {
108		return ServiceBroker{}, err
109	}
110	if resp.StatusCode != http.StatusCreated {
111		return ServiceBroker{}, fmt.Errorf("CF API returned with status code %d", resp.StatusCode)
112	}
113
114	body, err := ioutil.ReadAll(resp.Body)
115	defer resp.Body.Close()
116	if err != nil {
117		return ServiceBroker{}, err
118	}
119	err = json.Unmarshal(body, &serviceBrokerResource)
120	if err != nil {
121		return ServiceBroker{}, err
122	}
123
124	serviceBrokerResource.Entity.Guid = serviceBrokerResource.Meta.Guid
125	return serviceBrokerResource.Entity, nil
126}
127
128func (c *Client) ListServiceBrokersByQuery(query url.Values) ([]ServiceBroker, error) {
129	var sbs []ServiceBroker
130	requestUrl := "/v2/service_brokers?" + query.Encode()
131	for {
132		serviceBrokerResp, err := c.getServiceBrokerResponse(requestUrl)
133		if err != nil {
134			return []ServiceBroker{}, err
135		}
136		for _, sb := range serviceBrokerResp.Resources {
137			sb.Entity.Guid = sb.Meta.Guid
138			sb.Entity.CreatedAt = sb.Meta.CreatedAt
139			sb.Entity.UpdatedAt = sb.Meta.UpdatedAt
140			sbs = append(sbs, sb.Entity)
141		}
142		requestUrl = serviceBrokerResp.NextUrl
143		if requestUrl == "" {
144			break
145		}
146	}
147	return sbs, nil
148}
149
150func (c *Client) ListServiceBrokers() ([]ServiceBroker, error) {
151	return c.ListServiceBrokersByQuery(nil)
152}
153
154func (c *Client) GetServiceBrokerByGuid(guid string) (ServiceBroker, error) {
155	var serviceBrokerRes ServiceBrokerResource
156	r := c.NewRequest("GET", "/v2/service_brokers/"+guid)
157	resp, err := c.DoRequest(r)
158	if err != nil {
159		return ServiceBroker{}, err
160	}
161	body, err := ioutil.ReadAll(resp.Body)
162	defer resp.Body.Close()
163	if err != nil {
164		return ServiceBroker{}, err
165	}
166	err = json.Unmarshal(body, &serviceBrokerRes)
167	if err != nil {
168		return ServiceBroker{}, err
169	}
170	serviceBrokerRes.Entity.Guid = serviceBrokerRes.Meta.Guid
171	serviceBrokerRes.Entity.CreatedAt = serviceBrokerRes.Meta.CreatedAt
172	serviceBrokerRes.Entity.UpdatedAt = serviceBrokerRes.Meta.UpdatedAt
173	return serviceBrokerRes.Entity, nil
174}
175
176func (c *Client) GetServiceBrokerByName(name string) (ServiceBroker, error) {
177	var sb ServiceBroker
178	q := url.Values{}
179	q.Set("q", "name:"+name)
180	sbs, err := c.ListServiceBrokersByQuery(q)
181	if err != nil {
182		return sb, err
183	}
184	if len(sbs) == 0 {
185		return sb, fmt.Errorf("Unable to find service broker %s", name)
186	}
187	return sbs[0], nil
188}
189
190func (c *Client) getServiceBrokerResponse(requestUrl string) (ServiceBrokerResponse, error) {
191	var serviceBrokerResp ServiceBrokerResponse
192	r := c.NewRequest("GET", requestUrl)
193	resp, err := c.DoRequest(r)
194	if err != nil {
195		return ServiceBrokerResponse{}, errors.Wrap(err, "Error requesting Service Brokers")
196	}
197	resBody, err := ioutil.ReadAll(resp.Body)
198	defer resp.Body.Close()
199	if err != nil {
200		return ServiceBrokerResponse{}, errors.Wrap(err, "Error reading Service Broker request")
201	}
202	err = json.Unmarshal(resBody, &serviceBrokerResp)
203	if err != nil {
204		return ServiceBrokerResponse{}, errors.Wrap(err, "Error unmarshalling Service Broker")
205	}
206	return serviceBrokerResp, nil
207}
208