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