Skip to content

Commit

Permalink
Add description field to firewall rules (#177)
Browse files Browse the repository at this point in the history
Co-authored-by: Adrian Huber <[email protected]>
  • Loading branch information
Adi146 and Adrian Huber authored Aug 3, 2021
1 parent 4cf75f4 commit e3eca12
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 151 deletions.
1 change: 1 addition & 0 deletions hcloud/firewall.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type FirewallRule struct {
DestinationIPs []net.IPNet
Protocol FirewallRuleProtocol
Port *string
Description *string
}

// FirewallRuleDirection specifies the direction of a Firewall rule.
Expand Down
262 changes: 117 additions & 145 deletions hcloud/firewall_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,183 +317,155 @@ func TestFirewallClientUpdate(t *testing.T) {
}

func TestFirewallSetRules(t *testing.T) {
t.Run("direction in", func(t *testing.T) {
env := newTestEnv()
defer env.Teardown()
description := "allow icmp out"

env.Mux.HandleFunc("/firewalls/1/actions/set_rules", func(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
t.Error("expected POST")
}
var reqBody schema.FirewallActionSetRulesRequest
if err := json.NewDecoder(r.Body).Decode(&reqBody); err != nil {
t.Fatal(err)
}
expectedReqBody := schema.FirewallActionSetRulesRequest{
tests := []struct {
name string
expectedReqBody schema.FirewallActionSetRulesRequest
opts FirewallSetRulesOpts
}{
{
name: "direction in",
expectedReqBody: schema.FirewallActionSetRulesRequest{
Rules: []schema.FirewallRule{
{
Direction: "in",
SourceIPs: []string{"10.0.0.5/32", "10.0.0.6/32"},
Protocol: "icmp",
},
},
}
if !cmp.Equal(expectedReqBody, reqBody) {
t.Log(cmp.Diff(expectedReqBody, reqBody))
t.Error("unexpected request body")
}
json.NewEncoder(w).Encode(schema.FirewallActionSetRulesResponse{
Actions: []schema.Action{
},
opts: FirewallSetRulesOpts{
Rules: []FirewallRule{
{
ID: 1,
Direction: FirewallRuleDirectionIn,
SourceIPs: []net.IPNet{
{
IP: net.ParseIP("10.0.0.5"),
Mask: net.CIDRMask(32, 32),
},
{
IP: net.ParseIP("10.0.0.6"),
Mask: net.CIDRMask(32, 32),
},
},
Protocol: FirewallRuleProtocolICMP,
},
},
})
})

var (
ctx = context.Background()
firewall = &Firewall{ID: 1}
)

opts := FirewallSetRulesOpts{
Rules: []FirewallRule{
{
Direction: FirewallRuleDirectionIn,
SourceIPs: []net.IPNet{
{
IP: net.ParseIP("10.0.0.5"),
Mask: net.CIDRMask(32, 32),
},
{
IP: net.ParseIP("10.0.0.6"),
Mask: net.CIDRMask(32, 32),
},
},
{
name: "direction out",
expectedReqBody: schema.FirewallActionSetRulesRequest{
Rules: []schema.FirewallRule{
{
Direction: "out",
DestinationIPs: []string{"10.0.0.5/32", "10.0.0.6/32"},
Protocol: "icmp",
},
},
},
opts: FirewallSetRulesOpts{
Rules: []FirewallRule{
{
Direction: FirewallRuleDirectionOut,
DestinationIPs: []net.IPNet{
{
IP: net.ParseIP("10.0.0.5"),
Mask: net.CIDRMask(32, 32),
},
{
IP: net.ParseIP("10.0.0.6"),
Mask: net.CIDRMask(32, 32),
},
},
Protocol: FirewallRuleProtocolICMP,
},
Protocol: FirewallRuleProtocolICMP,
},
},
}

actions, _, err := env.Client.Firewall.SetRules(ctx, firewall, opts)
if err != nil {
t.Fatal(err)
}
if len(actions) != 1 || actions[0].ID != 1 {
t.Errorf("unexpected actions: %v", actions)
}
})
t.Run("direction out", func(t *testing.T) {
env := newTestEnv()
defer env.Teardown()

env.Mux.HandleFunc("/firewalls/1/actions/set_rules", func(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
t.Error("expected POST")
}
var reqBody schema.FirewallActionSetRulesRequest
if err := json.NewDecoder(r.Body).Decode(&reqBody); err != nil {
t.Fatal(err)
}
expectedReqBody := schema.FirewallActionSetRulesRequest{
},
{
name: "empty",
expectedReqBody: schema.FirewallActionSetRulesRequest{
Rules: []schema.FirewallRule{},
},
opts: FirewallSetRulesOpts{
Rules: []FirewallRule{},
},
},
{
name: "description",
expectedReqBody: schema.FirewallActionSetRulesRequest{
Rules: []schema.FirewallRule{
{
Direction: "out",
DestinationIPs: []string{"10.0.0.5/32", "10.0.0.6/32"},
Protocol: "icmp",
Description: &description,
},
},
}
if !cmp.Equal(expectedReqBody, reqBody) {
t.Log(cmp.Diff(expectedReqBody, reqBody))
t.Error("unexpected request body")
}
json.NewEncoder(w).Encode(schema.FirewallActionSetRulesResponse{
Actions: []schema.Action{
},
opts: FirewallSetRulesOpts{
Rules: []FirewallRule{
{
ID: 1,
Direction: FirewallRuleDirectionOut,
DestinationIPs: []net.IPNet{
{
IP: net.ParseIP("10.0.0.5"),
Mask: net.CIDRMask(32, 32),
},
{
IP: net.ParseIP("10.0.0.6"),
Mask: net.CIDRMask(32, 32),
},
},
Protocol: FirewallRuleProtocolICMP,
Description: &description,
},
},
})
})

var (
ctx = context.Background()
firewall = &Firewall{ID: 1}
)
},
},
}

opts := FirewallSetRulesOpts{
Rules: []FirewallRule{
{
Direction: FirewallRuleDirectionOut,
DestinationIPs: []net.IPNet{
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
env := newTestEnv()
defer env.Teardown()

env.Mux.HandleFunc("/firewalls/1/actions/set_rules", func(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
t.Error("expected POST")
}
var reqBody schema.FirewallActionSetRulesRequest
if err := json.NewDecoder(r.Body).Decode(&reqBody); err != nil {
t.Fatal(err)
}
if !cmp.Equal(tt.expectedReqBody, reqBody) {
t.Log(cmp.Diff(tt.expectedReqBody, reqBody))
t.Error("unexpected request body")
}
json.NewEncoder(w).Encode(schema.FirewallActionSetRulesResponse{
Actions: []schema.Action{
{
IP: net.ParseIP("10.0.0.5"),
Mask: net.CIDRMask(32, 32),
},
{
IP: net.ParseIP("10.0.0.6"),
Mask: net.CIDRMask(32, 32),
ID: 1,
},
},
Protocol: FirewallRuleProtocolICMP,
},
},
}

actions, _, err := env.Client.Firewall.SetRules(ctx, firewall, opts)
if err != nil {
t.Fatal(err)
}
if len(actions) != 1 || actions[0].ID != 1 {
t.Errorf("unexpected actions: %v", actions)
}
})
}
})
})

func TestFirewallSetRulesEmpty(t *testing.T) {
env := newTestEnv()
defer env.Teardown()
var (
ctx = context.Background()
firewall = &Firewall{ID: 1}
)

env.Mux.HandleFunc("/firewalls/1/actions/set_rules", func(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
t.Error("expected POST")
}
var reqBody schema.FirewallActionSetRulesRequest
if err := json.NewDecoder(r.Body).Decode(&reqBody); err != nil {
t.Fatal(err)
}
expectedReqBody := schema.FirewallActionSetRulesRequest{
Rules: []schema.FirewallRule{},
}
if !cmp.Equal(expectedReqBody, reqBody) {
t.Log(cmp.Diff(expectedReqBody, reqBody))
t.Error("unexpected request body")
}
json.NewEncoder(w).Encode(schema.FirewallActionSetRulesResponse{
Actions: []schema.Action{
{
ID: 1,
},
},
actions, _, err := env.Client.Firewall.SetRules(ctx, firewall, tt.opts)
if err != nil {
t.Fatal(err)
}
if len(actions) != 1 || actions[0].ID != 1 {
t.Errorf("unexpected actions: %v", actions)
}
})
})

var (
ctx = context.Background()
firewall = &Firewall{ID: 1}
)

opts := FirewallSetRulesOpts{
Rules: []FirewallRule{},
}

actions, _, err := env.Client.Firewall.SetRules(ctx, firewall, opts)
if err != nil {
t.Fatal(err)
}
if len(actions) != 1 || actions[0].ID != 1 {
t.Errorf("unexpected actions: %v", actions)
}
}

Expand Down
14 changes: 8 additions & 6 deletions hcloud/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -981,9 +981,10 @@ func firewallCreateOptsToSchema(opts FirewallCreateOpts) schema.FirewallCreateRe
}
for _, rule := range opts.Rules {
schemaRule := schema.FirewallRule{
Direction: string(rule.Direction),
Protocol: string(rule.Protocol),
Port: rule.Port,
Direction: string(rule.Direction),
Protocol: string(rule.Protocol),
Port: rule.Port,
Description: rule.Description,
}
switch rule.Direction {
case FirewallRuleDirectionOut:
Expand Down Expand Up @@ -1021,9 +1022,10 @@ func firewallSetRulesOptsToSchema(opts FirewallSetRulesOpts) schema.FirewallActi
req := schema.FirewallActionSetRulesRequest{Rules: []schema.FirewallRule{}}
for _, rule := range opts.Rules {
schemaRule := schema.FirewallRule{
Direction: string(rule.Direction),
Protocol: string(rule.Protocol),
Port: rule.Port,
Direction: string(rule.Direction),
Protocol: string(rule.Protocol),
Port: rule.Port,
Description: rule.Description,
}
switch rule.Direction {
case FirewallRuleDirectionOut:
Expand Down
1 change: 1 addition & 0 deletions hcloud/schema/firewall.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type FirewallRule struct {
DestinationIPs []string `json:"destination_ips,omitempty"`
Protocol string `json:"protocol"`
Port *string `json:"port,omitempty"`
Description *string `json:"description,omitempty"`
}

// FirewallListResponse defines the schema of the response when listing Firewalls.
Expand Down

0 comments on commit e3eca12

Please sign in to comment.