Repository: hetznercloud/hcloud-go
Pull request #169 (2021-05-28 08:12:32)

Add Firewall Resource Label Selector
Signed-off-by: Lukas Kämmerling <lukas.kaemmerling@hetzner-cloud.de>


Patch:
diff --git a/hcloud/firewall.go b/hcloud/firewall.go
index 23613a4..983bf50 100644
--- a/hcloud/firewall.go
+++ b/hcloud/firewall.go
@@ -62,12 +62,15 @@ type FirewallResourceType string
 const (
 	// FirewallResourceTypeServer specifies a Server.
 	FirewallResourceTypeServer FirewallResourceType = "server"
+	// FirewallResourceTypeLabelSelector specifies a LabelSelector.
+	FirewallResourceTypeLabelSelector FirewallResourceType = "label_selector"
 )
 
 // FirewallResource represents a resource to apply the new Firewall on.
 type FirewallResource struct {
-	Type   FirewallResourceType
-	Server *FirewallResourceServer
+	Type          FirewallResourceType
+	Server        *FirewallResourceServer
+	LabelSelector *FirewallResourceLabelSelector
 }
 
 // FirewallResourceServer represents a Server to apply a Firewall on.
@@ -75,6 +78,11 @@ type FirewallResourceServer struct {
 	ID int
 }
 
+// FirewallResourceLabelSelector represents a LabelSelector to apply a Firewall on.
+type FirewallResourceLabelSelector struct {
+	Selector string
+}
+
 // FirewallClient is a client for the Firewalls API.
 type FirewallClient struct {
 	client *Client
diff --git a/hcloud/schema.go b/hcloud/schema.go
index 2ab9e00..a50cafe 100644
--- a/hcloud/schema.go
+++ b/hcloud/schema.go
@@ -729,7 +729,10 @@ func FirewallFromSchema(s schema.Firewall) *Firewall {
 	}
 	for _, res := range s.AppliedTo {
 		r := FirewallResource{Type: FirewallResourceType(res.Type)}
-		if r.Type == FirewallResourceTypeServer {
+		switch r.Type {
+		case FirewallResourceTypeLabelSelector:
+			r.LabelSelector = &FirewallResourceLabelSelector{Selector: res.LabelSelector.Selector}
+		case FirewallResourceTypeServer:
 			r.Server = &FirewallResourceServer{ID: res.Server.ID}
 		}
 		f.AppliedTo = append(f.AppliedTo, r)
@@ -999,10 +1002,13 @@ func firewallCreateOptsToSchema(opts FirewallCreateOpts) schema.FirewallCreateRe
 		schemaFirewallResource := schema.FirewallResource{
 			Type: string(res.Type),
 		}
-		if res.Type == FirewallResourceTypeServer {
+		switch res.Type {
+		case FirewallResourceTypeServer:
 			schemaFirewallResource.Server = &schema.FirewallResourceServer{
 				ID: res.Server.ID,
 			}
+		case FirewallResourceTypeLabelSelector:
+			schemaFirewallResource.LabelSelector = &schema.FirewallResourceLabelSelector{Selector: res.LabelSelector.Selector}
 		}
 
 		req.ApplyTo = append(req.ApplyTo, schemaFirewallResource)
@@ -1039,7 +1045,10 @@ func firewallResourceToSchema(resource FirewallResource) schema.FirewallResource
 	s := schema.FirewallResource{
 		Type: string(resource.Type),
 	}
-	if resource.Type == FirewallResourceTypeServer {
+	switch resource.Type {
+	case FirewallResourceTypeLabelSelector:
+		s.LabelSelector = &schema.FirewallResourceLabelSelector{Selector: resource.LabelSelector.Selector}
+	case FirewallResourceTypeServer:
 		s.Server = &schema.FirewallResourceServer{ID: resource.Server.ID}
 	}
 	return s
diff --git a/hcloud/schema/firewall.go b/hcloud/schema/firewall.go
index fe8192c..208a1b5 100644
--- a/hcloud/schema/firewall.go
+++ b/hcloud/schema/firewall.go
@@ -41,8 +41,14 @@ type FirewallCreateRequest struct {
 
 // FirewallResource defines the schema of a resource to apply the new Firewall on.
 type FirewallResource struct {
-	Type   string                  `json:"type"`
-	Server *FirewallResourceServer `json:"server"`
+	Type          string                         `json:"type"`
+	Server        *FirewallResourceServer        `json:"server"`
+	LabelSelector *FirewallResourceLabelSelector `json:"label_selector"`
+}
+
+// FirewallResourceLabelSelector defines the schema of a LabelSelector to apply a Firewall on.
+type FirewallResourceLabelSelector struct {
+	Selector string `json:"selector"`
 }
 
 // FirewallResourceServer defines the schema of a Server to apply a Firewall on.


Test patch:
diff --git a/hcloud/firewall_test.go b/hcloud/firewall_test.go
index efbf32c..fd2ed29 100644
--- a/hcloud/firewall_test.go
+++ b/hcloud/firewall_test.go
@@ -515,6 +515,10 @@ func TestFirewallApplyToResources(t *testing.T) {
 					Type:   "server",
 					Server: &schema.FirewallResourceServer{ID: 5},
 				},
+				{
+					Type:          "label_selector",
+					LabelSelector: &schema.FirewallResourceLabelSelector{Selector: "a=b"},
+				},
 			},
 		}
 		if !cmp.Equal(expectedReqBody, reqBody) {
@@ -540,6 +544,10 @@ func TestFirewallApplyToResources(t *testing.T) {
 			Type:   FirewallResourceTypeServer,
 			Server: &FirewallResourceServer{ID: 5},
 		},
+		{
+			Type:          FirewallResourceTypeLabelSelector,
+			LabelSelector: &FirewallResourceLabelSelector{Selector: "a=b"},
+		},
 	}
 
 	actions, _, err := env.Client.Firewall.ApplyResources(ctx, firewall, resources)
@@ -569,6 +577,10 @@ func TestFirewallRemoveFromResources(t *testing.T) {
 					Type:   "server",
 					Server: &schema.FirewallResourceServer{ID: 5},
 				},
+				{
+					Type:          "label_selector",
+					LabelSelector: &schema.FirewallResourceLabelSelector{Selector: "a=b"},
+				},
 			},
 		}
 		if !cmp.Equal(expectedReqBody, reqBody) {
@@ -594,6 +606,10 @@ func TestFirewallRemoveFromResources(t *testing.T) {
 			Type:   FirewallResourceTypeServer,
 			Server: &FirewallResourceServer{ID: 5},
 		},
+		{
+			Type:          FirewallResourceTypeLabelSelector,
+			LabelSelector: &FirewallResourceLabelSelector{Selector: "a=b"},
+		},
 	}
 
 	actions, _, err := env.Client.Firewall.RemoveResources(ctx, firewall, resources)
diff --git a/hcloud/schema_test.go b/hcloud/schema_test.go
index f767920..a76c1c7 100644
--- a/hcloud/schema_test.go
+++ b/hcloud/schema_test.go
@@ -2727,6 +2727,12 @@ func TestFirewallFromSchema(t *testing.T) {
 					"id": 42
 				},
 				"type": "server"
+			},
+			{
+			 	"label_selector": {
+					"selector": "a=b"
+				},
+				"type": "label_selector"
 			}
 		  ]
 	}
@@ -2767,7 +2773,7 @@ func TestFirewallFromSchema(t *testing.T) {
 	if *firewall.Rules[0].Port != "80" {
 		t.Errorf("unexpected Rule Port: %s", *firewall.Rules[0].Port)
 	}
-	if len(firewall.AppliedTo) != 1 {
+	if len(firewall.AppliedTo) != 2 {
 		t.Errorf("unexpected UsedBy count: %d", len(firewall.AppliedTo))
 	}
 	if firewall.AppliedTo[0].Type != FirewallResourceTypeServer {
@@ -2776,4 +2782,10 @@ func TestFirewallFromSchema(t *testing.T) {
 	if firewall.AppliedTo[0].Server.ID != 42 {
 		t.Errorf("unexpected UsedBy Server ID: %d", firewall.AppliedTo[0].Server.ID)
 	}
+	if firewall.AppliedTo[1].Type != FirewallResourceTypeLabelSelector {
+		t.Errorf("unexpected UsedBy Type: %s", firewall.AppliedTo[0].Type)
+	}
+	if firewall.AppliedTo[1].LabelSelector.Selector != "a=b" {
+		t.Errorf("unexpected UsedBy Label Selector: %s", firewall.AppliedTo[1].LabelSelector.Selector)
+	}
 }