1package integration
2
3import (
4	"context"
5	"reflect"
6	"testing"
7
8	"github.com/google/go-cmp/cmp"
9	"github.com/google/go-cmp/cmp/cmpopts"
10	"github.com/linode/linodego"
11)
12
13var testFirewallCreateOpts = linodego.FirewallCreateOptions{
14	Label: "label",
15	Rules: testFirewallRuleSet, // borrowed from firewall_rules.test.go
16	Tags:  []string{"testing"},
17}
18
19// ignoreNetworkAddresses negates comparing IP addresses. Because of fixture sanitization,
20// these addresses will be changed to bogus values when running tests.
21var ignoreNetworkAddresses = cmpopts.IgnoreFields(linodego.FirewallRule{}, "Addresses")
22
23// ignoreFirewallTimestamps negates comparing created and updated timestamps. Because of
24// fixture sanitization, these addresses will be changed to bogus values when running tests.
25var ignoreFirewallTimestamps = cmpopts.IgnoreFields(linodego.Firewall{}, "Created", "Updated")
26
27// TestListFirewalls should return a paginated list of Firewalls
28func TestListFirewalls(t *testing.T) {
29	client, _, teardown, err := setupFirewall(t, []firewallModifier{
30		func(createOpts *linodego.FirewallCreateOptions) {
31			createOpts.Label = randString(12, lowerBytes, upperBytes) + "-linodego-testing"
32		},
33	}, "fixtures/TestListFirewalls")
34	if err != nil {
35		t.Error(err)
36	}
37	defer teardown()
38
39	result, err := client.ListFirewalls(context.Background(), nil)
40	if err != nil {
41		t.Errorf("Error listing Firewalls, expected struct, got error %v", err)
42	}
43
44	if len(result) == 0 {
45		t.Errorf("Expected a list of Firewalls, but got none: %v", err)
46	}
47}
48
49func TestGetFirewall(t *testing.T) {
50	label := randString(12, lowerBytes, upperBytes) + "-linodego-testing"
51	rules := linodego.FirewallRuleSet{
52		Inbound: []linodego.FirewallRule{
53			{
54				Label:    "test-label",
55				Action:   "DROP",
56				Protocol: linodego.ICMP,
57				Addresses: linodego.NetworkAddresses{
58					IPv4: &[]string{"0.0.0.0/0"},
59					IPv6: &[]string{"::/0"},
60				},
61			},
62		},
63		InboundPolicy:  "ACCEPT",
64		OutboundPolicy: "ACCEPT",
65	}
66	client, created, teardown, err := setupFirewall(t, []firewallModifier{
67		func(createOpts *linodego.FirewallCreateOptions) {
68			createOpts.Label = label
69			createOpts.Rules = rules
70		},
71	}, "fixtures/TestGetFirewall")
72	if err != nil {
73		t.Error(err)
74	}
75	defer teardown()
76
77	result, err := client.GetFirewall(context.Background(), created.ID)
78	if err != nil {
79		t.Errorf("failed to get newly created firewall %d: %s", created.ID, err)
80	}
81
82	if !reflect.DeepEqual(result.Rules, rules) {
83		t.Errorf("Expected firewall rules to be %#v but got %#v", rules, result.Rules)
84	}
85}
86
87func TestUpdateFirewall(t *testing.T) {
88	label := randString(12, lowerBytes, upperBytes) + "-linodego-testing"
89	rules := linodego.FirewallRuleSet{
90		InboundPolicy: "ACCEPT",
91		Inbound: []linodego.FirewallRule{
92			{
93				Label:    "test-label",
94				Action:   "DROP",
95				Protocol: linodego.ICMP,
96				Addresses: linodego.NetworkAddresses{
97					IPv4: &[]string{"0.0.0.0/0"},
98				},
99			},
100		},
101		OutboundPolicy: "ACCEPT",
102	}
103
104	client, firewall, teardown, err := setupFirewall(t, []firewallModifier{
105		func(createOpts *linodego.FirewallCreateOptions) {
106			createOpts.Label = label
107			createOpts.Rules = rules
108			createOpts.Tags = []string{"test"}
109		},
110	}, "fixtures/TestUpdateFirewall")
111	if err != nil {
112		t.Error(err)
113	}
114	defer teardown()
115
116	updateOpts := firewall.GetUpdateOptions()
117	updateOpts.Status = linodego.FirewallDisabled
118	updateOpts.Label = "updatedFirewallLabel"
119	updateOpts.Tags = &[]string{}
120
121	updated, err := client.UpdateFirewall(context.Background(), firewall.ID, updateOpts)
122	if err != nil {
123		t.Error(err)
124	}
125
126	if !cmp.Equal(updated.Tags, *updateOpts.Tags) {
127		t.Errorf("expected tags to be updated: %s", cmp.Diff(updated.Tags, *updateOpts.Tags))
128	}
129	if updated.Status != updateOpts.Status {
130		t.Errorf("expected status %s but got %s", updateOpts.Status, updated.Status)
131	}
132	if updated.Label != updateOpts.Label {
133		t.Errorf(`expected label to be "%s" but got "%s"`, updateOpts.Label, updated.Label)
134	}
135}
136
137type firewallModifier func(*linodego.FirewallCreateOptions)
138
139func createFirewall(t *testing.T, client *linodego.Client, firewallModifiers ...firewallModifier) (*linodego.Firewall, func(), error) {
140	t.Helper()
141
142	createOpts := testFirewallCreateOpts
143	for _, modifier := range firewallModifiers {
144		modifier(&createOpts)
145	}
146
147	firewall, err := client.CreateFirewall(context.Background(), createOpts)
148	if err != nil {
149		t.Errorf("failed to create firewall: %s", err)
150	}
151
152	teardown := func() {
153		if err := client.DeleteFirewall(context.Background(), firewall.ID); err != nil {
154			t.Errorf("failed to delete firewall: %s", err)
155		}
156	}
157	return firewall, teardown, nil
158}
159
160func setupFirewall(t *testing.T, firewallModifiers []firewallModifier, fixturesYaml string) (*linodego.Client, *linodego.Firewall, func(), error) {
161	t.Helper()
162	client, fixtureTeardown := createTestClient(t, fixturesYaml)
163	firewall, firewallTeardown, err := createFirewall(t, client, firewallModifiers...)
164
165	teardown := func() {
166		firewallTeardown()
167		fixtureTeardown()
168	}
169	return client, firewall, teardown, err
170}
171