Skip to content

Commit

Permalink
add firewall update method
Browse files Browse the repository at this point in the history
  • Loading branch information
0xch4z committed May 21, 2020
1 parent 1b0e355 commit 1d02995
Show file tree
Hide file tree
Showing 4 changed files with 293 additions and 10 deletions.
50 changes: 45 additions & 5 deletions firewalls.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,25 +44,40 @@ type FirewallCreateOptions struct {
Devices DevicesCreationOptions `json:"devices,omitempty"`
}

// FirewallUpdateOptions is an options struct used when Updating a Firewall
type FirewallUpdateOptions struct {
Label string `json:"label,omitempty"`
Status FirewallStatus `json:"status,omitempty"`
Tags *[]string `json:"tags,omitempty"`
}

// GetUpdateOptions converts a Firewall to FirewallUpdateOptions for use in Client.UpdateFirewall.
func (f *Firewall) GetUpdateOptions() FirewallUpdateOptions {
return FirewallUpdateOptions{
Label: f.Label,
Status: f.Status,
Tags: &f.Tags,
}
}

// UnmarshalJSON for Firewall responses
func (i *Firewall) UnmarshalJSON(b []byte) error {
func (f *Firewall) UnmarshalJSON(b []byte) error {
type Mask Firewall

p := struct {
*Mask
Created *parseabletime.ParseableTime `json:"created"`
Updated *parseabletime.ParseableTime `json:"updated"`
}{
Mask: (*Mask)(i),
Mask: (*Mask)(f),
}

if err := json.Unmarshal(b, &p); err != nil {
return err
}

i.Created = (*time.Time)(p.Created)
i.Updated = (*time.Time)(p.Updated)

f.Created = (*time.Time)(p.Created)
f.Updated = (*time.Time)(p.Updated)
return nil
}

Expand Down Expand Up @@ -141,6 +156,31 @@ func (c *Client) GetFirewall(ctx context.Context, id int) (*Firewall, error) {
return r.Result().(*Firewall), nil
}

// UpdateFirewall updates a Firewall with the given ID
func (c *Client) UpdateFirewall(ctx context.Context, id int, updateOpts FirewallUpdateOptions) (*Firewall, error) {
e, err := c.Firewalls.Endpoint()
if err != nil {
return nil, err
}

req := c.R(ctx).SetResult(&Firewall{})

var body string
if bodyData, err := json.Marshal(updateOpts); err != nil {
return nil, NewError(err)
} else {
body = string(bodyData)
}

e = fmt.Sprintf("%s/%d", e, id)
r, err := coupleAPIErrors(req.SetBody(body).Put(e))
if err != nil {
return nil, err
}

return r.Result().(*Firewall), nil
}

// DeleteFirewall deletes a single Firewall with the provided ID
func (c *Client) DeleteFirewall(ctx context.Context, id int) error {
e, err := c.Firewalls.Endpoint()
Expand Down
5 changes: 0 additions & 5 deletions test/integration/firewall_rules_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"testing"

"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/linode/linodego"
)

Expand All @@ -25,10 +24,6 @@ var (
}
)

// ignoreNetworkAddresses negates comparing IP addresses. Because of fixture sanitization,
// these addresses will be changed to bogus values when running tests.
var ignoreNetworkAddresses = cmpopts.IgnoreFields(linodego.FirewallRule{}, "Addresses")

func TestGetFirewallRules(t *testing.T) {
client, firewall, teardown, err := setupFirewall(t, []firewallModifier{func(createOpts *linodego.FirewallCreateOptions) {
createOpts.Rules = testFirewallRuleSet
Expand Down
44 changes: 44 additions & 0 deletions test/integration/firewalls_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"reflect"
"testing"

"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/linode/linodego"
)

Expand All @@ -16,6 +18,14 @@ var (
}
)

// ignoreNetworkAddresses negates comparing IP addresses. Because of fixture sanitization,
// these addresses will be changed to bogus values when running tests.
var ignoreNetworkAddresses = cmpopts.IgnoreFields(linodego.FirewallRule{}, "Addresses")

// ignoreFirewallTimestamps negates comparing created and updated timestamps. Because of
// fixture sanitization, these addresses will be changed to bogus values when running tests.
var ignoreFirewallTimestamps = cmpopts.IgnoreFields(linodego.Firewall{}, "Created", "Updated")

// TestListFirewalls should return a paginated list of Firewalls
func TestListFirewalls(t *testing.T) {
client, _, teardown, err := setupFirewall(t, []firewallModifier{
Expand Down Expand Up @@ -72,6 +82,40 @@ func TestGetFirewall(t *testing.T) {
}
}

func TestUpdateFirewall(t *testing.T) {
label := randString(12, lowerBytes, upperBytes) + "-linodego-testing"
rules := linodego.FirewallRuleSet{
Inbound: []linodego.FirewallRule{
{
Protocol: linodego.ICMP,
Addresses: linodego.NetworkAddresses{
IPv4: []string{"0.0.0.0/0"},
},
},
},
}

client, firewall, teardown, err := setupFirewall(t, []firewallModifier{
func(createOpts *linodego.FirewallCreateOptions) {
createOpts.Label = label
createOpts.Rules = rules
},
}, "fixtures/TestUpdateFirewall")
if err != nil {
t.Error(err)
}
defer teardown()

firewall.Status = linodego.FirewallDisabled
firewall.Label = "updatedFirewallLabel"
firewall.Tags = []string{"newTag"}
if updated, err := client.UpdateFirewall(context.Background(), firewall.ID, firewall.GetUpdateOptions()); err != nil {
t.Error(err)
} else if !cmp.Equal(firewall, updated, ignoreFirewallTimestamps, ignoreNetworkAddresses) {
t.Errorf("expected firewall to have updates but got diff: %s", cmp.Diff(firewall, updated, ignoreFirewallTimestamps, ignoreNetworkAddresses))
}
}

type firewallModifier func(*linodego.FirewallCreateOptions)

func createFirewall(t *testing.T, client *linodego.Client, firewallModifiers ...firewallModifier) (*linodego.Firewall, func(), error) {
Expand Down
204 changes: 204 additions & 0 deletions test/integration/fixtures/TestUpdateFirewall.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
---
version: 1
interactions:
- request:
body: '{"label":"aSTefFgoEhTM-linodego-testing","rules":{"inbound":[{"protocol":"ICMP","addresses":{"ipv4":["10.20.30.40/0"],"ipv6":null}}]},"tags":["testing"],"devices":{}}'
form: {}
headers:
Accept:
- application/json
Content-Type:
- application/json
User-Agent:
- linodego 0.12.0 https://github.com/linode/linodego
url: https://api.linode.com/v4beta/networking/firewalls
method: POST
response:
body: '{"id": 246, "label": "aSTefFgoEhTM-linodego-testing", "created": "2018-01-02T03:04:05",
"updated": "2018-01-02T03:04:05", "status": "enabled", "rules": {"inbound":
[{"protocol": "ICMP", "addresses": {"ipv4": ["10.20.30.40/0"], "ipv6": null}}]},
"tags": ["testing"]}'
headers:
Access-Control-Allow-Credentials:
- "true"
Access-Control-Allow-Headers:
- Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
Access-Control-Allow-Methods:
- HEAD, GET, OPTIONS, POST, PUT, DELETE
Access-Control-Allow-Origin:
- '*'
Access-Control-Expose-Headers:
- X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
Cache-Control:
- private, max-age=60, s-maxage=60
Content-Length:
- "261"
Content-Security-Policy:
- default-src 'none'
Content-Type:
- application/json
Date:
- Thu, 21 May 2020 18:12:11 GMT
Retry-After:
- "118"
Server:
- nginx
Strict-Transport-Security:
- max-age=31536000
Vary:
- Authorization, X-Filter
X-Accepted-Oauth-Scopes:
- firewall:read_write
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- DENY
- DENY
X-Oauth-Scopes:
- '*'
X-Ratelimit-Limit:
- "1600"
X-Ratelimit-Remaining:
- "1595"
X-Ratelimit-Reset:
- "1590084849"
X-Spec-Version:
- 4.65.1
X-Xss-Protection:
- 1; mode=block
status: 200 OK
code: 200
duration: ""
- request:
body: '{"label":"updatedFirewallLabel","status":"disabled","tags":["newTag"]}'
form: {}
headers:
Accept:
- application/json
Content-Type:
- application/json
User-Agent:
- linodego 0.12.0 https://github.com/linode/linodego
url: https://api.linode.com/v4beta/networking/firewalls/246
method: PUT
response:
body: '{"id": 246, "label": "updatedFirewallLabel", "created": "2018-01-02T03:04:05",
"updated": "2018-01-02T03:04:05", "status": "disabled", "rules": {"inbound":
[{"protocol": "ICMP", "addresses": {"ipv4": ["10.20.30.40/0"], "ipv6": null}}]},
"tags": ["newTag"]}'
headers:
Access-Control-Allow-Credentials:
- "true"
Access-Control-Allow-Headers:
- Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
Access-Control-Allow-Methods:
- HEAD, GET, OPTIONS, POST, PUT, DELETE
Access-Control-Allow-Origin:
- '*'
Access-Control-Expose-Headers:
- X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
Cache-Control:
- private, max-age=60, s-maxage=60
Content-Length:
- "252"
Content-Security-Policy:
- default-src 'none'
Content-Type:
- application/json
Date:
- Thu, 21 May 2020 18:12:11 GMT
Retry-After:
- "118"
Server:
- nginx
Strict-Transport-Security:
- max-age=31536000
Vary:
- Authorization, X-Filter
X-Accepted-Oauth-Scopes:
- firewall:read_write
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- DENY
- DENY
X-Oauth-Scopes:
- '*'
X-Ratelimit-Limit:
- "1600"
X-Ratelimit-Remaining:
- "1594"
X-Ratelimit-Reset:
- "1590084850"
X-Spec-Version:
- 4.65.1
X-Xss-Protection:
- 1; mode=block
status: 200 OK
code: 200
duration: ""
- request:
body: ""
form: {}
headers:
Accept:
- application/json
Content-Type:
- application/json
User-Agent:
- linodego 0.12.0 https://github.com/linode/linodego
url: https://api.linode.com/v4beta/networking/firewalls/246
method: DELETE
response:
body: '{}'
headers:
Access-Control-Allow-Credentials:
- "true"
Access-Control-Allow-Headers:
- Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter
Access-Control-Allow-Methods:
- HEAD, GET, OPTIONS, POST, PUT, DELETE
Access-Control-Allow-Origin:
- '*'
Access-Control-Expose-Headers:
- X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
Cache-Control:
- private, max-age=60, s-maxage=60
Content-Length:
- "2"
Content-Security-Policy:
- default-src 'none'
Content-Type:
- application/json
Date:
- Thu, 21 May 2020 18:12:11 GMT
Retry-After:
- "118"
Server:
- nginx
Strict-Transport-Security:
- max-age=31536000
Vary:
- Authorization, X-Filter
X-Accepted-Oauth-Scopes:
- firewall:read_write
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- DENY
- DENY
X-Oauth-Scopes:
- '*'
X-Ratelimit-Limit:
- "1600"
X-Ratelimit-Remaining:
- "1593"
X-Ratelimit-Reset:
- "1590084850"
X-Spec-Version:
- 4.65.1
X-Xss-Protection:
- 1; mode=block
status: 200 OK
code: 200
duration: ""

0 comments on commit 1d02995

Please sign in to comment.