From e407a8d1440b03be148bbae50c0d586e5893c425 Mon Sep 17 00:00:00 2001 From: Jordi Gil Date: Mon, 5 Feb 2024 09:42:08 +0100 Subject: [PATCH] Refactor logic to retrieve platform CR when deploying workflow to inject persistence configuration when platform provides one Signed-off-by: Jordi Gil --- api/v1alpha08/sonataflow_persistence_types.go | 60 +++++++++++++++++++ api/v1alpha08/sonataflow_types.go | 2 +- .../sonataflowplatform_services_types.go | 47 +-------------- api/v1alpha08/sonataflowplatform_types.go | 6 +- api/v1alpha08/zz_generated.deepcopy.go | 38 ++++++------ controllers/platform/k8s.go | 20 +++---- controllers/platform/platformutils.go | 16 +++-- .../services/properties_services_test.go | 4 +- controllers/platform/services/services.go | 19 +++--- controllers/profiles/common/ensurer.go | 10 ++-- .../profiles/common/mutate_visitors.go | 7 +-- .../profiles/common/object_creators.go | 10 ++-- .../profiles/common/object_creators_test.go | 17 +++--- .../profiles/common/persistence/postgresql.go | 2 +- .../common/properties/application_test.go | 13 +--- controllers/profiles/common/reconciler.go | 8 +-- .../profiles/dev/object_creators_dev.go | 15 ++--- .../profiles/dev/object_creators_dev_test.go | 2 +- controllers/profiles/dev/profile_dev.go | 6 +- controllers/profiles/dev/profile_dev_test.go | 36 +++++------ controllers/profiles/dev/states_dev.go | 20 ++++--- .../profiles/dev/status_enricher_dev_test.go | 6 +- .../profiles/prod/deployment_handler.go | 11 ++-- .../profiles/prod/deployment_handler_test.go | 8 +-- controllers/profiles/prod/profile_prod.go | 4 +- .../profiles/prod/profile_prod_test.go | 22 +++---- controllers/profiles/prod/states_prod.go | 8 +-- .../profiles/prod/states_prod_nobuild.go | 6 +- controllers/profiles/profile.go | 4 +- controllers/sonataflow_controller.go | 6 +- .../sonataflowplatform_controller_test.go | 32 +++++----- .../postgreSQL/02-sonataflow_platform.yaml | 7 +-- 32 files changed, 234 insertions(+), 238 deletions(-) create mode 100644 api/v1alpha08/sonataflow_persistence_types.go diff --git a/api/v1alpha08/sonataflow_persistence_types.go b/api/v1alpha08/sonataflow_persistence_types.go new file mode 100644 index 000000000..f93b7a4ca --- /dev/null +++ b/api/v1alpha08/sonataflow_persistence_types.go @@ -0,0 +1,60 @@ +// Copyright 2024 Apache Software Foundation (ASF) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1alpha08 + +// PersistencePostgreSQL configure postgresql connection for service(s). +// +kubebuilder:validation:MinProperties=2 +// +kubebuilder:validation:MaxProperties=2 +type PersistencePostgreSQL struct { + // Secret reference to the database user credentials + SecretRef PostgreSQLSecretOptions `json:"secretRef"` + // Service reference to postgresql datasource. Mutually exclusive to jdbcUrl. + // +optional + ServiceRef *PostgreSQLServiceOptions `json:"serviceRef,omitempty"` + // PostgreSql JDBC URL. Mutually exclusive to serviceRef. + // e.g. "jdbc:postgresql://host:port/database?currentSchema=data-index-service" + // +optional + JdbcUrl string `json:"jdbcUrl,omitempty"` +} + +// PostgreSQLSecretOptions use credential secret for postgresql connection. +type PostgreSQLSecretOptions struct { + // Name of the postgresql credentials secret. + Name string `json:"name"` + // Defaults to POSTGRESQL_USER + // +optional + UserKey string `json:"userKey,omitempty"` + // Defaults to POSTGRESQL_PASSWORD + // +optional + PasswordKey string `json:"passwordKey,omitempty"` +} + +// PostgreSQLServiceOptions use k8s service to configure postgresql jdbc url. +type PostgreSQLServiceOptions struct { + // Name of the postgresql k8s service. + Name string `json:"name"` + // Namespace of the postgresql k8s service. Defaults to the SonataFlowPlatform's local namespace. + // +optional + Namespace string `json:"namespace,omitempty"` + // Port to use when connecting to the postgresql k8s service. Defaults to 5432. + // +optional + Port *int `json:"port,omitempty"` + // Name of postgresql database to be used. Defaults to "sonataflow" + // +optional + DatabaseName string `json:"databaseName,omitempty"` + // Schema of postgresql database to be used. Defaults to "data-index-service" + // +optional + DatabaseSchema string `json:"databaseSchema,omitempty"` +} diff --git a/api/v1alpha08/sonataflow_types.go b/api/v1alpha08/sonataflow_types.go index 5233da15a..644fb0a3a 100644 --- a/api/v1alpha08/sonataflow_types.go +++ b/api/v1alpha08/sonataflow_types.go @@ -658,7 +658,7 @@ type SonataFlowSpec struct { //+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="podTemplate" PodTemplate PodTemplateSpec `json:"podTemplate,omitempty"` // Persistence defines the database persistence configuration for the workflow - Persistence *PersistenceSpec `json:"persistence,omitempty"` + Persistence *PersistencePlatformSpec `json:"persistence,omitempty"` } // SonataFlowStatus defines the observed state of SonataFlow diff --git a/api/v1alpha08/sonataflowplatform_services_types.go b/api/v1alpha08/sonataflowplatform_services_types.go index 753aa4db8..ae5e4a99c 100644 --- a/api/v1alpha08/sonataflowplatform_services_types.go +++ b/api/v1alpha08/sonataflowplatform_services_types.go @@ -32,53 +32,8 @@ type ServiceSpec struct { Enabled *bool `json:"enabled,omitempty"` // Persists service to a datasource of choice. Ephemeral by default. // +optional - Persistence *PersistenceSpec `json:"persistence,omitempty"` + Persistence *PersistencePlatformSpec `json:"persistence,omitempty"` // PodTemplate describes the deployment details of this platform service instance. //+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="podTemplate" PodTemplate PodTemplateSpec `json:"podTemplate,omitempty"` } - -// PersistencePostgreSQL configure postgresql connection for service(s). -// +kubebuilder:validation:MinProperties=2 -// +kubebuilder:validation:MaxProperties=2 -type PersistencePostgreSQL struct { - // Secret reference to the database user credentials - SecretRef PostgreSQLSecretOptions `json:"secretRef"` - // Service reference to postgresql datasource. Mutually exclusive to jdbcUrl. - // +optional - ServiceRef *PostgreSQLServiceOptions `json:"serviceRef,omitempty"` - // PostgreSql JDBC URL. Mutually exclusive to serviceRef. - // e.g. "jdbc:postgresql://host:port/database?currentSchema=data-index-service" - // +optional - JdbcUrl string `json:"jdbcUrl,omitempty"` -} - -// PostgreSQLSecretOptions use credential secret for postgresql connection. -type PostgreSQLSecretOptions struct { - // Name of the postgresql credentials secret. - Name string `json:"name"` - // Defaults to POSTGRESQL_USER - // +optional - UserKey string `json:"userKey,omitempty"` - // Defaults to POSTGRESQL_PASSWORD - // +optional - PasswordKey string `json:"passwordKey,omitempty"` -} - -// PostgreSQLServiceOptions use k8s service to configure postgresql jdbc url. -type PostgreSQLServiceOptions struct { - // Name of the postgresql k8s service. - Name string `json:"name"` - // Namespace of the postgresql k8s service. Defaults to the SonataFlowPlatform's local namespace. - // +optional - Namespace string `json:"namespace,omitempty"` - // Port to use when connecting to the postgresql k8s service. Defaults to 5432. - // +optional - Port *int `json:"port,omitempty"` - // Name of postgresql database to be used. Defaults to "sonataflow" - // +optional - DatabaseName string `json:"databaseName,omitempty"` - // Schema of postgresql database to be used. Defaults to "data-index-service" - // +optional - DatabaseSchema string `json:"databaseSchema,omitempty"` -} diff --git a/api/v1alpha08/sonataflowplatform_types.go b/api/v1alpha08/sonataflowplatform_types.go index 7622440c6..b59b53bcf 100644 --- a/api/v1alpha08/sonataflowplatform_types.go +++ b/api/v1alpha08/sonataflowplatform_types.go @@ -50,15 +50,15 @@ type SonataFlowPlatformSpec struct { // the configuration is used as the persistence for platform services and sonataflow instances // that don't provide one of their own. // +optional - Persistence *PersistenceSpec `json:"persistence,omitempty"` + Persistence *PersistencePlatformSpec `json:"persistence,omitempty"` } -// PersistenceSpec configures the DataBase support for both platform services and workflows. For services, it allows +// PersistencePlatformSpec configures the DataBase support for both platform services and workflows. For services, it allows // configuring a generic database connectivity if the service does not come with its own configured. In case of workflows, // the operator will add the necessary JDBC properties to in the workflow's application.properties so that it can communicate // with the persistence service based on the spec provided here. // +optional -type PersistenceSpec struct { +type PersistencePlatformSpec struct { // Connect configured services to a postgresql database. // +optional PostgreSQL *PersistencePostgreSQL `json:"postgresql,omitempty"` diff --git a/api/v1alpha08/zz_generated.deepcopy.go b/api/v1alpha08/zz_generated.deepcopy.go index e18dedf68..157c23c07 100644 --- a/api/v1alpha08/zz_generated.deepcopy.go +++ b/api/v1alpha08/zz_generated.deepcopy.go @@ -22,7 +22,7 @@ package v1alpha08 import ( "github.com/serverlessworkflow/sdk-go/v2/model" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "knative.dev/pkg/apis" @@ -320,42 +320,42 @@ func (in *Flow) DeepCopy() *Flow { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PersistencePostgreSQL) DeepCopyInto(out *PersistencePostgreSQL) { +func (in *PersistencePlatformSpec) DeepCopyInto(out *PersistencePlatformSpec) { *out = *in - out.SecretRef = in.SecretRef - if in.ServiceRef != nil { - in, out := &in.ServiceRef, &out.ServiceRef - *out = new(PostgreSQLServiceOptions) + if in.PostgreSQL != nil { + in, out := &in.PostgreSQL, &out.PostgreSQL + *out = new(PersistencePostgreSQL) (*in).DeepCopyInto(*out) } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PersistencePostgreSQL. -func (in *PersistencePostgreSQL) DeepCopy() *PersistencePostgreSQL { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PersistencePlatformSpec. +func (in *PersistencePlatformSpec) DeepCopy() *PersistencePlatformSpec { if in == nil { return nil } - out := new(PersistencePostgreSQL) + out := new(PersistencePlatformSpec) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PersistenceSpec) DeepCopyInto(out *PersistenceSpec) { +func (in *PersistencePostgreSQL) DeepCopyInto(out *PersistencePostgreSQL) { *out = *in - if in.PostgreSQL != nil { - in, out := &in.PostgreSQL, &out.PostgreSQL - *out = new(PersistencePostgreSQL) + out.SecretRef = in.SecretRef + if in.ServiceRef != nil { + in, out := &in.ServiceRef, &out.ServiceRef + *out = new(PostgreSQLServiceOptions) (*in).DeepCopyInto(*out) } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PersistenceSpec. -func (in *PersistenceSpec) DeepCopy() *PersistenceSpec { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PersistencePostgreSQL. +func (in *PersistencePostgreSQL) DeepCopy() *PersistencePostgreSQL { if in == nil { return nil } - out := new(PersistenceSpec) + out := new(PersistencePostgreSQL) in.DeepCopyInto(out) return out } @@ -645,7 +645,7 @@ func (in *ServiceSpec) DeepCopyInto(out *ServiceSpec) { } if in.Persistence != nil { in, out := &in.Persistence, &out.Persistence - *out = new(PersistenceSpec) + *out = new(PersistencePlatformSpec) (*in).DeepCopyInto(*out) } in.PodTemplate.DeepCopyInto(&out.PodTemplate) @@ -1030,7 +1030,7 @@ func (in *SonataFlowPlatformSpec) DeepCopyInto(out *SonataFlowPlatformSpec) { in.Services.DeepCopyInto(&out.Services) if in.Persistence != nil { in, out := &in.Persistence, &out.Persistence - *out = new(PersistenceSpec) + *out = new(PersistencePlatformSpec) (*in).DeepCopyInto(*out) } } @@ -1081,7 +1081,7 @@ func (in *SonataFlowSpec) DeepCopyInto(out *SonataFlowSpec) { in.PodTemplate.DeepCopyInto(&out.PodTemplate) if in.Persistence != nil { in, out := &in.Persistence, &out.Persistence - *out = new(PersistenceSpec) + *out = new(PersistencePlatformSpec) (*in).DeepCopyInto(*out) } } diff --git a/controllers/platform/k8s.go b/controllers/platform/k8s.go index 1ebe707df..f2e5313e7 100644 --- a/controllers/platform/k8s.go +++ b/controllers/platform/k8s.go @@ -61,19 +61,17 @@ func (action *serviceAction) Handle(ctx context.Context, platform *operatorapi.S return nil, err } - if platform.Spec.Services != nil { - psDI := services.NewDataIndexHandler(platform) - if psDI.IsServiceSetInSpec() { - if err := createOrUpdateServiceComponents(ctx, action.client, platform, psDI); err != nil { - return nil, err - } + psDI := services.NewDataIndexHandler(platform) + if psDI.IsServiceSetInSpec() { + if err := createOrUpdateServiceComponents(ctx, action.client, platform, psDI); err != nil { + return nil, err } + } - psJS := services.NewJobServiceHandler(platform) - if psJS.IsServiceSetInSpec() { - if err := createOrUpdateServiceComponents(ctx, action.client, platform, psJS); err != nil { - return nil, err - } + psJS := services.NewJobServiceHandler(platform) + if psJS.IsServiceSetInSpec() { + if err := createOrUpdateServiceComponents(ctx, action.client, platform, psJS); err != nil { + return nil, err } } diff --git a/controllers/platform/platformutils.go b/controllers/platform/platformutils.go index ae14c40e9..9249bed01 100644 --- a/controllers/platform/platformutils.go +++ b/controllers/platform/platformutils.go @@ -111,15 +111,13 @@ func setPlatformDefaults(p *operatorapi.SonataFlowPlatform, verbose bool) error } // When dataIndex object set, default to enabled if bool not set - if p.Spec.Services != nil { - var enable = true - if p.Spec.Services.DataIndex != nil && p.Spec.Services.DataIndex.Enabled == nil { - p.Spec.Services.DataIndex.Enabled = &enable - } - // When the JobService field has a value, default to enabled if the `Enabled` field's value is nil - if p.Spec.Services.JobService != nil && p.Spec.Services.JobService.Enabled == nil { - p.Spec.Services.JobService.Enabled = &enable - } + var enable = true + if p.Spec.Services.DataIndex != nil && p.Spec.Services.DataIndex.Enabled == nil { + p.Spec.Services.DataIndex.Enabled = &enable + } + // When the JobService field has a value, default to enabled if the `Enabled` field's value is nil + if p.Spec.Services.JobService != nil && p.Spec.Services.JobService.Enabled == nil { + p.Spec.Services.JobService.Enabled = &enable } setStatusAdditionalInfo(p) diff --git a/controllers/platform/services/properties_services_test.go b/controllers/platform/services/properties_services_test.go index b0e81821a..c0983b0b7 100644 --- a/controllers/platform/services/properties_services_test.go +++ b/controllers/platform/services/properties_services_test.go @@ -223,7 +223,7 @@ func setJobServiceJDBC(jdbc string) plfmOptionFn { p.Spec.Services.JobService = &operatorapi.ServiceSpec{} } if p.Spec.Services.JobService.Persistence == nil { - p.Spec.Services.JobService.Persistence = &operatorapi.PersistenceSpec{} + p.Spec.Services.JobService.Persistence = &operatorapi.PersistencePlatformSpec{} } if p.Spec.Services.JobService.Persistence.PostgreSQL == nil { p.Spec.Services.JobService.Persistence.PostgreSQL = &operatorapi.PersistencePostgreSQL{} @@ -238,7 +238,7 @@ func setDataIndexJDBC(jdbc string) plfmOptionFn { p.Spec.Services.DataIndex = &operatorapi.ServiceSpec{} } if p.Spec.Services.DataIndex.Persistence == nil { - p.Spec.Services.DataIndex.Persistence = &operatorapi.PersistenceSpec{} + p.Spec.Services.DataIndex.Persistence = &operatorapi.PersistencePlatformSpec{} } if p.Spec.Services.DataIndex.Persistence.PostgreSQL == nil { p.Spec.Services.DataIndex.Persistence.PostgreSQL = &operatorapi.PersistencePostgreSQL{} diff --git a/controllers/platform/services/services.go b/controllers/platform/services/services.go index 4ce41687d..d75a5a6bb 100644 --- a/controllers/platform/services/services.go +++ b/controllers/platform/services/services.go @@ -408,21 +408,16 @@ func (j JobServiceHandler) GenerateServiceProperties() (*properties.Properties, props.Set(constants.JobServiceKafkaSmallRyeHealthProperty, "false") // add data source reactive URL if j.hasPostgreSQLConfigured() { - var dataSourceReactiveURL string - var err error jspec := j.platform.Spec.Services.JobService + var pspec *operatorapi.PersistencePostgreSQL if j.IsServiceSetInSpec() && jspec.Persistence != nil && jspec.Persistence.PostgreSQL != nil { - dataSourceReactiveURL, err = generateReactiveURL(j.platform.Spec.Services.JobService.Persistence.PostgreSQL, j.GetServiceName(), j.platform.Namespace, constants.DefaultDatabaseName, constants.DefaultPostgreSQLPort) - if err != nil { - return nil, err - } + pspec = j.platform.Spec.Services.JobService.Persistence.PostgreSQL } else { - p := j.platform.Spec.Persistence.PostgreSQL - var namespace string - if len(p.ServiceRef.Namespace) > 0 { - namespace = fmt.Sprintf(".%s", p.ServiceRef.Namespace) - } - dataSourceReactiveURL = fmt.Sprintf("%s://%s%s:%d/%s?search_path=%s", constants.PersistenceTypePostgreSQL, p.ServiceRef.Name, namespace, *p.ServiceRef.Port, p.ServiceRef.DatabaseName, j.GetServiceName()) + pspec = j.platform.Spec.Persistence.PostgreSQL + } + dataSourceReactiveURL, err := generateReactiveURL(pspec, j.GetServiceName(), j.platform.Namespace, constants.DefaultDatabaseName, constants.DefaultPostgreSQLPort) + if err != nil { + return nil, err } props.Set(constants.JobServiceDataSourceReactiveURL, dataSourceReactiveURL) } diff --git a/controllers/profiles/common/ensurer.go b/controllers/profiles/common/ensurer.go index 7e2d63ec6..980d5cbf5 100644 --- a/controllers/profiles/common/ensurer.go +++ b/controllers/profiles/common/ensurer.go @@ -34,10 +34,10 @@ var _ ObjectEnsurer = &defaultObjectEnsurer{} var _ ObjectEnsurer = &noopObjectEnsurer{} type ObjectEnsurer interface { - Ensure(ctx context.Context, workflow *operatorapi.SonataFlow, plf *operatorapi.SonataFlowPlatform, visitors ...MutateVisitor) (client.Object, controllerutil.OperationResult, error) + Ensure(ctx context.Context, workflow *operatorapi.SonataFlow, visitors ...MutateVisitor) (client.Object, controllerutil.OperationResult, error) } type ObjectEnsurerWithPlatform interface { - Ensure(ctx context.Context, workflow *operatorapi.SonataFlow, platform *operatorapi.SonataFlowPlatform, visitors ...MutateVisitor) (client.Object, controllerutil.OperationResult, error) + Ensure(ctx context.Context, workflow *operatorapi.SonataFlow, pl *operatorapi.SonataFlowPlatform, visitors ...MutateVisitor) (client.Object, controllerutil.OperationResult, error) } // MutateVisitor is a visitor function that mutates the given object before performing any updates in the cluster. @@ -73,10 +73,10 @@ type defaultObjectEnsurer struct { creator ObjectCreator } -func (d *defaultObjectEnsurer) Ensure(ctx context.Context, workflow *operatorapi.SonataFlow, plf *operatorapi.SonataFlowPlatform, visitors ...MutateVisitor) (client.Object, controllerutil.OperationResult, error) { +func (d *defaultObjectEnsurer) Ensure(ctx context.Context, workflow *operatorapi.SonataFlow, visitors ...MutateVisitor) (client.Object, controllerutil.OperationResult, error) { result := controllerutil.OperationResultNone - object, err := d.creator(workflow, plf) + object, err := d.creator(workflow) if err != nil { return nil, result, err } @@ -132,7 +132,7 @@ func NewNoopObjectEnsurer() ObjectEnsurer { type noopObjectEnsurer struct { } -func (d *noopObjectEnsurer) Ensure(ctx context.Context, workflow *operatorapi.SonataFlow, plf *operatorapi.SonataFlowPlatform, visitors ...MutateVisitor) (client.Object, controllerutil.OperationResult, error) { +func (d *noopObjectEnsurer) Ensure(ctx context.Context, workflow *operatorapi.SonataFlow, visitors ...MutateVisitor) (client.Object, controllerutil.OperationResult, error) { result := controllerutil.OperationResultNone return nil, result, nil } diff --git a/controllers/profiles/common/mutate_visitors.go b/controllers/profiles/common/mutate_visitors.go index d264cd595..6b70bc0f1 100644 --- a/controllers/profiles/common/mutate_visitors.go +++ b/controllers/profiles/common/mutate_visitors.go @@ -27,7 +27,6 @@ import ( "github.com/imdario/mergo" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" - v1 "k8s.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" @@ -94,7 +93,7 @@ func ServiceMutateVisitor(workflow *operatorapi.SonataFlow) MutateVisitor { if kubeutil.IsObjectNew(object) { return nil } - original, err := ServiceCreator(workflow, nil) + original, err := ServiceCreator(workflow) if err != nil { return err } @@ -106,7 +105,7 @@ func ServiceMutateVisitor(workflow *operatorapi.SonataFlow) MutateVisitor { } func ManagedPropertiesMutateVisitor(ctx context.Context, catalog discovery.ServiceCatalog, - workflow *operatorapi.SonataFlow, platform *operatorapi.SonataFlowPlatform, userProps *corev1.ConfigMap) MutateVisitor { + workflow *operatorapi.SonataFlow, plf *operatorapi.SonataFlowPlatform, userProps *corev1.ConfigMap) MutateVisitor { return func(object client.Object) controllerutil.MutateFn { return func() error { managedProps := object.(*corev1.ConfigMap) @@ -138,7 +137,7 @@ func ManagedPropertiesMutateVisitor(ctx context.Context, catalog discovery.Servi // This method can be used as an alternative to the Kubernetes ConfigMap refresher. // // See: https://kubernetes.io/docs/concepts/configuration/configmap/#mounted-configmaps-are-updated-automatically -func RolloutDeploymentIfCMChangedMutateVisitor(workflow *operatorapi.SonataFlow, userPropsCM *v1.ConfigMap, managedPropsCM *v1.ConfigMap) MutateVisitor { +func RolloutDeploymentIfCMChangedMutateVisitor(workflow *operatorapi.SonataFlow, userPropsCM *corev1.ConfigMap, managedPropsCM *corev1.ConfigMap) MutateVisitor { return func(object client.Object) controllerutil.MutateFn { return func() error { deployment := object.(*appsv1.Deployment) diff --git a/controllers/profiles/common/object_creators.go b/controllers/profiles/common/object_creators.go index 0aa72a4e5..4806ec497 100644 --- a/controllers/profiles/common/object_creators.go +++ b/controllers/profiles/common/object_creators.go @@ -39,7 +39,7 @@ import ( // ObjectCreator is the func that creates the initial reference object, if the object doesn't exist in the cluster, this one is created. // Can be used as a reference to keep the object immutable -type ObjectCreator func(workflow *operatorapi.SonataFlow, plf *operatorapi.SonataFlowPlatform) (client.Object, error) +type ObjectCreator func(workflow *operatorapi.SonataFlow) (client.Object, error) // ObjectCreatorWithPlatform is the func equivalent to ObjectCreator to use when the resource being created needs a reference to the // SonataFlowPlatform @@ -60,7 +60,7 @@ const ( // DeploymentCreator is an objectCreator for a base Kubernetes Deployments for profiles that need to deploy the workflow on a vanilla deployment. // It serves as a basis for a basic Quarkus Java application, expected to listen on http 8080. -func DeploymentCreator(workflow *operatorapi.SonataFlow, platform *operatorapi.SonataFlowPlatform) (client.Object, error) { +func DeploymentCreator(workflow *operatorapi.SonataFlow, plf *operatorapi.SonataFlowPlatform) (client.Object, error) { lbl := workflowproj.GetDefaultLabels(workflow) deployment := &appsv1.Deployment{ @@ -86,7 +86,7 @@ func DeploymentCreator(workflow *operatorapi.SonataFlow, platform *operatorapi.S if err := mergo.Merge(&deployment.Spec.Template.Spec, workflow.Spec.PodTemplate.PodSpec.ToPodSpec(), mergo.WithOverride); err != nil { return nil, err } - flowContainer, err := defaultContainer(workflow, platform) + flowContainer, err := defaultContainer(workflow, plf) if err != nil { return nil, err } @@ -181,7 +181,7 @@ func defaultContainer(workflow *operatorapi.SonataFlow, plf *operatorapi.SonataF // ServiceCreator is an objectCreator for a basic Service aiming a vanilla Kubernetes Deployment. // It maps the default HTTP port (80) to the target Java application webserver on port 8080. -func ServiceCreator(workflow *operatorapi.SonataFlow, _ *operatorapi.SonataFlowPlatform) (client.Object, error) { +func ServiceCreator(workflow *operatorapi.SonataFlow) (client.Object, error) { lbl := workflowproj.GetDefaultLabels(workflow) service := &corev1.Service{ @@ -206,7 +206,7 @@ func ServiceCreator(workflow *operatorapi.SonataFlow, _ *operatorapi.SonataFlowP // OpenShiftRouteCreator is an ObjectCreator for a basic Route for a workflow running on OpenShift. // It enables the exposition of the service using an OpenShift Route. // See: https://github.com/openshift/api/blob/d170fcdc0fa638b664e4f35f2daf753cb4afe36b/route/v1/route.crd.yaml -func OpenShiftRouteCreator(workflow *operatorapi.SonataFlow, _ *operatorapi.SonataFlowPlatform) (client.Object, error) { +func OpenShiftRouteCreator(workflow *operatorapi.SonataFlow) (client.Object, error) { route, err := openshift.RouteForWorkflow(workflow) return route, err } diff --git a/controllers/profiles/common/object_creators_test.go b/controllers/profiles/common/object_creators_test.go index e1e1c9782..9e1a29b4d 100644 --- a/controllers/profiles/common/object_creators_test.go +++ b/controllers/profiles/common/object_creators_test.go @@ -27,6 +27,7 @@ import ( "github.com/stretchr/testify/assert" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/apache/incubator-kie-kogito-serverless-operator/utils" kubeutil "github.com/apache/incubator-kie-kogito-serverless-operator/utils/kubernetes" @@ -213,7 +214,7 @@ func TestMergePodSpec_WithPostgreSQL_and_JDBC_URL_field(t *testing.T) { }, }, }, - Persistence: &v1alpha08.PersistenceSpec{ + Persistence: &v1alpha08.PersistencePlatformSpec{ PostgreSQL: &v1alpha08.PersistencePostgreSQL{ SecretRef: v1alpha08.PostgreSQLSecretOptions{Name: "test"}, JdbcUrl: "jdbc:postgresql://host:port/database?currentSchema=workflow", @@ -303,7 +304,7 @@ func TestMergePodSpec_OverrideContainers_WithPostgreSQL_In_Workflow_CR(t *testin }, }, }, - Persistence: &v1alpha08.PersistenceSpec{ + Persistence: &v1alpha08.PersistencePlatformSpec{ PostgreSQL: &v1alpha08.PersistencePostgreSQL{ SecretRef: v1alpha08.PostgreSQLSecretOptions{Name: "test"}, ServiceRef: &v1alpha08.PostgreSQLServiceOptions{ @@ -374,7 +375,7 @@ func TestMergePodSpec_WithServicedPostgreSQL_In_Platform_CR_And_Worflow_Requesti Namespace: "default", }, Spec: v1alpha08.SonataFlowPlatformSpec{ - Persistence: &v1alpha08.PersistenceSpec{ + Persistence: &v1alpha08.PersistencePlatformSpec{ PostgreSQL: &v1alpha08.PersistencePostgreSQL{ SecretRef: v1alpha08.PostgreSQLSecretOptions{ Name: "foo_secret", @@ -395,7 +396,7 @@ func TestMergePodSpec_WithServicedPostgreSQL_In_Platform_CR_And_Worflow_Requesti workflow := test.GetBaseSonataFlow(t.Name()) workflow.Spec = v1alpha08.SonataFlowSpec{ - Persistence: &v1alpha08.PersistenceSpec{}, + Persistence: &v1alpha08.PersistencePlatformSpec{}, } object, err := DeploymentCreator(workflow, p) assert.NoError(t, err) @@ -455,7 +456,7 @@ func TestMergePodSpec_WithServicedPostgreSQL_In_Platform_And_In_Workflow_CR(t *t Namespace: "default", }, Spec: v1alpha08.SonataFlowPlatformSpec{ - Persistence: &v1alpha08.PersistenceSpec{ + Persistence: &v1alpha08.PersistencePlatformSpec{ PostgreSQL: &v1alpha08.PersistencePostgreSQL{ SecretRef: v1alpha08.PostgreSQLSecretOptions{ Name: "foo_secret", @@ -492,7 +493,7 @@ func TestMergePodSpec_WithServicedPostgreSQL_In_Platform_And_In_Workflow_CR(t *t }, }, }, - Persistence: &v1alpha08.PersistenceSpec{ + Persistence: &v1alpha08.PersistencePlatformSpec{ PostgreSQL: &v1alpha08.PersistencePostgreSQL{ SecretRef: v1alpha08.PostgreSQLSecretOptions{Name: "test"}, ServiceRef: &v1alpha08.PostgreSQLServiceOptions{ @@ -562,7 +563,7 @@ func TestMergePodSpec_WithServicedPostgreSQL_In_Platform_But_Workflow_CR_Not_Req Namespace: "default", }, Spec: v1alpha08.SonataFlowPlatformSpec{ - Persistence: &v1alpha08.PersistenceSpec{ + Persistence: &v1alpha08.PersistencePlatformSpec{ PostgreSQL: &v1alpha08.PersistencePostgreSQL{ SecretRef: v1alpha08.PostgreSQLSecretOptions{ Name: "foo_secret", @@ -604,7 +605,7 @@ func TestMergePodSpec_WithEphemeralPostgreSQL_And_Undefined_PostgreSQL_Image_In_ } workflow := test.GetBaseSonataFlow(t.Name()) workflow.Spec = v1alpha08.SonataFlowSpec{ - Persistence: &v1alpha08.PersistenceSpec{}, + Persistence: &v1alpha08.PersistencePlatformSpec{}, } _, err := DeploymentCreator(workflow, p) assert.Error(t, err) diff --git a/controllers/profiles/common/persistence/postgresql.go b/controllers/profiles/common/persistence/postgresql.go index f0f77a2ca..3ab969634 100644 --- a/controllers/profiles/common/persistence/postgresql.go +++ b/controllers/profiles/common/persistence/postgresql.go @@ -114,7 +114,7 @@ func ConfigurePostgreSQLEnv(postgresql *operatorapi.PersistencePostgreSQL, datab } } -func ConfigurePersistence(serviceContainer *corev1.Container, config *operatorapi.PersistenceSpec, defaultSchema, namespace string) (*corev1.Container, error) { +func ConfigurePersistence(serviceContainer *corev1.Container, config *operatorapi.PersistencePlatformSpec, defaultSchema, namespace string) (*corev1.Container, error) { if config == nil { return nil, fmt.Errorf("no persistence specification found") } diff --git a/controllers/profiles/common/properties/application_test.go b/controllers/profiles/common/properties/application_test.go index ca6a7327b..815bbf494 100644 --- a/controllers/profiles/common/properties/application_test.go +++ b/controllers/profiles/common/properties/application_test.go @@ -203,7 +203,7 @@ func Test_appPropertyHandler_WithServicesWithUserOverrides(t *testing.T) { platform := test.GetBasePlatform() platform.Namespace = ns platform.Spec = operatorapi.SonataFlowPlatformSpec{ - Services: &operatorapi.ServicesPlatformSpec{ + Services: operatorapi.ServicesPlatformSpec{ DataIndex: &operatorapi.ServiceSpec{ Enabled: &enabled, }, @@ -622,9 +622,6 @@ func generatePlatform(opts ...plfmOptionFn) *operatorapi.SonataFlowPlatform { func setJobServiceEnabledValue(v *bool) plfmOptionFn { return func(p *operatorapi.SonataFlowPlatform) { - if p.Spec.Services == nil { - p.Spec.Services = &operatorapi.ServicesPlatformSpec{} - } if p.Spec.Services.JobService == nil { p.Spec.Services.JobService = &operatorapi.ServiceSpec{} } @@ -634,9 +631,6 @@ func setJobServiceEnabledValue(v *bool) plfmOptionFn { func setDataIndexEnabledValue(v *bool) plfmOptionFn { return func(p *operatorapi.SonataFlowPlatform) { - if p.Spec.Services == nil { - p.Spec.Services = &operatorapi.ServicesPlatformSpec{} - } if p.Spec.Services.DataIndex == nil { p.Spec.Services.DataIndex = &operatorapi.ServiceSpec{} } @@ -658,14 +652,11 @@ func setPlatformName(name string) plfmOptionFn { func setJobServiceJDBC(jdbc string) plfmOptionFn { return func(p *operatorapi.SonataFlowPlatform) { - if p.Spec.Services == nil { - p.Spec.Services = &operatorapi.ServicesPlatformSpec{} - } if p.Spec.Services.JobService == nil { p.Spec.Services.JobService = &operatorapi.ServiceSpec{} } if p.Spec.Services.JobService.Persistence == nil { - p.Spec.Services.JobService.Persistence = &operatorapi.PersistenceSpec{} + p.Spec.Services.JobService.Persistence = &operatorapi.PersistencePlatformSpec{} } if p.Spec.Services.JobService.Persistence.PostgreSQL == nil { p.Spec.Services.JobService.Persistence.PostgreSQL = &operatorapi.PersistencePostgreSQL{} diff --git a/controllers/profiles/common/reconciler.go b/controllers/profiles/common/reconciler.go index 7deb259ec..da29a10a7 100644 --- a/controllers/profiles/common/reconciler.go +++ b/controllers/profiles/common/reconciler.go @@ -70,9 +70,9 @@ func NewReconciler(support *StateSupport, stateMachine *ReconciliationStateMachi } // Reconcile does the actual reconciliation algorithm based on a set of ReconciliationState -func (b *Reconciler) Reconcile(ctx context.Context, workflow *operatorapi.SonataFlow, plf *operatorapi.SonataFlowPlatform) (ctrl.Result, error) { +func (b *Reconciler) Reconcile(ctx context.Context, workflow *operatorapi.SonataFlow) (ctrl.Result, error) { workflow.Status.Manager().InitializeConditions() - result, objects, err := b.reconciliationStateMachine.do(ctx, workflow, plf) + result, objects, err := b.reconciliationStateMachine.do(ctx, workflow) if err != nil { return result, err } @@ -97,11 +97,11 @@ type ReconciliationStateMachine struct { states []profiles.ReconciliationState } -func (r *ReconciliationStateMachine) do(ctx context.Context, workflow *operatorapi.SonataFlow, plf *operatorapi.SonataFlowPlatform) (ctrl.Result, []client.Object, error) { +func (r *ReconciliationStateMachine) do(ctx context.Context, workflow *operatorapi.SonataFlow) (ctrl.Result, []client.Object, error) { for _, h := range r.states { if h.CanReconcile(workflow) { klog.V(log.I).InfoS("Found a condition to reconcile.", "Conditions", workflow.Status.Conditions) - result, objs, err := h.Do(ctx, workflow, plf) + result, objs, err := h.Do(ctx, workflow) if err != nil { return result, objs, err } diff --git a/controllers/profiles/dev/object_creators_dev.go b/controllers/profiles/dev/object_creators_dev.go index 43e60aa79..e5322dfed 100644 --- a/controllers/profiles/dev/object_creators_dev.go +++ b/controllers/profiles/dev/object_creators_dev.go @@ -44,8 +44,8 @@ const ( // aiming a vanilla Kubernetes Deployment. // It maps the default HTTP port (80) to the target Java application webserver on port 8080. // It configures the Service as a NodePort type service, in this way it will be easier for a developer access the service -func serviceCreator(workflow *operatorapi.SonataFlow, plf *operatorapi.SonataFlowPlatform) (client.Object, error) { - object, _ := common.ServiceCreator(workflow, plf) +func serviceCreator(workflow *operatorapi.SonataFlow) (client.Object, error) { + object, _ := common.ServiceCreator(workflow) service := object.(*corev1.Service) // Let's double-check that the workflow is using the Dev Profile we would like to expose it via NodePort if profiles.IsDevProfile(workflow) { @@ -54,8 +54,9 @@ func serviceCreator(workflow *operatorapi.SonataFlow, plf *operatorapi.SonataFlo return service, nil } -func deploymentCreator(workflow *operatorapi.SonataFlow, platform *operatorapi.SonataFlowPlatform) (client.Object, error) { - obj, err := common.DeploymentCreator(workflow, platform) +func deploymentCreator(workflow *operatorapi.SonataFlow, plf *operatorapi.SonataFlowPlatform) (client.Object, error) { + + obj, err := common.DeploymentCreator(workflow, plf) if err != nil { return nil, err } @@ -74,7 +75,7 @@ func deploymentCreator(workflow *operatorapi.SonataFlow, platform *operatorapi.S } // workflowDefConfigMapCreator creates a new ConfigMap that holds the definition of a workflow specification. -func workflowDefConfigMapCreator(workflow *operatorapi.SonataFlow, _ *operatorapi.SonataFlowPlatform) (client.Object, error) { +func workflowDefConfigMapCreator(workflow *operatorapi.SonataFlow) (client.Object, error) { configMap, err := workflowdef.CreateNewConfigMap(workflow) if err != nil { return nil, err @@ -100,13 +101,13 @@ func deploymentMutateVisitor(workflow *operatorapi.SonataFlow, plf *operatorapi. } } -func ensureWorkflowDefConfigMapMutator(workflow *operatorapi.SonataFlow, plf *operatorapi.SonataFlowPlatform) common.MutateVisitor { +func ensureWorkflowDefConfigMapMutator(workflow *operatorapi.SonataFlow) common.MutateVisitor { return func(object client.Object) controllerutil.MutateFn { return func() error { if kubeutil.IsObjectNew(object) { return nil } - original, err := workflowDefConfigMapCreator(workflow, plf) + original, err := workflowDefConfigMapCreator(workflow) if err != nil { return err } diff --git a/controllers/profiles/dev/object_creators_dev_test.go b/controllers/profiles/dev/object_creators_dev_test.go index 0a35499c3..8209940a2 100644 --- a/controllers/profiles/dev/object_creators_dev_test.go +++ b/controllers/profiles/dev/object_creators_dev_test.go @@ -31,7 +31,7 @@ import ( func Test_ensureWorkflowDevServiceIsExposed(t *testing.T) { workflow := test.GetBaseSonataFlowWithDevProfile(t.Name()) //On Kubernetes we want the service exposed in Dev with NodePort - service, _ := serviceCreator(workflow, nil) + service, _ := serviceCreator(workflow) service.SetUID("1") service.SetResourceVersion("1") diff --git a/controllers/profiles/dev/profile_dev.go b/controllers/profiles/dev/profile_dev.go index 42b9151ab..4093365e1 100644 --- a/controllers/profiles/dev/profile_dev.go +++ b/controllers/profiles/dev/profile_dev.go @@ -75,7 +75,7 @@ func NewProfileReconciler(client client.Client, cfg *rest.Config, recorder recor func newObjectEnsurers(support *common.StateSupport) *objectEnsurers { return &objectEnsurers{ - deployment: common.NewObjectEnsurer(support.C, deploymentCreator), + deployment: common.NewObjectEnsurerWithPlatform(support.C, deploymentCreator), service: common.NewObjectEnsurer(support.C, serviceCreator), network: common.NewNoopObjectEnsurer(), definitionConfigMap: common.NewObjectEnsurer(support.C, workflowDefConfigMapCreator), @@ -86,7 +86,7 @@ func newObjectEnsurers(support *common.StateSupport) *objectEnsurers { func newObjectEnsurersOpenShift(support *common.StateSupport) *objectEnsurers { return &objectEnsurers{ - deployment: common.NewObjectEnsurer(support.C, deploymentCreator), + deployment: common.NewObjectEnsurerWithPlatform(support.C, deploymentCreator), service: common.NewObjectEnsurer(support.C, serviceCreator), network: common.NewObjectEnsurer(support.C, common.OpenShiftRouteCreator), definitionConfigMap: common.NewObjectEnsurer(support.C, workflowDefConfigMapCreator), @@ -108,7 +108,7 @@ func newStatusEnrichersOpenShift(support *common.StateSupport) *statusEnrichers } type objectEnsurers struct { - deployment common.ObjectEnsurer + deployment common.ObjectEnsurerWithPlatform service common.ObjectEnsurer network common.ObjectEnsurer definitionConfigMap common.ObjectEnsurer diff --git a/controllers/profiles/dev/profile_dev_test.go b/controllers/profiles/dev/profile_dev_test.go index d7fd5478f..1c3478ea0 100644 --- a/controllers/profiles/dev/profile_dev_test.go +++ b/controllers/profiles/dev/profile_dev_test.go @@ -60,7 +60,7 @@ func Test_OverrideStartupProbe(t *testing.T) { devReconciler := NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()) - result, err := devReconciler.Reconcile(context.TODO(), workflow, nil) + result, err := devReconciler.Reconcile(context.TODO(), workflow) assert.NoError(t, err) assert.NotNil(t, result) @@ -71,7 +71,7 @@ func Test_OverrideStartupProbe(t *testing.T) { deployment.Spec.Template.Spec.Containers[0].StartupProbe.FailureThreshold = newThreshold assert.NoError(t, client.Update(context.TODO(), deployment)) // reconcile and fetch from the cluster - result, err = devReconciler.Reconcile(context.TODO(), workflow, nil) + result, err = devReconciler.Reconcile(context.TODO(), workflow) assert.NoError(t, err) assert.NotNil(t, result) deployment = test.MustGetDeployment(t, client, workflow) @@ -88,14 +88,14 @@ func Test_recoverFromFailureNoDeployment(t *testing.T) { reconciler := NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()) // we are in failed state and have no objects - result, err := reconciler.Reconcile(context.TODO(), workflow, nil) + result, err := reconciler.Reconcile(context.TODO(), workflow) assert.NoError(t, err) assert.NotNil(t, result) // the recover state tried to clear the conditions of our workflow, so we can try reconciling it again workflow = test.MustGetWorkflow(t, client, workflowID) assert.True(t, workflow.Status.GetTopLevelCondition().IsUnknown()) - result, err = reconciler.Reconcile(context.TODO(), workflow, nil) + result, err = reconciler.Reconcile(context.TODO(), workflow) assert.NoError(t, err) assert.NotNil(t, result) @@ -109,7 +109,7 @@ func Test_recoverFromFailureNoDeployment(t *testing.T) { assert.NoError(t, err) // the fake client won't update the deployment status condition since we don't have a deployment controller // our state will think that we don't have a deployment available yet, so it will try to reset the pods - result, err = reconciler.Reconcile(context.TODO(), workflow, nil) + result, err = reconciler.Reconcile(context.TODO(), workflow) assert.NoError(t, err) assert.NotNil(t, result) @@ -128,7 +128,7 @@ func Test_newDevProfile(t *testing.T) { devReconciler := NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()) - result, err := devReconciler.Reconcile(context.TODO(), workflow, nil) + result, err := devReconciler.Reconcile(context.TODO(), workflow) assert.NoError(t, err) assert.NotNil(t, result) @@ -169,7 +169,7 @@ func Test_newDevProfile(t *testing.T) { assert.NoError(t, err) // reconcile again - result, err = devReconciler.Reconcile(context.TODO(), workflow, nil) + result, err = devReconciler.Reconcile(context.TODO(), workflow) assert.NoError(t, err) assert.NotNil(t, result) @@ -196,7 +196,7 @@ func Test_newDevProfile(t *testing.T) { workflow.Status.Manager().MarkTrue(api.RunningConditionType) err = client.Status().Update(context.TODO(), workflow) assert.NoError(t, err) - result, err = devReconciler.Reconcile(context.TODO(), workflow, nil) + result, err = devReconciler.Reconcile(context.TODO(), workflow) assert.NoError(t, err) assert.NotNil(t, result) @@ -209,7 +209,7 @@ func Test_devProfileImageDefaultsNoPlatform(t *testing.T) { client := test.NewSonataFlowClientBuilder().WithRuntimeObjects(workflow).WithStatusSubresource(workflow).Build() devReconciler := NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()) - result, err := devReconciler.Reconcile(context.TODO(), workflow, nil) + result, err := devReconciler.Reconcile(context.TODO(), workflow) assert.NoError(t, err) assert.NotNil(t, result) @@ -226,7 +226,7 @@ func Test_devProfileWithImageSnapshotOverrideWithPlatform(t *testing.T) { client := test.NewSonataFlowClientBuilder().WithRuntimeObjects(workflow, platform).WithStatusSubresource(workflow, platform).Build() devReconciler := NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()) - result, err := devReconciler.Reconcile(context.TODO(), workflow, platform) + result, err := devReconciler.Reconcile(context.TODO(), workflow) assert.NoError(t, err) assert.NotNil(t, result) @@ -243,7 +243,7 @@ func Test_devProfileWithWPlatformWithoutDevBaseImageAndWithBaseImage(t *testing. client := test.NewSonataFlowClientBuilder().WithRuntimeObjects(workflow, platform).WithStatusSubresource(workflow, platform).Build() devReconciler := NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()) - result, err := devReconciler.Reconcile(context.TODO(), workflow, nil) + result, err := devReconciler.Reconcile(context.TODO(), workflow) assert.NoError(t, err) assert.NotNil(t, result) @@ -260,7 +260,7 @@ func Test_devProfileWithPlatformWithoutDevBaseImageAndWithoutBaseImage(t *testin client := test.NewSonataFlowClientBuilder().WithRuntimeObjects(workflow, platform).WithStatusSubresource(workflow, platform).Build() devReconciler := NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()) - result, err := devReconciler.Reconcile(context.TODO(), workflow, nil) + result, err := devReconciler.Reconcile(context.TODO(), workflow) assert.NoError(t, err) assert.NotNil(t, result) @@ -305,7 +305,7 @@ func Test_newDevProfileWithExternalConfigMaps(t *testing.T) { errCreate := client.Create(context.Background(), cmUser) assert.Nil(t, errCreate) - result, err := devReconciler.Reconcile(context.TODO(), workflow, nil) + result, err := devReconciler.Reconcile(context.TODO(), workflow) assert.NoError(t, err) assert.NotNil(t, result) @@ -330,7 +330,7 @@ func Test_newDevProfileWithExternalConfigMaps(t *testing.T) { workflow.Status.Manager().MarkTrue(api.RunningConditionType) err = client.Update(context.TODO(), workflow) assert.NoError(t, err) - result, err = devReconciler.Reconcile(context.TODO(), workflow, nil) + result, err = devReconciler.Reconcile(context.TODO(), workflow) assert.NoError(t, err) assert.NotNil(t, result) @@ -346,7 +346,7 @@ func Test_newDevProfileWithExternalConfigMaps(t *testing.T) { workflow.Status.Manager().MarkTrue(api.RunningConditionType) err = client.Update(context.TODO(), workflow) assert.NoError(t, err) - result, err = devReconciler.Reconcile(context.TODO(), workflow, nil) + result, err = devReconciler.Reconcile(context.TODO(), workflow) assert.NoError(t, err) assert.NotNil(t, result) @@ -362,7 +362,7 @@ func Test_newDevProfileWithExternalConfigMaps(t *testing.T) { workflow.Status.Manager().MarkTrue(api.RunningConditionType) err = client.Status().Update(context.TODO(), workflow) assert.NoError(t, err) - result, err = devReconciler.Reconcile(context.TODO(), workflow, nil) + result, err = devReconciler.Reconcile(context.TODO(), workflow) assert.NoError(t, err) assert.NotNil(t, result) assert.Equal(t, api.ExternalResourcesNotFoundReason, workflow.Status.GetTopLevelCondition().Reason) @@ -370,7 +370,7 @@ func Test_newDevProfileWithExternalConfigMaps(t *testing.T) { // delete the link workflow.Spec.Resources.ConfigMaps = nil assert.NoError(t, client.Update(context.TODO(), workflow)) - result, err = devReconciler.Reconcile(context.TODO(), workflow, nil) + result, err = devReconciler.Reconcile(context.TODO(), workflow) assert.NoError(t, err) assert.NotNil(t, result) @@ -393,7 +393,7 @@ func Test_VolumeWithCapitalizedPaths(t *testing.T) { devReconciler := NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()) - result, err := devReconciler.Reconcile(context.TODO(), workflow, nil) + result, err := devReconciler.Reconcile(context.TODO(), workflow) assert.NoError(t, err) assert.NotNil(t, result) diff --git a/controllers/profiles/dev/states_dev.go b/controllers/profiles/dev/states_dev.go index 55a4eb5a7..9307c2469 100644 --- a/controllers/profiles/dev/states_dev.go +++ b/controllers/profiles/dev/states_dev.go @@ -34,6 +34,7 @@ import ( "github.com/apache/incubator-kie-kogito-serverless-operator/api" operatorapi "github.com/apache/incubator-kie-kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-kogito-serverless-operator/controllers/platform" "github.com/apache/incubator-kie-kogito-serverless-operator/controllers/profiles/common" "github.com/apache/incubator-kie-kogito-serverless-operator/controllers/profiles/common/constants" "github.com/apache/incubator-kie-kogito-serverless-operator/controllers/workflowdef" @@ -58,10 +59,13 @@ func (e *ensureRunningWorkflowState) CanReconcile(workflow *operatorapi.SonataFl return workflow.Status.IsReady() || workflow.Status.GetTopLevelCondition().IsUnknown() || workflow.Status.IsChildObjectsProblem() } -func (e *ensureRunningWorkflowState) Do(ctx context.Context, workflow *operatorapi.SonataFlow, plf *operatorapi.SonataFlowPlatform) (ctrl.Result, []client.Object, error) { +func (e *ensureRunningWorkflowState) Do(ctx context.Context, workflow *operatorapi.SonataFlow) (ctrl.Result, []client.Object, error) { var objs []client.Object - - flowDefCM, _, err := e.ensurers.definitionConfigMap.Ensure(ctx, workflow, plf, ensureWorkflowDefConfigMapMutator(workflow, plf)) + plf, err := platform.GetActivePlatform(context.TODO(), e.C, workflow.Namespace) + if err != nil { + return ctrl.Result{Requeue: false}, objs, err + } + flowDefCM, _, err := e.ensurers.definitionConfigMap.Ensure(ctx, workflow, ensureWorkflowDefConfigMapMutator(workflow)) if err != nil { return ctrl.Result{Requeue: false}, objs, err } @@ -76,7 +80,7 @@ func (e *ensureRunningWorkflowState) Do(ctx context.Context, workflow *operatora if err != nil { return ctrl.Result{Requeue: false}, objs, err } - managedPropsCM, _, err := e.ensurers.managedPropsConfigMap.Ensure(ctx, workflow, pl, common.ManagedPropertiesMutateVisitor(ctx, e.StateSupport.Catalog, workflow, pl, userPropsCM.(*corev1.ConfigMap))) + managedPropsCM, _, err := e.ensurers.managedPropsConfigMap.Ensure(ctx, workflow, plf, common.ManagedPropertiesMutateVisitor(ctx, e.StateSupport.Catalog, workflow, plf, userPropsCM.(*corev1.ConfigMap))) if err != nil { return ctrl.Result{Requeue: false}, objs, err } @@ -100,13 +104,13 @@ func (e *ensureRunningWorkflowState) Do(ctx context.Context, workflow *operatora } objs = append(objs, deployment) - service, _, err := e.ensurers.service.Ensure(ctx, workflow, plf, common.ServiceMutateVisitor(workflow)) + service, _, err := e.ensurers.service.Ensure(ctx, workflow, common.ServiceMutateVisitor(workflow)) if err != nil { return ctrl.Result{RequeueAfter: constants.RequeueAfterFailure}, objs, err } objs = append(objs, service) - route, _, err := e.ensurers.network.Ensure(ctx, workflow, plf) + route, _, err := e.ensurers.network.Ensure(ctx, workflow) if err != nil { return ctrl.Result{RequeueAfter: constants.RequeueAfterFailure}, objs, err } @@ -151,7 +155,7 @@ func (f *followWorkflowDeploymentState) CanReconcile(workflow *operatorapi.Sonat return workflow.Status.IsWaitingForDeployment() } -func (f *followWorkflowDeploymentState) Do(ctx context.Context, workflow *operatorapi.SonataFlow, plf *operatorapi.SonataFlowPlatform) (ctrl.Result, []client.Object, error) { +func (f *followWorkflowDeploymentState) Do(ctx context.Context, workflow *operatorapi.SonataFlow) (ctrl.Result, []client.Object, error) { result, err := common.DeploymentManager(f.C).SyncDeploymentStatus(ctx, workflow) if err != nil { return ctrl.Result{RequeueAfter: constants.RequeueAfterFailure}, nil, err @@ -189,7 +193,7 @@ func (r *recoverFromFailureState) CanReconcile(workflow *operatorapi.SonataFlow) return workflow.Status.GetCondition(api.RunningConditionType).IsFalse() } -func (r *recoverFromFailureState) Do(ctx context.Context, workflow *operatorapi.SonataFlow, plf *operatorapi.SonataFlowPlatform) (ctrl.Result, []client.Object, error) { +func (r *recoverFromFailureState) Do(ctx context.Context, workflow *operatorapi.SonataFlow) (ctrl.Result, []client.Object, error) { // for now, a very basic attempt to recover by rolling out the deployment deployment := &appsv1.Deployment{} if err := r.C.Get(ctx, client.ObjectKeyFromObject(workflow), deployment); err != nil { diff --git a/controllers/profiles/dev/status_enricher_dev_test.go b/controllers/profiles/dev/status_enricher_dev_test.go index 5da675d47..39e4570df 100644 --- a/controllers/profiles/dev/status_enricher_dev_test.go +++ b/controllers/profiles/dev/status_enricher_dev_test.go @@ -39,7 +39,7 @@ func Test_enrichmentStatusOnK8s(t *testing.T) { workflow := test.GetBaseSonataFlowWithDevProfile(t.Name()) workflow.Namespace = toK8SNamespace(t.Name()) - service, _ := common.ServiceCreator(workflow, nil) + service, _ := common.ServiceCreator(workflow) client := test.NewSonataFlowClientBuilder().WithRuntimeObjects(workflow, service).Build() obj, err := statusEnricher(context.TODO(), client, workflow) @@ -55,7 +55,7 @@ func Test_enrichmentStatusOnK8s(t *testing.T) { workflow := test.GetBaseSonataFlowWithDevProfile(t.Name()) workflow.Namespace = t.Name() - service, _ := serviceCreator(workflow, nil) + service, _ := serviceCreator(workflow) client := test.NewSonataFlowClientBuilder().WithRuntimeObjects(workflow, service).Build() _, err := statusEnricher(context.TODO(), client, workflow) assert.Error(t, err) @@ -67,7 +67,7 @@ func Test_enrichmentStatusOnOCP(t *testing.T) { t.Run("verify that the service URL is returned with the default cluster name on default namespace", func(t *testing.T) { workflow := test.GetBaseSonataFlowWithDevProfile(t.Name()) workflow.Namespace = toK8SNamespace(t.Name()) - service, _ := serviceCreator(workflow, nil) + service, _ := serviceCreator(workflow) route := &openshiftv1.Route{} route.Name = workflow.Name route.Namespace = workflow.Namespace diff --git a/controllers/profiles/prod/deployment_handler.go b/controllers/profiles/prod/deployment_handler.go index 3f885e976..4581f2cce 100644 --- a/controllers/profiles/prod/deployment_handler.go +++ b/controllers/profiles/prod/deployment_handler.go @@ -43,8 +43,8 @@ func newDeploymentReconciler(stateSupport *common.StateSupport, ensurer *objectE } } -func (d *deploymentReconciler) reconcile(ctx context.Context, workflow *operatorapi.SonataFlow, plf *operatorapi.SonataFlowPlatform) (reconcile.Result, []client.Object, error) { - return d.reconcileWithBuiltImage(ctx, workflow, plf, "") +func (d *deploymentReconciler) reconcile(ctx context.Context, workflow *operatorapi.SonataFlow) (reconcile.Result, []client.Object, error) { + return d.reconcileWithBuiltImage(ctx, workflow, "") } func (d *deploymentReconciler) reconcileWithBuiltImage(ctx context.Context, workflow *operatorapi.SonataFlow, image string) (reconcile.Result, []client.Object, error) { @@ -67,7 +67,8 @@ func (d *deploymentReconciler) reconcileWithBuiltImage(ctx context.Context, work d.ensurers.deployment.Ensure( ctx, workflow, - d.getDeploymentMutateVisitors(workflow, image, userPropsCM.(*v1.ConfigMap), managedPropsCM.(*v1.ConfigMap))..., + pl, + d.getDeploymentMutateVisitors(workflow, pl, image, userPropsCM.(*v1.ConfigMap), managedPropsCM.(*v1.ConfigMap))..., ) if err != nil { workflow.Status.Manager().MarkFalse(api.RunningConditionType, api.DeploymentUnavailableReason, "Unable to perform the deploy due to ", err) @@ -75,7 +76,7 @@ func (d *deploymentReconciler) reconcileWithBuiltImage(ctx context.Context, work return reconcile.Result{}, nil, err } - service, _, err := d.ensurers.service.Ensure(ctx, workflow, plf, common.ServiceMutateVisitor(workflow)) + service, _, err := d.ensurers.service.Ensure(ctx, workflow, common.ServiceMutateVisitor(workflow)) if err != nil { workflow.Status.Manager().MarkFalse(api.RunningConditionType, api.DeploymentUnavailableReason, "Unable to make the service available due to ", err) _, err = d.PerformStatusUpdate(ctx, workflow) @@ -111,7 +112,7 @@ func (d *deploymentReconciler) getDeploymentMutateVisitors( userPropsCM *v1.ConfigMap, managedPropsCM *v1.ConfigMap) []common.MutateVisitor { if utils.IsOpenShift() { - return []common.MutateVisitor{common.DeploymentMutateVisitor(workflow), + return []common.MutateVisitor{common.DeploymentMutateVisitor(workflow, plf), mountProdConfigMapsMutateVisitor(workflow, userPropsCM, managedPropsCM), addOpenShiftImageTriggerDeploymentMutateVisitor(workflow, image), common.ImageDeploymentMutateVisitor(workflow, image), diff --git a/controllers/profiles/prod/deployment_handler_test.go b/controllers/profiles/prod/deployment_handler_test.go index d11b7bcc1..a133b9635 100644 --- a/controllers/profiles/prod/deployment_handler_test.go +++ b/controllers/profiles/prod/deployment_handler_test.go @@ -40,7 +40,7 @@ func Test_CheckPodTemplateChangesReflectDeployment(t *testing.T) { stateSupport := fakeReconcilerSupport(client) handler := newDeploymentReconciler(stateSupport, newObjectEnsurers(stateSupport)) - result, objects, err := handler.reconcile(context.TODO(), workflow, emptyPlatform) + result, objects, err := handler.reconcile(context.TODO(), workflow) assert.NoError(t, err) assert.NotEmpty(t, objects) assert.True(t, result.Requeue) @@ -49,7 +49,7 @@ func Test_CheckPodTemplateChangesReflectDeployment(t *testing.T) { expectedImg := "quay.io/apache/my-new-workflow:1.0.0" workflow.Spec.PodTemplate.Container.Image = expectedImg utilruntime.Must(client.Update(context.TODO(), workflow)) - result, objects, err = handler.reconcile(context.TODO(), workflow, emptyPlatform) + result, objects, err = handler.reconcile(context.TODO(), workflow) assert.NoError(t, err) assert.NotEmpty(t, objects) assert.True(t, result.Requeue) @@ -73,7 +73,7 @@ func Test_CheckDeploymentRolloutAfterCMChange(t *testing.T) { stateSupport := fakeReconcilerSupport(client) handler := newDeploymentReconciler(stateSupport, newObjectEnsurers(stateSupport)) - result, objects, err := handler.reconcile(context.TODO(), workflow, emptyPlatform) + result, objects, err := handler.reconcile(context.TODO(), workflow) assert.NoError(t, err) assert.NotEmpty(t, objects) assert.True(t, result.Requeue) @@ -135,7 +135,7 @@ func Test_CheckDeploymentUnchangedAfterCMChangeOtherKeys(t *testing.T) { stateSupport := fakeReconcilerSupport(client) handler := newDeploymentReconciler(stateSupport, newObjectEnsurers(stateSupport)) - result, objects, err := handler.reconcile(context.TODO(), workflow, emptyPlatform) + result, objects, err := handler.reconcile(context.TODO(), workflow) assert.NoError(t, err) assert.NotEmpty(t, objects) assert.True(t, result.Requeue) diff --git a/controllers/profiles/prod/profile_prod.go b/controllers/profiles/prod/profile_prod.go index f5046d05f..71622323b 100644 --- a/controllers/profiles/prod/profile_prod.go +++ b/controllers/profiles/prod/profile_prod.go @@ -52,7 +52,7 @@ const ( // ReconciliationState that needs access to it must include this struct as an attribute and initialize it in the profile builder. // Use newObjectEnsurers to facilitate building this struct type objectEnsurers struct { - deployment common.ObjectEnsurer + deployment common.ObjectEnsurerWithPlatform service common.ObjectEnsurer userPropsConfigMap common.ObjectEnsurer managedPropsConfigMap common.ObjectEnsurerWithPlatform @@ -60,7 +60,7 @@ type objectEnsurers struct { func newObjectEnsurers(support *common.StateSupport) *objectEnsurers { return &objectEnsurers{ - deployment: common.NewObjectEnsurer(support.C, common.DeploymentCreator), + deployment: common.NewObjectEnsurerWithPlatform(support.C, common.DeploymentCreator), service: common.NewObjectEnsurer(support.C, common.ServiceCreator), userPropsConfigMap: common.NewObjectEnsurer(support.C, common.UserPropsConfigMapCreator), managedPropsConfigMap: common.NewObjectEnsurerWithPlatform(support.C, common.ManagedPropsConfigMapCreator), diff --git a/controllers/profiles/prod/profile_prod_test.go b/controllers/profiles/prod/profile_prod_test.go index 181461c09..5ca93a97f 100644 --- a/controllers/profiles/prod/profile_prod_test.go +++ b/controllers/profiles/prod/profile_prod_test.go @@ -49,7 +49,7 @@ func Test_Reconciler_ProdOps(t *testing.T) { client := test.NewSonataFlowClientBuilder(). WithRuntimeObjects(workflow). WithStatusSubresource(workflow, &operatorapi.SonataFlowBuild{}).Build() - result, err := NewProfileForOpsReconciler(client, &rest.Config{}, test.NewFakeRecorder()).Reconcile(context.TODO(), workflow, emptyPlatform) + result, err := NewProfileForOpsReconciler(client, &rest.Config{}, test.NewFakeRecorder()).Reconcile(context.TODO(), workflow) assert.NoError(t, err) assert.NotNil(t, result.RequeueAfter) @@ -60,7 +60,7 @@ func Test_Reconciler_ProdOps(t *testing.T) { assert.False(t, workflow.Status.IsReady()) // Reconcile again to run the deployment handler - result, err = NewProfileForOpsReconciler(client, &rest.Config{}, test.NewFakeRecorder()).Reconcile(context.TODO(), workflow, emptyPlatform) + result, err = NewProfileForOpsReconciler(client, &rest.Config{}, test.NewFakeRecorder()).Reconcile(context.TODO(), workflow) assert.NoError(t, err) // Let's check for the right creation of the workflow (one CM volume, one container with a custom image) @@ -88,7 +88,7 @@ func Test_Reconciler_ProdCustomPod(t *testing.T) { client := test.NewSonataFlowClientBuilder(). WithRuntimeObjects(workflow, build, platform). WithStatusSubresource(workflow, build, platform).Build() - _, err := NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()).Reconcile(context.TODO(), workflow, emptyPlatform) + _, err := NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()).Reconcile(context.TODO(), workflow) assert.NoError(t, err) // Let's check for the right creation of the workflow (one CM volume, one container with a custom image) @@ -109,7 +109,7 @@ func Test_reconcilerProdBuildConditions(t *testing.T) { WithRuntimeObjects(workflow, platform). WithStatusSubresource(workflow, platform, &operatorapi.SonataFlowBuild{}).Build() - result, err := NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()).Reconcile(context.TODO(), workflow, emptyPlatform) + result, err := NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()).Reconcile(context.TODO(), workflow) assert.NoError(t, err) assert.NotNil(t, result.RequeueAfter) @@ -117,7 +117,7 @@ func Test_reconcilerProdBuildConditions(t *testing.T) { assert.False(t, workflow.Status.IsReady()) // still building - result, err = NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()).Reconcile(context.TODO(), workflow, emptyPlatform) + result, err = NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()).Reconcile(context.TODO(), workflow) assert.NoError(t, err) assert.Equal(t, requeueWhileWaitForBuild, result.RequeueAfter) assert.True(t, workflow.Status.IsBuildRunningOrUnknown()) @@ -130,7 +130,7 @@ func Test_reconcilerProdBuildConditions(t *testing.T) { assert.NoError(t, client.Status().Update(context.TODO(), build)) // last reconciliation cycle waiting for build - result, err = NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()).Reconcile(context.TODO(), workflow, emptyPlatform) + result, err = NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()).Reconcile(context.TODO(), workflow) assert.NoError(t, err) assert.Equal(t, requeueWhileWaitForBuild, result.RequeueAfter) assert.False(t, workflow.Status.IsBuildRunningOrUnknown()) @@ -138,7 +138,7 @@ func Test_reconcilerProdBuildConditions(t *testing.T) { assert.Equal(t, api.WaitingForDeploymentReason, workflow.Status.GetTopLevelCondition().Reason) // now we create the objects - result, err = NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()).Reconcile(context.TODO(), workflow, emptyPlatform) + result, err = NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()).Reconcile(context.TODO(), workflow) assert.NoError(t, err) assert.False(t, workflow.Status.IsBuildRunningOrUnknown()) assert.False(t, workflow.Status.IsReady()) @@ -156,7 +156,7 @@ func Test_reconcilerProdBuildConditions(t *testing.T) { err = client.Status().Update(context.TODO(), deployment) assert.NoError(t, err) - result, err = NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()).Reconcile(context.TODO(), workflow, emptyPlatform) + result, err = NewProfileReconciler(client, &rest.Config{}, test.NewFakeRecorder()).Reconcile(context.TODO(), workflow) assert.NoError(t, err) assert.False(t, workflow.Status.IsBuildRunningOrUnknown()) assert.True(t, workflow.Status.IsReady()) @@ -174,7 +174,7 @@ func Test_deployWorkflowReconciliationHandler_handleObjects(t *testing.T) { StateSupport: fakeReconcilerSupport(client), ensurers: newObjectEnsurers(&common.StateSupport{C: client}), } - result, objects, err := handler.Do(context.TODO(), workflow, emptyPlatform) + result, objects, err := handler.Do(context.TODO(), workflow) assert.Greater(t, result.RequeueAfter, int64(0)) assert.NoError(t, err) assert.NotNil(t, result) @@ -203,7 +203,7 @@ func Test_GenerationAnnotationCheck(t *testing.T) { StateSupport: fakeReconcilerSupport(client), ensurers: newObjectEnsurers(&common.StateSupport{C: client}), } - result, objects, err := handler.Do(context.TODO(), workflow, emptyPlatform) + result, objects, err := handler.Do(context.TODO(), workflow) assert.Greater(t, result.RequeueAfter, int64(time.Second)) assert.NoError(t, err) assert.NotNil(t, result) @@ -222,7 +222,7 @@ func Test_GenerationAnnotationCheck(t *testing.T) { StateSupport: fakeReconcilerSupport(client), ensurers: newObjectEnsurers(&common.StateSupport{C: client}), } - result, objects, err = handler.Do(context.TODO(), workflowChanged, emptyPlatform) + result, objects, err = handler.Do(context.TODO(), workflowChanged) assert.NoError(t, err) // no requeue, no objects since the workflow has changed assert.Equal(t, time.Duration(0), result.RequeueAfter) diff --git a/controllers/profiles/prod/states_prod.go b/controllers/profiles/prod/states_prod.go index 199cbd423..feb30dca6 100644 --- a/controllers/profiles/prod/states_prod.go +++ b/controllers/profiles/prod/states_prod.go @@ -48,7 +48,7 @@ func (h *newBuilderState) CanReconcile(workflow *operatorapi.SonataFlow) bool { workflow.Status.IsBuildFailed() } -func (h *newBuilderState) Do(ctx context.Context, workflow *operatorapi.SonataFlow, plf *operatorapi.SonataFlowPlatform) (ctrl.Result, []client.Object, error) { +func (h *newBuilderState) Do(ctx context.Context, workflow *operatorapi.SonataFlow) (ctrl.Result, []client.Object, error) { _, err := platform.GetActivePlatform(ctx, h.C, workflow.Namespace) if err != nil { if errors.IsNotFound(err) { @@ -100,7 +100,7 @@ func (h *followBuildStatusState) CanReconcile(workflow *operatorapi.SonataFlow) return workflow.Status.IsBuildRunningOrUnknown() || workflow.Status.IsWaitingForBuild() } -func (h *followBuildStatusState) Do(ctx context.Context, workflow *operatorapi.SonataFlow, _ *operatorapi.SonataFlowPlatform) (ctrl.Result, []client.Object, error) { +func (h *followBuildStatusState) Do(ctx context.Context, workflow *operatorapi.SonataFlow) (ctrl.Result, []client.Object, error) { // Let's retrieve the build to check the status build, err := builder.NewSonataFlowBuildManager(ctx, h.C).GetOrCreateBuild(workflow) if err != nil { @@ -160,7 +160,7 @@ func (h *deployWithBuildWorkflowState) CanReconcile(workflow *operatorapi.Sonata return workflow.Status.GetCondition(api.BuiltConditionType).IsTrue() } -func (h *deployWithBuildWorkflowState) Do(ctx context.Context, workflow *operatorapi.SonataFlow, plf *operatorapi.SonataFlowPlatform) (ctrl.Result, []client.Object, error) { +func (h *deployWithBuildWorkflowState) Do(ctx context.Context, workflow *operatorapi.SonataFlow) (ctrl.Result, []client.Object, error) { // Guard to avoid errors while getting a new builder manager. // Maybe we can do typed errors in the buildManager and // have something like sonataerr.IsPlatformNotFound(err) instead. @@ -189,7 +189,7 @@ func (h *deployWithBuildWorkflowState) Do(ctx context.Context, workflow *operato } // didn't change, business as usual - return newDeploymentReconciler(h.StateSupport, h.ensurers).reconcileWithBuiltImage(ctx, workflow, plf, build.Status.ImageTag) + return newDeploymentReconciler(h.StateSupport, h.ensurers).reconcileWithBuiltImage(ctx, workflow, build.Status.ImageTag) } func (h *deployWithBuildWorkflowState) PostReconcile(ctx context.Context, workflow *operatorapi.SonataFlow) error { diff --git a/controllers/profiles/prod/states_prod_nobuild.go b/controllers/profiles/prod/states_prod_nobuild.go index bc4d1b787..46449ce1f 100644 --- a/controllers/profiles/prod/states_prod_nobuild.go +++ b/controllers/profiles/prod/states_prod_nobuild.go @@ -36,7 +36,7 @@ func (f *ensureBuildSkipped) CanReconcile(workflow *operatorapi.SonataFlow) bool workflow.Status.GetCondition(api.BuiltConditionType).Reason != api.BuildSkippedReason } -func (f *ensureBuildSkipped) Do(ctx context.Context, workflow *operatorapi.SonataFlow, _ *operatorapi.SonataFlowPlatform) (ctrl.Result, []client.Object, error) { +func (f *ensureBuildSkipped) Do(ctx context.Context, workflow *operatorapi.SonataFlow) (ctrl.Result, []client.Object, error) { // We skip the build, so let's ensure the status reflect that workflow.Status.Manager().MarkFalse(api.BuiltConditionType, api.BuildSkippedReason, "") if _, err := f.PerformStatusUpdate(ctx, workflow); err != nil { @@ -61,8 +61,8 @@ func (f *followDeployWorkflowState) CanReconcile(workflow *operatorapi.SonataFlo return workflow.Status.GetCondition(api.BuiltConditionType).Reason == api.BuildSkippedReason } -func (f *followDeployWorkflowState) Do(ctx context.Context, workflow *operatorapi.SonataFlow, plf *operatorapi.SonataFlowPlatform) (ctrl.Result, []client.Object, error) { - return newDeploymentReconciler(f.StateSupport, f.ensurers).reconcile(ctx, workflow, plf) +func (f *followDeployWorkflowState) Do(ctx context.Context, workflow *operatorapi.SonataFlow) (ctrl.Result, []client.Object, error) { + return newDeploymentReconciler(f.StateSupport, f.ensurers).reconcile(ctx, workflow) } func (f *followDeployWorkflowState) PostReconcile(ctx context.Context, workflow *operatorapi.SonataFlow) error { diff --git a/controllers/profiles/profile.go b/controllers/profiles/profile.go index 8dd449b82..da981c75f 100644 --- a/controllers/profiles/profile.go +++ b/controllers/profiles/profile.go @@ -58,7 +58,7 @@ import ( // // While debugging, focus on the ReconciliationState(s), not in the profile implementation since the base algorithm is the same for every profile. type ProfileReconciler interface { - Reconcile(ctx context.Context, workflow *operatorapi.SonataFlow, plf *operatorapi.SonataFlowPlatform) (ctrl.Result, error) + Reconcile(ctx context.Context, workflow *operatorapi.SonataFlow) (ctrl.Result, error) GetProfile() metadata.ProfileType } @@ -68,7 +68,7 @@ type ReconciliationState interface { CanReconcile(workflow *operatorapi.SonataFlow) bool // Do perform the reconciliation task. It returns the controller result, the objects updated, and an error if any. // Objects can be nil if the reconciliation state doesn't perform any updates in any Kubernetes object. - Do(ctx context.Context, workflow *operatorapi.SonataFlow, plf *operatorapi.SonataFlowPlatform) (ctrl.Result, []client.Object, error) + Do(ctx context.Context, workflow *operatorapi.SonataFlow) (ctrl.Result, []client.Object, error) // PostReconcile performs the actions to perform after the reconciliation that are not mandatory PostReconcile(ctx context.Context, workflow *operatorapi.SonataFlow) error } diff --git a/controllers/sonataflow_controller.go b/controllers/sonataflow_controller.go index f946eab41..447e386f6 100644 --- a/controllers/sonataflow_controller.go +++ b/controllers/sonataflow_controller.go @@ -94,11 +94,7 @@ func (r *SonataFlowReconciler) Reconcile(ctx context.Context, req ctrl.Request) klog.V(log.I).InfoS("Ignoring request because resource is not assigned to current operator") return reconcile.Result{}, nil } - plf, err := platform.GetActivePlatform(context.TODO(), r.Client, workflow.Namespace) - if err != nil { - return reconcile.Result{}, err - } - return profiles.NewReconciler(r.Client, r.Config, r.Recorder, workflow).Reconcile(ctx, workflow, plf) + return profiles.NewReconciler(r.Client, r.Config, r.Recorder, workflow).Reconcile(ctx, workflow) } func platformEnqueueRequestsFromMapFunc(c client.Client, p *operatorapi.SonataFlowPlatform) []reconcile.Request { diff --git a/controllers/sonataflowplatform_controller_test.go b/controllers/sonataflowplatform_controller_test.go index c37957ca0..94ad9a8fe 100644 --- a/controllers/sonataflowplatform_controller_test.go +++ b/controllers/sonataflowplatform_controller_test.go @@ -77,7 +77,6 @@ func TestSonataFlowPlatformController(t *testing.T) { assert.Equal(t, "quay.io/kiegroup", ksp.Spec.Build.Config.Registry.Address) assert.Equal(t, "regcred", ksp.Spec.Build.Config.Registry.Secret) assert.Equal(t, v1alpha08.OperatorBuildStrategy, ksp.Spec.Build.Config.BuildStrategy) - assert.Nil(t, ksp.Spec.Services) assert.Equal(t, v1alpha08.PlatformClusterKubernetes, ksp.Status.Cluster) assert.Equal(t, v1alpha08.PlatformCreatingReason, ksp.Status.GetTopLevelCondition().Reason) @@ -87,7 +86,7 @@ func TestSonataFlowPlatformController(t *testing.T) { namespace := t.Name() // Create a SonataFlowPlatform object with metadata and spec. ksp := test.GetBasePlatformInReadyPhase(namespace) - ksp.Spec.Services = &v1alpha08.ServicesPlatformSpec{ + ksp.Spec.Services = v1alpha08.ServicesPlatformSpec{ DataIndex: &v1alpha08.ServiceSpec{}, } @@ -137,7 +136,7 @@ func TestSonataFlowPlatformController(t *testing.T) { assert.NotContains(t, dep.Spec.Template.Spec.Containers[0].Env, env) // Check with persistence set - ksp.Spec.Services.DataIndex.Persistence = &v1alpha08.PersistenceSpec{PostgreSQL: &v1alpha08.PersistencePostgreSQL{ + ksp.Spec.Services.DataIndex.Persistence = &v1alpha08.PersistencePlatformSpec{PostgreSQL: &v1alpha08.PersistencePostgreSQL{ SecretRef: v1alpha08.PostgreSQLSecretOptions{Name: "test"}, ServiceRef: &v1alpha08.PostgreSQLServiceOptions{Name: "test"}, }} @@ -166,7 +165,7 @@ func TestSonataFlowPlatformController(t *testing.T) { // Create a SonataFlowPlatform object with metadata and spec. ksp := test.GetBasePlatformInReadyPhase(namespace) var replicas int32 = 2 - ksp.Spec.Services = &v1alpha08.ServicesPlatformSpec{ + ksp.Spec.Services = v1alpha08.ServicesPlatformSpec{ DataIndex: &v1alpha08.ServiceSpec{ PodTemplate: v1alpha08.PodTemplateSpec{ Replicas: &replicas, @@ -224,7 +223,7 @@ func TestSonataFlowPlatformController(t *testing.T) { // Check with persistence set url := "jdbc:postgresql://host:1234/database?currentSchema=data-index-service" - ksp.Spec.Services.DataIndex.Persistence = &v1alpha08.PersistenceSpec{PostgreSQL: &v1alpha08.PersistencePostgreSQL{ + ksp.Spec.Services.DataIndex.Persistence = &v1alpha08.PersistencePlatformSpec{PostgreSQL: &v1alpha08.PersistencePostgreSQL{ SecretRef: v1alpha08.PostgreSQLSecretOptions{Name: "test"}, JdbcUrl: url, }} @@ -263,7 +262,7 @@ func TestSonataFlowPlatformController(t *testing.T) { DataIndex: &v1alpha08.ServiceSpec{}, JobService: &v1alpha08.ServiceSpec{}, }, - Persistence: &v1alpha08.PersistenceSpec{ + Persistence: &v1alpha08.PersistencePlatformSpec{ PostgreSQL: &v1alpha08.PersistencePostgreSQL{ SecretRef: v1alpha08.PostgreSQLSecretOptions{Name: "generic", UserKey: "POSTGRESQL_USER", PasswordKey: "POSTGRESQL_PASSWORD"}, ServiceRef: &v1alpha08.PostgreSQLServiceOptions{Name: "postgresql", Namespace: "default", Port: &postgreSQLPort, DatabaseName: "sonataflow"}, @@ -351,7 +350,7 @@ func TestSonataFlowPlatformController(t *testing.T) { ksp.Spec = v1alpha08.SonataFlowPlatformSpec{ Services: v1alpha08.ServicesPlatformSpec{ DataIndex: &v1alpha08.ServiceSpec{ - Persistence: &v1alpha08.PersistenceSpec{ + Persistence: &v1alpha08.PersistencePlatformSpec{ PostgreSQL: &v1alpha08.PersistencePostgreSQL{ SecretRef: v1alpha08.PostgreSQLSecretOptions{Name: "dataIndex"}, JdbcUrl: urlDI, @@ -359,7 +358,7 @@ func TestSonataFlowPlatformController(t *testing.T) { }, }, JobService: &v1alpha08.ServiceSpec{ - Persistence: &v1alpha08.PersistenceSpec{ + Persistence: &v1alpha08.PersistencePlatformSpec{ PostgreSQL: &v1alpha08.PersistencePostgreSQL{ SecretRef: v1alpha08.PostgreSQLSecretOptions{Name: "job"}, JdbcUrl: urlJS, @@ -367,7 +366,7 @@ func TestSonataFlowPlatformController(t *testing.T) { }, }, }, - Persistence: &v1alpha08.PersistenceSpec{ + Persistence: &v1alpha08.PersistencePlatformSpec{ PostgreSQL: &v1alpha08.PersistencePostgreSQL{ SecretRef: v1alpha08.PostgreSQLSecretOptions{Name: "generic", UserKey: "POSTGRESQL_USER", PasswordKey: "POSTGRESQL_PASSWORD"}, ServiceRef: &v1alpha08.PostgreSQLServiceOptions{Name: "postgresql", Namespace: "default", Port: &postgreSQLPort, DatabaseName: "sonataflow"}, @@ -462,7 +461,7 @@ func TestSonataFlowPlatformController(t *testing.T) { namespace := t.Name() // Create a SonataFlowPlatform object with metadata and spec. ksp := test.GetBasePlatformInReadyPhase(namespace) - ksp.Spec.Services = &v1alpha08.ServicesPlatformSpec{ + ksp.Spec.Services = v1alpha08.ServicesPlatformSpec{ JobService: &v1alpha08.ServiceSpec{}, } @@ -509,7 +508,7 @@ func TestSonataFlowPlatformController(t *testing.T) { assert.NotContains(t, dep.Spec.Template.Spec.Containers[0].Env, envDataIndex) // Check with persistence set - ksp.Spec.Services.JobService.Persistence = &v1alpha08.PersistenceSpec{PostgreSQL: &v1alpha08.PersistencePostgreSQL{ + ksp.Spec.Services.JobService.Persistence = &v1alpha08.PersistencePlatformSpec{PostgreSQL: &v1alpha08.PersistencePostgreSQL{ SecretRef: v1alpha08.PostgreSQLSecretOptions{Name: "test"}, ServiceRef: &v1alpha08.PostgreSQLServiceOptions{Name: "test"}, }} @@ -539,7 +538,7 @@ func TestSonataFlowPlatformController(t *testing.T) { // Create a SonataFlowPlatform object with metadata and spec. ksp := test.GetBasePlatformInReadyPhase(namespace) var replicas int32 = 2 - ksp.Spec.Services = &v1alpha08.ServicesPlatformSpec{ + ksp.Spec.Services = v1alpha08.ServicesPlatformSpec{ JobService: &v1alpha08.ServiceSpec{ PodTemplate: v1alpha08.PodTemplateSpec{ Replicas: &replicas, @@ -594,7 +593,7 @@ func TestSonataFlowPlatformController(t *testing.T) { // Check with persistence set url := "jdbc:postgresql://host:1234/database?currentSchema=data-index-service" - ksp.Spec.Services.JobService.Persistence = &v1alpha08.PersistenceSpec{PostgreSQL: &v1alpha08.PersistencePostgreSQL{ + ksp.Spec.Services.JobService.Persistence = &v1alpha08.PersistencePlatformSpec{PostgreSQL: &v1alpha08.PersistencePostgreSQL{ SecretRef: v1alpha08.PostgreSQLSecretOptions{Name: "test"}, JdbcUrl: url, }} @@ -620,7 +619,7 @@ func TestSonataFlowPlatformController(t *testing.T) { namespace := t.Name() // Create a SonataFlowPlatform object with metadata and spec. ksp := test.GetBasePlatformInReadyPhase(namespace) - ksp.Spec.Services = &v1alpha08.ServicesPlatformSpec{ + ksp.Spec.Services = v1alpha08.ServicesPlatformSpec{ DataIndex: &v1alpha08.ServiceSpec{}, JobService: &v1alpha08.ServiceSpec{}, } @@ -688,7 +687,7 @@ func TestSonataFlowPlatformController(t *testing.T) { // Create a SonataFlowPlatform object with metadata and spec. ksp := test.GetBasePlatformInReadyPhase(namespace) - ksp.Spec.Services = &v1alpha08.ServicesPlatformSpec{ + ksp.Spec.Services = v1alpha08.ServicesPlatformSpec{ DataIndex: &v1alpha08.ServiceSpec{}, JobService: &v1alpha08.ServiceSpec{}, } @@ -786,7 +785,7 @@ func TestSonataFlowPlatformController(t *testing.T) { assert.Equal(t, ksp2.Status.ClusterPlatformRef.Services.JobServiceRef.Url, psJs.GetLocalServiceBaseUrl()) assert.Equal(t, psJs.GetLocalServiceBaseUrl()+constants.JobServiceJobEventsPath, psJs2.GetServiceBaseUrl()+constants.JobServiceJobEventsPath) - ksp2.Spec.Services = &v1alpha08.ServicesPlatformSpec{} + ksp2.Spec.Services = v1alpha08.ServicesPlatformSpec{} assert.NoError(t, cl.Update(context.TODO(), ksp2)) _, err = r.Reconcile(context.TODO(), req2) @@ -799,6 +798,5 @@ func TestSonataFlowPlatformController(t *testing.T) { assert.NotNil(t, ksp2.Status.ClusterPlatformRef) assert.Equal(t, kscp.Spec.PlatformRef.Name, ksp2.Status.ClusterPlatformRef.PlatformRef.Name) assert.Equal(t, kscp.Spec.PlatformRef.Namespace, ksp2.Status.ClusterPlatformRef.PlatformRef.Namespace) - assert.Nil(t, ksp2.Status.ClusterPlatformRef.Services) }) } diff --git a/test/testdata/platform/services/prod/postgreSQL/02-sonataflow_platform.yaml b/test/testdata/platform/services/prod/postgreSQL/02-sonataflow_platform.yaml index feae7a943..9248f57b7 100644 --- a/test/testdata/platform/services/prod/postgreSQL/02-sonataflow_platform.yaml +++ b/test/testdata/platform/services/prod/postgreSQL/02-sonataflow_platform.yaml @@ -18,10 +18,9 @@ metadata: name: sonataflow-platform spec: build: - template: - buildArgs: - - name: QUARKUS_EXTENSIONS - value: org.kie.kogito:kogito-addons-quarkus-jobs-knative-eventing:999-SNAPSHOT + config: + strategyOptions: + KanikoBuildCacheEnabled: "true" services: dataIndex: enabled: true