Skip to content

Commit

Permalink
fix(trait): remove imageWasKit
Browse files Browse the repository at this point in the history
As discussed in apache#5399 we need to clarify the intent of each IntegrationKit types.

* removal of imageWasKit
* usage of external IntegrationKit when we are certain that the image comes from an IK
* usage of syntetic IntegrationKit when the image are coming from any container image
* rework of promote command to clone an external IntegrationKit beside the Integration and use it accordingly.

Closes apache#5408
  • Loading branch information
squakez committed Apr 25, 2024
1 parent c40ccaf commit 21e0339
Show file tree
Hide file tree
Showing 23 changed files with 390 additions and 202 deletions.
6 changes: 3 additions & 3 deletions docs/modules/ROOT/pages/running/camel-runtimes.adoc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
= Camel Runtimes
= Camel Runtimes (aka "sourceless" Integrations)

Camel K can run any runtime available in Apache Camel. However, this is possible only when the Camel application was previously built and packaged into a container image. Also, if you run through this option, some of the features offered by the operator may not be available. For example, you won't be able to discover Camel capabilities because the source is not available to the operator but embedded in the container image.

Expand All @@ -15,9 +15,9 @@ You can have your own Camel application or just create a basic one for the purpo

The step above is a very quick way to create a basic Camel application in any of the available runtime. Let's imagine we've done this for Camel Main or we have already a Camel application as a Maven project. As the build part is something we want to take care on our own, we create a pipeline to build, containerize and push the container to a registry (see as a reference https://github.com/tektoncd/catalog/blob/main/task/kamel-run/0.1/samples/run-external-build.yaml[Camel K Tekton example]).

At this stage we do have a container image with our Camel application. We can use the `kamel` CLI to run our Camel application via `kamel run --image docker.io/my-org/my-app:1.0.0` tuning, if it's the case, with any of the trait or configuration required.
At this stage we do have a container image with our Camel application. We can use the `kamel` CLI to run our Camel application via `kamel run --image docker.io/my-org/my-app:1.0.0` tuning, if it's the case, with any of the trait or configuration required. Mind that, when you run an Integration with this option, the operator will create a **synthetic** IntegrationKit.

NOTE: Jvm trait won't be available when running an application built externally.
NOTE: certain traits (ie, JVM) won't be available when running an application built externally.

If all is good, in a few seconds (there is no build involved) you should have your application up and running and you can monitor and operate with Camel K as usual.

Expand Down
14 changes: 11 additions & 3 deletions docs/modules/ROOT/pages/running/promoting.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,19 @@

As soon as you have an Integration running in your cluster, you will be challenged to move that Integration to an higher environment. Ie, you can test your Integration in a **development** environment, and, as soon as you're happy with the result, you will need to move it into a **production** environment.

Camel K has an opinionated way to achieve that goal through the usage of `kamel promote` command. With this command you will be able to easily move an Integration from one namespace to another without worrying about any low level detail such as resources needed by the Integration. You only need to make sure that both the source operator and the destination operator are using the same container registry and that the destination namespace provides the required Configmaps, Secrets or Kamelets required by the Integration.
== External IntegrationKits

NOTE: in order to use the same container registry, you can use the `--registry` option during installation phase or change the IntegrationPlatform to reflect that accordingly.
When you create an Integration, the operator takes care to use an existing IntegrationKit or creating one from scratch. When you're moving your Integration across environments you'll therefore need to create an IntegrationKit accordingly. The creation of the IntegrationKit, in this case, is a simple copy of the original IntegrationKit with the `.spec.image` coming from the `.status.image` of the original IntegrationKit. Additionally, it has to be labelled as `camel.apache.org/kit.type: external`.

NOTE: these two configuration are required to avoid the new IntegrationKit to kick off a new build operation.

The copy is something you can do with any external tooling or using the `kamel promote` command as provided below:

== Show me the code!
== CLI `promote` command

Camel K has an opinionated way to achieve the promotion goal through the usage of `kamel promote` command. With this command you will be able to easily move an Integration from one namespace to another without worrying about any low level detail such as resources needed by the Integration. You only need to make sure that both the source operator and the destination operator are using the same container registry and that the destination namespace provides the required Configmaps, Secrets or Kamelets required by the Integration.

NOTE: in order to use the same container registry, you can use the `--registry` option during installation phase or change the IntegrationPlatform to reflect that accordingly.

Let's see a simple Integration that uses a Configmap to expose some message on an HTTP endpoint. We can start creating such an Integration and testing in a namespace called `development`:

Expand Down
11 changes: 3 additions & 8 deletions docs/modules/ROOT/partials/apis/camel-k-crds.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -6521,14 +6521,9 @@ string
|
The main container image
|`imageWasKit` +
bool
|
A flag to mark the image used is coming from an IntegrationKit created externally.
The main container image to use for the Integration. When using this parameter the operator will create a synthetic 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.
|`imagePullPolicy` +
*https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#pullpolicy-v1-core[Kubernetes core/v1.PullPolicy]*
Expand Down
8 changes: 3 additions & 5 deletions docs/modules/traits/pages/container.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,9 @@ The following configuration options are available:

| container.image
| string
| The main container image

| container.image-was-kit
| bool
| A flag to mark the image used is coming from an IntegrationKit created externally.
| The main container image to use for the Integration. When using this parameter the operator will create a synthetic 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.

| container.image-pull-policy
| PullPolicy
Expand Down
34 changes: 25 additions & 9 deletions e2e/advanced/operator_id_filtering_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (

. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

. "github.com/apache/camel-k/v2/e2e/support"
v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
Expand Down Expand Up @@ -95,15 +96,31 @@ func TestOperatorIDFiltering(t *testing.T) {
})

t.Run("Operators can run scoped integrations with fixed image", func(t *testing.T) {
image := IntegrationPodImage(t, ctx, ns, "moving")()
g.Expect(image).NotTo(BeEmpty())
// Save resources by deleting "moving" integration
g.Expect(Kamel(t, ctx, "delete", "moving", "-n", ns).Execute()).To(Succeed())

g.Expect(KamelRunWithID(t, ctx, "operator-x", ns, "files/yaml.yaml", "--name", "pre-built", "--force", "-t", fmt.Sprintf("container.image=%s", image), "-t", "container.image-was-kit=true").Execute()).To(Succeed())
g.Consistently(IntegrationPhase(t, ctx, ns, "pre-built"), 10*time.Second).Should(BeEmpty())
g.Expect(AssignIntegrationToOperator(t, ctx, ns, "pre-built", operator2)).To(Succeed())
kitName := IntegrationKit(t, ctx, ns, "moving")()
g.Expect(kitName).NotTo(BeEmpty())
kitImage := KitImage(t, ctx, nsop2, kitName)()
g.Expect(kitImage).NotTo(BeEmpty())
// external kit creation
externalKit := v1.IntegrationKit{
ObjectMeta: metav1.ObjectMeta{
Namespace: ns,
Name: "external",
Labels: map[string]string{
"camel.apache.org/kit.type": v1.IntegrationKitTypeExternal,
},
Annotations: map[string]string{
"camel.apache.org/operator.id": operator2,
},
},
Spec: v1.IntegrationKitSpec{
Image: kitImage,
},
}
g.Expect(TestClient(t).Create(ctx, &externalKit)).Should(BeNil())
g.Expect(KamelRunWithID(t, ctx, operator2, ns, "files/yaml.yaml", "--name", "pre-built", "--kit", "external", "--force").Execute()).To(Succeed())
g.Consistently(IntegrationPhase(t, ctx, ns, "pre-built"), 10*time.Second).ShouldNot(Equal(v1.IntegrationPhaseBuildingKit))
g.Eventually(IntegrationPhase(t, ctx, ns, "pre-built"), TestTimeoutShort).Should(Equal(v1.IntegrationPhaseRunning))
g.Eventually(IntegrationStatusImage(t, ctx, ns, "pre-built"), TestTimeoutShort).Should(Equal(kitImage))
g.Eventually(IntegrationPodPhase(t, ctx, ns, "pre-built"), TestTimeoutLong).Should(Equal(corev1.PodRunning))
g.Eventually(IntegrationLogs(t, ctx, ns, "pre-built"), TestTimeoutShort).Should(ContainSubstring("Magicstring!"))
g.Expect(Kamel(t, ctx, "delete", "pre-built", "-n", ns).Execute()).To(Succeed())
Expand All @@ -112,7 +129,6 @@ func TestOperatorIDFiltering(t *testing.T) {
t.Run("Operators can run scoped Pipes", func(t *testing.T) {
g.Expect(KamelBindWithID(t, ctx, "operator-x", ns, "timer-source?message=Hello", "log-sink", "--name", "klb", "--force").Execute()).To(Succeed())
g.Consistently(Integration(t, ctx, ns, "klb"), 10*time.Second).Should(BeNil())

g.Expect(AssignPipeToOperator(t, ctx, ns, "klb", operator1)).To(Succeed())
g.Eventually(Integration(t, ctx, ns, "klb"), TestTimeoutShort).ShouldNot(BeNil())
g.Eventually(IntegrationPhase(t, ctx, ns, "klb"), TestTimeoutMedium).Should(Equal(v1.IntegrationPhaseRunning))
Expand Down
30 changes: 6 additions & 24 deletions e2e/install/cli/global_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ import (
"fmt"
"strings"
"testing"

ctrl "sigs.k8s.io/controller-runtime/pkg/client"
"time"

. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -120,6 +119,9 @@ func TestRunGlobalInstall(t *testing.T) {
g.Eventually(IntegrationLogs(t, ctx, ns5, "java"), TestTimeoutShort).Should(ContainSubstring("Magicstring!"))
g.Expect(IntegrationConditionMessage(IntegrationCondition(t, ctx, ns5, "java", v1.IntegrationConditionPlatformAvailable)())).To(MatchRegexp(operatorNamespace + "\\/.*"))
kit := IntegrationKit(t, ctx, ns5, "java")()
g.Expect(kit).NotTo(BeEmpty())
kitImage := KitImage(t, ctx, operatorNamespace, kit)()
g.Expect(kitImage).NotTo(BeEmpty())
g.Expect(Kamel(t, ctx, "delete", "--all", "-n", ns5).Execute()).To(Succeed())
g.Expect(Kits(t, ctx, ns5)()).Should(WithTransform(integrationKitsToNamesTransform(), Not(ContainElement(kit))))
globalKits := Kits(t, ctx, operatorNamespace)()
Expand All @@ -135,12 +137,13 @@ func TestRunGlobalInstall(t *testing.T) {
},
},
Spec: v1.IntegrationKitSpec{
Image: getKitImage(t, ctx, operatorNamespace, kit),
Image: kitImage,
},
}
g.Expect(TestClient(t).Create(ctx, &externalKit)).Should(BeNil())

g.Expect(KamelRun(t, ctx, ns5, "files/Java.java", "--name", "ext", "--kit", "external").Execute()).To(Succeed())
g.Consistently(IntegrationPhase(t, ctx, ns5, "ext"), 10*time.Second).ShouldNot(Equal(v1.IntegrationPhaseBuildingKit))
g.Eventually(IntegrationPodPhase(t, ctx, ns5, "ext"), TestTimeoutLong).Should(Equal(corev1.PodRunning))
g.Eventually(IntegrationLogs(t, ctx, ns5, "ext"), TestTimeoutShort).Should(ContainSubstring("Magicstring!"))
g.Expect(IntegrationKit(t, ctx, ns5, "ext")()).Should(Equal("external"))
Expand All @@ -165,24 +168,3 @@ func integrationKitsToNamesTransform() func([]v1.IntegrationKit) []string {
return names
}
}

func getKitImage(t *testing.T, ctx context.Context, ns string, name string) string {
get := v1.IntegrationKit{
TypeMeta: metav1.TypeMeta{
Kind: "IntegrationKit",
APIVersion: v1.SchemeGroupVersion.String(),
},
ObjectMeta: metav1.ObjectMeta{
Namespace: ns,
Name: name,
},
}
key := ctrl.ObjectKey{
Namespace: ns,
Name: name,
}
if err := TestClient(t).Get(ctx, key, &get); err != nil {
return ""
}
return get.Status.Image
}
10 changes: 10 additions & 0 deletions e2e/support/test_support.go
Original file line number Diff line number Diff line change
Expand Up @@ -1154,6 +1154,16 @@ func KitPhase(t *testing.T, ctx context.Context, ns, name string) func() v1.Inte
}
}

func KitImage(t *testing.T, ctx context.Context, ns, name string) func() string {
return func() string {
kit := Kit(t, ctx, ns, name)()
if kit == nil {
return ""
}
return kit.Status.Image
}
}

func KitCondition(t *testing.T, ctx context.Context, ns string, name string, conditionType v1.IntegrationKitConditionType) func() *v1.IntegrationKitCondition {
return func() *v1.IntegrationKitCondition {
kt := Kit(t, ctx, ns, name)()
Expand Down
24 changes: 14 additions & 10 deletions helm/camel-k/crds/crd-integration-platform.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -692,7 +692,13 @@ spec:
Service.
type: boolean
image:
description: The main container image
description: The main container image to use for the Integration.
When using this parameter the operator will create a synthetic
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
imagePullPolicy:
description: 'The pull policy: Always|Never|IfNotPresent'
Expand All @@ -701,10 +707,6 @@ spec:
- Never
- IfNotPresent
type: string
imageWasKit:
description: A flag to mark the image used is coming from
an IntegrationKit created externally.
type: boolean
limitCPU:
description: The maximum amount of CPU required.
type: string
Expand Down Expand Up @@ -2598,7 +2600,13 @@ spec:
Service.
type: boolean
image:
description: The main container image
description: The main container image to use for the Integration.
When using this parameter the operator will create a synthetic
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
imagePullPolicy:
description: 'The pull policy: Always|Never|IfNotPresent'
Expand All @@ -2607,10 +2615,6 @@ spec:
- Never
- IfNotPresent
type: string
imageWasKit:
description: A flag to mark the image used is coming from
an IntegrationKit created externally.
type: boolean
limitCPU:
description: The maximum amount of CPU required.
type: string
Expand Down
24 changes: 14 additions & 10 deletions helm/camel-k/crds/crd-integration-profile.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -569,7 +569,13 @@ spec:
Service.
type: boolean
image:
description: The main container image
description: The main container image to use for the Integration.
When using this parameter the operator will create a synthetic
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
imagePullPolicy:
description: 'The pull policy: Always|Never|IfNotPresent'
Expand All @@ -578,10 +584,6 @@ spec:
- Never
- IfNotPresent
type: string
imageWasKit:
description: A flag to mark the image used is coming from
an IntegrationKit created externally.
type: boolean
limitCPU:
description: The maximum amount of CPU required.
type: string
Expand Down Expand Up @@ -2358,7 +2360,13 @@ spec:
Service.
type: boolean
image:
description: The main container image
description: The main container image to use for the Integration.
When using this parameter the operator will create a synthetic
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
imagePullPolicy:
description: 'The pull policy: Always|Never|IfNotPresent'
Expand All @@ -2367,10 +2375,6 @@ spec:
- Never
- IfNotPresent
type: string
imageWasKit:
description: A flag to mark the image used is coming from
an IntegrationKit created externally.
type: boolean
limitCPU:
description: The maximum amount of CPU required.
type: string
Expand Down
12 changes: 7 additions & 5 deletions helm/camel-k/crds/crd-integration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6588,7 +6588,13 @@ spec:
Service.
type: boolean
image:
description: The main container image
description: The main container image to use for the Integration.
When using this parameter the operator will create a synthetic
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
imagePullPolicy:
description: 'The pull policy: Always|Never|IfNotPresent'
Expand All @@ -6597,10 +6603,6 @@ spec:
- Never
- IfNotPresent
type: string
imageWasKit:
description: A flag to mark the image used is coming from
an IntegrationKit created externally.
type: boolean
limitCPU:
description: The maximum amount of CPU required.
type: string
Expand Down
Loading

0 comments on commit 21e0339

Please sign in to comment.