diff --git a/cloud/linode/loadbalancers.go b/cloud/linode/loadbalancers.go index 95da8fa7..7cd1a0c5 100644 --- a/cloud/linode/loadbalancers.go +++ b/cloud/linode/loadbalancers.go @@ -644,12 +644,26 @@ func (l *loadbalancers) buildLoadBalancerRequest(ctx context.Context, clusterNam return l.createNodeBalancer(ctx, clusterName, service, configs) } +func coerceString(s string, minLen, maxLen int, padding string) string { + if len(padding) == 0 { + padding = "x" + } + if len(s) > maxLen { + return s[:maxLen] + } else if len(s) < minLen { + return coerceString(fmt.Sprintf("%s%s", padding, s), minLen, maxLen, padding) + } + return s +} + func (l *loadbalancers) buildNodeBalancerNodeCreateOptions(node *v1.Node, nodePort int32) linodego.NodeBalancerNodeCreateOptions { return linodego.NodeBalancerNodeCreateOptions{ Address: fmt.Sprintf("%v:%v", getNodePrivateIP(node), nodePort), - Label: node.Name, - Mode: "accept", - Weight: 100, + // NodeBalancer backends must be 3-32 chars in length + // If < 3 chars, pad node name with "node-" prefix + Label: coerceString(node.Name, 3, 32, "node-"), + Mode: "accept", + Weight: 100, } } diff --git a/cloud/linode/loadbalancers_test.go b/cloud/linode/loadbalancers_test.go index 63afdcc7..489a2e7d 100644 --- a/cloud/linode/loadbalancers_test.go +++ b/cloud/linode/loadbalancers_test.go @@ -2114,3 +2114,45 @@ func addTLSSecret(t *testing.T, kubeClient kubernetes.Interface) { t.Fatalf("failed to add TLS secret: %s\n", err) } } + +func Test_LoadbalNodeNameCoercion(t *testing.T) { + type testCase struct { + nodeName string + padding string + expectedOutput string + } + testCases := []testCase{ + { + nodeName: "n", + padding: "z", + expectedOutput: "zzn", + }, + { + nodeName: "n", + padding: "node-", + expectedOutput: "node-n", + }, + { + nodeName: "n", + padding: "", + expectedOutput: "xxn", + }, + { + nodeName: "infra-logging-controlplane-3-atl1-us-prod", + padding: "node-", + expectedOutput: "infra-logging-controlplane-3-atl", + }, + { + nodeName: "node1", + padding: "node-", + expectedOutput: "node1", + }, + } + + for _, tc := range testCases { + if out := coerceString(tc.nodeName, 3, 32, tc.padding); out != tc.expectedOutput { + t.Fatalf("Expected loadbal backend name to be %s (got: %s)", tc.expectedOutput, out) + } + } + +}