Skip to content

Commit

Permalink
ssa: add NormalizeDryRunUnstructured
Browse files Browse the repository at this point in the history
Signed-off-by: Hidde Beydals <[email protected]>
  • Loading branch information
hiddeco committed Oct 4, 2023
1 parent 45af777 commit 77e4575
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 70 deletions.
2 changes: 1 addition & 1 deletion ssa/manager_diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ func prepareObjectForDiff(object *unstructured.Unstructured) *unstructured.Unstr
deepCopy := object.DeepCopy()
unstructured.RemoveNestedField(deepCopy.Object, "metadata")
unstructured.RemoveNestedField(deepCopy.Object, "status")
if err := fixHorizontalPodAutoscaler(deepCopy); err != nil {
if err := NormalizeDryRunUnstructured(deepCopy); err != nil {
return object
}
return deepCopy
Expand Down
59 changes: 59 additions & 0 deletions ssa/normalize.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ package ssa

import (
appsv1 "k8s.io/api/apps/v1"
hpav2 "k8s.io/api/autoscaling/v2"
hpav2beta2 "k8s.io/api/autoscaling/v2beta2"
corev1 "k8s.io/api/core/v1"
apiequality "k8s.io/apimachinery/pkg/api/equality"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
Expand Down Expand Up @@ -112,6 +115,62 @@ func NormalizeUnstructuredWithScheme(object *unstructured.Unstructured, scheme *
return nil
}

// NormalizeDryRunUnstructured normalizes an Unstructured object retrieved from
// a dry-run by performing fixes for known upstream issues.
func NormalizeDryRunUnstructured(object *unstructured.Unstructured) error {
// Address an issue with dry-run returning a HorizontalPodAutoscaler
// with the first metric duplicated and an empty metric added at the
// end of the list.
// xref: https://github.com/kubernetes/kubernetes/issues/118293
if object.GetKind() == "HorizontalPodAutoscaler" {
typedObject, err := FromUnstructured(object)
if err != nil {
return err
}

switch o := typedObject.(type) {
case *hpav2beta2.HorizontalPodAutoscaler:
var metrics []hpav2beta2.MetricSpec
for _, metric := range o.Spec.Metrics {
found := false
for _, existing := range metrics {
if apiequality.Semantic.DeepEqual(metric, existing) {
found = true
break
}
}
if !found && metric.Type != "" {
metrics = append(metrics, metric)
}
}
o.Spec.Metrics = metrics
case *hpav2.HorizontalPodAutoscaler:
var metrics []hpav2.MetricSpec
for _, metric := range o.Spec.Metrics {
found := false
for _, existing := range metrics {
if apiequality.Semantic.DeepEqual(metric, existing) {
found = true
break
}
}
if !found && metric.Type != "" {
metrics = append(metrics, metric)
}
}
o.Spec.Metrics = metrics
}

normalizedObject, err := ToUnstructured(typedObject)
if err != nil {
return err
}

object.Object = normalizedObject.Object
}
return nil
}

// normalizeServiceProtoDefault sets the default protocol for ports in a
// ServiceSpec.
// xref: https://github.com/kubernetes/kubernetes/pull/98576
Expand Down
69 changes: 0 additions & 69 deletions ssa/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ import (
"strings"

"github.com/google/go-cmp/cmp"
hpav2 "k8s.io/api/autoscaling/v2"
hpav2beta2 "k8s.io/api/autoscaling/v2beta2"
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
Expand Down Expand Up @@ -339,72 +336,6 @@ func SetNativeKindsDefaults(objects []*unstructured.Unstructured) error {
return nil
}

// Fix bug in server-side dry-run apply that duplicates the first item in the metrics array
// and inserts an empty metric as the last item in the array.
func fixHorizontalPodAutoscaler(object *unstructured.Unstructured) error {
if object.GetKind() == "HorizontalPodAutoscaler" {
switch object.GetAPIVersion() {
case "autoscaling/v2beta2":
var d hpav2beta2.HorizontalPodAutoscaler
err := runtime.DefaultUnstructuredConverter.FromUnstructured(object.Object, &d)
if err != nil {
return fmt.Errorf("%s validation error: %w", FmtUnstructured(object), err)
}

var metrics []hpav2beta2.MetricSpec
for _, metric := range d.Spec.Metrics {
found := false
for _, existing := range metrics {
if apiequality.Semantic.DeepEqual(metric, existing) {
found = true
break
}
}
if !found && metric.Type != "" {
metrics = append(metrics, metric)
}
}

d.Spec.Metrics = metrics

out, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&d)
if err != nil {
return fmt.Errorf("%s validation error: %w", FmtUnstructured(object), err)
}
object.Object = out
case "autoscaling/v2":
var d hpav2.HorizontalPodAutoscaler
err := runtime.DefaultUnstructuredConverter.FromUnstructured(object.Object, &d)
if err != nil {
return fmt.Errorf("%s validation error: %w", FmtUnstructured(object), err)
}

var metrics []hpav2.MetricSpec
for _, metric := range d.Spec.Metrics {
found := false
for _, existing := range metrics {
if apiequality.Semantic.DeepEqual(metric, existing) {
found = true
break
}
}
if !found && metric.Type != "" {
metrics = append(metrics, metric)
}
}

d.Spec.Metrics = metrics

out, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&d)
if err != nil {
return fmt.Errorf("%s validation error: %w", FmtUnstructured(object), err)
}
object.Object = out
}
}
return nil
}

func containsItemString(s []string, e string) bool {
for _, a := range s {
if a == e {
Expand Down

0 comments on commit 77e4575

Please sign in to comment.