blob: 58ec6a8ff8c7c8137bba2a58964e93db51b0d0fe [file] [log] [blame]
Jamie Hannaford924c09d2014-11-19 12:05:38 +01001package secgroups
2
3import (
Jamie Hannaford8badf1e2014-11-19 14:39:26 +01004 "errors"
5
Jamie Hannaforda493e642014-11-19 12:40:30 +01006 "github.com/racker/perigee"
7
Jamie Hannaford924c09d2014-11-19 12:05:38 +01008 "github.com/rackspace/gophercloud"
9 "github.com/rackspace/gophercloud/pagination"
10)
11
Jamie Hannaford19151792014-11-19 12:46:47 +010012func commonList(client *gophercloud.ServiceClient, url string) pagination.Pager {
Jamie Hannaford924c09d2014-11-19 12:05:38 +010013 createPage := func(r pagination.PageResult) pagination.Page {
14 return SecurityGroupPage{pagination.SinglePageBase(r)}
15 }
16
Jamie Hannaford19151792014-11-19 12:46:47 +010017 return pagination.NewPager(client, url, createPage)
18}
19
Jamie Hannaford7f34d8e2014-11-20 12:24:55 +010020// List will return a collection of all the security groups for a particular
21// tenant.
Jamie Hannaford19151792014-11-19 12:46:47 +010022func List(client *gophercloud.ServiceClient) pagination.Pager {
23 return commonList(client, rootURL(client))
24}
25
Jamie Hannaford7f34d8e2014-11-20 12:24:55 +010026// ListByServer will return a collection of all the security groups which are
27// associated with a particular server.
Jamie Hannaford19151792014-11-19 12:46:47 +010028func ListByServer(client *gophercloud.ServiceClient, serverID string) pagination.Pager {
29 return commonList(client, listByServerURL(client, serverID))
Jamie Hannaford924c09d2014-11-19 12:05:38 +010030}
Jamie Hannaforda493e642014-11-19 12:40:30 +010031
Jamie Hannaford7f34d8e2014-11-20 12:24:55 +010032// GroupOpts is the underlying struct responsible for creating or updating
33// security groups. It therefore represents the mutable attributes of a
34// security group.
Jamie Hannaford30c74662014-11-19 15:37:34 +010035type GroupOpts struct {
Jamie Hannaforda493e642014-11-19 12:40:30 +010036 // Optional - the name of your security group. If no value provided, null
37 // will be set.
38 Name string `json:"name,omitempty"`
39
40 // Optional - the description of your security group. If no value provided,
41 // null will be set.
42 Description string `json:"description,omitempty"`
43}
44
Jamie Hannaford7f34d8e2014-11-20 12:24:55 +010045// CreateOpts is the struct responsible for creating a security group.
Jamie Hannaford30c74662014-11-19 15:37:34 +010046type CreateOpts GroupOpts
47
Jamie Hannaford7f34d8e2014-11-20 12:24:55 +010048// Create will create a new security group.
Jamie Hannaforda493e642014-11-19 12:40:30 +010049func Create(client *gophercloud.ServiceClient, opts CreateOpts) CreateResult {
50 var result CreateResult
51
52 reqBody := struct {
53 CreateOpts `json:"security_group"`
54 }{opts}
55
56 _, result.Err = perigee.Request("POST", rootURL(client), perigee.Options{
57 Results: &result.Body,
58 ReqBody: &reqBody,
59 MoreHeaders: client.AuthenticatedHeaders(),
60 OkCodes: []int{200},
61 })
62
63 return result
64}
Jamie Hannafordb38dd312014-11-19 13:02:11 +010065
Jamie Hannaford7f34d8e2014-11-20 12:24:55 +010066// UpdateOpts is the struct responsible for updating an existing security group.
Jamie Hannaford30c74662014-11-19 15:37:34 +010067type UpdateOpts GroupOpts
68
Jamie Hannaford7f34d8e2014-11-20 12:24:55 +010069// Update will modify the mutable properties of a security group, notably its
70// name and description.
Jamie Hannaford30c74662014-11-19 15:37:34 +010071func Update(client *gophercloud.ServiceClient, id string, opts UpdateOpts) UpdateResult {
72 var result UpdateResult
73
74 reqBody := struct {
75 UpdateOpts `json:"security_group"`
76 }{opts}
77
Jamie Hannaford740e4a32014-11-19 16:13:30 +010078 _, result.Err = perigee.Request("PUT", resourceURL(client, id), perigee.Options{
Jamie Hannaford30c74662014-11-19 15:37:34 +010079 Results: &result.Body,
80 ReqBody: &reqBody,
81 MoreHeaders: client.AuthenticatedHeaders(),
82 OkCodes: []int{200},
83 })
84
85 return result
86}
87
Jamie Hannaford7f34d8e2014-11-20 12:24:55 +010088// Get will return details for a particular security group.
Jamie Hannafordb38dd312014-11-19 13:02:11 +010089func Get(client *gophercloud.ServiceClient, id string) GetResult {
90 var result GetResult
91
92 _, result.Err = perigee.Request("GET", resourceURL(client, id), perigee.Options{
93 Results: &result.Body,
94 MoreHeaders: client.AuthenticatedHeaders(),
95 OkCodes: []int{200},
96 })
97
98 return result
99}
Jamie Hannafordd276e612014-11-19 13:56:28 +0100100
Jamie Hannaford7f34d8e2014-11-20 12:24:55 +0100101// Delete will permanently delete a security group from the project.
Jamie Hannafordd276e612014-11-19 13:56:28 +0100102func Delete(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
103 var result gophercloud.ErrResult
104
105 _, result.Err = perigee.Request("DELETE", resourceURL(client, id), perigee.Options{
106 MoreHeaders: client.AuthenticatedHeaders(),
107 OkCodes: []int{202},
108 })
109
110 return result
111}
Jamie Hannaford8badf1e2014-11-19 14:39:26 +0100112
Jamie Hannaford7f34d8e2014-11-20 12:24:55 +0100113// AddRuleOpts represents the configuration for adding a new rule to an
114// existing security group.
Jamie Hannaford8badf1e2014-11-19 14:39:26 +0100115type AddRuleOpts struct {
116 // Required - the ID of the group that this rule will be added to.
117 ParentGroupID string `json:"parent_group_id"`
118
119 // Required - the lower bound of the port range that will be opened.
120 FromPort int `json:"from_port"`
121
122 // Required - the upper bound of the port range that will be opened.
123 ToPort int `json:"to_port"`
124
125 // Required - the protocol type that will be allowed, e.g. TCP.
126 IPProtocol string `json:"ip_protocol"`
127
128 // ONLY required if FromGroupID is blank. This represents the IP range that
129 // will be the source of network traffic to your security group. Use
130 // 0.0.0.0/0 to allow all IP addresses.
131 CIDR string `json:"cidr,omitempty"`
132
133 // ONLY required if CIDR is blank. This value represents the ID of a group
134 // that forwards traffic to the parent group. So, instead of accepting
135 // network traffic from an entire IP range, you can instead refine the
136 // inbound source by an existing security group.
137 FromGroupID string `json:"group_id,omitempty"`
138}
139
Jamie Hannaford7f34d8e2014-11-20 12:24:55 +0100140// AddRule will add a new rule to an existing security group (whose ID is
141// specified in AddRuleOpts). You have the option of controlling inbound
142// traffic from both an IP range (CIDR) or from another security group.
Jamie Hannaford8badf1e2014-11-19 14:39:26 +0100143func AddRule(client *gophercloud.ServiceClient, opts AddRuleOpts) AddRuleResult {
144 var result AddRuleResult
145
146 if opts.ParentGroupID == "" {
147 result.Err = errors.New("A ParentGroupID must be set")
148 return result
149 }
150 if opts.FromPort == 0 {
151 result.Err = errors.New("A FromPort must be set")
152 return result
153 }
154 if opts.ToPort == 0 {
155 result.Err = errors.New("A ToPort must be set")
156 return result
157 }
158 if opts.IPProtocol == "" {
159 result.Err = errors.New("A IPProtocol must be set")
160 return result
161 }
162 if opts.CIDR == "" && opts.FromGroupID == "" {
163 result.Err = errors.New("A CIDR or FromGroupID must be set")
164 return result
165 }
166
167 reqBody := struct {
168 AddRuleOpts `json:"security_group_rule"`
169 }{opts}
170
171 _, result.Err = perigee.Request("POST", rootRuleURL(client), perigee.Options{
172 Results: &result.Body,
173 ReqBody: &reqBody,
174 MoreHeaders: client.AuthenticatedHeaders(),
175 OkCodes: []int{200},
176 })
177
178 return result
179}
Jamie Hannaford61f81ca2014-11-19 14:44:33 +0100180
Jamie Hannaford7f34d8e2014-11-20 12:24:55 +0100181// DeleteRule will permanently delete a rule from a security group.
Jamie Hannaford61f81ca2014-11-19 14:44:33 +0100182func DeleteRule(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
183 var result gophercloud.ErrResult
184
185 _, result.Err = perigee.Request("DELETE", resourceRuleURL(client, id), perigee.Options{
186 MoreHeaders: client.AuthenticatedHeaders(),
187 OkCodes: []int{202},
188 })
189
190 return result
191}
Jamie Hannaford740e4a32014-11-19 16:13:30 +0100192
193func actionMap(prefix, groupName string) map[string]map[string]string {
194 return map[string]map[string]string{
195 prefix + "SecurityGroup": map[string]string{"name": groupName},
196 }
197}
198
Jamie Hannaford7f34d8e2014-11-20 12:24:55 +0100199// AddServerToGroup will associate a server and a security group, enforcing the
200// rules of the group on the server.
Jamie Hannaford740e4a32014-11-19 16:13:30 +0100201func AddServerToGroup(client *gophercloud.ServiceClient, serverID, groupName string) gophercloud.ErrResult {
202 var result gophercloud.ErrResult
203
204 _, result.Err = perigee.Request("POST", serverActionURL(client, serverID), perigee.Options{
205 Results: &result.Body,
206 ReqBody: actionMap("add", groupName),
207 MoreHeaders: client.AuthenticatedHeaders(),
Jamie Hannafordd8ac5bb2014-11-20 12:01:37 +0100208 OkCodes: []int{202},
Jamie Hannaford740e4a32014-11-19 16:13:30 +0100209 })
210
211 return result
212}
213
Jamie Hannaford7f34d8e2014-11-20 12:24:55 +0100214// RemoveServerFromGroup will disassociate a server from a security group.
Jamie Hannaford740e4a32014-11-19 16:13:30 +0100215func RemoveServerFromGroup(client *gophercloud.ServiceClient, serverID, groupName string) gophercloud.ErrResult {
216 var result gophercloud.ErrResult
217
218 _, result.Err = perigee.Request("POST", serverActionURL(client, serverID), perigee.Options{
219 Results: &result.Body,
220 ReqBody: actionMap("remove", groupName),
221 MoreHeaders: client.AuthenticatedHeaders(),
Jamie Hannafordd8ac5bb2014-11-20 12:01:37 +0100222 OkCodes: []int{202},
Jamie Hannaford740e4a32014-11-19 16:13:30 +0100223 })
224
225 return result
226}