blob: d719f938c49073412f84329c7231b118c881a0d0 [file] [log] [blame]
Jamie Hannaford548d3402014-09-18 15:50:08 +02001package ports
2
3import (
Jon Perritt27249f42016-02-18 10:35:59 -06004 "github.com/gophercloud/gophercloud"
5 "github.com/gophercloud/gophercloud/pagination"
Jamie Hannaford548d3402014-09-18 15:50:08 +02006)
7
Jamie Hannafordc98f59b2014-10-09 10:32:50 +02008// AdminState gives users a solid type to work with for create and update
9// operations. It is recommended that users use the `Up` and `Down` enums.
10type AdminState *bool
11
12// Convenience vars for AdminStateUp values.
13var (
14 iTrue = true
15 iFalse = false
16
17 Up AdminState = &iTrue
18 Down AdminState = &iFalse
19)
20
Jon Perritt04851d32014-10-14 02:07:13 -050021// ListOptsBuilder allows extensions to add additional parameters to the
22// List request.
23type ListOptsBuilder interface {
Jon Perritt26780d52014-10-14 11:35:58 -050024 ToPortListQuery() (string, error)
Jon Perritt04851d32014-10-14 02:07:13 -050025}
26
Jamie Hannaford686c4962014-09-23 10:46:20 +020027// ListOpts allows the filtering and sorting of paginated collections through
28// the API. Filtering is achieved by passing in struct field values that map to
29// the port attributes you want to see returned. SortKey allows you to sort
30// by a particular port attribute. SortDir sets the direction, and is either
31// `asc' or `desc'. Marker and Limit are used for pagination.
Jamie Hannaford548d3402014-09-18 15:50:08 +020032type ListOpts struct {
Jamie Hannaford92523e32014-10-02 11:08:36 +020033 Status string `q:"status"`
34 Name string `q:"name"`
35 AdminStateUp *bool `q:"admin_state_up"`
36 NetworkID string `q:"network_id"`
37 TenantID string `q:"tenant_id"`
38 DeviceOwner string `q:"device_owner"`
39 MACAddress string `q:"mac_address"`
40 ID string `q:"id"`
41 DeviceID string `q:"device_id"`
42 Limit int `q:"limit"`
43 Marker string `q:"marker"`
44 SortKey string `q:"sort_key"`
45 SortDir string `q:"sort_dir"`
Jamie Hannaford548d3402014-09-18 15:50:08 +020046}
47
Jon Perritt26780d52014-10-14 11:35:58 -050048// ToPortListQuery formats a ListOpts into a query string.
49func (opts ListOpts) ToPortListQuery() (string, error) {
Jon Perritt04851d32014-10-14 02:07:13 -050050 q, err := gophercloud.BuildQueryString(opts)
51 if err != nil {
52 return "", err
53 }
54 return q.String(), nil
55}
56
Jamie Hannaford686c4962014-09-23 10:46:20 +020057// List returns a Pager which allows you to iterate over a collection of
58// ports. It accepts a ListOpts struct, which allows you to filter and sort
59// the returned collection for greater efficiency.
60//
61// Default policy settings return only those ports that are owned by the tenant
Alex Gaynora6d5f9f2014-10-27 10:52:32 -070062// who submits the request, unless the request is submitted by a user with
Jamie Hannaford686c4962014-09-23 10:46:20 +020063// administrative rights.
Jon Perritt04851d32014-10-14 02:07:13 -050064func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
65 url := listURL(c)
66 if opts != nil {
Jon Perritt26780d52014-10-14 11:35:58 -050067 query, err := opts.ToPortListQuery()
Jon Perritt04851d32014-10-14 02:07:13 -050068 if err != nil {
69 return pagination.Pager{Err: err}
70 }
71 url += query
Jamie Hannaford548d3402014-09-18 15:50:08 +020072 }
Jamie Hannaford548d3402014-09-18 15:50:08 +020073
Ash Wilsonb8b16f82014-10-20 10:19:49 -040074 return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
75 return PortPage{pagination.LinkedPageBase{PageResult: r}}
Jamie Hannaford548d3402014-09-18 15:50:08 +020076 })
77}
Jamie Hannaforda311f182014-09-19 11:19:10 +020078
Jamie Hannaford686c4962014-09-23 10:46:20 +020079// Get retrieves a specific port based on its unique ID.
Jamie Hannafordd9036422014-09-23 17:50:24 +020080func Get(c *gophercloud.ServiceClient, id string) GetResult {
81 var res GetResult
Jamie Hannaford059e1502015-03-24 16:20:32 +010082 _, res.Err = c.Get(getURL(c, id), &res.Body, nil)
Jamie Hannafordd9036422014-09-23 17:50:24 +020083 return res
Jamie Hannaforda311f182014-09-19 11:19:10 +020084}
Jamie Hannaforda5fb7822014-09-19 15:07:02 +020085
Jon Perritt04851d32014-10-14 02:07:13 -050086// CreateOptsBuilder is the interface options structs have to satisfy in order
87// to be used in the main Create operation in this package. Since many
88// extensions decorate or modify the common logic, it is useful for them to
89// satisfy a basic interface in order for them to be used.
90type CreateOptsBuilder interface {
91 ToPortCreateMap() (map[string]interface{}, error)
92}
93
Jamie Hannaford686c4962014-09-23 10:46:20 +020094// CreateOpts represents the attributes used when creating a new port.
Jamie Hannaford965ae702014-09-22 14:58:19 +020095type CreateOpts struct {
Travis Trumana371c0e2015-10-01 10:32:20 -040096 NetworkID string
97 Name string
98 AdminStateUp *bool
99 MACAddress string
100 FixedIPs interface{}
101 DeviceID string
102 DeviceOwner string
103 TenantID string
104 SecurityGroups []string
Travis Truman0c246652016-02-01 09:50:38 -0500105 AllowedAddressPairs []AddressPair
Jamie Hannaford965ae702014-09-22 14:58:19 +0200106}
107
Jon Perritt04851d32014-10-14 02:07:13 -0500108// ToPortCreateMap casts a CreateOpts struct to a map.
109func (opts CreateOpts) ToPortCreateMap() (map[string]interface{}, error) {
110 p := make(map[string]interface{})
111
112 if opts.NetworkID == "" {
113 return nil, errNetworkIDRequired
114 }
115 p["network_id"] = opts.NetworkID
116
117 if opts.DeviceID != "" {
118 p["device_id"] = opts.DeviceID
119 }
120 if opts.DeviceOwner != "" {
121 p["device_owner"] = opts.DeviceOwner
122 }
123 if opts.FixedIPs != nil {
124 p["fixed_ips"] = opts.FixedIPs
125 }
126 if opts.SecurityGroups != nil {
127 p["security_groups"] = opts.SecurityGroups
128 }
129 if opts.TenantID != "" {
130 p["tenant_id"] = opts.TenantID
131 }
132 if opts.AdminStateUp != nil {
133 p["admin_state_up"] = &opts.AdminStateUp
134 }
135 if opts.Name != "" {
136 p["name"] = opts.Name
137 }
138 if opts.MACAddress != "" {
139 p["mac_address"] = opts.MACAddress
140 }
Travis Trumana371c0e2015-10-01 10:32:20 -0400141 if opts.AllowedAddressPairs != nil {
142 p["allowed_address_pairs"] = opts.AllowedAddressPairs
143 }
Jon Perritt04851d32014-10-14 02:07:13 -0500144
145 return map[string]interface{}{"port": p}, nil
146}
147
Jamie Hannaford686c4962014-09-23 10:46:20 +0200148// Create accepts a CreateOpts struct and creates a new network using the values
149// provided. You must remember to provide a NetworkID value.
Jon Perritt04851d32014-10-14 02:07:13 -0500150func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
Jamie Hannafordd9036422014-09-23 17:50:24 +0200151 var res CreateResult
152
Jon Perritt04851d32014-10-14 02:07:13 -0500153 reqBody, err := opts.ToPortCreateMap()
154 if err != nil {
155 res.Err = err
Jamie Hannafordd9036422014-09-23 17:50:24 +0200156 return res
Jamie Hannaforda5fb7822014-09-19 15:07:02 +0200157 }
158
Jamie Hannaford059e1502015-03-24 16:20:32 +0100159 _, res.Err = c.Post(createURL(c), reqBody, &res.Body, nil)
Jamie Hannafordd9036422014-09-23 17:50:24 +0200160 return res
Jamie Hannaforda5fb7822014-09-19 15:07:02 +0200161}
162
Jon Perritt04851d32014-10-14 02:07:13 -0500163// UpdateOptsBuilder is the interface options structs have to satisfy in order
164// to be used in the main Update operation in this package. Since many
165// extensions decorate or modify the common logic, it is useful for them to
166// satisfy a basic interface in order for them to be used.
167type UpdateOptsBuilder interface {
168 ToPortUpdateMap() (map[string]interface{}, error)
169}
170
Jamie Hannaford686c4962014-09-23 10:46:20 +0200171// UpdateOpts represents the attributes used when updating an existing port.
Jamie Hannaford965ae702014-09-22 14:58:19 +0200172type UpdateOpts struct {
Travis Truman0447aca2015-09-15 16:09:24 -0400173 Name string
174 AdminStateUp *bool
175 FixedIPs interface{}
176 DeviceID string
177 DeviceOwner string
178 SecurityGroups []string
Travis Truman0c246652016-02-01 09:50:38 -0500179 AllowedAddressPairs []AddressPair
Jamie Hannaford965ae702014-09-22 14:58:19 +0200180}
181
Jon Perritt04851d32014-10-14 02:07:13 -0500182// ToPortUpdateMap casts an UpdateOpts struct to a map.
183func (opts UpdateOpts) ToPortUpdateMap() (map[string]interface{}, error) {
184 p := make(map[string]interface{})
185
186 if opts.DeviceID != "" {
187 p["device_id"] = opts.DeviceID
188 }
189 if opts.DeviceOwner != "" {
190 p["device_owner"] = opts.DeviceOwner
191 }
192 if opts.FixedIPs != nil {
193 p["fixed_ips"] = opts.FixedIPs
194 }
195 if opts.SecurityGroups != nil {
196 p["security_groups"] = opts.SecurityGroups
197 }
198 if opts.AdminStateUp != nil {
199 p["admin_state_up"] = &opts.AdminStateUp
200 }
201 if opts.Name != "" {
202 p["name"] = opts.Name
203 }
Travis Truman0447aca2015-09-15 16:09:24 -0400204 if opts.AllowedAddressPairs != nil {
205 p["allowed_address_pairs"] = opts.AllowedAddressPairs
206 }
Jon Perritt04851d32014-10-14 02:07:13 -0500207
208 return map[string]interface{}{"port": p}, nil
209}
210
Jamie Hannaford686c4962014-09-23 10:46:20 +0200211// Update accepts a UpdateOpts struct and updates an existing port using the
212// values provided.
Jon Perritt04851d32014-10-14 02:07:13 -0500213func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
Jamie Hannafordd9036422014-09-23 17:50:24 +0200214 var res UpdateResult
Jon Perritt04851d32014-10-14 02:07:13 -0500215
216 reqBody, err := opts.ToPortUpdateMap()
217 if err != nil {
218 res.Err = err
219 return res
220 }
221
Jamie Hannaford059e1502015-03-24 16:20:32 +0100222 _, res.Err = c.Put(updateURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{
223 OkCodes: []int{200, 201},
Jamie Hannaforda5fb7822014-09-19 15:07:02 +0200224 })
Jamie Hannafordd9036422014-09-23 17:50:24 +0200225 return res
Jamie Hannaforda5fb7822014-09-19 15:07:02 +0200226}
Jamie Hannafordd444b7a2014-09-19 15:08:27 +0200227
Jamie Hannaford686c4962014-09-23 10:46:20 +0200228// Delete accepts a unique ID and deletes the port associated with it.
Jamie Hannafordd9036422014-09-23 17:50:24 +0200229func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
230 var res DeleteResult
Jamie Hannaford059e1502015-03-24 16:20:32 +0100231 _, res.Err = c.Delete(deleteURL(c, id), nil)
Jamie Hannafordd9036422014-09-23 17:50:24 +0200232 return res
Jamie Hannafordd444b7a2014-09-19 15:08:27 +0200233}
Jon Perritt7ab13282015-06-28 18:47:19 -0600234
jrperritt14f716b2015-06-28 19:07:52 -0600235// IDFromName is a convenience function that returns a port's ID given its name.
Jon Perritt7ab13282015-06-28 18:47:19 -0600236func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
Jon Perritte3cb7e42016-03-07 06:24:11 -0600237 count := 0
238 id := ""
Jon Perritt7ab13282015-06-28 18:47:19 -0600239 if name == "" {
Jon Perritte3cb7e42016-03-07 06:24:11 -0600240 err := &gophercloud.ErrMissingInput{}
241 err.Function = "ports.IDFromName"
242 err.Argument = "name"
243 return "", err
Jon Perritt7ab13282015-06-28 18:47:19 -0600244 }
Jon Perritt7ab13282015-06-28 18:47:19 -0600245
Jon Perritte3cb7e42016-03-07 06:24:11 -0600246 pages, err := List(client, nil).AllPages()
247 if err != nil {
248 return "", err
249 }
Jon Perritt7ab13282015-06-28 18:47:19 -0600250
Jon Perritte3cb7e42016-03-07 06:24:11 -0600251 all, err := ExtractPorts(pages)
252 if err != nil {
253 return "", err
254 }
255
256 for _, s := range all {
257 if s.Name == name {
258 count++
259 id = s.ID
260 }
261 }
262
263 switch count {
Jon Perritt7ab13282015-06-28 18:47:19 -0600264 case 0:
Jon Perritte3cb7e42016-03-07 06:24:11 -0600265 err := &gophercloud.ErrResourceNotFound{}
266 err.Name = name
267 err.ResourceType = "port"
268 err.Function = "ports.IDFromName"
269 return "", err
Jon Perritt7ab13282015-06-28 18:47:19 -0600270 case 1:
Jon Perritte3cb7e42016-03-07 06:24:11 -0600271 return id, nil
Jon Perritt7ab13282015-06-28 18:47:19 -0600272 default:
Jon Perritte3cb7e42016-03-07 06:24:11 -0600273 err := &gophercloud.ErrMultipleResourcesFound{}
274 err.Count = count
275 err.Name = name
276 err.ResourceType = "port"
277 err.Function = "ports.IDFromName"
278 return "", err
Jon Perritt7ab13282015-06-28 18:47:19 -0600279 }
280}