This is an automated email from the ASF dual-hosted git repository. squakez pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel-k.git
commit adfd6b9e7945ba4d7e32b6a2b3d734eafec961d9 Author: harshilv17 <[email protected]> AuthorDate: Sat Sep 19 17:22:22 2026 +0530 feat(controller): drop support for deprecated Synthetic Integrations Synthetic Integrations were deprecated in 2.10.0 and gated behind the CAMEL_K_SYNTHETIC_INTEGRATIONS env var. Remove the feature and all the business logic that only existed to serve it. Removed: - pkg/controller/synthetic and the monitor_synthetic action - the CAMEL_K_SYNTHETIC_INTEGRATIONS lookup in the operator - IntegrationSyntheticLabel and Integration.IsSynthetic(), plus the seven trait guards and the syntheticActions reconciler wiring on top of it - the external application import path: the IntegrationImported* labels, initializeAction.importFromExternalApp, getCamelAppImportingCondition and the now orphaned IntegrationConditionImportingKindAvailableReason - trait.NewSyntheticEnvironment and getCamelAppObject, whose only caller was the synthetic monitor - the synthetic IntegrationKit type, already unreachable: nothing assigned IntegrationKitTypeSynthetic and lookupKitsForIntegration only ever selected platform and external Kits. Its branches in integrationkit monitor, error and controller collapse to IsExternal(), dropping three //nolint:staticcheck - docs/running/synthetic.adoc, its nav entry and the env var row The container trait image doc no longer calls the Kit it creates synthetic, since that Kit type no longer exists; CRDs, helm chart and docs regenerated. The Kit built from a user supplied image is untouched, it keys off kit.Spec.Image rather than the removed label. Fixes #6828 Signed-off-by: harshilv17 <[email protected]> --- docs/modules/ROOT/nav.adoc | 1 - .../ROOT/pages/installation/advanced/advanced.adoc | 4 - docs/modules/ROOT/pages/running/synthetic.adoc | 48 -- docs/modules/ROOT/partials/apis/camel-k-crds.adoc | 2 +- docs/modules/traits/pages/container.adoc | 2 +- helm/camel-k/crds/camel-k-crds.yaml | 16 +- pkg/apis/camel/v1/integration_types.go | 2 - pkg/apis/camel/v1/integration_types_support.go | 11 - pkg/apis/camel/v1/integrationkit_types.go | 5 - pkg/apis/camel/v1/integrationkit_types_support.go | 7 - pkg/apis/camel/v1/trait/container.go | 2 +- pkg/cmd/operator/operator.go | 7 - pkg/controller/integration/initialize.go | 87 ---- pkg/controller/integration/initialize_test.go | 190 -------- .../integration/integration_controller.go | 25 +- .../integration/integration_controller_test.go | 35 +- pkg/controller/integration/monitor_synthetic.go | 71 --- .../integration/monitor_synthetic_test.go | 529 --------------------- pkg/controller/integrationkit/error.go | 3 +- pkg/controller/integrationkit/initialize.go | 4 +- .../integrationkit/integrationkit_controller.go | 3 +- pkg/controller/integrationkit/monitor.go | 15 +- pkg/controller/synthetic/synthetic.go | 319 ------------- pkg/controller/synthetic/synthetic_test.go | 251 ---------- .../camel.apache.org_integrationplatforms.yaml | 4 +- .../camel.apache.org_integrationprofiles.yaml | 4 +- .../crd/bases/camel.apache.org_integrations.yaml | 4 +- .../config/crd/bases/camel.apache.org_pipes.yaml | 4 +- pkg/trait/camel.go | 15 +- pkg/trait/camel_test.go | 15 - pkg/trait/cron.go | 3 - pkg/trait/environment.go | 3 - pkg/trait/jvm.go | 10 +- pkg/trait/mount.go | 3 - pkg/trait/security_context.go | 3 - pkg/trait/trait.go | 69 --- 36 files changed, 48 insertions(+), 1728 deletions(-) diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index 41b724357..cd7b701f4 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -24,7 +24,6 @@ ** xref:running/build-from-git.adoc[Git hosted Integrations] ** xref:running/gitops.adoc[GitOps] ** xref:running/self-managed.adoc[Self managed Integrations] -** xref:running/synthetic.adoc[Synthetic Integrations] ** xref:running/promoting.adoc[kamel promote CLI] ** xref:running/dry-build.adoc[Dry build] * xref:pipes/pipes.adoc[Run an Pipe] diff --git a/docs/modules/ROOT/pages/installation/advanced/advanced.adoc b/docs/modules/ROOT/pages/installation/advanced/advanced.adoc index 76d53f234..c8503861f 100644 --- a/docs/modules/ROOT/pages/installation/advanced/advanced.adoc +++ b/docs/modules/ROOT/pages/installation/advanced/advanced.adoc @@ -61,10 +61,6 @@ The following environment variables can be configured on the operator Deployment |`eclipse-temurin:17-jdk@sha256:<digest>` |The base image used for building Integration images. Can also be set via `RELATED_IMAGE_BASE`. -|`CAMEL_K_SYNTHETIC_INTEGRATIONS` -|`false` -|When set to `true`, enables synthetic Integration support for managing external workloads. - |`CAMEL_MONITOR_OPERATOR_LABEL` |`camel.apache.org/monitor` |If it exists, the operator add this label beside regular Camel K labels in order to let the Camel Monitor operator discover and monitor the application. diff --git a/docs/modules/ROOT/pages/running/synthetic.adoc b/docs/modules/ROOT/pages/running/synthetic.adoc deleted file mode 100644 index f16a56b9b..000000000 --- a/docs/modules/ROOT/pages/running/synthetic.adoc +++ /dev/null @@ -1,48 +0,0 @@ -= Synthetic Integrations - -WARNING: the feature is deprecated and replaced by https://camel-tooling.github.io/camel-dashboard/docs/[Camel Dashboard monitoring] instead, see the new project official documentation. - -You may have already a Camel application running on your cluster. You may have created it via a manual deployment, a CICD or any other deployment mechanism you have in place. Since the Camel K operator is meant to operate any Camel application out there, then, you will be able to import it and monitor in a similar fashion of any other Camel K **managed Integration**. These Integrations are known as **Synthetic Integrations** - -== Importing existing Camel applications - -This feature is disabled by default. In order to enable it, you need to run the operator deployment with an environment variable, `CAMEL_K_SYNTHETIC_INTEGRATIONS`, set to `true`. - -NOTE: you will be only able to monitor the synthetic Integrations. Camel K won't be able to alter the lifecycle of non managed Integrations (ie, rebuild the original application). - -It's important to notice that the operator won't be altering any field of the original application in order to avoid breaking any deployment procedure which is already in place. As it cannot make any assumption on the way the application is built and deployed, it will only be able to **watch** for any changes happening around it. - -[[deploy-and-monitor]] -== Deploy externally, monitor via Camel K Operator - -An imported Integration is known as **synthetic Integration**. You can import any Camel application deployed as a **Deployment**, **CronJob** or **Knative Service**. We control this behavior via a label (`camel.apache.org/integration`) that the user need to apply on the Camel application (either manually or introducing in the deployment process, ie, via CICD). - -NOTE: the example here will work in a similar way using CronJob and Knative Service. - -As an example, we show how to import a Camel application which was deployed with the Deployment kind. Let's assume it is called `my-deploy`. -``` -$ kubectl label deploy my-camel-sb-svc camel.apache.org/integration=my-it -``` -The operator immediately creates a synthetic Integration: -``` -$ kubectl get it -NAMESPACE NAME PHASE RUNTIME PROVIDER RUNTIME VERSION KIT REPLICAS -test-79c385c3-d58e-4c28-826d-b14b6245f908 my-it Running -``` -You can see it will be in `Running` status phase. However, checking the conditions you will be able to see that the Integration is not yet able to be fully monitored. This is expected because the way Camel K operator monitor Pods. It requires that the same label applied to the Deployment is inherited by the generated Pods. For this reason, beside labelling the Deployment, we need to add a label in the Deployment template. -``` -$ kubectl patch deployment my-camel-sb-svc --patch '{"spec": {"template": {"metadata": {"labels": {"camel.apache.org/integration": "my-it"}}}}}' -``` -Also this operation can be performed manually or automated in the deployment procedure. We can see now that the operator will be able to monitor accordingly the status of the Pods: -``` -$ kubectl get it -NAMESPACE NAME PHASE RUNTIME PROVIDER RUNTIME VERSION KIT REPLICAS -test-79c385c3-d58e-4c28-826d-b14b6245f908 my-it Running 1 -``` -From now on, you will be able to monitor the status of the synthetic Integration in a similar fashion of what you do with managed Integrations. If, for example, your Deployment will scale up or down, then, you will see this information reflecting accordingly: -``` -$ kubectl scale deployment my-camel-sb-svc --replicas 2 -$ kubectl get it -NAMESPACE NAME PHASE RUNTIME PROVIDER RUNTIME VERSION KIT REPLICAS -test-79c385c3-d58e-4c28-826d-b14b6245f908 my-it Running 2 -``` diff --git a/docs/modules/ROOT/partials/apis/camel-k-crds.adoc b/docs/modules/ROOT/partials/apis/camel-k-crds.adoc index c71a1fa3c..087e47370 100644 --- a/docs/modules/ROOT/partials/apis/camel-k-crds.adoc +++ b/docs/modules/ROOT/partials/apis/camel-k-crds.adoc @@ -6977,7 +6977,7 @@ string | -The main container image to use for the Integration. When using this parameter the operator will create a synthetic IntegrationKit which +The main container image to use for the Integration. When using this parameter the operator will create an IntegrationKit which won't be able to execute traits requiring CamelCatalog. If the container image you're using is coming from an IntegrationKit, use instead Integration `.spec.integrationKit` parameter. If you're moving the Integration across environments, you will also need to create an "external" IntegrationKit. diff --git a/docs/modules/traits/pages/container.adoc b/docs/modules/traits/pages/container.adoc index ed2ba4847..4e9f910b0 100755 --- a/docs/modules/traits/pages/container.adoc +++ b/docs/modules/traits/pages/container.adoc @@ -85,7 +85,7 @@ It defaults to `http` only when the `expose` parameter is true. | container.image | string -| The main container image to use for the Integration. When using this parameter the operator will create a synthetic IntegrationKit which +| The main container image to use for the Integration. When using this parameter the operator will create an IntegrationKit which won't be able to execute traits requiring CamelCatalog. If the container image you're using is coming from an IntegrationKit, use instead Integration `.spec.integrationKit` parameter. If you're moving the Integration across environments, you will also need to create an "external" IntegrationKit. diff --git a/helm/camel-k/crds/camel-k-crds.yaml b/helm/camel-k/crds/camel-k-crds.yaml index f2d2b8cd8..8b9adc18a 100644 --- a/helm/camel-k/crds/camel-k-crds.yaml +++ b/helm/camel-k/crds/camel-k-crds.yaml @@ -4102,7 +4102,7 @@ spec: type: boolean image: description: |- - The main container image to use for the Integration. When using this parameter the operator will create a synthetic IntegrationKit which + The main container image to use for the Integration. When using this parameter the operator will create an IntegrationKit which won't be able to execute traits requiring CamelCatalog. If the container image you're using is coming from an IntegrationKit, use instead Integration `.spec.integrationKit` parameter. If you're moving the Integration across environments, you will also need to create an "external" IntegrationKit. type: string @@ -6673,7 +6673,7 @@ spec: type: boolean image: description: |- - The main container image to use for the Integration. When using this parameter the operator will create a synthetic IntegrationKit which + The main container image to use for the Integration. When using this parameter the operator will create an IntegrationKit which won't be able to execute traits requiring CamelCatalog. If the container image you're using is coming from an IntegrationKit, use instead Integration `.spec.integrationKit` parameter. If you're moving the Integration across environments, you will also need to create an "external" IntegrationKit. type: string @@ -9205,7 +9205,7 @@ spec: type: boolean image: description: |- - The main container image to use for the Integration. When using this parameter the operator will create a synthetic IntegrationKit which + The main container image to use for the Integration. When using this parameter the operator will create an IntegrationKit which won't be able to execute traits requiring CamelCatalog. If the container image you're using is coming from an IntegrationKit, use instead Integration `.spec.integrationKit` parameter. If you're moving the Integration across environments, you will also need to create an "external" IntegrationKit. type: string @@ -11725,7 +11725,7 @@ spec: type: boolean image: description: |- - The main container image to use for the Integration. When using this parameter the operator will create a synthetic IntegrationKit which + The main container image to use for the Integration. When using this parameter the operator will create an IntegrationKit which won't be able to execute traits requiring CamelCatalog. If the container image you're using is coming from an IntegrationKit, use instead Integration `.spec.integrationKit` parameter. If you're moving the Integration across environments, you will also need to create an "external" IntegrationKit. type: string @@ -21307,7 +21307,7 @@ spec: type: boolean image: description: |- - The main container image to use for the Integration. When using this parameter the operator will create a synthetic IntegrationKit which + The main container image to use for the Integration. When using this parameter the operator will create an IntegrationKit which won't be able to execute traits requiring CamelCatalog. If the container image you're using is coming from an IntegrationKit, use instead Integration `.spec.integrationKit` parameter. If you're moving the Integration across environments, you will also need to create an "external" IntegrationKit. type: string @@ -23715,7 +23715,7 @@ spec: type: boolean image: description: |- - The main container image to use for the Integration. When using this parameter the operator will create a synthetic IntegrationKit which + The main container image to use for the Integration. When using this parameter the operator will create an IntegrationKit which won't be able to execute traits requiring CamelCatalog. If the container image you're using is coming from an IntegrationKit, use instead Integration `.spec.integrationKit` parameter. If you're moving the Integration across environments, you will also need to create an "external" IntegrationKit. type: string @@ -34660,7 +34660,7 @@ spec: type: boolean image: description: |- - The main container image to use for the Integration. When using this parameter the operator will create a synthetic IntegrationKit which + The main container image to use for the Integration. When using this parameter the operator will create an IntegrationKit which won't be able to execute traits requiring CamelCatalog. If the container image you're using is coming from an IntegrationKit, use instead Integration `.spec.integrationKit` parameter. If you're moving the Integration across environments, you will also need to create an "external" IntegrationKit. type: string @@ -36990,7 +36990,7 @@ spec: type: boolean image: description: |- - The main container image to use for the Integration. When using this parameter the operator will create a synthetic IntegrationKit which + The main container image to use for the Integration. When using this parameter the operator will create an IntegrationKit which won't be able to execute traits requiring CamelCatalog. If the container image you're using is coming from an IntegrationKit, use instead Integration `.spec.integrationKit` parameter. If you're moving the Integration across environments, you will also need to create an "external" IntegrationKit. type: string diff --git a/pkg/apis/camel/v1/integration_types.go b/pkg/apis/camel/v1/integration_types.go index a2b98c423..a57720fdc 100644 --- a/pkg/apis/camel/v1/integration_types.go +++ b/pkg/apis/camel/v1/integration_types.go @@ -281,8 +281,6 @@ const ( IntegrationConditionKameletsAvailableReason string = "KameletsAvailable" // IntegrationConditionKameletsNotAvailableReason --. IntegrationConditionKameletsNotAvailableReason string = "KameletsNotAvailable" - // IntegrationConditionImportingKindAvailableReason used (as false) if we're trying to import an unsupported kind. - IntegrationConditionImportingKindAvailableReason string = "ImportingKindAvailable" ) // IntegrationCondition describes the state of a resource at a certain point. diff --git a/pkg/apis/camel/v1/integration_types_support.go b/pkg/apis/camel/v1/integration_types_support.go index edab20269..601670e92 100644 --- a/pkg/apis/camel/v1/integration_types_support.go +++ b/pkg/apis/camel/v1/integration_types_support.go @@ -37,12 +37,6 @@ const ( IntegrationLabel = "camel.apache.org/integration" // IntegrationGenerationLabel is used to check on outdated integration resources that can be removed by garbage collection. IntegrationGenerationLabel = "camel.apache.org/generation" - // IntegrationSyntheticLabel is used to tag k8s synthetic Integrations. - IntegrationSyntheticLabel = "camel.apache.org/is-synthetic" - // IntegrationImportedKindLabel specifies from what kind of resource an Integration was imported. - IntegrationImportedKindLabel = "camel.apache.org/imported-from-kind" - // IntegrationImportedNameLabel specifies from what resource an Integration was imported. - IntegrationImportedNameLabel = "camel.apache.org/imported-from-name" // IntegrationFlowEmbeddedSourceName --. IntegrationFlowEmbeddedSourceName = "camel-k-embedded-flow.yaml" @@ -352,11 +346,6 @@ func (in *Integration) SetReadyConditionError(err string) { in.SetReadyCondition(corev1.ConditionFalse, IntegrationConditionErrorReason, err) } -// IsSynthetic returns true for synthetic Integrations (non managed, likely imported from external deployments). -func (in *Integration) IsSynthetic() bool { - return in.Annotations[IntegrationSyntheticLabel] == "true" -} - // SetBuildCompletePhase set the proper building phase and the related timestamps. func (in *Integration) SetBuildCompletePhase() { now := metav1.Now().Rfc3339Copy() diff --git a/pkg/apis/camel/v1/integrationkit_types.go b/pkg/apis/camel/v1/integrationkit_types.go index 6407ff219..49f549b33 100644 --- a/pkg/apis/camel/v1/integrationkit_types.go +++ b/pkg/apis/camel/v1/integrationkit_types.go @@ -160,11 +160,6 @@ const ( IntegrationKitTypeUser = "user" // IntegrationKitTypeExternal identifies a Kit created by any third party. IntegrationKitTypeExternal = "external" - // IntegrationKitTypeSynthetic identifies a synthetic Kit (generated for any container image for which the operator cannot make any assumption). - // - // Deprecated: synthetic Integration Kits are replaced by non managed build Integrations. - IntegrationKitTypeSynthetic = "synthetic" - // IntegrationKitLayoutLabel labels the kit layout. IntegrationKitLayoutLabel = "camel.apache.org/kit.layout" diff --git a/pkg/apis/camel/v1/integrationkit_types_support.go b/pkg/apis/camel/v1/integrationkit_types_support.go index fcae6dfb5..9d790e74f 100644 --- a/pkg/apis/camel/v1/integrationkit_types_support.go +++ b/pkg/apis/camel/v1/integrationkit_types_support.go @@ -110,13 +110,6 @@ func (in *IntegrationKit) IsExternal() bool { return in.Labels[IntegrationKitTypeLabel] == IntegrationKitTypeExternal } -// IsSynthetic returns true for synthetic IntegrationKits. -// -// Deprecated: synthetic Integration Kits are replaced by syntentic Integrations. -func (in *IntegrationKit) IsSynthetic() bool { - return in.Labels[IntegrationKitTypeLabel] == IntegrationKitTypeSynthetic -} - // HasCapability returns true if the Kit is enabled with such a capability. func (in *IntegrationKit) HasCapability(capability string) bool { return slices.Contains(in.Spec.Capabilities, capability) diff --git a/pkg/apis/camel/v1/trait/container.go b/pkg/apis/camel/v1/trait/container.go index 2073840fb..3fd117213 100644 --- a/pkg/apis/camel/v1/trait/container.go +++ b/pkg/apis/camel/v1/trait/container.go @@ -57,7 +57,7 @@ type ContainerTrait struct { ServicePortName string `json:"servicePortName,omitempty" property:"service-port-name"` // The main container name. It's named `integration` by default. Name string `json:"name,omitempty" property:"name"` - // The main container image to use for the Integration. When using this parameter the operator will create a synthetic IntegrationKit which + // The main container image to use for the Integration. When using this parameter the operator will create an IntegrationKit which // won't be able to execute traits requiring CamelCatalog. If the container image you're using is coming from an IntegrationKit, use instead // Integration `.spec.integrationKit` parameter. If you're moving the Integration across environments, you will also need to create an "external" IntegrationKit. Image string `json:"image,omitempty" property:"image"` diff --git a/pkg/cmd/operator/operator.go b/pkg/cmd/operator/operator.go index 7a4804222..2d34ea496 100644 --- a/pkg/cmd/operator/operator.go +++ b/pkg/cmd/operator/operator.go @@ -58,7 +58,6 @@ import ( v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1" "github.com/apache/camel-k/v2/pkg/client" "github.com/apache/camel-k/v2/pkg/controller" - "github.com/apache/camel-k/v2/pkg/controller/synthetic" "github.com/apache/camel-k/v2/pkg/install" "github.com/apache/camel-k/v2/pkg/platform" "github.com/apache/camel-k/v2/pkg/util" @@ -240,12 +239,6 @@ func Run(healthPort, monitoringPort int32, leaderElection bool, leaderElectionID defer installCancel() install.OperatorStartupOptionalTools(installCtx, bootstrapClient, log) - synthEnvVal, synth := os.LookupEnv("CAMEL_K_SYNTHETIC_INTEGRATIONS") - if synth && synthEnvVal == "true" { - log.Info("Starting the synthetic Integration manager. " + - "WARNING: this is a deprecated feature and will be removed in future versions, use Camel Dashboard project instead.") - exitOnError(synthetic.ManageSyntheticIntegrations(ctx, ctrlClient, mgr.GetCache()), "synthetic Integration manager error") - } log.Info("Starting the manager") exitOnError(mgr.Start(ctx), "manager exited non-zero") } diff --git a/pkg/controller/integration/initialize.go b/pkg/controller/integration/initialize.go index a86b7ba0d..5c94cff1b 100644 --- a/pkg/controller/integration/initialize.go +++ b/pkg/controller/integration/initialize.go @@ -19,7 +19,6 @@ package integration import ( "context" - "fmt" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -53,10 +52,6 @@ func (action *initializeAction) CanHandle(integration *v1.Integration) bool { func (action *initializeAction) Handle(ctx context.Context, integration *v1.Integration) (*v1.Integration, error) { action.L.Info("Initializing Integration") - if integration.Annotations[v1.IntegrationImportedNameLabel] != "" { - return action.importFromExternalApp(integration) - } - // Only move to the build submitted when we're initializing, never on undeploying if integration.Status.Phase == v1.IntegrationPhaseInitialization && integration.Spec.Git != nil { integration.Status.Phase = v1.IntegrationPhaseBuildSubmitted @@ -110,85 +105,3 @@ func (action *initializeAction) lookupIntegrationKit(integration *v1.Integration return v1.NewIntegrationKit(kitNamespace, kitName) } - -func (action *initializeAction) importFromExternalApp(integration *v1.Integration) (*v1.Integration, error) { - readyMessage := fmt.Sprintf( - "imported from %s %s", - integration.Annotations[v1.IntegrationImportedNameLabel], - integration.Annotations[v1.IntegrationImportedKindLabel], - ) - // We need to set the condition for which this Integration is imported (required later by monitoring) - integration.Status.SetConditions( - getCamelAppImportingCondition( - integration.Annotations[v1.IntegrationImportedKindLabel], - readyMessage, - )..., - ) - // If it's ready, then we can safely assume the integration is running - if integration.IsConditionTrue(v1.IntegrationConditionReady) { - integration.Status.Phase = v1.IntegrationPhaseRunning - } else { - integration.Status.Phase = v1.IntegrationPhaseError - } - - return integration, nil -} - -func getCamelAppImportingCondition(kind, message string) []v1.IntegrationCondition { - switch kind { - case "Deployment": - return []v1.IntegrationCondition{ - { - Type: v1.IntegrationConditionDeploymentAvailable, - Status: corev1.ConditionTrue, - Reason: v1.IntegrationConditionDeploymentAvailableReason, - Message: message, - }, - { - Type: v1.IntegrationConditionReady, - Status: corev1.ConditionTrue, - Reason: v1.IntegrationConditionDeploymentReadyReason, - Message: message, - }, - } - case "CronJob": - return []v1.IntegrationCondition{ - { - Type: v1.IntegrationConditionCronJobAvailable, - Status: corev1.ConditionTrue, - Reason: v1.IntegrationConditionCronJobCreatedReason, - Message: message, - }, - { - Type: v1.IntegrationConditionReady, - Status: corev1.ConditionTrue, - Reason: v1.IntegrationConditionDeploymentReadyReason, - Message: message, - }, - } - case "KnativeService": - return []v1.IntegrationCondition{ - { - Type: v1.IntegrationConditionKnativeServiceAvailable, - Status: corev1.ConditionTrue, - Reason: v1.IntegrationConditionKnativeServiceAvailableReason, - Message: message, - }, - { - Type: v1.IntegrationConditionReady, - Status: corev1.ConditionTrue, - Reason: v1.IntegrationConditionKnativeServiceReadyReason, - Message: message, - }, - } - default: - return []v1.IntegrationCondition{ - { - Type: v1.IntegrationConditionReady, - Status: corev1.ConditionFalse, - Reason: v1.IntegrationConditionImportingKindAvailableReason, - Message: fmt.Sprintf("Unsupported %s import kind", kind), - }, - } - } -} diff --git a/pkg/controller/integration/initialize_test.go b/pkg/controller/integration/initialize_test.go deleted file mode 100644 index e956ae447..000000000 --- a/pkg/controller/integration/initialize_test.go +++ /dev/null @@ -1,190 +0,0 @@ -/* -Licensed to the Apache Software Foundation (ASF) under one or more -contributor license agreements. See the NOTICE file distributed with -this work for additional information regarding copyright ownership. -The ASF licenses this file to You under the Apache License, Version 2.0 -(the "License"); you may not use this file except in compliance with -the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package integration - -import ( - "context" - "testing" - - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1" - - "github.com/apache/camel-k/v2/pkg/util/log" - - "github.com/apache/camel-k/v2/pkg/internal" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestCamelImportDeployment(t *testing.T) { - importedIt := &v1.Integration{ - TypeMeta: metav1.TypeMeta{ - APIVersion: v1.SchemeGroupVersion.String(), - Kind: v1.IntegrationKind, - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "ns", - Name: "my-imported-it", - Annotations: map[string]string{ - v1.IntegrationImportedNameLabel: "my-deploy", - v1.IntegrationSyntheticLabel: "true", - v1.IntegrationImportedKindLabel: "Deployment", - }, - }, - Status: v1.IntegrationStatus{ - Phase: v1.IntegrationPhaseInitialization, - }, - } - c, err := internal.NewFakeClient(importedIt) - require.NoError(t, err) - - a := initializeAction{} - a.InjectLogger(log.Log) - a.InjectClient(c) - assert.Equal(t, "initialize", a.Name()) - assert.True(t, a.CanHandle(importedIt)) - handledIt, err := a.Handle(context.TODO(), importedIt) - require.NoError(t, err) - assert.Equal(t, v1.IntegrationPhaseRunning, handledIt.Status.Phase) - // Ready condition - assert.Equal(t, corev1.ConditionTrue, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Status) - assert.Equal(t, v1.IntegrationConditionDeploymentReadyReason, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Reason) - assert.Equal(t, "imported from my-deploy Deployment", handledIt.Status.GetCondition(v1.IntegrationConditionReady).Message) - // Deployment condition - assert.Equal(t, corev1.ConditionTrue, handledIt.Status.GetCondition(v1.IntegrationConditionDeploymentAvailable).Status) - assert.Equal(t, v1.IntegrationConditionDeploymentAvailableReason, handledIt.Status.GetCondition(v1.IntegrationConditionDeploymentAvailable).Reason) - assert.Equal(t, "imported from my-deploy Deployment", handledIt.Status.GetCondition(v1.IntegrationConditionDeploymentAvailable).Message) -} - -func TestCamelImportCronJob(t *testing.T) { - importedIt := &v1.Integration{ - TypeMeta: metav1.TypeMeta{ - APIVersion: v1.SchemeGroupVersion.String(), - Kind: v1.IntegrationKind, - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "ns", - Name: "my-imported-it", - Annotations: map[string]string{ - v1.IntegrationImportedNameLabel: "my-cron", - v1.IntegrationSyntheticLabel: "true", - v1.IntegrationImportedKindLabel: "CronJob", - }, - }, - Status: v1.IntegrationStatus{ - Phase: v1.IntegrationPhaseInitialization, - }, - } - c, err := internal.NewFakeClient(importedIt) - require.NoError(t, err) - - a := initializeAction{} - a.InjectLogger(log.Log) - a.InjectClient(c) - assert.Equal(t, "initialize", a.Name()) - assert.True(t, a.CanHandle(importedIt)) - handledIt, err := a.Handle(context.TODO(), importedIt) - require.NoError(t, err) - assert.Equal(t, v1.IntegrationPhaseRunning, handledIt.Status.Phase) - // Ready condition - assert.Equal(t, corev1.ConditionTrue, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Status) - assert.Equal(t, v1.IntegrationConditionDeploymentReadyReason, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Reason) - assert.Equal(t, "imported from my-cron CronJob", handledIt.Status.GetCondition(v1.IntegrationConditionReady).Message) - // CronJob condition - assert.Equal(t, corev1.ConditionTrue, handledIt.Status.GetCondition(v1.IntegrationConditionCronJobAvailable).Status) - assert.Equal(t, v1.IntegrationConditionCronJobCreatedReason, handledIt.Status.GetCondition(v1.IntegrationConditionCronJobAvailable).Reason) - assert.Equal(t, "imported from my-cron CronJob", handledIt.Status.GetCondition(v1.IntegrationConditionCronJobAvailable).Message) -} - -func TestCamelImportKnativeService(t *testing.T) { - importedIt := &v1.Integration{ - TypeMeta: metav1.TypeMeta{ - APIVersion: v1.SchemeGroupVersion.String(), - Kind: v1.IntegrationKind, - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "ns", - Name: "my-imported-it", - Annotations: map[string]string{ - v1.IntegrationImportedNameLabel: "my-ksvc", - v1.IntegrationSyntheticLabel: "true", - v1.IntegrationImportedKindLabel: "KnativeService", - }, - }, - Status: v1.IntegrationStatus{ - Phase: v1.IntegrationPhaseInitialization, - }, - } - c, err := internal.NewFakeClient(importedIt) - require.NoError(t, err) - - a := initializeAction{} - a.InjectLogger(log.Log) - a.InjectClient(c) - assert.Equal(t, "initialize", a.Name()) - assert.True(t, a.CanHandle(importedIt)) - handledIt, err := a.Handle(context.TODO(), importedIt) - require.NoError(t, err) - assert.Equal(t, v1.IntegrationPhaseRunning, handledIt.Status.Phase) - // Ready condition - assert.Equal(t, corev1.ConditionTrue, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Status) - assert.Equal(t, v1.IntegrationConditionKnativeServiceReadyReason, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Reason) - assert.Equal(t, "imported from my-ksvc KnativeService", handledIt.Status.GetCondition(v1.IntegrationConditionReady).Message) - // Knative Service condition - assert.Equal(t, corev1.ConditionTrue, handledIt.Status.GetCondition(v1.IntegrationConditionKnativeServiceAvailable).Status) - assert.Equal(t, v1.IntegrationConditionKnativeServiceAvailableReason, handledIt.Status.GetCondition(v1.IntegrationConditionKnativeServiceAvailable).Reason) - assert.Equal(t, "imported from my-ksvc KnativeService", handledIt.Status.GetCondition(v1.IntegrationConditionKnativeServiceAvailable).Message) -} - -func TestCamelImportUnsupportedKind(t *testing.T) { - importedIt := &v1.Integration{ - TypeMeta: metav1.TypeMeta{ - APIVersion: v1.SchemeGroupVersion.String(), - Kind: v1.IntegrationKind, - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "ns", - Name: "my-imported-it", - Annotations: map[string]string{ - v1.IntegrationImportedNameLabel: "my-kind", - v1.IntegrationSyntheticLabel: "true", - v1.IntegrationImportedKindLabel: "SomeKind", - }, - }, - Status: v1.IntegrationStatus{ - Phase: v1.IntegrationPhaseInitialization, - }, - } - c, err := internal.NewFakeClient(importedIt) - require.NoError(t, err) - - a := initializeAction{} - a.InjectLogger(log.Log) - a.InjectClient(c) - assert.Equal(t, "initialize", a.Name()) - assert.True(t, a.CanHandle(importedIt)) - handledIt, err := a.Handle(context.TODO(), importedIt) - require.NoError(t, err) - assert.Equal(t, v1.IntegrationPhaseError, handledIt.Status.Phase) - // Ready condition - assert.Equal(t, corev1.ConditionFalse, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Status) - assert.Equal(t, v1.IntegrationConditionImportingKindAvailableReason, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Reason) - assert.Equal(t, "Unsupported SomeKind import kind", handledIt.Status.GetCondition(v1.IntegrationConditionReady).Message) -} diff --git a/pkg/controller/integration/integration_controller.go b/pkg/controller/integration/integration_controller.go index ebb276c21..9da11fa18 100644 --- a/pkg/controller/integration/integration_controller.go +++ b/pkg/controller/integration/integration_controller.go @@ -79,11 +79,10 @@ func newReconciler(mgr manager.Manager, c client.Client) reconcile.Reconciler { return monitoring.NewInstrumentedReconciler( &reconcileIntegration{ - client: c, - scheme: mgr.GetScheme(), - recorder: mgr.GetEventRecorder("camel-k-integration-controller"), - syntheticActions: append(append([]Action{}, base...), NewMonitorSyntheticAction()), - baseActions: append(append([]Action{}, base...), NewMonitorAction()), + client: c, + scheme: mgr.GetScheme(), + recorder: mgr.GetEventRecorder("camel-k-integration-controller"), + baseActions: append(append([]Action{}, base...), NewMonitorAction()), }, schema.GroupVersionKind{ Group: v1.SchemeGroupVersion.Group, @@ -436,11 +435,10 @@ var _ reconcile.Reconciler = &reconcileIntegration{} type reconcileIntegration struct { // This client, initialized using mgr.Client() above, is a split client // that reads objects from the cache and writes to the API server - client client.Client - scheme *runtime.Scheme - recorder events.EventRecorder - syntheticActions []Action - baseActions []Action + client client.Client + scheme *runtime.Scheme + recorder events.EventRecorder + baseActions []Action } // Reconcile reads that state of the cluster for an Integration object and makes changes based on the state read @@ -485,12 +483,7 @@ func (r *reconcileIntegration) Reconcile(ctx context.Context, request reconcile. target := instance.DeepCopy() targetLog := rlog.ForIntegration(target) - actions := r.baseActions - if instance.IsSynthetic() { - actions = r.syntheticActions - } - - for _, a := range actions { + for _, a := range r.baseActions { a.InjectClient(r.client) a.InjectLogger(targetLog) diff --git a/pkg/controller/integration/integration_controller_test.go b/pkg/controller/integration/integration_controller_test.go index 307c31f6e..634686302 100644 --- a/pkg/controller/integration/integration_controller_test.go +++ b/pkg/controller/integration/integration_controller_test.go @@ -38,33 +38,18 @@ func TestActions(t *testing.T) { NewBuildCompleteAction(), } reconciler := reconcileIntegration{ - syntheticActions: append(append([]Action{}, base...), NewMonitorSyntheticAction()), - baseActions: append(append([]Action{}, base...), NewMonitorAction()), + baseActions: append(append([]Action{}, base...), NewMonitorAction()), } - t.Run("non-synthetic", func(t *testing.T) { - actions := reconciler.baseActions - require.Len(t, actions, 6) - - assert.IsType(t, &platformSetupAction{}, actions[0]) - assert.IsType(t, &initializeAction{}, actions[1]) - assert.IsType(t, &buildAction{}, actions[2]) - assert.IsType(t, &buildKitAction{}, actions[3]) - assert.IsType(t, &buildCompleteAction{}, actions[4]) - assert.IsType(t, &monitorAction{}, actions[5]) - }) - - t.Run("synthetic", func(t *testing.T) { - actions := reconciler.syntheticActions - require.Len(t, actions, 6) - - assert.IsType(t, &platformSetupAction{}, actions[0]) - assert.IsType(t, &initializeAction{}, actions[1]) - assert.IsType(t, &buildAction{}, actions[2]) - assert.IsType(t, &buildKitAction{}, actions[3]) - assert.IsType(t, &buildCompleteAction{}, actions[4]) - assert.IsType(t, &monitorSyntheticAction{}, actions[5]) - }) + actions := reconciler.baseActions + require.Len(t, actions, 6) + + assert.IsType(t, &platformSetupAction{}, actions[0]) + assert.IsType(t, &initializeAction{}, actions[1]) + assert.IsType(t, &buildAction{}, actions[2]) + assert.IsType(t, &buildKitAction{}, actions[3]) + assert.IsType(t, &buildCompleteAction{}, actions[4]) + assert.IsType(t, &monitorAction{}, actions[5]) } func TestIsIntegrationUpdated(t *testing.T) { diff --git a/pkg/controller/integration/monitor_synthetic.go b/pkg/controller/integration/monitor_synthetic.go deleted file mode 100644 index ee93c31ad..000000000 --- a/pkg/controller/integration/monitor_synthetic.go +++ /dev/null @@ -1,71 +0,0 @@ -/* -Licensed to the Apache Software Foundation (ASF) under one or more -contributor license agreements. See the NOTICE file distributed with -this work for additional information regarding copyright ownership. -The ASF licenses this file to You under the Apache License, Version 2.0 -(the "License"); you may not use this file except in compliance with -the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package integration - -import ( - "context" - - corev1 "k8s.io/api/core/v1" - - v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1" - "github.com/apache/camel-k/v2/pkg/trait" - k8serrors "k8s.io/apimachinery/pkg/api/errors" -) - -// NewMonitorSyntheticAction is an action used to monitor synthetic Integrations. -func NewMonitorSyntheticAction() Action { - return &monitorSyntheticAction{} -} - -type monitorSyntheticAction struct { - monitorAction -} - -func (action *monitorSyntheticAction) Name() string { - return "monitor-synthetic" -} - -func (action *monitorSyntheticAction) Handle(ctx context.Context, integration *v1.Integration) (*v1.Integration, error) { - environment, err := trait.NewSyntheticEnvironment(ctx, action.client, integration, nil) - if err != nil { - // Importing application no longer available - if k8serrors.IsNotFound(err) { - // Application was deleted. The GC will take care of - return nil, nil - } - // other reasons, likely some error to report - integration.Status.Phase = v1.IntegrationPhaseError - integration.SetReadyCondition(corev1.ConditionFalse, v1.IntegrationConditionImportingKindAvailableReason, err.Error()) - - return integration, err - } - - if environment == nil { - // The application which generated the Integration has no longer the importing label. We may have missed the - // delete event, therefore we need to perform the operation here. - err := action.client.Delete(ctx, integration) - action.L.Infof("Deleting synthetic Integration %s", integration.Name) - if err != nil { - return integration, err - } - - return nil, nil - } - - return action.monitorPods(ctx, environment, integration) -} diff --git a/pkg/controller/integration/monitor_synthetic_test.go b/pkg/controller/integration/monitor_synthetic_test.go deleted file mode 100644 index 7eaa6d88a..000000000 --- a/pkg/controller/integration/monitor_synthetic_test.go +++ /dev/null @@ -1,529 +0,0 @@ -/* -Licensed to the Apache Software Foundation (ASF) under one or more -contributor license agreements. See the NOTICE file distributed with -this work for additional information regarding copyright ownership. -The ASF licenses this file to You under the Apache License, Version 2.0 -(the "License"); you may not use this file except in compliance with -the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package integration - -import ( - "context" - "testing" - - appsv1 "k8s.io/api/apps/v1" - batchv1 "k8s.io/api/batch/v1" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/utils/ptr" - servingv1 "knative.dev/serving/pkg/apis/serving/v1" - - v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1" - "github.com/apache/camel-k/v2/pkg/apis/camel/v1/trait" - - "github.com/apache/camel-k/v2/pkg/util/log" - - "github.com/apache/camel-k/v2/pkg/internal" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "knative.dev/pkg/apis" - duckv1 "knative.dev/pkg/apis/duck/v1" -) - -func TestMonitorSyntheticIntegrationImportingKindUnavailable(t *testing.T) { - importedIt := &v1.Integration{ - TypeMeta: metav1.TypeMeta{ - APIVersion: v1.SchemeGroupVersion.String(), - Kind: v1.IntegrationKind, - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "ns", - Name: "my-imported-it", - Annotations: map[string]string{ - v1.IntegrationImportedNameLabel: "my-deploy", - v1.IntegrationSyntheticLabel: "true", - v1.IntegrationImportedKindLabel: "SomeKind", - }, - }, - Spec: v1.IntegrationSpec{ - Traits: v1.Traits{ - Health: &trait.HealthTrait{ - Trait: trait.Trait{ - Enabled: ptr.To(false), - }, - }, - }, - }, - Status: v1.IntegrationStatus{ - Phase: v1.IntegrationPhaseRunning, - }, - } - c, err := internal.NewFakeClient(importedIt) - require.NoError(t, err) - - a := monitorSyntheticAction{} - a.InjectLogger(log.Log) - a.InjectClient(c) - assert.Equal(t, "monitor-synthetic", a.Name()) - assert.True(t, a.CanHandle(importedIt)) - handledIt, err := a.Handle(context.TODO(), importedIt) - require.Error(t, err) - assert.Equal(t, v1.IntegrationPhaseError, handledIt.Status.Phase) - assert.Equal(t, corev1.ConditionFalse, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Status) - assert.Equal(t, v1.IntegrationConditionImportingKindAvailableReason, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Reason) - assert.Equal(t, "cannot create a synthetic environment for SomeKind kind", handledIt.Status.GetCondition(v1.IntegrationConditionReady).Message) -} - -func TestMonitorSyntheticIntegrationCannotMonitorPods(t *testing.T) { - importedIt := &v1.Integration{ - TypeMeta: metav1.TypeMeta{ - APIVersion: v1.SchemeGroupVersion.String(), - Kind: v1.IntegrationKind, - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "ns", - Name: "my-imported-it", - Annotations: map[string]string{ - v1.IntegrationImportedNameLabel: "my-deploy", - v1.IntegrationSyntheticLabel: "true", - v1.IntegrationImportedKindLabel: "Deployment", - }, - }, - Spec: v1.IntegrationSpec{ - Traits: v1.Traits{ - Health: &trait.HealthTrait{ - Trait: trait.Trait{ - Enabled: ptr.To(false), - }, - }, - }, - }, - Status: v1.IntegrationStatus{ - Phase: v1.IntegrationPhaseRunning, - Conditions: []v1.IntegrationCondition{ - { - Type: v1.IntegrationConditionDeploymentAvailable, - Status: corev1.ConditionTrue, - }, - { - Type: v1.IntegrationConditionReady, - Status: corev1.ConditionTrue, - }, - }, - }, - } - deploy := &appsv1.Deployment{ - TypeMeta: metav1.TypeMeta{ - APIVersion: appsv1.SchemeGroupVersion.String(), - Kind: "Deployment", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "ns", - Name: "my-deploy", - Labels: map[string]string{ - v1.IntegrationLabel: "my-imported-it", - }, - }, - } - c, err := internal.NewFakeClient(importedIt, deploy) - require.NoError(t, err) - - a := monitorSyntheticAction{} - a.InjectLogger(log.Log) - a.InjectClient(c) - assert.Equal(t, "monitor-synthetic", a.Name()) - assert.True(t, a.CanHandle(importedIt)) - handledIt, err := a.Handle(context.TODO(), importedIt) - require.NoError(t, err) - assert.Equal(t, corev1.ConditionFalse, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Status) - // Check monitoring pods condition - assert.Equal(t, v1.IntegrationConditionMonitoringPodsAvailableReason, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Reason) - assert.Equal(t, "Could not find `camel.apache.org/integration: my-imported-it` label in the Deployment/my-deploy template. Make sure to include this label in the template for Pod monitoring purposes.", handledIt.Status.GetCondition(v1.IntegrationConditionReady).Message) -} - -func TestMonitorSyntheticIntegrationDeployment(t *testing.T) { - importedIt := &v1.Integration{ - TypeMeta: metav1.TypeMeta{ - APIVersion: v1.SchemeGroupVersion.String(), - Kind: v1.IntegrationKind, - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "ns", - Name: "my-imported-it", - Annotations: map[string]string{ - v1.IntegrationImportedNameLabel: "my-deploy", - v1.IntegrationSyntheticLabel: "true", - v1.IntegrationImportedKindLabel: "Deployment", - }, - }, - Spec: v1.IntegrationSpec{ - Traits: v1.Traits{ - Container: &trait.ContainerTrait{ - Name: "my-cnt", - }, - Health: &trait.HealthTrait{ - Trait: trait.Trait{ - Enabled: ptr.To(false), - }, - }, - }, - }, - Status: v1.IntegrationStatus{ - Phase: v1.IntegrationPhaseRunning, - Conditions: []v1.IntegrationCondition{ - { - Type: v1.IntegrationConditionDeploymentAvailable, - Status: corev1.ConditionTrue, - }, - { - Type: v1.IntegrationConditionReady, - Status: corev1.ConditionTrue, - }, - }, - }, - } - deploy := &appsv1.Deployment{ - TypeMeta: metav1.TypeMeta{ - APIVersion: appsv1.SchemeGroupVersion.String(), - Kind: "Deployment", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "ns", - Name: "my-deploy", - Labels: map[string]string{ - v1.IntegrationLabel: "my-imported-it", - }, - }, - Spec: appsv1.DeploymentSpec{ - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - v1.IntegrationLabel: "my-imported-it", - }, - }, - Spec: corev1.PodSpec{ - Containers: []corev1.Container{ - { - Name: "my-cnt", - Image: "my-img", - }, - }, - }, - }, - }, - } - pod := &corev1.Pod{ - TypeMeta: metav1.TypeMeta{ - APIVersion: appsv1.SchemeGroupVersion.String(), - Kind: "Pod", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "ns", - Name: "my-pod", - Labels: map[string]string{ - v1.IntegrationLabel: "my-imported-it", - }, - }, - Spec: corev1.PodSpec{ - Containers: []corev1.Container{ - { - Name: "my-cnt", - Image: "my-img", - }, - }, - }, - Status: corev1.PodStatus{ - Phase: corev1.PodRunning, - Conditions: []corev1.PodCondition{ - { - Type: corev1.PodReady, - Status: corev1.ConditionTrue, - }, - }, - }, - } - c, err := internal.NewFakeClient(importedIt, deploy, pod) - require.NoError(t, err) - - a := monitorSyntheticAction{} - a.InjectLogger(log.Log) - a.InjectClient(c) - assert.Equal(t, "monitor-synthetic", a.Name()) - assert.True(t, a.CanHandle(importedIt)) - handledIt, err := a.Handle(context.TODO(), importedIt) - require.NoError(t, err) - assert.Equal(t, v1.IntegrationPhaseRunning, handledIt.Status.Phase) - assert.Equal(t, int32(1), *handledIt.Status.Replicas) - // Ready condition - assert.Equal(t, corev1.ConditionTrue, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Status) - assert.Equal(t, v1.IntegrationConditionDeploymentReadyReason, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Reason) - assert.Equal(t, "1/1 ready replicas", handledIt.Status.GetCondition(v1.IntegrationConditionReady).Message) - - // Remove label from deployment - deploy.Labels = nil - c, err = internal.NewFakeClient(importedIt, deploy) - require.NoError(t, err) - a.InjectClient(c) - handledIt, err = a.Handle(context.TODO(), importedIt) - require.NoError(t, err) - assert.Nil(t, handledIt) -} - -func TestMonitorSyntheticIntegrationCronJob(t *testing.T) { - importedIt := &v1.Integration{ - TypeMeta: metav1.TypeMeta{ - APIVersion: v1.SchemeGroupVersion.String(), - Kind: v1.IntegrationKind, - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "ns", - Name: "my-imported-it", - Annotations: map[string]string{ - v1.IntegrationImportedNameLabel: "my-cron", - v1.IntegrationSyntheticLabel: "true", - v1.IntegrationImportedKindLabel: "CronJob", - }, - }, - Spec: v1.IntegrationSpec{ - Traits: v1.Traits{ - Health: &trait.HealthTrait{ - Trait: trait.Trait{ - Enabled: ptr.To(false), - }, - }, - }, - }, - Status: v1.IntegrationStatus{ - Phase: v1.IntegrationPhaseRunning, - Conditions: []v1.IntegrationCondition{ - { - Type: v1.IntegrationConditionCronJobAvailable, - Status: corev1.ConditionTrue, - }, - { - Type: v1.IntegrationConditionReady, - Status: corev1.ConditionTrue, - }, - }, - }, - } - cron := &batchv1.CronJob{ - TypeMeta: metav1.TypeMeta{ - APIVersion: appsv1.SchemeGroupVersion.String(), - Kind: "CronJob", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "ns", - Name: "my-cron", - Labels: map[string]string{ - v1.IntegrationLabel: "my-imported-it", - }, - }, - Spec: batchv1.CronJobSpec{ - JobTemplate: batchv1.JobTemplateSpec{ - Spec: batchv1.JobSpec{ - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - v1.IntegrationLabel: "my-imported-it", - }, - }, - Spec: corev1.PodSpec{ - Containers: []corev1.Container{ - { - Name: "my-cnt", - Image: "my-img", - }, - }, - }, - }, - }, - }, - }, - } - pod := &corev1.Pod{ - TypeMeta: metav1.TypeMeta{ - APIVersion: appsv1.SchemeGroupVersion.String(), - Kind: "Pod", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "ns", - Name: "my-pod", - Labels: map[string]string{ - v1.IntegrationLabel: "my-imported-it", - }, - }, - Spec: corev1.PodSpec{ - Containers: []corev1.Container{ - { - Name: "my-cnt", - Image: "my-img", - }, - }, - }, - Status: corev1.PodStatus{ - Phase: corev1.PodRunning, - Conditions: []corev1.PodCondition{ - { - Type: corev1.PodReady, - Status: corev1.ConditionTrue, - }, - }, - }, - } - c, err := internal.NewFakeClient(importedIt, cron, pod) - require.NoError(t, err) - - a := monitorSyntheticAction{} - a.InjectLogger(log.Log) - a.InjectClient(c) - assert.Equal(t, "monitor-synthetic", a.Name()) - assert.True(t, a.CanHandle(importedIt)) - handledIt, err := a.Handle(context.TODO(), importedIt) - require.NoError(t, err) - assert.Equal(t, v1.IntegrationPhaseRunning, handledIt.Status.Phase) - assert.Equal(t, int32(1), *handledIt.Status.Replicas) - // Ready condition - assert.Equal(t, corev1.ConditionTrue, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Status) - assert.Equal(t, v1.IntegrationConditionCronJobCreatedReason, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Reason) - assert.Equal(t, "cronjob created", handledIt.Status.GetCondition(v1.IntegrationConditionReady).Message) -} - -func TestMonitorSyntheticIntegrationKnativeService(t *testing.T) { - importedIt := &v1.Integration{ - TypeMeta: metav1.TypeMeta{ - APIVersion: v1.SchemeGroupVersion.String(), - Kind: v1.IntegrationKind, - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "ns", - Name: "my-imported-it", - Annotations: map[string]string{ - v1.IntegrationImportedNameLabel: "my-ksvc", - v1.IntegrationSyntheticLabel: "true", - v1.IntegrationImportedKindLabel: "KnativeService", - }, - }, - Spec: v1.IntegrationSpec{ - Traits: v1.Traits{ - Health: &trait.HealthTrait{ - Trait: trait.Trait{ - Enabled: ptr.To(false), - }, - }, - }, - }, - Status: v1.IntegrationStatus{ - Phase: v1.IntegrationPhaseRunning, - Conditions: []v1.IntegrationCondition{ - { - Type: v1.IntegrationConditionKnativeServiceAvailable, - Status: corev1.ConditionTrue, - }, - { - Type: v1.IntegrationConditionReady, - Status: corev1.ConditionTrue, - }, - }, - }, - } - ksvc := &servingv1.Service{ - TypeMeta: metav1.TypeMeta{ - APIVersion: appsv1.SchemeGroupVersion.String(), - Kind: "Service", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "ns", - Name: "my-ksvc", - Labels: map[string]string{ - v1.IntegrationLabel: "my-imported-it", - }, - }, - Spec: servingv1.ServiceSpec{ - ConfigurationSpec: servingv1.ConfigurationSpec{ - Template: servingv1.RevisionTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - v1.IntegrationLabel: "my-imported-it", - }, - }, - Spec: servingv1.RevisionSpec{ - PodSpec: corev1.PodSpec{ - Containers: []corev1.Container{ - { - Name: "my-cnt", - Image: "my-img", - }, - }, - }, - }, - }, - }, - }, - Status: servingv1.ServiceStatus{ - Status: duckv1.Status{ - Conditions: duckv1.Conditions{ - apis.Condition{ - Type: servingv1.ServiceConditionReady, - Status: corev1.ConditionTrue, - }, - }, - }, - }, - } - pod := &corev1.Pod{ - TypeMeta: metav1.TypeMeta{ - APIVersion: appsv1.SchemeGroupVersion.String(), - Kind: "Pod", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "ns", - Name: "my-pod", - Labels: map[string]string{ - v1.IntegrationLabel: "my-imported-it", - }, - }, - Spec: corev1.PodSpec{ - Containers: []corev1.Container{ - { - Name: "my-cnt", - Image: "my-img", - }, - }, - }, - Status: corev1.PodStatus{ - Phase: corev1.PodRunning, - Conditions: []corev1.PodCondition{ - { - Type: corev1.PodReady, - Status: corev1.ConditionTrue, - }, - }, - }, - } - c, err := internal.NewFakeClient(importedIt, ksvc, pod) - require.NoError(t, err) - - a := monitorSyntheticAction{} - a.InjectLogger(log.Log) - a.InjectClient(c) - assert.Equal(t, "monitor-synthetic", a.Name()) - assert.True(t, a.CanHandle(importedIt)) - handledIt, err := a.Handle(context.TODO(), importedIt) - require.NoError(t, err) - assert.Equal(t, v1.IntegrationPhaseRunning, handledIt.Status.Phase) - assert.Equal(t, int32(1), *handledIt.Status.Replicas) - // Ready condition - assert.Equal(t, corev1.ConditionTrue, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Status) - assert.Equal(t, v1.IntegrationConditionKnativeServiceReadyReason, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Reason) -} diff --git a/pkg/controller/integrationkit/error.go b/pkg/controller/integrationkit/error.go index 596690ee9..b309fcd13 100644 --- a/pkg/controller/integrationkit/error.go +++ b/pkg/controller/integrationkit/error.go @@ -42,8 +42,7 @@ func (action *errorAction) CanHandle(kit *v1.IntegrationKit) bool { } func (action *errorAction) Handle(ctx context.Context, kit *v1.IntegrationKit) (*v1.IntegrationKit, error) { - //nolint: staticcheck - if kit.IsExternal() || kit.IsSynthetic() { + if kit.IsExternal() { // do nothing, it's not a managed kit return nil, nil } diff --git a/pkg/controller/integrationkit/initialize.go b/pkg/controller/integrationkit/initialize.go index 9d5d1db7b..44876bc2d 100644 --- a/pkg/controller/integrationkit/initialize.go +++ b/pkg/controller/integrationkit/initialize.go @@ -51,8 +51,8 @@ func (action *initializeAction) CanHandle(kit *v1.IntegrationKit) bool { func (action *initializeAction) Handle(ctx context.Context, kit *v1.IntegrationKit) (*v1.IntegrationKit, error) { action.L.Info("Initializing IntegrationKit") if kit.Spec.Image != "" { - // Synthetic Kit - action.L.Info("Synthetic Kit, won't be able to build or monitor this one.") + // The user provided the image directly, so there is nothing to build. + action.L.Info("Kit with a user provided image, won't be able to build or monitor this one.") kit.Status.Phase = v1.IntegrationKitPhaseReady kit.Status.Image = kit.Spec.Image diff --git a/pkg/controller/integrationkit/integrationkit_controller.go b/pkg/controller/integrationkit/integrationkit_controller.go index 7b0b23344..b583648fb 100644 --- a/pkg/controller/integrationkit/integrationkit_controller.go +++ b/pkg/controller/integrationkit/integrationkit_controller.go @@ -239,8 +239,7 @@ func (r *reconcileIntegrationKit) Reconcile(ctx context.Context, request reconci //nolint:nestif if target.Status.Phase == v1.IntegrationKitPhaseNone || target.Status.Phase == v1.IntegrationKitPhaseWaitingForPlatform { rlog.Debug("Preparing to shift integration kit phase") - //nolint: staticcheck - if target.IsExternal() || target.IsSynthetic() { + if target.IsExternal() { target.Status.Phase = v1.IntegrationKitPhaseInitialization return r.update(ctx, &instance, target) diff --git a/pkg/controller/integrationkit/monitor.go b/pkg/controller/integrationkit/monitor.go index d2b29ad82..c75f9fd3f 100644 --- a/pkg/controller/integrationkit/monitor.go +++ b/pkg/controller/integrationkit/monitor.go @@ -44,21 +44,8 @@ func (action *monitorAction) CanHandle(kit *v1.IntegrationKit) bool { } func (action *monitorAction) Handle(ctx context.Context, kit *v1.IntegrationKit) (*v1.IntegrationKit, error) { - //nolint: staticcheck - if kit.IsExternal() || kit.IsSynthetic() { + if kit.IsExternal() { // do nothing, it's not a managed kit - // if it's a syntetic Kit add a condition to warn this is a - // deprecated feature which may be removed soon. - if kit.IsSynthetic() { - kit.Status.SetCondition( - v1.IntegrationKitConditionType("SyntheticKitDeprecated"), - corev1.ConditionTrue, - "DeprecationNotice", - "Synthetic IntegrationKit feature is deprecated and will be removed soon.", - ) - action.L.Infof("WARN: Synthetic IntegrationKit feature is deprecated and will be removed soon.") - } - return kit, nil } hash, err := digest.ComputeForIntegrationKit(kit) diff --git a/pkg/controller/synthetic/synthetic.go b/pkg/controller/synthetic/synthetic.go deleted file mode 100644 index ba2a694b3..000000000 --- a/pkg/controller/synthetic/synthetic.go +++ /dev/null @@ -1,319 +0,0 @@ -/* -Licensed to the Apache Software Foundation (ASF) under one or more -contributor license agreements. See the NOTICE file distributed with -this work for additional information regarding copyright ownership. -The ASF licenses this file to You under the Apache License, Version 2.0 -(the "License"); you may not use this file except in compliance with -the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package synthetic - -import ( - "context" - "fmt" - "reflect" - - v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1" - "github.com/apache/camel-k/v2/pkg/apis/camel/v1/trait" - "github.com/apache/camel-k/v2/pkg/client" - "github.com/apache/camel-k/v2/pkg/platform" - "github.com/apache/camel-k/v2/pkg/util/kubernetes" - "github.com/apache/camel-k/v2/pkg/util/log" - appsv1 "k8s.io/api/apps/v1" - batchv1 "k8s.io/api/batch/v1" - k8serrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - clientgocache "k8s.io/client-go/tools/cache" - "knative.dev/serving/pkg/apis/serving" - servingv1 "knative.dev/serving/pkg/apis/serving/v1" - "sigs.k8s.io/controller-runtime/pkg/cache" - ctrl "sigs.k8s.io/controller-runtime/pkg/client" -) - -var ( - controller = true -) - -// ManageSyntheticIntegrations is the controller for synthetic Integrations. Consider that the lifecycle of the objects are driven -// by the way we are monitoring them. Since we're filtering by `camel.apache.org/integration` label in the cached client, -// you must consider an add, update or delete -// accordingly, ie, when the user label the resource, then it is considered as an add, when it removes the label, it is considered as a delete. -// We must filter only non managed objects in order to avoid to conflict with the reconciliation loop of managed objects (owned by an Integration). -func ManageSyntheticIntegrations(ctx context.Context, c client.Client, cache cache.Cache) error { - informers, err := getInformers(ctx, c, cache) - if err != nil { - return err - } - for _, informer := range informers { - _, err := informer.AddEventHandler(clientgocache.ResourceEventHandlerFuncs{ - AddFunc: func(obj any) { - ctrlObj, ok := obj.(ctrl.Object) - if !ok { - log.Error(fmt.Errorf("type assertion failed: %v", obj), "Failed to retrieve Object on add event") - - return - } - if isManagedObject(ctrlObj) { - return - } - - onAdd(ctx, c, ctrlObj) - }, - DeleteFunc: func(obj any) { - ctrlObj, ok := obj.(ctrl.Object) - if !ok { - log.Errorf(fmt.Errorf("type assertion failed: %v", obj), "Failed to retrieve Object on delete event") - - return - } - if isManagedObject(ctrlObj) { - return - } - - onDelete(ctx, c, ctrlObj) - }, - }) - if err != nil { - return err - } - } - - return nil -} - -// TODO: refactor this code and remove lint exclusion -// -//nolint:nestif -func onAdd(ctx context.Context, c client.Client, ctrlObj ctrl.Object) { - integrationName := ctrlObj.GetLabels()[v1.IntegrationLabel] - it, err := getSyntheticIntegration(ctx, c, ctrlObj.GetNamespace(), integrationName) - if err != nil { - if k8serrors.IsNotFound(err) { - adapter, err := nonManagedCamelApplicationFactory(ctrlObj) - if err != nil { - log.Errorf(err, "Some error happened while creating a Camel application adapter for %s", integrationName) - } - - // TODO: looking at the code, nonManagedCamelApplicationFactory may return nil but the - // previous error handler does not return/break so the code below may panic when - // invoking adapter.Integration() - if err = createSyntheticIntegration(ctx, c, adapter.Integration()); err != nil { - log.Errorf(err, "Some error happened while creating a synthetic Integration %s", integrationName) - } - log.Infof("Created a synthetic Integration %s after %s resource object", it.GetName(), ctrlObj.GetName()) - } else { - log.Errorf(err, "Some error happened while loading a synthetic Integration %s", integrationName) - } - } else { - log.Infof("Synthetic Integration %s is in phase %s. Skipping.", integrationName, it.Status.Phase) - } -} - -func onDelete(ctx context.Context, c client.Client, ctrlObj ctrl.Object) { - integrationName := ctrlObj.GetLabels()[v1.IntegrationLabel] - // Importing label removed - if err := deleteSyntheticIntegration(ctx, c, ctrlObj.GetNamespace(), integrationName); err != nil { - log.Errorf(err, "Some error happened while deleting a synthetic Integration %s", integrationName) - } - log.Infof("Deleted synthetic Integration %s", integrationName) -} - -func getInformers(ctx context.Context, cl client.Client, c cache.Cache) ([]cache.Informer, error) { - deploy, err := c.GetInformer(ctx, &appsv1.Deployment{}) - if err != nil { - return nil, err - } - informers := []cache.Informer{deploy} - // Watch for the CronJob conditionally - if ok, err := kubernetes.IsAPIResourceInstalled(cl, batchv1.SchemeGroupVersion.String(), reflect.TypeFor[batchv1.CronJob]().Name()); ok && err == nil { - cron, err := c.GetInformer(ctx, &batchv1.CronJob{}) - if err != nil { - return nil, err - } - informers = append(informers, cron) - } - // Watch for the Knative Services conditionally - if ok, err := kubernetes.IsAPIResourceInstalled(cl, servingv1.SchemeGroupVersion.String(), reflect.TypeFor[servingv1.Service]().Name()); ok && err == nil { - if ok, err := kubernetes.CheckSelfPermission(ctx, cl, serving.GroupName, "services", platform.GetOperatorWatchNamespace(), "", "watch"); ok && err == nil { - ksvc, err := c.GetInformer(ctx, &servingv1.Service{}) - if err != nil { - return nil, err - } - informers = append(informers, ksvc) - } - } - - return informers, nil -} - -func getSyntheticIntegration(ctx context.Context, c client.Client, namespace, name string) (*v1.Integration, error) { - it := v1.NewIntegration(namespace, name) - err := c.Get(ctx, ctrl.ObjectKeyFromObject(&it), &it) - - return &it, err -} - -func createSyntheticIntegration(ctx context.Context, c client.Client, it *v1.Integration) error { - return c.Create(ctx, it, ctrl.FieldOwner("camel-k-operator")) -} - -func deleteSyntheticIntegration(ctx context.Context, c client.Client, namespace, name string) error { - // As the Integration label was removed, we don't know which is the Synthetic integration to remove - it := v1.NewIntegration(namespace, name) - - return c.Delete(ctx, &it) -} - -// isManagedObject returns true if the object is managed by an Integration. -func isManagedObject(obj ctrl.Object) bool { - for _, mr := range obj.GetOwnerReferences() { - if mr.APIVersion == "camel.apache.org/v1" && - mr.Kind == "Integration" { - return true - } - } - - return false -} - -// nonManagedCamelApplicationAdapter represents a Camel application built and deployed outside the operator lifecycle. -type nonManagedCamelApplicationAdapter interface { - // Integration return an Integration resource fed by the Camel application adapter. - Integration() *v1.Integration -} - -func nonManagedCamelApplicationFactory(obj ctrl.Object) (nonManagedCamelApplicationAdapter, error) { - deploy, ok := obj.(*appsv1.Deployment) - if ok { - return &nonManagedCamelDeployment{deploy: deploy}, nil - } - cronjob, ok := obj.(*batchv1.CronJob) - if ok { - return &NonManagedCamelCronjob{cron: cronjob}, nil - } - ksvc, ok := obj.(*servingv1.Service) - if ok { - return &NonManagedCamelKnativeService{ksvc: ksvc}, nil - } - - return nil, fmt.Errorf("unsupported %s object kind", obj.GetName()) -} - -// NonManagedCamelDeployment represents a regular Camel application built and deployed outside the operator lifecycle. -type nonManagedCamelDeployment struct { - deploy *appsv1.Deployment -} - -// Integration return an Integration resource fed by the Camel application adapter. -func (app *nonManagedCamelDeployment) Integration() *v1.Integration { - it := v1.NewIntegration(app.deploy.Namespace, app.deploy.Labels[v1.IntegrationLabel]) - it.SetAnnotations(map[string]string{ - v1.IntegrationImportedNameLabel: app.deploy.Name, - v1.IntegrationImportedKindLabel: "Deployment", - v1.IntegrationSyntheticLabel: "true", - }) - it.Spec = v1.IntegrationSpec{ - Traits: v1.Traits{ - Container: &trait.ContainerTrait{ - Name: app.getContainerNameFromDeployment(), - }, - }, - } - references := []metav1.OwnerReference{ - { - APIVersion: "apps/v1", - Kind: "Deployment", - Name: app.deploy.Name, - UID: app.deploy.UID, - Controller: &controller, - }, - } - it.SetOwnerReferences(references) - - return &it -} - -// getContainerNameFromDeployment returns the container name which is running the Camel application. -func (app *nonManagedCamelDeployment) getContainerNameFromDeployment() string { - firstContainerName := "" - for _, ct := range app.deploy.Spec.Template.Spec.Containers { - // set as fallback if no container is named as the deployment - if firstContainerName == "" { - firstContainerName = ct.Name - } - if ct.Name == app.deploy.Name { - return app.deploy.Name - } - } - - return firstContainerName -} - -// NonManagedCamelCronjob represents a cron Camel application built and deployed outside the operator lifecycle. -type NonManagedCamelCronjob struct { - cron *batchv1.CronJob -} - -// Integration return an Integration resource fed by the Camel application adapter. -func (app *NonManagedCamelCronjob) Integration() *v1.Integration { - it := v1.NewIntegration(app.cron.Namespace, app.cron.Labels[v1.IntegrationLabel]) - it.SetAnnotations(map[string]string{ - v1.IntegrationImportedNameLabel: app.cron.Name, - v1.IntegrationImportedKindLabel: "CronJob", - v1.IntegrationSyntheticLabel: "true", - }) - it.Spec = v1.IntegrationSpec{ - Traits: v1.Traits{}, - } - references := []metav1.OwnerReference{ - { - APIVersion: "batch/v1", - Kind: "CronJob", - Name: app.cron.Name, - UID: app.cron.UID, - Controller: &controller, - }, - } - it.SetOwnerReferences(references) - - return &it -} - -// NonManagedCamelKnativeService represents a Knative Service based Camel application built and deployed outside the operator lifecycle. -type NonManagedCamelKnativeService struct { - ksvc *servingv1.Service -} - -// Integration return an Integration resource fed by the Camel application adapter. -func (app *NonManagedCamelKnativeService) Integration() *v1.Integration { - it := v1.NewIntegration(app.ksvc.Namespace, app.ksvc.Labels[v1.IntegrationLabel]) - it.SetAnnotations(map[string]string{ - v1.IntegrationImportedNameLabel: app.ksvc.Name, - v1.IntegrationImportedKindLabel: "KnativeService", - v1.IntegrationSyntheticLabel: "true", - }) - it.Spec = v1.IntegrationSpec{ - Traits: v1.Traits{}, - } - references := []metav1.OwnerReference{ - { - APIVersion: servingv1.SchemeGroupVersion.String(), - Kind: "Service", - Name: app.ksvc.Name, - UID: app.ksvc.UID, - Controller: &controller, - }, - } - it.SetOwnerReferences(references) - - return &it -} diff --git a/pkg/controller/synthetic/synthetic_test.go b/pkg/controller/synthetic/synthetic_test.go deleted file mode 100644 index b5beb3be3..000000000 --- a/pkg/controller/synthetic/synthetic_test.go +++ /dev/null @@ -1,251 +0,0 @@ -/* -Licensed to the Apache Software Foundation (ASF) under one or more -contributor license agreements. See the NOTICE file distributed with -this work for additional information regarding copyright ownership. -The ASF licenses this file to You under the Apache License, Version 2.0 -(the "License"); you may not use this file except in compliance with -the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package synthetic - -import ( - "testing" - - appsv1 "k8s.io/api/apps/v1" - batchv1 "k8s.io/api/batch/v1" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - servingv1 "knative.dev/serving/pkg/apis/serving/v1" - - v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1" - "github.com/apache/camel-k/v2/pkg/apis/camel/v1/trait" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestNonManagedUnsupported(t *testing.T) { - pod := &corev1.Pod{ - TypeMeta: metav1.TypeMeta{ - APIVersion: corev1.SchemeGroupVersion.String(), - Kind: "Pod", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "ns", - Name: "my-pod", - Labels: map[string]string{ - v1.IntegrationLabel: "my-imported-it", - }, - }, - Spec: corev1.PodSpec{ - Containers: []corev1.Container{ - { - Name: "my-cnt", - Image: "my-img", - }, - }, - }, - Status: corev1.PodStatus{ - Phase: corev1.PodRunning, - Conditions: []corev1.PodCondition{ - { - Type: corev1.PodReady, - Status: corev1.ConditionTrue, - }, - }, - }, - } - - nilAdapter, err := nonManagedCamelApplicationFactory(pod) - require.Error(t, err) - assert.Equal(t, "unsupported my-pod object kind", err.Error()) - assert.Nil(t, nilAdapter) -} - -func TestNonManagedDeployment(t *testing.T) { - deploy := &appsv1.Deployment{ - TypeMeta: metav1.TypeMeta{ - APIVersion: appsv1.SchemeGroupVersion.String(), - Kind: "Deployment", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "ns", - Name: "my-deploy", - Labels: map[string]string{ - v1.IntegrationLabel: "my-imported-it", - }, - }, - Spec: appsv1.DeploymentSpec{ - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - v1.IntegrationLabel: "my-imported-it", - }, - }, - Spec: corev1.PodSpec{ - Containers: []corev1.Container{ - { - Name: "my-cnt", - Image: "my-img", - }, - }, - }, - }, - }, - } - - expectedIt := v1.NewIntegration("ns", "my-imported-it") - expectedIt.SetAnnotations(map[string]string{ - v1.IntegrationImportedNameLabel: "my-deploy", - v1.IntegrationImportedKindLabel: "Deployment", - v1.IntegrationSyntheticLabel: "true", - }) - expectedIt.Spec = v1.IntegrationSpec{ - Traits: v1.Traits{ - Container: &trait.ContainerTrait{ - Name: "my-cnt", - }, - }, - } - references := []metav1.OwnerReference{ - { - APIVersion: "apps/v1", - Kind: "Deployment", - Name: deploy.Name, - UID: deploy.UID, - Controller: &controller, - }, - } - expectedIt.SetOwnerReferences(references) - - deploymentAdapter, err := nonManagedCamelApplicationFactory(deploy) - require.NoError(t, err) - assert.NotNil(t, deploymentAdapter) - assert.Equal(t, expectedIt, *deploymentAdapter.Integration()) -} - -func TestNonManagedCronJob(t *testing.T) { - cron := &batchv1.CronJob{ - TypeMeta: metav1.TypeMeta{ - APIVersion: batchv1.SchemeGroupVersion.String(), - Kind: "CronJob", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "ns", - Name: "my-cron", - Labels: map[string]string{ - v1.IntegrationLabel: "my-imported-it", - }, - }, - Spec: batchv1.CronJobSpec{ - JobTemplate: batchv1.JobTemplateSpec{ - Spec: batchv1.JobSpec{ - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - v1.IntegrationLabel: "my-imported-it", - }, - }, - Spec: corev1.PodSpec{ - Containers: []corev1.Container{ - { - Name: "my-cnt", - Image: "my-img", - }, - }, - }, - }, - }, - }, - }, - } - - expectedIt := v1.NewIntegration("ns", "my-imported-it") - expectedIt.SetAnnotations(map[string]string{ - v1.IntegrationImportedNameLabel: "my-cron", - v1.IntegrationImportedKindLabel: "CronJob", - v1.IntegrationSyntheticLabel: "true", - }) - references := []metav1.OwnerReference{ - { - APIVersion: "batch/v1", - Kind: "CronJob", - Name: cron.Name, - UID: cron.UID, - Controller: &controller, - }, - } - expectedIt.SetOwnerReferences(references) - cronJobAdapter, err := nonManagedCamelApplicationFactory(cron) - require.NoError(t, err) - assert.NotNil(t, cronJobAdapter) - assert.Equal(t, expectedIt, *cronJobAdapter.Integration()) -} - -func TestNonManagedKnativeService(t *testing.T) { - ksvc := &servingv1.Service{ - TypeMeta: metav1.TypeMeta{ - APIVersion: servingv1.SchemeGroupVersion.String(), - Kind: "Service", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "ns", - Name: "my-ksvc", - Labels: map[string]string{ - v1.IntegrationLabel: "my-imported-it", - }, - }, - Spec: servingv1.ServiceSpec{ - ConfigurationSpec: servingv1.ConfigurationSpec{ - Template: servingv1.RevisionTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - v1.IntegrationLabel: "my-imported-it", - }, - }, - Spec: servingv1.RevisionSpec{ - PodSpec: corev1.PodSpec{ - Containers: []corev1.Container{ - { - Name: "my-cnt", - Image: "my-img", - }, - }, - }, - }, - }, - }, - }, - } - - expectedIt := v1.NewIntegration("ns", "my-imported-it") - expectedIt.SetAnnotations(map[string]string{ - v1.IntegrationImportedNameLabel: "my-ksvc", - v1.IntegrationImportedKindLabel: "KnativeService", - v1.IntegrationSyntheticLabel: "true", - }) - references := []metav1.OwnerReference{ - { - APIVersion: servingv1.SchemeGroupVersion.String(), - Kind: "Service", - Name: ksvc.Name, - UID: ksvc.UID, - Controller: &controller, - }, - } - expectedIt.SetOwnerReferences(references) - - knativeServiceAdapter, err := nonManagedCamelApplicationFactory(ksvc) - require.NoError(t, err) - assert.NotNil(t, knativeServiceAdapter) - assert.Equal(t, expectedIt, *knativeServiceAdapter.Integration()) -} diff --git a/pkg/resources/config/crd/bases/camel.apache.org_integrationplatforms.yaml b/pkg/resources/config/crd/bases/camel.apache.org_integrationplatforms.yaml index 98b1b0388..edbbc905b 100644 --- a/pkg/resources/config/crd/bases/camel.apache.org_integrationplatforms.yaml +++ b/pkg/resources/config/crd/bases/camel.apache.org_integrationplatforms.yaml @@ -794,7 +794,7 @@ spec: type: boolean image: description: |- - The main container image to use for the Integration. When using this parameter the operator will create a synthetic IntegrationKit which + The main container image to use for the Integration. When using this parameter the operator will create an IntegrationKit which won't be able to execute traits requiring CamelCatalog. If the container image you're using is coming from an IntegrationKit, use instead Integration `.spec.integrationKit` parameter. If you're moving the Integration across environments, you will also need to create an "external" IntegrationKit. type: string @@ -3365,7 +3365,7 @@ spec: type: boolean image: description: |- - The main container image to use for the Integration. When using this parameter the operator will create a synthetic IntegrationKit which + The main container image to use for the Integration. When using this parameter the operator will create an IntegrationKit which won't be able to execute traits requiring CamelCatalog. If the container image you're using is coming from an IntegrationKit, use instead Integration `.spec.integrationKit` parameter. If you're moving the Integration across environments, you will also need to create an "external" IntegrationKit. type: string diff --git a/pkg/resources/config/crd/bases/camel.apache.org_integrationprofiles.yaml b/pkg/resources/config/crd/bases/camel.apache.org_integrationprofiles.yaml index 11e4dce10..d5ae4f001 100644 --- a/pkg/resources/config/crd/bases/camel.apache.org_integrationprofiles.yaml +++ b/pkg/resources/config/crd/bases/camel.apache.org_integrationprofiles.yaml @@ -719,7 +719,7 @@ spec: type: boolean image: description: |- - The main container image to use for the Integration. When using this parameter the operator will create a synthetic IntegrationKit which + The main container image to use for the Integration. When using this parameter the operator will create an IntegrationKit which won't be able to execute traits requiring CamelCatalog. If the container image you're using is coming from an IntegrationKit, use instead Integration `.spec.integrationKit` parameter. If you're moving the Integration across environments, you will also need to create an "external" IntegrationKit. type: string @@ -3239,7 +3239,7 @@ spec: type: boolean image: description: |- - The main container image to use for the Integration. When using this parameter the operator will create a synthetic IntegrationKit which + The main container image to use for the Integration. When using this parameter the operator will create an IntegrationKit which won't be able to execute traits requiring CamelCatalog. If the container image you're using is coming from an IntegrationKit, use instead Integration `.spec.integrationKit` parameter. If you're moving the Integration across environments, you will also need to create an "external" IntegrationKit. type: string diff --git a/pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml b/pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml index d3e36aaa3..355240ae0 100644 --- a/pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml +++ b/pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml @@ -7772,7 +7772,7 @@ spec: type: boolean image: description: |- - The main container image to use for the Integration. When using this parameter the operator will create a synthetic IntegrationKit which + The main container image to use for the Integration. When using this parameter the operator will create an IntegrationKit which won't be able to execute traits requiring CamelCatalog. If the container image you're using is coming from an IntegrationKit, use instead Integration `.spec.integrationKit` parameter. If you're moving the Integration across environments, you will also need to create an "external" IntegrationKit. type: string @@ -10180,7 +10180,7 @@ spec: type: boolean image: description: |- - The main container image to use for the Integration. When using this parameter the operator will create a synthetic IntegrationKit which + The main container image to use for the Integration. When using this parameter the operator will create an IntegrationKit which won't be able to execute traits requiring CamelCatalog. If the container image you're using is coming from an IntegrationKit, use instead Integration `.spec.integrationKit` parameter. If you're moving the Integration across environments, you will also need to create an "external" IntegrationKit. type: string diff --git a/pkg/resources/config/crd/bases/camel.apache.org_pipes.yaml b/pkg/resources/config/crd/bases/camel.apache.org_pipes.yaml index 27e5f806f..c7584b72c 100644 --- a/pkg/resources/config/crd/bases/camel.apache.org_pipes.yaml +++ b/pkg/resources/config/crd/bases/camel.apache.org_pipes.yaml @@ -7827,7 +7827,7 @@ spec: type: boolean image: description: |- - The main container image to use for the Integration. When using this parameter the operator will create a synthetic IntegrationKit which + The main container image to use for the Integration. When using this parameter the operator will create an IntegrationKit which won't be able to execute traits requiring CamelCatalog. If the container image you're using is coming from an IntegrationKit, use instead Integration `.spec.integrationKit` parameter. If you're moving the Integration across environments, you will also need to create an "external" IntegrationKit. type: string @@ -10157,7 +10157,7 @@ spec: type: boolean image: description: |- - The main container image to use for the Integration. When using this parameter the operator will create a synthetic IntegrationKit which + The main container image to use for the Integration. When using this parameter the operator will create an IntegrationKit which won't be able to execute traits requiring CamelCatalog. If the container image you're using is coming from an IntegrationKit, use instead Integration `.spec.integrationKit` parameter. If you're moving the Integration across environments, you will also need to create an "external" IntegrationKit. type: string diff --git a/pkg/trait/camel.go b/pkg/trait/camel.go index 75a05fe3c..459490aa3 100644 --- a/pkg/trait/camel.go +++ b/pkg/trait/camel.go @@ -75,10 +75,6 @@ func (t *camelTrait) Matches(trait Trait) bool { } func (t *camelTrait) Configure(e *Environment) (bool, *TraitCondition, error) { - if e.Integration != nil && e.Integration.IsSynthetic() { - return false, NewIntegrationConditionPlatformDisabledWithMessage("Camel", "synthetic integration"), nil - } - if t.RuntimeProvider == "" { t.runtimeProvider = determineRuntimeProvider(e) } else { @@ -91,9 +87,7 @@ func (t *camelTrait) Configure(e *Environment) (bool, *TraitCondition, error) { } var cond *TraitCondition - //nolint: staticcheck - if (e.Integration != nil && (!e.Integration.IsManagedBuild() || e.Integration.IsGitBuild())) || - (e.IntegrationKit != nil && e.IntegrationKit.IsSynthetic()) { + if e.Integration != nil && (!e.Integration.IsManagedBuild() || e.Integration.IsGitBuild()) { // We set a condition to warn the user the catalog used to run the Integration // may differ from the runtime version which we don't control cond = NewIntegrationCondition( @@ -133,11 +127,8 @@ func (t *camelTrait) Apply(e *Environment) error { } } if e.IntegrationKit != nil { - //nolint: staticcheck - if !e.IntegrationKit.IsSynthetic() { - e.IntegrationKit.Status.RuntimeVersion = t.runtimeVersion - e.IntegrationKit.Status.RuntimeProvider = t.runtimeProvider - } + e.IntegrationKit.Status.RuntimeVersion = t.runtimeVersion + e.IntegrationKit.Status.RuntimeProvider = t.runtimeProvider e.IntegrationKit.Status.Catalog = &v1.Catalog{ Version: e.CamelCatalog.Runtime.Version, Provider: e.CamelCatalog.Runtime.Provider, diff --git a/pkg/trait/camel_test.go b/pkg/trait/camel_test.go index 4ac760ea3..d4ef842a5 100644 --- a/pkg/trait/camel_test.go +++ b/pkg/trait/camel_test.go @@ -313,18 +313,3 @@ func TestCamelCatalogSemver(t *testing.T) { // 2.x will translate with 2.16.1 as it is already existing assert.Equal(t, "2.16.1", environment.CamelCatalog.GetRuntimeVersion()) } - -func TestCamelTraitSyntheticIntegration(t *testing.T) { - trait, environment := createNominalCamelTest(true) - environment.Integration.Status = v1.IntegrationStatus{} - environment.Integration.Annotations = make(map[string]string) - environment.Integration.Annotations[v1.IntegrationSyntheticLabel] = boolean.TrueString - - configured, condition, err := trait.Configure(environment) - require.NoError(t, err) - assert.Equal(t, "explicitly disabled by the platform: synthetic integration", condition.message) - assert.False(t, configured) - - assert.Equal(t, v1.RuntimeProvider(""), environment.Integration.Status.RuntimeProvider) - assert.Equal(t, "", environment.Integration.Status.RuntimeVersion) -} diff --git a/pkg/trait/cron.go b/pkg/trait/cron.go index 25b9f33a2..d52435f0a 100644 --- a/pkg/trait/cron.go +++ b/pkg/trait/cron.go @@ -91,9 +91,6 @@ func (t *cronTrait) Configure(e *Environment) (bool, *TraitCondition, error) { if !ptr.Deref(t.Enabled, true) { return false, NewIntegrationConditionUserDisabled("Cron"), nil } - if e.Integration.IsSynthetic() { - return false, NewIntegrationConditionPlatformDisabledWithMessage("Cron", "synthetic integration"), nil - } if !e.IntegrationInPhase(v1.IntegrationPhaseInitialization) && !e.IntegrationInRunningPhases() { return false, nil, nil } diff --git a/pkg/trait/environment.go b/pkg/trait/environment.go index 0951768d6..6ce36ac3f 100644 --- a/pkg/trait/environment.go +++ b/pkg/trait/environment.go @@ -67,9 +67,6 @@ func (t *environmentTrait) Configure(e *Environment) (bool, *TraitCondition, err if e.Integration == nil { return false, nil, nil } - if e.Integration.IsSynthetic() { - return false, NewIntegrationConditionPlatformDisabledWithMessage("Environment", "synthetic integration"), nil - } return e.IntegrationInRunningPhases(), nil, nil } diff --git a/pkg/trait/jvm.go b/pkg/trait/jvm.go index 91af3cef2..ce3579426 100644 --- a/pkg/trait/jvm.go +++ b/pkg/trait/jvm.go @@ -72,15 +72,9 @@ func (t *jvmTrait) Configure(e *Environment) (bool, *TraitCondition, error) { if (e.IntegrationKit != nil && !e.IntegrationKitInPhase(v1.IntegrationKitPhaseReady)) || !e.IntegrationInRunningPhases() { return false, nil, nil } - if e.Integration != nil && e.Integration.IsSynthetic() { - return false, NewIntegrationConditionPlatformDisabledWithMessage("JVM", "synthetic integration"), nil - } - - //nolint: staticcheck - if ((e.Integration != nil && !e.Integration.IsManagedBuild()) || (e.IntegrationKit != nil && e.IntegrationKit.IsSynthetic())) && - t.Jar == "" { + if e.Integration != nil && !e.Integration.IsManagedBuild() && t.Jar == "" { // We skip this trait since we cannot make any assumption on the container Java tooling running - // for the synthetic IntegrationKit + // for an Integration the operator did not build return false, NewIntegrationConditionPlatformDisabledWithMessage( "JVM", "integration kit was not created via Camel K operator and the user did not provide the jar to execute", diff --git a/pkg/trait/mount.go b/pkg/trait/mount.go index 99a7e287c..a8a0a3ea6 100644 --- a/pkg/trait/mount.go +++ b/pkg/trait/mount.go @@ -60,9 +60,6 @@ func (t *mountTrait) Configure(e *Environment) (bool, *TraitCondition, error) { if e.Integration == nil || !e.IntegrationInRunningPhases() { return false, nil, nil } - if e.Integration.IsSynthetic() { - return false, NewIntegrationConditionPlatformDisabledWithMessage("Mount", "synthetic integration"), nil - } // Validate resources and pvcs for _, c := range t.Configs { if !strings.HasPrefix(c, "configmap:") && !strings.HasPrefix(c, "secret:") { diff --git a/pkg/trait/security_context.go b/pkg/trait/security_context.go index 7b6f8d351..b4888085e 100644 --- a/pkg/trait/security_context.go +++ b/pkg/trait/security_context.go @@ -51,9 +51,6 @@ func (t *securityContextTrait) Configure(e *Environment) (bool, *TraitCondition, if e.Integration == nil { return false, nil, nil } - if e.Integration.IsSynthetic() { - return false, NewIntegrationConditionPlatformDisabledWithMessage("SecurityContext", "synthetic integration"), nil - } if !e.IntegrationInRunningPhases() { return false, nil, nil } diff --git a/pkg/trait/trait.go b/pkg/trait/trait.go index cb499eaab..301dbebc9 100644 --- a/pkg/trait/trait.go +++ b/pkg/trait/trait.go @@ -24,14 +24,12 @@ import ( corev1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1" "github.com/apache/camel-k/v2/pkg/client" "github.com/apache/camel-k/v2/pkg/platform" "github.com/apache/camel-k/v2/pkg/util/kubernetes" "github.com/apache/camel-k/v2/pkg/util/log" - serving "knative.dev/serving/pkg/apis/serving/v1" ctrl "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -156,70 +154,3 @@ func newEnvironment(ctx context.Context, c client.Client, integration *v1.Integr return &env, nil } - -// NewSyntheticEnvironment creates an environment suitable for a synthetic Integration. If the application which generated the synthetic Integration -// has no longer the label, it will return a nil result. -func NewSyntheticEnvironment(ctx context.Context, c client.Client, integration *v1.Integration, kit *v1.IntegrationKit) (*Environment, error) { - if integration == nil && kit == nil { - return nil, errors.New("neither integration nor kit are set") - } - - env := Environment{ - Ctx: ctx, - IntegrationProfile: nil, - Client: c, - IntegrationKit: kit, - Integration: integration, - ExecutedTraits: make([]Trait, 0), - Resources: kubernetes.NewCollection(), - EnvVars: make([]corev1.EnvVar, 0), - ApplicationProperties: make(map[string]string), - } - - catalog := NewCatalog(c) - // set the catalog - env.Catalog = catalog - // we need to simulate the execution of the traits to fill certain values used later by monitoring - _, _, err := catalog.apply(&env) - if err != nil { - return nil, fmt.Errorf("error during trait customization: %w", err) - } - camelApp, err := getCamelAppObject( - ctx, - c, - integration.Annotations[v1.IntegrationImportedKindLabel], - integration.Namespace, - integration.Annotations[v1.IntegrationImportedNameLabel], - ) - if err != nil { - return nil, err - } - // Verify if the application has still the expected label. If not, return nil. - if camelApp.GetLabels()[v1.IntegrationLabel] != integration.Name { - return nil, nil - } - env.Resources.Add(camelApp) - - return &env, nil -} - -func getCamelAppObject(ctx context.Context, c client.Client, kind, namespace, name string) (ctrl.Object, error) { - switch kind { - case "Deployment": - return c.AppsV1().Deployments(namespace).Get(ctx, name, metav1.GetOptions{}) - case "CronJob": - return c.BatchV1().CronJobs(namespace).Get(ctx, name, metav1.GetOptions{}) - case "KnativeService": - ksvc := &serving.Service{ - Kind: "Service", - APIVersion: serving.SchemeGroupVersion.String(), - Name: name, - Namespace: namespace, - } - err := c.Get(ctx, ctrl.ObjectKeyFromObject(ksvc), ksvc) - - return ksvc, err - default: - return nil, fmt.Errorf("cannot create a synthetic environment for %s kind", kind) - } -}
