blob: b1629bfc7226ae1df6bc3ddefe8608ec5d9bd2aa [file] [log] [blame]
Jamie Hannaford7afb7af2014-11-04 13:32:20 +01001package monitors
2
3import (
4 "errors"
5
6 "github.com/racker/perigee"
7
8 "github.com/rackspace/gophercloud"
9)
10
11// UpdateOptsBuilder is the interface options structs have to satisfy in order
12// to be used in the main Update operation in this package.
13type UpdateOptsBuilder interface {
14 ToMonitorUpdateMap() (map[string]interface{}, error)
15}
16
17// UpdateConnectMonitorOpts represents the options needed to update a CONNECT
18// monitor.
19type UpdateConnectMonitorOpts struct {
20 // Required - number of permissible monitor failures before removing a node
21 // from rotation. Must be a number between 1 and 10.
22 AttemptLimit int
23
24 // Required - the minimum number of seconds to wait before executing the
25 // health monitor. Must be a number between 1 and 3600.
26 Delay int
27
28 // Required - maximum number of seconds to wait for a connection to be
29 // established before timing out. Must be a number between 1 and 300.
30 Timeout int
31}
32
33var (
34 errAttemptLimit = errors.New("AttemptLimit field must be an int greater than 1 and less than 10")
35 errDelay = errors.New("Delay field must be an int greater than 1 and less than 10")
36 errTimeout = errors.New("Timeout field must be an int greater than 1 and less than 10")
37)
38
39func withinRange(val, min, max int) bool {
40 return val > min && val < max
41}
42
43// ToMonitorUpdateMap produces a map for updating CONNECT monitors.
44func (opts UpdateConnectMonitorOpts) ToMonitorUpdateMap() (map[string]interface{}, error) {
45 type m map[string]interface{}
46
47 if !withinRange(opts.AttemptLimit, 1, 10) {
48 return m{}, errAttemptLimit
49 }
50 if !withinRange(opts.Delay, 1, 3600) {
51 return m{}, errDelay
52 }
53 if !withinRange(opts.Timeout, 1, 300) {
54 return m{}, errTimeout
55 }
56
57 return m{"healthMonitor": m{
58 "attemptsBeforeDeactivation": opts.AttemptLimit,
59 "delay": opts.Delay,
60 "timeout": opts.Timeout,
61 "type": CONNECT,
62 }}, nil
63}
64
65// UpdateHTTPMonitorOpts represents the options needed to update a HTTP monitor.
66type UpdateHTTPMonitorOpts struct {
67 // Required - number of permissible monitor failures before removing a node
68 // from rotation. Must be a number between 1 and 10.
69 AttemptLimit int `mapstructure:"attemptsBeforeDeactivation"`
70
71 // Required - the minimum number of seconds to wait before executing the
72 // health monitor. Must be a number between 1 and 3600.
73 Delay int
74
75 // Required - maximum number of seconds to wait for a connection to be
76 // established before timing out. Must be a number between 1 and 300.
77 Timeout int
78
79 // Required - a regular expression that will be used to evaluate the contents
80 // of the body of the response.
81 BodyRegex string
82
83 // Required - the HTTP path that will be used in the sample request.
84 Path string
85
86 // Required - a regular expression that will be used to evaluate the HTTP
87 // status code returned in the response.
88 StatusRegex string
89
90 // Optional - the name of a host for which the health monitors will check.
91 HostHeader string
92
93 // Required - either HTTP or HTTPS
94 Type Type
95}
96
97// ToMonitorUpdateMap produces a map for updating HTTP(S) monitors.
98func (opts UpdateHTTPMonitorOpts) ToMonitorUpdateMap() (map[string]interface{}, error) {
99 type m map[string]interface{}
100
101 if !withinRange(opts.AttemptLimit, 1, 10) {
102 return m{}, errAttemptLimit
103 }
104 if !withinRange(opts.Delay, 1, 3600) {
105 return m{}, errDelay
106 }
107 if !withinRange(opts.Timeout, 1, 300) {
108 return m{}, errTimeout
109 }
110 if opts.Type != HTTP && opts.Type != HTTPS {
111 return m{}, errors.New("Type must either by HTTP or HTTPS")
112 }
113 if opts.BodyRegex == "" {
114 return m{}, errors.New("BodyRegex is a required field")
115 }
116 if opts.Path == "" {
117 return m{}, errors.New("Path is a required field")
118 }
119 if opts.StatusRegex == "" {
120 return m{}, errors.New("StatusRegex is a required field")
121 }
122
123 json := m{
124 "attemptsBeforeDeactivation": opts.AttemptLimit,
125 "delay": opts.Delay,
126 "timeout": opts.Timeout,
127 "type": opts.Type,
128 "bodyRegex": opts.BodyRegex,
129 "path": opts.Path,
130 "statusRegex": opts.StatusRegex,
131 }
132
133 if opts.HostHeader != "" {
134 json["hostHeader"] = opts.HostHeader
135 }
136
137 return m{"healthMonitor": json}, nil
138}
139
140// Update is the operation responsible for updating a health monitor.
141func Update(c *gophercloud.ServiceClient, id int, opts UpdateOptsBuilder) UpdateResult {
142 var res UpdateResult
143
144 reqBody, err := opts.ToMonitorUpdateMap()
145 if err != nil {
146 res.Err = err
147 return res
148 }
149
150 _, res.Err = perigee.Request("PUT", rootURL(c, id), perigee.Options{
151 MoreHeaders: c.AuthenticatedHeaders(),
152 ReqBody: &reqBody,
153 OkCodes: []int{200},
154 })
155
156 return res
157}
Jamie Hannafordc9a4d892014-11-04 14:01:56 +0100158
Jamie Hannafordd7301dd2014-11-04 14:05:39 +0100159// Get is the operation responsible for showing details of a health monitor.
Jamie Hannafordc9a4d892014-11-04 14:01:56 +0100160func Get(c *gophercloud.ServiceClient, id int) GetResult {
161 var res GetResult
162
163 _, res.Err = perigee.Request("GET", rootURL(c, id), perigee.Options{
164 MoreHeaders: c.AuthenticatedHeaders(),
165 Results: &res.Body,
166 OkCodes: []int{200},
167 })
168
169 return res
170}
Jamie Hannafordd7301dd2014-11-04 14:05:39 +0100171
172// Delete is the operation responsible for deleting a health monitor.
173func Delete(c *gophercloud.ServiceClient, id int) DeleteResult {
174 var res DeleteResult
175
176 _, res.Err = perigee.Request("DELETE", rootURL(c, id), perigee.Options{
177 MoreHeaders: c.AuthenticatedHeaders(),
178 OkCodes: []int{200},
179 })
180
181 return res
182}