1package subnets
2
3import (
4	"github.com/gophercloud/gophercloud"
5	"github.com/gophercloud/gophercloud/pagination"
6)
7
8type commonResult struct {
9	gophercloud.Result
10}
11
12// Extract is a function that accepts a result and extracts a subnet resource.
13func (r commonResult) Extract() (*Subnet, error) {
14	var s struct {
15		Subnet *Subnet `json:"subnet"`
16	}
17	err := r.ExtractInto(&s)
18	return s.Subnet, err
19}
20
21// CreateResult represents the result of a create operation. Call its Extract
22// method to interpret it as a Subnet.
23type CreateResult struct {
24	commonResult
25}
26
27// GetResult represents the result of a get operation. Call its Extract
28// method to interpret it as a Subnet.
29type GetResult struct {
30	commonResult
31}
32
33// UpdateResult represents the result of an update operation. Call its Extract
34// method to interpret it as a Subnet.
35type UpdateResult struct {
36	commonResult
37}
38
39// DeleteResult represents the result of a delete operation. Call its
40// ExtractErr method to determine if the request succeeded or failed.
41type DeleteResult struct {
42	gophercloud.ErrResult
43}
44
45// AllocationPool represents a sub-range of cidr available for dynamic
46// allocation to ports, e.g. {Start: "10.0.0.2", End: "10.0.0.254"}
47type AllocationPool struct {
48	Start string `json:"start"`
49	End   string `json:"end"`
50}
51
52// HostRoute represents a route that should be used by devices with IPs from
53// a subnet (not including local subnet route).
54type HostRoute struct {
55	DestinationCIDR string `json:"destination"`
56	NextHop         string `json:"nexthop"`
57}
58
59// Subnet represents a subnet. See package documentation for a top-level
60// description of what this is.
61type Subnet struct {
62	// UUID representing the subnet.
63	ID string `json:"id"`
64
65	// UUID of the parent network.
66	NetworkID string `json:"network_id"`
67
68	// Human-readable name for the subnet. Might not be unique.
69	Name string `json:"name"`
70
71	// Description for the subnet.
72	Description string `json:"description"`
73
74	// IP version, either `4' or `6'.
75	IPVersion int `json:"ip_version"`
76
77	// CIDR representing IP range for this subnet, based on IP version.
78	CIDR string `json:"cidr"`
79
80	// Default gateway used by devices in this subnet.
81	GatewayIP string `json:"gateway_ip"`
82
83	// DNS name servers used by hosts in this subnet.
84	DNSNameservers []string `json:"dns_nameservers"`
85
86	// Sub-ranges of CIDR available for dynamic allocation to ports.
87	// See AllocationPool.
88	AllocationPools []AllocationPool `json:"allocation_pools"`
89
90	// Routes that should be used by devices with IPs from this subnet
91	// (not including local subnet route).
92	HostRoutes []HostRoute `json:"host_routes"`
93
94	// Specifies whether DHCP is enabled for this subnet or not.
95	EnableDHCP bool `json:"enable_dhcp"`
96
97	// TenantID is the project owner of the subnet.
98	TenantID string `json:"tenant_id"`
99
100	// ProjectID is the project owner of the subnet.
101	ProjectID string `json:"project_id"`
102
103	// The IPv6 address modes specifies mechanisms for assigning IPv6 IP addresses.
104	IPv6AddressMode string `json:"ipv6_address_mode"`
105
106	// The IPv6 router advertisement specifies whether the networking service
107	// should transmit ICMPv6 packets.
108	IPv6RAMode string `json:"ipv6_ra_mode"`
109
110	// SubnetPoolID is the id of the subnet pool associated with the subnet.
111	SubnetPoolID string `json:"subnetpool_id"`
112
113	// Tags optionally set via extensions/attributestags
114	Tags []string `json:"tags"`
115}
116
117// SubnetPage is the page returned by a pager when traversing over a collection
118// of subnets.
119type SubnetPage struct {
120	pagination.LinkedPageBase
121}
122
123// NextPageURL is invoked when a paginated collection of subnets has reached
124// the end of a page and the pager seeks to traverse over a new one. In order
125// to do this, it needs to construct the next page's URL.
126func (r SubnetPage) NextPageURL() (string, error) {
127	var s struct {
128		Links []gophercloud.Link `json:"subnets_links"`
129	}
130	err := r.ExtractInto(&s)
131	if err != nil {
132		return "", err
133	}
134	return gophercloud.ExtractNextURL(s.Links)
135}
136
137// IsEmpty checks whether a SubnetPage struct is empty.
138func (r SubnetPage) IsEmpty() (bool, error) {
139	is, err := ExtractSubnets(r)
140	return len(is) == 0, err
141}
142
143// ExtractSubnets accepts a Page struct, specifically a SubnetPage struct,
144// and extracts the elements into a slice of Subnet structs. In other words,
145// a generic collection is mapped into a relevant slice.
146func ExtractSubnets(r pagination.Page) ([]Subnet, error) {
147	var s struct {
148		Subnets []Subnet `json:"subnets"`
149	}
150	err := (r.(SubnetPage)).ExtractInto(&s)
151	return s.Subnets, err
152}
153