Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions pkg/operator/resourcesynccontroller/resourcesync_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ type ResourceSyncController struct {
kubeInformersForNamespaces v1helpers.KubeInformersForNamespaces
operatorConfigClient v1helpers.OperatorClient

degradedConditionType string

runFn func(ctx context.Context, workers int)
syncCtx factory.SyncContext
}
Expand All @@ -69,6 +71,7 @@ func NewResourceSyncController(
secretSyncRules: syncRules{},
kubeInformersForNamespaces: kubeInformersForNamespaces,
knownNamespaces: kubeInformersForNamespaces.Namespaces(),
degradedConditionType: condition.ResourceSyncControllerDegradedConditionType,

configMapGetter: v1helpers.CachedConfigMapGetter(configMapsGetter, kubeInformersForNamespaces),
secretGetter: v1helpers.CachedSecretGetter(secretsGetter, kubeInformersForNamespaces),
Expand Down Expand Up @@ -109,6 +112,14 @@ func (c *ResourceSyncController) Name() string {
return c.controllerInstanceName
}

// WithConditionPrefix sets a prefix for the controller's condition types.
// This is useful when multiple operators reuse the same controller but would like to have
// distinct conditions.
func (c *ResourceSyncController) WithConditionPrefix(prefix string) *ResourceSyncController {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably don’t want to change the instance name, so that there is only one manager.

Alternatively, we could add a new constructor that allows assigning a new prefix.

c.degradedConditionType = fmt.Sprintf("%s%s", prefix, c.degradedConditionType)
return c
}

func (c *ResourceSyncController) SyncConfigMap(destination, source ResourceLocation) error {
return c.syncConfigMap(destination, source, alwaysFulfilledPreconditions)
}
Expand Down Expand Up @@ -262,7 +273,7 @@ func (c *ResourceSyncController) Sync(ctx context.Context, syncCtx factory.SyncC
if len(errors) > 0 {
condition := applyoperatorv1.OperatorStatus().
WithConditions(applyoperatorv1.OperatorCondition().
WithType(condition.ResourceSyncControllerDegradedConditionType).
WithType(c.degradedConditionType).
WithStatus(operatorv1.ConditionTrue).
WithReason("Error").
WithMessage(v1helpers.NewMultiLineAggregate(errors).Error()))
Expand All @@ -275,7 +286,7 @@ func (c *ResourceSyncController) Sync(ctx context.Context, syncCtx factory.SyncC

condition := applyoperatorv1.OperatorStatus().
WithConditions(applyoperatorv1.OperatorCondition().
WithType(condition.ResourceSyncControllerDegradedConditionType).
WithType(c.degradedConditionType).
WithStatus(operatorv1.ConditionFalse))
updateErr := c.operatorConfigClient.ApplyOperatorStatus(ctx, c.controllerInstanceName, condition)
if updateErr != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,28 @@ package resourcesynccontroller

import (
"context"
clocktesting "k8s.io/utils/clock/testing"
"fmt"
"net/http"
"net/http/httptest"
"sync"
"testing"
"time"

"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/wait"
ktesting "k8s.io/client-go/testing"

"github.com/openshift/library-go/pkg/operator/events/eventstesting"
"github.com/openshift/library-go/pkg/operator/v1helpers"

corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes/fake"
ktesting "k8s.io/client-go/testing"
clocktesting "k8s.io/utils/clock/testing"

operatorv1 "github.com/openshift/api/operator/v1"

"github.com/openshift/library-go/pkg/operator/condition"
"github.com/openshift/library-go/pkg/operator/events"
"github.com/openshift/library-go/pkg/operator/events/eventstesting"
"github.com/openshift/library-go/pkg/operator/v1helpers"
)

func TestSyncSecret(t *testing.T) {
Expand Down Expand Up @@ -368,3 +367,75 @@ func TestServeHTTP(t *testing.T) {
t.Errorf("Expected:%+v\n Got: %+v\n", expected, response)
}
}

func TestWithConditionPrefix(t *testing.T) {
tests := []struct {
name string
customConditionPrefix string
expectedCondition string
}{
{
name: "Without ConditionPrefix",
expectedCondition: condition.ResourceSyncControllerDegradedConditionType,
},
{
name: "WithConditionPrefix",
customConditionPrefix: "RecoveryPod",
expectedCondition: fmt.Sprintf("RecoveryPod%s", condition.ResourceSyncControllerDegradedConditionType),
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
informerFactory := informers.NewSharedInformerFactoryWithOptions(nil, 1*time.Minute, informers.WithNamespace("foo"))
fakeStaticPodOperatorClient := v1helpers.NewFakeOperatorClient(
&operatorv1.OperatorSpec{
ManagementState: operatorv1.Managed,
},
&operatorv1.OperatorStatus{},
nil,
)
eventRecorder := eventstesting.NewTestingEventRecorder(t)

c := NewResourceSyncController(
"testing-instance",
fakeStaticPodOperatorClient,
v1helpers.NewFakeKubeInformersForNamespaces(map[string]informers.SharedInformerFactory{
"foo": informerFactory,
}),
nil,
nil,
eventRecorder,
)
if len(test.customConditionPrefix) > 0 {
c.WithConditionPrefix(test.customConditionPrefix)
}

if err := c.Sync(context.TODO(), c.syncCtx); err != nil {
t.Fatal(err)
}
_, status, _, err := fakeStaticPodOperatorClient.GetOperatorState()
if err != nil {
t.Fatal(err)
}
if !v1helpers.IsOperatorConditionFalse(status.Conditions, test.expectedCondition) {
t.Errorf("expected resource sync condition: %q to NOT be degraded", test.expectedCondition)
}

if err = c.SyncSecretConditionally(ResourceLocation{Namespace: "foo", Name: "secret"}, ResourceLocation{Namespace: "foo", Name: "secret2"}, func() (bool, error) {
return false, fmt.Errorf("nasty err")
}); err != nil {
t.Fatal(err)
}
if err = c.Sync(context.TODO(), c.syncCtx); err != nil {
t.Fatal(err)
}
_, status, _, err = fakeStaticPodOperatorClient.GetOperatorState()
if err != nil {
t.Fatal(err)
}
if !v1helpers.IsOperatorConditionTrue(status.Conditions, test.expectedCondition) {
t.Errorf("expected resource sync condition: %q to be degraded", test.expectedCondition)
}
})
}
}