| Jamie Hannaford | 89f9af2 | 2014-09-17 12:21:48 +0200 | [diff] [blame] | 1 | package subnets | 
| Jamie Hannaford | 0708c00 | 2014-09-17 16:08:49 +0200 | [diff] [blame] | 2 |  | 
 | 3 | import ( | 
| Jamie Hannaford | 0708c00 | 2014-09-17 16:08:49 +0200 | [diff] [blame] | 4 | 	"github.com/rackspace/gophercloud" | 
| Jamie Hannaford | 0708c00 | 2014-09-17 16:08:49 +0200 | [diff] [blame] | 5 | 	"github.com/rackspace/gophercloud/pagination" | 
| Jon Perritt | 04851d3 | 2014-10-14 02:07:13 -0500 | [diff] [blame^] | 6 |  | 
 | 7 | 	"github.com/racker/perigee" | 
| Jamie Hannaford | 0708c00 | 2014-09-17 16:08:49 +0200 | [diff] [blame] | 8 | ) | 
 | 9 |  | 
| Jamie Hannaford | a2976ab | 2014-10-09 10:32:58 +0200 | [diff] [blame] | 10 | // 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. | 
 | 12 | type AdminState *bool | 
 | 13 |  | 
 | 14 | // Convenience vars for AdminStateUp values. | 
 | 15 | var ( | 
 | 16 | 	iTrue  = true | 
 | 17 | 	iFalse = false | 
 | 18 |  | 
 | 19 | 	Up   AdminState = &iTrue | 
 | 20 | 	Down AdminState = &iFalse | 
 | 21 | ) | 
 | 22 |  | 
| Jon Perritt | 04851d3 | 2014-10-14 02:07:13 -0500 | [diff] [blame^] | 23 | // ListOptsBuilder allows extensions to add additional parameters to the | 
 | 24 | // List request. | 
 | 25 | type ListOptsBuilder interface { | 
 | 26 | 	ToSubnetListString() (string, error) | 
 | 27 | } | 
 | 28 |  | 
| Jamie Hannaford | 686c496 | 2014-09-23 10:46:20 +0200 | [diff] [blame] | 29 | // 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 Hannaford | 0708c00 | 2014-09-17 16:08:49 +0200 | [diff] [blame] | 34 | type ListOpts struct { | 
| Jamie Hannaford | 5c6e996 | 2014-10-02 10:34:14 +0200 | [diff] [blame] | 35 | 	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 Hannaford | 0708c00 | 2014-09-17 16:08:49 +0200 | [diff] [blame] | 47 | } | 
 | 48 |  | 
| Jon Perritt | 04851d3 | 2014-10-14 02:07:13 -0500 | [diff] [blame^] | 49 | // ToSubnetListString formats a ListOpts into a query string. | 
 | 50 | func (opts ListOpts) ToSubnetListString() (string, error) { | 
 | 51 | 	q, err := gophercloud.BuildQueryString(opts) | 
 | 52 | 	if err != nil { | 
 | 53 | 		return "", err | 
 | 54 | 	} | 
 | 55 | 	return q.String(), nil | 
 | 56 | } | 
 | 57 |  | 
| Jamie Hannaford | 686c496 | 2014-09-23 10:46:20 +0200 | [diff] [blame] | 58 | // 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 Perritt | 04851d3 | 2014-10-14 02:07:13 -0500 | [diff] [blame^] | 65 | func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { | 
 | 66 | 	url := listURL(c) | 
 | 67 | 	if opts != nil { | 
 | 68 | 		query, err := opts.ToSubnetListString() | 
 | 69 | 		if err != nil { | 
 | 70 | 			return pagination.Pager{Err: err} | 
 | 71 | 		} | 
 | 72 | 		url += query | 
| Jamie Hannaford | 92523e3 | 2014-10-02 11:08:36 +0200 | [diff] [blame] | 73 | 	} | 
| Jamie Hannaford | 0708c00 | 2014-09-17 16:08:49 +0200 | [diff] [blame] | 74 |  | 
| Jamie Hannaford | 92523e3 | 2014-10-02 11:08:36 +0200 | [diff] [blame] | 75 | 	return pagination.NewPager(c, url, func(r pagination.LastHTTPResponse) pagination.Page { | 
| Ash Wilson | fc55c82 | 2014-09-25 13:18:16 -0400 | [diff] [blame] | 76 | 		return SubnetPage{pagination.LinkedPageBase{LastHTTPResponse: r}} | 
| Jamie Hannaford | 0708c00 | 2014-09-17 16:08:49 +0200 | [diff] [blame] | 77 | 	}) | 
 | 78 | } | 
 | 79 |  | 
| Jamie Hannaford | 686c496 | 2014-09-23 10:46:20 +0200 | [diff] [blame] | 80 | // Get retrieves a specific subnet based on its unique ID. | 
| Jamie Hannaford | d903642 | 2014-09-23 17:50:24 +0200 | [diff] [blame] | 81 | func Get(c *gophercloud.ServiceClient, id string) GetResult { | 
 | 82 | 	var res GetResult | 
| Jamie Hannaford | 6f57e9e | 2014-10-02 10:27:28 +0200 | [diff] [blame] | 83 | 	_, res.Err = perigee.Request("GET", getURL(c, id), perigee.Options{ | 
| Jamie Hannaford | 0708c00 | 2014-09-17 16:08:49 +0200 | [diff] [blame] | 84 | 		MoreHeaders: c.Provider.AuthenticatedHeaders(), | 
| Jamie Hannaford | d903642 | 2014-09-23 17:50:24 +0200 | [diff] [blame] | 85 | 		Results:     &res.Resp, | 
 | 86 | 		OkCodes:     []int{200}, | 
| Jamie Hannaford | 0708c00 | 2014-09-17 16:08:49 +0200 | [diff] [blame] | 87 | 	}) | 
| Jamie Hannaford | d903642 | 2014-09-23 17:50:24 +0200 | [diff] [blame] | 88 | 	return res | 
| Jamie Hannaford | 0708c00 | 2014-09-17 16:08:49 +0200 | [diff] [blame] | 89 | } | 
| Jamie Hannaford | 6363143 | 2014-09-18 11:40:09 +0200 | [diff] [blame] | 90 |  | 
| Jamie Hannaford | 686c496 | 2014-09-23 10:46:20 +0200 | [diff] [blame] | 91 | // Valid IP types | 
| Jamie Hannaford | 6363143 | 2014-09-18 11:40:09 +0200 | [diff] [blame] | 92 | const ( | 
 | 93 | 	IPv4 = 4 | 
 | 94 | 	IPv6 = 6 | 
 | 95 | ) | 
 | 96 |  | 
| Jon Perritt | 04851d3 | 2014-10-14 02:07:13 -0500 | [diff] [blame^] | 97 | // 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. | 
 | 101 | type CreateOptsBuilder interface { | 
 | 102 | 	ToSubnetCreateMap() (map[string]interface{}, error) | 
 | 103 | } | 
 | 104 |  | 
| Jamie Hannaford | 686c496 | 2014-09-23 10:46:20 +0200 | [diff] [blame] | 105 | // CreateOpts represents the attributes used when creating a new subnet. | 
| Jamie Hannaford | 965ae70 | 2014-09-22 14:58:19 +0200 | [diff] [blame] | 106 | type CreateOpts struct { | 
| Jamie Hannaford | 6363143 | 2014-09-18 11:40:09 +0200 | [diff] [blame] | 107 | 	// 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 Hannaford | 6363143 | 2014-09-18 11:40:09 +0200 | [diff] [blame] | 116 | 	EnableDHCP      *bool | 
| Jamie Hannaford | 965ae70 | 2014-09-22 14:58:19 +0200 | [diff] [blame] | 117 | 	DNSNameservers  []string | 
| Jamie Hannaford | 5d93f56 | 2014-10-09 10:53:32 +0200 | [diff] [blame] | 118 | 	HostRoutes      []HostRoute | 
| Jamie Hannaford | 6363143 | 2014-09-18 11:40:09 +0200 | [diff] [blame] | 119 | } | 
 | 120 |  | 
| Jon Perritt | 04851d3 | 2014-10-14 02:07:13 -0500 | [diff] [blame^] | 121 | // ToSubnetCreateMap casts a CreateOpts struct to a map. | 
 | 122 | func (opts CreateOpts) ToSubnetCreateMap() (map[string]interface{}, error) { | 
 | 123 | 	s := make(map[string]interface{}) | 
| Jamie Hannaford | d903642 | 2014-09-23 17:50:24 +0200 | [diff] [blame] | 124 |  | 
| Jamie Hannaford | 6363143 | 2014-09-18 11:40:09 +0200 | [diff] [blame] | 125 | 	if opts.NetworkID == "" { | 
| Jon Perritt | 04851d3 | 2014-10-14 02:07:13 -0500 | [diff] [blame^] | 126 | 		return nil, errNetworkIDRequired | 
| Jamie Hannaford | 6363143 | 2014-09-18 11:40:09 +0200 | [diff] [blame] | 127 | 	} | 
 | 128 | 	if opts.CIDR == "" { | 
| Jon Perritt | 04851d3 | 2014-10-14 02:07:13 -0500 | [diff] [blame^] | 129 | 		return nil, errCIDRRequired | 
| Jamie Hannaford | 6363143 | 2014-09-18 11:40:09 +0200 | [diff] [blame] | 130 | 	} | 
 | 131 | 	if opts.IPVersion != 0 && opts.IPVersion != IPv4 && opts.IPVersion != IPv6 { | 
| Jon Perritt | 04851d3 | 2014-10-14 02:07:13 -0500 | [diff] [blame^] | 132 | 		return nil, errInvalidIPType | 
| Jamie Hannaford | 6363143 | 2014-09-18 11:40:09 +0200 | [diff] [blame] | 133 | 	} | 
 | 134 |  | 
| Jon Perritt | 04851d3 | 2014-10-14 02:07:13 -0500 | [diff] [blame^] | 135 | 	s["network_id"] = opts.NetworkID | 
 | 136 | 	s["cidr"] = opts.CIDR | 
| Jamie Hannaford | 6363143 | 2014-09-18 11:40:09 +0200 | [diff] [blame] | 137 |  | 
| Jon Perritt | 04851d3 | 2014-10-14 02:07:13 -0500 | [diff] [blame^] | 138 | 	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 Hannaford | 6363143 | 2014-09-18 11:40:09 +0200 | [diff] [blame] | 150 | 	if opts.IPVersion != 0 { | 
| Jon Perritt | 04851d3 | 2014-10-14 02:07:13 -0500 | [diff] [blame^] | 151 | 		s["ip_version"] = opts.IPVersion | 
| Jamie Hannaford | 6363143 | 2014-09-18 11:40:09 +0200 | [diff] [blame] | 152 | 	} | 
| Jamie Hannaford | 6363143 | 2014-09-18 11:40:09 +0200 | [diff] [blame] | 153 | 	if len(opts.AllocationPools) != 0 { | 
| Jon Perritt | 04851d3 | 2014-10-14 02:07:13 -0500 | [diff] [blame^] | 154 | 		s["allocation_pools"] = opts.AllocationPools | 
| Jamie Hannaford | 6363143 | 2014-09-18 11:40:09 +0200 | [diff] [blame] | 155 | 	} | 
| Jamie Hannaford | 965ae70 | 2014-09-22 14:58:19 +0200 | [diff] [blame] | 156 | 	if len(opts.DNSNameservers) != 0 { | 
| Jon Perritt | 04851d3 | 2014-10-14 02:07:13 -0500 | [diff] [blame^] | 157 | 		s["dns_nameservers"] = opts.DNSNameservers | 
| Jamie Hannaford | 965ae70 | 2014-09-22 14:58:19 +0200 | [diff] [blame] | 158 | 	} | 
 | 159 | 	if len(opts.HostRoutes) != 0 { | 
| Jon Perritt | 04851d3 | 2014-10-14 02:07:13 -0500 | [diff] [blame^] | 160 | 		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. | 
 | 168 | func 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 Hannaford | 965ae70 | 2014-09-22 14:58:19 +0200 | [diff] [blame] | 175 | 	} | 
| Jamie Hannaford | 6363143 | 2014-09-18 11:40:09 +0200 | [diff] [blame] | 176 |  | 
| Jamie Hannaford | 6f57e9e | 2014-10-02 10:27:28 +0200 | [diff] [blame] | 177 | 	_, res.Err = perigee.Request("POST", createURL(c), perigee.Options{ | 
| Jamie Hannaford | 6363143 | 2014-09-18 11:40:09 +0200 | [diff] [blame] | 178 | 		MoreHeaders: c.Provider.AuthenticatedHeaders(), | 
 | 179 | 		ReqBody:     &reqBody, | 
| Jamie Hannaford | d903642 | 2014-09-23 17:50:24 +0200 | [diff] [blame] | 180 | 		Results:     &res.Resp, | 
| Jamie Hannaford | 6363143 | 2014-09-18 11:40:09 +0200 | [diff] [blame] | 181 | 		OkCodes:     []int{201}, | 
 | 182 | 	}) | 
| Jamie Hannaford | 6363143 | 2014-09-18 11:40:09 +0200 | [diff] [blame] | 183 |  | 
| Jamie Hannaford | d903642 | 2014-09-23 17:50:24 +0200 | [diff] [blame] | 184 | 	return res | 
| Jamie Hannaford | 6363143 | 2014-09-18 11:40:09 +0200 | [diff] [blame] | 185 | } | 
| Jamie Hannaford | d11e20c | 2014-09-18 12:03:01 +0200 | [diff] [blame] | 186 |  | 
| Jon Perritt | 04851d3 | 2014-10-14 02:07:13 -0500 | [diff] [blame^] | 187 | // UpdateOptsBuilder allows extensions to add additional parameters to the | 
 | 188 | // Update request. | 
 | 189 | type UpdateOptsBuilder interface { | 
 | 190 | 	ToSubnetUpdateMap() (map[string]interface{}, error) | 
 | 191 | } | 
 | 192 |  | 
| Jamie Hannaford | 686c496 | 2014-09-23 10:46:20 +0200 | [diff] [blame] | 193 | // UpdateOpts represents the attributes used when updating an existing subnet. | 
| Jamie Hannaford | 965ae70 | 2014-09-22 14:58:19 +0200 | [diff] [blame] | 194 | type UpdateOpts struct { | 
 | 195 | 	Name           string | 
 | 196 | 	GatewayIP      string | 
 | 197 | 	DNSNameservers []string | 
| Jamie Hannaford | 5d93f56 | 2014-10-09 10:53:32 +0200 | [diff] [blame] | 198 | 	HostRoutes     []HostRoute | 
| Jamie Hannaford | 965ae70 | 2014-09-22 14:58:19 +0200 | [diff] [blame] | 199 | 	EnableDHCP     *bool | 
 | 200 | } | 
| Jamie Hannaford | d11e20c | 2014-09-18 12:03:01 +0200 | [diff] [blame] | 201 |  | 
| Jon Perritt | 04851d3 | 2014-10-14 02:07:13 -0500 | [diff] [blame^] | 202 | // ToSubnetUpdateMap casts an UpdateOpts struct to a map. | 
 | 203 | func (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 Hannaford | 686c496 | 2014-09-23 10:46:20 +0200 | [diff] [blame] | 225 | // Update accepts a UpdateOpts struct and updates an existing subnet using the | 
 | 226 | // values provided. | 
| Jon Perritt | 04851d3 | 2014-10-14 02:07:13 -0500 | [diff] [blame^] | 227 | func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult { | 
| Jamie Hannaford | d903642 | 2014-09-23 17:50:24 +0200 | [diff] [blame] | 228 | 	var res UpdateResult | 
| Jon Perritt | 04851d3 | 2014-10-14 02:07:13 -0500 | [diff] [blame^] | 229 |  | 
 | 230 | 	reqBody, err := opts.ToSubnetUpdateMap() | 
 | 231 | 	if err != nil { | 
 | 232 | 		res.Err = err | 
 | 233 | 		return res | 
 | 234 | 	} | 
 | 235 |  | 
| Jamie Hannaford | 6f57e9e | 2014-10-02 10:27:28 +0200 | [diff] [blame] | 236 | 	_, res.Err = perigee.Request("PUT", updateURL(c, id), perigee.Options{ | 
| Jamie Hannaford | d11e20c | 2014-09-18 12:03:01 +0200 | [diff] [blame] | 237 | 		MoreHeaders: c.Provider.AuthenticatedHeaders(), | 
 | 238 | 		ReqBody:     &reqBody, | 
| Jamie Hannaford | d903642 | 2014-09-23 17:50:24 +0200 | [diff] [blame] | 239 | 		Results:     &res.Resp, | 
| Jamie Hannaford | f84171d | 2014-09-18 14:00:01 +0200 | [diff] [blame] | 240 | 		OkCodes:     []int{200, 201}, | 
| Jamie Hannaford | d11e20c | 2014-09-18 12:03:01 +0200 | [diff] [blame] | 241 | 	}) | 
| Jamie Hannaford | d11e20c | 2014-09-18 12:03:01 +0200 | [diff] [blame] | 242 |  | 
| Jamie Hannaford | d903642 | 2014-09-23 17:50:24 +0200 | [diff] [blame] | 243 | 	return res | 
| Jamie Hannaford | d11e20c | 2014-09-18 12:03:01 +0200 | [diff] [blame] | 244 | } | 
 | 245 |  | 
| Jamie Hannaford | 686c496 | 2014-09-23 10:46:20 +0200 | [diff] [blame] | 246 | // Delete accepts a unique ID and deletes the subnet associated with it. | 
| Jamie Hannaford | d903642 | 2014-09-23 17:50:24 +0200 | [diff] [blame] | 247 | func Delete(c *gophercloud.ServiceClient, id string) DeleteResult { | 
 | 248 | 	var res DeleteResult | 
| Jamie Hannaford | 6f57e9e | 2014-10-02 10:27:28 +0200 | [diff] [blame] | 249 | 	_, res.Err = perigee.Request("DELETE", deleteURL(c, id), perigee.Options{ | 
| Jamie Hannaford | d11e20c | 2014-09-18 12:03:01 +0200 | [diff] [blame] | 250 | 		MoreHeaders: c.Provider.AuthenticatedHeaders(), | 
 | 251 | 		OkCodes:     []int{204}, | 
 | 252 | 	}) | 
| Jamie Hannaford | d903642 | 2014-09-23 17:50:24 +0200 | [diff] [blame] | 253 | 	return res | 
| Jamie Hannaford | d11e20c | 2014-09-18 12:03:01 +0200 | [diff] [blame] | 254 | } |