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