blob: b5b38fcfef69e9ffa8fb3853806ac669d38abb9c [file] [log] [blame]
Ash Wilson0a997f82014-09-03 15:50:52 -04001package endpoints
Ash Wilsonbdfc3302014-09-04 10:16:28 -04002
3import (
Ash Wilson989ce542014-09-04 10:52:49 -04004 "strconv"
Ash Wilsonbdfc3302014-09-04 10:16:28 -04005
Ash Wilson989ce542014-09-04 10:52:49 -04006 "github.com/racker/perigee"
Ash Wilsonbdfc3302014-09-04 10:16:28 -04007 "github.com/rackspace/gophercloud"
Ash Wilson989ce542014-09-04 10:52:49 -04008 "github.com/rackspace/gophercloud/openstack/utils"
Ash Wilsonbdfc3302014-09-04 10:16:28 -04009)
10
11// Interface describes the availability of a specific service endpoint.
12type Interface string
13
14const (
15 // InterfaceAdmin makes an endpoint only available to administrators.
16 InterfaceAdmin Interface = "admin"
17
18 // InterfacePublic makes an endpoint available to everyone.
19 InterfacePublic Interface = "public"
20
21 // InterfaceInternal makes an endpoint only available within the cluster.
22 InterfaceInternal Interface = "internal"
23)
24
Ash Wilsonf04a74c2014-09-04 11:16:20 -040025// maybeString returns nil for empty strings and nil for empty.
26func maybeString(original string) *string {
27 if original != "" {
28 return &original
29 }
30 return nil
31}
32
Ash Wilsonbdfc3302014-09-04 10:16:28 -040033// EndpointOpts contains the subset of Endpoint attributes that should be used to create or update an Endpoint.
34type EndpointOpts struct {
35 Interface Interface
36 Name string
37 Region string
38 URL string
39 ServiceID string
40}
41
42// Create inserts a new Endpoint into the service catalog.
Ash Wilson989ce542014-09-04 10:52:49 -040043// Within EndpointOpts, Region may be omitted by being left as "", but all other fields are required.
Ash Wilsonbdfc3302014-09-04 10:16:28 -040044func Create(client *gophercloud.ServiceClient, opts EndpointOpts) (*Endpoint, error) {
Ash Wilson989ce542014-09-04 10:52:49 -040045 // Redefined so that Region can be re-typed as a *string, which can be omitted from the JSON output.
46 type endpoint struct {
47 Interface string `json:"interface"`
48 Name string `json:"name"`
49 Region *string `json:"region,omitempty"`
50 URL string `json:"url"`
51 ServiceID string `json:"service_id"`
52 }
53
54 type request struct {
55 Endpoint endpoint `json:"endpoint"`
56 }
57
58 type response struct {
59 Endpoint Endpoint `json:"endpoint"`
60 }
61
62 // Ensure that EndpointOpts is fully populated.
63 if opts.Interface == "" {
64 return nil, ErrInterfaceRequired
65 }
66 if opts.Name == "" {
67 return nil, ErrNameRequired
68 }
69 if opts.URL == "" {
70 return nil, ErrURLRequired
71 }
72 if opts.ServiceID == "" {
73 return nil, ErrServiceIDRequired
74 }
75
76 // Populate the request body.
77 reqBody := request{
78 Endpoint: endpoint{
79 Interface: string(opts.Interface),
80 Name: opts.Name,
81 URL: opts.URL,
82 ServiceID: opts.ServiceID,
83 },
84 }
Ash Wilsonf04a74c2014-09-04 11:16:20 -040085 reqBody.Endpoint.Region = maybeString(opts.Region)
Ash Wilson989ce542014-09-04 10:52:49 -040086
87 var respBody response
88 _, err := perigee.Request("POST", getListURL(client), perigee.Options{
89 MoreHeaders: client.Provider.AuthenticatedHeaders(),
90 ReqBody: &reqBody,
91 Results: &respBody,
92 OkCodes: []int{201},
93 })
94 if err != nil {
95 return nil, err
96 }
97
98 return &respBody.Endpoint, nil
Ash Wilsonbdfc3302014-09-04 10:16:28 -040099}
100
101// ListOpts allows finer control over the the endpoints returned by a List call.
102// All fields are optional.
103type ListOpts struct {
104 Interface Interface
105 ServiceID string
106 Page int
107 PerPage int
108}
109
110// List enumerates endpoints in a paginated collection, optionally filtered by ListOpts criteria.
111func List(client *gophercloud.ServiceClient, opts ListOpts) (*EndpointList, error) {
Ash Wilson32c0e8d2014-09-04 10:53:08 -0400112 q := make(map[string]string)
113 if opts.Interface != "" {
114 q["interface"] = string(opts.Interface)
115 }
116 if opts.ServiceID != "" {
117 q["service_id"] = opts.ServiceID
118 }
119 if opts.Page != 0 {
120 q["page"] = strconv.Itoa(opts.Page)
121 }
122 if opts.PerPage != 0 {
123 q["per_page"] = strconv.Itoa(opts.Page)
124 }
125
126 u := getListURL(client) + utils.BuildQuery(q)
127
128 var respBody []Endpoint
129 _, err := perigee.Request("GET", u, perigee.Options{
130 MoreHeaders: client.Provider.AuthenticatedHeaders(),
131 Results: &respBody,
132 OkCodes: []int{200},
133 })
134 if err != nil {
135 return nil, err
136 }
137
138 return &EndpointList{Endpoints: respBody}, nil
Ash Wilsonbdfc3302014-09-04 10:16:28 -0400139}
140
141// Update changes an existing endpoint with new data.
Ash Wilsonf04a74c2014-09-04 11:16:20 -0400142// All fields are optional in the provided EndpointOpts.
Ash Wilsonbdfc3302014-09-04 10:16:28 -0400143func Update(client *gophercloud.ServiceClient, endpointID string, opts EndpointOpts) (*Endpoint, error) {
Ash Wilsonf04a74c2014-09-04 11:16:20 -0400144 type endpoint struct {
145 Interface *string `json:"interface,omitempty"`
146 Name *string `json:"name,omitempty"`
147 Region *string `json:"region,omitempty"`
148 URL *string `json:"url,omitempty"`
149 ServiceID *string `json:"service_id,omitempty"`
150 }
151
152 type request struct {
153 Endpoint endpoint `json:"endpoint"`
154 }
155
156 type response struct {
157 Endpoint Endpoint `json:"endpoint"`
158 }
159
160 reqBody := request{Endpoint: endpoint{}}
161 reqBody.Endpoint.Interface = maybeString(string(opts.Interface))
162 reqBody.Endpoint.Name = maybeString(opts.Name)
163 reqBody.Endpoint.Region = maybeString(opts.Region)
164 reqBody.Endpoint.URL = maybeString(opts.URL)
165 reqBody.Endpoint.ServiceID = maybeString(opts.ServiceID)
166
167 var respBody response
168 _, err := perigee.Request("PATCH", getEndpointURL(client, endpointID), perigee.Options{
169 MoreHeaders: client.Provider.AuthenticatedHeaders(),
170 ReqBody: &reqBody,
171 Results: &respBody,
172 OkCodes: []int{200},
173 })
174 if err != nil {
175 return nil, err
176 }
177
178 return &respBody.Endpoint, nil
Ash Wilsonbdfc3302014-09-04 10:16:28 -0400179}
180
181// Delete removes an endpoint from the service catalog.
182func Delete(client *gophercloud.ServiceClient, endpointID string) error {
Ash Wilson70db2ab2014-09-04 11:18:32 -0400183 _, err := perigee.Request("DELETE", getEndpointURL(client, endpointID), perigee.Options{
184 MoreHeaders: client.Provider.AuthenticatedHeaders(),
185 OkCodes: []int{204},
186 })
187 return err
Ash Wilsonbdfc3302014-09-04 10:16:28 -0400188}