Skip to content

Commit

Permalink
resource: IgnoreObjectOwnedByVirtOperator
Browse files Browse the repository at this point in the history
Co-authored-by: Felix Matouschek <[email protected]>
Signed-off-by: Lee Yarwood <[email protected]>
  • Loading branch information
lyarwood and 0xFelix committed Oct 23, 2023
1 parent 345d81d commit b9023dc
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 0 deletions.
31 changes: 31 additions & 0 deletions internal/common/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
rbac "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/errors"
kubevirtCorev1 "kubevirt.io/api/core/v1"
instancetypev1alpha2 "kubevirt.io/api/instancetype/v1alpha2"
instancetypev1beta1 "kubevirt.io/api/instancetype/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/client"
Expand All @@ -28,6 +29,7 @@ const (
OperationResultCreated OperationResult = "created"
OperationResultUpdated OperationResult = "updated"
OperationResultDeleted OperationResult = "deleted"
OperationResultIgnored OperationResult = "ignored"
)

type StatusMessage = *string
Expand Down Expand Up @@ -79,6 +81,9 @@ type ReconcileOptions struct {
// on changes that don't increase the .metadata.generation field.
// For example, labels and annotations.
AlwaysCallUpdateFunc bool

// Ignore any existing objects associated with the virt-operator
IgnoreObjectOwnedByVirtOperator bool
}

type ReconcileBuilder interface {
Expand All @@ -88,6 +93,7 @@ type ReconcileBuilder interface {
UpdateFunc(ResourceUpdateFunc) ReconcileBuilder
StatusFunc(ResourceStatusFunc) ReconcileBuilder
ImmutableSpec(getter ResourceSpecGetter) ReconcileBuilder
IgnoreObjectOwnedByVirtOperator() ReconcileBuilder

Options(options ReconcileOptions) ReconcileBuilder

Expand Down Expand Up @@ -161,6 +167,11 @@ func (r *reconcileBuilder) Options(options ReconcileOptions) ReconcileBuilder {
return r
}

func (r *reconcileBuilder) IgnoreObjectOwnedByVirtOperator() ReconcileBuilder {
r.options.IgnoreObjectOwnedByVirtOperator = true
return r
}

func (r *reconcileBuilder) Reconcile() (ReconcileResult, error) {
if r.addLabels {
AddAppLabels(r.request.Instance, r.operandName, r.operandComponent, r.resource)
Expand Down Expand Up @@ -303,6 +314,14 @@ func (r *reconcileBuilder) createOrUpdateWithImmutableSpec(obj client.Object, f
}

existing := obj.DeepCopyObject().(client.Object)

// During an upgrade to v0.19.0 we might encounter virt-operator attempting
// to reconcile the same set of common-instancetype resources. If configured
// ignore these requests to reconcile such objects once owned by virt-operator
if r.options.IgnoreObjectOwnedByVirtOperator && isOwnedByVirtOperator(existing) {
return OperationResultIgnored, existing, nil
}

if err := mutate(f, key, obj); err != nil {
return OperationResultNone, existing, err
}
Expand Down Expand Up @@ -337,6 +356,14 @@ func mutate(f controllerutil.MutateFn, key client.ObjectKey, obj client.Object)
return nil
}

func isOwnedByVirtOperator(obj client.Object) bool {
if obj.GetLabels() == nil {
return false
}
managedValue, managedOk := obj.GetLabels()[kubevirtCorev1.ManagedByLabel]
return managedOk && managedValue == kubevirtCorev1.ManagedByLabelOperatorValue
}

func setOwner(request *Request, resource client.Object, isClusterRes bool) error {
if isClusterRes {
resource.SetOwnerReferences(nil)
Expand Down Expand Up @@ -391,6 +418,10 @@ func logOperation(result OperationResult, resource client.Object, logger logr.Lo
logger.Info(fmt.Sprintf("Deleted %s resource: %s",
resource.GetObjectKind().GroupVersionKind().Kind,
resource.GetName()))
case OperationResultIgnored:
logger.Info(fmt.Sprintf("Ignored %s resource owned by virt-operator: %s",
resource.GetObjectKind().GroupVersionKind().Kind,
resource.GetName()))
}
}

Expand Down
15 changes: 15 additions & 0 deletions internal/common/resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/reconcile"

kubevirtCorev1 "kubevirt.io/api/core/v1"
ssp "kubevirt.io/ssp-operator/api/v1beta2"
)

Expand Down Expand Up @@ -217,6 +218,20 @@ var _ = Describe("Resource", func() {
Expect(err).ToNot(HaveOccurred())
expectEqualResourceExists(newTestResource(namespace), &request)
})

It("should ignore object when owned by virt-operator when configured", func() {
resource := newTestResource(namespace)
resource.Labels[kubevirtCorev1.ManagedByLabel] = kubevirtCorev1.ManagedByLabelOperatorValue
Expect(request.Client.Create(request.Context, resource)).To(Succeed())

res, err := CreateOrUpdate(&request).
NamespacedResource(newTestResource(namespace)).
IgnoreObjectOwnedByVirtOperator().
Reconcile()

Expect(err).ToNot(HaveOccurred())
Expect(res.OperationResult).To(Equal(OperationResultIgnored))
})
})

Context("Cleanup", func() {
Expand Down

0 comments on commit b9023dc

Please sign in to comment.