Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fixup! ✨ Plumb the Extension API
Browse files Browse the repository at this point in the history
Signed-off-by: Todd Short <[email protected]>
tmshort committed Feb 14, 2024

Verified

This commit was signed with the committer’s verified signature.
tmshort Todd Short
1 parent 8e39443 commit 9d5daca
Showing 9 changed files with 66 additions and 84 deletions.
4 changes: 0 additions & 4 deletions api/v1alpha1/clusterextension_types.go
Original file line number Diff line number Diff line change
@@ -173,7 +173,3 @@ func (r *ClusterExtension) GetPackageSpec() *ExtensionSourcePackage {
func (r *ClusterExtension) GetUID() types.UID {
return r.ObjectMeta.GetUID()
}

func (r *ClusterExtension) GetUpgradeConstraintPolicy() UpgradeConstraintPolicy {
return r.Spec.UpgradeConstraintPolicy
}
7 changes: 0 additions & 7 deletions api/v1alpha1/extension_types.go
Original file line number Diff line number Diff line change
@@ -132,10 +132,3 @@ func (r *Extension) GetPackageSpec() *ExtensionSourcePackage {
func (r *Extension) GetUID() types.UID {
return r.ObjectMeta.GetUID()
}

func (r *Extension) GetUpgradeConstraintPolicy() UpgradeConstraintPolicy {
if r.Spec.Source.Package != nil {
return r.Spec.Source.Package.UpgradeConstraintPolicy
}
return ""
}
19 changes: 9 additions & 10 deletions cmd/manager/main.go
Original file line number Diff line number Diff line change
@@ -123,16 +123,15 @@ func main() {
setupLog.Error(err, "unable to create controller", "controller", "ClusterExtension")
os.Exit(1)
}
if features.OperatorControllerFeatureGate.Enabled(features.EnableExtensionAPI) {
if err = (&controllers.ExtensionReconciler{
Client: cl,
BundleProvider: catalogClient,
Scheme: mgr.GetScheme(),
Resolver: resolver,
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "Extension")
os.Exit(1)
}

if err = (&controllers.ExtensionReconciler{
Client: cl,
BundleProvider: catalogClient,
Scheme: mgr.GetScheme(),
Resolver: resolver,
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "Extension")
os.Exit(1)
}
//+kubebuilder:scaffold:builder

13 changes: 0 additions & 13 deletions config/rbac/extension_editor_role.yaml
Original file line number Diff line number Diff line change
@@ -2,13 +2,6 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/name: clusterrole
app.kubernetes.io/instance: extension-editor-role
app.kubernetes.io/component: rbac
app.kubernetes.io/created-by: operator-controller
app.kubernetes.io/part-of: operator-controller
app.kubernetes.io/managed-by: kustomize
name: extension-editor-role
rules:
- apiGroups:
@@ -23,9 +16,3 @@ rules:
- patch
- update
- watch
- apiGroups:
- olm.operatorframework.io
resources:
- extensions/status
verbs:
- get
13 changes: 0 additions & 13 deletions config/rbac/extension_viewer_role.yaml
Original file line number Diff line number Diff line change
@@ -2,13 +2,6 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/name: clusterrole
app.kubernetes.io/instance: extension-viewer-role
app.kubernetes.io/component: rbac
app.kubernetes.io/created-by: operator-controller
app.kubernetes.io/part-of: operator-controller
app.kubernetes.io/managed-by: kustomize
name: extension-viewer-role
rules:
- apiGroups:
@@ -19,9 +12,3 @@ rules:
- get
- list
- watch
- apiGroups:
- olm.operatorframework.io
resources:
- extensions/status
verbs:
- get
6 changes: 0 additions & 6 deletions config/samples/olm_v1alpha1_extension.yaml
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
apiVersion: olm.operatorframework.io/v1alpha1
kind: Extension
metadata:
labels:
app.kubernetes.io/name: extension
app.kubernetes.io/instance: extension-sample
app.kubernetes.io/part-of: operator-controller
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/created-by: operator-controller
name: extension-sample
namespace: extension-namespace
spec:
60 changes: 31 additions & 29 deletions internal/controllers/extension_controller.go
Original file line number Diff line number Diff line change
@@ -21,20 +21,18 @@ import (

"k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
utilerrors "k8s.io/apimachinery/pkg/util/errors"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/reconcile"

"github.com/go-logr/logr"
catalogd "github.com/operator-framework/catalogd/api/core/v1alpha1"
"github.com/operator-framework/deppy/pkg/deppy/solver"

ocv1alpha1 "github.com/operator-framework/operator-controller/api/v1alpha1"
"github.com/operator-framework/operator-controller/internal/controllers/validators"
"github.com/operator-framework/operator-controller/pkg/features"
)

// ExtensionReconciler reconciles a Extension object
@@ -102,9 +100,29 @@ func (*ExtensionReconciler) checkForUnexpectedFieldChange(a, b ocv1alpha1.Extens
// to return different results (e.g. requeue).
//
//nolint:unparam
func (r *ExtensionReconciler) reconcile(_ context.Context, ext *ocv1alpha1.Extension) (ctrl.Result, error) {
func (r *ExtensionReconciler) reconcile(ctx context.Context, ext *ocv1alpha1.Extension) (ctrl.Result, error) {
l := log.FromContext(ctx).WithName("extension-controller")

// Don't do anything if feature gated
if !features.OperatorControllerFeatureGate.Enabled(features.EnableExtensionAPI) {
l.Info("extension feature is gated", "name", ext.GetName(), "namespace", ext.GetNamespace())

// Set the TypeInstalled condition to Unknown to indicate that the resolution
// hasn't been attempted yet, due to the spec being invalid.
ext.Status.InstalledBundleResource = ""
setInstalledStatusConditionUnknown(&ext.Status.Conditions, "extension feature is disabled", ext.GetGeneration())
// Set the TypeResolved condition to Unknown to indicate that the resolution
// hasn't been attempted yet, due to the spec being invalid.
ext.Status.ResolvedBundleResource = ""
setResolvedStatusConditionUnknown(&ext.Status.Conditions, "extension feature is disabled", ext.GetGeneration())

setDeprecationStatusesUnknown(&ext.Status.Conditions, "extension feature is disabled", ext.GetGeneration())
return ctrl.Result{}, nil
}

// Don't do anything if Paused
if ext.Spec.Managed == ocv1alpha1.ManagedStatePaused {
l.Info("resource is paused", "name", ext.GetName(), "namespace", ext.GetNamespace())
return ctrl.Result{}, nil
}

@@ -146,32 +164,16 @@ func (r *ExtensionReconciler) reconcile(_ context.Context, ext *ocv1alpha1.Exten
// SetupWithManager sets up the controller with the Manager.
func (r *ExtensionReconciler) SetupWithManager(mgr ctrl.Manager) error {
// TODO: Add watch for kapp-controller resources

// When feature-gated, don't watch catalogs.
if !features.OperatorControllerFeatureGate.Enabled(features.EnableExtensionAPI) {
return ctrl.NewControllerManagedBy(mgr).
For(&ocv1alpha1.Extension{}).
Complete(r)
}

return ctrl.NewControllerManagedBy(mgr).
For(&ocv1alpha1.Extension{}).
Watches(&catalogd.Catalog{},
handler.EnqueueRequestsFromMapFunc(extensionRequestsForCatalog(mgr.GetClient(), mgr.GetLogger()))).
Watches(&catalogd.Catalog{}, &handler.EnqueueRequestForObject{}).
Complete(r)
}

// Generate reconcile requests for all extensions affected by a catalog change
func extensionRequestsForCatalog(c client.Reader, logger logr.Logger) handler.MapFunc {
return func(ctx context.Context, _ client.Object) []reconcile.Request {
// no way of associating an extension to a catalog so create reconcile requests for everything
extensions := ocv1alpha1.ExtensionList{}
err := c.List(ctx, &extensions)
if err != nil {
logger.Error(err, "unable to enqueue extensions for catalog reconcile")
return nil
}
var requests []reconcile.Request
for _, ext := range extensions.Items {
requests = append(requests, reconcile.Request{
NamespacedName: types.NamespacedName{
Namespace: ext.GetNamespace(),
Name: ext.GetName(),
},
})
}
return requests
}
}
27 changes: 26 additions & 1 deletion internal/controllers/extension_controller_test.go
Original file line number Diff line number Diff line change
@@ -12,12 +12,14 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/rand"
featuregatetesting "k8s.io/component-base/featuregate/testing"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/fake"

ocv1alpha1 "github.com/operator-framework/operator-controller/api/v1alpha1"
"github.com/operator-framework/operator-controller/internal/conditionsets"
"github.com/operator-framework/operator-controller/pkg/features"
)

// Describe: Extension Controller Test
@@ -108,19 +110,42 @@ func TestExtensionBadResources(t *testing.T) {
require.Equal(t, ctrl.Result{}, res)
require.NoError(t, err)

require.NoError(t, cl.Get(ctx, name, ext), fmt.Sprintf("Get failed on %q", e.ObjectMeta.GetName()))
cond := apimeta.FindStatusCondition(ext.Status.Conditions, ocv1alpha1.TypeResolved)
require.NotNil(t, cond, fmt.Sprintf("Get condition failed on %q", ext.ObjectMeta.GetName()))
require.Equal(t, metav1.ConditionUnknown, cond.Status, fmt.Sprintf("Get status check failed on %q", ext.ObjectMeta.GetName()))
require.Equal(t, ocv1alpha1.ReasonResolutionUnknown, cond.Reason, fmt.Sprintf("Get status reason failed on %q", ext.ObjectMeta.GetName()))
require.Equal(t, "extension feature is disabled", cond.Message)
require.NoError(t, client.IgnoreNotFound(cl.Delete(ctx, ext)))
}

for _, e := range invalidExtensions {
resetFeatureGate := featuregatetesting.SetFeatureGateDuringTest(t, features.OperatorControllerFeatureGate, features.EnableExtensionAPI, true)
ext := e.DeepCopy()
require.NoError(t, cl.Create(ctx, ext), fmt.Sprintf("Create failed on %q", e.GetObjectMeta().GetName()))
name := types.NamespacedName{Name: e.GetObjectMeta().GetName(), Namespace: e.GetObjectMeta().GetNamespace()}

cl, reconciler := newClientAndExtensionReconciler(t)
res, err := reconciler.Reconcile(ctx, ctrl.Request{NamespacedName: name})
require.Equal(t, ctrl.Result{}, res)
require.NoError(t, err)

require.NoError(t, cl.Get(ctx, name, ext), fmt.Sprintf("Get failed on %q", e.ObjectMeta.GetName()))
cond := apimeta.FindStatusCondition(ext.Status.Conditions, ocv1alpha1.TypeResolved)
require.NotNil(t, cond, fmt.Sprintf("Get condition failed on %q", ext.ObjectMeta.GetName()))
require.Equal(t, metav1.ConditionUnknown, cond.Status, fmt.Sprintf("Get status check failed on %q", ext.ObjectMeta.GetName()))
require.Equal(t, ocv1alpha1.ReasonResolutionUnknown, cond.Reason, fmt.Sprintf("Get status reason failed on %q", ext.ObjectMeta.GetName()))
require.Equal(t, "validation has not been attempted as spec is invalid", cond.Message)

resetFeatureGate()
}

require.NoError(t, cl.DeleteAllOf(ctx, &ocv1alpha1.Extension{}, client.InNamespace(extKey.Namespace)))
require.NoError(t, cl.Delete(ctx, namespace))
}

func TestExtensionInvalidSemverPastRegex(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, features.OperatorControllerFeatureGate, features.EnableExtensionAPI, true)()
cl, reconciler := newClientAndExtensionReconciler(t)
ctx := context.Background()
t.Log("When an invalid semver is provided that bypasses the regex validation")
@@ -135,7 +160,7 @@ func TestExtensionInvalidSemverPastRegex(t *testing.T) {
}
require.NoError(t, cl.Create(ctx, namespace))

t.Log("By injecting creating a client with the bad clusterextension CR")
t.Log("By injecting creating a client with the bad extension CR")
pkgName := fmt.Sprintf("exists-%s", rand.String(6))
extension := &ocv1alpha1.Extension{
ObjectMeta: metav1.ObjectMeta{Name: extKey.Name, Namespace: extKey.Namespace},
1 change: 0 additions & 1 deletion internal/internal.go
Original file line number Diff line number Diff line change
@@ -24,7 +24,6 @@ import (

type ExtensionInterface interface {
GetPackageSpec() *ocv1alpha1.ExtensionSourcePackage
GetUpgradeConstraintPolicy() ocv1alpha1.UpgradeConstraintPolicy
GetUID() types.UID
}

0 comments on commit 9d5daca

Please sign in to comment.