Skip to content

Commit b380153

Browse files
Georg Schreiberschreibergeorg
authored andcommitted
FWaaSv2 CRUD firewall-groups
FWaaSv2 Create firewall-groups FWaaSv2 Update & Delete firewall-groups acc tests for fwaasv2 firewall groups
1 parent 0e6f9ce commit b380153

8 files changed

Lines changed: 680 additions & 1 deletion

File tree

acceptance/openstack/networking/v2/extensions/fwaas/fwaas.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import (
1414
th "github.com/gophercloud/gophercloud/testhelper"
1515
)
1616

17-
// CreateFirewall will create a Firewaill with a random name and a specified
17+
// CreateFirewall will create a Firewall with a random name and a specified
1818
// policy ID. An error will be returned if the firewall could not be created.
1919
func CreateFirewall(t *testing.T, client *gophercloud.ServiceClient, policyID string) (*firewalls.Firewall, error) {
2020
firewallName := tools.RandomString("TESTACC-", 8)

acceptance/openstack/networking/v2/extensions/fwaas_v2/fwaas_v2.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77

88
"github.com/gophercloud/gophercloud"
99
"github.com/gophercloud/gophercloud/acceptance/tools"
10+
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas_v2/groups"
1011
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas_v2/rules"
1112
th "github.com/gophercloud/gophercloud/testhelper"
1213
)
@@ -65,3 +66,47 @@ func DeleteRule(t *testing.T, client *gophercloud.ServiceClient, ruleID string)
6566

6667
t.Logf("Deleted rule: %s", ruleID)
6768
}
69+
70+
// CreateGroup will create a Firewall Group. An error will be returned if the
71+
// firewall group could not be created.
72+
func CreateGroup(t *testing.T, client *gophercloud.ServiceClient) (*groups.Group, error) {
73+
74+
groupName := tools.RandomString("TESTACC-", 8)
75+
description := tools.RandomString("TESTACC-", 8)
76+
adminStateUp := true
77+
shared := false
78+
79+
createOpts := groups.CreateOpts{
80+
Name: groupName,
81+
Description: description,
82+
AdminStateUp: &adminStateUp,
83+
Shared: &shared,
84+
}
85+
86+
t.Logf("Attempting to create firewall group %s",
87+
groupName)
88+
89+
group, err := groups.Create(client, createOpts).Extract()
90+
if err != nil {
91+
return group, err
92+
}
93+
94+
t.Logf("firewall group %s successfully created", groupName)
95+
96+
th.AssertEquals(t, group.Name, groupName)
97+
return group, nil
98+
}
99+
100+
// DeleteGroup will delete a group with a specified ID. A fatal error will occur
101+
// if the delete was not successful. This works best when used as a deferred
102+
// function.
103+
func DeleteGroup(t *testing.T, client *gophercloud.ServiceClient, groupId string) {
104+
t.Logf("Attempting to delete firewall group %s", groupId)
105+
106+
err := groups.Delete(client, groupId).ExtractErr()
107+
if err != nil {
108+
t.Fatalf("Unable to delete firewall group %s: %v", groupId, err)
109+
}
110+
111+
t.Logf("Deleted firewall group %s", groupId)
112+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// +build acceptance networking fwaas_v2
2+
3+
package fwaas_v2
4+
5+
import (
6+
"testing"
7+
8+
"github.com/gophercloud/gophercloud/acceptance/clients"
9+
"github.com/gophercloud/gophercloud/acceptance/tools"
10+
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas_v2/groups"
11+
th "github.com/gophercloud/gophercloud/testhelper"
12+
)
13+
14+
func TestGroupCRUD(t *testing.T) {
15+
16+
client, err := clients.NewNetworkV2Client()
17+
th.AssertNoErr(t, err)
18+
19+
createdGroup, err := CreateGroup(t, client)
20+
th.AssertNoErr(t, err)
21+
defer DeleteGroup(t, client, createdGroup.ID)
22+
23+
tools.PrintResource(t, createdGroup)
24+
25+
groupName := tools.RandomString("TESTACC-", 8)
26+
adminStateUp := false
27+
description := ("Some firewall group description")
28+
updateOpts := groups.UpdateOpts{
29+
Name: &groupName,
30+
Description: &description,
31+
AdminStateUp: &adminStateUp,
32+
}
33+
34+
groupUpdated, err := groups.Update(client, createdGroup.ID, updateOpts).Extract()
35+
if err != nil {
36+
t.Fatalf("Unable to update firewall group %s: %v", createdGroup.ID, err)
37+
}
38+
39+
th.AssertNoErr(t, err)
40+
th.AssertEquals(t, groupUpdated.Name, groupName)
41+
th.AssertEquals(t, groupUpdated.Description, description)
42+
th.AssertEquals(t, groupUpdated.AdminStateUp, adminStateUp)
43+
44+
t.Logf("Updated firewall group %s", groupUpdated.ID)
45+
46+
allPages, err := groups.List(client, nil).AllPages()
47+
th.AssertNoErr(t, err)
48+
49+
allGroups, err := groups.ExtractGroups(allPages)
50+
th.AssertNoErr(t, err)
51+
52+
t.Logf("Attempting to find firewall group %s\n", createdGroup.ID)
53+
var found bool
54+
for _, group := range allGroups {
55+
if group.ID == createdGroup.ID {
56+
found = true
57+
t.Logf("Found firewall group %s\n", group.ID)
58+
}
59+
}
60+
61+
th.AssertEquals(t, found, true)
62+
}
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
package groups
2+
3+
import (
4+
"github.com/gophercloud/gophercloud"
5+
"github.com/gophercloud/gophercloud/pagination"
6+
)
7+
8+
// ListOptsBuilder allows extensions to add additional parameters to the
9+
// List request.
10+
type ListOptsBuilder interface {
11+
ToGroupListQuery() (string, error)
12+
}
13+
14+
// ListOpts allows the filtering and sorting of paginated collections through
15+
// the API. Filtering is achieved by passing in struct field values that map to
16+
// the firewall group attributes you want to see returned. SortKey allows you
17+
// to sort by a particular firewall group attribute. SortDir sets the direction,
18+
// and is either `asc' or `desc'. Marker and Limit are used for pagination.
19+
type ListOpts struct {
20+
TenantID string `q:"tenant_id"`
21+
Name string `q:"name"`
22+
Description string `q:"description"`
23+
IngressFirewallPolicyID string `q:"ingress_firewall_policy_id"`
24+
EgressFirewallPolicyID string `q:"egress_firewall_policy_id"`
25+
AdminStateUp *bool `q:"admin_state_up"`
26+
Ports *[]string `q:"ports"`
27+
Status string `q:"status"`
28+
ID string `q:"id"`
29+
Shared *bool `q:"shared"`
30+
ProjectID string `q:"project_id"`
31+
Limit int `q:"limit"`
32+
Marker string `q:"marker"`
33+
SortKey string `q:"sort_key"`
34+
SortDir string `q:"sort_dir"`
35+
}
36+
37+
// ToGroupListQuery formats a ListOpts into a query string.
38+
func (opts ListOpts) ToGroupListQuery() (string, error) {
39+
q, err := gophercloud.BuildQueryString(opts)
40+
if err != nil {
41+
return "", err
42+
}
43+
return q.String(), err
44+
}
45+
46+
// List returns a Pager which allows you to iterate over a collection of
47+
// firewall groups. It accepts a ListOpts struct, which allows you to filter
48+
// and sort the returned collection for greater efficiency.
49+
//
50+
// Default group settings return only those firewall groups that are owned by the
51+
// tenant who submits the request, unless an admin user submits the request.
52+
func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
53+
url := rootURL(c)
54+
55+
if opts != nil {
56+
query, err := opts.ToGroupListQuery()
57+
if err != nil {
58+
return pagination.Pager{Err: err}
59+
}
60+
url += query
61+
}
62+
63+
return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
64+
return GroupPage{pagination.LinkedPageBase{PageResult: r}}
65+
})
66+
}
67+
68+
// Get retrieves a particular firewall group based on its unique ID.
69+
func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
70+
_, r.Err = c.Get(resourceURL(c, id), &r.Body, nil)
71+
return
72+
}
73+
74+
// CreateOptsBuilder is the interface options structs have to satisfy in order
75+
// to be used in the main Create operation in this package. Since many
76+
// extensions decorate or modify the common logic, it is useful for them to
77+
// satisfy a basic interface in order for them to be used.
78+
type CreateOptsBuilder interface {
79+
ToFirewallGroupCreateMap() (map[string]interface{}, error)
80+
}
81+
82+
// CreateOpts contains all the values needed to create a new firewall group.
83+
type CreateOpts struct {
84+
ID string `json:"id,omitempty"`
85+
TenantID string `json:"tenant_id,omitempty"`
86+
Name string `json:"name,omitempty"`
87+
Description string `json:"description,omitempty"`
88+
IngressFirewallPolicyID string `json:"ingress_firewall_policy_id,omitempty"`
89+
EgressFirewallPolicyID string `json:"egress_firewall_policy_id,omitempty"`
90+
AdminStateUp *bool `json:"admin_state_up,omitempty"`
91+
Ports []string `json:"ports,omitempty"`
92+
Shared *bool `json:"shared,omitempty"`
93+
ProjectID string `json:"project_id,omitempty"`
94+
}
95+
96+
// ToFirewallGroupCreateMap casts a CreateOpts struct to a map.
97+
func (opts CreateOpts) ToFirewallGroupCreateMap() (map[string]interface{}, error) {
98+
return gophercloud.BuildRequestBody(opts, "firewall_group")
99+
}
100+
101+
// Create accepts a CreateOpts struct and uses the values to create a new firewall group
102+
func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
103+
b, err := opts.ToFirewallGroupCreateMap()
104+
if err != nil {
105+
r.Err = err
106+
return
107+
}
108+
_, r.Err = c.Post(rootURL(c), b, &r.Body, nil)
109+
return
110+
}
111+
112+
// UpdateOptsBuilder is the interface options structs have to satisfy in order
113+
// to be used in the main Update operation in this package. Since many
114+
// extensions decorate or modify the common logic, it is useful for them to
115+
// satisfy a basic interface in order for them to be used.
116+
type UpdateOptsBuilder interface {
117+
ToFirewallGroupUpdateMap() (map[string]interface{}, error)
118+
}
119+
120+
// UpdateOpts contains the values used when updating a firewall group.
121+
type UpdateOpts struct {
122+
Name *string `json:"name,omitempty"`
123+
Description *string `json:"description,omitempty"`
124+
IngressFirewallPolicyID *string `json:"ingress_firewall_policy_id,omitempty"`
125+
EgressFirewallPolicyID *string `json:"egress_firewall_policy_id,omitempty"`
126+
AdminStateUp *bool `json:"admin_state_up,omitempty"`
127+
Ports []string `json:"ports,omitempty"`
128+
Shared *bool `json:"shared,omitempty"`
129+
}
130+
131+
// ToFirewallGroupUpdateMap casts a CreateOpts struct to a map.
132+
func (opts UpdateOpts) ToFirewallGroupUpdateMap() (map[string]interface{}, error) {
133+
return gophercloud.BuildRequestBody(opts, "firewall_group")
134+
}
135+
136+
// Update allows firewall groups to be updated.
137+
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
138+
b, err := opts.ToFirewallGroupUpdateMap()
139+
if err != nil {
140+
r.Err = err
141+
return
142+
}
143+
_, r.Err = c.Put(resourceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
144+
OkCodes: []int{200},
145+
})
146+
return
147+
}
148+
149+
// Delete will permanently delete a particular firewall group based on its unique ID.
150+
func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) {
151+
_, r.Err = c.Delete(resourceURL(c, id), nil)
152+
return
153+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package groups
2+
3+
import (
4+
"github.com/gophercloud/gophercloud"
5+
"github.com/gophercloud/gophercloud/pagination"
6+
)
7+
8+
// Group is a firewall group.
9+
type Group struct {
10+
ID string `json:"id"`
11+
TenantID string `json:"tenant_id"`
12+
Name string `json:"name"`
13+
Description string `json:"description"`
14+
IngressFirewallPolicyID string `json:"ingress_firewall_policy_id"`
15+
EgressFirewallPolicyID string `json:"egress_firewall_policy_id"`
16+
AdminStateUp bool `json:"admin_state_up"`
17+
Ports []string `json:"ports"`
18+
Status string `json:"status"`
19+
Shared bool `json:"shared"`
20+
ProjectID string `json:"project_id"`
21+
}
22+
23+
type commonResult struct {
24+
gophercloud.Result
25+
}
26+
27+
// Extract is a function that accepts a result and extracts a firewall group.
28+
func (r commonResult) Extract() (*Group, error) {
29+
var s struct {
30+
Group *Group `json:"firewall_group"`
31+
}
32+
err := r.ExtractInto(&s)
33+
return s.Group, err
34+
}
35+
36+
// GroupPage is the page returned by a pager when traversing over a
37+
// collection of firewall groups.
38+
type GroupPage struct {
39+
pagination.LinkedPageBase
40+
}
41+
42+
// NextPageURL is invoked when a paginated collection of firewall groups has
43+
// reached the end of a page and the pager seeks to traverse over a new one.
44+
// In order to do this, it needs to construct the next page's URL.
45+
func (r GroupPage) NextPageURL() (string, error) {
46+
var s struct {
47+
Links []gophercloud.Link `json:"firewall_groups_links"`
48+
}
49+
err := r.ExtractInto(&s)
50+
if err != nil {
51+
return "", err
52+
}
53+
return gophercloud.ExtractNextURL(s.Links)
54+
}
55+
56+
// IsEmpty checks whether a GroupPage struct is empty.
57+
func (r GroupPage) IsEmpty() (bool, error) {
58+
is, err := ExtractGroups(r)
59+
return len(is) == 0, err
60+
}
61+
62+
// ExtractGroups accepts a Page struct, specifically a GroupPage struct,
63+
// and extracts the elements into a slice of Group structs. In other words,
64+
// a generic collection is mapped into a relevant slice.
65+
func ExtractGroups(r pagination.Page) ([]Group, error) {
66+
var s struct {
67+
Groups []Group `json:"firewall_groups"`
68+
}
69+
err := (r.(GroupPage)).ExtractInto(&s)
70+
return s.Groups, err
71+
}
72+
73+
// GetResult represents the result of a get operation.
74+
type GetResult struct {
75+
commonResult
76+
}
77+
78+
// CreateResult represents the result of a create operation.
79+
type CreateResult struct {
80+
commonResult
81+
}
82+
83+
// UpdateResult represents the result of an update operation.
84+
type UpdateResult struct {
85+
commonResult
86+
}
87+
88+
// DeleteResult represents the result of a delete operation.
89+
type DeleteResult struct {
90+
gophercloud.ErrResult
91+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// networking_extensions_fwaas_groups_v2
2+
package testing

0 commit comments

Comments
 (0)