diff --git a/README.md b/README.md index bd0158ba..5c296277 100644 --- a/README.md +++ b/README.md @@ -230,7 +230,7 @@ _See [helm upgrade](https://helm.sh/docs/helm/helm_upgrade/) for command documen ### Configurations -There are other variables that can be set to a different value. For list of all the modifiable variables/values, take a look at './deploy/chart/values.yaml'. +There are other variables that can be set to a different value. For list of all the modifiable variables/values, take a look at './deploy/chart/values.yaml'. Values can be set/overrided by using the '--set var=value,...' flag or by passing in a custom-values.yaml using '-f custom-values.yaml'. diff --git a/cloud/linode/loadbalancers.go b/cloud/linode/loadbalancers.go index 8d7436a4..b3e4cda2 100644 --- a/cloud/linode/loadbalancers.go +++ b/cloud/linode/loadbalancers.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "net/http" + "os" "strconv" "strings" "time" @@ -776,14 +777,26 @@ func makeLoadBalancerStatus(service *v1.Service, nb *linodego.NodeBalancer) *v1. Hostname: *nb.Hostname, } if !getServiceBoolAnnotation(service, annLinodeHostnameOnlyIngress) { - ingress.IP = *nb.IPv4 + if val := envBoolOptions("LINODE_HOSTNAME_ONLY_INGRESS"); val { + klog.Infof("LINODE_HOSTNAME_ONLY_INGRESS: (%v)", val) + } else { + ingress.IP = *nb.IPv4 + } } - return &v1.LoadBalancerStatus{ Ingress: []v1.LoadBalancerIngress{ingress}, } } +// Checks for a truth value in an environment variable +func envBoolOptions(o string) bool { + boolValue, err := strconv.ParseBool(os.Getenv(o)) + if err != nil { + return false + } + return boolValue +} + // getServiceNn returns the services namespaced name. func getServiceNn(service *v1.Service) string { return fmt.Sprintf("%s/%s", service.Namespace, service.Name) diff --git a/cloud/linode/loadbalancers_test.go b/cloud/linode/loadbalancers_test.go index 68c36450..f4ad2c6f 100644 --- a/cloud/linode/loadbalancers_test.go +++ b/cloud/linode/loadbalancers_test.go @@ -5,6 +5,7 @@ import ( "fmt" "net/http" "net/http/httptest" + "os" "reflect" "strconv" "testing" @@ -166,6 +167,10 @@ func TestCCMLoadBalancers(t *testing.T) { name: "makeLoadBalancerStatus", f: testMakeLoadBalancerStatus, }, + { + name: "makeLoadBalancerStatusEnvVar", + f: testMakeLoadBalancerStatusEnvVar, + }, { name: "Cleanup does not call the API unless Service annotated", f: testCleanupDoesntCall, @@ -1448,6 +1453,55 @@ func testMakeLoadBalancerStatus(t *testing.T, client *linodego.Client, _ *fakeAP } } +func testMakeLoadBalancerStatusEnvVar(t *testing.T, client *linodego.Client, _ *fakeAPI) { + ipv4 := "192.168.0.1" + hostname := "nb-192-168-0-1.newark.nodebalancer.linode.com" + nb := &linodego.NodeBalancer{ + IPv4: &ipv4, + Hostname: &hostname, + } + + svc := &v1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Annotations: make(map[string]string, 1), + }, + } + + expectedStatus := &v1.LoadBalancerStatus{ + Ingress: []v1.LoadBalancerIngress{{ + Hostname: hostname, + IP: ipv4, + }}, + } + status := makeLoadBalancerStatus(svc, nb) + if !reflect.DeepEqual(status, expectedStatus) { + t.Errorf("expected status for basic service to be %#v; got %#v", expectedStatus, status) + } + + os.Setenv("LINODE_HOSTNAME_ONLY_INGRESS", "true") + expectedStatus.Ingress[0] = v1.LoadBalancerIngress{Hostname: hostname} + status = makeLoadBalancerStatus(svc, nb) + if !reflect.DeepEqual(status, expectedStatus) { + t.Errorf("expected status for %q annotated service to be %#v; got %#v", annLinodeHostnameOnlyIngress, expectedStatus, status) + } + + os.Setenv("LINODE_HOSTNAME_ONLY_INGRESS", "false") + expectedStatus.Ingress[0] = v1.LoadBalancerIngress{Hostname: hostname} + status = makeLoadBalancerStatus(svc, nb) + if reflect.DeepEqual(status, expectedStatus) { + t.Errorf("expected status for %q annotated service to be %#v; got %#v", annLinodeHostnameOnlyIngress, expectedStatus, status) + } + + os.Setenv("LINODE_HOSTNAME_ONLY_INGRESS", "banana") + expectedStatus.Ingress[0] = v1.LoadBalancerIngress{Hostname: hostname} + status = makeLoadBalancerStatus(svc, nb) + if reflect.DeepEqual(status, expectedStatus) { + t.Errorf("expected status for %q annotated service to be %#v; got %#v", annLinodeHostnameOnlyIngress, expectedStatus, status) + } + os.Unsetenv("LINODE_HOSTNAME_ONLY_INGRESS") +} + func testCleanupDoesntCall(t *testing.T, client *linodego.Client, fakeAPI *fakeAPI) { region := "us-west" nb1, err := client.CreateNodeBalancer(context.TODO(), linodego.NodeBalancerCreateOptions{Region: region}) diff --git a/deploy/chart/templates/daemonset.yaml b/deploy/chart/templates/daemonset.yaml index c91c8216..5d1511ca 100644 --- a/deploy/chart/templates/daemonset.yaml +++ b/deploy/chart/templates/daemonset.yaml @@ -47,6 +47,7 @@ spec: secretKeyRef: name: ccm-linode key: region + {{- toYaml .Values.env | nindent 12 }} volumes: - name: k8s hostPath: diff --git a/deploy/chart/values.yaml b/deploy/chart/values.yaml index 1a63e51b..44e5635a 100644 --- a/deploy/chart/values.yaml +++ b/deploy/chart/values.yaml @@ -1,4 +1,4 @@ -# apiToken [Required] - Must be a Linode APIv4 Personal Access Token with all permissions. (https://cloud.linode.com/profile/tokens) +# apiToken [Required] - Must be a Linode APIv4 Personal Access Token with all permissions. (https://cloud.linode.com/profile/tokens) apiToken: "" # region [Required] - Must be a Linode region. (https://api.linode.com/v4/regions) @@ -20,7 +20,7 @@ image: namespace: "kube-system" # Set of default tolerations -tolerations: +tolerations: # The CCM can run on Nodes tainted as masters - key: "node-role.kubernetes.io/master" effect: "NoSchedule" @@ -37,3 +37,9 @@ tolerations: - key: node.kubernetes.io/unreachable operator: Exists effect: NoSchedule +# This section adds the ability to pass environment variables to adjust CCM defaults +# https://github.com/linode/linode-cloud-controller-manager/blob/master/cloud/linode/loadbalancers.go +# LINODE_HOSTNAME_ONLY_INGRESS type bool is supported +# env: + # - name: EXAMPLE_ENV_VAR + # value: "true" \ No newline at end of file