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 4f505a71 Fix #385 - Introduce Knative deployments for workflows (#447)
4f505a71 is described below
commit 4f505a71bf2eb4844587a2e75489a8ad35fcae1e
Author: Ricardo Zanini <[email protected]>
AuthorDate: Wed May 8 10:59:02 2024 -0300
Fix #385 - Introduce Knative deployments for workflows (#447)
---
api/metadata/annotations.go | 28 ++
api/metadata/annotations_test.go | 43 ++
.../{sonataflow_types.go => podtemplate_types.go} | 264 +---------
api/v1alpha08/sonataflow_types.go | 540 +--------------------
api/v1alpha08/zz_generated.deepcopy.go | 22 +
.../sonataflow-operator.clusterserviceversion.yaml | 19 +
bundle/manifests/sonataflow.org_sonataflows.yaml | 9 +
config/crd/bases/sonataflow.org_sonataflows.yaml | 9 +
.../sonataflow-operator.clusterserviceversion.yaml | 3 +
config/rbac/builder_role.yaml | 30 --
config/rbac/knative_role.yaml | 52 ++
config/rbac/knative_role_binding.yaml | 13 +
config/rbac/kustomization.yaml | 2 +
controllers/platform/k8s.go | 4 +-
...{deployment.go => deployment_status_manager.go} | 36 +-
.../common/{knative.go => knative_eventing.go} | 0
controllers/profiles/common/mutate_visitors.go | 50 ++
controllers/profiles/common/object_creators.go | 42 +-
.../profiles/common/object_creators_test.go | 20 +-
.../profiles/common/persistence/postgresql.go | 15 +-
controllers/profiles/dev/object_creators_dev.go | 3 +-
controllers/profiles/factory/factory.go | 23 +-
controllers/profiles/gitops/profile_gitops_test.go | 2 +-
controllers/profiles/preview/deployment_handler.go | 104 ++--
.../profiles/preview/deployment_handler_test.go | 42 +-
.../profiles/preview/object_creators_preview.go | 35 +-
controllers/profiles/preview/profile_preview.go | 27 +-
.../profiles/preview/profile_preview_test.go | 1 +
controllers/profiles/preview/states_preview.go | 2 +-
controllers/sonataflow_controller.go | 15 +
hack/local/run-operator.sh | 3 +
main.go | 2 +
operator.yaml | 44 ++
test/kubernetes_cli.go | 8 +
test/yaml.go | 4 +-
testbdd/go.mod | 4 +
testbdd/go.sum | 4 +
utils/common.go | 6 +-
workflowproj/workflowproj.go | 6 +-
39 files changed, 625 insertions(+), 911 deletions(-)
diff --git a/api/metadata/annotations.go b/api/metadata/annotations.go
index a0980ab9..a8f56091 100644
--- a/api/metadata/annotations.go
+++ b/api/metadata/annotations.go
@@ -73,3 +73,31 @@ const (
// Ideally used in production use cases
GitOpsProfile ProfileType = "gitops"
)
+
+const (
+ DefaultProfile = PreviewProfile
+)
+
+// deprecated prod profile is deprecate and not supported, use preview profile
+var supportedProfiles = map[ProfileType]ProfileType{DevProfile: DevProfile,
PreviewProfile: PreviewProfile, GitOpsProfile: GitOpsProfile}
+
+func GetProfileOrDefault(annotation map[string]string) ProfileType {
+ if annotation == nil {
+ return DefaultProfile
+ }
+ if profile, ok := supportedProfiles[ProfileType(annotation[Profile])];
!ok {
+ return DefaultProfile
+ } else {
+ return profile
+ }
+}
+
+func IsDevProfile(annotation map[string]string) bool {
+ if annotation == nil {
+ return false
+ }
+ if len(annotation[Profile]) == 0 {
+ return false
+ }
+ return ProfileType(annotation[Profile]) == DevProfile
+}
diff --git a/api/metadata/annotations_test.go b/api/metadata/annotations_test.go
new file mode 100644
index 00000000..b0437bb3
--- /dev/null
+++ b/api/metadata/annotations_test.go
@@ -0,0 +1,43 @@
+// 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 metadata
+
+import (
+ "testing"
+)
+
+func TestGetProfile(t *testing.T) {
+ type args struct {
+ annotation map[string]string
+ }
+ tests := []struct {
+ name string
+ args args
+ want ProfileType
+ }{
+ {"Empty Annotations", args{annotation: nil}, DefaultProfile},
+ {"Non-existent Profile", args{annotation:
map[string]string{Profile: "IDontExist"}}, DefaultProfile},
+ {"Regular Annotation", args{annotation:
map[string]string{Profile: GitOpsProfile.String()}}, GitOpsProfile},
+ {"Deprecated Annotation", args{annotation:
map[string]string{Profile: ProdProfile.String()}}, DefaultProfile},
+ {"Dev Annotation", args{annotation: map[string]string{Profile:
DevProfile.String()}}, DevProfile},
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := GetProfileOrDefault(tt.args.annotation); got
!= tt.want {
+ t.Errorf("GetProfileOrDefault() = %v, want %v",
got, tt.want)
+ }
+ })
+ }
+}
diff --git a/api/v1alpha08/sonataflow_types.go
b/api/v1alpha08/podtemplate_types.go
similarity index 72%
copy from api/v1alpha08/sonataflow_types.go
copy to api/v1alpha08/podtemplate_types.go
index 3237fc1f..3811a1bb 100644
--- a/api/v1alpha08/sonataflow_types.go
+++ b/api/v1alpha08/podtemplate_types.go
@@ -1,35 +1,20 @@
-/*
- * 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.
- */
+// 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
-import (
- cncfmodel "github.com/serverlessworkflow/sdk-go/v2/model"
- corev1 "k8s.io/api/core/v1"
- metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- "knative.dev/pkg/apis"
- duckv1 "knative.dev/pkg/apis/duck/v1"
-
- "github.com/apache/incubator-kie-kogito-serverless-operator/api"
-)
-
-const DefaultContainerName = "workflow"
+import corev1 "k8s.io/api/core/v1"
// ContainerSpec is the container for the internal deployments based on the
default Kubernetes Container API
type ContainerSpec struct {
@@ -558,224 +543,3 @@ type PodTemplateSpec struct {
// +optional
Replicas *int32 `json:"replicas,omitempty"`
}
-
-// Flow describes the contents of the Workflow definition following the CNCF
Serverless Workflow Specification.
-// The attributes not part of the flow are defined by the Custom Resource
metadata information, as follows:
-//
-// - Id, name, and key are replaced by the Custom Resource's name. Must follow
the Kubernetes naming patterns (RFC1123).
-//
-// - Description can be added in the CR's annotation field
sonataflow.org/description
-//
-// - Version is also defined in the CR's annotation, field
sonataflow.org/version
-//
-// - SpecVersion is in the CR's apiVersion, for example v1alpha08 means that
it follows the specification version 0.8.
-type Flow struct {
- // Workflow start definition.
- // +kubebuilder:validation:Schemaless
- // +kubebuilder:pruning:PreserveUnknownFields
- // +optional
- Start *cncfmodel.Start `json:"start,omitempty"`
- // Annotations List of helpful terms describing the workflows intended
purpose, subject areas, or other important
- // qualities.
- // +optional
- Annotations []string `json:"annotations,omitempty"`
- // DataInputSchema URI of the JSON Schema used to validate the workflow
data input
- // +optional
- DataInputSchema *cncfmodel.DataInputSchema
`json:"dataInputSchema,omitempty"`
- // Secrets allow you to access sensitive information, such as
passwords, OAuth tokens, ssh keys, etc,
- // inside your Workflow Expressions.
- // +optional
- Secrets cncfmodel.Secrets `json:"secrets,omitempty"`
- // Constants Workflow constants are used to define static, and
immutable, data which is available to
- // Workflow Expressions.
- // +optional
- Constants *cncfmodel.Constants `json:"constants,omitempty"`
- // Defines the workflow default timeout settings.
- // +optional
- Timeouts *cncfmodel.Timeouts `json:"timeouts,omitempty"`
- // Defines checked errors that can be explicitly handled during
workflow execution.
- // +optional
- Errors cncfmodel.Errors `json:"errors,omitempty"`
- // If "true", workflow instances is not terminated when there are no
active execution paths.
- // Instance can be terminated with "terminate end definition" or
reaching defined "workflowExecTimeout"
- // +optional
- KeepActive bool `json:"keepActive,omitempty"`
- // Metadata custom information shared with the runtime.
- // +kubebuilder:validation:Schemaless
- // +kubebuilder:pruning:PreserveUnknownFields
- // +optional
- Metadata cncfmodel.Metadata `json:"metadata,omitempty"`
- // AutoRetries If set to true, actions should automatically be retried
on unchecked errors. Default is false
- // +optional
- AutoRetries bool `json:"autoRetries,omitempty"`
- // Auth definitions can be used to define authentication information
that should be applied to resources defined
- // in the operation property of function definitions. It is not used as
authentication information for the
- // function invocation, but just to access the resource containing the
function invocation information.
- // +kubebuilder:validation:Schemaless
- // +kubebuilder:pruning:PreserveUnknownFields
- // +optional
- Auth cncfmodel.Auths `json:"auth,omitempty" validate:"omitempty"`
- // +kubebuilder:validation:MinItems=1
- // +kubebuilder:pruning:PreserveUnknownFields
- States []cncfmodel.State `json:"states" validate:"required,min=1,dive"`
- // +optional
- Events cncfmodel.Events `json:"events,omitempty"`
- // +optional
- Functions cncfmodel.Functions `json:"functions,omitempty"`
- // +optional
- Retries cncfmodel.Retries `json:"retries,omitempty" validate:"dive"`
-}
-
-// WorkflowResources collection of local objects holding workflow resources,
such as OpenAPI files
-// that will be mounted in the workflow application.
-type WorkflowResources struct {
- ConfigMaps []ConfigMapWorkflowResource `json:"configMaps,omitempty"`
-}
-
-// ConfigMapWorkflowResource ConfigMap local reference holding one or more
workflow resources, such as OpenAPI files
-// that will be mounted in the workflow application.
-type ConfigMapWorkflowResource struct {
- // ConfigMap the given configMap name in the same workflow context to
find the resource
- // +kubebuilder:validation:Required
- ConfigMap corev1.LocalObjectReference `json:"configMap"`
- // WorkflowPath path relative to the workflow application root file
system within the pod (/<application path>/src/main/resources).
- // Starting trailing slashes will be removed.
- WorkflowPath string `json:"workflowPath,omitempty"`
-}
-
-// SonataFlowSpec defines the desired state of SonataFlow
-// +k8s:openapi-gen=true
-type SonataFlowSpec struct {
- // Flow the workflow definition.
- // +kubebuilder:validation:Required
-
//+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="flow"
- Flow Flow `json:"flow"`
- // Resources workflow resources that are linked to this workflow
definition.
- // For example, a collection of OpenAPI specification files.
-
//+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="resources"
- Resources WorkflowResources `json:"resources,omitempty"`
- // PodTemplate describes the deployment details of this SonataFlow
instance.
-
//+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="podTemplate"
- PodTemplate PodTemplateSpec `json:"podTemplate,omitempty"`
- // Persistence defines the database persistence configuration for the
workflow
- Persistence *PersistenceOptionsSpec `json:"persistence,omitempty"`
- // Sink describes the sinkBinding details of this SonataFlow instance.
-
//+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="sink"
- Sink *duckv1.Destination `json:"sink,omitempty"`
-}
-
-// SonataFlowStatus defines the observed state of SonataFlow
-// +k8s:openapi-gen=true
-type SonataFlowStatus struct {
- api.Status `json:",inline"`
- // Address is used as a part of Addressable interface
(status.address.url) for knative
- // +optional
-
//+operator-sdk:csv:customresourcedefinitions:type=status,displayName="address"
- Address duckv1.Addressable `json:"address,omitempty"`
- // keeps track of how many failure recovers a given workflow had so far
-
//+operator-sdk:csv:customresourcedefinitions:type=status,displayName="recoverFailureAttempts"
- RecoverFailureAttempts int `json:"recoverFailureAttempts,omitempty"`
-
//+operator-sdk:csv:customresourcedefinitions:type=status,displayName="lastTimeRecoverAttempt"
- LastTimeRecoverAttempt metav1.Time
`json:"lastTimeRecoverAttempt,omitempty"`
- // Endpoint is an externally accessible URL of the workflow
-
//+operator-sdk:csv:customresourcedefinitions:type=status,displayName="endpoint"
- Endpoint *apis.URL `json:"endpoint,omitempty"`
- // Services displays which platform services are being used by this
workflow
-
//+operator-sdk:csv:customresourcedefinitions:type=status,displayName="services"
- Services *PlatformServicesStatus `json:"services,omitempty"`
-}
-
-func (s *SonataFlowStatus) GetTopLevelConditionType() api.ConditionType {
- return api.RunningConditionType
-}
-
-func (s *SonataFlowStatus) IsReady() bool {
- return s.GetTopLevelCondition().IsTrue()
-}
-
-func (s *SonataFlowStatus) GetTopLevelCondition() *api.Condition {
- return s.GetCondition(s.GetTopLevelConditionType())
-}
-
-func (s *SonataFlowStatus) Manager() api.ConditionsManager {
- return api.NewConditionManager(s, api.RunningConditionType,
api.BuiltConditionType)
-}
-
-func (s *SonataFlowStatus) IsWaitingForPlatform() bool {
- cond := s.GetCondition(api.BuiltConditionType)
- return cond.IsFalse() && cond.Reason == api.WaitingForPlatformReason
-}
-
-func (s *SonataFlowStatus) IsWaitingForDeployment() bool {
- cond := s.GetCondition(api.RunningConditionType)
- return cond.IsFalse() && cond.Reason == api.WaitingForDeploymentReason
-}
-
-// IsChildObjectsProblem indicates a problem during objects creation during
reconciliation
-// For example, a deployment that couldn't be created or a referenced object
not found.
-func (s *SonataFlowStatus) IsChildObjectsProblem() bool {
- cond := s.GetCondition(api.RunningConditionType)
- // You can add more conditions that meet this conditional here
- return cond.IsFalse() && (cond.Reason ==
api.ExternalResourcesNotFoundReason)
-}
-
-func (s *SonataFlowStatus) IsWaitingForBuild() bool {
- cond := s.GetCondition(api.RunningConditionType)
- return cond.IsFalse() && cond.Reason == api.WaitingForBuildReason
-}
-
-func (s *SonataFlowStatus) IsBuildRunningOrUnknown() bool {
- cond := s.GetCondition(api.BuiltConditionType)
- return cond.IsUnknown() || (cond.IsFalse() && cond.Reason ==
api.BuildIsRunningReason)
-}
-
-func (s *SonataFlowStatus) IsBuildRunning() bool {
- cond := s.GetCondition(api.BuiltConditionType)
- return cond.IsFalse() && cond.Reason == api.BuildIsRunningReason
-}
-
-func (s *SonataFlowStatus) IsBuildFailed() bool {
- cond := s.GetCondition(api.BuiltConditionType)
- return cond.IsFalse() && cond.Reason == api.BuildFailedReason
-}
-
-// SonataFlow is the descriptor representation for a workflow application
based on the CNCF Serverless Workflow specification.
-// +kubebuilder:object:root=true
-// +kubebuilder:object:generate=true
-// +kubebuilder:subresource:status
-// +kubebuilder:resource:shortName={"sf", "workflow", "workflows"}
-// +k8s:openapi-gen=true
-//
+kubebuilder:printcolumn:name="Profile",type=string,JSONPath=`.metadata.annotations.sonataflow\.org\/profile`
-//
+kubebuilder:printcolumn:name="Version",type=string,JSONPath=`.metadata.annotations.sonataflow\.org\/version`
-// +kubebuilder:printcolumn:name="URL",type=string,JSONPath=`.status.endpoint`
-//
+kubebuilder:printcolumn:name="Ready",type=string,JSONPath=`.status.conditions[?(@.type=='Running')].status`
-//
+kubebuilder:printcolumn:name="Reason",type=string,JSONPath=`.status.conditions[?(@.type=='Running')].reason`
-//
+operator-sdk:csv:customresourcedefinitions:resources={{SonataFlowBuild,sonataflow.org/v1alpha08,"A
SonataFlow Build"}}
-//
+operator-sdk:csv:customresourcedefinitions:resources={{Deployment,apps/v1,"A
Deployment for the Flow"}}
-// +operator-sdk:csv:customresourcedefinitions:resources={{Service,v1,"A
Service for the Flow"}}
-//
+operator-sdk:csv:customresourcedefinitions:resources={{Route,route.openshift.io/v1,"An
OpenShift Route for the Flow"}}
-// +operator-sdk:csv:customresourcedefinitions:resources={{ConfigMap,v1,"The
ConfigMaps with Flow definition and additional configuration files"}}
-type SonataFlow struct {
- metav1.TypeMeta `json:",inline"`
- metav1.ObjectMeta `json:"metadata,omitempty"`
-
- Spec SonataFlowSpec `json:"spec,omitempty"`
- Status SonataFlowStatus `json:"status,omitempty"`
-}
-
-func (s *SonataFlow) HasContainerSpecImage() bool {
- return len(s.Spec.PodTemplate.Container.Image) > 0
-}
-
-// SonataFlowList contains a list of SonataFlow
-// +kubebuilder:object:root=true
-// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
-type SonataFlowList struct {
- metav1.TypeMeta `json:",inline"`
- metav1.ListMeta `json:"metadata,omitempty"`
- Items []SonataFlow `json:"items"`
-}
-
-func init() {
- SchemeBuilder.Register(&SonataFlow{}, &SonataFlowList{})
-}
diff --git a/api/v1alpha08/sonataflow_types.go
b/api/v1alpha08/sonataflow_types.go
index 3237fc1f..7763dc23 100644
--- a/api/v1alpha08/sonataflow_types.go
+++ b/api/v1alpha08/sonataflow_types.go
@@ -31,524 +31,19 @@ import (
const DefaultContainerName = "workflow"
-// ContainerSpec is the container for the internal deployments based on the
default Kubernetes Container API
-type ContainerSpec struct {
- // Container image name.
- // More info: https://kubernetes.io/docs/concepts/containers/images
- // This field is optional to allow higher level config management to
default or override
- // container images in workload controllers like Deployments and
StatefulSets.
- // +optional
- Image string `json:"image,omitempty" protobuf:"bytes,2,opt,name=image"`
- // Entrypoint array. Not executed within a shell.
- // The container image's ENTRYPOINT is used if this is not provided.
- // Variable references $(VAR_NAME) are expanded using the container's
environment. If a variable
- // cannot be resolved, the reference in the input string will be
unchanged. Double $$ are reduced
- // to a single $, which allows for escaping the $(VAR_NAME) syntax:
i.e. "$$(VAR_NAME)" will
- // produce the string literal "$(VAR_NAME)". Escaped references will
never be expanded, regardless
- // of whether the variable exists or not. Cannot be updated.
- // More info:
https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell
- // +optional
- Command []string `json:"command,omitempty"
protobuf:"bytes,3,rep,name=command"`
- // Arguments to the entrypoint.
- // The container image's CMD is used if this is not provided.
- // Variable references $(VAR_NAME) are expanded using the container's
environment. If a variable
- // cannot be resolved, the reference in the input string will be
unchanged. Double $$ are reduced
- // to a single $, which allows for escaping the $(VAR_NAME) syntax:
i.e. "$$(VAR_NAME)" will
- // produce the string literal "$(VAR_NAME)". Escaped references will
never be expanded, regardless
- // of whether the variable exists or not. Cannot be updated.
- // More info:
https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell
- // +optional
- Args []string `json:"args,omitempty" protobuf:"bytes,4,rep,name=args"`
- // List of ports to expose from the container. Not specifying a port
here
- // DOES NOT prevent that port from being exposed. Any port which is
- // listening on the default "0.0.0.0" address inside a container will be
- // accessible from the network.
- // Modifying this array with strategic merge patch may corrupt the data.
- // For more information See
https://github.com/kubernetes/kubernetes/issues/108255.
- // Cannot be updated.
- // +optional
- // +patchMergeKey=containerPort
- // +patchStrategy=merge
- // +listType=map
- // +listMapKey=containerPort
- // +listMapKey=protocol
- Ports []corev1.ContainerPort `json:"ports,omitempty"
patchStrategy:"merge" patchMergeKey:"containerPort"
protobuf:"bytes,6,rep,name=ports"`
- // List of sources to populate environment variables in the container.
- // The keys defined within a source must be a C_IDENTIFIER. All invalid
keys
- // will be reported as an event when the container is starting. When a
key exists in multiple
- // sources, the value associated with the last source will take
precedence.
- // Values defined by an Env with a duplicate key will take precedence.
- // Cannot be updated.
- // +optional
- EnvFrom []corev1.EnvFromSource `json:"envFrom,omitempty"
protobuf:"bytes,19,rep,name=envFrom"`
- // List of environment variables to set in the container.
- // Cannot be updated.
- // +optional
- // +patchMergeKey=name
- // +patchStrategy=merge
- Env []corev1.EnvVar `json:"env,omitempty" patchStrategy:"merge"
patchMergeKey:"name" protobuf:"bytes,7,rep,name=env"`
- // Compute Resources required by this container.
- // Cannot be updated.
- // More info:
https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
- // +optional
- Resources corev1.ResourceRequirements `json:"resources,omitempty"
protobuf:"bytes,8,opt,name=resources"`
- // Resources resize policy for the container.
- // +featureGate=InPlacePodVerticalScaling
- // +optional
- // +listType=atomic
- ResizePolicy []corev1.ContainerResizePolicy
`json:"resizePolicy,omitempty" protobuf:"bytes,23,rep,name=resizePolicy"`
- // Pod volumes to mount into the container's filesystem.
- // Cannot be updated.
- // +optional
- // +patchMergeKey=mountPath
- // +patchStrategy=merge
- VolumeMounts []corev1.VolumeMount `json:"volumeMounts,omitempty"
patchStrategy:"merge" patchMergeKey:"mountPath"
protobuf:"bytes,9,rep,name=volumeMounts"`
- // volumeDevices is the list of block devices to be used by the
container.
- // +patchMergeKey=devicePath
- // +patchStrategy=merge
- // +optional
- VolumeDevices []corev1.VolumeDevice `json:"volumeDevices,omitempty"
patchStrategy:"merge" patchMergeKey:"devicePath"
protobuf:"bytes,21,rep,name=volumeDevices"`
- // Periodic probe of container liveness.
- // Container will be restarted if the probe fails.
- // Cannot be updated.
- // More info:
https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes
- // +optional
- LivenessProbe *corev1.Probe `json:"livenessProbe,omitempty"
protobuf:"bytes,10,opt,name=livenessProbe"`
- // Periodic probe of container service readiness.
- // Container will be removed from service endpoints if the probe fails.
- // Cannot be updated.
- // More info:
https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes
- // +optional
- ReadinessProbe *corev1.Probe `json:"readinessProbe,omitempty"
protobuf:"bytes,11,opt,name=readinessProbe"`
- // StartupProbe indicates that the Pod has successfully initialized.
- // If specified, no other probes are executed until this completes
successfully.
- // If this probe fails, the Pod will be restarted, just as if the
livenessProbe failed.
- // This can be used to provide different probe parameters at the
beginning of a Pod's lifecycle,
- // when it might take a long time to load data or warm a cache, than
during steady-state operation.
- // This cannot be updated.
- // More info:
https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes
- // +optional
- StartupProbe *corev1.Probe `json:"startupProbe,omitempty"
protobuf:"bytes,22,opt,name=startupProbe"`
- // Actions that the management system should take in response to
container lifecycle events.
- // Cannot be updated.
- // +optional
- Lifecycle *corev1.Lifecycle `json:"lifecycle,omitempty"
protobuf:"bytes,12,opt,name=lifecycle"`
- // Optional: Path at which the file to which the container's
termination message
- // will be written is mounted into the container's filesystem.
- // Message written is intended to be brief final status, such as an
assertion failure message.
- // Will be truncated by the node if greater than 4096 bytes. The total
message length across
- // all containers will be limited to 12kb.
- // Defaults to /dev/termination-log.
- // Cannot be updated.
- // +optional
- TerminationMessagePath string `json:"terminationMessagePath,omitempty"
protobuf:"bytes,13,opt,name=terminationMessagePath"`
- // Indicate how the termination message should be populated. File will
use the contents of
- // terminationMessagePath to populate the container status message on
both success and failure.
- // FallbackToLogsOnError will use the last chunk of container log
output if the termination
- // message file is empty and the container exited with an error.
- // The log output is limited to 2048 bytes or 80 lines, whichever is
smaller.
- // Defaults to File.
- // Cannot be updated.
- // +optional
- TerminationMessagePolicy corev1.TerminationMessagePolicy
`json:"terminationMessagePolicy,omitempty"
protobuf:"bytes,20,opt,name=terminationMessagePolicy,casttype=TerminationMessagePolicy"`
- // Image pull policy.
- // One of Always, Never, IfNotPresent.
- // Defaults to Always if :latest tag is specified, or IfNotPresent
otherwise.
- // Cannot be updated.
- // More info:
https://kubernetes.io/docs/concepts/containers/images#updating-images
- // +optional
- ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"
protobuf:"bytes,14,opt,name=imagePullPolicy,casttype=PullPolicy"`
- // SecurityContext defines the security options the container should be
run with.
- // If set, the fields of SecurityContext override the equivalent fields
of PodSecurityContext.
- // More info:
https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
- // +optional
- SecurityContext *corev1.SecurityContext
`json:"securityContext,omitempty" protobuf:"bytes,15,opt,name=securityContext"`
-
- // Variables for interactive containers, these have very specialized
use-cases (e.g. debugging)
- // and shouldn't be used for general purpose containers.
-
- // Whether this container should allocate a buffer for stdin in the
container runtime. If this
- // is not set, reads from stdin in the container will always result in
EOF.
- // Default is false.
- // +optional
- Stdin bool `json:"stdin,omitempty" protobuf:"varint,16,opt,name=stdin"`
- // Whether the container runtime should close the stdin channel after
it has been opened by
- // a single attach. When stdin is true the stdin stream will remain
open across multiple attach
- // sessions. If stdinOnce is set to true, stdin is opened on container
start, is empty until the
- // first client attaches to stdin, and then remains open and accepts
data until the client disconnects,
- // at which time stdin is closed and remains closed until the container
is restarted. If this
- // flag is false, a container processes that reads from stdin will
never receive an EOF.
- // Default is false
- // +optional
- StdinOnce bool `json:"stdinOnce,omitempty"
protobuf:"varint,17,opt,name=stdinOnce"`
- // Whether this container should allocate a TTY for itself, also
requires 'stdin' to be true.
- // Default is false.
- // +optional
- TTY bool `json:"tty,omitempty" protobuf:"varint,18,opt,name=tty"`
-}
-
-// ToContainer converts to Kubernetes Container API.
-func (f *ContainerSpec) ToContainer() corev1.Container {
- return corev1.Container{
- Name: DefaultContainerName,
- Image: f.Image,
- Command: f.Command,
- Args: f.Args,
- Ports: f.Ports,
- EnvFrom: f.EnvFrom,
- Env: f.Env,
- Resources: f.Resources,
- ResizePolicy: f.ResizePolicy,
- VolumeMounts: f.VolumeMounts,
- VolumeDevices: f.VolumeDevices,
- LivenessProbe: f.LivenessProbe,
- ReadinessProbe: f.ReadinessProbe,
- StartupProbe: f.StartupProbe,
- Lifecycle: f.Lifecycle,
- TerminationMessagePath: f.TerminationMessagePath,
- TerminationMessagePolicy: f.TerminationMessagePolicy,
- ImagePullPolicy: f.ImagePullPolicy,
- SecurityContext: f.SecurityContext,
- Stdin: f.Stdin,
- StdinOnce: f.StdinOnce,
- TTY: f.TTY,
- }
-}
-
-// PodSpec describes the PodSpec for the internal deployments based on the
default Kubernetes PodSpec API
-type PodSpec struct {
- // List of volumes that can be mounted by containers belonging to the
pod.
- // More info: https://kubernetes.io/docs/concepts/storage/volumes
- // +optional
- // +patchMergeKey=name
- // +patchStrategy=merge,retainKeys
- Volumes []corev1.Volume `json:"volumes,omitempty"
patchStrategy:"merge,retainKeys" patchMergeKey:"name"
protobuf:"bytes,1,rep,name=volumes"`
- // List of initialization containers belonging to the pod.
- // Init containers are executed in order prior to containers being
started. If any
- // init container fails, the pod is considered to have failed and is
handled according
- // to its restartPolicy. The name for an init container or normal
container must be
- // unique among all containers.
- // Init containers may not have Lifecycle actions, Readiness probes,
Liveness probes, or Startup probes.
- // The resourceRequirements of an init container are taken into account
during scheduling
- // by finding the highest request/limit for each resource type, and
then using the max of
- // of that value or the sum of the normal containers. Limits are
applied to init containers
- // in a similar fashion.
- // Init containers cannot currently be added or removed.
- // Cannot be updated.
- // More info:
https://kubernetes.io/docs/concepts/workloads/pods/init-containers/
- // +patchMergeKey=name
- // +patchStrategy=merge
- InitContainers []corev1.Container `json:"initContainers,omitempty"
patchStrategy:"merge" patchMergeKey:"name"
protobuf:"bytes,20,rep,name=initContainers"`
- // List of containers belonging to the pod.
- // Containers cannot currently be added or removed.
- // There must be at least one container in a Pod.
- // Cannot be updated.
- // +optional
- // +patchMergeKey=name
- // +patchStrategy=merge
- Containers []corev1.Container `json:"containers,omitempty"
patchStrategy:"merge" patchMergeKey:"name"
protobuf:"bytes,2,rep,name=containers"`
- // Restart policy for all containers within the pod.
- // One of Always, OnFailure, Never. In some contexts, only a subset of
those values may be permitted.
- // Default to Always.
- // More info:
https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy
- // +optional
- RestartPolicy corev1.RestartPolicy `json:"restartPolicy,omitempty"
protobuf:"bytes,3,opt,name=restartPolicy,casttype=RestartPolicy"`
- // Optional duration in seconds the pod needs to terminate gracefully.
May be decreased in delete request.
- // Value must be non-negative integer. The value zero indicates stop
immediately via
- // the kill signal (no opportunity to shut down).
- // If this value is nil, the default grace period will be used instead.
- // The grace period is the duration in seconds after the processes
running in the pod are sent
- // a termination signal and the time when the processes are forcibly
halted with a kill signal.
- // Set this value longer than the expected cleanup time for your
process.
- // Defaults to 30 seconds.
- // +optional
- TerminationGracePeriodSeconds *int64
`json:"terminationGracePeriodSeconds,omitempty"
protobuf:"varint,4,opt,name=terminationGracePeriodSeconds"`
- // Optional duration in seconds the pod may be active on the node
relative to
- // StartTime before the system will actively try to mark it failed and
kill associated containers.
- // Value must be a positive integer.
- // +optional
- ActiveDeadlineSeconds *int64 `json:"activeDeadlineSeconds,omitempty"
protobuf:"varint,5,opt,name=activeDeadlineSeconds"`
- // Set DNS policy for the pod.
- // Defaults to "ClusterFirst".
- // Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst',
'Default' or 'None'.
- // DNS parameters given in DNSConfig will be merged with the policy
selected with DNSPolicy.
- // To have DNS options set along with hostNetwork, you have to specify
DNS policy
- // explicitly to 'ClusterFirstWithHostNet'.
- // +optional
- DNSPolicy corev1.DNSPolicy `json:"dnsPolicy,omitempty"
protobuf:"bytes,6,opt,name=dnsPolicy,casttype=DNSPolicy"`
- // NodeSelector is a selector which must be true for the pod to fit on
a node.
- // Selector which must match a node's labels for the pod to be
scheduled on that node.
- // More info:
https://kubernetes.io/docs/concepts/configuration/assign-pod-node/
- // +optional
- // +mapType=atomic
- NodeSelector map[string]string `json:"nodeSelector,omitempty"
protobuf:"bytes,7,rep,name=nodeSelector"`
-
- // ServiceAccountName is the name of the ServiceAccount to use to run
this pod.
- // More info:
https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
- // +optional
- ServiceAccountName string `json:"serviceAccountName,omitempty"
protobuf:"bytes,8,opt,name=serviceAccountName"`
- // AutomountServiceAccountToken indicates whether a service account
token should be automatically mounted.
- // +optional
- AutomountServiceAccountToken *bool
`json:"automountServiceAccountToken,omitempty"
protobuf:"varint,21,opt,name=automountServiceAccountToken"`
-
- // NodeName is a request to schedule this pod onto a specific node. If
it is non-empty,
- // the scheduler simply schedules this pod onto that node, assuming
that it fits resource
- // requirements.
- // +optional
- NodeName string `json:"nodeName,omitempty"
protobuf:"bytes,10,opt,name=nodeName"`
- // Host networking requested for this pod. Use the host's network
namespace.
- // If this option is set, the ports that will be used must be specified.
- // Default to false.
- // +k8s:conversion-gen=false
- // +optional
- HostNetwork bool `json:"hostNetwork,omitempty"
protobuf:"varint,11,opt,name=hostNetwork"`
- // Use the host's pid namespace.
- // Optional: Default to false.
- // +k8s:conversion-gen=false
- // +optional
- HostPID bool `json:"hostPID,omitempty"
protobuf:"varint,12,opt,name=hostPID"`
- // Use the host's ipc namespace.
- // Optional: Default to false.
- // +k8s:conversion-gen=false
- // +optional
- HostIPC bool `json:"hostIPC,omitempty"
protobuf:"varint,13,opt,name=hostIPC"`
- // Share a single process namespace between all of the containers in a
pod.
- // When this is set containers will be able to view and signal
processes from other containers
- // in the same pod, and the first process in each container will not be
assigned PID 1.
- // HostPID and ShareProcessNamespace cannot both be set.
- // Optional: Default to false.
- // +k8s:conversion-gen=false
- // +optional
- ShareProcessNamespace *bool `json:"shareProcessNamespace,omitempty"
protobuf:"varint,27,opt,name=shareProcessNamespace"`
- // SecurityContext holds pod-level security attributes and common
container settings.
- // Optional: Defaults to empty. See type description for default
values of each field.
- // +optional
- SecurityContext *corev1.PodSecurityContext
`json:"securityContext,omitempty" protobuf:"bytes,14,opt,name=securityContext"`
- // ImagePullSecrets is an optional list of references to secrets in the
same namespace to use for pulling any of the images used by this PodSpec.
- // If specified, these secrets will be passed to individual puller
implementations for them to use.
- // More info:
https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod
- // +optional
- // +patchMergeKey=name
- // +patchStrategy=merge
- ImagePullSecrets []corev1.LocalObjectReference
`json:"imagePullSecrets,omitempty" patchStrategy:"merge" patchMergeKey:"name"
protobuf:"bytes,15,rep,name=imagePullSecrets"`
- // Specifies the hostname of the Pod
- // If not specified, the pod's hostname will be set to a system-defined
value.
- // +optional
- Hostname string `json:"hostname,omitempty"
protobuf:"bytes,16,opt,name=hostname"`
- // If specified, the fully qualified Pod hostname will be
"<hostname>.<subdomain>.<pod namespace>.svc.<cluster domain>".
- // If not specified, the pod will not have a domainname at all.
- // +optional
- Subdomain string `json:"subdomain,omitempty"
protobuf:"bytes,17,opt,name=subdomain"`
- // If specified, the pod's scheduling constraints
- // +optional
- Affinity *corev1.Affinity `json:"affinity,omitempty"
protobuf:"bytes,18,opt,name=affinity"`
- // If specified, the pod will be dispatched by specified scheduler.
- // If not specified, the pod will be dispatched by default scheduler.
- // +optional
- SchedulerName string `json:"schedulerName,omitempty"
protobuf:"bytes,19,opt,name=schedulerName"`
- // If specified, the pod's tolerations.
- // +optional
- Tolerations []corev1.Toleration `json:"tolerations,omitempty"
protobuf:"bytes,22,opt,name=tolerations"`
- // HostAliases is an optional list of hosts and IPs that will be
injected into the pod's hosts
- // file if specified. This is only valid for non-hostNetwork pods.
- // +optional
- // +patchMergeKey=ip
- // +patchStrategy=merge
- HostAliases []corev1.HostAlias `json:"hostAliases,omitempty"
patchStrategy:"merge" patchMergeKey:"ip"
protobuf:"bytes,23,rep,name=hostAliases"`
- // If specified, indicates the pod's priority. "system-node-critical"
and
- // "system-cluster-critical" are two special keywords which indicate the
- // highest priorities with the former being the highest priority. Any
other
- // name must be defined by creating a PriorityClass object with that
name.
- // If not specified, the pod priority will be default or zero if there
is no
- // default.
- // +optional
- PriorityClassName string `json:"priorityClassName,omitempty"
protobuf:"bytes,24,opt,name=priorityClassName"`
- // The priority value. Various system components use this field to find
the
- // priority of the pod. When Priority Admission Controller is enabled,
it
- // prevents users from setting this field. The admission controller
populates
- // this field from PriorityClassName.
- // The higher the value, the higher the priority.
- // +optional
- Priority *int32 `json:"priority,omitempty"
protobuf:"bytes,25,opt,name=priority"`
- // Specifies the DNS parameters of a pod.
- // Parameters specified here will be merged to the generated DNS
- // configuration based on DNSPolicy.
- // +optional
- DNSConfig *corev1.PodDNSConfig `json:"dnsConfig,omitempty"
protobuf:"bytes,26,opt,name=dnsConfig"`
- // If specified, all readiness gates will be evaluated for pod
readiness.
- // A pod is ready when all its containers are ready AND
- // all conditions specified in the readiness gates have status equal to
"True"
- // More info:
https://git.k8s.io/enhancements/keps/sig-network/580-pod-readiness-gates
- // +optional
- ReadinessGates []corev1.PodReadinessGate
`json:"readinessGates,omitempty" protobuf:"bytes,28,opt,name=readinessGates"`
- // RuntimeClassName refers to a RuntimeClass object in the node.k8s.io
group, which should be used
- // to run this pod. If no RuntimeClass resource matches the named
class, the pod will not be run.
- // If unset or empty, the "legacy" RuntimeClass will be used, which is
an implicit class with an
- // empty definition that uses the default runtime handler.
- // More info:
https://git.k8s.io/enhancements/keps/sig-node/585-runtime-class
- // +optional
- RuntimeClassName *string `json:"runtimeClassName,omitempty"
protobuf:"bytes,29,opt,name=runtimeClassName"`
- // EnableServiceLinks indicates whether information about services
should be injected into pod's
- // environment variables, matching the syntax of Docker links.
- // Optional: Defaults to true.
- // +optional
- EnableServiceLinks *bool `json:"enableServiceLinks,omitempty"
protobuf:"varint,30,opt,name=enableServiceLinks"`
- // PreemptionPolicy is the Policy for preempting pods with lower
priority.
- // One of Never, PreemptLowerPriority.
- // Defaults to PreemptLowerPriority if unset.
- // +optional
- PreemptionPolicy *corev1.PreemptionPolicy
`json:"preemptionPolicy,omitempty"
protobuf:"bytes,31,opt,name=preemptionPolicy"`
- // Overhead represents the resource overhead associated with running a
pod for a given RuntimeClass.
- // This field will be autopopulated at admission time by the
RuntimeClass admission controller. If
- // the RuntimeClass admission controller is enabled, overhead must not
be set in Pod create requests.
- // The RuntimeClass admission controller will reject Pod create
requests which have the overhead already
- // set. If RuntimeClass is configured and selected in the PodSpec,
Overhead will be set to the value
- // defined in the corresponding RuntimeClass, otherwise it will remain
unset and treated as zero.
- // More info:
https://git.k8s.io/enhancements/keps/sig-node/688-pod-overhead/README.md
- // +optional
- Overhead corev1.ResourceList `json:"overhead,omitempty"
protobuf:"bytes,32,opt,name=overhead"`
- // TopologySpreadConstraints describes how a group of pods ought to
spread across topology
- // domains. Scheduler will schedule pods in a way which abides by the
constraints.
- // All topologySpreadConstraints are ANDed.
- // +optional
- // +patchMergeKey=topologyKey
- // +patchStrategy=merge
- // +listType=map
- // +listMapKey=topologyKey
- // +listMapKey=whenUnsatisfiable
- TopologySpreadConstraints []corev1.TopologySpreadConstraint
`json:"topologySpreadConstraints,omitempty" patchStrategy:"merge"
patchMergeKey:"topologyKey"
protobuf:"bytes,33,opt,name=topologySpreadConstraints"`
- // If true the pod's hostname will be configured as the pod's FQDN,
rather than the leaf name (the default).
- // In Linux containers, this means setting the FQDN in the hostname
field of the kernel (the nodename field of struct utsname).
- // In Windows containers, this means setting the registry value of
hostname for the registry key
HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters to
FQDN.
- // If a pod does not have FQDN, this has no effect.
- // Default to false.
- // +optional
- SetHostnameAsFQDN *bool `json:"setHostnameAsFQDN,omitempty"
protobuf:"varint,35,opt,name=setHostnameAsFQDN"`
- // Specifies the OS of the containers in the pod.
- // Some pod and container fields are restricted if this is set.
- //
- // If the OS field is set to linux, the following fields must be unset:
- // -securityContext.windowsOptions
- //
- // If the OS field is set to windows, following fields must be unset:
- // - spec.hostPID
- // - spec.hostIPC
- // - spec.hostUsers
- // - spec.securityContext.seLinuxOptions
- // - spec.securityContext.seccompProfile
- // - spec.securityContext.fsGroup
- // - spec.securityContext.fsGroupChangePolicy
- // - spec.securityContext.sysctls
- // - spec.shareProcessNamespace
- // - spec.securityContext.runAsUser
- // - spec.securityContext.runAsGroup
- // - spec.securityContext.supplementalGroups
- // - spec.containers[*].securityContext.seLinuxOptions
- // - spec.containers[*].securityContext.seccompProfile
- // - spec.containers[*].securityContext.capabilities
- // - spec.containers[*].securityContext.readOnlyRootFilesystem
- // - spec.containers[*].securityContext.privileged
- // - spec.containers[*].securityContext.allowPrivilegeEscalation
- // - spec.containers[*].securityContext.procMount
- // - spec.containers[*].securityContext.runAsUser
- // - spec.containers[*].securityContext.runAsGroup
- // +optional
- OS *corev1.PodOS `json:"os,omitempty" protobuf:"bytes,36,opt,name=os"`
-
- // Use the host's user namespace.
- // Optional: Default to true.
- // If set to true or not present, the pod will be run in the host user
namespace, useful
- // for when the pod needs a feature only available to the host user
namespace, such as
- // loading a kernel module with CAP_SYS_MODULE.
- // When set to false, a new userns is created for the pod. Setting
false is useful for
- // mitigating container breakout vulnerabilities even allowing users to
run their
- // containers as root without actually having root privileges on the
host.
- // This field is alpha-level and is only honored by servers that enable
the UserNamespacesSupport feature.
- // +k8s:conversion-gen=false
- // +optional
- HostUsers *bool `json:"hostUsers,omitempty"
protobuf:"bytes,37,opt,name=hostUsers"`
-
- // SchedulingGates is an opaque list of values that if specified will
block scheduling the pod.
- // If schedulingGates is not empty, the pod will stay in the
SchedulingGated state and the
- // scheduler will not attempt to schedule the pod.
- //
- // SchedulingGates can only be set at pod creation time, and be removed
only afterwards.
- //
- // This is a beta feature enabled by the PodSchedulingReadiness feature
gate.
- //
- // +patchMergeKey=name
- // +patchStrategy=merge
- // +listType=map
- // +listMapKey=name
- // +featureGate=PodSchedulingReadiness
- // +optional
- SchedulingGates []corev1.PodSchedulingGate
`json:"schedulingGates,omitempty" patchStrategy:"merge" patchMergeKey:"name"
protobuf:"bytes,38,opt,name=schedulingGates"`
- // ResourceClaims defines which ResourceClaims must be allocated
- // and reserved before the Pod is allowed to start. The resources
- // will be made available to those containers which consume them
- // by name.
- //
- // This is an alpha field and requires enabling the
- // DynamicResourceAllocation feature gate.
- //
- // This field is immutable.
- //
- // +patchMergeKey=name
- // +patchStrategy=merge,retainKeys
- // +listType=map
- // +listMapKey=name
- // +featureGate=DynamicResourceAllocation
- // +optional
- ResourceClaims []corev1.PodResourceClaim
`json:"resourceClaims,omitempty" patchStrategy:"merge,retainKeys"
patchMergeKey:"name" protobuf:"bytes,39,rep,name=resourceClaims"`
-}
-
-func (f *PodSpec) ToPodSpec() corev1.PodSpec {
- return corev1.PodSpec{
- Volumes: f.Volumes,
- InitContainers: f.InitContainers,
- Containers: f.Containers,
- RestartPolicy: f.RestartPolicy,
- TerminationGracePeriodSeconds: f.TerminationGracePeriodSeconds,
- ActiveDeadlineSeconds: f.ActiveDeadlineSeconds,
- DNSPolicy: f.DNSPolicy,
- NodeSelector: f.NodeSelector,
- ServiceAccountName: f.ServiceAccountName,
- AutomountServiceAccountToken: f.AutomountServiceAccountToken,
- NodeName: f.NodeName,
- HostNetwork: f.HostNetwork,
- HostPID: f.HostPID,
- HostIPC: f.HostIPC,
- ShareProcessNamespace: f.ShareProcessNamespace,
- SecurityContext: f.SecurityContext,
- ImagePullSecrets: f.ImagePullSecrets,
- Hostname: f.Hostname,
- Subdomain: f.Subdomain,
- Affinity: f.Affinity,
- SchedulerName: f.SchedulerName,
- Tolerations: f.Tolerations,
- HostAliases: f.HostAliases,
- PriorityClassName: f.PriorityClassName,
- Priority: f.Priority,
- DNSConfig: f.DNSConfig,
- ReadinessGates: f.ReadinessGates,
- RuntimeClassName: f.RuntimeClassName,
- EnableServiceLinks: f.EnableServiceLinks,
- PreemptionPolicy: f.PreemptionPolicy,
- Overhead: f.Overhead,
- TopologySpreadConstraints: f.TopologySpreadConstraints,
- SetHostnameAsFQDN: f.SetHostnameAsFQDN,
- OS: f.OS,
- HostUsers: f.HostUsers,
- SchedulingGates: f.SchedulingGates,
- ResourceClaims: f.ResourceClaims,
- }
-}
+// DeploymentModel defines how a given pod will be deployed
+// +kubebuilder:validation:Enum=kubernetes;knative
+type DeploymentModel string
+
+const (
+ // KubernetesDeploymentModel defines a PodSpec to be deployed as a
regular Kubernetes Deployment
+ KubernetesDeploymentModel DeploymentModel = "kubernetes"
+ // KnativeDeploymentModel defines a PodSpec to be deployed as a Knative
Serving Service
+ KnativeDeploymentModel DeploymentModel = "knative"
+)
-// PodTemplateSpec describes the desired custom Kubernetes PodTemplate
definition for the deployed flow or service.
-//
-// The ContainerSpec describes the container where the actual flow or service
is running. It will override any default definitions.
-// For example, to override the image one can use
`.spec.podTemplate.container.image = my/image:tag`.
-type PodTemplateSpec struct {
+// FlowPodTemplateSpec is a special PodTemplateSpec designed for SonataFlow
deployments
+type FlowPodTemplateSpec struct {
// Container is the Kubernetes container where the application should
run.
// One can change this attribute in order to override the defaults
provided by the operator.
// +optional
@@ -556,7 +51,11 @@ type PodTemplateSpec struct {
// +optional
PodSpec `json:",inline"`
// +optional
+ // Replicas define the number of pods to start by default for this
deployment model. Ignored in "knative" deployment model.
Replicas *int32 `json:"replicas,omitempty"`
+ // Defines the kind of deployment model for this pod spec. In dev
profile, only "kubernetes" is valid.
+ // +optional
+ DeploymentModel DeploymentModel `json:"deploymentModel,omitempty"`
}
// Flow describes the contents of the Workflow definition following the CNCF
Serverless Workflow Specification.
@@ -656,7 +155,7 @@ type SonataFlowSpec struct {
Resources WorkflowResources `json:"resources,omitempty"`
// PodTemplate describes the deployment details of this SonataFlow
instance.
//+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="podTemplate"
- PodTemplate PodTemplateSpec `json:"podTemplate,omitempty"`
+ PodTemplate FlowPodTemplateSpec `json:"podTemplate,omitempty"`
// Persistence defines the database persistence configuration for the
workflow
Persistence *PersistenceOptionsSpec `json:"persistence,omitempty"`
// Sink describes the sinkBinding details of this SonataFlow instance.
@@ -752,6 +251,7 @@ func (s *SonataFlowStatus) IsBuildFailed() bool {
//
+kubebuilder:printcolumn:name="Reason",type=string,JSONPath=`.status.conditions[?(@.type=='Running')].reason`
//
+operator-sdk:csv:customresourcedefinitions:resources={{SonataFlowBuild,sonataflow.org/v1alpha08,"A
SonataFlow Build"}}
//
+operator-sdk:csv:customresourcedefinitions:resources={{Deployment,apps/v1,"A
Deployment for the Flow"}}
+//
+operator-sdk:csv:customresourcedefinitions:resources={{Service,serving.knative.dev/v1,"A
Knative Serving Service for the Flow"}}
// +operator-sdk:csv:customresourcedefinitions:resources={{Service,v1,"A
Service for the Flow"}}
//
+operator-sdk:csv:customresourcedefinitions:resources={{Route,route.openshift.io/v1,"An
OpenShift Route for the Flow"}}
// +operator-sdk:csv:customresourcedefinitions:resources={{ConfigMap,v1,"The
ConfigMaps with Flow definition and additional configuration files"}}
@@ -763,6 +263,10 @@ type SonataFlow struct {
Status SonataFlowStatus `json:"status,omitempty"`
}
+func (s *SonataFlow) IsKnativeDeployment() bool {
+ return s.Spec.PodTemplate.DeploymentModel == KnativeDeploymentModel
+}
+
func (s *SonataFlow) HasContainerSpecImage() bool {
return len(s.Spec.PodTemplate.Container.Image) > 0
}
diff --git a/api/v1alpha08/zz_generated.deepcopy.go
b/api/v1alpha08/zz_generated.deepcopy.go
index c970b108..645d2b60 100644
--- a/api/v1alpha08/zz_generated.deepcopy.go
+++ b/api/v1alpha08/zz_generated.deepcopy.go
@@ -320,6 +320,28 @@ func (in *Flow) DeepCopy() *Flow {
return out
}
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver,
writing into out. in must be non-nil.
+func (in *FlowPodTemplateSpec) DeepCopyInto(out *FlowPodTemplateSpec) {
+ *out = *in
+ in.Container.DeepCopyInto(&out.Container)
+ in.PodSpec.DeepCopyInto(&out.PodSpec)
+ if in.Replicas != nil {
+ in, out := &in.Replicas, &out.Replicas
+ *out = new(int32)
+ **out = **in
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver,
creating a new FlowPodTemplateSpec.
+func (in *FlowPodTemplateSpec) DeepCopy() *FlowPodTemplateSpec {
+ if in == nil {
+ return nil
+ }
+ out := new(FlowPodTemplateSpec)
+ in.DeepCopyInto(out)
+ return out
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver,
writing into out. in must be non-nil.
func (in *PersistenceOptionsSpec) DeepCopyInto(out *PersistenceOptionsSpec) {
*out = *in
diff --git a/bundle/manifests/sonataflow-operator.clusterserviceversion.yaml
b/bundle/manifests/sonataflow-operator.clusterserviceversion.yaml
index b71c508b..7e78264f 100644
--- a/bundle/manifests/sonataflow-operator.clusterserviceversion.yaml
+++ b/bundle/manifests/sonataflow-operator.clusterserviceversion.yaml
@@ -288,6 +288,9 @@ spec:
- kind: Deployment
name: A Deployment for the Flow
version: apps/v1
+ - kind: Service
+ name: A Knative Serving Service for the Flow
+ version: serving.knative.dev/v1
- kind: Service
name: A Service for the Flow
version: v1
@@ -437,6 +440,22 @@ spec:
- patch
- update
- watch
+ - apiGroups:
+ - serving.knative.dev
+ resources:
+ - service
+ - services
+ - services/status
+ - services/finalizers
+ verbs:
+ - create
+ - delete
+ - deletecollection
+ - get
+ - list
+ - patch
+ - update
+ - watch
- apiGroups:
- coordination.k8s.io
resources:
diff --git a/bundle/manifests/sonataflow.org_sonataflows.yaml
b/bundle/manifests/sonataflow.org_sonataflows.yaml
index eaf80c91..6f2cb2e7 100644
--- a/bundle/manifests/sonataflow.org_sonataflows.yaml
+++ b/bundle/manifests/sonataflow.org_sonataflows.yaml
@@ -5626,6 +5626,13 @@ spec:
- name
type: object
type: array
+ deploymentModel:
+ description: Defines the kind of deployment model for this
pod
+ spec. In dev profile, only "kubernetes" is valid.
+ enum:
+ - kubernetes
+ - knative
+ type: string
dnsConfig:
description: Specifies the DNS parameters of a pod.
Parameters
specified here will be merged to the generated DNS
configuration
@@ -7153,6 +7160,8 @@ spec:
type: object
type: array
replicas:
+ description: Replicas define the number of pods to start
by default
+ for this deployment model. Ignored in "knative"
deployment model.
format: int32
type: integer
resourceClaims:
diff --git a/config/crd/bases/sonataflow.org_sonataflows.yaml
b/config/crd/bases/sonataflow.org_sonataflows.yaml
index 1557c3b8..61002c32 100644
--- a/config/crd/bases/sonataflow.org_sonataflows.yaml
+++ b/config/crd/bases/sonataflow.org_sonataflows.yaml
@@ -5627,6 +5627,13 @@ spec:
- name
type: object
type: array
+ deploymentModel:
+ description: Defines the kind of deployment model for this
pod
+ spec. In dev profile, only "kubernetes" is valid.
+ enum:
+ - kubernetes
+ - knative
+ type: string
dnsConfig:
description: Specifies the DNS parameters of a pod.
Parameters
specified here will be merged to the generated DNS
configuration
@@ -7154,6 +7161,8 @@ spec:
type: object
type: array
replicas:
+ description: Replicas define the number of pods to start
by default
+ for this deployment model. Ignored in "knative"
deployment model.
format: int32
type: integer
resourceClaims:
diff --git
a/config/manifests/bases/sonataflow-operator.clusterserviceversion.yaml
b/config/manifests/bases/sonataflow-operator.clusterserviceversion.yaml
index c61183d8..c6fdf4e6 100644
--- a/config/manifests/bases/sonataflow-operator.clusterserviceversion.yaml
+++ b/config/manifests/bases/sonataflow-operator.clusterserviceversion.yaml
@@ -172,6 +172,9 @@ spec:
- kind: Deployment
name: A Deployment for the Flow
version: apps/v1
+ - kind: Service
+ name: A Knative Serving Service for the Flow
+ version: serving.knative.dev/v1
- kind: Service
name: A Service for the Flow
version: v1
diff --git a/config/rbac/builder_role.yaml b/config/rbac/builder_role.yaml
index 70b2ab54..ffced490 100644
--- a/config/rbac/builder_role.yaml
+++ b/config/rbac/builder_role.yaml
@@ -66,33 +66,3 @@ rules:
- patch
- update
- watch
-- apiGroups:
- - eventing.knative.dev
- resources:
- - triggers
- - triggers/status
- - triggers/finalizers
- verbs:
- - create
- - delete
- - deletecollection
- - get
- - list
- - patch
- - update
- - watch
-- apiGroups:
- - sources.knative.dev
- resources:
- - sinkbindings
- - sinkbindings/status
- - sinkbindings/finalizers
- verbs:
- - create
- - delete
- - deletecollection
- - get
- - list
- - patch
- - update
- - watch
\ No newline at end of file
diff --git a/config/rbac/knative_role.yaml b/config/rbac/knative_role.yaml
new file mode 100644
index 00000000..8dad9419
--- /dev/null
+++ b/config/rbac/knative_role.yaml
@@ -0,0 +1,52 @@
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: knative-manager-role
+rules:
+ - apiGroups:
+ - eventing.knative.dev
+ resources:
+ - triggers
+ - triggers/status
+ - triggers/finalizers
+ verbs:
+ - create
+ - delete
+ - deletecollection
+ - get
+ - list
+ - patch
+ - update
+ - watch
+ - apiGroups:
+ - sources.knative.dev
+ resources:
+ - sinkbindings
+ - sinkbindings/status
+ - sinkbindings/finalizers
+ verbs:
+ - create
+ - delete
+ - deletecollection
+ - get
+ - list
+ - patch
+ - update
+ - watch
+ - apiGroups:
+ - serving.knative.dev
+ resources:
+ - service
+ - services
+ - services/status
+ - services/finalizers
+ verbs:
+ - create
+ - delete
+ - deletecollection
+ - get
+ - list
+ - patch
+ - update
+ - watch
diff --git a/config/rbac/knative_role_binding.yaml
b/config/rbac/knative_role_binding.yaml
new file mode 100644
index 00000000..cbab613c
--- /dev/null
+++ b/config/rbac/knative_role_binding.yaml
@@ -0,0 +1,13 @@
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: knative-manager-rolebinding
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: knative-manager-role
+subjects:
+ - kind: ServiceAccount
+ name: controller-manager
+ namespace: system
diff --git a/config/rbac/kustomization.yaml b/config/rbac/kustomization.yaml
index 2ffd5efa..9a097cc2 100644
--- a/config/rbac/kustomization.yaml
+++ b/config/rbac/kustomization.yaml
@@ -17,6 +17,8 @@ resources:
- operator_role_binding_leases.yaml
- service_discovery_role.yaml
- service_discovery_role_binding.yaml
+- knative_role.yaml
+- knative_role_binding.yaml
# Comment the following 4 lines if you want to disable
# the auth proxy (https://github.com/brancz/kube-rbac-proxy)
# which protects your /metrics endpoint.
diff --git a/controllers/platform/k8s.go b/controllers/platform/k8s.go
index e4310de8..62d8b369 100644
--- a/controllers/platform/k8s.go
+++ b/controllers/platform/k8s.go
@@ -115,7 +115,7 @@ func createOrUpdateDeployment(ctx context.Context, client
client.Client, platfor
LivenessProbe: liveProbe,
Ports: []corev1.ContainerPort{
{
- Name: utils.HttpScheme,
+ Name: utils.DefaultServicePortName,
ContainerPort:
int32(constants.DefaultHTTPWorkflowPortInt),
Protocol: corev1.ProtocolTCP,
},
@@ -199,7 +199,7 @@ func createOrUpdateService(ctx context.Context, client
client.Client, platform *
dataSvcSpec := corev1.ServiceSpec{
Ports: []corev1.ServicePort{
{
- Name: utils.HttpScheme,
+ Name: utils.DefaultServicePortName,
Protocol: corev1.ProtocolTCP,
Port: 80,
TargetPort:
variables.DefaultHTTPWorkflowPortIntStr,
diff --git a/controllers/profiles/common/deployment.go
b/controllers/profiles/common/deployment_status_manager.go
similarity index 83%
rename from controllers/profiles/common/deployment.go
rename to controllers/profiles/common/deployment_status_manager.go
index 64b67767..6272d3f3 100644
--- a/controllers/profiles/common/deployment.go
+++ b/controllers/profiles/common/deployment_status_manager.go
@@ -26,7 +26,9 @@ import (
appsv1 "k8s.io/api/apps/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/types"
"k8s.io/klog/v2"
+ servingv1 "knative.dev/serving/pkg/apis/serving/v1"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -39,6 +41,8 @@ import (
var _ WorkflowDeploymentManager = &deploymentHandler{}
+const knativeDeploymentSuffix = "-deployment"
+
// WorkflowDeploymentManager interface to handle workflow deployment features.
type WorkflowDeploymentManager interface {
// SyncDeploymentStatus updates the workflow status aligned with the
deployment counterpart.
@@ -58,24 +62,42 @@ type deploymentHandler struct {
c client.Client
}
-func (d *deploymentHandler) RolloutDeployment(ctx context.Context, workflow
*operatorapi.SonataFlow) error {
+func (d *deploymentHandler) getDeployment(ctx context.Context, workflow
*operatorapi.SonataFlow) (*appsv1.Deployment, error) {
+ deploymentName := workflow.Name
+ if workflow.IsKnativeDeployment() {
+ ksvc := &servingv1.Service{}
+ if err := d.c.Get(ctx, client.ObjectKeyFromObject(workflow),
ksvc); err != nil {
+ if errors.IsNotFound(err) {
+ return nil, nil
+ }
+ return nil, err
+ }
+ deploymentName = ksvc.Status.LatestCreatedRevisionName +
knativeDeploymentSuffix
+ }
deployment := &appsv1.Deployment{}
- if err := d.c.Get(ctx, client.ObjectKeyFromObject(workflow),
deployment); err != nil {
- // Deployment not found, nothing to do.
+ if err := d.c.Get(ctx, types.NamespacedName{Namespace:
workflow.Namespace, Name: deploymentName}, deployment); err != nil {
if errors.IsNotFound(err) {
- return nil
+ return nil, nil
}
+ return nil, err
+ }
+ return deployment, nil
+}
+
+func (d *deploymentHandler) RolloutDeployment(ctx context.Context, workflow
*operatorapi.SonataFlow) error {
+ deployment, err := d.getDeployment(ctx, workflow)
+ if err != nil || deployment == nil {
return err
}
- if err := kubeutil.MarkDeploymentToRollout(deployment); err != nil {
+ if err = kubeutil.MarkDeploymentToRollout(deployment); err != nil {
return err
}
return d.c.Update(ctx, deployment)
}
func (d *deploymentHandler) SyncDeploymentStatus(ctx context.Context, workflow
*operatorapi.SonataFlow) (ctrl.Result, error) {
- deployment := &appsv1.Deployment{}
- if err := d.c.Get(ctx, client.ObjectKeyFromObject(workflow),
deployment); err != nil {
+ deployment, err := d.getDeployment(ctx, workflow)
+ if err != nil || deployment == nil {
// we should have the deployment by this time, so even if the
error above is not found, we should halt.
workflow.Status.Manager().MarkFalse(api.RunningConditionType,
api.DeploymentUnavailableReason, "Couldn't find the workflow deployment")
return ctrl.Result{RequeueAfter:
constants.RequeueAfterFailure}, err
diff --git a/controllers/profiles/common/knative.go
b/controllers/profiles/common/knative_eventing.go
similarity index 100%
rename from controllers/profiles/common/knative.go
rename to controllers/profiles/common/knative_eventing.go
diff --git a/controllers/profiles/common/mutate_visitors.go
b/controllers/profiles/common/mutate_visitors.go
index eab1944b..426154ee 100644
--- a/controllers/profiles/common/mutate_visitors.go
+++ b/controllers/profiles/common/mutate_visitors.go
@@ -27,6 +27,7 @@ import (
"github.com/imdario/mergo"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
+ servingv1 "knative.dev/serving/pkg/apis/serving/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
@@ -55,6 +56,25 @@ func ImageDeploymentMutateVisitor(workflow
*operatorapi.SonataFlow, image string
}
}
+// ImageKServiceMutateVisitor same as ImageDeploymentMutateVisitor for Knative
Serving
+func ImageKServiceMutateVisitor(workflow *operatorapi.SonataFlow, image
string) MutateVisitor {
+ return func(object client.Object) controllerutil.MutateFn {
+ // noop since we already have an image in the flow container
defined by the user.
+ if workflow.HasContainerSpecImage() {
+ return func() error {
+ return nil
+ }
+ }
+ return func() error {
+ ksvc := object.(*servingv1.Service)
+ _, idx :=
kubeutil.GetContainerByName(operatorapi.DefaultContainerName,
&ksvc.Spec.Template.Spec.PodSpec)
+ ksvc.Spec.Template.Spec.Containers[idx].Image = image
+ ksvc.Spec.Template.Spec.Containers[idx].ImagePullPolicy
= kubeutil.GetImagePullPolicy(image)
+ return nil
+ }
+ }
+}
+
// DeploymentMutateVisitor guarantees the state of the default Deployment
object
func DeploymentMutateVisitor(workflow *operatorapi.SonataFlow, plf
*operatorapi.SonataFlowPlatform) MutateVisitor {
return func(object client.Object) controllerutil.MutateFn {
@@ -87,6 +107,36 @@ func EnsureDeployment(original *appsv1.Deployment, object
*appsv1.Deployment) er
return mergo.Merge(&object.Spec.Template.Spec,
original.Spec.Template.Spec, mergo.WithOverride)
}
+// KServiceMutateVisitor guarantees the state of the default Knative Service
object
+func KServiceMutateVisitor(workflow *operatorapi.SonataFlow, plf
*operatorapi.SonataFlowPlatform) MutateVisitor {
+ return func(object client.Object) controllerutil.MutateFn {
+ return func() error {
+ if kubeutil.IsObjectNew(object) {
+ return nil
+ }
+ original, err := KServiceCreator(workflow, plf)
+ if err != nil {
+ return err
+ }
+ return EnsureKService(original.(*servingv1.Service),
object.(*servingv1.Service))
+ }
+ }
+}
+
+// EnsureKService Ensure that the original Knative Service fields are
immutable.
+func EnsureKService(original *servingv1.Service, object *servingv1.Service)
error {
+ object.Labels = original.GetLabels()
+
+ // Clean up the volumes, they are inherited from original, additional
are added by other visitors
+ object.Spec.Template.Spec.Volumes = nil
+ for i := range object.Spec.Template.Spec.Containers {
+ object.Spec.Template.Spec.Containers[i].VolumeMounts = nil
+ }
+
+ // we do a merge to not keep changing the spec since k8s will set
default values to the podSpec
+ return mergo.Merge(&object.Spec.Template.Spec.PodSpec,
original.Spec.Template.Spec.PodSpec, mergo.WithOverride)
+}
+
func ServiceMutateVisitor(workflow *operatorapi.SonataFlow) MutateVisitor {
return func(object client.Object) controllerutil.MutateFn {
return func() error {
diff --git a/controllers/profiles/common/object_creators.go
b/controllers/profiles/common/object_creators.go
index 8da5956d..c1ac6703 100644
--- a/controllers/profiles/common/object_creators.go
+++ b/controllers/profiles/common/object_creators.go
@@ -24,6 +24,7 @@ import (
"strings"
"github.com/apache/incubator-kie-kogito-serverless-operator/controllers/workflowdef"
+ servingv1 "knative.dev/serving/pkg/apis/serving/v1"
cncfmodel "github.com/serverlessworkflow/sdk-go/v2/model"
@@ -108,6 +109,41 @@ func DeploymentCreator(workflow *operatorapi.SonataFlow,
plf *operatorapi.Sonata
return deployment, nil
}
+// KServiceCreator creates the default Knative Service object for SonataFlow
instances. It's based on the default DeploymentCreator.
+func KServiceCreator(workflow *operatorapi.SonataFlow, plf
*operatorapi.SonataFlowPlatform) (client.Object, error) {
+ lbl := workflowproj.GetMergedLabels(workflow)
+ ksvc := &servingv1.Service{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: workflow.Name,
+ Namespace: workflow.Namespace,
+ Labels: lbl,
+ },
+ Spec: servingv1.ServiceSpec{
+ ConfigurationSpec: servingv1.ConfigurationSpec{
+ Template: servingv1.RevisionTemplateSpec{
+ ObjectMeta: metav1.ObjectMeta{
+ Labels: lbl,
+ },
+ Spec: servingv1.RevisionSpec{
+ PodSpec: corev1.PodSpec{},
+ },
+ },
+ },
+ },
+ }
+
+ if err := mergo.Merge(&ksvc.Spec.Template.Spec.PodSpec,
workflow.Spec.PodTemplate.PodSpec.ToPodSpec(), mergo.WithOverride); err != nil {
+ return nil, err
+ }
+ flowContainer, err := defaultContainer(workflow, plf)
+ if err != nil {
+ return nil, err
+ }
+ kubeutil.AddOrReplaceContainer(operatorapi.DefaultContainerName,
*flowContainer, &ksvc.Spec.Template.Spec.PodSpec)
+
+ return ksvc, nil
+}
+
func getReplicasOrDefault(workflow *operatorapi.SonataFlow) *int32 {
var dReplicas int32 = 1
if workflow.Spec.PodTemplate.Replicas == nil {
@@ -119,7 +155,7 @@ func getReplicasOrDefault(workflow *operatorapi.SonataFlow)
*int32 {
func defaultContainer(workflow *operatorapi.SonataFlow, plf
*operatorapi.SonataFlowPlatform) (*corev1.Container, error) {
defaultContainerPort := corev1.ContainerPort{
ContainerPort: variables.DefaultHTTPWorkflowPortIntStr.IntVal,
- Name: utils.HttpScheme,
+ Name: utils.DefaultServicePortName,
Protocol: corev1.ProtocolTCP,
}
defaultFlowContainer := &corev1.Container{
@@ -134,6 +170,7 @@ func defaultContainer(workflow *operatorapi.SonataFlow, plf
*operatorapi.SonataF
},
},
TimeoutSeconds: healthTimeoutSeconds,
+ PeriodSeconds: healthStartedPeriodSeconds,
},
ReadinessProbe: &corev1.Probe{
ProbeHandler: corev1.ProbeHandler{
@@ -143,6 +180,7 @@ func defaultContainer(workflow *operatorapi.SonataFlow, plf
*operatorapi.SonataF
},
},
TimeoutSeconds: healthTimeoutSeconds,
+ PeriodSeconds: healthStartedPeriodSeconds,
},
StartupProbe: &corev1.Probe{
ProbeHandler: corev1.ProbeHandler{
@@ -173,7 +211,7 @@ func defaultContainer(workflow *operatorapi.SonataFlow, plf
*operatorapi.SonataF
defaultFlowContainer.Name = operatorapi.DefaultContainerName
portIdx := -1
for i := range defaultFlowContainer.Ports {
- if defaultFlowContainer.Ports[i].Name == utils.HttpScheme ||
+ if defaultFlowContainer.Ports[i].Name ==
utils.DefaultServicePortName ||
defaultFlowContainer.Ports[i].ContainerPort ==
variables.DefaultHTTPWorkflowPortIntStr.IntVal {
portIdx = i
break
diff --git a/controllers/profiles/common/object_creators_test.go
b/controllers/profiles/common/object_creators_test.go
index 26b54999..8b42e5fc 100644
--- a/controllers/profiles/common/object_creators_test.go
+++ b/controllers/profiles/common/object_creators_test.go
@@ -94,13 +94,13 @@ func
Test_ensureWorkflowPropertiesConfigMapMutator_DollarReplacement(t *testing.
func TestMergePodSpec(t *testing.T) {
workflow := test.GetBaseSonataFlow(t.Name())
- workflow.Spec.PodTemplate = v1alpha08.PodTemplateSpec{
+ workflow.Spec.PodTemplate = v1alpha08.FlowPodTemplateSpec{
Container: v1alpha08.ContainerSpec{
// this one we can override
Image: "quay.io/example/my-workflow:1.0.0",
Ports: []corev1.ContainerPort{
// let's override a immutable attribute
- {Name: utils.HttpScheme, ContainerPort: 9090},
+ {Name: utils.DefaultServicePortName,
ContainerPort: 9090},
},
Env: []corev1.EnvVar{
// We should be able to override this too
@@ -147,7 +147,7 @@ func TestMergePodSpec(t *testing.T) {
func TestMergePodSpec_OverrideContainers(t *testing.T) {
workflow := test.GetBaseSonataFlow(t.Name())
- workflow.Spec.PodTemplate = v1alpha08.PodTemplateSpec{
+ workflow.Spec.PodTemplate = v1alpha08.FlowPodTemplateSpec{
PodSpec: v1alpha08.PodSpec{
// Try to override the workflow container via the
podspec
Containers: []corev1.Container{
@@ -155,7 +155,7 @@ func TestMergePodSpec_OverrideContainers(t *testing.T) {
Name: v1alpha08.DefaultContainerName,
Image:
"quay.io/example/my-workflow:1.0.0",
Ports: []corev1.ContainerPort{
- {Name: utils.HttpScheme,
ContainerPort: 9090},
+ {Name:
utils.DefaultServicePortName, ContainerPort: 9090},
},
Env: []corev1.EnvVar{
{Name: "ENV1", Value:
"VALUE_CUSTOM"},
@@ -213,13 +213,13 @@ func Test_ensureWorkflowTriggersAreCreated(t *testing.T) {
func TestMergePodSpec_WithPostgreSQL_and_JDBC_URL_field(t *testing.T) {
workflow := test.GetBaseSonataFlow(t.Name())
workflow.Spec = v1alpha08.SonataFlowSpec{
- PodTemplate: v1alpha08.PodTemplateSpec{
+ PodTemplate: v1alpha08.FlowPodTemplateSpec{
Container: v1alpha08.ContainerSpec{
// this one we can override
Image: "quay.io/example/my-workflow:1.0.0",
Ports: []corev1.ContainerPort{
// let's override a immutable attribute
- {Name: utils.HttpScheme, ContainerPort:
9090},
+ {Name: utils.DefaultServicePortName,
ContainerPort: 9090},
},
Env: []corev1.EnvVar{
// We should be able to override this
too
@@ -321,7 +321,7 @@ var (
func TestMergePodSpec_OverrideContainers_WithPostgreSQL_In_Workflow_CR(t
*testing.T) {
workflow := test.GetBaseSonataFlow(t.Name())
workflow.Spec = v1alpha08.SonataFlowSpec{
- PodTemplate: v1alpha08.PodTemplateSpec{
+ PodTemplate: v1alpha08.FlowPodTemplateSpec{
PodSpec: v1alpha08.PodSpec{
// Try to override the workflow container via
the podspec
Containers: []corev1.Container{
@@ -329,7 +329,7 @@ func
TestMergePodSpec_OverrideContainers_WithPostgreSQL_In_Workflow_CR(t *testin
Name:
v1alpha08.DefaultContainerName,
Image:
"quay.io/example/my-workflow:1.0.0",
Ports: []corev1.ContainerPort{
- {Name:
utils.HttpScheme, ContainerPort: 9090},
+ {Name:
utils.DefaultServicePortName, ContainerPort: 9090},
},
Env: []corev1.EnvVar{
{Name: "ENV1", Value:
"VALUE_CUSTOM"},
@@ -510,7 +510,7 @@ func
TestMergePodSpec_WithServicedPostgreSQL_In_Platform_And_In_Workflow_CR(t *t
}
workflow := test.GetBaseSonataFlow(t.Name())
workflow.Spec = v1alpha08.SonataFlowSpec{
- PodTemplate: v1alpha08.PodTemplateSpec{
+ PodTemplate: v1alpha08.FlowPodTemplateSpec{
PodSpec: v1alpha08.PodSpec{
// Try to override the workflow container via
the podspec
Containers: []corev1.Container{
@@ -518,7 +518,7 @@ func
TestMergePodSpec_WithServicedPostgreSQL_In_Platform_And_In_Workflow_CR(t *t
Name:
v1alpha08.DefaultContainerName,
Image:
"quay.io/example/my-workflow:1.0.0",
Ports: []corev1.ContainerPort{
- {Name:
utils.HttpScheme, ContainerPort: 9090},
+ {Name:
utils.DefaultServicePortName, ContainerPort: 9090},
},
Env: []corev1.EnvVar{
{Name: "ENV1", Value:
"VALUE_CUSTOM"},
diff --git a/controllers/profiles/common/persistence/postgresql.go
b/controllers/profiles/common/persistence/postgresql.go
index 4bb5f38d..e88a3425 100644
--- a/controllers/profiles/common/persistence/postgresql.go
+++ b/controllers/profiles/common/persistence/postgresql.go
@@ -25,20 +25,7 @@ import (
)
const (
- defaultDatabaseName = "sonataflow"
- timeoutSeconds = 3
- failureThreshold = 5
- initialPeriodSeconds = 15
- initialDelaySeconds = 10
- successThreshold = 1
-
- postgreSQLCPULimit = "500m"
- postgreSQLMemoryLimit = "256Mi"
- postgreSQLMemoryRequest = "256Mi"
- postgreSQLCPURequest = "100m"
-
- defaultPostgreSQLUsername = "sonataflow"
- defaultPostgresSQLPassword = "sonataflow"
+ defaultDatabaseName = "sonataflow"
)
func ConfigurePostgreSQLEnv(postgresql *operatorapi.PersistencePostgreSQL,
databaseSchema, databaseNamespace string) []corev1.EnvVar {
diff --git a/controllers/profiles/dev/object_creators_dev.go
b/controllers/profiles/dev/object_creators_dev.go
index 45f6926c..0f6069f1 100644
--- a/controllers/profiles/dev/object_creators_dev.go
+++ b/controllers/profiles/dev/object_creators_dev.go
@@ -90,8 +90,7 @@ func deploymentMutateVisitor(workflow
*operatorapi.SonataFlow, plf *operatorapi.
if err != nil {
return err
}
- common.EnsureDeployment(original.(*appsv1.Deployment),
object.(*appsv1.Deployment))
- return nil
+ return
common.EnsureDeployment(original.(*appsv1.Deployment),
object.(*appsv1.Deployment))
}
}
}
diff --git a/controllers/profiles/factory/factory.go
b/controllers/profiles/factory/factory.go
index d54b0df3..511c6ca3 100644
--- a/controllers/profiles/factory/factory.go
+++ b/controllers/profiles/factory/factory.go
@@ -34,10 +34,6 @@ import (
"github.com/apache/incubator-kie-kogito-serverless-operator/controllers/profiles/dev"
)
-const (
- defaultProfile = metadata.PreviewProfile
-)
-
type reconcilerBuilder func(client client.Client, cfg *rest.Config, recorder
record.EventRecorder) profiles.ProfileReconciler
var profileBuilders = map[metadata.ProfileType]reconcilerBuilder{
@@ -47,25 +43,22 @@ var profileBuilders =
map[metadata.ProfileType]reconcilerBuilder{
}
func profileBuilder(workflow *operatorapi.SonataFlow) reconcilerBuilder {
- profile := workflow.Annotations[metadata.Profile]
- if len(profile) == 0 {
- profile = defaultProfile.String()
- }
+ profile := metadata.GetProfileOrDefault(workflow.Annotations)
// keep backward compatibility
- if profile == metadata.ProdProfile.String() {
+ if profile == metadata.ProdProfile {
klog.V(log.W).Infof("Profile %s is deprecated, please use '%s'
instead.", metadata.ProdProfile, metadata.PreviewProfile)
- profile = metadata.PreviewProfile.String()
+ profile = metadata.PreviewProfile
}
// Enforce GitOps profile if the .spec.podTemplate.container.image is
set in the Preview profile.
- if (profile == metadata.PreviewProfile.String() || profile ==
metadata.ProdProfile.String()) && workflow.HasContainerSpecImage() {
+ if (profile == metadata.PreviewProfile || profile ==
metadata.ProdProfile) && workflow.HasContainerSpecImage() {
workflow.Annotations[metadata.Profile] =
metadata.GitOpsProfile.String()
return profileBuilders[metadata.GitOpsProfile]
}
- if _, ok := profileBuilders[metadata.ProfileType(profile)]; !ok {
- klog.V(log.W).Infof("Profile %s not supported, please use '%s'
or '%s'. Falling back to %s", profile, metadata.PreviewProfile,
metadata.DevProfile, defaultProfile)
- return profileBuilders[defaultProfile]
+ if _, ok := profileBuilders[profile]; !ok {
+ klog.V(log.W).Infof("Profile %s not supported, please use '%s'
or '%s'. Falling back to %s", profile, metadata.PreviewProfile,
metadata.DevProfile, metadata.DefaultProfile)
+ return profileBuilders[metadata.DefaultProfile]
}
- return profileBuilders[metadata.ProfileType(profile)]
+ return profileBuilders[profile]
}
// NewReconciler creates a new ProfileReconciler based on the given workflow
and context.
diff --git a/controllers/profiles/gitops/profile_gitops_test.go
b/controllers/profiles/gitops/profile_gitops_test.go
index 9287cbc2..051ea577 100644
--- a/controllers/profiles/gitops/profile_gitops_test.go
+++ b/controllers/profiles/gitops/profile_gitops_test.go
@@ -29,7 +29,7 @@ import (
)
func Test_Reconciler_ProdOps(t *testing.T) {
- workflow := test.GetBaseSonataFlowWithProdOpsProfile(t.Name())
+ workflow := test.GetBaseSonataFlowWithPreviewProfile(t.Name())
workflow.Spec.PodTemplate.PodSpec.InitContainers =
append(workflow.Spec.PodTemplate.PodSpec.InitContainers, corev1.Container{
Name: "check-postgres",
Image: "registry.access.redhat.com/ubi9/ubi-micro:latest",
diff --git a/controllers/profiles/preview/deployment_handler.go
b/controllers/profiles/preview/deployment_handler.go
index 5fce2688..dfbac253 100644
--- a/controllers/profiles/preview/deployment_handler.go
+++ b/controllers/profiles/preview/deployment_handler.go
@@ -17,8 +17,8 @@ package preview
import (
"context"
+
"github.com/apache/incubator-kie-kogito-serverless-operator/controllers/knative"
v1 "k8s.io/api/core/v1"
- ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
@@ -44,81 +44,117 @@ func NewDeploymentReconciler(stateSupport
*common.StateSupport, ensurer *ObjectE
}
func (d *DeploymentReconciler) Reconcile(ctx context.Context, workflow
*operatorapi.SonataFlow) (reconcile.Result, []client.Object, error) {
- return d.reconcileWithBuiltImage(ctx, workflow, "")
+ return d.reconcileWithImage(ctx, workflow, "")
}
-func (d *DeploymentReconciler) reconcileWithBuiltImage(ctx context.Context,
workflow *operatorapi.SonataFlow, image string) (reconcile.Result,
[]client.Object, error) {
+func (d *DeploymentReconciler) reconcileWithImage(ctx context.Context,
workflow *operatorapi.SonataFlow, image string) (reconcile.Result,
[]client.Object, error) {
+ // Checks if we need Knative installed and is not present.
+ if requires, err := d.ensureKnativeServingRequired(workflow); requires
|| err != nil {
+ return reconcile.Result{Requeue: false}, nil, err
+ }
+
+ // Ensure objects
+ result, objs, err := d.ensureObjects(ctx, workflow, image)
+ if err != nil || result.Requeue {
+ return result, objs, err
+ }
+
+ // Follow deployment status
+ result, err = common.DeploymentManager(d.C).SyncDeploymentStatus(ctx,
workflow)
+ if err != nil {
+ return reconcile.Result{Requeue: false}, nil, err
+ }
+
+ if _, err := d.PerformStatusUpdate(ctx, workflow); err != nil {
+ return reconcile.Result{Requeue: false}, nil, err
+ }
+ return result, objs, nil
+}
+
+// ensureKnativeServingRequired returns true if the SonataFlow instance
requires Knative deployment and Knative Serving is not available.
+func (d *DeploymentReconciler) ensureKnativeServingRequired(workflow
*operatorapi.SonataFlow) (bool, error) {
+ if workflow.IsKnativeDeployment() {
+ avail, err := knative.GetKnativeAvailability(d.Cfg)
+ if err != nil {
+ return true, err
+ }
+ if !avail.Serving {
+ d.Recorder.Eventf(workflow, v1.EventTypeWarning,
+ "KnativeServingNotAvailable",
+ "Knative Serving is not available in this
cluster, can't deploy workflow. Please update the deployment model to %s",
+ operatorapi.KubernetesDeploymentModel)
+ return true, nil
+ }
+ }
+ return false, nil
+}
+
+func (d *DeploymentReconciler) ensureObjects(ctx context.Context, workflow
*operatorapi.SonataFlow, image string) (reconcile.Result, []client.Object,
error) {
pl, _ := platform.GetActivePlatform(ctx, d.C, workflow.Namespace)
userPropsCM, _, err := d.ensurers.userPropsConfigMap.Ensure(ctx,
workflow)
if err != nil {
workflow.Status.Manager().MarkFalse(api.RunningConditionType,
api.ExternalResourcesNotFoundReason, "Unable to retrieve the user properties
config map")
- _, err = d.PerformStatusUpdate(ctx, workflow)
- return ctrl.Result{}, nil, err
+ _, _ = d.PerformStatusUpdate(ctx, workflow)
+ return reconcile.Result{}, nil, err
}
managedPropsCM, _, err := d.ensurers.managedPropsConfigMap.Ensure(ctx,
workflow, pl,
common.ManagedPropertiesMutateVisitor(ctx,
d.StateSupport.Catalog, workflow, pl, userPropsCM.(*v1.ConfigMap)))
if err != nil {
workflow.Status.Manager().MarkFalse(api.RunningConditionType,
api.ExternalResourcesNotFoundReason, "Unable to retrieve the managed properties
config map")
- _, err = d.PerformStatusUpdate(ctx, workflow)
- return ctrl.Result{}, nil, err
+ _, _ = d.PerformStatusUpdate(ctx, workflow)
+ return reconcile.Result{}, nil, err
}
deployment, deploymentOp, err :=
- d.ensurers.deployment.Ensure(
- ctx,
- workflow,
- pl,
- d.getDeploymentMutateVisitors(workflow, pl, image,
userPropsCM.(*v1.ConfigMap), managedPropsCM.(*v1.ConfigMap))...,
- )
+ d.ensurers.DeploymentByDeploymentModel(workflow).Ensure(ctx,
workflow, pl,
+ d.deploymentModelMutateVisitors(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)
- _, err = d.PerformStatusUpdate(ctx, workflow)
+ _, _ = d.PerformStatusUpdate(ctx, workflow)
return reconcile.Result{}, nil, err
}
- service, _, err := d.ensurers.service.Ensure(ctx, workflow,
common.ServiceMutateVisitor(workflow))
+ service, _, err :=
d.ensurers.ServiceByDeploymentModel(workflow).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)
+ _, _ = d.PerformStatusUpdate(ctx, workflow)
return reconcile.Result{}, nil, err
}
- knativeObjs, err :=
common.NewKnativeEventingHandler(d.StateSupport).Ensure(ctx, workflow)
+ eventingObjs, err :=
common.NewKnativeEventingHandler(d.StateSupport).Ensure(ctx, workflow)
if err != nil {
- return ctrl.Result{RequeueAfter:
constants.RequeueAfterFailure}, nil, err
+ return reconcile.Result{}, nil, err
}
- objs := []client.Object{deployment, service, managedPropsCM}
- objs = append(objs, knativeObjs...)
+ objs := []client.Object{deployment, managedPropsCM, service}
if deploymentOp == controllerutil.OperationResultCreated {
workflow.Status.Manager().MarkFalse(api.RunningConditionType,
api.WaitingForDeploymentReason, "")
if _, err := d.PerformStatusUpdate(ctx, workflow); err != nil {
- return reconcile.Result{Requeue: false}, nil, err
+ return reconcile.Result{}, nil, err
}
return reconcile.Result{RequeueAfter:
constants.RequeueAfterFollowDeployment, Requeue: true}, objs, nil
}
+ objs = append(objs, eventingObjs...)
- // Follow deployment status
- result, err := common.DeploymentManager(d.C).SyncDeploymentStatus(ctx,
workflow)
- if err != nil {
- return reconcile.Result{Requeue: false}, nil, err
- }
-
- if _, err := d.PerformStatusUpdate(ctx, workflow); err != nil {
- return reconcile.Result{Requeue: false}, nil, err
- }
- return result, objs, nil
+ return reconcile.Result{}, objs, nil
}
-func (d *DeploymentReconciler) getDeploymentMutateVisitors(
+func (d *DeploymentReconciler) deploymentModelMutateVisitors(
workflow *operatorapi.SonataFlow,
plf *operatorapi.SonataFlowPlatform,
image string,
userPropsCM *v1.ConfigMap,
managedPropsCM *v1.ConfigMap) []common.MutateVisitor {
+
+ if workflow.IsKnativeDeployment() {
+ return
[]common.MutateVisitor{common.KServiceMutateVisitor(workflow, plf),
+ common.ImageKServiceMutateVisitor(workflow, image),
+ mountConfigMapsMutateVisitor(workflow, userPropsCM,
managedPropsCM)}
+ }
+
if utils.IsOpenShift() {
return
[]common.MutateVisitor{common.DeploymentMutateVisitor(workflow, plf),
- mountProdConfigMapsMutateVisitor(workflow, userPropsCM,
managedPropsCM),
+ mountConfigMapsMutateVisitor(workflow, userPropsCM,
managedPropsCM),
addOpenShiftImageTriggerDeploymentMutateVisitor(workflow, image),
common.ImageDeploymentMutateVisitor(workflow, image),
common.RolloutDeploymentIfCMChangedMutateVisitor(workflow, userPropsCM,
managedPropsCM),
@@ -126,6 +162,6 @@ func (d *DeploymentReconciler) getDeploymentMutateVisitors(
}
return []common.MutateVisitor{common.DeploymentMutateVisitor(workflow,
plf),
common.ImageDeploymentMutateVisitor(workflow, image),
- mountProdConfigMapsMutateVisitor(workflow, userPropsCM,
managedPropsCM),
+ mountConfigMapsMutateVisitor(workflow, userPropsCM,
managedPropsCM),
common.RolloutDeploymentIfCMChangedMutateVisitor(workflow,
userPropsCM, managedPropsCM)}
}
diff --git a/controllers/profiles/preview/deployment_handler_test.go
b/controllers/profiles/preview/deployment_handler_test.go
index d70436d7..5faf98bb 100644
--- a/controllers/profiles/preview/deployment_handler_test.go
+++ b/controllers/profiles/preview/deployment_handler_test.go
@@ -28,10 +28,42 @@ import (
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
+ servingv1 "knative.dev/serving/pkg/apis/serving/v1"
)
+type fakeDeploymentReconciler struct {
+ DeploymentReconciler
+}
+
+func Test_CheckDeploymentModelIsKnative(t *testing.T) {
+ workflow := test.GetBaseSonataFlowWithPreviewProfile(t.Name())
+ workflow.Spec.PodTemplate.DeploymentModel =
v1alpha08.KnativeDeploymentModel
+
+ cli := test.NewSonataFlowClientBuilderWithKnative().
+ WithRuntimeObjects(workflow).
+ WithStatusSubresource(workflow).
+ Build()
+ stateSupport := fakeReconcilerSupport(cli)
+ handler := NewDeploymentReconciler(stateSupport,
NewObjectEnsurers(stateSupport))
+
+ result, objects, err := handler.ensureObjects(context.TODO(), workflow,
"")
+ assert.NoError(t, err)
+ assert.NotEmpty(t, objects)
+ assert.True(t, result.Requeue)
+
+ var ksvc *servingv1.Service
+ for _, o := range objects {
+ if _, ok := o.(*servingv1.Service); ok {
+ ksvc = o.(*servingv1.Service)
+ assert.Equal(t, v1alpha08.DefaultContainerName,
ksvc.Spec.Template.Spec.Containers[0].Name)
+ break
+ }
+ }
+ assert.NotNil(t, ksvc)
+}
+
func Test_CheckPodTemplateChangesReflectDeployment(t *testing.T) {
- workflow := test.GetBaseSonataFlowWithProdOpsProfile(t.Name())
+ workflow := test.GetBaseSonataFlowWithPreviewProfile(t.Name())
client := test.NewSonataFlowClientBuilder().
WithRuntimeObjects(workflow).
@@ -53,18 +85,20 @@ func Test_CheckPodTemplateChangesReflectDeployment(t
*testing.T) {
assert.NoError(t, err)
assert.NotEmpty(t, objects)
assert.True(t, result.Requeue)
+ var deployment *v1.Deployment
for _, o := range objects {
if _, ok := o.(*v1.Deployment); ok {
- deployment := o.(*v1.Deployment)
+ deployment = o.(*v1.Deployment)
assert.Equal(t, expectedImg,
deployment.Spec.Template.Spec.Containers[0].Image)
assert.Equal(t, v1alpha08.DefaultContainerName,
deployment.Spec.Template.Spec.Containers[0].Name)
break
}
}
+ assert.NotNil(t, deployment)
}
func Test_CheckDeploymentRolloutAfterCMChange(t *testing.T) {
- workflow := test.GetBaseSonataFlowWithProdOpsProfile(t.Name())
+ workflow := test.GetBaseSonataFlowWithPreviewProfile(t.Name())
client := test.NewSonataFlowClientBuilder().
WithRuntimeObjects(workflow).
@@ -126,7 +160,7 @@ func Test_CheckDeploymentRolloutAfterCMChange(t *testing.T)
{
}
func Test_CheckDeploymentUnchangedAfterCMChangeOtherKeys(t *testing.T) {
- workflow := test.GetBaseSonataFlowWithProdOpsProfile(t.Name())
+ workflow := test.GetBaseSonataFlowWithPreviewProfile(t.Name())
client := test.NewSonataFlowClientBuilder().
WithRuntimeObjects(workflow).
diff --git a/controllers/profiles/preview/object_creators_preview.go
b/controllers/profiles/preview/object_creators_preview.go
index 903cd741..a48a4e5d 100644
--- a/controllers/profiles/preview/object_creators_preview.go
+++ b/controllers/profiles/preview/object_creators_preview.go
@@ -24,6 +24,7 @@ import (
appsv1 "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
+ servingv1 "knative.dev/serving/pkg/apis/serving/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
@@ -64,28 +65,40 @@ func
addOpenShiftImageTriggerDeploymentMutateVisitor(workflow *v1alpha08.SonataF
}
}
-// mountDevConfigMapsMutateVisitor mounts the required configMaps in the
Workflow Dev Deployment
-func mountProdConfigMapsMutateVisitor(workflow *operatorapi.SonataFlow,
userPropsCM *v1.ConfigMap, managedPropsCM *v1.ConfigMap) common.MutateVisitor {
+// mountConfigMapsMutateVisitor mounts the required configMaps in the
SonataFlow instance
+func mountConfigMapsMutateVisitor(workflow *operatorapi.SonataFlow,
userPropsCM *v1.ConfigMap, managedPropsCM *v1.ConfigMap) common.MutateVisitor {
return func(object client.Object) controllerutil.MutateFn {
return func() error {
- deployment := object.(*appsv1.Deployment)
- _, idx :=
kubeutil.GetContainerByName(v1alpha08.DefaultContainerName,
&deployment.Spec.Template.Spec)
+ var podTemplateSpec *v1.PodSpec
- if len(deployment.Spec.Template.Spec.Volumes) == 0 {
- deployment.Spec.Template.Spec.Volumes =
make([]v1.Volume, 0, 1)
+ if workflow.IsKnativeDeployment() {
+ ksvc := object.(*servingv1.Service)
+ podTemplateSpec =
&ksvc.Spec.Template.Spec.PodSpec
+ } else {
+ deployment := object.(*appsv1.Deployment)
+ podTemplateSpec = &deployment.Spec.Template.Spec
+ if err :=
kubeutil.AnnotateDeploymentConfigChecksum(workflow, deployment, userPropsCM,
managedPropsCM); err != nil {
+ return err
+ }
}
- if
len(deployment.Spec.Template.Spec.Containers[idx].VolumeMounts) == 0 {
-
deployment.Spec.Template.Spec.Containers[idx].VolumeMounts =
make([]v1.VolumeMount, 0, 1)
+
+ _, idx :=
kubeutil.GetContainerByName(v1alpha08.DefaultContainerName, podTemplateSpec)
+
+ if len(podTemplateSpec.Volumes) == 0 {
+ podTemplateSpec.Volumes = make([]v1.Volume, 0,
1)
+ }
+ if len(podTemplateSpec.Containers[idx].VolumeMounts) ==
0 {
+ podTemplateSpec.Containers[idx].VolumeMounts =
make([]v1.VolumeMount, 0, 1)
}
defaultResourcesVolume := v1.Volume{Name:
constants.ConfigMapWorkflowPropsVolumeName, VolumeSource:
v1.VolumeSource{Projected: &v1.ProjectedVolumeSource{}}}
kubeutil.VolumeProjectionAddConfigMap(defaultResourcesVolume.Projected,
userPropsCM.Name, v1.KeyToPath{Key: workflowproj.ApplicationPropertiesFileName,
Path: workflowproj.ApplicationPropertiesFileName})
kubeutil.VolumeProjectionAddConfigMap(defaultResourcesVolume.Projected,
managedPropsCM.Name, v1.KeyToPath{Key:
workflowproj.GetManagedPropertiesFileName(workflow), Path:
workflowproj.GetManagedPropertiesFileName(workflow)})
-
kubeutil.AddOrReplaceVolume(&deployment.Spec.Template.Spec,
defaultResourcesVolume)
- kubeutil.AddOrReplaceVolumeMount(idx,
&deployment.Spec.Template.Spec,
+ kubeutil.AddOrReplaceVolume(podTemplateSpec,
defaultResourcesVolume)
+ kubeutil.AddOrReplaceVolumeMount(idx, podTemplateSpec,
kubeutil.VolumeMount(constants.ConfigMapWorkflowPropsVolumeName, true,
quarkusProdConfigMountPath))
- return
kubeutil.AnnotateDeploymentConfigChecksum(workflow, deployment, userPropsCM,
managedPropsCM)
+ return nil
}
}
}
diff --git a/controllers/profiles/preview/profile_preview.go
b/controllers/profiles/preview/profile_preview.go
index a4afea9b..1a0dda49 100644
--- a/controllers/profiles/preview/profile_preview.go
+++ b/controllers/profiles/preview/profile_preview.go
@@ -23,6 +23,7 @@ import (
"time"
"github.com/apache/incubator-kie-kogito-serverless-operator/api/metadata"
+
"github.com/apache/incubator-kie-kogito-serverless-operator/api/v1alpha08"
"k8s.io/client-go/rest"
"github.com/apache/incubator-kie-kogito-serverless-operator/controllers/discovery"
@@ -48,20 +49,42 @@ const (
quarkusProdConfigMountPath = "/deployments/config"
)
-// ObjectEnsurers is a struct for the objects that ReconciliationState needs
to create in the platform for the Production profile.
+// ObjectEnsurers is a struct for the objects that ReconciliationState needs
to create in the platform for the preview profile.
// 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.ObjectEnsurerWithPlatform
+ // deployment for this ensurer. Don't call it directly, use
DeploymentByDeploymentModel instead
+ deployment common.ObjectEnsurerWithPlatform
+ // kservice Knative Serving deployment for this ensurer. Don't call it
directly, use DeploymentByDeploymentModel instead
+ kservice common.ObjectEnsurerWithPlatform
+ // service for this ensurer. Don't call it directly, use
ServiceByDeploymentModel instead
service common.ObjectEnsurer
userPropsConfigMap common.ObjectEnsurer
managedPropsConfigMap common.ObjectEnsurerWithPlatform
}
+// DeploymentByDeploymentModel gets the deployment ensurer based on the
SonataFlow deployment model
+func (o *ObjectEnsurers) DeploymentByDeploymentModel(workflow
*v1alpha08.SonataFlow) common.ObjectEnsurerWithPlatform {
+ if workflow.IsKnativeDeployment() {
+ return o.kservice
+ }
+ return o.deployment
+}
+
+// ServiceByDeploymentModel gets the service ensurer based on the SonataFlow
deployment model
+func (o *ObjectEnsurers) ServiceByDeploymentModel(workflow
*v1alpha08.SonataFlow) common.ObjectEnsurer {
+ if workflow.IsKnativeDeployment() {
+ // Knative Serving handles the service
+ return common.NewNoopObjectEnsurer()
+ }
+ return o.service
+}
+
// NewObjectEnsurers common.ObjectEnsurer(s) for the preview profile.
func NewObjectEnsurers(support *common.StateSupport) *ObjectEnsurers {
return &ObjectEnsurers{
deployment:
common.NewObjectEnsurerWithPlatform(support.C, common.DeploymentCreator),
+ kservice:
common.NewObjectEnsurerWithPlatform(support.C, common.KServiceCreator),
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/preview/profile_preview_test.go
b/controllers/profiles/preview/profile_preview_test.go
index cc518db0..22146ccf 100644
--- a/controllers/profiles/preview/profile_preview_test.go
+++ b/controllers/profiles/preview/profile_preview_test.go
@@ -198,5 +198,6 @@ func fakeReconcilerSupport(client clientruntime.Client)
*common.StateSupport {
return &common.StateSupport{
C: client,
Recorder: test.NewFakeRecorder(),
+ Cfg: &rest.Config{},
}
}
diff --git a/controllers/profiles/preview/states_preview.go
b/controllers/profiles/preview/states_preview.go
index 933820e8..4612c84d 100644
--- a/controllers/profiles/preview/states_preview.go
+++ b/controllers/profiles/preview/states_preview.go
@@ -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, build.Status.ImageTag)
+ return NewDeploymentReconciler(h.StateSupport,
h.ensurers).reconcileWithImage(ctx, workflow, build.Status.ImageTag)
}
func (h *deployWithBuildWorkflowState) PostReconcile(ctx context.Context,
workflow *operatorapi.SonataFlow) error {
diff --git a/controllers/sonataflow_controller.go
b/controllers/sonataflow_controller.go
index 447e386f..7c1d28ab 100644
--- a/controllers/sonataflow_controller.go
+++ b/controllers/sonataflow_controller.go
@@ -23,6 +23,7 @@ import (
"context"
"fmt"
+
"github.com/apache/incubator-kie-kogito-serverless-operator/api/metadata"
"k8s.io/klog/v2"
profiles
"github.com/apache/incubator-kie-kogito-serverless-operator/controllers/profiles/factory"
@@ -89,6 +90,8 @@ func (r *SonataFlowReconciler) Reconcile(ctx context.Context,
req ctrl.Request)
return ctrl.Result{}, err
}
+ r.setDefaults(workflow)
+
// Only process resources assigned to the operator
if !platform.IsOperatorHandlerConsideringLock(ctx, r.Client,
req.Namespace, workflow) {
klog.V(log.I).InfoS("Ignoring request because resource is not
assigned to current operator")
@@ -97,6 +100,18 @@ func (r *SonataFlowReconciler) Reconcile(ctx
context.Context, req ctrl.Request)
return profiles.NewReconciler(r.Client, r.Config, r.Recorder,
workflow).Reconcile(ctx, workflow)
}
+// TODO: move to webhook see
https://github.com/apache/incubator-kie-kogito-serverless-operator/pull/239
+func (r *SonataFlowReconciler) setDefaults(workflow *operatorapi.SonataFlow) {
+ if workflow.Annotations == nil {
+ workflow.Annotations = map[string]string{}
+ }
+ profile := metadata.GetProfileOrDefault(workflow.Annotations)
+ workflow.Annotations[metadata.Profile] = string(profile)
+ if profile == metadata.DevProfile {
+ workflow.Spec.PodTemplate.DeploymentModel =
operatorapi.KubernetesDeploymentModel
+ }
+}
+
func platformEnqueueRequestsFromMapFunc(c client.Client, p
*operatorapi.SonataFlowPlatform) []reconcile.Request {
var requests []reconcile.Request
diff --git a/hack/local/run-operator.sh b/hack/local/run-operator.sh
index 5cb8a73c..8b57477c 100755
--- a/hack/local/run-operator.sh
+++ b/hack/local/run-operator.sh
@@ -17,6 +17,9 @@
# under the License.
# Runs the operator locally via go main
+POD_NAMESPACE=$(kubectl config view --minify | grep namespace | cut -d" " -f6)
+
+export POD_NAMESPACE
kubectl delete --ignore-not-found=true -f
./bundle/manifests/sonataflow.org_sonataflowclusterplatforms.yaml
kubectl delete --ignore-not-found=true -f
./bundle/manifests/sonataflow.org_sonataflowplatforms.yaml
diff --git a/main.go b/main.go
index 535a3ed0..e0265ed6 100644
--- a/main.go
+++ b/main.go
@@ -26,6 +26,7 @@ import (
"github.com/apache/incubator-kie-kogito-serverless-operator/controllers/cfg"
eventingv1 "knative.dev/eventing/pkg/apis/eventing/v1"
sourcesv1 "knative.dev/eventing/pkg/apis/sources/v1"
+ servingv1 "knative.dev/serving/pkg/apis/serving/v1"
"k8s.io/klog/v2/klogr"
@@ -60,6 +61,7 @@ func init() {
utilruntime.Must(operatorapi.AddToScheme(scheme))
utilruntime.Must(sourcesv1.AddToScheme(scheme))
utilruntime.Must(eventingv1.AddToScheme(scheme))
+ utilruntime.Must(servingv1.AddToScheme(scheme))
//+kubebuilder:scaffold:scheme
}
diff --git a/operator.yaml b/operator.yaml
index 14dfec14..f2ef7178 100644
--- a/operator.yaml
+++ b/operator.yaml
@@ -22523,6 +22523,13 @@ spec:
- name
type: object
type: array
+ deploymentModel:
+ description: Defines the kind of deployment model for this
pod
+ spec. In dev profile, only "kubernetes" is valid.
+ enum:
+ - kubernetes
+ - knative
+ type: string
dnsConfig:
description: Specifies the DNS parameters of a pod.
Parameters
specified here will be merged to the generated DNS
configuration
@@ -24050,6 +24057,8 @@ spec:
type: object
type: array
replicas:
+ description: Replicas define the number of pods to start
by default
+ for this deployment model. Ignored in "knative"
deployment model.
format: int32
type: integer
resourceClaims:
@@ -26492,6 +26501,12 @@ rules:
- patch
- update
- watch
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: sonataflow-operator-knative-manager-role
+rules:
- apiGroups:
- eventing.knative.dev
resources:
@@ -26522,6 +26537,22 @@ rules:
- patch
- update
- watch
+- apiGroups:
+ - serving.knative.dev
+ resources:
+ - service
+ - services
+ - services/status
+ - services/finalizers
+ verbs:
+ - create
+ - delete
+ - deletecollection
+ - get
+ - list
+ - patch
+ - update
+ - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
@@ -26864,6 +26895,19 @@ subjects:
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
+metadata:
+ name: sonataflow-operator-knative-manager-rolebinding
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: sonataflow-operator-knative-manager-role
+subjects:
+- kind: ServiceAccount
+ name: sonataflow-operator-controller-manager
+ namespace: sonataflow-operator-system
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
metadata:
name: sonataflow-operator-leases-binding
roleRef:
diff --git a/test/kubernetes_cli.go b/test/kubernetes_cli.go
index c4d7021f..72029fd1 100644
--- a/test/kubernetes_cli.go
+++ b/test/kubernetes_cli.go
@@ -33,6 +33,7 @@ import (
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/tools/record"
+ servingv1 "knative.dev/serving/pkg/apis/serving/v1"
ctrl "sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
@@ -50,6 +51,13 @@ func NewSonataFlowClientBuilder() *fake.ClientBuilder {
return fake.NewClientBuilder().WithScheme(s)
}
+func NewSonataFlowClientBuilderWithKnative() *fake.ClientBuilder {
+ s := scheme.Scheme
+ utilruntime.Must(operatorapi.AddToScheme(s))
+ utilruntime.Must(servingv1.AddToScheme(s))
+ return fake.NewClientBuilder().WithScheme(s)
+}
+
// NewKogitoClientBuilderWithOpenShift creates a new fake client with
OpenShift schemas.
// If your object is not present, just add in the list below.
func NewKogitoClientBuilderWithOpenShift() *fake.ClientBuilder {
diff --git a/test/yaml.go b/test/yaml.go
index 84ac1b7d..fd96943b 100644
--- a/test/yaml.go
+++ b/test/yaml.go
@@ -215,8 +215,8 @@ func GetBaseSonataFlowWithProdProfile(namespace string)
*operatorapi.SonataFlow
return NewSonataFlow(sonataFlowSampleYamlCR, namespace,
SetPreviewProfile)
}
-// GetBaseSonataFlowWithProdOpsProfile gets a base workflow that has a
pre-built image set in podTemplate.
-func GetBaseSonataFlowWithProdOpsProfile(namespace string)
*operatorapi.SonataFlow {
+// GetBaseSonataFlowWithPreviewProfile gets a base workflow that has a
pre-built image set in podTemplate.
+func GetBaseSonataFlowWithPreviewProfile(namespace string)
*operatorapi.SonataFlow {
return NewSonataFlow(SonataFlowSimpleOpsYamlCR, namespace)
}
diff --git a/testbdd/go.mod b/testbdd/go.mod
index 5f0c0ed6..bea1546d 100644
--- a/testbdd/go.mod
+++ b/testbdd/go.mod
@@ -66,6 +66,7 @@ require (
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/gnostic v0.6.9 // indirect
github.com/google/go-cmp v0.6.0 // indirect
+ github.com/google/go-containerregistry v0.13.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/pprof v0.0.0-20230705174524-200ffdc848b8 // indirect
github.com/google/uuid v1.3.1 // indirect
@@ -89,6 +90,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 //
indirect
github.com/onsi/ginkgo/v2 v2.13.0 // indirect
+ github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/openshift/client-go v0.0.0-20230503144108-75015d2347cb //
indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 //
indirect
@@ -137,7 +139,9 @@ require (
k8s.io/klog/v2 v2.100.1 // indirect
k8s.io/kube-openapi v0.0.0-20230525220651-2546d827e515 // indirect
k8s.io/utils v0.0.0-20230711102312-30195339c3c7 // indirect
+ knative.dev/networking v0.0.0-20231017124814-2a7676e912b7 // indirect
knative.dev/pkg v0.0.0-20231023151236-29775d7c9e5c // indirect
+ knative.dev/serving v0.39.0 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.3.0 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
diff --git a/testbdd/go.sum b/testbdd/go.sum
index 2e0cf298..16617aed 100644
--- a/testbdd/go.sum
+++ b/testbdd/go.sum
@@ -460,6 +460,7 @@ github.com/google/go-cmp v0.5.4/go.mod
h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.5/go.mod
h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod
h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-containerregistry v0.13.0
h1:y1C7Z3e149OJbOPDBxLYR8ITPz8dTKqQwjErKVHJC8k=
github.com/google/go-github v17.0.0+incompatible/go.mod
h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-github/v27 v27.0.6/go.mod
h1:/0Gr8pJ55COkmv+S/yPKCczSkUPIM/LnFyubufRNIS0=
github.com/google/go-querystring v1.0.0/go.mod
h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
@@ -718,6 +719,7 @@ github.com/onsi/gomega v1.30.0
h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=
github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod
h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod
h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod
h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
+github.com/opencontainers/go-digest v1.0.0
h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/image-spec v1.0.0/go.mod
h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/image-spec v1.0.1/go.mod
h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod
h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
@@ -1566,10 +1568,12 @@ knative.dev/eventing v0.26.0
h1:osDUdav7S0FuChN0onfwL5cEcsdb54Kee2hjAPMpY7o=
knative.dev/eventing v0.26.0/go.mod
h1:6tTam0lsPtBSJHJ63/195obj2VAHlTZZB7TLiBSeqk0=
knative.dev/hack v0.0.0-20210806075220-815cd312d65c/go.mod
h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI=
knative.dev/hack/schema v0.0.0-20210806075220-815cd312d65c/go.mod
h1:ffjwmdcrH5vN3mPhO8RrF2KfNnbHeCE2C60A+2cv3U0=
+knative.dev/networking v0.0.0-20231017124814-2a7676e912b7
h1:6+1icZuxiZO1paFZ4d/ysKWVG2M4WB7OxNJNyLG0P/E=
knative.dev/pkg v0.0.0-20210914164111-4857ab6939e3/go.mod
h1:jMSqkNMsrzuy+XR4Yr/BMy7SDVbUOl3KKB6+5MR+ZU8=
knative.dev/pkg v0.0.0-20210919202233-5ae482141474/go.mod
h1:jMSqkNMsrzuy+XR4Yr/BMy7SDVbUOl3KKB6+5MR+ZU8=
knative.dev/pkg v0.0.0-20231023151236-29775d7c9e5c
h1:xyPoEToTWeBdn6tinhLxXfnhJhTNQt5WzHiTNiFphRw=
knative.dev/reconciler-test v0.0.0-20210915181908-49fac7555086/go.mod
h1:6yDmb26SINSmgw6wVy9qQwgRMewiW8ddkkwGLR0ZvOY=
+knative.dev/serving v0.39.0 h1:NVt8WthHmFFMWZ3qpBblXt47del8qqrbCegqwGBVSwk=
modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw=
modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
modernc.org/mathutil v1.0.0/go.mod
h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
diff --git a/utils/common.go b/utils/common.go
index e24e8691..073bb255 100644
--- a/utils/common.go
+++ b/utils/common.go
@@ -28,7 +28,11 @@ import (
)
const (
- HttpScheme = "http"
+ // DefaultServicePortName default service name to increase
compatibility with Knative
+ //
+ // see:
https://github.com/knative/specs/blob/main/specs/serving/runtime-contract.md#protocols-and-ports
+ // By default we do support
HTTP/2:https://quarkus.io/guides/http-reference#http2-support
+ DefaultServicePortName = "h2c"
)
// GetOperatorIDAnnotation to safely get the operator id annotation value.
diff --git a/workflowproj/workflowproj.go b/workflowproj/workflowproj.go
index bd8653d2..2bf1deba 100644
--- a/workflowproj/workflowproj.go
+++ b/workflowproj/workflowproj.go
@@ -304,9 +304,5 @@ func (w *workflowProjectHandler)
addResourceConfigMapToProject(cm *corev1.Config
// IsDevProfile detects if the workflow is using the Dev profile or not
func IsDevProfile(workflow *operatorapi.SonataFlow) bool {
- profile := workflow.Annotations[metadata.Profile]
- if len(profile) == 0 {
- return false
- }
- return metadata.ProfileType(profile) == metadata.DevProfile
+ return metadata.IsDevProfile(workflow.Annotations)
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]