Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option for global NodeBalancer tags (Closes #220) #221

Merged
merged 2 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cloud/linode/cloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ var Options struct {
BGPNodeSelector string
IpHolderSuffix string
LinodeExternalNetwork *net.IPNet
NodeBalancerTags []string
}

type linodeCloud struct {
Expand Down
2 changes: 2 additions & 0 deletions cloud/linode/loadbalancers.go
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,8 @@ func (l *loadbalancers) GetLoadBalancerTags(_ context.Context, clusterName strin
tags = append(tags, clusterName)
}

tags = append(tags, Options.NodeBalancerTags...)

tagStr, ok := service.GetAnnotations()[annotations.AnnLinodeLoadBalancerTags]
if ok {
return append(tags, strings.Split(tagStr, ",")...)
Expand Down
37 changes: 28 additions & 9 deletions cloud/linode/loadbalancers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,10 @@ func TestCCMLoadBalancers(t *testing.T) {
name: "Create Load Balancer With Invalid Firewall ACL - NO Allow Or Deny",
f: testCreateNodeBalanceWithNoAllowOrDenyList,
},
{
name: "Create Load Balancer With Global Tags set",
f: testCreateNodeBalancerWithGlobalTags,
},
{
name: "Update Load Balancer - Add Node",
f: testUpdateLoadBalancerAddNode,
Expand Down Expand Up @@ -274,7 +278,7 @@ func stubService(fake *fake.Clientset, service *v1.Service) {
_, _ = fake.CoreV1().Services("").Create(context.TODO(), service, metav1.CreateOptions{})
}

func testCreateNodeBalancer(t *testing.T, client *linodego.Client, _ *fakeAPI, annMap map[string]string) error {
func testCreateNodeBalancer(t *testing.T, client *linodego.Client, _ *fakeAPI, annMap map[string]string, expectedTags []string) error {
svc := &v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: randString(),
Expand Down Expand Up @@ -341,7 +345,9 @@ func testCreateNodeBalancer(t *testing.T, client *linodego.Client, _ *fakeAPI, a
t.Logf("actual: %v", nb.ClientConnThrottle)
}

expectedTags := []string{"linodelb", "fake", "test", "yolo"}
if len(expectedTags) == 0 {
expectedTags = []string{"linodelb", "fake", "test", "yolo"}
}
if !reflect.DeepEqual(nb.Tags, expectedTags) {
t.Error("unexpected Tags")
t.Logf("expected: %v", expectedTags)
Expand All @@ -366,7 +372,7 @@ func testCreateNodeBalancer(t *testing.T, client *linodego.Client, _ *fakeAPI, a
}

func testCreateNodeBalancerWithOutFirewall(t *testing.T, client *linodego.Client, f *fakeAPI) {
err := testCreateNodeBalancer(t, client, f, nil)
err := testCreateNodeBalancer(t, client, f, nil, nil)
if err != nil {
t.Fatalf("expected a nil error, got %v", err)
}
Expand All @@ -377,7 +383,7 @@ func testCreateNodeBalanceWithNoAllowOrDenyList(t *testing.T, client *linodego.C
annotations.AnnLinodeCloudFirewallACL: `{}`,
}

err := testCreateNodeBalancer(t, client, f, annotations)
err := testCreateNodeBalancer(t, client, f, annotations, nil)
if err == nil || !stderrors.Is(err, firewall.ErrInvalidFWConfig) {
t.Fatalf("expected a %v error, got %v", firewall.ErrInvalidFWConfig, err)
}
Expand All @@ -395,7 +401,7 @@ func testCreateNodeBalanceWithBothAllowOrDenyList(t *testing.T, client *linodego
}`,
}

err := testCreateNodeBalancer(t, client, f, annotations)
err := testCreateNodeBalancer(t, client, f, annotations, nil)
if err == nil || !stderrors.Is(err, firewall.ErrInvalidFWConfig) {
t.Fatalf("expected a %v error, got %v", firewall.ErrInvalidFWConfig, err)
}
Expand All @@ -410,7 +416,7 @@ func testCreateNodeBalancerWithAllowList(t *testing.T, client *linodego.Client,
}`,
}

err := testCreateNodeBalancer(t, client, f, annotations)
err := testCreateNodeBalancer(t, client, f, annotations, nil)
if err != nil {
t.Fatalf("expected a non-nil error, got %v", err)
}
Expand All @@ -425,7 +431,7 @@ func testCreateNodeBalancerWithDenyList(t *testing.T, client *linodego.Client, f
}`,
}

err := testCreateNodeBalancer(t, client, f, annotations)
err := testCreateNodeBalancer(t, client, f, annotations, nil)
if err != nil {
t.Fatalf("expected a non-nil error, got %v", err)
}
Expand All @@ -435,7 +441,7 @@ func testCreateNodeBalancerWithFirewall(t *testing.T, client *linodego.Client, f
annotations := map[string]string{
annotations.AnnLinodeCloudFirewallID: "123",
}
err := testCreateNodeBalancer(t, client, f, annotations)
err := testCreateNodeBalancer(t, client, f, annotations, nil)
if err != nil {
t.Fatalf("expected a nil error, got %v", err)
}
Expand All @@ -446,12 +452,25 @@ func testCreateNodeBalancerWithInvalidFirewall(t *testing.T, client *linodego.Cl
annotations.AnnLinodeCloudFirewallID: "qwerty",
}
expectedError := "strconv.Atoi: parsing \"qwerty\": invalid syntax"
err := testCreateNodeBalancer(t, client, f, annotations)
err := testCreateNodeBalancer(t, client, f, annotations, nil)
if err.Error() != expectedError {
t.Fatalf("expected a %s error, got %v", expectedError, err)
}
}

func testCreateNodeBalancerWithGlobalTags(t *testing.T, client *linodego.Client, f *fakeAPI) {
original := Options.NodeBalancerTags
defer func() {
Options.NodeBalancerTags = original
}()
Options.NodeBalancerTags = []string{"foobar"}
expectedTags := []string{"linodelb", "foobar", "fake", "test", "yolo"}
err := testCreateNodeBalancer(t, client, f, nil, expectedTags)
if err != nil {
t.Fatalf("expected a nil error, got %v", err)
}
}

func testUpdateLoadBalancerAddNode(t *testing.T, client *linodego.Client, f *fakeAPI) {
svc := &v1.Service{
ObjectMeta: metav1.ObjectMeta{
Expand Down
3 changes: 3 additions & 0 deletions deploy/chart/templates/daemonset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ spec:
{{- end}}
- --load-balancer-type={{ required "A valid .Values.sharedIPLoadBalancing.loadBalancerType is required for shared IP load-balancing" .Values.sharedIPLoadBalancing.loadBalancerType }}
{{- end }}
{{- if .Values.nodeBalancerTags }}
- --nodebalancer-tags={{ join " " .Values.nodeBalancerTags }}
{{- end }}
volumeMounts:
- mountPath: /etc/kubernetes
name: k8s
Expand Down
3 changes: 3 additions & 0 deletions deploy/chart/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ env:
# - name: EXAMPLE_ENV_VAR
# value: "true"

# Linode tags to apply to all NodeBalancers
nodeBalancerTags: []

# This section adds the ability to pass volumes to the CCM DaemonSet
volumes:
# - name: test-volume
Expand Down
1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ func main() {
command.Flags().StringVar(&linode.Options.LoadBalancerType, "load-balancer-type", "nodebalancer", "configures which type of load-balancing to use for LoadBalancer Services (options: nodebalancer, cilium-bgp)")
command.Flags().StringVar(&linode.Options.BGPNodeSelector, "bgp-node-selector", "", "node selector to use to perform shared IP fail-over with BGP (e.g. cilium-bgp-peering=true")
command.Flags().StringVar(&linode.Options.IpHolderSuffix, "ip-holder-suffix", "", "suffix to append to the ip holder name when using shared IP fail-over with BGP (e.g. ip-holder-suffix=my-cluster-name")
command.Flags().StringSliceVar(&linode.Options.NodeBalancerTags, "nodebalancer-tags", []string{}, "Linode tags to apply to all NodeBalancers")

// Set static flags
command.Flags().VisitAll(func(fl *pflag.Flag) {
Expand Down
Loading