blob: abfffb20e10bea8a1b063e33a0d4970df4e479b7 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 controllers
import (
"context"
"testing"
"github.com/apache/incubator-kie-kogito-serverless-operator/api/v1alpha08"
"github.com/apache/incubator-kie-kogito-serverless-operator/controllers/clusterplatform"
"github.com/apache/incubator-kie-kogito-serverless-operator/controllers/platform/services"
"github.com/apache/incubator-kie-kogito-serverless-operator/controllers/profiles/common/constants"
"github.com/apache/incubator-kie-kogito-serverless-operator/test"
"github.com/stretchr/testify/assert"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/record"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
)
var (
envDBKind = corev1.EnvVar{
Name: "QUARKUS_DATASOURCE_DB_KIND",
Value: constants.PersistenceTypePostgreSQL,
}
envDataIndex = corev1.EnvVar{
Name: "KOGITO_DATA_INDEX_QUARKUS_PROFILE",
Value: "http-events-support",
}
)
func TestSonataFlowPlatformController(t *testing.T) {
t.Run("verify that a basic reconcile is performed without error", func(t *testing.T) {
// Create a SonataFlowPlatform object with metadata and spec.
ksp := test.GetBasePlatform()
// Create a fake client to mock API calls.
cl := test.NewSonataFlowClientBuilder().WithRuntimeObjects(ksp).WithStatusSubresource(ksp).Build()
// Create a SonataFlowPlatformReconciler object with the scheme and fake client.
r := &SonataFlowPlatformReconciler{cl, cl, cl.Scheme(), &rest.Config{}, &record.FakeRecorder{}}
// Mock request to simulate Reconcile() being called on an event for a
// watched resource .
req := reconcile.Request{
NamespacedName: types.NamespacedName{
Name: ksp.Name,
Namespace: ksp.Namespace,
},
}
_, err := r.Reconcile(context.TODO(), req)
if err != nil {
t.Fatalf("reconcile: (%v)", err)
}
assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: ksp.Name, Namespace: ksp.Namespace}, ksp))
// Perform some checks on the created CR
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.Equal(t, v1alpha08.PlatformClusterKubernetes, ksp.Status.Cluster)
assert.Equal(t, v1alpha08.PlatformCreatingReason, ksp.Status.GetTopLevelCondition().Reason)
})
t.Run("verify that a basic reconcile with data index service & persistence is performed without error", func(t *testing.T) {
namespace := t.Name()
// Create a SonataFlowPlatform object with metadata and spec.
ksp := test.GetBasePlatformInReadyPhase(namespace)
ksp.Spec.Services = &v1alpha08.ServicesPlatformSpec{
DataIndex: &v1alpha08.ServiceSpec{},
}
// Create a fake client to mock API calls.
cl := test.NewKogitoClientBuilderWithOpenShift().WithRuntimeObjects(ksp).WithStatusSubresource(ksp).Build()
// Create a SonataFlowPlatformReconciler object with the scheme and fake client.
r := &SonataFlowPlatformReconciler{cl, cl, cl.Scheme(), &rest.Config{}, &record.FakeRecorder{}}
// Mock request to simulate Reconcile() being called on an event for a
// watched resource .
req := reconcile.Request{
NamespacedName: types.NamespacedName{
Name: ksp.Name,
Namespace: ksp.Namespace,
},
}
_, err := r.Reconcile(context.TODO(), req)
if err != nil {
t.Fatalf("reconcile: (%v)", err)
}
assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: ksp.Name, Namespace: ksp.Namespace}, ksp))
// Perform some checks on the created CR
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.NotNil(t, ksp.Spec.Services.DataIndex)
assert.Nil(t, ksp.Spec.Services.DataIndex.PodTemplate.Replicas)
assert.NotNil(t, ksp.Spec.Services.DataIndex.Enabled)
assert.Equal(t, true, *ksp.Spec.Services.DataIndex.Enabled)
assert.Equal(t, v1alpha08.PlatformClusterKubernetes, ksp.Status.Cluster)
assert.Equal(t, "", ksp.Status.GetTopLevelCondition().Reason)
// Check data index deployment
dep := &appsv1.Deployment{}
di := services.NewDataIndexHandler(ksp)
assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: di.GetServiceName(), Namespace: ksp.Namespace}, dep))
env := corev1.EnvVar{
Name: "QUARKUS_DATASOURCE_DB_KIND",
Value: constants.PersistenceTypePostgreSQL,
}
assert.Len(t, dep.Spec.Template.Spec.Containers, 1)
assert.Equal(t, di.GetServiceImageName(constants.PersistenceTypeEphemeral), dep.Spec.Template.Spec.Containers[0].Image)
assert.NotContains(t, dep.Spec.Template.Spec.Containers[0].Env, env)
// Check with persistence set
ksp.Spec.Services.DataIndex.Persistence = &v1alpha08.PersistenceOptionsSpec{PostgreSQL: &v1alpha08.PersistencePostgreSQL{
SecretRef: v1alpha08.PostgreSQLSecretOptions{Name: "test"},
ServiceRef: &v1alpha08.PostgreSQLServiceOptions{SQLServiceOptions: &v1alpha08.SQLServiceOptions{Name: "test"}},
}}
// Ensure correct container overriding anything set in PodSpec
ksp.Spec.Services.DataIndex.PodTemplate.Container = v1alpha08.ContainerSpec{TerminationMessagePath: "testing"}
ksp.Spec.Services.DataIndex.PodTemplate.Containers = []corev1.Container{{Name: constants.DataIndexServiceName + "2", TerminationMessagePath: "testing"}}
assert.NoError(t, cl.Update(context.TODO(), ksp))
_, err = r.Reconcile(context.TODO(), req)
if err != nil {
t.Fatalf("reconcile: (%v)", err)
}
assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: di.GetServiceName(), Namespace: ksp.Namespace}, dep))
assert.Len(t, dep.Spec.Template.Spec.Containers, 2)
assert.Equal(t, constants.DataIndexServiceName+"2", dep.Spec.Template.Spec.Containers[0].Name)
assert.Equal(t, "testing", dep.Spec.Template.Spec.Containers[0].TerminationMessagePath)
assert.Equal(t, constants.DataIndexServiceName, dep.Spec.Template.Spec.Containers[1].Name)
assert.Equal(t, "testing", dep.Spec.Template.Spec.Containers[1].TerminationMessagePath)
assert.Equal(t, di.GetServiceImageName(constants.PersistenceTypePostgreSQL), dep.Spec.Template.Spec.Containers[1].Image)
assert.Contains(t, dep.Spec.Template.Spec.Containers[1].Env, env)
})
t.Run("verify that a basic reconcile with data index service & jdbcUrl is performed without error", func(t *testing.T) {
namespace := t.Name()
// Create a SonataFlowPlatform object with metadata and spec.
ksp := test.GetBasePlatformInReadyPhase(namespace)
var replicas int32 = 2
ksp.Spec.Services = &v1alpha08.ServicesPlatformSpec{
DataIndex: &v1alpha08.ServiceSpec{
PodTemplate: v1alpha08.PodTemplateSpec{
Replicas: &replicas,
Container: v1alpha08.ContainerSpec{
Command: []string{"test:latest"},
},
},
},
}
di := services.NewDataIndexHandler(ksp)
// Create a fake client to mock API calls.
cl := test.NewKogitoClientBuilderWithOpenShift().WithRuntimeObjects(ksp).WithStatusSubresource(ksp).Build()
// Create a SonataFlowPlatformReconciler object with the scheme and fake client.
r := &SonataFlowPlatformReconciler{cl, cl, cl.Scheme(), &rest.Config{}, &record.FakeRecorder{}}
// Mock request to simulate Reconcile() being called on an event for a
// watched resource .
req := reconcile.Request{
NamespacedName: types.NamespacedName{
Name: ksp.Name,
Namespace: ksp.Namespace,
},
}
_, err := r.Reconcile(context.TODO(), req)
if err != nil {
t.Fatalf("reconcile: (%v)", err)
}
assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: ksp.Name, Namespace: ksp.Namespace}, ksp))
// Perform some checks on the created CR
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.NotNil(t, ksp.Spec.Services.DataIndex)
assert.NotNil(t, ksp.Spec.Services.DataIndex.Enabled)
assert.Equal(t, true, *ksp.Spec.Services.DataIndex.Enabled)
assert.Equal(t, v1alpha08.PlatformClusterKubernetes, ksp.Status.Cluster)
assert.Equal(t, "", ksp.Status.GetTopLevelCondition().Reason)
// Check data index deployment
dep := &appsv1.Deployment{}
assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: di.GetServiceName(), Namespace: ksp.Namespace}, dep))
env := corev1.EnvVar{
Name: "QUARKUS_DATASOURCE_DB_KIND",
Value: constants.PersistenceTypePostgreSQL,
}
assert.Len(t, dep.Spec.Template.Spec.Containers, 1)
assert.Equal(t, di.GetServiceImageName(constants.PersistenceTypeEphemeral), dep.Spec.Template.Spec.Containers[0].Image)
assert.NotContains(t, dep.Spec.Template.Spec.Containers[0].Env, env)
// Check with persistence set
url := "jdbc:postgresql://host:1234/database?currentSchema=data-index-service"
ksp.Spec.Services.DataIndex.Persistence = &v1alpha08.PersistenceOptionsSpec{PostgreSQL: &v1alpha08.PersistencePostgreSQL{
SecretRef: v1alpha08.PostgreSQLSecretOptions{Name: "test"},
JdbcUrl: url,
}}
// Ensure correct container overriding anything set in PodSpec
ksp.Spec.Services.DataIndex.PodTemplate.PodSpec.Containers = []corev1.Container{{Name: constants.DataIndexServiceName}}
assert.NoError(t, cl.Update(context.TODO(), ksp))
_, err = r.Reconcile(context.TODO(), req)
if err != nil {
t.Fatalf("reconcile: (%v)", err)
}
env2 := corev1.EnvVar{
Name: "QUARKUS_DATASOURCE_JDBC_URL",
Value: url,
}
assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: di.GetServiceName(), Namespace: ksp.Namespace}, dep))
assert.Len(t, dep.Spec.Template.Spec.Containers, 1)
assert.Equal(t, di.GetServiceImageName(constants.PersistenceTypePostgreSQL), dep.Spec.Template.Spec.Containers[0].Image)
assert.Equal(t, &replicas, dep.Spec.Replicas)
assert.Equal(t, []string{"test:latest"}, dep.Spec.Template.Spec.Containers[0].Command)
assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, env)
assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, env2)
})
var (
postgreSQLPort int = 5432
)
t.Run("verify that persistence options are correctly reconciled when defined in the platform", func(t *testing.T) {
namespace := t.Name()
// Create a SonataFlowPlatform object with metadata and spec.
ksp := test.GetBasePlatformInReadyPhase(namespace)
// Check with persistence set
ksp.Spec = v1alpha08.SonataFlowPlatformSpec{
Services: &v1alpha08.ServicesPlatformSpec{
DataIndex: &v1alpha08.ServiceSpec{},
JobService: &v1alpha08.ServiceSpec{},
},
Persistence: &v1alpha08.PlatformPersistenceOptionsSpec{
PostgreSQL: &v1alpha08.PlatformPersistencePostgreSQL{
SecretRef: v1alpha08.PostgreSQLSecretOptions{Name: "generic", UserKey: "POSTGRESQL_USER", PasswordKey: "POSTGRESQL_PASSWORD"},
ServiceRef: &v1alpha08.SQLServiceOptions{
Name: "postgresql",
Namespace: "default",
Port: &postgreSQLPort,
DatabaseName: "sonataflow"},
},
},
}
// Create a fake client to mock API calls.
cl := test.NewKogitoClientBuilderWithOpenShift().WithRuntimeObjects(ksp).WithStatusSubresource(ksp).Build()
// Create a SonataFlowPlatformReconciler object with the scheme and fake client.
r := &SonataFlowPlatformReconciler{cl, cl, cl.Scheme(), &rest.Config{}, &record.FakeRecorder{}}
// Mock request to simulate Reconcile() being called on an event for a
// watched resource .
req := reconcile.Request{
NamespacedName: types.NamespacedName{
Name: ksp.Name,
Namespace: ksp.Namespace,
},
}
_, err := r.Reconcile(context.TODO(), req)
if err != nil {
t.Fatalf("reconcile: (%v)", err)
}
dbSourceKind := corev1.EnvVar{
Name: "QUARKUS_DATASOURCE_DB_KIND",
Value: constants.PersistenceTypePostgreSQL,
}
dbSourceDIURL := corev1.EnvVar{
Name: "QUARKUS_DATASOURCE_JDBC_URL",
Value: "jdbc:postgresql://postgresql.default:5432/sonataflow?currentSchema=sonataflow-platform-data-index-service",
}
dbSourceJSURL := corev1.EnvVar{
Name: "QUARKUS_DATASOURCE_JDBC_URL",
Value: "jdbc:postgresql://postgresql.default:5432/sonataflow?currentSchema=sonataflow-platform-jobs-service",
}
dbUsername := corev1.EnvVar{
Name: "QUARKUS_DATASOURCE_USERNAME",
Value: "",
ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{Name: "generic"},
Key: "POSTGRESQL_USER",
},
},
}
dbPassword := corev1.EnvVar{
Name: "QUARKUS_DATASOURCE_PASSWORD",
Value: "",
ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{Name: "generic"},
Key: "POSTGRESQL_PASSWORD",
},
},
}
// Check Data Index deployment to ensure it contains references to the persistence values defined in the platform CR
dep := &appsv1.Deployment{}
di := services.NewDataIndexHandler(ksp)
assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: di.GetServiceName(), Namespace: ksp.Namespace}, dep))
assert.Len(t, dep.Spec.Template.Spec.Containers, 1)
assert.Equal(t, di.GetServiceImageName(constants.PersistenceTypePostgreSQL), dep.Spec.Template.Spec.Containers[0].Image)
assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, dbSourceKind)
assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, dbUsername)
assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, dbPassword)
assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, dbSourceDIURL)
js := services.NewJobServiceHandler(ksp)
assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: js.GetServiceName(), Namespace: ksp.Namespace}, dep))
assert.Len(t, dep.Spec.Template.Spec.Containers, 1)
assert.Equal(t, js.GetServiceImageName(constants.PersistenceTypePostgreSQL), dep.Spec.Template.Spec.Containers[0].Image)
assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, dbSourceKind)
assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, dbUsername)
assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, dbPassword)
assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, dbSourceJSURL)
})
t.Run("verify that persistence options are correctly reconciled when defined in the platform and overwriten in the services spec", func(t *testing.T) {
namespace := t.Name()
// Create a SonataFlowPlatform object with metadata and spec.
ksp := test.GetBasePlatformInReadyPhase(namespace)
// Check with persistence set
urlDI := "jdbc:postgresql://localhost:5432/database?currentSchema=data-index-service"
urlJS := "jdbc:postgresql://localhost:5432/database?currentSchema=job-service"
ksp.Spec = v1alpha08.SonataFlowPlatformSpec{
Services: &v1alpha08.ServicesPlatformSpec{
DataIndex: &v1alpha08.ServiceSpec{
Persistence: &v1alpha08.PersistenceOptionsSpec{
PostgreSQL: &v1alpha08.PersistencePostgreSQL{
SecretRef: v1alpha08.PostgreSQLSecretOptions{Name: "dataIndex"},
JdbcUrl: urlDI,
},
},
},
JobService: &v1alpha08.ServiceSpec{
Persistence: &v1alpha08.PersistenceOptionsSpec{
PostgreSQL: &v1alpha08.PersistencePostgreSQL{
SecretRef: v1alpha08.PostgreSQLSecretOptions{Name: "job"},
JdbcUrl: urlJS,
},
},
},
},
Persistence: &v1alpha08.PlatformPersistenceOptionsSpec{
PostgreSQL: &v1alpha08.PlatformPersistencePostgreSQL{
SecretRef: v1alpha08.PostgreSQLSecretOptions{Name: "generic", UserKey: "POSTGRESQL_USER", PasswordKey: "POSTGRESQL_PASSWORD"},
ServiceRef: &v1alpha08.SQLServiceOptions{Name: "postgresql", Namespace: "default", Port: &postgreSQLPort, DatabaseName: "sonataflow"},
},
},
}
// Create a fake client to mock API calls.
cl := test.NewKogitoClientBuilderWithOpenShift().WithRuntimeObjects(ksp).WithStatusSubresource(ksp).Build()
// Create a SonataFlowPlatformReconciler object with the scheme and fake client.
r := &SonataFlowPlatformReconciler{cl, cl, cl.Scheme(), &rest.Config{}, &record.FakeRecorder{}}
// Mock request to simulate Reconcile() being called on an event for a
// watched resource .
req := reconcile.Request{
NamespacedName: types.NamespacedName{
Name: ksp.Name,
Namespace: ksp.Namespace,
},
}
_, err := r.Reconcile(context.TODO(), req)
if err != nil {
t.Fatalf("reconcile: (%v)", err)
}
dbSourceKind := corev1.EnvVar{
Name: "QUARKUS_DATASOURCE_DB_KIND",
Value: constants.PersistenceTypePostgreSQL,
}
dbDIUsername := corev1.EnvVar{
Name: "QUARKUS_DATASOURCE_USERNAME",
Value: "",
ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{Name: "dataIndex"},
Key: "POSTGRESQL_USER",
},
},
}
dbDIPassword := corev1.EnvVar{
Name: "QUARKUS_DATASOURCE_PASSWORD",
Value: "",
ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{Name: "dataIndex"},
Key: "POSTGRESQL_PASSWORD",
},
},
}
dbJSUsername := corev1.EnvVar{
Name: "QUARKUS_DATASOURCE_USERNAME",
Value: "",
ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{Name: "job"},
Key: "POSTGRESQL_USER",
},
},
}
dbJSPassword := corev1.EnvVar{
Name: "QUARKUS_DATASOURCE_PASSWORD",
Value: "",
ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{Name: "job"},
Key: "POSTGRESQL_PASSWORD",
},
},
}
// Check Data Index deployment to ensure it contains references to the persistence values defined in the platform CR
dep := &appsv1.Deployment{}
di := services.NewDataIndexHandler(ksp)
assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: di.GetServiceName(), Namespace: ksp.Namespace}, dep))
assert.Len(t, dep.Spec.Template.Spec.Containers, 1)
assert.Equal(t, di.GetServiceImageName(constants.PersistenceTypePostgreSQL), dep.Spec.Template.Spec.Containers[0].Image)
assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, dbSourceKind)
assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, dbDIUsername)
assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, dbDIPassword)
assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{Name: "QUARKUS_DATASOURCE_JDBC_URL", Value: urlDI})
js := services.NewJobServiceHandler(ksp)
assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: js.GetServiceName(), Namespace: ksp.Namespace}, dep))
assert.Len(t, dep.Spec.Template.Spec.Containers, 1)
assert.Equal(t, js.GetServiceImageName(constants.PersistenceTypePostgreSQL), dep.Spec.Template.Spec.Containers[0].Image)
assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, dbSourceKind)
assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, dbJSUsername)
assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, dbJSPassword)
assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{Name: "QUARKUS_DATASOURCE_JDBC_URL", Value: urlJS})
})
// Job Service tests
t.Run("verify that a basic reconcile with job service & persistence is performed without error", func(t *testing.T) {
namespace := t.Name()
// Create a SonataFlowPlatform object with metadata and spec.
ksp := test.GetBasePlatformInReadyPhase(namespace)
ksp.Spec.Services = &v1alpha08.ServicesPlatformSpec{
JobService: &v1alpha08.ServiceSpec{},
}
// Create a fake client to mock API calls.
cl := test.NewKogitoClientBuilderWithOpenShift().WithRuntimeObjects(ksp).WithStatusSubresource(ksp).Build()
// Create a SonataFlowPlatformReconciler object with the scheme and fake client.
r := &SonataFlowPlatformReconciler{cl, cl, cl.Scheme(), &rest.Config{}, &record.FakeRecorder{}}
// Mock request to simulate Reconcile() being called on an event for a
// watched resource .
req := reconcile.Request{
NamespacedName: types.NamespacedName{
Name: ksp.Name,
Namespace: ksp.Namespace,
},
}
_, err := r.Reconcile(context.TODO(), req)
if err != nil {
t.Fatalf("reconcile: (%v)", err)
}
assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: ksp.Name, Namespace: ksp.Namespace}, ksp))
// Perform some checks on the created CR
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.NotNil(t, ksp.Spec.Services.JobService)
assert.Nil(t, ksp.Spec.Services.DataIndex)
assert.NotNil(t, ksp.Spec.Services.JobService.Enabled)
assert.Equal(t, true, *ksp.Spec.Services.JobService.Enabled)
assert.Equal(t, v1alpha08.PlatformClusterKubernetes, ksp.Status.Cluster)
assert.Equal(t, "", ksp.Status.GetTopLevelCondition().Reason)
// Check data index deployment
dep := &appsv1.Deployment{}
js := services.NewJobServiceHandler(ksp)
assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: js.GetServiceName(), Namespace: ksp.Namespace}, dep))
assert.Len(t, dep.Spec.Template.Spec.Containers, 1)
assert.Equal(t, js.GetServiceImageName(constants.PersistenceTypeEphemeral), dep.Spec.Template.Spec.Containers[0].Image)
assert.NotContains(t, dep.Spec.Template.Spec.Containers[0].Env, envDBKind)
assert.NotContains(t, dep.Spec.Template.Spec.Containers[0].Env, envDataIndex)
// Check with persistence set
ksp.Spec.Services.JobService.Persistence = &v1alpha08.PersistenceOptionsSpec{PostgreSQL: &v1alpha08.PersistencePostgreSQL{
SecretRef: v1alpha08.PostgreSQLSecretOptions{Name: "test"},
ServiceRef: &v1alpha08.PostgreSQLServiceOptions{SQLServiceOptions: &v1alpha08.SQLServiceOptions{Name: "test"}},
}}
// Ensure correct container overriding anything set in PodSpec
ksp.Spec.Services.JobService.PodTemplate.Container = v1alpha08.ContainerSpec{TerminationMessagePath: "testing"}
ksp.Spec.Services.JobService.PodTemplate.Containers = []corev1.Container{{Name: constants.JobServiceName + "2", TerminationMessagePath: "testing"}}
assert.NoError(t, cl.Update(context.TODO(), ksp))
_, err = r.Reconcile(context.TODO(), req)
if err != nil {
t.Fatalf("reconcile: (%v)", err)
}
assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: js.GetServiceName(), Namespace: ksp.Namespace}, dep))
assert.Len(t, dep.Spec.Template.Spec.Containers, 2)
assert.Equal(t, constants.JobServiceName+"2", dep.Spec.Template.Spec.Containers[0].Name)
assert.Equal(t, "testing", dep.Spec.Template.Spec.Containers[0].TerminationMessagePath)
assert.Equal(t, constants.JobServiceName, dep.Spec.Template.Spec.Containers[1].Name)
assert.Equal(t, "testing", dep.Spec.Template.Spec.Containers[1].TerminationMessagePath)
assert.Equal(t, js.GetServiceImageName(constants.PersistenceTypePostgreSQL), dep.Spec.Template.Spec.Containers[1].Image)
assert.Contains(t, dep.Spec.Template.Spec.Containers[1].Env, envDBKind)
assert.NotContains(t, dep.Spec.Template.Spec.Containers[1].Env, envDataIndex)
})
t.Run("verify that a basic reconcile with job service & jdbcUrl is performed without error", func(t *testing.T) {
namespace := t.Name()
// Create a SonataFlowPlatform object with metadata and spec.
ksp := test.GetBasePlatformInReadyPhase(namespace)
var replicas int32 = 2
ksp.Spec.Services = &v1alpha08.ServicesPlatformSpec{
JobService: &v1alpha08.ServiceSpec{
PodTemplate: v1alpha08.PodTemplateSpec{
Replicas: &replicas,
Container: v1alpha08.ContainerSpec{
Command: []string{"test:latest"},
},
},
},
}
js := services.NewJobServiceHandler(ksp)
// Create a fake client to mock API calls.
cl := test.NewKogitoClientBuilderWithOpenShift().WithRuntimeObjects(ksp).WithStatusSubresource(ksp).Build()
// Create a SonataFlowPlatformReconciler object with the scheme and fake client.
r := &SonataFlowPlatformReconciler{cl, cl, cl.Scheme(), &rest.Config{}, &record.FakeRecorder{}}
// Mock request to simulate Reconcile() being called on an event for a
// watched resource .
req := reconcile.Request{
NamespacedName: types.NamespacedName{
Name: ksp.Name,
Namespace: ksp.Namespace,
},
}
_, err := r.Reconcile(context.TODO(), req)
if err != nil {
t.Fatalf("reconcile: (%v)", err)
}
assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: ksp.Name, Namespace: ksp.Namespace}, ksp))
// Perform some checks on the created CR
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.NotNil(t, ksp.Spec.Services.JobService)
assert.NotNil(t, ksp.Spec.Services.JobService.Enabled)
assert.Equal(t, true, *ksp.Spec.Services.JobService.Enabled)
assert.Equal(t, v1alpha08.PlatformClusterKubernetes, ksp.Status.Cluster)
assert.Equal(t, "", ksp.Status.GetTopLevelCondition().Reason)
// Check job service deployment
dep := &appsv1.Deployment{}
assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: js.GetServiceName(), Namespace: ksp.Namespace}, dep))
assert.Len(t, dep.Spec.Template.Spec.Containers, 1)
assert.Equal(t, js.GetServiceImageName(constants.PersistenceTypeEphemeral), dep.Spec.Template.Spec.Containers[0].Image)
assert.NotContains(t, dep.Spec.Template.Spec.Containers[0].Env, envDBKind)
assert.NotContains(t, dep.Spec.Template.Spec.Containers[0].Env, envDataIndex)
// Check with persistence set
url := "jdbc:postgresql://host:1234/database?currentSchema=data-index-service"
ksp.Spec.Services.JobService.Persistence = &v1alpha08.PersistenceOptionsSpec{PostgreSQL: &v1alpha08.PersistencePostgreSQL{
SecretRef: v1alpha08.PostgreSQLSecretOptions{Name: "test"},
JdbcUrl: url,
}}
// Ensure correct container overriding anything set in PodSpec
ksp.Spec.Services.JobService.PodTemplate.PodSpec.Containers = []corev1.Container{{Name: constants.JobServiceName}}
assert.NoError(t, cl.Update(context.TODO(), ksp))
_, err = r.Reconcile(context.TODO(), req)
if err != nil {
t.Fatalf("reconcile: (%v)", err)
}
assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: js.GetServiceName(), Namespace: ksp.Namespace}, dep))
assert.Len(t, dep.Spec.Template.Spec.Containers, 1)
assert.Equal(t, js.GetServiceImageName(constants.PersistenceTypePostgreSQL), dep.Spec.Template.Spec.Containers[0].Image)
assert.Equal(t, int32(1), *dep.Spec.Replicas)
assert.Equal(t, []string{"test:latest"}, dep.Spec.Template.Spec.Containers[0].Command)
assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, envDBKind)
assert.NotContains(t, dep.Spec.Template.Spec.Containers[0].Env, envDataIndex)
})
t.Run("verify that a default deployment of a job and data index service will is performed without error", func(t *testing.T) {
namespace := t.Name()
// Create a SonataFlowPlatform object with metadata and spec.
ksp := test.GetBasePlatformInReadyPhase(namespace)
ksp.Spec.Services = &v1alpha08.ServicesPlatformSpec{
DataIndex: &v1alpha08.ServiceSpec{},
JobService: &v1alpha08.ServiceSpec{},
}
di := services.NewDataIndexHandler(ksp)
js := services.NewJobServiceHandler(ksp)
// Create a fake client to mock API calls.
cl := test.NewKogitoClientBuilderWithOpenShift().WithRuntimeObjects(ksp).WithStatusSubresource(ksp).Build()
// Create a SonataFlowPlatformReconciler object with the scheme and fake client.
r := &SonataFlowPlatformReconciler{cl, cl, cl.Scheme(), &rest.Config{}, &record.FakeRecorder{}}
// Mock request to simulate Reconcile() being called on an event for a
// watched resource .
req := reconcile.Request{
NamespacedName: types.NamespacedName{
Name: ksp.Name,
Namespace: ksp.Namespace,
},
}
_, err := r.Reconcile(context.TODO(), req)
if err != nil {
t.Fatalf("reconcile: (%v)", err)
}
assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: ksp.Name, Namespace: ksp.Namespace}, ksp))
// Perform some checks on the created CR
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.NotNil(t, ksp.Spec.Services.DataIndex)
assert.NotNil(t, ksp.Spec.Services.DataIndex.Enabled)
assert.Equal(t, true, *ksp.Spec.Services.DataIndex.Enabled)
assert.NotNil(t, ksp.Spec.Services.JobService)
assert.NotNil(t, ksp.Spec.Services.JobService.Enabled)
assert.Equal(t, true, *ksp.Spec.Services.JobService.Enabled)
assert.Equal(t, v1alpha08.PlatformClusterKubernetes, ksp.Status.Cluster)
assert.Equal(t, "", ksp.Status.GetTopLevelCondition().Reason)
// Check data index deployment
dep := &appsv1.Deployment{}
assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: di.GetServiceName(), Namespace: ksp.Namespace}, dep))
assert.Len(t, dep.Spec.Template.Spec.Containers, 1)
assert.Equal(t, di.GetServiceImageName(constants.PersistenceTypeEphemeral), dep.Spec.Template.Spec.Containers[0].Image)
assert.NotContains(t, dep.Spec.Template.Spec.Containers[0].Env, envDBKind)
assert.Contains(t, dep.Spec.Template.Spec.Containers[0].Env, envDataIndex)
// Check job service deployment
dep = &appsv1.Deployment{}
assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: js.GetServiceName(), Namespace: ksp.Namespace}, dep))
assert.Len(t, dep.Spec.Template.Spec.Containers, 1)
assert.Equal(t, js.GetServiceImageName(constants.PersistenceTypeEphemeral), dep.Spec.Template.Spec.Containers[0].Image)
assert.NotContains(t, dep.Spec.Template.Spec.Containers[0].Env, envDBKind)
assert.NotContains(t, dep.Spec.Template.Spec.Containers[0].Env, envDataIndex)
})
t.Run("verify that a basic reconcile of a cluster platform is performed without error", func(t *testing.T) {
namespace := t.Name()
// Create a SonataFlowClusterPlatform object with metadata and spec.
kscp := test.GetBaseClusterPlatformInReadyPhase(namespace)
// Create a SonataFlowPlatform object with metadata and spec.
ksp := test.GetBasePlatformInReadyPhase(namespace)
ksp.Spec.Services = &v1alpha08.ServicesPlatformSpec{
DataIndex: &v1alpha08.ServiceSpec{},
JobService: &v1alpha08.ServiceSpec{},
}
ksp2 := test.GetBasePlatformInReadyPhase(namespace)
ksp2.Name = "ksp2"
// Create a fake client to mock API calls.
cl := test.NewSonataFlowClientBuilder().WithRuntimeObjects(kscp, ksp, ksp2).WithStatusSubresource(kscp, ksp, ksp2).Build()
// Create a SonataFlowPlatformReconciler object with the scheme and fake client.
r := &SonataFlowPlatformReconciler{cl, cl, cl.Scheme(), &rest.Config{}, &record.FakeRecorder{}}
// Mock request to simulate Reconcile() being called on an event for a
// watched resource .
req := reconcile.Request{
NamespacedName: types.NamespacedName{
Name: ksp.Name,
Namespace: ksp.Namespace,
},
}
_, err := r.Reconcile(context.TODO(), req)
if err != nil {
t.Fatalf("reconcile: (%v)", err)
}
assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: ksp.Name, Namespace: ksp.Namespace}, ksp))
assert.Greater(t, len(ksp2.Status.Conditions), 0)
assert.Nil(t, ksp2.Status.ClusterPlatformRef)
// Create a SonataFlowClusterPlatformReconciler object with the scheme and fake client.
cr := &SonataFlowClusterPlatformReconciler{cl, cl, cl.Scheme(), &rest.Config{}, &record.FakeRecorder{}}
// Mock request to simulate Reconcile() being called on an event for a
// watched resource .
cReq := reconcile.Request{
NamespacedName: types.NamespacedName{
Name: kscp.Name,
},
}
_, err = cr.Reconcile(context.TODO(), cReq)
if err != nil {
t.Fatalf("reconcile: (%v)", err)
}
assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: kscp.Name}, kscp))
assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: ksp.Name, Namespace: ksp.Namespace}, ksp))
// Perform some checks on the created CR
assert.True(t, ksp.Status.IsReady())
assert.True(t, kscp.Status.IsReady())
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.NotNil(t, ksp.Spec.Services.DataIndex)
assert.NotNil(t, ksp.Spec.Services.DataIndex.Enabled)
assert.Equal(t, true, *ksp.Spec.Services.DataIndex.Enabled)
assert.Equal(t, v1alpha08.PlatformClusterKubernetes, ksp.Status.Cluster)
assert.Equal(t, "", ksp.Status.GetTopLevelCondition().Reason)
assert.Equal(t, kscp.Name, ksp.Status.ClusterPlatformRef.Name)
assert.Equal(t, kscp.Spec.PlatformRef.Name, ksp.Status.ClusterPlatformRef.PlatformRef.Name)
assert.Equal(t, kscp.Spec.PlatformRef.Namespace, ksp.Status.ClusterPlatformRef.PlatformRef.Namespace)
assert.NotNil(t, kscp.Spec.Capabilities)
assert.Contains(t, kscp.Spec.Capabilities.Workflows, clusterplatform.PlatformServices)
assert.NotNil(t, ksp.Status.ClusterPlatformRef)
assert.Nil(t, ksp.Status.ClusterPlatformRef.Services)
req2 := reconcile.Request{
NamespacedName: types.NamespacedName{
Name: ksp2.Name,
Namespace: ksp2.Namespace,
},
}
_, err = r.Reconcile(context.TODO(), req2)
if err != nil {
t.Fatalf("reconcile: (%v)", err)
}
assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: ksp2.Name, Namespace: ksp2.Namespace}, ksp2))
assert.True(t, ksp2.Status.IsReady())
assert.NotNil(t, ksp2.Status.ClusterPlatformRef)
assert.Equal(t, kscp.Name, ksp2.Status.ClusterPlatformRef.Name)
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.NotNil(t, ksp2.Status.ClusterPlatformRef.Services)
assert.NotNil(t, ksp2.Status.ClusterPlatformRef.Services.DataIndexRef)
assert.NotEmpty(t, ksp2.Status.ClusterPlatformRef.Services.DataIndexRef.Url)
assert.NotNil(t, ksp2.Status.ClusterPlatformRef.Services.JobServiceRef)
assert.NotEmpty(t, ksp2.Status.ClusterPlatformRef.Services.JobServiceRef.Url)
psDi := services.NewDataIndexHandler(ksp)
psDi2 := services.NewDataIndexHandler(ksp2)
assert.Equal(t, ksp2.Status.ClusterPlatformRef.Services.DataIndexRef.Url, psDi.GetLocalServiceBaseUrl())
assert.Equal(t, psDi.GetLocalServiceBaseUrl()+constants.KogitoProcessInstancesEventsPath, psDi2.GetServiceBaseUrl()+constants.KogitoProcessInstancesEventsPath)
psJs := services.NewJobServiceHandler(ksp)
psJs2 := services.NewJobServiceHandler(ksp2)
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{}
assert.NoError(t, cl.Update(context.TODO(), ksp2))
_, err = r.Reconcile(context.TODO(), req2)
if err != nil {
t.Fatalf("reconcile: (%v)", err)
}
assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: ksp2.Name, Namespace: ksp2.Namespace}, ksp2))
assert.True(t, ksp2.Status.IsReady())
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)
kscp.Spec.Capabilities = &v1alpha08.SonataFlowClusterPlatformCapSpec{}
assert.NoError(t, cl.Update(context.TODO(), kscp))
_, err = cr.Reconcile(context.TODO(), cReq)
if err != nil {
t.Fatalf("reconcile: (%v)", err)
}
_, err = r.Reconcile(context.TODO(), req2)
if err != nil {
t.Fatalf("reconcile: (%v)", err)
}
assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: kscp.Name}, kscp))
assert.NoError(t, cl.Get(context.TODO(), types.NamespacedName{Name: ksp2.Name, Namespace: ksp2.Namespace}, ksp2))
assert.NotNil(t, kscp.Spec.Capabilities)
assert.Empty(t, kscp.Spec.Capabilities.Workflows)
assert.NotNil(t, ksp2.Status.ClusterPlatformRef)
assert.Nil(t, ksp2.Status.ClusterPlatformRef.Services)
})
}