You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kie.apache.org by ri...@apache.org on 2024/02/28 16:07:23 UTC

(incubator-kie-kogito-serverless-operator) branch main updated: [380] enhance SonataFlowClusterPlatform.spec (#389)

This is an automated email from the ASF dual-hosted git repository.

ricardozanini pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-kie-kogito-serverless-operator.git


The following commit(s) were added to refs/heads/main by this push:
     new 64db02d0 [380] enhance SonataFlowClusterPlatform.spec (#389)
64db02d0 is described below

commit 64db02d0f398c08d43ba1bb390f43542dad17360
Author: Tommy Hughes IV <to...@redhat.com>
AuthorDate: Wed Feb 28 10:07:19 2024 -0600

    [380] enhance SonataFlowClusterPlatform.spec (#389)
    
    Signed-off-by: Tommy Hughes <to...@redhat.com>
---
 api/v1alpha08/sonataflowclusterplatform_types.go   |  12 +
 api/v1alpha08/zz_generated.deepcopy.go             |  27 +-
 .../sonataflow-operator.clusterserviceversion.yaml |   4 +
 .../sonataflow.org_sonataflowclusterplatforms.yaml |  13 +
 .../sonataflow.org_sonataflowclusterplatforms.yaml |  13 +
 .../sonataflow-operator.clusterserviceversion.yaml |   4 +
 controllers/clusterplatform/clusterplatform.go     |   4 +
 controllers/clusterplatform/defaults.go            |  55 +++++
 controllers/clusterplatform/initialize.go          |   4 +
 controllers/platform/services/services.go          |   8 +-
 controllers/sonataflowplatform_controller.go       |  19 +-
 controllers/sonataflowplatform_controller_test.go  |  24 ++
 operator.yaml                                      |  13 +
 test/e2e/clusterplatform_test.go                   | 271 +++++++++++++++++++++
 test/e2e/platform_test.go                          |  11 +-
 .../dev/ephemeral/02-sonataflow_platform.yaml      |  27 ++
 .../noservices/dev/ephemeral/kustomization.yaml    |  20 ++
 .../03-sonataflow_callbackstatetimeouts.sw.yaml    |  81 ++++++
 .../01-sonataflow_clusterplatform.yaml             |  25 ++
 .../02-sonataflow_platform.yaml                    |  32 +++
 .../dev/cluster-wide-ephemeral/kustomization.yaml  |  17 ++
 .../02-sonataflow_platform.yaml                    |  30 +++
 .../dev/ephemeral-data-index/kustomization.yaml    |  20 ++
 .../03-sonataflow_callbackstatetimeouts.sw.yaml    |  81 ++++++
 .../02-sonataflow_platform.yaml                    |  30 +++
 .../dev/ephemeral-job-service/kustomization.yaml   |  20 ++
 .../03-sonataflow_callbackstatetimeouts.sw.yaml    |  81 ++++++
 test/yaml.go                                       |   4 +
 28 files changed, 937 insertions(+), 13 deletions(-)

diff --git a/api/v1alpha08/sonataflowclusterplatform_types.go b/api/v1alpha08/sonataflowclusterplatform_types.go
index b5063545..d5205d9c 100644
--- a/api/v1alpha08/sonataflowclusterplatform_types.go
+++ b/api/v1alpha08/sonataflowclusterplatform_types.go
@@ -31,8 +31,20 @@ type SonataFlowClusterPlatformSpec struct {
 	// PlatformRef defines which existing SonataFlowPlatform's supporting services should be used cluster-wide.
 	//+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="PlatformRef"
 	PlatformRef SonataFlowPlatformRef `json:"platformRef"`
+	// Capabilities defines which platform capabilities should be applied cluster-wide. If nil, defaults to `capabilities.workflows["services"]`
+	//+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Capabilities"
+	Capabilities *SonataFlowClusterPlatformCapSpec `json:"capabilities,omitempty"`
 }
 
+// SonataFlowClusterPlatformCapSpec defines which platform capabilities should be applied cluster-wide
+type SonataFlowClusterPlatformCapSpec struct {
+	// Workflows defines which platform capabilities should be applied to workflows cluster-wide.
+	Workflows []WorkFlowCapability `json:"workflows,omitempty"`
+}
+
+// +kubebuilder:validation:Enum=services
+type WorkFlowCapability string
+
 // SonataFlowPlatformRef defines which existing SonataFlowPlatform's supporting services should be used cluster-wide.
 type SonataFlowPlatformRef struct {
 	// Name of the SonataFlowPlatform
diff --git a/api/v1alpha08/zz_generated.deepcopy.go b/api/v1alpha08/zz_generated.deepcopy.go
index cc7870ae..75e8bf32 100644
--- a/api/v1alpha08/zz_generated.deepcopy.go
+++ b/api/v1alpha08/zz_generated.deepcopy.go
@@ -870,7 +870,7 @@ func (in *SonataFlowClusterPlatform) DeepCopyInto(out *SonataFlowClusterPlatform
 	*out = *in
 	out.TypeMeta = in.TypeMeta
 	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
-	out.Spec = in.Spec
+	in.Spec.DeepCopyInto(&out.Spec)
 	in.Status.DeepCopyInto(&out.Status)
 }
 
@@ -892,6 +892,26 @@ func (in *SonataFlowClusterPlatform) DeepCopyObject() runtime.Object {
 	return nil
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *SonataFlowClusterPlatformCapSpec) DeepCopyInto(out *SonataFlowClusterPlatformCapSpec) {
+	*out = *in
+	if in.Workflows != nil {
+		in, out := &in.Workflows, &out.Workflows
+		*out = make([]WorkFlowCapability, len(*in))
+		copy(*out, *in)
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SonataFlowClusterPlatformCapSpec.
+func (in *SonataFlowClusterPlatformCapSpec) DeepCopy() *SonataFlowClusterPlatformCapSpec {
+	if in == nil {
+		return nil
+	}
+	out := new(SonataFlowClusterPlatformCapSpec)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *SonataFlowClusterPlatformList) DeepCopyInto(out *SonataFlowClusterPlatformList) {
 	*out = *in
@@ -949,6 +969,11 @@ func (in *SonataFlowClusterPlatformRefStatus) DeepCopy() *SonataFlowClusterPlatf
 func (in *SonataFlowClusterPlatformSpec) DeepCopyInto(out *SonataFlowClusterPlatformSpec) {
 	*out = *in
 	out.PlatformRef = in.PlatformRef
+	if in.Capabilities != nil {
+		in, out := &in.Capabilities, &out.Capabilities
+		*out = new(SonataFlowClusterPlatformCapSpec)
+		(*in).DeepCopyInto(*out)
+	}
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SonataFlowClusterPlatformSpec.
diff --git a/bundle/manifests/sonataflow-operator.clusterserviceversion.yaml b/bundle/manifests/sonataflow-operator.clusterserviceversion.yaml
index 95bceb33..cffce25e 100644
--- a/bundle/manifests/sonataflow-operator.clusterserviceversion.yaml
+++ b/bundle/manifests/sonataflow-operator.clusterserviceversion.yaml
@@ -190,6 +190,10 @@ spec:
         name: A SonataFlow Platform
         version: sonataflow.org/v1alpha08
       specDescriptors:
+      - description: Capabilities defines which platform capabilities should be applied
+          cluster-wide. If nil, defaults to `capabilities.workflows["services"]`
+        displayName: Capabilities
+        path: capabilities
       - description: PlatformRef defines which existing SonataFlowPlatform's supporting
           services should be used cluster-wide.
         displayName: PlatformRef
diff --git a/bundle/manifests/sonataflow.org_sonataflowclusterplatforms.yaml b/bundle/manifests/sonataflow.org_sonataflowclusterplatforms.yaml
index 0d9a7b20..a5071d1e 100644
--- a/bundle/manifests/sonataflow.org_sonataflowclusterplatforms.yaml
+++ b/bundle/manifests/sonataflow.org_sonataflowclusterplatforms.yaml
@@ -49,6 +49,19 @@ spec:
             description: SonataFlowClusterPlatformSpec defines the desired state of
               SonataFlowClusterPlatform
             properties:
+              capabilities:
+                description: Capabilities defines which platform capabilities should
+                  be applied cluster-wide. If nil, defaults to `capabilities.workflows["services"]`
+                properties:
+                  workflows:
+                    description: Workflows defines which platform capabilities should
+                      be applied to workflows cluster-wide.
+                    items:
+                      enum:
+                      - services
+                      type: string
+                    type: array
+                type: object
               platformRef:
                 description: PlatformRef defines which existing SonataFlowPlatform's
                   supporting services should be used cluster-wide.
diff --git a/config/crd/bases/sonataflow.org_sonataflowclusterplatforms.yaml b/config/crd/bases/sonataflow.org_sonataflowclusterplatforms.yaml
index 537d06ba..15275005 100644
--- a/config/crd/bases/sonataflow.org_sonataflowclusterplatforms.yaml
+++ b/config/crd/bases/sonataflow.org_sonataflowclusterplatforms.yaml
@@ -50,6 +50,19 @@ spec:
             description: SonataFlowClusterPlatformSpec defines the desired state of
               SonataFlowClusterPlatform
             properties:
+              capabilities:
+                description: Capabilities defines which platform capabilities should
+                  be applied cluster-wide. If nil, defaults to `capabilities.workflows["services"]`
+                properties:
+                  workflows:
+                    description: Workflows defines which platform capabilities should
+                      be applied to workflows cluster-wide.
+                    items:
+                      enum:
+                      - services
+                      type: string
+                    type: array
+                type: object
               platformRef:
                 description: PlatformRef defines which existing SonataFlowPlatform's
                   supporting services should be used cluster-wide.
diff --git a/config/manifests/bases/sonataflow-operator.clusterserviceversion.yaml b/config/manifests/bases/sonataflow-operator.clusterserviceversion.yaml
index 3442b025..1f65bbed 100644
--- a/config/manifests/bases/sonataflow-operator.clusterserviceversion.yaml
+++ b/config/manifests/bases/sonataflow-operator.clusterserviceversion.yaml
@@ -74,6 +74,10 @@ spec:
         name: A SonataFlow Platform
         version: sonataflow.org/v1alpha08
       specDescriptors:
+      - description: Capabilities defines which platform capabilities should be applied
+          cluster-wide. If nil, defaults to `capabilities.workflows["services"]`
+        displayName: Capabilities
+        path: capabilities
       - description: PlatformRef defines which existing SonataFlowPlatform's supporting
           services should be used cluster-wide.
         displayName: PlatformRef
diff --git a/controllers/clusterplatform/clusterplatform.go b/controllers/clusterplatform/clusterplatform.go
index 6c1ffe45..e9a8c86c 100644
--- a/controllers/clusterplatform/clusterplatform.go
+++ b/controllers/clusterplatform/clusterplatform.go
@@ -30,6 +30,10 @@ import (
 	ctrl "sigs.k8s.io/controller-runtime/pkg/client"
 )
 
+const (
+	PlatformServices operatorapi.WorkFlowCapability = "services"
+)
+
 // GetActiveClusterPlatform returns the currently installed active cluster platform.
 func GetActiveClusterPlatform(ctx context.Context, c ctrl.Client) (*operatorapi.SonataFlowClusterPlatform, error) {
 	return getClusterPlatform(ctx, c, true)
diff --git a/controllers/clusterplatform/defaults.go b/controllers/clusterplatform/defaults.go
new file mode 100644
index 00000000..17657fc6
--- /dev/null
+++ b/controllers/clusterplatform/defaults.go
@@ -0,0 +1,55 @@
+/*
+ * 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 clusterplatform
+
+import (
+	"context"
+
+	operatorapi "github.com/apache/incubator-kie-kogito-serverless-operator/api/v1alpha08"
+	"github.com/apache/incubator-kie-kogito-serverless-operator/container-builder/client"
+	"github.com/apache/incubator-kie-kogito-serverless-operator/log"
+	"k8s.io/klog/v2"
+	ctrl "sigs.k8s.io/controller-runtime/pkg/client"
+)
+
+func configureDefaults(ctx context.Context, c client.Client, cp *operatorapi.SonataFlowClusterPlatform, verbose bool) error {
+	if cp.Spec.Capabilities == nil {
+		cp.Spec.Capabilities = &operatorapi.SonataFlowClusterPlatformCapSpec{
+			Workflows: []operatorapi.WorkFlowCapability{PlatformServices},
+		}
+	}
+
+	return updateClusterPlatform(ctx, c, cp)
+}
+
+func updateClusterPlatform(ctx context.Context, c client.Client, cp *operatorapi.SonataFlowClusterPlatform) error {
+	sfcPlatform := operatorapi.SonataFlowClusterPlatform{}
+	if err := c.Get(ctx, ctrl.ObjectKey{Namespace: cp.Namespace, Name: cp.Name}, &sfcPlatform); err != nil {
+		klog.V(log.E).ErrorS(err, "Error reading the Cluster Platform")
+		return err
+	}
+
+	sfcPlatform.Spec = cp.Spec
+	if err := c.Update(ctx, &sfcPlatform); err != nil {
+		klog.V(log.E).ErrorS(err, "Error updating the Cluster Platform")
+	}
+
+	return nil
+}
diff --git a/controllers/clusterplatform/initialize.go b/controllers/clusterplatform/initialize.go
index 15a9b9f8..ac595e36 100644
--- a/controllers/clusterplatform/initialize.go
+++ b/controllers/clusterplatform/initialize.go
@@ -61,6 +61,10 @@ func (action *initializeAction) Handle(ctx context.Context, cPlatform *operatora
 		}
 		return nil
 	}
+
+	if err = configureDefaults(ctx, action.client, cPlatform, true); err != nil {
+		return err
+	}
 	cPlatform.Status.Version = metadata.SpecVersion
 	platformRef := cPlatform.Spec.PlatformRef
 
diff --git a/controllers/platform/services/services.go b/controllers/platform/services/services.go
index 33a275fd..4b442c6a 100644
--- a/controllers/platform/services/services.go
+++ b/controllers/platform/services/services.go
@@ -159,7 +159,7 @@ func (d DataIndexHandler) GetServiceBaseUrl() string {
 }
 
 func (d DataIndexHandler) GetLocalServiceBaseUrl() string {
-	return generateServiceURL(constants.KogitoServiceURLProtocol, d.platform.Namespace, d.GetServiceName())
+	return GenerateServiceURL(constants.KogitoServiceURLProtocol, d.platform.Namespace, d.GetServiceName())
 }
 
 func (d DataIndexHandler) GetEnvironmentVariables() []corev1.EnvVar {
@@ -327,7 +327,7 @@ func (j JobServiceHandler) GetServiceBaseUrl() string {
 }
 
 func (j JobServiceHandler) GetLocalServiceBaseUrl() string {
-	return generateServiceURL(constants.JobServiceURLProtocol, j.platform.Namespace, j.GetServiceName())
+	return GenerateServiceURL(constants.JobServiceURLProtocol, j.platform.Namespace, j.GetServiceName())
 }
 
 func (j JobServiceHandler) GetEnvironmentVariables() []corev1.EnvVar {
@@ -395,7 +395,7 @@ func (j JobServiceHandler) MergePodSpec(podSpec corev1.PodSpec) (corev1.PodSpec,
 
 func (j JobServiceHandler) GenerateServiceProperties() (*properties.Properties, error) {
 	props := properties.NewProperties()
-	props.Set(constants.KogitoServiceURLProperty, generateServiceURL(constants.KogitoServiceURLProtocol, j.platform.Namespace, j.GetServiceName()))
+	props.Set(constants.KogitoServiceURLProperty, GenerateServiceURL(constants.KogitoServiceURLProtocol, j.platform.Namespace, j.GetServiceName()))
 	props.Set(constants.JobServiceKafkaSmallRyeHealthProperty, "false")
 	// add data source reactive URL
 	if j.hasPostgreSQLConfigured() {
@@ -447,7 +447,7 @@ func isServicesSet(platform *operatorapi.SonataFlowPlatform) bool {
 	return platform != nil && platform.Spec.Services != nil
 }
 
-func generateServiceURL(protocol string, namespace string, name string) string {
+func GenerateServiceURL(protocol string, namespace string, name string) string {
 	var serviceUrl string
 	if len(namespace) > 0 {
 		serviceUrl = fmt.Sprintf("%s://%s.%s", protocol, name, namespace)
diff --git a/controllers/sonataflowplatform_controller.go b/controllers/sonataflowplatform_controller.go
index c0ccd399..a26db2fb 100644
--- a/controllers/sonataflowplatform_controller.go
+++ b/controllers/sonataflowplatform_controller.go
@@ -203,11 +203,13 @@ func (r *SonataFlowPlatformReconciler) SonataFlowPlatformUpdateStatus(ctx contex
 			},
 		}
 
-		tpsDI := services.NewDataIndexHandler(target)
-		tpsDI.SetServiceUrlInStatus(sfPlatform)
+		if sfcPlatform.Spec.Capabilities != nil && contains(sfcPlatform.Spec.Capabilities.Workflows, clusterplatform.PlatformServices) {
+			tpsDI := services.NewDataIndexHandler(target)
+			tpsDI.SetServiceUrlInStatus(sfPlatform)
 
-		tpsJS := services.NewJobServiceHandler(target)
-		tpsJS.SetServiceUrlInStatus(sfPlatform)
+			tpsJS := services.NewJobServiceHandler(target)
+			tpsJS.SetServiceUrlInStatus(sfPlatform)
+		}
 	} else {
 		target.Status.ClusterPlatformRef = nil
 	}
@@ -273,3 +275,12 @@ func (r *SonataFlowPlatformReconciler) platformRequests(ctx context.Context, sfc
 	}
 	return requests
 }
+
+func contains(slice []operatorapi.WorkFlowCapability, s operatorapi.WorkFlowCapability) bool {
+	for _, a := range slice {
+		if a == s {
+			return true
+		}
+	}
+	return false
+}
diff --git a/controllers/sonataflowplatform_controller_test.go b/controllers/sonataflowplatform_controller_test.go
index 48c7b91c..abfffb20 100644
--- a/controllers/sonataflowplatform_controller_test.go
+++ b/controllers/sonataflowplatform_controller_test.go
@@ -24,6 +24,7 @@ import (
 	"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"
@@ -753,6 +754,8 @@ func TestSonataFlowPlatformController(t *testing.T) {
 		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)
@@ -802,5 +805,26 @@ 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)
+
+		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)
 	})
 }
diff --git a/operator.yaml b/operator.yaml
index 2869f707..a4693bd6 100644
--- a/operator.yaml
+++ b/operator.yaml
@@ -413,6 +413,19 @@ spec:
             description: SonataFlowClusterPlatformSpec defines the desired state of
               SonataFlowClusterPlatform
             properties:
+              capabilities:
+                description: Capabilities defines which platform capabilities should
+                  be applied cluster-wide. If nil, defaults to `capabilities.workflows["services"]`
+                properties:
+                  workflows:
+                    description: Workflows defines which platform capabilities should
+                      be applied to workflows cluster-wide.
+                    items:
+                      enum:
+                      - services
+                      type: string
+                    type: array
+                type: object
               platformRef:
                 description: PlatformRef defines which existing SonataFlowPlatform's
                   supporting services should be used cluster-wide.
diff --git a/test/e2e/clusterplatform_test.go b/test/e2e/clusterplatform_test.go
new file mode 100644
index 00000000..d0b545f6
--- /dev/null
+++ b/test/e2e/clusterplatform_test.go
@@ -0,0 +1,271 @@
+// 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 e2e
+
+import (
+	//nolint:golint
+	//nolint:revive
+
+	"bytes"
+	"fmt"
+	"math/rand"
+	"os/exec"
+	"path/filepath"
+	"time"
+
+	"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/apache/incubator-kie-kogito-serverless-operator/test/utils"
+
+	//nolint:golint
+	//nolint:revive
+	. "github.com/onsi/ginkgo/v2"
+
+	//nolint:golint
+	//nolint:revive
+	. "github.com/onsi/gomega"
+)
+
+var _ = Describe("Validate a clusterplatform", Ordered, func() {
+
+	var (
+		projectDir       string
+		targetNamespace  string
+		targetNamespace2 string
+	)
+
+	BeforeEach(func() {
+		targetNamespace = fmt.Sprintf("test-%d", rand.Intn(1024)+1)
+		cmd := exec.Command("kubectl", "create", "namespace", targetNamespace)
+		_, err := utils.Run(cmd)
+		Expect(err).NotTo(HaveOccurred())
+
+		targetNamespace2 = fmt.Sprintf("test-%d", rand.Intn(1024)+1)
+		cmd = exec.Command("kubectl", "create", "namespace", targetNamespace2)
+		_, err = utils.Run(cmd)
+		Expect(err).NotTo(HaveOccurred())
+	})
+	AfterEach(func() {
+		// Remove resources in test namespacs with no failure
+		if !CurrentSpecReport().Failed() {
+			if len(targetNamespace) > 0 {
+				cmd := exec.Command("kubectl", "delete", "namespace", targetNamespace, "--wait")
+				_, err := utils.Run(cmd)
+				Expect(err).NotTo(HaveOccurred())
+			}
+			if len(targetNamespace2) > 0 {
+				cmd := exec.Command("kubectl", "delete", "namespace", targetNamespace2, "--wait")
+				_, err := utils.Run(cmd)
+				Expect(err).NotTo(HaveOccurred())
+			}
+		}
+	})
+	var _ = Context("with supporting services enabled", func() {
+
+		DescribeTable("against a platform in a separate namespace", func(testcaseDir string, profile string, persistenceType string, withServices bool) {
+			By("Deploy the SonataFlowPlatform CR")
+			var manifests []byte
+			EventuallyWithOffset(1, func() error {
+				var err error
+				cmd := exec.Command("kubectl", "kustomize", filepath.Join(projectDir,
+					test.GetSonataFlowE2EPlatformServicesDirectory(), profile, clusterWideEphemeral))
+				manifests, err = utils.Run(cmd)
+				return err
+			}, time.Minute, time.Second).Should(Succeed())
+
+			cmd := exec.Command("kubectl", "create", "-n", targetNamespace, "-f", "-")
+			cmd.Stdin = bytes.NewBuffer(manifests)
+			_, err := utils.Run(cmd)
+			Expect(err).NotTo(HaveOccurred())
+
+			By("Wait for SonatatFlowPlatform CR in " + targetNamespace + " to be ready")
+			// wait for platform to be ready
+			EventuallyWithOffset(1, func() error {
+				cmd = exec.Command("kubectl", "wait", "sfplatform", "-n", targetNamespace, "sonataflow-platform", "--for", "condition=Succeed", "--timeout=5s")
+				_, err = utils.Run(cmd)
+				return err
+			}, 20*time.Minute, 5).Should(Succeed())
+			EventuallyWithOffset(1, func() []byte {
+				cmd = exec.Command("kubectl", "get", "sfplatform", "-n", targetNamespace, "sonataflow-platform", "-o", "jsonpath='{.status.clusterPlatformRef}'")
+				returnedValue, _ := utils.Run(cmd)
+				println(string(returnedValue))
+				return returnedValue
+			}, 20*time.Minute, 5).Should(Equal([]byte("''")))
+
+			By("Evaluate status of SonataFlowClusterPlatform CR")
+			cmd = exec.Command("kubectl", "patch", "SonataFlowClusterPlatform", "cluster", "--type", "merge", "-p", `{"spec": {"platformRef": {"namespace": "`+targetNamespace+`"}}}`)
+			_, err = utils.Run(cmd)
+			Expect(err).NotTo(HaveOccurred())
+			EventuallyWithOffset(1, func() error {
+				cmd = exec.Command("kubectl", "wait", "SonataFlowClusterPlatform", "cluster", "--for", "condition=Succeed", "--timeout=5s")
+				_, err = utils.Run(cmd)
+				return err
+			}, 20*time.Minute, 5).Should(Succeed())
+
+			if withServices {
+				By("Deploy SonatatFlowPlatform CR with services configured in " + targetNamespace2)
+				EventuallyWithOffset(1, func() error {
+					var err error
+					cmd := exec.Command("kubectl", "kustomize", filepath.Join(projectDir,
+						testcaseDir, profile, persistenceType))
+					manifests, err = utils.Run(cmd)
+					return err
+				}, time.Minute, time.Second).Should(Succeed())
+
+				cmd = exec.Command("kubectl", "create", "-n", targetNamespace2, "-f", "-")
+				cmd.Stdin = bytes.NewBuffer(manifests)
+				_, err = utils.Run(cmd)
+				Expect(err).NotTo(HaveOccurred())
+
+				By("Wait for SonatatFlowPlatform CR in " + targetNamespace2 + " to be ready")
+				// wait for platform to be ready
+				EventuallyWithOffset(1, func() error {
+					cmd = exec.Command("kubectl", "wait", "sfplatform", "-n", targetNamespace2, "sonataflow-platform", "--for", "condition=Succeed", "--timeout=5s")
+					_, err = utils.Run(cmd)
+					return err
+				}, 20*time.Minute, 5).Should(Succeed())
+				EventuallyWithOffset(1, func() []byte {
+					cmd = exec.Command("kubectl", "get", "sfplatform", "-n", targetNamespace2, "sonataflow-platform", "-o", "jsonpath='{.status.clusterPlatformRef}'")
+					returnedValue, _ := utils.Run(cmd)
+					return returnedValue
+				}, 20*time.Minute, 5).Should(Not(Equal([]byte("''"))))
+				EventuallyWithOffset(1, func() []byte {
+					cmd = exec.Command("kubectl", "get", "sfplatform", "-n", targetNamespace2, "sonataflow-platform", "-o", "jsonpath='{.status.clusterPlatformRef.services}'")
+					returnedValue, _ := utils.Run(cmd)
+					return returnedValue
+				}, 20*time.Minute, 5).Should(Equal([]byte("''")))
+			} else {
+				EventuallyWithOffset(1, func() error {
+					var err error
+					cmd := exec.Command("kubectl", "kustomize", filepath.Join(projectDir,
+						testcaseDir, profile, persistenceType))
+					manifests, err = utils.Run(cmd)
+					return err
+				}, time.Minute, time.Second).Should(Succeed())
+
+				cmd = exec.Command("kubectl", "create", "-n", targetNamespace2, "-f", "-")
+				cmd.Stdin = bytes.NewBuffer(manifests)
+				_, err = utils.Run(cmd)
+				Expect(err).NotTo(HaveOccurred())
+
+				By("Wait for SonatatFlowPlatform CR in " + targetNamespace2 + " to be ready")
+				dataIndexServiceUrl := services.GenerateServiceURL(constants.KogitoServiceURLProtocol, targetNamespace, "sonataflow-platform-"+constants.DataIndexServiceName)
+				jobServiceUrl := services.GenerateServiceURL(constants.KogitoServiceURLProtocol, targetNamespace, "sonataflow-platform-"+constants.JobServiceName)
+				// wait for platform to be ready
+				EventuallyWithOffset(1, func() error {
+					cmd = exec.Command("kubectl", "wait", "sfplatform", "-n", targetNamespace2, "sonataflow-platform", "--for", "condition=Succeed", "--timeout=5s")
+					_, err = utils.Run(cmd)
+					return err
+				}, 20*time.Minute, 5).Should(Succeed())
+				EventuallyWithOffset(1, func() []byte {
+					cmd = exec.Command("kubectl", "get", "sfplatform", "-n", targetNamespace2, "sonataflow-platform", "-o", "jsonpath='{.status.clusterPlatformRef.services.dataIndexRef.url}'")
+					returnedValue, _ := utils.Run(cmd)
+					return returnedValue
+				}, 20*time.Minute, 5).Should(Equal([]byte("'" + dataIndexServiceUrl + "'")))
+				EventuallyWithOffset(1, func() []byte {
+					cmd = exec.Command("kubectl", "get", "sfplatform", "-n", targetNamespace2, "sonataflow-platform", "-o", "jsonpath='{.status.clusterPlatformRef.services.jobServiceRef.url}'")
+					returnedValue, _ := utils.Run(cmd)
+					return returnedValue
+				}, 20*time.Minute, 5).Should(Equal([]byte("'" + jobServiceUrl + "'")))
+			}
+			cmd = exec.Command("kubectl", "delete", "SonataFlowClusterPlatform", "cluster", "--wait")
+			_, err = utils.Run(cmd)
+			Expect(err).NotTo(HaveOccurred())
+		},
+			Entry("without services configured", test.GetSonataFlowE2EPlatformNoServicesDirectory(), dev, ephemeral, false),
+			Entry("with services configured", test.GetSonataFlowE2EPlatformServicesDirectory(), dev, ephemeral, true),
+		)
+
+		DescribeTable("against a platform in a separate namespace", func(testcaseDir string, profile string, persistenceType string) {
+			By("Deploy the SonataFlowPlatform CR")
+			var manifests []byte
+			EventuallyWithOffset(1, func() error {
+				var err error
+				cmd := exec.Command("kubectl", "kustomize", filepath.Join(projectDir,
+					test.GetSonataFlowE2EPlatformServicesDirectory(), profile, clusterWideEphemeral))
+				manifests, err = utils.Run(cmd)
+				return err
+			}, time.Minute, time.Second).Should(Succeed())
+
+			cmd := exec.Command("kubectl", "create", "-n", targetNamespace, "-f", "-")
+			cmd.Stdin = bytes.NewBuffer(manifests)
+			_, err := utils.Run(cmd)
+			Expect(err).NotTo(HaveOccurred())
+
+			By("Wait for SonatatFlowPlatform CR in " + targetNamespace + " to be ready")
+			// wait for platform to be ready
+			EventuallyWithOffset(1, func() error {
+				cmd = exec.Command("kubectl", "wait", "sfplatform", "-n", targetNamespace, "sonataflow-platform", "--for", "condition=Succeed", "--timeout=5s")
+				_, err = utils.Run(cmd)
+				return err
+			}, 20*time.Minute, 5).Should(Succeed())
+			EventuallyWithOffset(1, func() []byte {
+				cmd = exec.Command("kubectl", "get", "sfplatform", "-n", targetNamespace, "sonataflow-platform", "-o", "jsonpath='{.status.clusterPlatformRef}'")
+				returnedValue, _ := utils.Run(cmd)
+				println(string(returnedValue))
+				return returnedValue
+			}, 20*time.Minute, 5).Should(Equal([]byte("''")))
+
+			By("Evaluate status of SonataFlowClusterPlatform CR")
+			cmd = exec.Command("kubectl", "patch", "SonataFlowClusterPlatform", "cluster", "--type", "merge", "-p", `{"spec": {"platformRef": {"namespace": "`+targetNamespace+`"}}}`)
+			_, err = utils.Run(cmd)
+			Expect(err).NotTo(HaveOccurred())
+			EventuallyWithOffset(1, func() error {
+				cmd = exec.Command("kubectl", "wait", "SonataFlowClusterPlatform", "cluster", "--for", "condition=Succeed", "--timeout=5s")
+				_, err = utils.Run(cmd)
+				return err
+			}, 20*time.Minute, 5).Should(Succeed())
+
+			EventuallyWithOffset(1, func() error {
+				var err error
+				cmd := exec.Command("kubectl", "kustomize", filepath.Join(projectDir,
+					testcaseDir, profile, persistenceType))
+				manifests, err = utils.Run(cmd)
+				return err
+			}, time.Minute, time.Second).Should(Succeed())
+
+			cmd = exec.Command("kubectl", "create", "-n", targetNamespace2, "-f", "-")
+			cmd.Stdin = bytes.NewBuffer(manifests)
+			_, err = utils.Run(cmd)
+			Expect(err).NotTo(HaveOccurred())
+
+			By("Wait for SonatatFlowPlatform CR in " + targetNamespace2 + " to be ready")
+			// wait for platform to be ready
+			EventuallyWithOffset(1, func() error {
+				cmd = exec.Command("kubectl", "wait", "sfplatform", "-n", targetNamespace2, "sonataflow-platform", "--for", "condition=Succeed", "--timeout=5s")
+				_, err = utils.Run(cmd)
+				return err
+			}, 20*time.Minute, 5).Should(Succeed())
+			EventuallyWithOffset(1, func() []byte {
+				cmd = exec.Command("kubectl", "get", "sfplatform", "-n", targetNamespace2, "sonataflow-platform", "-o", "jsonpath='{.status.clusterPlatformRef}'")
+				returnedValue, _ := utils.Run(cmd)
+				return returnedValue
+			}, 20*time.Minute, 5).Should(Not(Equal([]byte("''"))))
+			EventuallyWithOffset(1, func() []byte {
+				cmd = exec.Command("kubectl", "get", "sfplatform", "-n", targetNamespace2, "sonataflow-platform", "-o", "jsonpath='{.status.clusterPlatformRef.services}'")
+				returnedValue, _ := utils.Run(cmd)
+				return returnedValue
+			}, 20*time.Minute, 5).Should(Equal([]byte("''")))
+
+			cmd = exec.Command("kubectl", "delete", "SonataFlowClusterPlatform", "cluster", "--wait")
+			_, err = utils.Run(cmd)
+			Expect(err).NotTo(HaveOccurred())
+		},
+			Entry("with only Data Index configured", test.GetSonataFlowE2EPlatformServicesDirectory(), dev, ephemeralDataIndex),
+			Entry("with only Job Service configured", test.GetSonataFlowE2EPlatformServicesDirectory(), dev, ephemeralJobService),
+		)
+	})
+})
diff --git a/test/e2e/platform_test.go b/test/e2e/platform_test.go
index 90c485d7..00f51039 100644
--- a/test/e2e/platform_test.go
+++ b/test/e2e/platform_test.go
@@ -36,10 +36,13 @@ import (
 )
 
 const (
-	ephemeral  = "ephemeral"
-	postgreSQL = "postgreSQL"
-	dev        = "dev"
-	production = "prod"
+	ephemeral            = "ephemeral"
+	postgreSQL           = "postgreSQL"
+	dev                  = "dev"
+	production           = "prod"
+	clusterWideEphemeral = "cluster-wide-ephemeral"
+	ephemeralDataIndex   = "ephemeral-data-index"
+	ephemeralJobService  = "ephemeral-job-service"
 )
 
 var _ = Describe("Validate the persistence", Ordered, func() {
diff --git a/test/testdata/platform/noservices/dev/ephemeral/02-sonataflow_platform.yaml b/test/testdata/platform/noservices/dev/ephemeral/02-sonataflow_platform.yaml
new file mode 100644
index 00000000..c86ba512
--- /dev/null
+++ b/test/testdata/platform/noservices/dev/ephemeral/02-sonataflow_platform.yaml
@@ -0,0 +1,27 @@
+# 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.
+
+apiVersion: sonataflow.org/v1alpha08
+kind: SonataFlowPlatform
+metadata:
+  name: sonataflow-platform
+spec:
+  build:
+    template:
+      buildArgs:
+      - name: QUARKUS_EXTENSION
+        value: org.kie.kogito:kogito-addons-quarkus-jobs-knative-eventing:999-SNAPSHOT
+    config:
+      strategyOptions:
+        KanikoBuildCacheEnabled: "true"
diff --git a/test/testdata/platform/noservices/dev/ephemeral/kustomization.yaml b/test/testdata/platform/noservices/dev/ephemeral/kustomization.yaml
new file mode 100644
index 00000000..5441bfce
--- /dev/null
+++ b/test/testdata/platform/noservices/dev/ephemeral/kustomization.yaml
@@ -0,0 +1,20 @@
+# 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.
+
+resources:
+- 02-sonataflow_platform.yaml
+
+sortOptions:
+  order: fifo
+
diff --git a/test/testdata/platform/noservices/dev/ephemeral/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml b/test/testdata/platform/noservices/dev/ephemeral/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml
new file mode 100644
index 00000000..8bc8a77d
--- /dev/null
+++ b/test/testdata/platform/noservices/dev/ephemeral/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml
@@ -0,0 +1,81 @@
+# 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.
+
+apiVersion: sonataflow.org/v1alpha08
+kind: SonataFlow
+metadata:
+  name: callbackstatetimeouts
+  annotations:
+    sonataflow.org/description: Callback State Timeouts Example k8s
+    sonataflow.org/version: 0.0.1
+    sonataflow.org/profile: dev
+spec:
+  flow:
+    start: PrintStartMessage
+    events:
+      - name: callbackEvent
+        source: ''
+        type: callback_event_type
+    functions:
+      - name: systemOut
+        type: custom
+        operation: sysout
+    states:
+      - name: PrintStartMessage
+        type: operation
+        actions:
+          - name: printSystemOut
+            functionRef:
+              refName: systemOut
+              arguments:
+                message: "${\"callback-state-timeouts: \" + $WORKFLOW.instanceId + \" has started.\"}"
+        transition: CallbackState
+      - name: CallbackState
+        type: callback
+        action:
+          name: callbackAction
+          functionRef:
+            refName: systemOut
+            arguments:
+              message: "${\"callback-state-timeouts: \" + $WORKFLOW.instanceId + \" has executed the callbackFunction.\"}"
+        eventRef: callbackEvent
+        transition: CheckEventArrival
+        timeouts:
+          eventTimeout: PT30S
+      - name: CheckEventArrival
+        type: switch
+        dataConditions:
+          - condition: "${ .eventData != null }"
+            transition: EventArrived
+        defaultCondition:
+          transition: EventNotArrived
+      - name: EventArrived
+        type: inject
+        data:
+          exitMessage: "The callback event has arrived."
+        transition: PrintExitMessage
+      - name: EventNotArrived
+        type: inject
+        data:
+          exitMessage: "The callback event has not arrived, and the timeout has overdue."
+        transition: PrintExitMessage
+      - name: PrintExitMessage
+        type: operation
+        actions:
+          - name: printSystemOut
+            functionRef:
+              refName: systemOut
+              arguments:
+                message: "${\"callback-state-timeouts: \" + $WORKFLOW.instanceId + \" has finalized. \" + .exitMessage + \" eventData: \" + .eventData}"
+        end: true
diff --git a/test/testdata/platform/services/dev/cluster-wide-ephemeral/01-sonataflow_clusterplatform.yaml b/test/testdata/platform/services/dev/cluster-wide-ephemeral/01-sonataflow_clusterplatform.yaml
new file mode 100644
index 00000000..57e9735d
--- /dev/null
+++ b/test/testdata/platform/services/dev/cluster-wide-ephemeral/01-sonataflow_clusterplatform.yaml
@@ -0,0 +1,25 @@
+# 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.
+
+apiVersion: sonataflow.org/v1alpha08
+kind: SonataFlowClusterPlatform
+metadata:
+  name: cluster
+spec:
+  platformRef:
+    name: sonataflow-platform
+    namespace: test-ns
diff --git a/test/testdata/platform/services/dev/cluster-wide-ephemeral/02-sonataflow_platform.yaml b/test/testdata/platform/services/dev/cluster-wide-ephemeral/02-sonataflow_platform.yaml
new file mode 100644
index 00000000..c7048fff
--- /dev/null
+++ b/test/testdata/platform/services/dev/cluster-wide-ephemeral/02-sonataflow_platform.yaml
@@ -0,0 +1,32 @@
+# 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.
+
+apiVersion: sonataflow.org/v1alpha08
+kind: SonataFlowPlatform
+metadata:
+  name: sonataflow-platform
+spec:
+  build:
+    template:
+      buildArgs:
+      - name: QUARKUS_EXTENSION
+        value: org.kie.kogito:kogito-addons-quarkus-jobs-knative-eventing:999-SNAPSHOT
+    config:
+      strategyOptions:
+        KanikoBuildCacheEnabled: "true"
+  services:
+    dataIndex:
+      enabled: true
+    jobService:
+      enabled: true
diff --git a/test/testdata/platform/services/dev/cluster-wide-ephemeral/kustomization.yaml b/test/testdata/platform/services/dev/cluster-wide-ephemeral/kustomization.yaml
new file mode 100644
index 00000000..b6e60d37
--- /dev/null
+++ b/test/testdata/platform/services/dev/cluster-wide-ephemeral/kustomization.yaml
@@ -0,0 +1,17 @@
+# 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.
+
+resources:
+- 01-sonataflow_clusterplatform.yaml
+- 02-sonataflow_platform.yaml
diff --git a/test/testdata/platform/services/dev/ephemeral-data-index/02-sonataflow_platform.yaml b/test/testdata/platform/services/dev/ephemeral-data-index/02-sonataflow_platform.yaml
new file mode 100644
index 00000000..9c09a82d
--- /dev/null
+++ b/test/testdata/platform/services/dev/ephemeral-data-index/02-sonataflow_platform.yaml
@@ -0,0 +1,30 @@
+# 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.
+
+apiVersion: sonataflow.org/v1alpha08
+kind: SonataFlowPlatform
+metadata:
+  name: sonataflow-platform
+spec:
+  build:
+    template:
+      buildArgs:
+      - name: QUARKUS_EXTENSION
+        value: org.kie.kogito:kogito-addons-quarkus-jobs-knative-eventing:999-SNAPSHOT
+    config:
+      strategyOptions:
+        KanikoBuildCacheEnabled: "true"
+  services:
+    dataIndex:
+      enabled: false
diff --git a/test/testdata/platform/services/dev/ephemeral-data-index/kustomization.yaml b/test/testdata/platform/services/dev/ephemeral-data-index/kustomization.yaml
new file mode 100644
index 00000000..5441bfce
--- /dev/null
+++ b/test/testdata/platform/services/dev/ephemeral-data-index/kustomization.yaml
@@ -0,0 +1,20 @@
+# 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.
+
+resources:
+- 02-sonataflow_platform.yaml
+
+sortOptions:
+  order: fifo
+
diff --git a/test/testdata/platform/services/dev/ephemeral-data-index/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml b/test/testdata/platform/services/dev/ephemeral-data-index/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml
new file mode 100644
index 00000000..8bc8a77d
--- /dev/null
+++ b/test/testdata/platform/services/dev/ephemeral-data-index/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml
@@ -0,0 +1,81 @@
+# 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.
+
+apiVersion: sonataflow.org/v1alpha08
+kind: SonataFlow
+metadata:
+  name: callbackstatetimeouts
+  annotations:
+    sonataflow.org/description: Callback State Timeouts Example k8s
+    sonataflow.org/version: 0.0.1
+    sonataflow.org/profile: dev
+spec:
+  flow:
+    start: PrintStartMessage
+    events:
+      - name: callbackEvent
+        source: ''
+        type: callback_event_type
+    functions:
+      - name: systemOut
+        type: custom
+        operation: sysout
+    states:
+      - name: PrintStartMessage
+        type: operation
+        actions:
+          - name: printSystemOut
+            functionRef:
+              refName: systemOut
+              arguments:
+                message: "${\"callback-state-timeouts: \" + $WORKFLOW.instanceId + \" has started.\"}"
+        transition: CallbackState
+      - name: CallbackState
+        type: callback
+        action:
+          name: callbackAction
+          functionRef:
+            refName: systemOut
+            arguments:
+              message: "${\"callback-state-timeouts: \" + $WORKFLOW.instanceId + \" has executed the callbackFunction.\"}"
+        eventRef: callbackEvent
+        transition: CheckEventArrival
+        timeouts:
+          eventTimeout: PT30S
+      - name: CheckEventArrival
+        type: switch
+        dataConditions:
+          - condition: "${ .eventData != null }"
+            transition: EventArrived
+        defaultCondition:
+          transition: EventNotArrived
+      - name: EventArrived
+        type: inject
+        data:
+          exitMessage: "The callback event has arrived."
+        transition: PrintExitMessage
+      - name: EventNotArrived
+        type: inject
+        data:
+          exitMessage: "The callback event has not arrived, and the timeout has overdue."
+        transition: PrintExitMessage
+      - name: PrintExitMessage
+        type: operation
+        actions:
+          - name: printSystemOut
+            functionRef:
+              refName: systemOut
+              arguments:
+                message: "${\"callback-state-timeouts: \" + $WORKFLOW.instanceId + \" has finalized. \" + .exitMessage + \" eventData: \" + .eventData}"
+        end: true
diff --git a/test/testdata/platform/services/dev/ephemeral-job-service/02-sonataflow_platform.yaml b/test/testdata/platform/services/dev/ephemeral-job-service/02-sonataflow_platform.yaml
new file mode 100644
index 00000000..9e0bd3ad
--- /dev/null
+++ b/test/testdata/platform/services/dev/ephemeral-job-service/02-sonataflow_platform.yaml
@@ -0,0 +1,30 @@
+# 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.
+
+apiVersion: sonataflow.org/v1alpha08
+kind: SonataFlowPlatform
+metadata:
+  name: sonataflow-platform
+spec:
+  build:
+    template:
+      buildArgs:
+      - name: QUARKUS_EXTENSION
+        value: org.kie.kogito:kogito-addons-quarkus-jobs-knative-eventing:999-SNAPSHOT
+    config:
+      strategyOptions:
+        KanikoBuildCacheEnabled: "true"
+  services:
+    jobService:
+      enabled: false
diff --git a/test/testdata/platform/services/dev/ephemeral-job-service/kustomization.yaml b/test/testdata/platform/services/dev/ephemeral-job-service/kustomization.yaml
new file mode 100644
index 00000000..5441bfce
--- /dev/null
+++ b/test/testdata/platform/services/dev/ephemeral-job-service/kustomization.yaml
@@ -0,0 +1,20 @@
+# 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.
+
+resources:
+- 02-sonataflow_platform.yaml
+
+sortOptions:
+  order: fifo
+
diff --git a/test/testdata/platform/services/dev/ephemeral-job-service/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml b/test/testdata/platform/services/dev/ephemeral-job-service/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml
new file mode 100644
index 00000000..8bc8a77d
--- /dev/null
+++ b/test/testdata/platform/services/dev/ephemeral-job-service/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml
@@ -0,0 +1,81 @@
+# 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.
+
+apiVersion: sonataflow.org/v1alpha08
+kind: SonataFlow
+metadata:
+  name: callbackstatetimeouts
+  annotations:
+    sonataflow.org/description: Callback State Timeouts Example k8s
+    sonataflow.org/version: 0.0.1
+    sonataflow.org/profile: dev
+spec:
+  flow:
+    start: PrintStartMessage
+    events:
+      - name: callbackEvent
+        source: ''
+        type: callback_event_type
+    functions:
+      - name: systemOut
+        type: custom
+        operation: sysout
+    states:
+      - name: PrintStartMessage
+        type: operation
+        actions:
+          - name: printSystemOut
+            functionRef:
+              refName: systemOut
+              arguments:
+                message: "${\"callback-state-timeouts: \" + $WORKFLOW.instanceId + \" has started.\"}"
+        transition: CallbackState
+      - name: CallbackState
+        type: callback
+        action:
+          name: callbackAction
+          functionRef:
+            refName: systemOut
+            arguments:
+              message: "${\"callback-state-timeouts: \" + $WORKFLOW.instanceId + \" has executed the callbackFunction.\"}"
+        eventRef: callbackEvent
+        transition: CheckEventArrival
+        timeouts:
+          eventTimeout: PT30S
+      - name: CheckEventArrival
+        type: switch
+        dataConditions:
+          - condition: "${ .eventData != null }"
+            transition: EventArrived
+        defaultCondition:
+          transition: EventNotArrived
+      - name: EventArrived
+        type: inject
+        data:
+          exitMessage: "The callback event has arrived."
+        transition: PrintExitMessage
+      - name: EventNotArrived
+        type: inject
+        data:
+          exitMessage: "The callback event has not arrived, and the timeout has overdue."
+        transition: PrintExitMessage
+      - name: PrintExitMessage
+        type: operation
+        actions:
+          - name: printSystemOut
+            functionRef:
+              refName: systemOut
+              arguments:
+                message: "${\"callback-state-timeouts: \" + $WORKFLOW.instanceId + \" has finalized. \" + .exitMessage + \" eventData: \" + .eventData}"
+        end: true
diff --git a/test/yaml.go b/test/yaml.go
index 80aed8f5..5638e53a 100644
--- a/test/yaml.go
+++ b/test/yaml.go
@@ -263,6 +263,10 @@ func GetSonataFlowE2EPlatformServicesDirectory() string {
 	return filepath.Join(getTestDataDir(), "platform", "services")
 }
 
+func GetSonataFlowE2EPlatformNoServicesDirectory() string {
+	return filepath.Join(getTestDataDir(), "platform", "noservices")
+}
+
 func GetSonataFlowE2EPlatformPersistenceSampleDataDirectory(subdir string) string {
 	return filepath.Join(getTestDataDir(), "platform", "persistence", subdir)
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org