diff --git a/controllers/clusterplatform/clusterplatform.go b/controllers/clusterplatform/clusterplatform.go index e9a8c86cd..0e1db52c6 100644 --- a/controllers/clusterplatform/clusterplatform.go +++ b/controllers/clusterplatform/clusterplatform.go @@ -25,9 +25,9 @@ import ( "github.com/apache/incubator-kie-kogito-serverless-operator/api/metadata" operatorapi "github.com/apache/incubator-kie-kogito-serverless-operator/api/v1alpha08" "github.com/apache/incubator-kie-kogito-serverless-operator/log" + "github.com/apache/incubator-kie-kogito-serverless-operator/utils" k8serrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/klog/v2" - ctrl "sigs.k8s.io/controller-runtime/pkg/client" ) const ( @@ -35,15 +35,15 @@ const ( ) // GetActiveClusterPlatform returns the currently installed active cluster platform. -func GetActiveClusterPlatform(ctx context.Context, c ctrl.Client) (*operatorapi.SonataFlowClusterPlatform, error) { - return getClusterPlatform(ctx, c, true) +func GetActiveClusterPlatform(ctx context.Context) (*operatorapi.SonataFlowClusterPlatform, error) { + return getClusterPlatform(ctx, true) } // getClusterPlatform returns the currently active cluster platform or any cluster platform existing in the cluster. -func getClusterPlatform(ctx context.Context, c ctrl.Client, active bool) (*operatorapi.SonataFlowClusterPlatform, error) { +func getClusterPlatform(ctx context.Context, active bool) (*operatorapi.SonataFlowClusterPlatform, error) { klog.V(log.D).InfoS("Finding available cluster platforms") - lst, err := listPrimaryClusterPlatforms(ctx, c) + lst, err := listPrimaryClusterPlatforms(ctx) if err != nil { return nil, err } @@ -66,8 +66,8 @@ func getClusterPlatform(ctx context.Context, c ctrl.Client, active bool) (*opera } // listPrimaryClusterPlatforms returns all non-secondary cluster platforms installed (only one will be active). -func listPrimaryClusterPlatforms(ctx context.Context, c ctrl.Reader) (*operatorapi.SonataFlowClusterPlatformList, error) { - lst, err := listAllClusterPlatforms(ctx, c) +func listPrimaryClusterPlatforms(ctx context.Context) (*operatorapi.SonataFlowClusterPlatformList, error) { + lst, err := listAllClusterPlatforms(ctx) if err != nil { return nil, err } @@ -83,8 +83,8 @@ func listPrimaryClusterPlatforms(ctx context.Context, c ctrl.Reader) (*operatora } // allDuplicatedClusterPlatforms returns true if every cluster platform has a "Duplicated" status set -func allDuplicatedClusterPlatforms(ctx context.Context, c ctrl.Reader) bool { - lst, err := listAllClusterPlatforms(ctx, c) +func allDuplicatedClusterPlatforms(ctx context.Context) bool { + lst, err := listAllClusterPlatforms(ctx) if err != nil { return false } @@ -99,9 +99,9 @@ func allDuplicatedClusterPlatforms(ctx context.Context, c ctrl.Reader) bool { } // listAllClusterPlatforms returns all clusterplatforms installed. -func listAllClusterPlatforms(ctx context.Context, c ctrl.Reader) (*operatorapi.SonataFlowClusterPlatformList, error) { +func listAllClusterPlatforms(ctx context.Context) (*operatorapi.SonataFlowClusterPlatformList, error) { lst := operatorapi.NewSonataFlowClusterPlatformList() - if err := c.List(ctx, &lst); err != nil { + if err := utils.GetClient().List(ctx, &lst); err != nil { return nil, err } return &lst, nil diff --git a/controllers/clusterplatform/initialize.go b/controllers/clusterplatform/initialize.go index ac595e366..6f530d2b9 100644 --- a/controllers/clusterplatform/initialize.go +++ b/controllers/clusterplatform/initialize.go @@ -46,7 +46,7 @@ func (action *initializeAction) Name() string { } func (action *initializeAction) CanHandle(ctx context.Context, cPlatform *operatorapi.SonataFlowClusterPlatform) bool { - return !cPlatform.Status.IsDuplicated() || allDuplicatedClusterPlatforms(ctx, action.client) + return !cPlatform.Status.IsDuplicated() || allDuplicatedClusterPlatforms(ctx) } func (action *initializeAction) Handle(ctx context.Context, cPlatform *operatorapi.SonataFlowClusterPlatform) error { @@ -107,7 +107,7 @@ func (action *initializeAction) isPrimaryDuplicate(ctx context.Context, cPlatfor // Always reconcile secondary cluster platforms return false, nil } - platforms, err := listPrimaryClusterPlatforms(ctx, action.client) + platforms, err := listPrimaryClusterPlatforms(ctx) if err != nil { return false, err } diff --git a/controllers/platform/defaults.go b/controllers/platform/defaults.go index 95d8a4c8b..9d24e70f7 100644 --- a/controllers/platform/defaults.go +++ b/controllers/platform/defaults.go @@ -23,11 +23,9 @@ import ( "context" "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/klog/v2" ctrl "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/apache/incubator-kie-kogito-serverless-operator/container-builder/client" "github.com/apache/incubator-kie-kogito-serverless-operator/log" "github.com/apache/incubator-kie-kogito-serverless-operator/utils" @@ -36,7 +34,7 @@ import ( const defaultSonataFlowPlatformName = "sonataflow-platform" -func ConfigureDefaults(ctx context.Context, c client.Client, p *operatorapi.SonataFlowPlatform, verbose bool) error { +func CreateOrUpdateWithDefaults(ctx context.Context, p *operatorapi.SonataFlowPlatform, verbose bool) error { // update missing fields in the resource if p.Status.Cluster == "" || utils.IsOpenShift() { p.Status.Cluster = operatorapi.PlatformClusterOpenShift @@ -52,7 +50,7 @@ func ConfigureDefaults(ctx context.Context, c client.Client, p *operatorapi.Sona return err } - err = configureRegistry(ctx, c, p, verbose) + err = configureRegistry(ctx, p, verbose) if err != nil { return err } @@ -61,15 +59,15 @@ func ConfigureDefaults(ctx context.Context, c client.Client, p *operatorapi.Sona klog.V(log.I).InfoS("Maven Timeout set", "timeout", p.Spec.Build.Config.Timeout.Duration) } - return createOrUpdatePlatform(ctx, c, p) + return createOrUpdatePlatform(ctx, p) } -func createOrUpdatePlatform(ctx context.Context, c client.Client, p *operatorapi.SonataFlowPlatform) error { +func createOrUpdatePlatform(ctx context.Context, p *operatorapi.SonataFlowPlatform) error { config := operatorapi.SonataFlowPlatform{} - err := c.Get(ctx, ctrl.ObjectKey{Namespace: p.Namespace, Name: p.Name}, &config) + err := utils.GetClient().Get(ctx, ctrl.ObjectKey{Namespace: p.Namespace, Name: p.Name}, &config) if errors.IsNotFound(err) { klog.V(log.D).ErrorS(err, "Platform not found, creating it") - return c.Create(ctx, p) + return utils.GetClient().Create(ctx, p) } else if err != nil { klog.V(log.E).ErrorS(err, "Error reading the Platform") return err @@ -77,37 +75,9 @@ func createOrUpdatePlatform(ctx context.Context, c client.Client, p *operatorapi config.Spec = p.Spec config.Status.Cluster = p.Status.Cluster - err = c.Update(ctx, &config) + err = utils.GetClient().Update(ctx, &config) if err != nil { klog.V(log.E).ErrorS(err, "Error updating the BuildPlatform") } return err } - -func newDefaultSonataFlowPlatform(namespace string) *operatorapi.SonataFlowPlatform { - if utils.IsOpenShift() { - return &operatorapi.SonataFlowPlatform{ - ObjectMeta: metav1.ObjectMeta{Name: defaultSonataFlowPlatformName, Namespace: namespace}, - Spec: operatorapi.SonataFlowPlatformSpec{ - Build: operatorapi.BuildPlatformSpec{ - Config: operatorapi.BuildPlatformConfig{ - BuildStrategy: operatorapi.PlatformBuildStrategy, - }, - }, - }, - } - } - - return &operatorapi.SonataFlowPlatform{ - ObjectMeta: metav1.ObjectMeta{Name: defaultSonataFlowPlatformName, Namespace: namespace}, - Spec: operatorapi.SonataFlowPlatformSpec{ - Build: operatorapi.BuildPlatformSpec{ - Config: operatorapi.BuildPlatformConfig{ - BuildStrategyOptions: map[string]string{ - kanikoBuildCacheEnabled: "true", - }, - }, - }, - }, - } -} diff --git a/controllers/platform/initialize.go b/controllers/platform/initialize.go index d1bfb07b2..bd3ac2bf7 100644 --- a/controllers/platform/initialize.go +++ b/controllers/platform/initialize.go @@ -77,7 +77,7 @@ func (action *initializeAction) Handle(ctx context.Context, platform *operatorap return nil, nil } - if err = ConfigureDefaults(ctx, action.client, platform, true); err != nil { + if err = CreateOrUpdateWithDefaults(ctx, platform, true); err != nil { return nil, err } // nolint: staticcheck diff --git a/controllers/platform/k8s.go b/controllers/platform/k8s.go index 62d8b3699..022b63504 100644 --- a/controllers/platform/k8s.go +++ b/controllers/platform/k8s.go @@ -57,7 +57,7 @@ func (action *serviceAction) CanHandle(platform *operatorapi.SonataFlowPlatform) func (action *serviceAction) Handle(ctx context.Context, platform *operatorapi.SonataFlowPlatform) (*operatorapi.SonataFlowPlatform, error) { // Refresh applied configuration - if err := ConfigureDefaults(ctx, action.client, platform, false); err != nil { + if err := CreateOrUpdateWithDefaults(ctx, platform, false); err != nil { return nil, err } diff --git a/controllers/platform/monitor.go b/controllers/platform/monitor.go index ae5b57453..ed10326ab 100644 --- a/controllers/platform/monitor.go +++ b/controllers/platform/monitor.go @@ -54,7 +54,7 @@ func (action *monitorAction) Handle(ctx context.Context, platform *operatorapi.S } // Refresh applied configuration - if err := ConfigureDefaults(ctx, action.client, platform, false); err != nil { + if err := CreateOrUpdateWithDefaults(ctx, platform, false); err != nil { return nil, err } diff --git a/controllers/platform/platform.go b/controllers/platform/platform.go index 69b636dc6..23488731d 100644 --- a/controllers/platform/platform.go +++ b/controllers/platform/platform.go @@ -25,6 +25,7 @@ import ( "os" "strings" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/klog/v2" coordination "k8s.io/api/coordination/v1" @@ -147,13 +148,41 @@ func getLocalPlatform(ctx context.Context, c ctrl.Client, namespace string, acti } klog.V(log.I).InfoS("Not found a local build platform", "Namespace", namespace) klog.V(log.I).InfoS("Creating a default SonataFlowPlatform", "Namespace", namespace) - sfp := newDefaultSonataFlowPlatform(namespace) - if err = c.Create(ctx, sfp); err != nil { + sfp := newEmptySonataFlowPlatform(namespace) + if err = CreateOrUpdateWithDefaults(ctx, sfp, false); err != nil { return nil, err } return sfp, nil } +func newEmptySonataFlowPlatform(namespace string) *operatorapi.SonataFlowPlatform { + if utils.IsOpenShift() { + return &operatorapi.SonataFlowPlatform{ + ObjectMeta: metav1.ObjectMeta{Name: defaultSonataFlowPlatformName, Namespace: namespace}, + Spec: operatorapi.SonataFlowPlatformSpec{ + Build: operatorapi.BuildPlatformSpec{ + Config: operatorapi.BuildPlatformConfig{ + BuildStrategy: operatorapi.PlatformBuildStrategy, + }, + }, + }, + } + } + + return &operatorapi.SonataFlowPlatform{ + ObjectMeta: metav1.ObjectMeta{Name: defaultSonataFlowPlatformName, Namespace: namespace}, + Spec: operatorapi.SonataFlowPlatformSpec{ + Build: operatorapi.BuildPlatformSpec{ + Config: operatorapi.BuildPlatformConfig{ + BuildStrategyOptions: map[string]string{ + kanikoBuildCacheEnabled: "true", + }, + }, + }, + }, + } +} + // listPrimaryPlatforms returns all non-secondary platforms installed in a given namespace (only one will be active). func listPrimaryPlatforms(ctx context.Context, c ctrl.Reader, namespace string) (*operatorapi.SonataFlowPlatformList, error) { lst, err := listAllPlatforms(ctx, c, namespace) diff --git a/controllers/platform/platformutils.go b/controllers/platform/platformutils.go index f3978b742..4bde8c92d 100644 --- a/controllers/platform/platformutils.go +++ b/controllers/platform/platformutils.go @@ -26,6 +26,7 @@ import ( "strings" "time" + "github.com/apache/incubator-kie-kogito-serverless-operator/utils" corev1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -35,7 +36,6 @@ import ( "github.com/apache/incubator-kie-kogito-serverless-operator/controllers/workflowdef" - "github.com/apache/incubator-kie-kogito-serverless-operator/container-builder/client" "github.com/apache/incubator-kie-kogito-serverless-operator/log" operatorapi "github.com/apache/incubator-kie-kogito-serverless-operator/api/v1alpha08" @@ -46,7 +46,7 @@ var builderDockerfileFromRE = regexp.MustCompile(`FROM (.*) AS builder`) // ResourceCustomizer can be used to inject code that changes the objects before they are created. type ResourceCustomizer func(object ctrl.Object) ctrl.Object -func configureRegistry(ctx context.Context, c client.Client, p *operatorapi.SonataFlowPlatform, verbose bool) error { +func configureRegistry(ctx context.Context, p *operatorapi.SonataFlowPlatform, verbose bool) error { if p.Spec.Build.Config.BuildStrategy == operatorapi.PlatformBuildStrategy && p.Status.Cluster == operatorapi.PlatformClusterOpenShift { p.Spec.Build.Config.Registry = operatorapi.RegistrySpec{} klog.V(log.D).InfoS("Platform registry not set and ignored on openshift cluster") @@ -55,7 +55,7 @@ func configureRegistry(ctx context.Context, c client.Client, p *operatorapi.Sona if p.Spec.Build.Config.Registry.Address == "" && p.Status.Cluster == operatorapi.PlatformClusterKubernetes { // try KEP-1755 - address, err := GetRegistryAddress(ctx, c) + address, err := GetRegistryAddress(ctx) if err != nil && verbose { klog.V(log.E).ErrorS(err, "Cannot find a registry where to push images via KEP-1755") } else if err == nil && address != nil { @@ -139,9 +139,9 @@ func setStatusAdditionalInfo(platform *operatorapi.SonataFlowPlatform) { // GetRegistryAddress KEP-1755 // https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry -func GetRegistryAddress(ctx context.Context, c client.Client) (*string, error) { +func GetRegistryAddress(ctx context.Context) (*string, error) { config := corev1.ConfigMap{} - err := c.Get(ctx, ctrl.ObjectKey{Namespace: "kube-public", Name: "local-registry-hosting"}, &config) + err := utils.GetClient().Get(ctx, ctrl.ObjectKey{Namespace: "kube-public", Name: "local-registry-hosting"}, &config) if err != nil { if k8serrors.IsNotFound(err) { return nil, nil diff --git a/controllers/profiles/common/properties/platform_test.go b/controllers/profiles/common/properties/platform_test.go index 523636615..093a56052 100644 --- a/controllers/profiles/common/properties/platform_test.go +++ b/controllers/profiles/common/properties/platform_test.go @@ -19,7 +19,6 @@ import ( "github.com/apache/incubator-kie-kogito-serverless-operator/api/v1alpha08" "github.com/apache/incubator-kie-kogito-serverless-operator/test" - "github.com/apache/incubator-kie-kogito-serverless-operator/utils" "github.com/stretchr/testify/assert" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -64,8 +63,7 @@ func Test_resolvePlatformWorkflowProperties(t *testing.T) { }, } - client := test.NewSonataFlowClientBuilder().WithRuntimeObjects(platform, secret, cm).WithStatusSubresource(platform).Build() - utils.SetClient(client) + _ = test.NewSonataFlowClientBuilder().WithRuntimeObjects(platform, secret, cm).WithStatusSubresource(platform).Build() props, err := resolvePlatformWorkflowProperties(platform) assert.NoError(t, err) @@ -106,8 +104,7 @@ func Test_resolvePlatformWorkflowProperties_RefNotFound(t *testing.T) { }, } - client := test.NewSonataFlowClientBuilder().WithRuntimeObjects(platform).WithStatusSubresource(platform).Build() - utils.SetClient(client) + _ = test.NewSonataFlowClientBuilder().WithRuntimeObjects(platform).WithStatusSubresource(platform).Build() props, err := resolvePlatformWorkflowProperties(platform) assert.NoError(t, err) diff --git a/controllers/sonataflowclusterplatform_controller.go b/controllers/sonataflowclusterplatform_controller.go index a511bbafb..1142b4a8d 100644 --- a/controllers/sonataflowclusterplatform_controller.go +++ b/controllers/sonataflowclusterplatform_controller.go @@ -134,7 +134,7 @@ func (r *SonataFlowClusterPlatformReconciler) SetupWithManager(mgr ctrlrun.Manag // if actively referenced sonataflowplatform object is changed, reconcile the active SonataFlowClusterPlatform. func (r *SonataFlowClusterPlatformReconciler) mapPlatformToClusterPlatformRequests(ctx context.Context, object client.Object) []reconcile.Request { - sfcPlatform, err := clusterplatform.GetActiveClusterPlatform(ctx, r.Client) + sfcPlatform, err := clusterplatform.GetActiveClusterPlatform(ctx) if err != nil && !errors.IsNotFound(err) { klog.V(log.E).ErrorS(err, "Failed to get active SonataFlowClusterPlatform") return nil diff --git a/controllers/sonataflowplatform_controller.go b/controllers/sonataflowplatform_controller.go index ff36a8aeb..e111a3212 100644 --- a/controllers/sonataflowplatform_controller.go +++ b/controllers/sonataflowplatform_controller.go @@ -114,7 +114,7 @@ func (r *SonataFlowPlatformReconciler) Reconcile(ctx context.Context, req reconc target := instance.DeepCopy() - if err = r.SonataFlowPlatformUpdateStatus(ctx, req, target); err != nil { + if err = r.updateSonataFlowPlatformStatus(ctx, req, target); err != nil { return reconcile.Result{}, err } @@ -170,10 +170,10 @@ func (r *SonataFlowPlatformReconciler) Reconcile(ctx context.Context, req reconc } -// If an active cluster platform exists, update platform.Status accordingly -func (r *SonataFlowPlatformReconciler) SonataFlowPlatformUpdateStatus(ctx context.Context, req reconcile.Request, target *operatorapi.SonataFlowPlatform) error { +// sonataFlowPlatformUpdateStatus If an active cluster platform exists, update platform.Status accordingly +func (r *SonataFlowPlatformReconciler) updateSonataFlowPlatformStatus(ctx context.Context, req reconcile.Request, target *operatorapi.SonataFlowPlatform) error { // Fetch the active SonataFlowClusterPlatform instance - sfcPlatform, err := clusterplatform.GetActiveClusterPlatform(ctx, r.Client) + sfcPlatform, err := clusterplatform.GetActiveClusterPlatform(ctx) if err != nil && !errors.IsNotFound(err) { klog.V(log.E).ErrorS(err, "Failed to get active SonataFlowClusterPlatform") return err @@ -241,7 +241,7 @@ func (r *SonataFlowPlatformReconciler) mapClusterPlatformToPlatformRequests(ctx // if actively referenced sonataflowplatform is changed, reconcile other SonataFlowPlatforms in the cluster. func (r *SonataFlowPlatformReconciler) mapPlatformToPlatformRequests(ctx context.Context, object client.Object) []reconcile.Request { platform := object.(*operatorapi.SonataFlowPlatform) - sfcPlatform, err := clusterplatform.GetActiveClusterPlatform(ctx, r.Client) + sfcPlatform, err := clusterplatform.GetActiveClusterPlatform(ctx) if err != nil && !errors.IsNotFound(err) { klog.V(log.E).ErrorS(err, "Failed to get active SonataFlowClusterPlatform") return nil diff --git a/test/kubernetes_cli.go b/test/kubernetes_cli.go index 72029fd1c..5120a5caa 100644 --- a/test/kubernetes_cli.go +++ b/test/kubernetes_cli.go @@ -23,12 +23,14 @@ import ( "context" "testing" + "github.com/apache/incubator-kie-kogito-serverless-operator/utils" buildv1 "github.com/openshift/api/build/v1" imgv1 "github.com/openshift/api/image/v1" routev1 "github.com/openshift/api/route/v1" "github.com/stretchr/testify/assert" appsv1 "k8s.io/api/apps/v1" v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/client-go/kubernetes/scheme" @@ -44,29 +46,61 @@ func NewFakeRecorder() record.EventRecorder { return record.NewFakeRecorder(10) } +type SonataFlowClientBuilder struct { + innerBuilder *fake.ClientBuilder +} + +// Build from the underlying fake.ClientBuilder. +// To overwrite this method we need to forward all the functions from the +// base implementation since they do not use an interface. +func (s *SonataFlowClientBuilder) Build() ctrl.WithWatch { + cli := s.innerBuilder.Build() + utils.SetClient(cli) + return cli +} + +func (s *SonataFlowClientBuilder) WithRuntimeObjects(initRuntimeObjs ...runtime.Object) *SonataFlowClientBuilder { + _ = s.innerBuilder.WithRuntimeObjects(initRuntimeObjs...) + return s +} + +func (s *SonataFlowClientBuilder) WithStatusSubresource(o ...ctrl.Object) *SonataFlowClientBuilder { + _ = s.innerBuilder.WithStatusSubresource(o...) + return s +} + // NewSonataFlowClientBuilder creates a new fake.ClientBuilder with the right scheme references -func NewSonataFlowClientBuilder() *fake.ClientBuilder { +func NewSonataFlowClientBuilder() *SonataFlowClientBuilder { s := scheme.Scheme utilruntime.Must(operatorapi.AddToScheme(s)) - return fake.NewClientBuilder().WithScheme(s) + builder := fake.NewClientBuilder().WithScheme(s) + return &SonataFlowClientBuilder{ + innerBuilder: builder, + } } -func NewSonataFlowClientBuilderWithKnative() *fake.ClientBuilder { +func NewSonataFlowClientBuilderWithKnative() *SonataFlowClientBuilder { s := scheme.Scheme utilruntime.Must(operatorapi.AddToScheme(s)) utilruntime.Must(servingv1.AddToScheme(s)) - return fake.NewClientBuilder().WithScheme(s) + builder := fake.NewClientBuilder().WithScheme(s) + return &SonataFlowClientBuilder{ + innerBuilder: builder, + } } // NewKogitoClientBuilderWithOpenShift creates a new fake client with OpenShift schemas. // If your object is not present, just add in the list below. -func NewKogitoClientBuilderWithOpenShift() *fake.ClientBuilder { +func NewKogitoClientBuilderWithOpenShift() *SonataFlowClientBuilder { s := scheme.Scheme utilruntime.Must(routev1.Install(s)) utilruntime.Must(buildv1.Install(s)) utilruntime.Must(imgv1.Install(s)) utilruntime.Must(operatorapi.AddToScheme(s)) - return fake.NewClientBuilder().WithScheme(s) + builder := fake.NewClientBuilder().WithScheme(s) + return &SonataFlowClientBuilder{ + innerBuilder: builder, + } } func MustGetDeployment(t *testing.T, client ctrl.WithWatch, workflow *operatorapi.SonataFlow) *appsv1.Deployment {