From 770d4c0839598969dcc41ab4ea246b23d83213df Mon Sep 17 00:00:00 2001 From: pauhull Date: Thu, 16 Nov 2023 17:13:31 +0100 Subject: [PATCH] test(firewall): add missing firewall unit tests --- internal/cmd/firewall/add_rule_test.go | 56 +++++++++++ .../cmd/firewall/apply_to_resource_test.go | 93 +++++++++++++++++++ internal/cmd/firewall/delete_rule_test.go | 55 +++++++++++ .../cmd/firewall/remove_from_resource_test.go | 93 +++++++++++++++++++ internal/cmd/firewall/replace_rules_test.go | 79 ++++++++++++++++ internal/cmd/firewall/testdata/rules.json | 23 +++++ 6 files changed, 399 insertions(+) create mode 100644 internal/cmd/firewall/add_rule_test.go create mode 100644 internal/cmd/firewall/apply_to_resource_test.go create mode 100644 internal/cmd/firewall/delete_rule_test.go create mode 100644 internal/cmd/firewall/remove_from_resource_test.go create mode 100644 internal/cmd/firewall/replace_rules_test.go create mode 100644 internal/cmd/firewall/testdata/rules.json diff --git a/internal/cmd/firewall/add_rule_test.go b/internal/cmd/firewall/add_rule_test.go new file mode 100644 index 00000000..c7052daf --- /dev/null +++ b/internal/cmd/firewall/add_rule_test.go @@ -0,0 +1,56 @@ +package firewall + +import ( + "context" + "net" + "testing" + + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" + + "github.com/hetznercloud/cli/internal/testutil" + "github.com/hetznercloud/hcloud-go/v2/hcloud" +) + +func TestAddRule(t *testing.T) { + fx := testutil.NewFixture(t) + defer fx.Finish() + + cmd := AddRuleCmd.CobraCommand( + context.Background(), + fx.Client, + fx.TokenEnsurer, + fx.ActionWaiter) + fx.ExpectEnsureToken() + + firewall := &hcloud.Firewall{ + ID: 123, + Name: "test", + } + + fx.Client.FirewallClient.EXPECT(). + Get(gomock.Any(), "test"). + Return(firewall, nil, nil) + fx.Client.FirewallClient.EXPECT(). + SetRules(gomock.Any(), firewall, hcloud.FirewallSetRulesOpts{ + Rules: []hcloud.FirewallRule{{ + Direction: hcloud.FirewallRuleDirectionIn, + SourceIPs: []net.IPNet{{IP: net.IP{0, 0, 0, 0}, Mask: net.IPMask{0, 0, 0, 0}}}, + DestinationIPs: nil, + Protocol: hcloud.FirewallRuleProtocolTCP, + Port: hcloud.Ptr("80"), + Description: hcloud.Ptr("http"), + }}, + }). + Return([]*hcloud.Action{{ID: 123}, {ID: 321}}, nil, nil) + fx.ActionWaiter.EXPECT(). + WaitForActions(gomock.Any(), []*hcloud.Action{{ID: 123}, {ID: 321}}). + Return(nil) + + out, _, err := fx.Run(cmd, []string{"--direction", "in", "--protocol", "tcp", "--source-ips", "0.0.0.0/0", "--port", "80", "--description", "http", "test"}) + + expOut := "Firewall Rules for Firewall 123 updated\n" + + assert.NoError(t, err) + assert.Equal(t, expOut, out) +} diff --git a/internal/cmd/firewall/apply_to_resource_test.go b/internal/cmd/firewall/apply_to_resource_test.go new file mode 100644 index 00000000..7c805ba7 --- /dev/null +++ b/internal/cmd/firewall/apply_to_resource_test.go @@ -0,0 +1,93 @@ +package firewall + +import ( + "context" + "testing" + + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" + + "github.com/hetznercloud/cli/internal/testutil" + "github.com/hetznercloud/hcloud-go/v2/hcloud" +) + +func TestApplyToServer(t *testing.T) { + fx := testutil.NewFixture(t) + defer fx.Finish() + + cmd := ApplyToResourceCmd.CobraCommand( + context.Background(), + fx.Client, + fx.TokenEnsurer, + fx.ActionWaiter) + fx.ExpectEnsureToken() + + firewall := &hcloud.Firewall{ + ID: 123, + Name: "test", + } + + fx.Client.FirewallClient.EXPECT(). + Get(gomock.Any(), "test"). + Return(firewall, nil, nil) + fx.Client.ServerClient.EXPECT(). + Get(gomock.Any(), "my-server"). + Return(&hcloud.Server{ID: 456}, nil, nil) + fx.Client.FirewallClient.EXPECT(). + ApplyResources(gomock.Any(), firewall, []hcloud.FirewallResource{{ + Type: hcloud.FirewallResourceTypeServer, + Server: &hcloud.FirewallResourceServer{ + ID: 456, + }, + }}). + Return([]*hcloud.Action{{ID: 123}, {ID: 321}}, nil, nil) + fx.ActionWaiter.EXPECT(). + WaitForActions(gomock.Any(), []*hcloud.Action{{ID: 123}, {ID: 321}}). + Return(nil) + + out, _, err := fx.Run(cmd, []string{"--type", "server", "--server", "my-server", "test"}) + + expOut := "Firewall 123 applied\n" + + assert.NoError(t, err) + assert.Equal(t, expOut, out) +} + +func TestApplyToLabelSelector(t *testing.T) { + fx := testutil.NewFixture(t) + defer fx.Finish() + + cmd := ApplyToResourceCmd.CobraCommand( + context.Background(), + fx.Client, + fx.TokenEnsurer, + fx.ActionWaiter) + fx.ExpectEnsureToken() + + firewall := &hcloud.Firewall{ + ID: 123, + Name: "test", + } + + fx.Client.FirewallClient.EXPECT(). + Get(gomock.Any(), "test"). + Return(firewall, nil, nil) + fx.Client.FirewallClient.EXPECT(). + ApplyResources(gomock.Any(), firewall, []hcloud.FirewallResource{{ + Type: hcloud.FirewallResourceTypeLabelSelector, + LabelSelector: &hcloud.FirewallResourceLabelSelector{ + Selector: "my-label", + }, + }}). + Return([]*hcloud.Action{{ID: 123}, {ID: 321}}, nil, nil) + fx.ActionWaiter.EXPECT(). + WaitForActions(gomock.Any(), []*hcloud.Action{{ID: 123}, {ID: 321}}). + Return(nil) + + out, _, err := fx.Run(cmd, []string{"--type", "label_selector", "--label-selector", "my-label", "test"}) + + expOut := "Firewall 123 applied\n" + + assert.NoError(t, err) + assert.Equal(t, expOut, out) +} diff --git a/internal/cmd/firewall/delete_rule_test.go b/internal/cmd/firewall/delete_rule_test.go new file mode 100644 index 00000000..40d646e4 --- /dev/null +++ b/internal/cmd/firewall/delete_rule_test.go @@ -0,0 +1,55 @@ +package firewall + +import ( + "context" + "net" + "testing" + + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" + + "github.com/hetznercloud/cli/internal/testutil" + "github.com/hetznercloud/hcloud-go/v2/hcloud" +) + +func TestDeleteRule(t *testing.T) { + fx := testutil.NewFixture(t) + defer fx.Finish() + + cmd := DeleteRuleCmd.CobraCommand( + context.Background(), + fx.Client, + fx.TokenEnsurer, + fx.ActionWaiter) + fx.ExpectEnsureToken() + + firewall := &hcloud.Firewall{ + ID: 123, + Name: "test", + Rules: []hcloud.FirewallRule{{ + Direction: hcloud.FirewallRuleDirectionIn, + SourceIPs: []net.IPNet{{IP: net.IP{0, 0, 0, 0}, Mask: net.IPMask{0, 0, 0, 0}}}, + DestinationIPs: []net.IPNet{}, + Protocol: hcloud.FirewallRuleProtocolTCP, + Port: hcloud.Ptr("80"), + Description: hcloud.Ptr("http"), + }}, + } + + fx.Client.FirewallClient.EXPECT(). + Get(gomock.Any(), "test"). + Return(firewall, nil, nil) + fx.Client.FirewallClient.EXPECT(). + SetRules(gomock.Any(), firewall, hcloud.FirewallSetRulesOpts{Rules: nil}). + Return([]*hcloud.Action{{ID: 123}, {ID: 321}}, nil, nil) + fx.ActionWaiter.EXPECT(). + WaitForActions(gomock.Any(), []*hcloud.Action{{ID: 123}, {ID: 321}}). + Return(nil) + + out, _, err := fx.Run(cmd, []string{"--direction", "in", "--protocol", "tcp", "--source-ips", "0.0.0.0/0", "--port", "80", "--description", "http", "test"}) + + expOut := "Firewall Rules for Firewall 123 updated\n" + + assert.NoError(t, err) + assert.Equal(t, expOut, out) +} diff --git a/internal/cmd/firewall/remove_from_resource_test.go b/internal/cmd/firewall/remove_from_resource_test.go new file mode 100644 index 00000000..31522bb9 --- /dev/null +++ b/internal/cmd/firewall/remove_from_resource_test.go @@ -0,0 +1,93 @@ +package firewall + +import ( + "context" + "testing" + + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" + + "github.com/hetznercloud/cli/internal/testutil" + "github.com/hetznercloud/hcloud-go/v2/hcloud" +) + +func TestRemoveFromServer(t *testing.T) { + fx := testutil.NewFixture(t) + defer fx.Finish() + + cmd := RemoveFromResourceCmd.CobraCommand( + context.Background(), + fx.Client, + fx.TokenEnsurer, + fx.ActionWaiter) + fx.ExpectEnsureToken() + + firewall := &hcloud.Firewall{ + ID: 123, + Name: "test", + } + + fx.Client.FirewallClient.EXPECT(). + Get(gomock.Any(), "test"). + Return(firewall, nil, nil) + fx.Client.ServerClient.EXPECT(). + Get(gomock.Any(), "my-server"). + Return(&hcloud.Server{ID: 456}, nil, nil) + fx.Client.FirewallClient.EXPECT(). + RemoveResources(gomock.Any(), firewall, []hcloud.FirewallResource{{ + Type: hcloud.FirewallResourceTypeServer, + Server: &hcloud.FirewallResourceServer{ + ID: 456, + }, + }}). + Return([]*hcloud.Action{{ID: 123}, {ID: 321}}, nil, nil) + fx.ActionWaiter.EXPECT(). + WaitForActions(gomock.Any(), []*hcloud.Action{{ID: 123}, {ID: 321}}). + Return(nil) + + out, _, err := fx.Run(cmd, []string{"--type", "server", "--server", "my-server", "test"}) + + expOut := "Firewall 123 applied\n" + + assert.NoError(t, err) + assert.Equal(t, expOut, out) +} + +func TestRemoveFromLabelSelector(t *testing.T) { + fx := testutil.NewFixture(t) + defer fx.Finish() + + cmd := RemoveFromResourceCmd.CobraCommand( + context.Background(), + fx.Client, + fx.TokenEnsurer, + fx.ActionWaiter) + fx.ExpectEnsureToken() + + firewall := &hcloud.Firewall{ + ID: 123, + Name: "test", + } + + fx.Client.FirewallClient.EXPECT(). + Get(gomock.Any(), "test"). + Return(firewall, nil, nil) + fx.Client.FirewallClient.EXPECT(). + RemoveResources(gomock.Any(), firewall, []hcloud.FirewallResource{{ + Type: hcloud.FirewallResourceTypeLabelSelector, + LabelSelector: &hcloud.FirewallResourceLabelSelector{ + Selector: "my-label", + }, + }}). + Return([]*hcloud.Action{{ID: 123}, {ID: 321}}, nil, nil) + fx.ActionWaiter.EXPECT(). + WaitForActions(gomock.Any(), []*hcloud.Action{{ID: 123}, {ID: 321}}). + Return(nil) + + out, _, err := fx.Run(cmd, []string{"--type", "label_selector", "--label-selector", "my-label", "test"}) + + expOut := "Firewall 123 applied\n" + + assert.NoError(t, err) + assert.Equal(t, expOut, out) +} diff --git a/internal/cmd/firewall/replace_rules_test.go b/internal/cmd/firewall/replace_rules_test.go new file mode 100644 index 00000000..24105519 --- /dev/null +++ b/internal/cmd/firewall/replace_rules_test.go @@ -0,0 +1,79 @@ +package firewall + +import ( + "context" + "net" + "testing" + + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" + + "github.com/hetznercloud/cli/internal/testutil" + "github.com/hetznercloud/hcloud-go/v2/hcloud" +) + +func TestReplaceRules(t *testing.T) { + fx := testutil.NewFixture(t) + defer fx.Finish() + + cmd := ReplaceRulesCmd.CobraCommand( + context.Background(), + fx.Client, + fx.TokenEnsurer, + fx.ActionWaiter) + fx.ExpectEnsureToken() + + firewall := &hcloud.Firewall{ + ID: 123, + Name: "test", + } + + fx.Client.FirewallClient.EXPECT(). + Get(gomock.Any(), "test"). + Return(firewall, nil, nil) + fx.Client.FirewallClient.EXPECT(). + SetRules(gomock.Any(), firewall, hcloud.FirewallSetRulesOpts{ + Rules: []hcloud.FirewallRule{ + { + Direction: hcloud.FirewallRuleDirectionIn, + SourceIPs: []net.IPNet{ + {IP: net.IP{28, 239, 13, 1}, Mask: net.IPMask{255, 255, 255, 255}}, + {IP: net.IP{28, 239, 14, 0}, Mask: net.IPMask{255, 255, 255, 0}}, + { + IP: net.IP{0xff, 0x21, 0x1e, 0xac, 0x9a, 0x3b, 0xee, 0x58, 0x05, 0xca, 0x99, 0x0c, 0x8b, 0xc9, 0xc0, 0x3b}, + Mask: net.IPMask{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + }, + }, + DestinationIPs: nil, + Protocol: hcloud.FirewallRuleProtocolTCP, + Port: hcloud.Ptr("80"), + Description: hcloud.Ptr("Allow port 80"), + }, + { + Direction: hcloud.FirewallRuleDirectionIn, + SourceIPs: []net.IPNet{ + {IP: net.IP{0, 0, 0, 0}, Mask: net.IPMask{0, 0, 0, 0}}, + { + IP: net.IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + Mask: net.IPMask{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + }, + }, + DestinationIPs: nil, + Protocol: hcloud.FirewallRuleProtocolTCP, + Port: hcloud.Ptr("443"), + Description: hcloud.Ptr("Allow port 443"), + }, + }, + }). + Return([]*hcloud.Action{{ID: 123}, {ID: 321}}, nil, nil) + fx.ActionWaiter.EXPECT(). + WaitForActions(gomock.Any(), []*hcloud.Action{{ID: 123}, {ID: 321}}). + Return(nil) + + out, _, err := fx.Run(cmd, []string{"--rules-file", "testdata/rules.json", "test"}) + + expOut := "Firewall Rules for Firewall 123 updated\n" + + assert.NoError(t, err) + assert.Equal(t, expOut, out) +} diff --git a/internal/cmd/firewall/testdata/rules.json b/internal/cmd/firewall/testdata/rules.json new file mode 100644 index 00000000..7efec894 --- /dev/null +++ b/internal/cmd/firewall/testdata/rules.json @@ -0,0 +1,23 @@ +[ + { + "description": "Allow port 80", + "direction": "in", + "port": "80", + "protocol": "tcp", + "source_ips": [ + "28.239.13.1/32", + "28.239.14.0/24", + "ff21:1eac:9a3b:ee58:5ca:990c:8bc9:c03b/128" + ] + }, + { + "description": "Allow port 443", + "direction": "in", + "port": "443", + "protocol": "tcp", + "source_ips": [ + "0.0.0.0/0", + "::/0" + ] + } +]