Skip to content

Commit

Permalink
doc(runtimes): kamel --image instructions
Browse files Browse the repository at this point in the history
  • Loading branch information
squakez committed Oct 25, 2023
1 parent 27e07a2 commit b1a94df
Show file tree
Hide file tree
Showing 21 changed files with 81 additions and 43 deletions.
2 changes: 1 addition & 1 deletion addons/telemetry/telemetry.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func (t *telemetryTrait) Configure(e *trait.Environment) (bool, *trait.TraitCond
condition = trait.NewIntegrationCondition(
v1.IntegrationConditionTraitInfo,
corev1.ConditionTrue,
"Tracing endpoint",
"TracingEndpoint",
endpoint,
)
t.Endpoint = endpoint
Expand Down
1 change: 1 addition & 0 deletions docs/modules/ROOT/nav.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
** xref:running/dev-mode.adoc[Developer mode]
** xref:running/dry-run.adoc[Dry run]
** xref:running/runtime-version.adoc[Camel version]
** xref:running/camel-runtimes.adoc[Camel runtimes]
** xref:running/quarkus-native.adoc[Quarkus Native]
** xref:running/run-from-github.adoc[Run from GitHub]
** xref:running/promoting.adoc[Promote an Integration]
Expand Down
22 changes: 22 additions & 0 deletions docs/modules/ROOT/pages/running/camel-runtimes.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
= Camel Runtimes

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.

This option is quite interesting if in general you're building your applications externally, ie, via a CICD technology, and you want to delegate the operator only the "operational" part, taking care on your own of the building and publishing part.

NOTE: you may loose more features, such as incremental image and container kit reusability.

[[build-and-run]]
== Build externally, run via Operator

Let's see a very simple example in action.

You can have your own Camel application or just create a basic one for the purpose via Camel JBang (`camel init test.yaml`). Once your development is over, you can test locally via `camel run test.yaml` and export in the runtime of your choice via `camel export test.yaml --runtime ...`.

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.

NOTE: Jvm trait 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.
3 changes: 3 additions & 0 deletions e2e/common/runtimes/runtimes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ func TestSourceLessIntegrations(t *testing.T) {
Expect(KamelRunWithID(operatorID, ns, "--image", "docker.io/squakez/my-camel-main:1.0.0", "--resource", "configmap:my-cm-sourceless@/tmp/app/data").Execute()).To(Succeed())
Eventually(IntegrationPodPhase(ns, itName), TestTimeoutShort).Should(Equal(corev1.PodRunning))
Eventually(IntegrationConditionStatus(ns, itName, v1.IntegrationConditionReady), TestTimeoutShort).Should(Equal(corev1.ConditionTrue))
Eventually(IntegrationCondition(ns, itName, v1.IntegrationConditionTraitInfo)().Message).Should(Equal("explicitly disabled by the platform: container image was not built via Camel K operator"))
Eventually(IntegrationLogs(ns, itName), TestTimeoutShort).Should(ContainSubstring(cmData["my-file.txt"]))
Eventually(IntegrationLogs(ns, itName), TestTimeoutShort).Should(ContainSubstring("Apache Camel (Main)"))
})
Expand All @@ -53,6 +54,7 @@ func TestSourceLessIntegrations(t *testing.T) {
Expect(KamelRunWithID(operatorID, ns, "--image", "docker.io/squakez/my-camel-sb:1.0.0", "--resource", "configmap:my-cm-sourceless@/tmp/app/data").Execute()).To(Succeed())
Eventually(IntegrationPodPhase(ns, itName), TestTimeoutShort).Should(Equal(corev1.PodRunning))
Eventually(IntegrationConditionStatus(ns, itName, v1.IntegrationConditionReady), TestTimeoutShort).Should(Equal(corev1.ConditionTrue))
Eventually(IntegrationCondition(ns, itName, v1.IntegrationConditionTraitInfo)().Message).Should(Equal("explicitly disabled by the platform: container image was not built via Camel K operator"))
Eventually(IntegrationLogs(ns, itName), TestTimeoutShort).Should(ContainSubstring(cmData["my-file.txt"]))
Eventually(IntegrationLogs(ns, itName), TestTimeoutShort).Should(ContainSubstring("Spring Boot"))
})
Expand All @@ -62,6 +64,7 @@ func TestSourceLessIntegrations(t *testing.T) {
Expect(KamelRunWithID(operatorID, ns, "--image", "docker.io/squakez/my-camel-quarkus:1.0.0", "--resource", "configmap:my-cm-sourceless@/tmp/app/data").Execute()).To(Succeed())
Eventually(IntegrationPodPhase(ns, itName), TestTimeoutShort).Should(Equal(corev1.PodRunning))
Eventually(IntegrationConditionStatus(ns, itName, v1.IntegrationConditionReady), TestTimeoutShort).Should(Equal(corev1.ConditionTrue))
Eventually(IntegrationCondition(ns, itName, v1.IntegrationConditionTraitInfo)().Message).Should(Equal("explicitly disabled by the platform: container image was not built via Camel K operator"))
Eventually(IntegrationLogs(ns, itName), TestTimeoutShort).Should(ContainSubstring(cmData["my-file.txt"]))
Eventually(IntegrationLogs(ns, itName), TestTimeoutShort).Should(ContainSubstring("powered by Quarkus"))
})
Expand Down
3 changes: 1 addition & 2 deletions e2e/commonwithcustominstall/incremental_build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ import (
"github.com/apache/camel-k/v2/pkg/util/defaults"
)

/*
func TestRunIncrementalBuildRoutine(t *testing.T) {
WithNewTestNamespace(t, func(ns string) {
operatorID := "camel-k-incremental-build"
Expand Down Expand Up @@ -191,7 +190,7 @@ func TestRunIncrementalBuildOff(t *testing.T) {
Expect(Kamel("delete", "--all", "-n", ns).Execute()).To(Succeed())
})
}
*/

func TestRunIncrementalBuildWithDifferentBaseImages(t *testing.T) {
WithNewTestNamespace(t, func(ns string) {
operatorID := "camel-k-standard-build"
Expand Down
6 changes: 5 additions & 1 deletion pkg/apis/camel/v1/trait/jvm.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ limitations under the License.

package trait

// The JVM trait is used to configure the JVM that runs the integration.
// The JVM trait is used to configure the JVM that runs the Integration. This trait can be configured only for Integration and related IntegrationKits
// (bound to a container image) built by Camel K operator. If the system detects the usage of a different container image (ie, built externally), then, the
// trait is disabled by the platform.
//
// NOTE: the platform will skip the trait configuration for those container image matching `camel-k-kit-` name.
//
// +camel-k:trait=jvm.
type JVMTrait struct {
Expand Down
1 change: 0 additions & 1 deletion pkg/cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,6 @@ func (o *runCmdOptions) createOrUpdateIntegration(cmd *cobra.Command, c client.C
} else {
// Source-less Integration as the user provided a container image built externally
o.Traits = append(o.Traits, fmt.Sprintf("container.image=%s", o.ContainerImage))
o.Traits = append(o.Traits, "jvm.enabled=false")
}

if err := resolvePodTemplate(context.Background(), cmd, o.PodTemplate, &integration.Spec); err != nil {
Expand Down
2 changes: 0 additions & 2 deletions pkg/cmd/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -840,8 +840,6 @@ spec:
traits:
container:
image: docker.io/my-org/my-app:1.0.0
jvm:
enabled: false
mount:
configs:
- configmap:my-cm
Expand Down
8 changes: 4 additions & 4 deletions pkg/trait/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ func (t *builderTrait) adaptDeprecatedFields() *TraitCondition {
m := "The limit-memory parameter is deprecated and may be removed in future releases. Make sure to use tasks-limit-memory parameter instead."
t.L.Info(m)
if condition == nil {
condition = NewIntegrationCondition(v1.IntegrationConditionTraitInfo, corev1.ConditionTrue, traitConfigurationMessage, "")
condition = NewIntegrationCondition(v1.IntegrationConditionTraitInfo, corev1.ConditionTrue, traitConfigurationReason, "")
}
condition = newOrAppend(condition, m)
t.TasksLimitMemory = append(t.TasksLimitMemory, fmt.Sprintf("builder:%s", t.LimitMemory))
Expand All @@ -135,11 +135,11 @@ func (t *builderTrait) adaptDeprecatedFields() *TraitCondition {
return condition
}

func newOrAppend(condition *TraitCondition, reason string) *TraitCondition {
func newOrAppend(condition *TraitCondition, message string) *TraitCondition {
if condition == nil {
condition = NewIntegrationCondition(v1.IntegrationConditionTraitInfo, corev1.ConditionTrue, traitConfigurationMessage, reason)
condition = NewIntegrationCondition(v1.IntegrationConditionTraitInfo, corev1.ConditionTrue, traitConfigurationReason, message)
} else {
condition.reason += "; " + reason
condition.message += "; " + message
}

return condition
Expand Down
8 changes: 4 additions & 4 deletions pkg/trait/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -429,10 +429,10 @@ func TestBuilderDeprecatedParams(t *testing.T) {
assert.Nil(t, err)
assert.True(t, active)
assert.NotNil(t, condition)
assert.Contains(t, condition.reason, "The request-cpu parameter is deprecated and may be removed in future releases")
assert.Contains(t, condition.reason, "The limit-cpu parameter is deprecated and may be removed in future releases")
assert.Contains(t, condition.reason, "The request-memory parameter is deprecated and may be removed in future releases")
assert.Contains(t, condition.reason, "The limit-memory parameter is deprecated and may be removed in future releases")
assert.Contains(t, condition.message, "The request-cpu parameter is deprecated and may be removed in future releases")
assert.Contains(t, condition.message, "The limit-cpu parameter is deprecated and may be removed in future releases")
assert.Contains(t, condition.message, "The request-memory parameter is deprecated and may be removed in future releases")
assert.Contains(t, condition.message, "The limit-memory parameter is deprecated and may be removed in future releases")
assert.Len(t, builderTrait.TasksLimitCPU, 1)
assert.Len(t, builderTrait.TasksRequestCPU, 1)
assert.Len(t, builderTrait.TasksLimitMemory, 1)
Expand Down
6 changes: 6 additions & 0 deletions pkg/trait/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"errors"
"fmt"
"path/filepath"
"strings"

appsv1 "k8s.io/api/apps/v1"
batchv1 "k8s.io/api/batch/v1"
Expand Down Expand Up @@ -347,3 +348,8 @@ func (t *containerTrait) configureSecurityContext(e *Environment, container *cor
}
}
}

// It's a user provided image if it does not match the naming convention used by Camel K Integration Kits.
func (t *containerTrait) hasUserProvidedImage() bool {
return t.Image != "" && !strings.Contains(t.Image, "camel-k-kit-")
}
4 changes: 2 additions & 2 deletions pkg/trait/container_probes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,13 +186,13 @@ func TestProbesOnKnativeService(t *testing.T) {
serviceOverrideCondition := NewIntegrationCondition(
v1.IntegrationConditionTraitInfo,
corev1.ConditionTrue,
"service trait configuration",
"serviceTraitConfiguration",
"explicitly disabled by the platform: knative-service trait has priority over this trait",
)
ctrlStrategyCondition := NewIntegrationCondition(
v1.IntegrationConditionDeploymentAvailable,
corev1.ConditionFalse,
"deployment trait configuration",
"deploymentTraitConfiguration",
"controller strategy: knative-service",
)

Expand Down
4 changes: 2 additions & 2 deletions pkg/trait/cron_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ func TestCronWithActiveDeadline(t *testing.T) {
expectedCondition := NewIntegrationCondition(
v1.IntegrationConditionDeploymentAvailable,
corev1.ConditionFalse,
"deployment trait configuration",
"deploymentTraitConfiguration",
"controller strategy: cron-job",
)
conditions, err := tc.apply(&environment)
Expand Down Expand Up @@ -532,7 +532,7 @@ func TestCronWithBackoffLimit(t *testing.T) {
expectedCondition := NewIntegrationCondition(
v1.IntegrationConditionDeploymentAvailable,
corev1.ConditionFalse,
"deployment trait configuration",
"deploymentTraitConfiguration",
"controller strategy: cron-job",
)
conditions, err := tc.apply(&environment)
Expand Down
2 changes: 1 addition & 1 deletion pkg/trait/gc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func TestConfigureDisabledGCTraitDoesNotSucceed(t *testing.T) {
expectedCondition := NewIntegrationCondition(
v1.IntegrationConditionTraitInfo,
corev1.ConditionTrue,
"Trait configuration",
"TraitConfiguration",
"explicitly disabled by the user",
)
configured, condition, err := gcTrait.Configure(environment)
Expand Down
14 changes: 10 additions & 4 deletions pkg/trait/jvm.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,16 @@ func (t *jvmTrait) Configure(e *Environment) (bool, *TraitCondition, error) {
return false, nil, nil
}

if trait := e.Catalog.GetTrait(quarkusTraitID); trait != nil {
// The JVM trait must be disabled in case the current IntegrationKit corresponds to a native build
if quarkus, ok := trait.(*quarkusTrait); ok && quarkus.isNativeIntegration(e) {
return false, newIntegrationConditionPlatformDisabledWithReason("Quarkus native build"), nil
// The JVM trait must be disabled in case the current IntegrationKit corresponds to a native build
if qt := e.Catalog.GetTrait(quarkusTraitID); qt != nil {
if quarkus, ok := qt.(*quarkusTrait); ok && quarkus.isNativeIntegration(e) {
return false, newIntegrationConditionPlatformDisabledWithMessage("quarkus native build"), nil
}
}
// The JVM trait must be disabled if it's a user based build (for which we do not control the way to handle JVM parameters)
if ct := e.Catalog.GetTrait(containerTraitID); ct != nil {
if ct, ok := ct.(*containerTrait); ok && ct.hasUserProvidedImage() {
return false, newIntegrationConditionPlatformDisabledWithMessage("container image was not built via Camel K operator"), nil
}
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/trait/quarkus.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ func (t *quarkusTrait) adaptDeprecatedFields() *TraitCondition {
t.Modes = append(t.Modes, traitv1.JvmQuarkusMode)
}
}
return NewIntegrationCondition(v1.IntegrationConditionTraitInfo, corev1.ConditionTrue, traitConfigurationMessage, message)
return NewIntegrationCondition(v1.IntegrationConditionTraitInfo, corev1.ConditionTrue, traitConfigurationReason, message)
}

return nil
Expand Down
2 changes: 1 addition & 1 deletion pkg/trait/route_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ func TestRoute_Disabled(t *testing.T) {
expectedCondition := NewIntegrationCondition(
v1.IntegrationConditionExposureAvailable,
corev1.ConditionFalse,
"route trait configuration",
"routeTraitConfiguration",
"explicitly disabled",
)
traitsCatalog := environment.Catalog
Expand Down
2 changes: 1 addition & 1 deletion pkg/trait/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func (t *serviceTrait) Configure(e *Environment) (bool, *TraitCondition, error)
if e.GetTrait(knativeServiceTraitID) != nil {
knativeServiceTrait, _ := e.GetTrait(knativeServiceTraitID).(*knativeServiceTrait)
if pointer.BoolDeref(knativeServiceTrait.Enabled, true) {
return false, newIntegrationConditionPlatformDisabledWithReason("knative-service trait has priority over this trait"), nil
return false, newIntegrationConditionPlatformDisabledWithMessage("knative-service trait has priority over this trait"), nil
}
}

Expand Down
10 changes: 5 additions & 5 deletions pkg/trait/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -494,13 +494,13 @@ func TestServiceWithKnativeServiceEnabled(t *testing.T) {
deploymentCondition := NewIntegrationCondition(
v1.IntegrationConditionDeploymentAvailable,
corev1.ConditionFalse,
"deployment trait configuration",
"deploymentTraitConfiguration",
"controller strategy: knative-service",
)
serviceCondition := NewIntegrationCondition(
v1.IntegrationConditionTraitInfo,
corev1.ConditionTrue,
"service trait configuration",
"serviceTraitConfiguration",
"explicitly disabled by the platform: knative-service trait has priority over this trait",
)
conditions, err := traitCatalog.apply(&environment)
Expand Down Expand Up @@ -572,13 +572,13 @@ func TestServicesWithKnativeProfile(t *testing.T) {
deploymentCondition := NewIntegrationCondition(
v1.IntegrationConditionDeploymentAvailable,
corev1.ConditionFalse,
"deployment trait configuration",
"deploymentTraitConfiguration",
"controller strategy: knative-service",
)
serviceCondition := NewIntegrationCondition(
v1.IntegrationConditionTraitInfo,
corev1.ConditionTrue,
"service trait configuration",
"serviceTraitConfiguration",
"explicitly disabled by the platform: knative-service trait has priority over this trait",
)
conditions, err := traitCatalog.apply(&environment)
Expand Down Expand Up @@ -658,7 +658,7 @@ func TestServiceWithKnativeServiceDisabledInIntegrationPlatform(t *testing.T) {
expectedCondition := NewIntegrationCondition(
v1.IntegrationConditionKnativeServiceAvailable,
corev1.ConditionFalse,
"knative-service trait configuration",
"knative-serviceTraitConfiguration",
"explicitly disabled",
)
conditions, err := traitCatalog.apply(&environment)
Expand Down
2 changes: 1 addition & 1 deletion pkg/trait/trait_catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ func (c *Catalog) apply(environment *Environment) ([]*TraitCondition, error) {
applicable = true
enabled, condition, err := trait.Configure(environment)
if condition != nil {
condition.message = fmt.Sprintf("%s trait configuration", trait.ID())
condition.reason = fmt.Sprintf("%sTraitConfiguration", trait.ID())
traitsConditions = append(traitsConditions, condition)
}
if err != nil {
Expand Down
20 changes: 10 additions & 10 deletions pkg/trait/trait_condition_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ import (
)

const (
traitConfigurationMessage = "Trait configuration"
userDisabledMessage = "explicitly disabled by the user"
platformDisabledMessage = "explicitly disabled by the platform"
traitConfigurationReason = "TraitConfiguration"
userDisabledMessage = "explicitly disabled by the user"
platformDisabledMessage = "explicitly disabled by the platform"
)

// TraitCondition is used to get all information/warning about a trait configuration.
Expand All @@ -41,27 +41,27 @@ type TraitCondition struct {
reason string
}

func NewIntegrationCondition(ict v1.IntegrationConditionType, cs corev1.ConditionStatus, message, reason string) *TraitCondition {
func NewIntegrationCondition(ict v1.IntegrationConditionType, cs corev1.ConditionStatus, reason, message string) *TraitCondition {
return &TraitCondition{
integrationConditionType: ict,
conditionStatus: cs,
message: message,
reason: reason,
message: message,
}
}

func NewIntegrationConditionUserDisabled() *TraitCondition {
return NewIntegrationCondition(v1.IntegrationConditionTraitInfo, corev1.ConditionTrue, traitConfigurationMessage, userDisabledMessage)
return NewIntegrationCondition(v1.IntegrationConditionTraitInfo, corev1.ConditionTrue, traitConfigurationReason, userDisabledMessage)
}

func newIntegrationConditionPlatformDisabledWithReason(reason string) *TraitCondition {
return NewIntegrationCondition(v1.IntegrationConditionTraitInfo, corev1.ConditionTrue, traitConfigurationMessage, fmt.Sprintf("%s: %s", platformDisabledMessage, reason))
func newIntegrationConditionPlatformDisabledWithMessage(message string) *TraitCondition {
return NewIntegrationCondition(v1.IntegrationConditionTraitInfo, corev1.ConditionTrue, traitConfigurationReason, fmt.Sprintf("%s: %s", platformDisabledMessage, message))
}

func (tc *TraitCondition) integrationCondition() (v1.IntegrationConditionType, corev1.ConditionStatus, string, string) {
return tc.integrationConditionType, tc.conditionStatus, tc.message, tc.reason
return tc.integrationConditionType, tc.conditionStatus, tc.reason, tc.message
}

func (tc *TraitCondition) integrationKitCondition() (v1.IntegrationKitConditionType, corev1.ConditionStatus, string, string) {
return tc.integrationKitConditionType, tc.conditionStatus, tc.message, tc.reason
return tc.integrationKitConditionType, tc.conditionStatus, tc.reason, tc.message
}

0 comments on commit b1a94df

Please sign in to comment.