Skip to content
This repository was archived by the owner on Aug 1, 2023. It is now read-only.

Commit d6336c4

Browse files
committed
Adding Support for LBaaS v2 - Health Monitors
1 parent e940a16 commit d6336c4

File tree

4 files changed

+763
-0
lines changed

4 files changed

+763
-0
lines changed
Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
package monitors
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/rackspace/gophercloud"
7+
"github.com/rackspace/gophercloud/pagination"
8+
)
9+
10+
// ListOpts allows the filtering and sorting of paginated collections through
11+
// the API. Filtering is achieved by passing in struct field values that map to
12+
// the Monitor attributes you want to see returned. SortKey allows you to
13+
// sort by a particular Monitor attribute. SortDir sets the direction, and is
14+
// either `asc' or `desc'. Marker and Limit are used for pagination.
15+
type ListOpts struct {
16+
ID string `q:"id"`
17+
TenantID string `q:"tenant_id"`
18+
Type string `q:"type"`
19+
Delay int `q:"delay"`
20+
Timeout int `q:"timeout"`
21+
MaxRetries int `q:"max_retries"`
22+
HTTPMethod string `q:"http_method"`
23+
URLPath string `q:"url_path"`
24+
ExpectedCodes string `q:"expected_codes"`
25+
AdminStateUp *bool `q:"admin_state_up"`
26+
Status string `q:"status"`
27+
Limit int `q:"limit"`
28+
Marker string `q:"marker"`
29+
SortKey string `q:"sort_key"`
30+
SortDir string `q:"sort_dir"`
31+
}
32+
33+
// List returns a Pager which allows you to iterate over a collection of
34+
// routers. It accepts a ListOpts struct, which allows you to filter and sort
35+
// the returned collection for greater efficiency.
36+
//
37+
// Default policy settings return only those routers that are owned by the
38+
// tenant who submits the request, unless an admin user submits the request.
39+
func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
40+
q, err := gophercloud.BuildQueryString(&opts)
41+
if err != nil {
42+
return pagination.Pager{Err: err}
43+
}
44+
u := rootURL(c) + q.String()
45+
46+
return pagination.NewPager(c, u, func(r pagination.PageResult) pagination.Page {
47+
return MonitorPage{pagination.LinkedPageBase{PageResult: r}}
48+
})
49+
}
50+
51+
// Constants that represent approved monitoring types.
52+
const (
53+
TypePING = "PING"
54+
TypeTCP = "TCP"
55+
TypeHTTP = "HTTP"
56+
TypeHTTPS = "HTTPS"
57+
)
58+
59+
var (
60+
errPoolIDRequired = fmt.Errorf("Pool ID to monitor is required")
61+
errValidTypeRequired = fmt.Errorf("A valid Type is required. Supported values are PING, TCP, HTTP and HTTPS")
62+
errDelayRequired = fmt.Errorf("Delay is required")
63+
errTimeoutRequired = fmt.Errorf("Timeout is required")
64+
errMaxRetriesRequired = fmt.Errorf("MaxRetries is required")
65+
errURLPathRequired = fmt.Errorf("URL path is required")
66+
errExpectedCodesRequired = fmt.Errorf("ExpectedCodes is required")
67+
errDelayMustGETimeout = fmt.Errorf("Delay must be greater than or equal to timeout")
68+
)
69+
70+
// CreateOpts contains all the values needed to create a new Health Monitor.
71+
type CreateOpts struct {
72+
// The Pool to Monitor.
73+
PoolID string
74+
75+
// Required for admins. Indicates the owner of the Loadbalancer.
76+
TenantID string
77+
78+
// Required. The type of probe, which is PING, TCP, HTTP, or HTTPS, that is
79+
// sent by the load balancer to verify the member state.
80+
Type string
81+
82+
// Required. The time, in seconds, between sending probes to members.
83+
Delay int
84+
85+
// Required. Maximum number of seconds for a Monitor to wait for a ping reply
86+
// before it times out. The value must be less than the delay value.
87+
Timeout int
88+
89+
// Required. Number of permissible ping failures before changing the member's
90+
// status to INACTIVE. Must be a number between 1 and 10.
91+
MaxRetries int
92+
93+
// Required for HTTP(S) types. URI path that will be accessed if Monitor type
94+
// is HTTP or HTTPS.
95+
URLPath string
96+
97+
// Required for HTTP(S) types. The HTTP method used for requests by the
98+
// Monitor. If this attribute is not specified, it defaults to "GET".
99+
HTTPMethod string
100+
101+
// Required for HTTP(S) types. Expected HTTP codes for a passing HTTP(S)
102+
// Monitor. You can either specify a single status like "200", or a range
103+
// like "200-202".
104+
ExpectedCodes string
105+
106+
AdminStateUp *bool
107+
}
108+
109+
// Create is an operation which provisions a new Health Monitor. There are
110+
// different types of Monitor you can provision: PING, TCP or HTTP(S). Below
111+
// are examples of how to create each one.
112+
//
113+
// Here is an example config struct to use when creating a PING or TCP Monitor:
114+
//
115+
// CreateOpts{Type: TypePING, Delay: 20, Timeout: 10, MaxRetries: 3}
116+
// CreateOpts{Type: TypeTCP, Delay: 20, Timeout: 10, MaxRetries: 3}
117+
//
118+
// Here is an example config struct to use when creating a HTTP(S) Monitor:
119+
//
120+
// CreateOpts{Type: TypeHTTP, Delay: 20, Timeout: 10, MaxRetries: 3,
121+
// HttpMethod: "HEAD", ExpectedCodes: "200". PoolID: "2c946bfc-1804-43ab-a2ff-58f6a762b505"}
122+
//
123+
func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult {
124+
var res CreateResult
125+
126+
// Validate inputs
127+
allowed := map[string]bool{TypeHTTP: true, TypeHTTPS: true, TypeTCP: true, TypePING: true}
128+
if opts.Type == "" || allowed[opts.Type] == false {
129+
res.Err = errValidTypeRequired
130+
}
131+
if opts.PoolID == "" {
132+
res.Err = errPoolIDRequired
133+
}
134+
if opts.Delay == 0 {
135+
res.Err = errDelayRequired
136+
}
137+
if opts.Timeout == 0 {
138+
res.Err = errTimeoutRequired
139+
}
140+
if opts.MaxRetries == 0 {
141+
res.Err = errMaxRetriesRequired
142+
}
143+
if opts.Type == TypeHTTP || opts.Type == TypeHTTPS {
144+
if opts.URLPath == "" {
145+
res.Err = errURLPathRequired
146+
}
147+
if opts.ExpectedCodes == "" {
148+
res.Err = errExpectedCodesRequired
149+
}
150+
}
151+
if opts.Delay < opts.Timeout {
152+
res.Err = errDelayMustGETimeout
153+
}
154+
if res.Err != nil {
155+
return res
156+
}
157+
158+
type monitor struct {
159+
Type string `json:"type"`
160+
PoolID string `json:"pool_id"`
161+
Delay int `json:"delay"`
162+
Timeout int `json:"timeout"`
163+
MaxRetries int `json:"max_retries"`
164+
TenantID *string `json:"tenant_id,omitempty"`
165+
URLPath *string `json:"url_path,omitempty"`
166+
ExpectedCodes *string `json:"expected_codes,omitempty"`
167+
HTTPMethod *string `json:"http_method,omitempty"`
168+
AdminStateUp *bool `json:"admin_state_up,omitempty"`
169+
}
170+
171+
type request struct {
172+
Monitor monitor `json:"health_monitor"`
173+
}
174+
175+
reqBody := request{Monitor: monitor{
176+
Type: opts.Type,
177+
PoolID: opts.PoolID,
178+
Delay: opts.Delay,
179+
Timeout: opts.Timeout,
180+
MaxRetries: opts.MaxRetries,
181+
TenantID: gophercloud.MaybeString(opts.TenantID),
182+
URLPath: gophercloud.MaybeString(opts.URLPath),
183+
ExpectedCodes: gophercloud.MaybeString(opts.ExpectedCodes),
184+
HTTPMethod: gophercloud.MaybeString(opts.HTTPMethod),
185+
AdminStateUp: opts.AdminStateUp,
186+
}}
187+
188+
_, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil)
189+
return res
190+
}
191+
192+
// Get retrieves a particular Health Monitor based on its unique ID.
193+
func Get(c *gophercloud.ServiceClient, id string) GetResult {
194+
var res GetResult
195+
_, res.Err = c.Get(resourceURL(c, id), &res.Body, nil)
196+
return res
197+
}
198+
199+
// UpdateOpts contains all the values needed to update an existing Monitor.
200+
// Attributes not listed here but appear in CreateOpts are immutable and cannot
201+
// be updated.
202+
type UpdateOpts struct {
203+
// Required. The time, in seconds, between sending probes to members.
204+
Delay int
205+
206+
// Required. Maximum number of seconds for a Monitor to wait for a ping reply
207+
// before it times out. The value must be less than the delay value.
208+
Timeout int
209+
210+
// Required. Number of permissible ping failures before changing the member's
211+
// status to INACTIVE. Must be a number between 1 and 10.
212+
MaxRetries int
213+
214+
// Required for HTTP(S) types. URI path that will be accessed if Monitor type
215+
// is HTTP or HTTPS.
216+
URLPath string
217+
218+
// Required for HTTP(S) types. The HTTP method used for requests by the
219+
// Monitor. If this attribute is not specified, it defaults to "GET".
220+
HTTPMethod string
221+
222+
// Required for HTTP(S) types. Expected HTTP codes for a passing HTTP(S)
223+
// Monitor. You can either specify a single status like "200", or a range
224+
// like "200-202".
225+
ExpectedCodes string
226+
227+
AdminStateUp *bool
228+
}
229+
230+
// Update is an operation which modifies the attributes of the specified Monitor.
231+
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) UpdateResult {
232+
var res UpdateResult
233+
234+
if opts.Delay > 0 && opts.Timeout > 0 && opts.Delay < opts.Timeout {
235+
res.Err = errDelayMustGETimeout
236+
}
237+
238+
type monitor struct {
239+
Delay int `json:"delay"`
240+
Timeout int `json:"timeout"`
241+
MaxRetries int `json:"max_retries"`
242+
URLPath *string `json:"url_path,omitempty"`
243+
ExpectedCodes *string `json:"expected_codes,omitempty"`
244+
HTTPMethod *string `json:"http_method,omitempty"`
245+
AdminStateUp *bool `json:"admin_state_up,omitempty"`
246+
}
247+
248+
type request struct {
249+
Monitor monitor `json:"health_monitor"`
250+
}
251+
252+
reqBody := request{Monitor: monitor{
253+
Delay: opts.Delay,
254+
Timeout: opts.Timeout,
255+
MaxRetries: opts.MaxRetries,
256+
URLPath: gophercloud.MaybeString(opts.URLPath),
257+
ExpectedCodes: gophercloud.MaybeString(opts.ExpectedCodes),
258+
HTTPMethod: gophercloud.MaybeString(opts.HTTPMethod),
259+
AdminStateUp: opts.AdminStateUp,
260+
}}
261+
262+
_, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{
263+
OkCodes: []int{200, 202},
264+
})
265+
266+
return res
267+
}
268+
269+
// Delete will permanently delete a particular Monitor based on its unique ID.
270+
func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
271+
var res DeleteResult
272+
_, res.Err = c.Delete(resourceURL(c, id), nil)
273+
return res
274+
}

0 commit comments

Comments
 (0)