blob: e73e10ac69c0421b43668c1532693fb72e337c7f [file] [log] [blame]
Jamie Hannaford548d3402014-09-18 15:50:08 +02001package ports
2
3import (
Jon Perritt7ab13282015-06-28 18:47:19 -06004 "fmt"
5
Jamie Hannaford548d3402014-09-18 15:50:08 +02006 "github.com/rackspace/gophercloud"
Jamie Hannaford548d3402014-09-18 15:50:08 +02007 "github.com/rackspace/gophercloud/pagination"
8)
9
Jamie Hannafordc98f59b2014-10-09 10:32:50 +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 ToPortListQuery() (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 port attributes you want to see returned. SortKey allows you to sort
32// by a particular port attribute. SortDir sets the direction, and is either
33// `asc' or `desc'. Marker and Limit are used for pagination.
Jamie Hannaford548d3402014-09-18 15:50:08 +020034type ListOpts struct {
Jamie Hannaford92523e32014-10-02 11:08:36 +020035 Status string `q:"status"`
36 Name string `q:"name"`
37 AdminStateUp *bool `q:"admin_state_up"`
38 NetworkID string `q:"network_id"`
39 TenantID string `q:"tenant_id"`
40 DeviceOwner string `q:"device_owner"`
41 MACAddress string `q:"mac_address"`
42 ID string `q:"id"`
43 DeviceID string `q:"device_id"`
44 Limit int `q:"limit"`
45 Marker string `q:"marker"`
46 SortKey string `q:"sort_key"`
47 SortDir string `q:"sort_dir"`
Jamie Hannaford548d3402014-09-18 15:50:08 +020048}
49
Jon Perritt26780d52014-10-14 11:35:58 -050050// ToPortListQuery formats a ListOpts into a query string.
51func (opts ListOpts) ToPortListQuery() (string, error) {
Jon Perritt04851d32014-10-14 02:07:13 -050052 q, err := gophercloud.BuildQueryString(opts)
53 if err != nil {
54 return "", err
55 }
56 return q.String(), nil
57}
58
Jamie Hannaford686c4962014-09-23 10:46:20 +020059// List returns a Pager which allows you to iterate over a collection of
60// ports. It accepts a ListOpts struct, which allows you to filter and sort
61// the returned collection for greater efficiency.
62//
63// Default policy settings return only those ports that are owned by the tenant
Alex Gaynora6d5f9f2014-10-27 10:52:32 -070064// who submits the request, unless the request is submitted by a user with
Jamie Hannaford686c4962014-09-23 10:46:20 +020065// administrative rights.
Jon Perritt04851d32014-10-14 02:07:13 -050066func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
67 url := listURL(c)
68 if opts != nil {
Jon Perritt26780d52014-10-14 11:35:58 -050069 query, err := opts.ToPortListQuery()
Jon Perritt04851d32014-10-14 02:07:13 -050070 if err != nil {
71 return pagination.Pager{Err: err}
72 }
73 url += query
Jamie Hannaford548d3402014-09-18 15:50:08 +020074 }
Jamie Hannaford548d3402014-09-18 15:50:08 +020075
Ash Wilsonb8b16f82014-10-20 10:19:49 -040076 return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
77 return PortPage{pagination.LinkedPageBase{PageResult: r}}
Jamie Hannaford548d3402014-09-18 15:50:08 +020078 })
79}
Jamie Hannaforda311f182014-09-19 11:19:10 +020080
Jamie Hannaford686c4962014-09-23 10:46:20 +020081// Get retrieves a specific port based on its unique ID.
Jamie Hannafordd9036422014-09-23 17:50:24 +020082func Get(c *gophercloud.ServiceClient, id string) GetResult {
83 var res GetResult
Jamie Hannaford059e1502015-03-24 16:20:32 +010084 _, res.Err = c.Get(getURL(c, id), &res.Body, nil)
Jamie Hannafordd9036422014-09-23 17:50:24 +020085 return res
Jamie Hannaforda311f182014-09-19 11:19:10 +020086}
Jamie Hannaforda5fb7822014-09-19 15:07:02 +020087
Jon Perritt04851d32014-10-14 02:07:13 -050088// CreateOptsBuilder is the interface options structs have to satisfy in order
89// to be used in the main Create operation in this package. Since many
90// extensions decorate or modify the common logic, it is useful for them to
91// satisfy a basic interface in order for them to be used.
92type CreateOptsBuilder interface {
93 ToPortCreateMap() (map[string]interface{}, error)
94}
95
Jamie Hannaford686c4962014-09-23 10:46:20 +020096// CreateOpts represents the attributes used when creating a new port.
Jamie Hannaford965ae702014-09-22 14:58:19 +020097type CreateOpts struct {
Travis Trumana371c0e2015-10-01 10:32:20 -040098 NetworkID string
99 Name string
100 AdminStateUp *bool
101 MACAddress string
102 FixedIPs interface{}
103 DeviceID string
104 DeviceOwner string
105 TenantID string
106 SecurityGroups []string
Travis Truman0c246652016-02-01 09:50:38 -0500107 AllowedAddressPairs []AddressPair
Jamie Hannaford965ae702014-09-22 14:58:19 +0200108}
109
Jon Perritt04851d32014-10-14 02:07:13 -0500110// ToPortCreateMap casts a CreateOpts struct to a map.
111func (opts CreateOpts) ToPortCreateMap() (map[string]interface{}, error) {
112 p := make(map[string]interface{})
113
114 if opts.NetworkID == "" {
115 return nil, errNetworkIDRequired
116 }
117 p["network_id"] = opts.NetworkID
118
119 if opts.DeviceID != "" {
120 p["device_id"] = opts.DeviceID
121 }
122 if opts.DeviceOwner != "" {
123 p["device_owner"] = opts.DeviceOwner
124 }
125 if opts.FixedIPs != nil {
126 p["fixed_ips"] = opts.FixedIPs
127 }
128 if opts.SecurityGroups != nil {
129 p["security_groups"] = opts.SecurityGroups
130 }
131 if opts.TenantID != "" {
132 p["tenant_id"] = opts.TenantID
133 }
134 if opts.AdminStateUp != nil {
135 p["admin_state_up"] = &opts.AdminStateUp
136 }
137 if opts.Name != "" {
138 p["name"] = opts.Name
139 }
140 if opts.MACAddress != "" {
141 p["mac_address"] = opts.MACAddress
142 }
Travis Trumana371c0e2015-10-01 10:32:20 -0400143 if opts.AllowedAddressPairs != nil {
144 p["allowed_address_pairs"] = opts.AllowedAddressPairs
145 }
Jon Perritt04851d32014-10-14 02:07:13 -0500146
147 return map[string]interface{}{"port": p}, nil
148}
149
Jamie Hannaford686c4962014-09-23 10:46:20 +0200150// Create accepts a CreateOpts struct and creates a new network using the values
151// provided. You must remember to provide a NetworkID value.
Jon Perritt04851d32014-10-14 02:07:13 -0500152func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
Jamie Hannafordd9036422014-09-23 17:50:24 +0200153 var res CreateResult
154
Jon Perritt04851d32014-10-14 02:07:13 -0500155 reqBody, err := opts.ToPortCreateMap()
156 if err != nil {
157 res.Err = err
Jamie Hannafordd9036422014-09-23 17:50:24 +0200158 return res
Jamie Hannaforda5fb7822014-09-19 15:07:02 +0200159 }
160
Jamie Hannaford059e1502015-03-24 16:20:32 +0100161 _, res.Err = c.Post(createURL(c), reqBody, &res.Body, nil)
Jamie Hannafordd9036422014-09-23 17:50:24 +0200162 return res
Jamie Hannaforda5fb7822014-09-19 15:07:02 +0200163}
164
Jon Perritt04851d32014-10-14 02:07:13 -0500165// UpdateOptsBuilder is the interface options structs have to satisfy in order
166// to be used in the main Update operation in this package. Since many
167// extensions decorate or modify the common logic, it is useful for them to
168// satisfy a basic interface in order for them to be used.
169type UpdateOptsBuilder interface {
170 ToPortUpdateMap() (map[string]interface{}, error)
171}
172
Jamie Hannaford686c4962014-09-23 10:46:20 +0200173// UpdateOpts represents the attributes used when updating an existing port.
Jamie Hannaford965ae702014-09-22 14:58:19 +0200174type UpdateOpts struct {
Travis Truman0447aca2015-09-15 16:09:24 -0400175 Name string
176 AdminStateUp *bool
177 FixedIPs interface{}
178 DeviceID string
179 DeviceOwner string
180 SecurityGroups []string
Travis Truman0c246652016-02-01 09:50:38 -0500181 AllowedAddressPairs []AddressPair
Jamie Hannaford965ae702014-09-22 14:58:19 +0200182}
183
Jon Perritt04851d32014-10-14 02:07:13 -0500184// ToPortUpdateMap casts an UpdateOpts struct to a map.
185func (opts UpdateOpts) ToPortUpdateMap() (map[string]interface{}, error) {
186 p := make(map[string]interface{})
187
188 if opts.DeviceID != "" {
189 p["device_id"] = opts.DeviceID
190 }
191 if opts.DeviceOwner != "" {
192 p["device_owner"] = opts.DeviceOwner
193 }
194 if opts.FixedIPs != nil {
195 p["fixed_ips"] = opts.FixedIPs
196 }
197 if opts.SecurityGroups != nil {
198 p["security_groups"] = opts.SecurityGroups
199 }
200 if opts.AdminStateUp != nil {
201 p["admin_state_up"] = &opts.AdminStateUp
202 }
203 if opts.Name != "" {
204 p["name"] = opts.Name
205 }
Travis Truman0447aca2015-09-15 16:09:24 -0400206 if opts.AllowedAddressPairs != nil {
207 p["allowed_address_pairs"] = opts.AllowedAddressPairs
208 }
Jon Perritt04851d32014-10-14 02:07:13 -0500209
210 return map[string]interface{}{"port": p}, nil
211}
212
Jamie Hannaford686c4962014-09-23 10:46:20 +0200213// Update accepts a UpdateOpts struct and updates an existing port using the
214// values provided.
Jon Perritt04851d32014-10-14 02:07:13 -0500215func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
Jamie Hannafordd9036422014-09-23 17:50:24 +0200216 var res UpdateResult
Jon Perritt04851d32014-10-14 02:07:13 -0500217
218 reqBody, err := opts.ToPortUpdateMap()
219 if err != nil {
220 res.Err = err
221 return res
222 }
223
Jamie Hannaford059e1502015-03-24 16:20:32 +0100224 _, res.Err = c.Put(updateURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{
225 OkCodes: []int{200, 201},
Jamie Hannaforda5fb7822014-09-19 15:07:02 +0200226 })
Jamie Hannafordd9036422014-09-23 17:50:24 +0200227 return res
Jamie Hannaforda5fb7822014-09-19 15:07:02 +0200228}
Jamie Hannafordd444b7a2014-09-19 15:08:27 +0200229
Jamie Hannaford686c4962014-09-23 10:46:20 +0200230// Delete accepts a unique ID and deletes the port associated with it.
Jamie Hannafordd9036422014-09-23 17:50:24 +0200231func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
232 var res DeleteResult
Jamie Hannaford059e1502015-03-24 16:20:32 +0100233 _, res.Err = c.Delete(deleteURL(c, id), nil)
Jamie Hannafordd9036422014-09-23 17:50:24 +0200234 return res
Jamie Hannafordd444b7a2014-09-19 15:08:27 +0200235}
Jon Perritt7ab13282015-06-28 18:47:19 -0600236
jrperritt14f716b2015-06-28 19:07:52 -0600237// IDFromName is a convenience function that returns a port's ID given its name.
Jon Perritt7ab13282015-06-28 18:47:19 -0600238func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
239 portCount := 0
240 portID := ""
241 if name == "" {
jrperritt00399b42015-06-28 19:00:45 -0600242 return "", fmt.Errorf("A port name must be provided.")
Jon Perritt7ab13282015-06-28 18:47:19 -0600243 }
244 pager := List(client, nil)
245 pager.EachPage(func(page pagination.Page) (bool, error) {
246 portList, err := ExtractPorts(page)
247 if err != nil {
248 return false, err
249 }
250
251 for _, p := range portList {
252 if p.Name == name {
253 portCount++
254 portID = p.ID
255 }
256 }
257 return true, nil
258 })
259
260 switch portCount {
261 case 0:
jrperritt00399b42015-06-28 19:00:45 -0600262 return "", fmt.Errorf("Unable to find port: %s", name)
Jon Perritt7ab13282015-06-28 18:47:19 -0600263 case 1:
264 return portID, nil
265 default:
jrperritt00399b42015-06-28 19:00:45 -0600266 return "", fmt.Errorf("Found %d ports matching %s", portCount, name)
Jon Perritt7ab13282015-06-28 18:47:19 -0600267 }
268}