dryrun: Don't reuse current object for conversion

dry-run and non-dry-run are currently a little different since dry-run
was using the destination object to get the current status. That causes
a weird duplication bug with the HorizontalPodAutoscaler conversion
code. Addresses the bug by using an empty object for the current state
and keep the destination for its actual "out" purpose.
This commit is contained in:
Antoine Pelisse 2023-06-02 13:37:34 -07:00
parent 1dc8384cdd
commit 20866b3f85

View File

@ -18,7 +18,10 @@ package registry
import (
"context"
"fmt"
"reflect"
"k8s.io/apimachinery/pkg/conversion"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/apiserver/pkg/storage"
@ -72,19 +75,30 @@ func (s *DryRunnableStorage) GuaranteedUpdate(
ctx context.Context, key string, destination runtime.Object, ignoreNotFound bool,
preconditions *storage.Preconditions, tryUpdate storage.UpdateFunc, dryRun bool, cachedExistingObject runtime.Object) error {
if dryRun {
err := s.Storage.Get(ctx, key, storage.GetOptions{IgnoreNotFound: ignoreNotFound}, destination)
var current runtime.Object
v, err := conversion.EnforcePtr(destination)
if err != nil {
return fmt.Errorf("unable to convert output object to pointer: %v", err)
}
if u, ok := v.Addr().Interface().(runtime.Unstructured); ok {
current = u.NewEmptyInstance()
} else {
current = reflect.New(v.Type()).Interface().(runtime.Object)
}
err = s.Storage.Get(ctx, key, storage.GetOptions{IgnoreNotFound: ignoreNotFound}, current)
if err != nil {
return err
}
err = preconditions.Check(key, destination)
err = preconditions.Check(key, current)
if err != nil {
return err
}
rev, err := s.Versioner().ObjectResourceVersion(destination)
rev, err := s.Versioner().ObjectResourceVersion(current)
if err != nil {
return err
}
updated, _, err := tryUpdate(destination, storage.ResponseMeta{ResourceVersion: rev})
updated, _, err := tryUpdate(current, storage.ResponseMeta{ResourceVersion: rev})
if err != nil {
return err
}