diff --git a/bundle/manifests/opendatahub-operator.clusterserviceversion.yaml b/bundle/manifests/opendatahub-operator.clusterserviceversion.yaml index 752e41221e2..45f22c8640c 100644 --- a/bundle/manifests/opendatahub-operator.clusterserviceversion.yaml +++ b/bundle/manifests/opendatahub-operator.clusterserviceversion.yaml @@ -106,7 +106,7 @@ metadata: categories: AI/Machine Learning, Big Data certified: "False" containerImage: quay.io/opendatahub/opendatahub-operator:v2.21.0 - createdAt: "2024-11-22T19:16:14Z" + createdAt: "2024-12-16T13:35:31Z" olm.skipRange: '>=1.0.0 <2.21.0' operators.operatorframework.io/builder: operator-sdk-v1.31.0 operators.operatorframework.io/internal-objects: '["featuretrackers.features.opendatahub.io", @@ -649,6 +649,7 @@ spec: verbs: - create - delete + - deletecollection - get - list - patch diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index e259f476bad..ae000c13f5b 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -389,6 +389,7 @@ rules: verbs: - create - delete + - deletecollection - get - list - patch diff --git a/controllers/datasciencecluster/datasciencecluster_controller.go b/controllers/datasciencecluster/datasciencecluster_controller.go index da9351f97d1..73cd9f911ae 100644 --- a/controllers/datasciencecluster/datasciencecluster_controller.go +++ b/controllers/datasciencecluster/datasciencecluster_controller.go @@ -28,7 +28,6 @@ import ( corev1 "k8s.io/api/core/v1" k8serr "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/tools/record" @@ -36,9 +35,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "sigs.k8s.io/controller-runtime/pkg/event" logf "sigs.k8s.io/controller-runtime/pkg/log" - "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" "github.com/opendatahub-io/opendatahub-operator/v2/apis/common" @@ -52,7 +49,6 @@ import ( "github.com/opendatahub-io/opendatahub-operator/v2/pkg/controller/handlers" "github.com/opendatahub-io/opendatahub-operator/v2/pkg/controller/predicates" "github.com/opendatahub-io/opendatahub-operator/v2/pkg/controller/predicates/dependent" - "github.com/opendatahub-io/opendatahub-operator/v2/pkg/upgrade" ) // DataScienceClusterReconciler reconciles a DataScienceCluster object. @@ -76,53 +72,24 @@ const ( func (r *DataScienceClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { log := logf.FromContext(ctx).WithName("DataScienceCluster") log.Info("Reconciling DataScienceCluster resources", "Request.Name", req.Name) - instance := &dscv1.DataScienceCluster{} err := r.Client.Get(ctx, req.NamespacedName, instance) switch { case k8serr.IsNotFound(err): - // Request object not found, could have been deleted after reconcile request. - // Owned objects are automatically garbage collected. - // For additional cleanup logic use operatorUninstall function. - // Return and don't requeue - if upgrade.HasDeleteConfigMap(ctx, r.Client) { - if uninstallErr := upgrade.OperatorUninstall(ctx, r.Client, cluster.GetRelease().Name); uninstallErr != nil { - return ctrl.Result{}, fmt.Errorf("error while operator uninstall: %w", uninstallErr) - } - } - return ctrl.Result{}, nil case err != nil: return ctrl.Result{}, err } - // We don't need finalizer anymore, remove it if present to handle the - // upgrade case if controllerutil.RemoveFinalizer(instance, finalizerName) { if err := r.Client.Update(ctx, instance); err != nil { return ctrl.Result{}, err } } - // If DSC CR exist and deletion CM exist - // delete DSC CR and let reconcile requeue - if upgrade.HasDeleteConfigMap(ctx, r.Client) { - err := r.Client.Delete(ctx, instance, client.PropagationPolicy(metav1.DeletePropagationForeground)) - if err != nil { - return ctrl.Result{}, client.IgnoreNotFound(err) - } - - return ctrl.Result{}, nil - } - if !instance.ObjectMeta.DeletionTimestamp.IsZero() { log.Info("Finalization DataScienceCluster start deleting instance", "name", instance.Name) - - if upgrade.HasDeleteConfigMap(ctx, r.Client) { - return ctrl.Result{Requeue: true}, nil - } - return ctrl.Result{}, nil } @@ -327,53 +294,9 @@ func (r *DataScienceClusterReconciler) SetupWithManager(_ context.Context, mgr c Watches( &dsciv1.DSCInitialization{}, handlers.Fn(r.watchDataScienceClusters)). - Watches( - &corev1.ConfigMap{}, - handlers.Fn(r.watchDataScienceClusters), - builder.WithPredicates(r.filterDeleteConfigMap())). Complete(r) } -func (r *DataScienceClusterReconciler) filterDeleteConfigMap() predicate.Funcs { - filter := func(obj client.Object) bool { - cm, ok := obj.(*corev1.ConfigMap) - if !ok { - return false - } - - // Trigger reconcile function when uninstall configmap is created - operatorNs, err := cluster.GetOperatorNamespace() - if err != nil { - return false - } - - if cm.Namespace != operatorNs { - return false - } - - if cm.Labels[upgrade.DeleteConfigMapLabel] != "true" { - return false - } - - return true - } - - return predicate.Funcs{ - CreateFunc: func(e event.CreateEvent) bool { - return filter(e.Object) - }, - UpdateFunc: func(e event.UpdateEvent) bool { - return filter(e.ObjectNew) - }, - DeleteFunc: func(e event.DeleteEvent) bool { - return false - }, - GenericFunc: func(e event.GenericEvent) bool { - return false - }, - } -} - func (r *DataScienceClusterReconciler) watchDataScienceClusters(ctx context.Context, _ client.Object) []reconcile.Request { instanceList := &dscv1.DataScienceClusterList{} err := r.Client.List(ctx, instanceList) diff --git a/controllers/datasciencecluster/kubebuilder_rbac.go b/controllers/datasciencecluster/kubebuilder_rbac.go index e9a31405cc4..3cfcaf14c0f 100644 --- a/controllers/datasciencecluster/kubebuilder_rbac.go +++ b/controllers/datasciencecluster/kubebuilder_rbac.go @@ -2,7 +2,7 @@ package datasciencecluster // +kubebuilder:rbac:groups="datasciencecluster.opendatahub.io",resources=datascienceclusters/status,verbs=get;update;patch // +kubebuilder:rbac:groups="datasciencecluster.opendatahub.io",resources=datascienceclusters/finalizers,verbs=update;patch -// +kubebuilder:rbac:groups="datasciencecluster.opendatahub.io",resources=datascienceclusters,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups="datasciencecluster.opendatahub.io",resources=datascienceclusters,verbs=get;list;watch;create;update;patch;delete;deletecollection // +kubebuilder:rbac:groups="authentication.k8s.io",resources=tokenreviews,verbs=create;get // +kubebuilder:rbac:groups="authorization.k8s.io",resources=subjectaccessreviews,verbs=create;get diff --git a/controllers/setupcontroller/setup_controller.go b/controllers/setupcontroller/setup_controller.go new file mode 100644 index 00000000000..767e7e1b30a --- /dev/null +++ b/controllers/setupcontroller/setup_controller.go @@ -0,0 +1,83 @@ +package setupcontroller + +import ( + "context" + "fmt" + + corev1 "k8s.io/api/core/v1" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/builder" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/event" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/predicate" + + "github.com/opendatahub-io/opendatahub-operator/v2/pkg/cluster" + odhClient "github.com/opendatahub-io/opendatahub-operator/v2/pkg/controller/client" + "github.com/opendatahub-io/opendatahub-operator/v2/pkg/upgrade" +) + +type SetupControllerReconciler struct { + *odhClient.Client +} + +func (r *SetupControllerReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + log := logf.FromContext(ctx).WithName("SetupController") + log.Info("Reconciling setup controller") + + if !upgrade.HasDeleteConfigMap(ctx, r.Client) { + return ctrl.Result{}, nil + } + + if err := upgrade.OperatorUninstall(ctx, r.Client, cluster.GetRelease().Name); err != nil { + return ctrl.Result{}, fmt.Errorf("operator uninstall failed : %w", err) + } + + return ctrl.Result{}, nil +} + +func (r *SetupControllerReconciler) SetupWithManager(mgr ctrl.Manager) error { + operatorNs, err := cluster.GetOperatorNamespace() + + if err != nil { + return fmt.Errorf("failed to get operator namespace: %w", err) + } + return ctrl.NewControllerManagedBy(mgr). + For(&corev1.ConfigMap{}, builder.WithPredicates(r.filterDeleteConfigMap(operatorNs))). + Complete(r) +} + +func (r *SetupControllerReconciler) filterDeleteConfigMap(operatorNs string) predicate.Funcs { + filter := func(obj client.Object) bool { + cm, ok := obj.(*corev1.ConfigMap) + + if !ok { + return false + } + + if cm.Namespace != operatorNs { + return false + } + + if cm.Labels[upgrade.DeleteConfigMapLabel] != "true" { + return false + } + + return true + } + + return predicate.Funcs{ + CreateFunc: func(e event.CreateEvent) bool { + return filter(e.Object) + }, + UpdateFunc: func(e event.UpdateEvent) bool { + return filter(e.ObjectNew) + }, + DeleteFunc: func(e event.DeleteEvent) bool { + return false + }, + GenericFunc: func(e event.GenericEvent) bool { + return false + }, + } +} diff --git a/main.go b/main.go index c1ea5274e2c..fcbe3a0a1a0 100644 --- a/main.go +++ b/main.go @@ -69,6 +69,7 @@ import ( dscctrl "github.com/opendatahub-io/opendatahub-operator/v2/controllers/datasciencecluster" dscictrl "github.com/opendatahub-io/opendatahub-operator/v2/controllers/dscinitialization" "github.com/opendatahub-io/opendatahub-operator/v2/controllers/secretgenerator" + "github.com/opendatahub-io/opendatahub-operator/v2/controllers/setupcontroller" "github.com/opendatahub-io/opendatahub-operator/v2/controllers/webhook" "github.com/opendatahub-io/opendatahub-operator/v2/pkg/cluster" "github.com/opendatahub-io/opendatahub-operator/v2/pkg/cluster/gvk" @@ -301,6 +302,13 @@ func main() { //nolint:funlen,maintidx os.Exit(1) } + if err = (&setupcontroller.SetupControllerReconciler{ + Client: oc, + }).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "SetupController") + os.Exit(1) + } + if err = (&secretgenerator.SecretGeneratorReconciler{ Client: oc, Scheme: mgr.GetScheme(), diff --git a/pkg/upgrade/uninstallation.go b/pkg/upgrade/uninstallation.go index 4701866285a..aef43edc053 100644 --- a/pkg/upgrade/uninstallation.go +++ b/pkg/upgrade/uninstallation.go @@ -8,10 +8,12 @@ import ( "github.com/hashicorp/go-multierror" corev1 "k8s.io/api/core/v1" k8serr "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" logf "sigs.k8s.io/controller-runtime/pkg/log" + dscv1 "github.com/opendatahub-io/opendatahub-operator/v2/apis/datasciencecluster/v1" dsciv1 "github.com/opendatahub-io/opendatahub-operator/v2/apis/dscinitialization/v1" "github.com/opendatahub-io/opendatahub-operator/v2/pkg/cluster" "github.com/opendatahub-io/opendatahub-operator/v2/pkg/metadata/labels" @@ -27,6 +29,11 @@ const ( // This includes DSCI, namespace created by operator (but not workbench or MR's), subscription and CSV. func OperatorUninstall(ctx context.Context, cli client.Client, platform cluster.Platform) error { log := logf.FromContext(ctx) + + if err := removeDSC(ctx, cli); err != nil { + return err + } + if err := removeDSCInitialization(ctx, cli); err != nil { return err } @@ -102,6 +109,16 @@ func removeDSCInitialization(ctx context.Context, cli client.Client) error { return multiErr.ErrorOrNil() } +func removeDSC(ctx context.Context, cli client.Client) error { + instance := &dscv1.DataScienceCluster{} + + if err := cli.DeleteAllOf(ctx, instance, client.PropagationPolicy(metav1.DeletePropagationForeground)); err != nil { + return fmt.Errorf("failure deleting DSC: %w", err) + } + + return nil +} + // HasDeleteConfigMap returns true if delete configMap is added to the operator namespace by managed-tenants repo. // It returns false in all other cases. func HasDeleteConfigMap(ctx context.Context, c client.Client) bool {