blob: e913e61b92c27a0c884a614dbda4048bd81e31ea [file] [log] [blame]
Jamie Hannaford89f9af22014-09-17 12:21:48 +02001package subnets
Jamie Hannaford0708c002014-09-17 16:08:49 +02002
3import (
Jamie Hannaford0708c002014-09-17 16:08:49 +02004 "github.com/rackspace/gophercloud"
Jamie Hannaford0708c002014-09-17 16:08:49 +02005 "github.com/rackspace/gophercloud/pagination"
Jon Perritt04851d32014-10-14 02:07:13 -05006
7 "github.com/racker/perigee"
Jamie Hannaford0708c002014-09-17 16:08:49 +02008)
9
Jamie Hannaforda2976ab2014-10-09 10:32:58 +020010// AdminState gives users a solid type to work with for create and update
11// operations. It is recommended that users use the `Up` and `Down` enums.
12type AdminState *bool
13
14// Convenience vars for AdminStateUp values.
15var (
16 iTrue = true
17 iFalse = false
18
19 Up AdminState = &iTrue
20 Down AdminState = &iFalse
21)
22
Jon Perritt04851d32014-10-14 02:07:13 -050023// ListOptsBuilder allows extensions to add additional parameters to the
24// List request.
25type ListOptsBuilder interface {
Jon Perritt26780d52014-10-14 11:35:58 -050026 ToSubnetListQuery() (string, error)
Jon Perritt04851d32014-10-14 02:07:13 -050027}
28
Jamie Hannaford686c4962014-09-23 10:46:20 +020029// ListOpts allows the filtering and sorting of paginated collections through
30// the API. Filtering is achieved by passing in struct field values that map to
31// the subnet attributes you want to see returned. SortKey allows you to sort
32// by a particular subnet attribute. SortDir sets the direction, and is either
33// `asc' or `desc'. Marker and Limit are used for pagination.
Jamie Hannaford0708c002014-09-17 16:08:49 +020034type ListOpts struct {
Jamie Hannaford5c6e9962014-10-02 10:34:14 +020035 Name string `q:"name"`
36 EnableDHCP *bool `q:"enable_dhcp"`
37 NetworkID string `q:"network_id"`
38 TenantID string `q:"tenant_id"`
39 IPVersion int `q:"ip_version"`
40 GatewayIP string `q:"gateway_ip"`
41 CIDR string `q:"cidr"`
42 ID string `q:"id"`
43 Limit int `q:"limit"`
44 Marker string `q:"marker"`
45 SortKey string `q:"sort_key"`
46 SortDir string `q:"sort_dir"`
Jamie Hannaford0708c002014-09-17 16:08:49 +020047}
48
Jon Perritt26780d52014-10-14 11:35:58 -050049// ToSubnetListQuery formats a ListOpts into a query string.
50func (opts ListOpts) ToSubnetListQuery() (string, error) {
Jon Perritt04851d32014-10-14 02:07:13 -050051 q, err := gophercloud.BuildQueryString(opts)
52 if err != nil {
53 return "", err
54 }
55 return q.String(), nil
56}
57
Jamie Hannaford686c4962014-09-23 10:46:20 +020058// List returns a Pager which allows you to iterate over a collection of
59// subnets. It accepts a ListOpts struct, which allows you to filter and sort
60// the returned collection for greater efficiency.
61//
62// Default policy settings return only those subnets that are owned by the tenant
63// who submits the request, unless the request is submitted by an user with
64// administrative rights.
Jon Perritt04851d32014-10-14 02:07:13 -050065func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
66 url := listURL(c)
67 if opts != nil {
Jon Perritt26780d52014-10-14 11:35:58 -050068 query, err := opts.ToSubnetListQuery()
Jon Perritt04851d32014-10-14 02:07:13 -050069 if err != nil {
70 return pagination.Pager{Err: err}
71 }
72 url += query
Jamie Hannaford92523e32014-10-02 11:08:36 +020073 }
Jamie Hannaford0708c002014-09-17 16:08:49 +020074
Jamie Hannaford92523e32014-10-02 11:08:36 +020075 return pagination.NewPager(c, url, func(r pagination.LastHTTPResponse) pagination.Page {
Ash Wilsonfc55c822014-09-25 13:18:16 -040076 return SubnetPage{pagination.LinkedPageBase{LastHTTPResponse: r}}
Jamie Hannaford0708c002014-09-17 16:08:49 +020077 })
78}
79
Jamie Hannaford686c4962014-09-23 10:46:20 +020080// Get retrieves a specific subnet based on its unique ID.
Jamie Hannafordd9036422014-09-23 17:50:24 +020081func Get(c *gophercloud.ServiceClient, id string) GetResult {
82 var res GetResult
Jamie Hannaford6f57e9e2014-10-02 10:27:28 +020083 _, res.Err = perigee.Request("GET", getURL(c, id), perigee.Options{
Jamie Hannaford0708c002014-09-17 16:08:49 +020084 MoreHeaders: c.Provider.AuthenticatedHeaders(),
Ash Wilsond3dc2542014-10-20 10:10:48 -040085 Results: &res.Body,
Jamie Hannafordd9036422014-09-23 17:50:24 +020086 OkCodes: []int{200},
Jamie Hannaford0708c002014-09-17 16:08:49 +020087 })
Jamie Hannafordd9036422014-09-23 17:50:24 +020088 return res
Jamie Hannaford0708c002014-09-17 16:08:49 +020089}
Jamie Hannaford63631432014-09-18 11:40:09 +020090
Jamie Hannaford686c4962014-09-23 10:46:20 +020091// Valid IP types
Jamie Hannaford63631432014-09-18 11:40:09 +020092const (
93 IPv4 = 4
94 IPv6 = 6
95)
96
Jon Perritt04851d32014-10-14 02:07:13 -050097// CreateOptsBuilder is the interface options structs have to satisfy in order
98// to be used in the main Create operation in this package. Since many
99// extensions decorate or modify the common logic, it is useful for them to
100// satisfy a basic interface in order for them to be used.
101type CreateOptsBuilder interface {
102 ToSubnetCreateMap() (map[string]interface{}, error)
103}
104
Jamie Hannaford686c4962014-09-23 10:46:20 +0200105// CreateOpts represents the attributes used when creating a new subnet.
Jamie Hannaford965ae702014-09-22 14:58:19 +0200106type CreateOpts struct {
Jamie Hannaford63631432014-09-18 11:40:09 +0200107 // Required
108 NetworkID string
109 CIDR string
110 // Optional
111 Name string
112 TenantID string
113 AllocationPools []AllocationPool
114 GatewayIP string
115 IPVersion int
Jamie Hannaford63631432014-09-18 11:40:09 +0200116 EnableDHCP *bool
Jamie Hannaford965ae702014-09-22 14:58:19 +0200117 DNSNameservers []string
Jamie Hannaford5d93f562014-10-09 10:53:32 +0200118 HostRoutes []HostRoute
Jamie Hannaford63631432014-09-18 11:40:09 +0200119}
120
Jon Perritt04851d32014-10-14 02:07:13 -0500121// ToSubnetCreateMap casts a CreateOpts struct to a map.
122func (opts CreateOpts) ToSubnetCreateMap() (map[string]interface{}, error) {
123 s := make(map[string]interface{})
Jamie Hannafordd9036422014-09-23 17:50:24 +0200124
Jamie Hannaford63631432014-09-18 11:40:09 +0200125 if opts.NetworkID == "" {
Jon Perritt04851d32014-10-14 02:07:13 -0500126 return nil, errNetworkIDRequired
Jamie Hannaford63631432014-09-18 11:40:09 +0200127 }
128 if opts.CIDR == "" {
Jon Perritt04851d32014-10-14 02:07:13 -0500129 return nil, errCIDRRequired
Jamie Hannaford63631432014-09-18 11:40:09 +0200130 }
131 if opts.IPVersion != 0 && opts.IPVersion != IPv4 && opts.IPVersion != IPv6 {
Jon Perritt04851d32014-10-14 02:07:13 -0500132 return nil, errInvalidIPType
Jamie Hannaford63631432014-09-18 11:40:09 +0200133 }
134
Jon Perritt04851d32014-10-14 02:07:13 -0500135 s["network_id"] = opts.NetworkID
136 s["cidr"] = opts.CIDR
Jamie Hannaford63631432014-09-18 11:40:09 +0200137
Jon Perritt04851d32014-10-14 02:07:13 -0500138 if opts.EnableDHCP != nil {
139 s["enable_dhcp"] = &opts.EnableDHCP
140 }
141 if opts.Name != "" {
142 s["name"] = opts.Name
143 }
144 if opts.GatewayIP != "" {
145 s["gateway_ip"] = opts.GatewayIP
146 }
147 if opts.TenantID != "" {
148 s["tenant_id"] = opts.TenantID
149 }
Jamie Hannaford63631432014-09-18 11:40:09 +0200150 if opts.IPVersion != 0 {
Jon Perritt04851d32014-10-14 02:07:13 -0500151 s["ip_version"] = opts.IPVersion
Jamie Hannaford63631432014-09-18 11:40:09 +0200152 }
Jamie Hannaford63631432014-09-18 11:40:09 +0200153 if len(opts.AllocationPools) != 0 {
Jon Perritt04851d32014-10-14 02:07:13 -0500154 s["allocation_pools"] = opts.AllocationPools
Jamie Hannaford63631432014-09-18 11:40:09 +0200155 }
Jamie Hannaford965ae702014-09-22 14:58:19 +0200156 if len(opts.DNSNameservers) != 0 {
Jon Perritt04851d32014-10-14 02:07:13 -0500157 s["dns_nameservers"] = opts.DNSNameservers
Jamie Hannaford965ae702014-09-22 14:58:19 +0200158 }
159 if len(opts.HostRoutes) != 0 {
Jon Perritt04851d32014-10-14 02:07:13 -0500160 s["host_routes"] = opts.HostRoutes
161 }
162
163 return map[string]interface{}{"subnet": s}, nil
164}
165
166// Create accepts a CreateOpts struct and creates a new subnet using the values
167// provided. You must remember to provide a valid NetworkID, CIDR and IP version.
168func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
169 var res CreateResult
170
171 reqBody, err := opts.ToSubnetCreateMap()
172 if err != nil {
173 res.Err = err
174 return res
Jamie Hannaford965ae702014-09-22 14:58:19 +0200175 }
Jamie Hannaford63631432014-09-18 11:40:09 +0200176
Jamie Hannaford6f57e9e2014-10-02 10:27:28 +0200177 _, res.Err = perigee.Request("POST", createURL(c), perigee.Options{
Jamie Hannaford63631432014-09-18 11:40:09 +0200178 MoreHeaders: c.Provider.AuthenticatedHeaders(),
179 ReqBody: &reqBody,
Ash Wilsond3dc2542014-10-20 10:10:48 -0400180 Results: &res.Body,
Jamie Hannaford63631432014-09-18 11:40:09 +0200181 OkCodes: []int{201},
182 })
Jamie Hannaford63631432014-09-18 11:40:09 +0200183
Jamie Hannafordd9036422014-09-23 17:50:24 +0200184 return res
Jamie Hannaford63631432014-09-18 11:40:09 +0200185}
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200186
Jon Perritt04851d32014-10-14 02:07:13 -0500187// UpdateOptsBuilder allows extensions to add additional parameters to the
188// Update request.
189type UpdateOptsBuilder interface {
190 ToSubnetUpdateMap() (map[string]interface{}, error)
191}
192
Jamie Hannaford686c4962014-09-23 10:46:20 +0200193// UpdateOpts represents the attributes used when updating an existing subnet.
Jamie Hannaford965ae702014-09-22 14:58:19 +0200194type UpdateOpts struct {
195 Name string
196 GatewayIP string
197 DNSNameservers []string
Jamie Hannaford5d93f562014-10-09 10:53:32 +0200198 HostRoutes []HostRoute
Jamie Hannaford965ae702014-09-22 14:58:19 +0200199 EnableDHCP *bool
200}
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200201
Jon Perritt04851d32014-10-14 02:07:13 -0500202// ToSubnetUpdateMap casts an UpdateOpts struct to a map.
203func (opts UpdateOpts) ToSubnetUpdateMap() (map[string]interface{}, error) {
204 s := make(map[string]interface{})
205
206 if opts.EnableDHCP != nil {
207 s["enable_dhcp"] = &opts.EnableDHCP
208 }
209 if opts.Name != "" {
210 s["name"] = opts.Name
211 }
212 if opts.GatewayIP != "" {
213 s["gateway_ip"] = opts.GatewayIP
214 }
215 if len(opts.DNSNameservers) != 0 {
216 s["dns_nameservers"] = opts.DNSNameservers
217 }
218 if len(opts.HostRoutes) != 0 {
219 s["host_routes"] = opts.HostRoutes
220 }
221
222 return map[string]interface{}{"subnet": s}, nil
223}
224
Jamie Hannaford686c4962014-09-23 10:46:20 +0200225// Update accepts a UpdateOpts struct and updates an existing subnet using the
226// values provided.
Jon Perritt04851d32014-10-14 02:07:13 -0500227func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
Jamie Hannafordd9036422014-09-23 17:50:24 +0200228 var res UpdateResult
Jon Perritt04851d32014-10-14 02:07:13 -0500229
230 reqBody, err := opts.ToSubnetUpdateMap()
231 if err != nil {
232 res.Err = err
233 return res
234 }
235
Jamie Hannaford6f57e9e2014-10-02 10:27:28 +0200236 _, res.Err = perigee.Request("PUT", updateURL(c, id), perigee.Options{
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200237 MoreHeaders: c.Provider.AuthenticatedHeaders(),
238 ReqBody: &reqBody,
Ash Wilsond3dc2542014-10-20 10:10:48 -0400239 Results: &res.Body,
Jamie Hannafordf84171d2014-09-18 14:00:01 +0200240 OkCodes: []int{200, 201},
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200241 })
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200242
Jamie Hannafordd9036422014-09-23 17:50:24 +0200243 return res
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200244}
245
Jamie Hannaford686c4962014-09-23 10:46:20 +0200246// Delete accepts a unique ID and deletes the subnet associated with it.
Jamie Hannafordd9036422014-09-23 17:50:24 +0200247func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
248 var res DeleteResult
Jamie Hannaford6f57e9e2014-10-02 10:27:28 +0200249 _, res.Err = perigee.Request("DELETE", deleteURL(c, id), perigee.Options{
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200250 MoreHeaders: c.Provider.AuthenticatedHeaders(),
251 OkCodes: []int{204},
252 })
Jamie Hannafordd9036422014-09-23 17:50:24 +0200253 return res
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200254}