From bb4d878940fbffbac6809c757c655a581850b83b Mon Sep 17 00:00:00 2001 From: michael mccune Date: Thu, 16 Feb 2023 16:00:18 -0500 Subject: [PATCH] UPSTREAM: : add machine api label and taint functionality This change re-adds the machine api support for labels and taints on node groups. The code was removed upstream as it is openshift specific, see this pull request[0]. It also adds in the functionality of the upstream override annotation for labels and taints[1] to support https://issues.redhat.com/browse/MIXEDARCH-259 [0]: https://github.com/kubernetes/autoscaler/pull/5249 [1]: https://github.com/kubernetes/autoscaler/pull/5382 --- .../clusterapi/clusterapi_nodegroup_test.go | 15 +++++- .../clusterapi/clusterapi_unstructured.go | 51 ++++++++++++++----- 2 files changed, 53 insertions(+), 13 deletions(-) diff --git a/cluster-autoscaler/cloudprovider/clusterapi/clusterapi_nodegroup_test.go b/cluster-autoscaler/cloudprovider/clusterapi/clusterapi_nodegroup_test.go index 9bb63931baf8..7ef6440f7532 100644 --- a/cluster-autoscaler/cloudprovider/clusterapi/clusterapi_nodegroup_test.go +++ b/cluster-autoscaler/cloudprovider/clusterapi/clusterapi_nodegroup_test.go @@ -1309,6 +1309,7 @@ func TestNodeGroupTemplateNodeInfo(t *testing.T) { type testCaseConfig struct { nodeLabels map[string]string + nodegroupLabels map[string]string includeNodes bool expectedErr error expectedCapacity map[corev1.ResourceName]int64 @@ -1364,6 +1365,10 @@ func TestNodeGroupTemplateNodeInfo(t *testing.T) { }, config: testCaseConfig{ expectedErr: nil, + nodegroupLabels: map[string]string{ + "nodeGroupLabel": "value", + "anotherLabel": "anotherValue", + }, expectedCapacity: map[corev1.ResourceName]int64{ corev1.ResourceCPU: 2, corev1.ResourceMemory: 2048 * 1024 * 1024, @@ -1371,9 +1376,11 @@ func TestNodeGroupTemplateNodeInfo(t *testing.T) { gpuapis.ResourceNvidiaGPU: 1, }, expectedNodeLabels: map[string]string{ + "kubernetes.io/hostname": "random value", "kubernetes.io/os": "linux", "kubernetes.io/arch": "arm64", - "kubernetes.io/hostname": "random value", + "nodeGroupLabel": "value", + "anotherLabel": "anotherValue", "my-custom-label": "custom-value", }, }, @@ -1408,6 +1415,12 @@ func TestNodeGroupTemplateNodeInfo(t *testing.T) { } test := func(t *testing.T, testConfig *testConfig, config testCaseConfig) { + if testConfig.machineDeployment != nil { + unstructured.SetNestedStringMap(testConfig.machineDeployment.Object, config.nodegroupLabels, "spec", "template", "spec", "metadata", "labels") + } else { + unstructured.SetNestedStringMap(testConfig.machineSet.Object, config.nodegroupLabels, "spec", "template", "spec", "metadata", "labels") + } + if config.includeNodes { for i := range testConfig.nodes { testConfig.nodes[i].SetLabels(config.nodeLabels) diff --git a/cluster-autoscaler/cloudprovider/clusterapi/clusterapi_unstructured.go b/cluster-autoscaler/cloudprovider/clusterapi/clusterapi_unstructured.go index 51e680729591..ccf049bfc941 100644 --- a/cluster-autoscaler/cloudprovider/clusterapi/clusterapi_unstructured.go +++ b/cluster-autoscaler/cloudprovider/clusterapi/clusterapi_unstructured.go @@ -175,37 +175,64 @@ func (r unstructuredScalableResource) MarkMachineForDeletion(machine *unstructur } func (r unstructuredScalableResource) Labels() map[string]string { + labels := make(map[string]string, 0) + + newlabels, found, err := unstructured.NestedStringMap(r.unstructured.Object, "spec", "template", "spec", "metadata", "labels") + if err != nil { + return nil + } + if found { + for k, v := range newlabels { + labels[k] = v + } + } + annotations := r.unstructured.GetAnnotations() // annotation value of the form "key1=value1,key2=value2" if val, found := annotations[labelsKey]; found { - labels := strings.Split(val, ",") - kv := make(map[string]string, len(labels)) - for _, label := range labels { + newlabels := strings.Split(val, ",") + for _, label := range newlabels { split := strings.SplitN(label, "=", 2) if len(split) == 2 { - kv[split[0]] = split[1] + labels[split[0]] = split[1] } } - return kv } - return nil + + return labels } func (r unstructuredScalableResource) Taints() []apiv1.Taint { + taints := make([]apiv1.Taint, 0) + + newtaints, found, err := unstructured.NestedSlice(r.unstructured.Object, "spec", "template", "spec", "taints") + if err != nil { + return nil + } + if found { + for _, t := range newtaints { + if v, ok := t.(apiv1.Taint); ok { + taints = append(taints, v) + } else { + klog.Warning("Unable to convert data to taint: %v", t) + continue + } + } + } + annotations := r.unstructured.GetAnnotations() // annotation value the form of "key1=value1:condition,key2=value2:condition" if val, found := annotations[taintsKey]; found { - taints := strings.Split(val, ",") - ret := make([]apiv1.Taint, 0, len(taints)) - for _, taintStr := range taints { + newtaints := strings.Split(val, ",") + for _, taintStr := range newtaints { taint, err := parseTaint(taintStr) if err == nil { - ret = append(ret, taint) + taints = append(taints, taint) } } - return ret } - return nil + + return taints } // A node group can scale from zero if it can inform about the CPU and memory