diff --git a/.gitignore b/.gitignore index 3338a0fb..3be6f6f2 100644 --- a/.gitignore +++ b/.gitignore @@ -38,5 +38,4 @@ test/function_tests/results/* test/mock-component-image/bin test/mock-component-image/scripts/_pycache_ -hack/bundle-automation/tmp/ - +hack/bundle-automation/tmp/ \ No newline at end of file diff --git a/api/v1/multiclusterengine_types.go b/api/v1/multiclusterengine_types.go index 0b61d9f3..1ab7f658 100644 --- a/api/v1/multiclusterengine_types.go +++ b/api/v1/multiclusterengine_types.go @@ -250,6 +250,24 @@ type MultiClusterEngineList struct { Items []MultiClusterEngine `json:"items"` } +// +kubebuilder:object:root=true +// +operator-sdk:csv:customresourcedefinitions:displayName="InternalEngineComponent" +type InternalEngineComponent struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + Spec InternalEngineComponentSpec `json:"spec,omitempty"` +} + +// +kubebuilder:object:root=true +type InternalEngineComponentList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []InternalEngineComponent `json:"items"` +} + +type InternalEngineComponentSpec struct{} + func init() { SchemeBuilder.Register(&MultiClusterEngine{}, &MultiClusterEngineList{}) + SchemeBuilder.Register(&InternalEngineComponent{}, &InternalEngineComponentList{}) } diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go index b1182987..08c43f1e 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -1,5 +1,4 @@ //go:build !ignore_autogenerated -// +build !ignore_autogenerated /* Copyright 2021. @@ -58,6 +57,79 @@ func (in *ComponentConfig) DeepCopy() *ComponentConfig { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InternalEngineComponent) DeepCopyInto(out *InternalEngineComponent) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InternalEngineComponent. +func (in *InternalEngineComponent) DeepCopy() *InternalEngineComponent { + if in == nil { + return nil + } + out := new(InternalEngineComponent) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *InternalEngineComponent) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InternalEngineComponentList) DeepCopyInto(out *InternalEngineComponentList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]InternalEngineComponent, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InternalEngineComponentList. +func (in *InternalEngineComponentList) DeepCopy() *InternalEngineComponentList { + if in == nil { + return nil + } + out := new(InternalEngineComponentList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *InternalEngineComponentList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InternalEngineComponentSpec) DeepCopyInto(out *InternalEngineComponentSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InternalEngineComponentSpec. +func (in *InternalEngineComponentSpec) DeepCopy() *InternalEngineComponentSpec { + if in == nil { + return nil + } + out := new(InternalEngineComponentSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MultiClusterEngine) DeepCopyInto(out *MultiClusterEngine) { *out = *in diff --git a/bundle/manifests/multicluster-engine.clusterserviceversion.yaml b/bundle/manifests/multicluster-engine.clusterserviceversion.yaml index 8b84da8b..168e25de 100644 --- a/bundle/manifests/multicluster-engine.clusterserviceversion.yaml +++ b/bundle/manifests/multicluster-engine.clusterserviceversion.yaml @@ -79,6 +79,17 @@ spec: spec: clusterPermissions: - rules: + - apiGroups: + - multicluster.openshift.io + resources: + - internalenginecomponents + verbs: + - create + - get + - delete + - patch + - list + - watch - apiGroups: - "" resources: diff --git a/config/crd/bases/multicluster.openshift.io_internalenginecomponents.yaml b/config/crd/bases/multicluster.openshift.io_internalenginecomponents.yaml new file mode 100644 index 00000000..b044005d --- /dev/null +++ b/config/crd/bases/multicluster.openshift.io_internalenginecomponents.yaml @@ -0,0 +1,42 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.15.0 + name: internalenginecomponents.multicluster.openshift.io +spec: + group: multicluster.openshift.io + names: + kind: InternalEngineComponent + listKind: InternalEngineComponentList + plural: internalenginecomponents + singular: internalenginecomponent + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + type: object + type: object + served: true + storage: true diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 03f6db46..0c97d84c 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -2041,6 +2041,17 @@ rules: - patch - update - watch +- apiGroups: + - multicluster.openshift.io + resources: + - internalenginecomponents + verbs: + - create + - delete + - get + - list + - patch + - watch - apiGroups: - multicluster.openshift.io resources: diff --git a/controllers/backplaneconfig_controller.go b/controllers/backplaneconfig_controller.go index 365c3578..e3b8b5ef 100644 --- a/controllers/backplaneconfig_controller.go +++ b/controllers/backplaneconfig_controller.go @@ -152,6 +152,9 @@ var ( //+kubebuilder:rbac:groups="",resources=serviceaccounts/token,verbs=create //+kubebuilder:rbac:groups=authentication.k8s.io,resources=tokenrequests,verbs=create +// InternalEngineComponent +// +kubebuilder:rbac:groups="multicluster.openshift.io",resources="internalenginecomponents",verbs=create;get;delete;patch;list;watch + // Reconcile is part of the main kubernetes reconciliation loop which aims to // move the current state of the cluster closer to the desired state. func (r *MultiClusterEngineReconciler) Reconcile(ctx context.Context, req ctrl.Request) (retRes ctrl.Result, retErr error) { @@ -793,6 +796,57 @@ func (r *MultiClusterEngineReconciler) DeployAlwaysSubcomponents(ctx context.Con return ctrl.Result{}, nil } +func (r *MultiClusterEngineReconciler) ensureInternalEngineComponent( + ctx context.Context, + backplaneConfig *backplanev1.MultiClusterEngine, + component string) (ctrl.Result, error) { + + componentCR := &backplanev1.InternalEngineComponent{ + TypeMeta: metav1.TypeMeta{ + APIVersion: backplanev1.GroupVersion.String(), + Kind: "InternalEngineComponent", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: component, + Namespace: backplaneConfig.Spec.TargetNamespace, + }, + } + + force := true + err := r.Client.Patch(ctx, componentCR, client.Apply, &client.PatchOptions{Force: &force, FieldManager: "backplane-operator"}) + if err != nil { + r.Log.Info(fmt.Sprintf("error applying %s CR. Error: %s", component, err.Error())) + return ctrl.Result{Requeue: true}, err + } + + return ctrl.Result{}, nil +} + +func (r *MultiClusterEngineReconciler) ensureNoInternalEngineComponent( + ctx context.Context, + backplaneConfig *backplanev1.MultiClusterEngine, + component string) (ctrl.Result, error) { + + comp := &backplanev1.InternalEngineComponent{} + err := r.Client.Get(ctx, types.NamespacedName{Name: component, Namespace: backplaneConfig.Spec.TargetNamespace}, comp) + if apierrors.IsNotFound(err) { + return ctrl.Result{}, nil + } + if err != nil { + log.Error(err, fmt.Sprintf("Error getting InternalEngineComponent. Error: %v: Component was: %v", err, comp)) + return reconcile.Result{Requeue: true}, err + } + + log.Info(fmt.Sprintf("Ensuring No InternalEngineComponent: %s", component)) + err = r.Client.Delete(ctx, comp) + if err != nil && !apierrors.IsNotFound(err) { + log.Error(err, fmt.Sprintf("Error deleting InternalEngineComponent. Error: %v", err)) + return reconcile.Result{Requeue: true}, err + } + + return ctrl.Result{}, nil +} + func (r *MultiClusterEngineReconciler) ensureToggleableComponents(ctx context.Context, backplaneConfig *backplanev1.MultiClusterEngine) (ctrl.Result, error) { @@ -800,7 +854,15 @@ func (r *MultiClusterEngineReconciler) ensureToggleableComponents(ctx context.Co requeue := false if backplaneConfig.Enabled(backplanev1.ManagedServiceAccount) { - result, err := r.ensureManagedServiceAccount(ctx, backplaneConfig) + + result, err := r.ensureInternalEngineComponent(ctx, backplaneConfig, backplanev1.ManagedServiceAccount) + if result != (ctrl.Result{}) { + requeue = true + } + if err != nil { + errs[backplanev1.ManagedServiceAccount+"InternalEngineComponent"] = err + } + result, err = r.ensureManagedServiceAccount(ctx, backplaneConfig) if result != (ctrl.Result{}) { requeue = true } @@ -808,7 +870,14 @@ func (r *MultiClusterEngineReconciler) ensureToggleableComponents(ctx context.Co errs[backplanev1.ManagedServiceAccount] = err } } else { - result, err := r.ensureNoManagedServiceAccount(ctx, backplaneConfig) + result, err := r.ensureNoInternalEngineComponent(ctx, backplaneConfig, backplanev1.ManagedServiceAccount) + if result != (ctrl.Result{}) { + requeue = true + } + if err != nil { + errs[backplanev1.ManagedServiceAccount+"InternalEngineComponent"] = err + } + result, err = r.ensureNoManagedServiceAccount(ctx, backplaneConfig) if result != (ctrl.Result{}) { requeue = true } @@ -818,7 +887,14 @@ func (r *MultiClusterEngineReconciler) ensureToggleableComponents(ctx context.Co } if backplaneConfig.Enabled(backplanev1.ImageBasedInstallOperator) { - result, err := r.ensureImageBasedInstallOperator(ctx, backplaneConfig) + result, err := r.ensureInternalEngineComponent(ctx, backplaneConfig, backplanev1.ImageBasedInstallOperator) + if result != (ctrl.Result{}) { + requeue = true + } + if err != nil { + errs[backplanev1.ImageBasedInstallOperator+"InternalEngineComponent"] = err + } + result, err = r.ensureImageBasedInstallOperator(ctx, backplaneConfig) if result != (ctrl.Result{}) { requeue = true } @@ -826,7 +902,14 @@ func (r *MultiClusterEngineReconciler) ensureToggleableComponents(ctx context.Co errs[backplanev1.ImageBasedInstallOperator] = err } } else { - result, err := r.ensureNoImageBasedInstallOperator(ctx, backplaneConfig) + result, err := r.ensureNoInternalEngineComponent(ctx, backplaneConfig, backplanev1.ImageBasedInstallOperator) + if result != (ctrl.Result{}) { + requeue = true + } + if err != nil { + errs[backplanev1.ImageBasedInstallOperator+"InternalEngineComponent"] = err + } + result, err = r.ensureNoImageBasedInstallOperator(ctx, backplaneConfig) if result != (ctrl.Result{}) { requeue = true } @@ -836,7 +919,14 @@ func (r *MultiClusterEngineReconciler) ensureToggleableComponents(ctx context.Co } if backplaneConfig.Enabled(backplanev1.HyperShift) { - result, err := r.ensureHyperShift(ctx, backplaneConfig) + result, err := r.ensureInternalEngineComponent(ctx, backplaneConfig, backplanev1.HyperShift) + if result != (ctrl.Result{}) { + requeue = true + } + if err != nil { + errs[backplanev1.HyperShift+"InternalEngineComponent"] = err + } + result, err = r.ensureHyperShift(ctx, backplaneConfig) if result != (ctrl.Result{}) { requeue = true } @@ -844,7 +934,14 @@ func (r *MultiClusterEngineReconciler) ensureToggleableComponents(ctx context.Co errs[backplanev1.HyperShift] = err } } else { - result, err := r.ensureNoHyperShift(ctx, backplaneConfig) + result, err := r.ensureNoInternalEngineComponent(ctx, backplaneConfig, backplanev1.HyperShift) + if result != (ctrl.Result{}) { + requeue = true + } + if err != nil { + errs[backplanev1.HyperShift+"InternalEngineComponent"] = err + } + result, err = r.ensureNoHyperShift(ctx, backplaneConfig) if result != (ctrl.Result{}) { requeue = true } @@ -866,7 +963,14 @@ func (r *MultiClusterEngineReconciler) ensureToggleableComponents(ctx context.Co } if backplaneConfig.Enabled(backplanev1.ConsoleMCE) && ocpConsole { - result, err := r.ensureConsoleMCE(ctx, backplaneConfig) + result, err := r.ensureInternalEngineComponent(ctx, backplaneConfig, backplanev1.ConsoleMCE) + if result != (ctrl.Result{}) { + requeue = true + } + if err != nil { + errs[backplanev1.ConsoleMCE+"InternalEngineComponent"] = err + } + result, err = r.ensureConsoleMCE(ctx, backplaneConfig) if result != (ctrl.Result{}) { requeue = true } @@ -874,7 +978,14 @@ func (r *MultiClusterEngineReconciler) ensureToggleableComponents(ctx context.Co errs[backplanev1.ConsoleMCE] = err } } else { - result, err := r.ensureNoConsoleMCE(ctx, backplaneConfig, ocpConsole) + result, err := r.ensureNoInternalEngineComponent(ctx, backplaneConfig, backplanev1.ConsoleMCE) + if result != (ctrl.Result{}) { + requeue = true + } + if err != nil { + errs[backplanev1.ConsoleMCE+"InternalEngineComponent"] = err + } + result, err = r.ensureNoConsoleMCE(ctx, backplaneConfig, ocpConsole) if result != (ctrl.Result{}) { requeue = true } @@ -884,7 +995,14 @@ func (r *MultiClusterEngineReconciler) ensureToggleableComponents(ctx context.Co } if backplaneConfig.Enabled(backplanev1.Discovery) { - result, err := r.ensureDiscovery(ctx, backplaneConfig) + result, err := r.ensureInternalEngineComponent(ctx, backplaneConfig, backplanev1.Discovery) + if result != (ctrl.Result{}) { + requeue = true + } + if err != nil { + errs[backplanev1.Discovery+"InternalEngineComponent"] = err + } + result, err = r.ensureDiscovery(ctx, backplaneConfig) if result != (ctrl.Result{}) { requeue = true } @@ -892,7 +1010,14 @@ func (r *MultiClusterEngineReconciler) ensureToggleableComponents(ctx context.Co errs[backplanev1.Discovery] = err } } else { - result, err := r.ensureNoDiscovery(ctx, backplaneConfig) + result, err := r.ensureNoInternalEngineComponent(ctx, backplaneConfig, backplanev1.Discovery) + if result != (ctrl.Result{}) { + requeue = true + } + if err != nil { + errs[backplanev1.Discovery+"InternalEngineComponent"] = err + } + result, err = r.ensureNoDiscovery(ctx, backplaneConfig) if result != (ctrl.Result{}) { requeue = true } @@ -902,7 +1027,14 @@ func (r *MultiClusterEngineReconciler) ensureToggleableComponents(ctx context.Co } if backplaneConfig.Enabled(backplanev1.Hive) { - result, err := r.ensureHive(ctx, backplaneConfig) + result, err := r.ensureInternalEngineComponent(ctx, backplaneConfig, backplanev1.Hive) + if result != (ctrl.Result{}) { + requeue = true + } + if err != nil { + errs[backplanev1.Hive+"InternalEngineComponent"] = err + } + result, err = r.ensureHive(ctx, backplaneConfig) if result != (ctrl.Result{}) { requeue = true } @@ -910,7 +1042,14 @@ func (r *MultiClusterEngineReconciler) ensureToggleableComponents(ctx context.Co errs[backplanev1.Hive] = err } } else { - result, err := r.ensureNoHive(ctx, backplaneConfig) + result, err := r.ensureNoInternalEngineComponent(ctx, backplaneConfig, backplanev1.Hive) + if result != (ctrl.Result{}) { + requeue = true + } + if err != nil { + errs[backplanev1.Hive+"InternalEngineComponent"] = err + } + result, err = r.ensureNoHive(ctx, backplaneConfig) if result != (ctrl.Result{}) { requeue = true } @@ -920,7 +1059,14 @@ func (r *MultiClusterEngineReconciler) ensureToggleableComponents(ctx context.Co } if backplaneConfig.Enabled(backplanev1.AssistedService) { - result, err := r.ensureAssistedService(ctx, backplaneConfig) + result, err := r.ensureInternalEngineComponent(ctx, backplaneConfig, backplanev1.AssistedService) + if result != (ctrl.Result{}) { + requeue = true + } + if err != nil { + errs[backplanev1.AssistedService+"InternalEngineComponent"] = err + } + result, err = r.ensureAssistedService(ctx, backplaneConfig) if result != (ctrl.Result{}) { requeue = true } @@ -928,7 +1074,14 @@ func (r *MultiClusterEngineReconciler) ensureToggleableComponents(ctx context.Co errs[backplanev1.AssistedService] = err } } else { - result, err := r.ensureNoAssistedService(ctx, backplaneConfig) + result, err := r.ensureNoInternalEngineComponent(ctx, backplaneConfig, backplanev1.AssistedService) + if result != (ctrl.Result{}) { + requeue = true + } + if err != nil { + errs[backplanev1.AssistedService+"InternalEngineComponent"] = err + } + result, err = r.ensureNoAssistedService(ctx, backplaneConfig) if result != (ctrl.Result{}) { requeue = true } @@ -938,7 +1091,14 @@ func (r *MultiClusterEngineReconciler) ensureToggleableComponents(ctx context.Co } if backplaneConfig.Enabled(backplanev1.ClusterLifecycle) { - result, err := r.ensureClusterLifecycle(ctx, backplaneConfig) + result, err := r.ensureInternalEngineComponent(ctx, backplaneConfig, backplanev1.ClusterLifecycle) + if result != (ctrl.Result{}) { + requeue = true + } + if err != nil { + errs[backplanev1.ClusterLifecycle+"InternalEngineComponent"] = err + } + result, err = r.ensureClusterLifecycle(ctx, backplaneConfig) if result != (ctrl.Result{}) { requeue = true } @@ -946,7 +1106,14 @@ func (r *MultiClusterEngineReconciler) ensureToggleableComponents(ctx context.Co errs[backplanev1.ClusterLifecycle] = err } } else { - result, err := r.ensureNoClusterLifecycle(ctx, backplaneConfig) + result, err := r.ensureNoInternalEngineComponent(ctx, backplaneConfig, backplanev1.ClusterLifecycle) + if result != (ctrl.Result{}) { + requeue = true + } + if err != nil { + errs[backplanev1.ClusterLifecycle+"InternalEngineComponent"] = err + } + result, err = r.ensureNoClusterLifecycle(ctx, backplaneConfig) if result != (ctrl.Result{}) { requeue = true } @@ -956,7 +1123,14 @@ func (r *MultiClusterEngineReconciler) ensureToggleableComponents(ctx context.Co } if backplaneConfig.Enabled(backplanev1.ClusterManager) { - result, err := r.ensureClusterManager(ctx, backplaneConfig) + result, err := r.ensureInternalEngineComponent(ctx, backplaneConfig, backplanev1.ClusterManager) + if result != (ctrl.Result{}) { + requeue = true + } + if err != nil { + errs[backplanev1.ClusterManager+"InternalEngineComponent"] = err + } + result, err = r.ensureClusterManager(ctx, backplaneConfig) if result != (ctrl.Result{}) { requeue = true } @@ -964,7 +1138,14 @@ func (r *MultiClusterEngineReconciler) ensureToggleableComponents(ctx context.Co errs[backplanev1.ClusterManager] = err } } else { - result, err := r.ensureNoClusterManager(ctx, backplaneConfig) + result, err := r.ensureNoInternalEngineComponent(ctx, backplaneConfig, backplanev1.ClusterManager) + if result != (ctrl.Result{}) { + requeue = true + } + if err != nil { + errs[backplanev1.ClusterManager+"InternalEngineComponent"] = err + } + result, err = r.ensureNoClusterManager(ctx, backplaneConfig) if result != (ctrl.Result{}) { requeue = true } @@ -974,7 +1155,14 @@ func (r *MultiClusterEngineReconciler) ensureToggleableComponents(ctx context.Co } if backplaneConfig.Enabled(backplanev1.ServerFoundation) { - result, err := r.ensureServerFoundation(ctx, backplaneConfig) + result, err := r.ensureInternalEngineComponent(ctx, backplaneConfig, backplanev1.ServerFoundation) + if result != (ctrl.Result{}) { + requeue = true + } + if err != nil { + errs[backplanev1.ServerFoundation+"InternalEngineComponent"] = err + } + result, err = r.ensureServerFoundation(ctx, backplaneConfig) if result != (ctrl.Result{}) { requeue = true } @@ -982,7 +1170,14 @@ func (r *MultiClusterEngineReconciler) ensureToggleableComponents(ctx context.Co errs[backplanev1.ServerFoundation] = err } } else { - result, err := r.ensureNoServerFoundation(ctx, backplaneConfig) + result, err := r.ensureNoInternalEngineComponent(ctx, backplaneConfig, backplanev1.ServerFoundation) + if result != (ctrl.Result{}) { + requeue = true + } + if err != nil { + errs[backplanev1.ServerFoundation+"InternalEngineComponent"] = err + } + result, err = r.ensureNoServerFoundation(ctx, backplaneConfig) if result != (ctrl.Result{}) { requeue = true } @@ -992,7 +1187,14 @@ func (r *MultiClusterEngineReconciler) ensureToggleableComponents(ctx context.Co } if backplaneConfig.Enabled(backplanev1.ClusterProxyAddon) { - result, err := r.ensureClusterProxyAddon(ctx, backplaneConfig) + result, err := r.ensureInternalEngineComponent(ctx, backplaneConfig, backplanev1.ClusterProxyAddon) + if result != (ctrl.Result{}) { + requeue = true + } + if err != nil { + errs[backplanev1.ClusterProxyAddon+"InternalEngineComponent"] = err + } + result, err = r.ensureClusterProxyAddon(ctx, backplaneConfig) if result != (ctrl.Result{}) { requeue = true } @@ -1000,7 +1202,14 @@ func (r *MultiClusterEngineReconciler) ensureToggleableComponents(ctx context.Co errs[backplanev1.ClusterProxyAddon] = err } } else { - result, err := r.ensureNoClusterProxyAddon(ctx, backplaneConfig) + result, err := r.ensureNoInternalEngineComponent(ctx, backplaneConfig, backplanev1.ClusterProxyAddon) + if result != (ctrl.Result{}) { + requeue = true + } + if err != nil { + errs[backplanev1.ClusterProxyAddon+"InternalEngineComponent"] = err + } + result, err = r.ensureNoClusterProxyAddon(ctx, backplaneConfig) if result != (ctrl.Result{}) { requeue = true } @@ -1010,6 +1219,13 @@ func (r *MultiClusterEngineReconciler) ensureToggleableComponents(ctx context.Co } if backplaneConfig.Enabled(backplanev1.LocalCluster) { + // result, err := r.ensureInternalEngineComponent(ctx, backplaneConfig, backplanev1.LocalCluster) + // if result != (ctrl.Result{}) { + // requeue = true + // } + // if err != nil { + // errs[backplanev1.LocalCluster+"InternalEngineComponent"] = err + // } result, err := r.ensureLocalCluster(ctx, backplaneConfig) if result != (ctrl.Result{}) { requeue = true @@ -1018,6 +1234,13 @@ func (r *MultiClusterEngineReconciler) ensureToggleableComponents(ctx context.Co errs[backplanev1.LocalCluster] = err } } else { + // result, err := r.ensureNoInternalEngineComponent(ctx, backplaneConfig, backplanev1.LocalCluster) + // if result != (ctrl.Result{}) { + // requeue = true + // } + // if err != nil { + // errs[backplanev1.LocalCluster+"InternalEngineComponent"] = err + // } result, err := r.ensureNoLocalCluster(ctx, backplaneConfig) if result != (ctrl.Result{}) { requeue = true @@ -1093,10 +1316,14 @@ func (r *MultiClusterEngineReconciler) applyTemplate(ctx context.Context, func (r *MultiClusterEngineReconciler) deleteTemplate(ctx context.Context, backplaneConfig *backplanev1.MultiClusterEngine, template *unstructured.Unstructured) (ctrl.Result, error) { + // before := template.DeepCopy() err := r.Client.Get(ctx, types.NamespacedName{Name: template.GetName(), Namespace: template.GetNamespace()}, template) if err != nil && (apierrors.IsNotFound(err) || apimeta.IsNoMatchError(err)) { return ctrl.Result{}, nil } + // after := template.DeepCopy() + + // log.Info(fmt.Sprintf("Before: %v, After: %v", before, after)) // set status progressing condition if err != nil { @@ -1106,7 +1333,7 @@ func (r *MultiClusterEngineReconciler) deleteTemplate(ctx context.Context, log.Info(fmt.Sprintf("finalizing template: %s\n", template.GetName())) err = r.Client.Delete(ctx, template) - if err != nil { + if err != nil && !apierrors.IsNotFound(err) { log.Error(err, "Failed to delete template") return ctrl.Result{}, err } diff --git a/controllers/backplaneconfig_controller_test.go b/controllers/backplaneconfig_controller_test.go index 59e05511..4e8fbdc9 100644 --- a/controllers/backplaneconfig_controller_test.go +++ b/controllers/backplaneconfig_controller_test.go @@ -534,6 +534,208 @@ var _ = Describe("BackplaneConfig controller", func() { }) }) + Context("ensuring InternalEngineComponent CRs", func() { + It("should deploy sub components", func() { + createCtx := context.Background() + By("creating the backplane config with everything enabled") + os.Setenv("ACM_HUB_OCP_VERSION", "4.12.0") + defer os.Unsetenv("ACM_HUB_OCP_VERSION") + backplaneConfig := &backplanev1.MultiClusterEngine{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "multicluster.openshift.io/v1", + Kind: "MultiClusterEngine", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: BackplaneConfigName, + }, + Spec: backplanev1.MultiClusterEngineSpec{ + TargetNamespace: DestinationNamespace, + ImagePullSecret: "testsecret", + Overrides: &backplanev1.Overrides{ + Components: []backplanev1.ComponentConfig{ + { + Name: backplanev1.AssistedService, + Enabled: true, + }, + { + Name: backplanev1.ClusterLifecycle, + Enabled: true, + }, + { + Name: backplanev1.ClusterManager, + Enabled: true, + }, + { + Name: backplanev1.ClusterProxyAddon, + Enabled: true, + }, + { + Name: backplanev1.ConsoleMCE, + Enabled: false, + }, + { + Name: backplanev1.Discovery, + Enabled: true, + }, + { + Name: backplanev1.Hive, + Enabled: true, + }, + { + Name: backplanev1.HyperShift, + Enabled: true, + }, + { + Name: backplanev1.HypershiftLocalHosting, + Enabled: false, + }, + { + Name: backplanev1.ManagedServiceAccount, + Enabled: true, + }, + { + Name: backplanev1.ServerFoundation, + Enabled: true, + }, + { + Name: backplanev1.ImageBasedInstallOperator, + Enabled: true, + }, + }, + }, + }, + } + Expect(k8sClient.Create(createCtx, backplaneConfig)).Should(Succeed()) + + By("ensuring the InternalEngineComponent CRD is created") + ctx := context.Background() + iecCRD := &apixv1.CustomResourceDefinition{} + + Eventually(k8sClient.Get(ctx, types.NamespacedName{Name: "internalenginecomponents.multicluster.openshift.io"}, iecCRD)).Should(Succeed()) + + By("ensuring togglable components") + _, err := reconciler.ensureToggleableComponents(ctx, backplaneConfig) + Expect(err).To(BeNil()) + + By("ensuring each enabled component's CR is created") + for _, mcecomponent := range backplanev1.MCEComponents { + if backplaneConfig.Enabled(mcecomponent) { + By(fmt.Sprintf("ensuring %s CR is created", mcecomponent)) + Eventually(k8sClient.Get(ctx, types.NamespacedName{Name: mcecomponent, Namespace: backplaneConfig.Spec.TargetNamespace}, &backplanev1.InternalEngineComponent{})).Should(Succeed()) + } + } + + By("ensuring each disabled component's CR is not present") + for _, mcecomponent := range backplanev1.MCEComponents { + if !backplaneConfig.Enabled(mcecomponent) { + By(fmt.Sprintf("ensuring %s CR is not present", mcecomponent)) + Eventually(k8sClient.Get(ctx, types.NamespacedName{Name: mcecomponent, Namespace: backplaneConfig.Spec.TargetNamespace}, &backplanev1.InternalEngineComponent{})).Should(Not(Succeed())) + } + } + }) + }) + + Context("ensuring No InternalEngineComponent CRs", func() { + It("should deploy sub components", func() { + createCtx := context.Background() + By("creating the backplane config with everything enabled") + backplaneConfig := &backplanev1.MultiClusterEngine{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "multicluster.openshift.io/v1", + Kind: "MultiClusterEngine", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: BackplaneConfigName, + }, + Spec: backplanev1.MultiClusterEngineSpec{ + TargetNamespace: DestinationNamespace, + ImagePullSecret: "testsecret", + Overrides: &backplanev1.Overrides{ + Components: []backplanev1.ComponentConfig{ + { + Name: backplanev1.AssistedService, + Enabled: false, + }, + { + Name: backplanev1.ClusterLifecycle, + Enabled: false, + }, + { + Name: backplanev1.ClusterManager, + Enabled: false, + }, + { + Name: backplanev1.ClusterProxyAddon, + Enabled: false, + }, + { + Name: backplanev1.ConsoleMCE, + Enabled: false, + }, + { + Name: backplanev1.Discovery, + Enabled: false, + }, + { + Name: backplanev1.Hive, + Enabled: false, + }, + { + Name: backplanev1.HyperShift, + Enabled: false, + }, + { + Name: backplanev1.HypershiftLocalHosting, + Enabled: false, + }, + { + Name: backplanev1.ManagedServiceAccount, + Enabled: false, + }, + { + Name: backplanev1.ServerFoundation, + Enabled: false, + }, + { + Name: backplanev1.ImageBasedInstallOperator, + Enabled: false, + }, + }, + }, + }, + } + Expect(k8sClient.Create(createCtx, backplaneConfig)).Should(Succeed()) + + By("ensuring the InternalEngineComponent CRD is created") + ctx := context.Background() + iecCRD := &apixv1.CustomResourceDefinition{} + + Eventually(k8sClient.Get(ctx, types.NamespacedName{Name: "internalenginecomponents.multicluster.openshift.io"}, iecCRD)).Should(Succeed()) + + By("ensuring togglable components") + _, err := reconciler.ensureToggleableComponents(ctx, backplaneConfig) + Expect(err).To(BeNil()) + + By("ensuring each enabled component's CR is created") + for _, mcecomponent := range backplanev1.MCEComponents { + if backplaneConfig.Enabled(mcecomponent) { + By(fmt.Sprintf("ensuring %s CR is created", mcecomponent)) + Eventually(k8sClient.Get(ctx, types.NamespacedName{Name: mcecomponent, Namespace: backplaneConfig.Spec.TargetNamespace}, &backplanev1.InternalEngineComponent{})).Should(Succeed()) + } + } + + By("ensuring each disabled component's CR is not present") + for _, mcecomponent := range backplanev1.MCEComponents { + if !backplaneConfig.Enabled(mcecomponent) { + By(fmt.Sprintf("ensuring %s CR is not present", mcecomponent)) + component := &backplanev1.InternalEngineComponent{} + err := k8sClient.Get(ctx, types.NamespacedName{Name: mcecomponent, Namespace: backplaneConfig.Spec.TargetNamespace}, component) + log.Info(fmt.Sprintf("component and error: %v :: %v", component, err)) + Expect(err).NotTo(BeNil()) + } + } + }) + }) Context("2nd attempt", func() { It("should deploy sub components", func() { createCtx := context.Background() diff --git a/controllers/suite_test.go b/controllers/suite_test.go index 673666b5..1f1dface 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -88,6 +88,7 @@ var _ = BeforeSuite(func() { filepath.Join("..", "pkg", "templates", "crds", "cluster-lifecycle"), filepath.Join("..", "pkg", "templates", "crds", "discovery-operator"), filepath.Join("..", "pkg", "templates", "crds", "cluster-proxy-addon"), + filepath.Join("..", "pkg", "templates", "crds", "internal"), filepath.Join("..", "hack", "unit-test-crds"), }, CRDInstallOptions: envtest.CRDInstallOptions{ diff --git a/main.go b/main.go index 23151a9d..fe854096 100644 --- a/main.go +++ b/main.go @@ -240,7 +240,6 @@ func main() { } // Render CRD templates - crdsDir := crdsDir var backplaneConfig *backplanev1.MultiClusterEngine crds, errs := renderer.RenderCRDs(crdsDir, backplaneConfig) diff --git a/config/crd/internal/internal-hub-component.yaml b/pkg/templates/crds/internal/internal-engine-component.yaml similarity index 81% rename from config/crd/internal/internal-hub-component.yaml rename to pkg/templates/crds/internal/internal-engine-component.yaml index b8dc18bd..76d89796 100644 --- a/config/crd/internal/internal-hub-component.yaml +++ b/pkg/templates/crds/internal/internal-engine-component.yaml @@ -2,10 +2,10 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: # name must match the spec fields below, and be in the form: . - name: internalhubcomponents.operator.open-cluster-management.io + name: internalenginecomponents.multicluster.openshift.io spec: # group name to use for REST API: /apis// - group: operator.open-cluster-management.io + group: multicluster.openshift.io # list of versions supported by this CustomResourceDefinition versions: - name: v1 @@ -23,11 +23,11 @@ spec: scope: Namespaced names: # plural name to be used in the URL: /apis/// - plural: internalhubcomponents + plural: internalenginecomponents # singular name to be used as an alias on the CLI and for display - singular: internalhubcomponent + singular: internalenginecomponent # kind is normally the CamelCased singular type. Your resource manifests use this. - kind: InternalHubComponent + kind: InternalEngineComponent # shortNames allow shorter string to match your resource on the CLI shortNames: - - ihc \ No newline at end of file + - iec \ No newline at end of file