diff --git a/cluster-autoscaler/cloudprovider/clusterapi/README.md b/cluster-autoscaler/cloudprovider/clusterapi/README.md index 20581f1b89ac4013025ee1912e771a747ff0745a..bd800ffa4f7cbdc49bbf5f195ede3ab055c25b10 100644 --- a/cluster-autoscaler/cloudprovider/clusterapi/README.md +++ b/cluster-autoscaler/cloudprovider/clusterapi/README.md @@ -180,6 +180,23 @@ the machine annotation on nodes will be `test.8s.io/machine`, the machine deleti annotation will be `test.k8s.io/delete-machine`, and the cluster name label will be `test.k8s.io/cluster-name`. +## Specifying a Custom Resource Version + +When determining the group version for the Cluster API types, by default the autoscaler +will look for the latest version of the group. For example, if `MachineDeployments` +exist in the `cluster.x-k8s.io` group at versions `v1alpha1` and `v1beta1`, the +autoscaler will choose `v1beta1`. + +In some cases it may be desirable to specify which version of the API the cluster +autoscaler should use. This can be useful in debugging scenarios, or in situations +where you have deployed multiple API versions and wish to ensure that the autoscaler +uses a specific version. + +Setting the `CAPI_VERSION` environment variable will instruct the autoscaler to use +the version specified. This works in a similar fashion as the API group environment +variable with the exception that there is no default value. When this variable is not +set, the autoscaler will use the behavior described above. + ## Sample manifest A sample manifest that will create a deployment running the autoscaler is diff --git a/cluster-autoscaler/cloudprovider/clusterapi/clusterapi_controller.go b/cluster-autoscaler/cloudprovider/clusterapi/clusterapi_controller.go index 54877b8b6460059f698b41b9ce707a70393ae602..1cc7f1989be1e51fcd690986b8e558844cdd7544 100644 --- a/cluster-autoscaler/cloudprovider/clusterapi/clusterapi_controller.go +++ b/cluster-autoscaler/cloudprovider/clusterapi/clusterapi_controller.go @@ -46,7 +46,9 @@ const ( nodeProviderIDIndex = "nodeProviderIDIndex" defaultCAPIGroup = "cluster.x-k8s.io" // CAPIGroupEnvVar contains the environment variable name which allows overriding defaultCAPIGroup. - CAPIGroupEnvVar = "CAPI_GROUP" + CAPIGroupEnvVar = "CAPI_GROUP" + // CAPIVersionEnvVar contains the environment variable name which allows overriding the Cluster API group version. + CAPIVersionEnvVar = "CAPI_VERSION" resourceNameMachine = "machines" resourceNameMachineSet = "machinesets" resourceNameMachineDeployment = "machinedeployments" @@ -305,6 +307,17 @@ func getCAPIGroup() string { return g } +// getCAPIVersion returns a string the specifies the version for the API. +// It will return either the value from the CAPI_VERSION environment variable, +// or an empty string if the variable is not set. +func getCAPIVersion() string { + v := os.Getenv(CAPIVersionEnvVar) + if v != "" { + klog.V(4).Infof("Using API Version %q", v) + } + return v +} + // newMachineController constructs a controller that watches Nodes, // Machines and MachineSet as they are added, updated and deleted on // the cluster. @@ -415,6 +428,10 @@ func groupVersionHasResource(client discovery.DiscoveryInterface, groupVersion, } func getAPIGroupPreferredVersion(client discovery.DiscoveryInterface, APIGroup string) (string, error) { + if version := os.Getenv(CAPIVersionEnvVar); version != "" { + return version, nil + } + groupList, err := client.ServerGroups() if err != nil { return "", fmt.Errorf("failed to get ServerGroups: %v", err) diff --git a/cluster-autoscaler/cloudprovider/clusterapi/clusterapi_controller_test.go b/cluster-autoscaler/cloudprovider/clusterapi/clusterapi_controller_test.go index 158c5b78e75e428d4bfcdd8855c885b483ca0890..5413de38a5409f105f91bd0bee725e0854833be3 100644 --- a/cluster-autoscaler/cloudprovider/clusterapi/clusterapi_controller_test.go +++ b/cluster-autoscaler/cloudprovider/clusterapi/clusterapi_controller_test.go @@ -1369,6 +1369,26 @@ func TestControllerGetAPIVersionGroup(t *testing.T) { } } +func TestControllerGetAPIVersion(t *testing.T) { + expected := "v1beta1" + if err := os.Setenv(CAPIVersionEnvVar, expected); err != nil { + t.Fatalf("unexpected error: %v", err) + } + observed := getCAPIVersion() + if observed != expected { + t.Fatalf("Wrong API Version detected, expected %q, got %q", expected, observed) + } + + if err := os.Unsetenv(CAPIVersionEnvVar); err != nil { + t.Fatalf("unexpected error: %v", err) + } + expected = "" + observed = getCAPIVersion() + if observed != expected { + t.Fatalf("Wrong API Version detected, expected %q, got %q", expected, observed) + } +} + func TestControllerGetAPIVersionGroupWithMachineDeployments(t *testing.T) { testConfig := createMachineDeploymentTestConfig(RandomString(6), RandomString(6), RandomString(6), 1, map[string]string{ nodeGroupMinSizeAnnotationKey: "1", @@ -1424,28 +1444,40 @@ func TestControllerGetAPIVersionGroupWithMachineDeployments(t *testing.T) { } func TestGetAPIGroupPreferredVersion(t *testing.T) { + customVersion := "v1" testCases := []struct { description string APIGroup string preferredVersion string + envVar string error bool }{ { description: "find version for default API group", APIGroup: defaultCAPIGroup, preferredVersion: "v1alpha3", + envVar: "", error: false, }, { description: "find version for another API group", APIGroup: customCAPIGroup, preferredVersion: "v1beta1", + envVar: "", + error: false, + }, + { + description: "find version for another API group while overriding version with env var", + APIGroup: customCAPIGroup, + preferredVersion: customVersion, + envVar: customVersion, error: false, }, { description: "API group does not exist", APIGroup: "does.not.exist", preferredVersion: "", + envVar: "", error: true, }, } @@ -1459,11 +1491,23 @@ func TestGetAPIGroupPreferredVersion(t *testing.T) { { GroupVersion: fmt.Sprintf("%s/v1alpha3", defaultCAPIGroup), }, + { + GroupVersion: fmt.Sprintf("%s/%s", customCAPIGroup, customVersion), + }, }, }, } for _, tc := range testCases { t.Run(tc.description, func(t *testing.T) { + if tc.envVar == "" { + if err := os.Unsetenv(CAPIVersionEnvVar); err != nil { + t.Fatalf("unexpected error: %v", err) + } + } else { + if err := os.Setenv(CAPIVersionEnvVar, tc.envVar); err != nil { + t.Fatalf("unexpected error: %v", err) + } + } version, err := getAPIGroupPreferredVersion(discoveryClient, tc.APIGroup) if (err != nil) != tc.error { t.Errorf("expected to have error: %t. Had an error: %t", tc.error, err != nil) @@ -1473,6 +1517,10 @@ func TestGetAPIGroupPreferredVersion(t *testing.T) { } }) } + + if err := os.Unsetenv(CAPIVersionEnvVar); err != nil { + t.Fatalf("unexpected error: %v", err) + } } func TestGroupVersionHasResource(t *testing.T) {