You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by pc...@apache.org on 2024/09/14 05:23:38 UTC
(camel-k) branch main updated (6dbded5ab -> fa10c8d30)
This is an automated email from the ASF dual-hosted git repository.
pcongiusti pushed a change to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git
from 6dbded5ab feat(kamelets): bundling from jar
new dcb7f36cf fix(ctrl): resume from unknown
new fa10c8d30 fix(kamelets): don't fail on Kamelets recreation
The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.../{reset_test.go => operator_restart_test.go} | 54 +++++-----
e2e/advanced/operator_resume_unknown_test.go | 93 ++++++++++++++++
e2e/support/test_support.go | 29 ++++-
pkg/controller/integration/monitor.go | 8 +-
pkg/controller/integration/monitor_test.go | 120 +++++++++++++++++++++
pkg/controller/integration/monitor_unknown.go | 6 ++
pkg/controller/integrationplatform/create.go | 21 ++--
pkg/controller/integrationplatform/create_test.go | 23 +++-
pkg/controller/integrationplatform/kamelets.go | 15 ++-
.../integrationplatform/kamelets_test.go | 3 +-
10 files changed, 326 insertions(+), 46 deletions(-)
copy e2e/advanced/{reset_test.go => operator_restart_test.go} (52%)
create mode 100644 e2e/advanced/operator_resume_unknown_test.go
(camel-k) 01/02: fix(ctrl): resume from unknown
Posted by pc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
pcongiusti pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git
commit dcb7f36cff7f3cbc56b2b9ed7dc94df31600a65a
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Fri Sep 13 07:40:55 2024 +0200
fix(ctrl): resume from unknown
If an IntegrationPlatform is deleted, when the Integration requires monitoring it fails
---
e2e/advanced/operator_restart_test.go | 81 +++++++++++++++++
e2e/advanced/operator_resume_unknown_test.go | 93 ++++++++++++++++++++
e2e/support/test_support.go | 29 ++++++-
pkg/controller/integration/monitor.go | 8 +-
pkg/controller/integration/monitor_test.go | 120 ++++++++++++++++++++++++++
pkg/controller/integration/monitor_unknown.go | 6 ++
6 files changed, 335 insertions(+), 2 deletions(-)
diff --git a/e2e/advanced/operator_restart_test.go b/e2e/advanced/operator_restart_test.go
new file mode 100644
index 000000000..0f84972d5
--- /dev/null
+++ b/e2e/advanced/operator_restart_test.go
@@ -0,0 +1,81 @@
+//go:build integration
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "integration"
+
+/*
+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 advanced
+
+import (
+ "context"
+ "testing"
+ "time"
+
+ . "github.com/onsi/gomega"
+ corev1 "k8s.io/api/core/v1"
+
+ . "github.com/apache/camel-k/v2/e2e/support"
+ v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
+)
+
+func TestOperatorRestart(t *testing.T) {
+ t.Parallel()
+
+ WithNewTestNamespace(t, func(ctx context.Context, g *WithT, ns string) {
+ name := RandomizedSuffixName("yaml")
+
+ t.Run("Operator started", func(t *testing.T) {
+ InstallOperator(t, ctx, g, ns)
+ g.Eventually(OperatorPod(t, ctx, ns)).Should(Not(BeNil()))
+ g.Eventually(PlatformPhase(t, ctx, ns), TestTimeoutShort).Should(Equal(v1.IntegrationPlatformPhaseReady))
+ g.Expect(KamelRun(t, ctx, ns, "files/yaml.yaml", "--name", name).Execute()).To(Succeed())
+ g.Eventually(IntegrationPhase(t, ctx, ns, name), TestTimeoutMedium).Should(Equal(v1.IntegrationPhaseRunning))
+ g.Eventually(IntegrationConditionStatus(t, ctx, ns, name, v1.IntegrationConditionReady), TestTimeoutShort).Should(Equal(corev1.ConditionTrue))
+ g.Eventually(IntegrationPodPhase(t, ctx, ns, name), TestTimeoutShort).Should(Equal(corev1.PodRunning))
+ g.Eventually(IntegrationLogs(t, ctx, ns, name), TestTimeoutShort).Should(ContainSubstring("Magicstring!"))
+ g.Eventually(Kit(t, ctx, ns, IntegrationKit(t, ctx, ns, name)())).Should(Not(BeNil()))
+ g.Eventually(Integration(t, ctx, ns, name)).Should(Not(BeNil()))
+ })
+
+ t.Run("Operator uninstalled", func(t *testing.T) {
+ UninstallOperator(t, ctx, g, ns, "../../")
+ g.Eventually(OperatorPod(t, ctx, ns)).Should(BeNil())
+ g.Eventually(Platform(t, ctx, ns)).Should(BeNil())
+ g.Eventually(IntegrationPhase(t, ctx, ns, name), TestTimeoutShort).Should(Equal(v1.IntegrationPhaseRunning))
+ g.Eventually(IntegrationConditionStatus(t, ctx, ns, name, v1.IntegrationConditionReady), TestTimeoutShort).Should(Equal(corev1.ConditionTrue))
+ g.Eventually(IntegrationPodPhase(t, ctx, ns, name), TestTimeoutShort).Should(Equal(corev1.PodRunning))
+ g.Eventually(IntegrationLogs(t, ctx, ns, name), TestTimeoutShort).Should(ContainSubstring("Magicstring!"))
+ g.Eventually(Kit(t, ctx, ns, IntegrationKit(t, ctx, ns, name)())).Should(Not(BeNil()))
+ g.Eventually(Integration(t, ctx, ns, name)).Should(Not(BeNil()))
+ })
+
+ t.Run("Operator reinstalled", func(t *testing.T) {
+ InstallOperator(t, ctx, g, ns)
+ g.Eventually(OperatorPod(t, ctx, ns)).Should(Not(BeNil()))
+ g.Eventually(PlatformPhase(t, ctx, ns), TestTimeoutShort).Should(Equal(v1.IntegrationPlatformPhaseReady))
+ g.Consistently(OperatorLogs(t, ctx, ns), 1*time.Minute, 3*time.Second).Should(Not(ContainSubstring("error")))
+ g.Eventually(IntegrationPhase(t, ctx, ns, name), TestTimeoutShort).Should(Equal(v1.IntegrationPhaseRunning))
+ g.Eventually(IntegrationConditionStatus(t, ctx, ns, name, v1.IntegrationConditionReady), TestTimeoutShort).Should(Equal(corev1.ConditionTrue))
+ g.Eventually(IntegrationPodPhase(t, ctx, ns, name), TestTimeoutShort).Should(Equal(corev1.PodRunning))
+ g.Eventually(IntegrationLogs(t, ctx, ns, name), TestTimeoutShort).Should(ContainSubstring("Magicstring!"))
+ g.Eventually(Kit(t, ctx, ns, IntegrationKit(t, ctx, ns, name)())).Should(Not(BeNil()))
+ g.Eventually(Integration(t, ctx, ns, name)).Should(Not(BeNil()))
+ })
+ })
+}
diff --git a/e2e/advanced/operator_resume_unknown_test.go b/e2e/advanced/operator_resume_unknown_test.go
new file mode 100644
index 000000000..61c4af663
--- /dev/null
+++ b/e2e/advanced/operator_resume_unknown_test.go
@@ -0,0 +1,93 @@
+//go:build integration
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "integration"
+
+/*
+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 advanced
+
+import (
+ "context"
+ "os"
+ "testing"
+ "time"
+
+ . "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"
+)
+
+func TestOperatorResumeFromUnknown(t *testing.T) {
+ t.Parallel()
+
+ WithNewTestNamespace(t, func(ctx context.Context, g *WithT, ns string) {
+ name := RandomizedSuffixName("yaml")
+ containerRegistry, ok := os.LookupEnv("KAMEL_INSTALL_REGISTRY")
+ g.Expect(ok).To(BeTrue(), "You need to provide the registry as KAMEL_INSTALL_REGISTRY env var")
+
+ InstallOperator(t, ctx, g, ns)
+ g.Eventually(OperatorPod(t, ctx, ns)).Should(Not(BeNil()))
+ g.Eventually(PlatformPhase(t, ctx, ns), TestTimeoutShort).Should(Equal(v1.IntegrationPlatformPhaseReady))
+ g.Expect(KamelRun(t, ctx, ns, "files/yaml.yaml", "--name", name).Execute()).To(Succeed())
+ g.Eventually(IntegrationPhase(t, ctx, ns, name), TestTimeoutMedium).Should(Equal(v1.IntegrationPhaseRunning))
+ g.Eventually(IntegrationConditionStatus(t, ctx, ns, name, v1.IntegrationConditionReady), TestTimeoutShort).Should(Equal(corev1.ConditionTrue))
+ g.Eventually(IntegrationConditionStatus(t, ctx, ns, name, v1.IntegrationConditionPlatformAvailable), TestTimeoutShort).Should(Equal(corev1.ConditionTrue))
+ g.Eventually(IntegrationPodPhase(t, ctx, ns, name), TestTimeoutShort).Should(Equal(corev1.PodRunning))
+ g.Eventually(IntegrationLogs(t, ctx, ns, name), TestTimeoutShort).Should(ContainSubstring("Magicstring!"))
+
+ // Delete the IntegrationPlatform: as soon as there is a "monitoring" operation, the Integration
+ // should go in Unknown status as it cannot create traits, therefore, it would fail
+ g.Expect(DeletePlatform(t, ctx, ns)()).To(BeTrue())
+ g.Consistently(IntegrationPhase(t, ctx, ns, name), 1*time.Minute, 5*time.Second).Should(Equal(v1.IntegrationPhaseRunning))
+ g.Eventually(IntegrationConditionStatus(t, ctx, ns, name, v1.IntegrationConditionReady), TestTimeoutShort).Should(Equal(corev1.ConditionTrue))
+ // Asking for a scale operation triggers a monitoring action
+ g.Expect(ScaleIntegration(t, ctx, ns, name, 2)).To(Succeed())
+ g.Eventually(IntegrationPhase(t, ctx, ns, name), TestTimeoutMedium).Should(Equal(v1.IntegrationPhaseUnknown))
+ g.Eventually(IntegrationConditionStatus(t, ctx, ns, name, v1.IntegrationConditionReady), TestTimeoutShort).Should(Equal(corev1.ConditionTrue))
+ g.Eventually(IntegrationConditionStatus(t, ctx, ns, name, v1.IntegrationConditionPlatformAvailable), TestTimeoutShort).Should(Equal(corev1.ConditionFalse))
+ // Fix the platform (create a new one)
+ platform := &v1.IntegrationPlatform{
+ TypeMeta: metav1.TypeMeta{
+ APIVersion: v1.SchemeGroupVersion.String(),
+ Kind: v1.IntegrationPlatformKind,
+ },
+ ObjectMeta: metav1.ObjectMeta{
+ Namespace: ns,
+ Name: "camel-k",
+ },
+ Spec: v1.IntegrationPlatformSpec{
+ Build: v1.IntegrationPlatformBuildSpec{
+ Registry: v1.RegistrySpec{
+ Address: containerRegistry,
+ },
+ },
+ },
+ }
+ g.Expect(CreateIntegrationPlatform(t, ctx, platform)).To(Succeed())
+ g.Eventually(PlatformPhase(t, ctx, ns), TestTimeoutShort).Should(Equal(v1.IntegrationPlatformPhaseReady))
+ // The monitoring should now start correctly
+ g.Eventually(IntegrationPhase(t, ctx, ns, name), TestTimeoutMedium).Should(Equal(v1.IntegrationPhaseRunning))
+ g.Eventually(IntegrationConditionStatus(t, ctx, ns, name, v1.IntegrationConditionReady), TestTimeoutShort).Should(Equal(corev1.ConditionTrue))
+ g.Eventually(IntegrationConditionStatus(t, ctx, ns, name, v1.IntegrationConditionPlatformAvailable), TestTimeoutShort).Should(Equal(corev1.ConditionTrue))
+ g.Eventually(IntegrationPods(t, ctx, ns, name), TestTimeoutShort).Should(HaveLen(2))
+ })
+}
diff --git a/e2e/support/test_support.go b/e2e/support/test_support.go
index 565e21a49..a1fceebaf 100644
--- a/e2e/support/test_support.go
+++ b/e2e/support/test_support.go
@@ -439,6 +439,32 @@ func IntegrationLogs(t *testing.T, ctx context.Context, ns, name string) func()
}
}
+func OperatorLogs(t *testing.T, ctx context.Context, ns string) func() string {
+ return func() string {
+ pod := OperatorPod(t, ctx, ns)()
+ if pod == nil {
+ return ""
+ }
+
+ options := corev1.PodLogOptions{
+ TailLines: ptr.To(int64(200)),
+ }
+
+ for _, container := range pod.Status.ContainerStatuses {
+ if !container.Ready || container.State.Waiting != nil {
+ // avoid logs watch fail due to container creating state
+ return ""
+ }
+ }
+
+ if len(pod.Spec.Containers) > 1 {
+ options.Container = pod.Spec.Containers[0].Name
+ }
+
+ return Logs(t, ctx, ns, pod.Name, options)()
+ }
+}
+
// TailedLogs Retrieve the Logs from the Pod defined by its name in the given namespace ns. The number of lines numLines from the end of the logs to show.
func TailedLogs(t *testing.T, ctx context.Context, ns, name string, numLines int64) func() string {
return func() string {
@@ -2085,8 +2111,9 @@ func DeletePlatform(t *testing.T, ctx context.Context, ns string) func() bool {
}
if err := TestClient(t).Delete(ctx, pl); err != nil {
log.Error(err, "Got error while deleting the platform")
+ return false
}
- return false
+ return true
}
}
diff --git a/pkg/controller/integration/monitor.go b/pkg/controller/integration/monitor.go
index 5c395a86d..8759af19e 100644
--- a/pkg/controller/integration/monitor.go
+++ b/pkg/controller/integration/monitor.go
@@ -140,8 +140,14 @@ func (action *monitorAction) Handle(ctx context.Context, integration *v1.Integra
// If the platform is not in ready status (it may happen when a new IntegrationPlatform is created), then, we may not be able to
// properly apply all the traits. We must set the phase in an unknown status which should be periodically reconciled in order to make sure that
// we eventually return in a ready phase (likely once the platform is done)
- if environment.Platform != nil && environment.Platform.Status.Phase != v1.IntegrationPlatformPhaseReady {
+ if environment.Platform == nil || environment.Platform.Status.Phase != v1.IntegrationPlatformPhaseReady {
integration.Status.Phase = v1.IntegrationPhaseUnknown
+ integration.Status.SetCondition(
+ v1.IntegrationConditionPlatformAvailable,
+ corev1.ConditionFalse,
+ "PlatformMissing",
+ "IntegrationPlatform is missing or not yet ready. If the problem persist, make sure to fix the IntegrationPlatform error or create a new one.",
+ )
return integration, nil
}
action.checkTraitAnnotationsDeprecatedNotice(integration)
diff --git a/pkg/controller/integration/monitor_test.go b/pkg/controller/integration/monitor_test.go
index dbd56507a..1f430037d 100644
--- a/pkg/controller/integration/monitor_test.go
+++ b/pkg/controller/integration/monitor_test.go
@@ -244,11 +244,129 @@ func TestMonitorIntegrationWhilePlatformRecreating(t *testing.T) {
handledIt, err := a.Handle(context.TODO(), it)
require.NoError(t, err)
assert.Equal(t, v1.IntegrationPhaseUnknown, handledIt.Status.Phase)
+ condition := handledIt.Status.GetCondition(v1.IntegrationConditionPlatformAvailable)
+ assert.Equal(t, corev1.ConditionFalse, condition.Status)
+ assert.Equal(t, "PlatformMissing", condition.Reason)
+ assert.Equal(t, "IntegrationPlatform is missing or not yet ready. If the problem persist, "+
+ "make sure to fix the IntegrationPlatform error or create a new one.", condition.Message)
+}
+
+func TestMonitorIntegrationPlatformNil(t *testing.T) {
+ catalog := &v1.CamelCatalog{
+ TypeMeta: metav1.TypeMeta{
+ APIVersion: v1.SchemeGroupVersion.String(),
+ Kind: v1.CamelCatalogKind,
+ },
+ ObjectMeta: metav1.ObjectMeta{
+ Namespace: "ns",
+ Name: "camel-k-catalog",
+ },
+ Spec: v1.CamelCatalogSpec{
+ Runtime: v1.RuntimeSpec{
+ Provider: v1.RuntimeProviderQuarkus,
+ Version: defaults.DefaultRuntimeVersion,
+ },
+ },
+ }
+ kit := &v1.IntegrationKit{
+ TypeMeta: metav1.TypeMeta{
+ APIVersion: v1.SchemeGroupVersion.String(),
+ Kind: v1.IntegrationKitKind,
+ },
+ ObjectMeta: metav1.ObjectMeta{
+ Namespace: "ns",
+ Name: "my-kit",
+ },
+ Status: v1.IntegrationKitStatus{
+ Phase: v1.IntegrationKitPhaseReady,
+ },
+ }
+ it := &v1.Integration{
+ TypeMeta: metav1.TypeMeta{
+ APIVersion: v1.SchemeGroupVersion.String(),
+ Kind: v1.IntegrationKind,
+ },
+ ObjectMeta: metav1.ObjectMeta{
+ Namespace: "ns",
+ Name: "my-it",
+ },
+ Status: v1.IntegrationStatus{
+ RuntimeVersion: defaults.DefaultRuntimeVersion,
+ Phase: v1.IntegrationPhaseRunning,
+ IntegrationKit: &corev1.ObjectReference{
+ Name: kit.Name,
+ Namespace: kit.Namespace,
+ Kind: kit.Kind,
+ APIVersion: kit.APIVersion,
+ },
+ Conditions: []v1.IntegrationCondition{
+ {
+ Type: v1.IntegrationConditionDeploymentAvailable,
+ Status: corev1.ConditionTrue,
+ },
+ {
+ Type: v1.IntegrationConditionReady,
+ Status: corev1.ConditionTrue,
+ },
+ },
+ },
+ }
+ hash, _ := digest.ComputeForIntegration(it, nil, nil)
+ it.Status.Digest = hash
+ 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-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 := test.NewFakeClient(catalog, it, kit, pod)
+ require.NoError(t, err)
+
+ a := monitorAction{}
+ a.InjectLogger(log.Log)
+ a.InjectClient(c)
+ assert.Equal(t, "monitor", a.Name())
+ assert.True(t, a.CanHandle(it))
+ handledIt, err := a.Handle(context.TODO(), it)
+ require.NoError(t, err)
+ assert.Equal(t, v1.IntegrationPhaseUnknown, handledIt.Status.Phase)
+ condition := handledIt.Status.GetCondition(v1.IntegrationConditionPlatformAvailable)
+ assert.Equal(t, corev1.ConditionFalse, condition.Status)
+ assert.Equal(t, "PlatformMissing", condition.Reason)
+ assert.Equal(t, "IntegrationPlatform is missing or not yet ready. If the problem persist, "+
+ "make sure to fix the IntegrationPlatform error or create a new one.", condition.Message)
}
func TestMonitorIntegrationRecoverFromUnknown(t *testing.T) {
c, it, err := nominalEnvironment()
it.Status.Phase = v1.IntegrationPhaseUnknown
+ it.Status.SetCondition(
+ v1.IntegrationConditionPlatformAvailable, corev1.ConditionFalse, "PlatformMissing",
+ "IntegrationPlatform is missing or not yet ready. If the problem persist, make sure to fix the IntegrationPlatform error or create a new one.")
require.NoError(t, err)
a := monitorUnknownAction{}
@@ -259,6 +377,8 @@ func TestMonitorIntegrationRecoverFromUnknown(t *testing.T) {
handledIt, err := a.Handle(context.TODO(), it)
require.NoError(t, err)
assert.Equal(t, v1.IntegrationPhaseRunning, handledIt.Status.Phase)
+ condition := handledIt.Status.GetCondition(v1.IntegrationConditionPlatformAvailable)
+ assert.Equal(t, corev1.ConditionTrue, condition.Status)
}
func nominalEnvironment() (client.Client, *v1.Integration, error) {
diff --git a/pkg/controller/integration/monitor_unknown.go b/pkg/controller/integration/monitor_unknown.go
index e9e1cbc30..98c966ace 100644
--- a/pkg/controller/integration/monitor_unknown.go
+++ b/pkg/controller/integration/monitor_unknown.go
@@ -54,6 +54,12 @@ func (action *monitorUnknownAction) Handle(ctx context.Context, integration *v1.
// We're good to monitor this again
if environment.Platform != nil && environment.Platform.Status.Phase == v1.IntegrationPlatformPhaseReady {
integration.Status.Phase = v1.IntegrationPhaseRunning
+ integration.Status.SetCondition(
+ v1.IntegrationConditionPlatformAvailable,
+ corev1.ConditionTrue,
+ v1.IntegrationConditionPlatformAvailableReason,
+ environment.Platform.Namespace+"/"+environment.Platform.Name,
+ )
return integration, nil
}
(camel-k) 02/02: fix(kamelets): don't fail on Kamelets recreation
Posted by pc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
pcongiusti pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git
commit fa10c8d303ddbce697feab25c04f8fbece79c06e
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Fri Sep 13 16:37:03 2024 +0200
fix(kamelets): don't fail on Kamelets recreation
---
pkg/controller/integrationplatform/create.go | 21 ++++++++++----------
pkg/controller/integrationplatform/create_test.go | 23 +++++++++++++++++++++-
pkg/controller/integrationplatform/kamelets.go | 15 ++++++++++----
.../integrationplatform/kamelets_test.go | 3 ++-
4 files changed, 45 insertions(+), 17 deletions(-)
diff --git a/pkg/controller/integrationplatform/create.go b/pkg/controller/integrationplatform/create.go
index 85edbf94a..55e9ca3f3 100644
--- a/pkg/controller/integrationplatform/create.go
+++ b/pkg/controller/integrationplatform/create.go
@@ -167,23 +167,22 @@ func installKamelets(ctx context.Context, c client.Client, platform *v1.Integrat
camelVersion := platform.Status.Build.RuntimeCoreVersion
installedKam, erroredKam, err := installKameletCatalog(ctx, c, platform, camelVersion)
if err != nil {
- platform.Status.Phase = v1.IntegrationPlatformPhaseError
+ // An error here should not be disruptive, we just report it happened
platform.Status.SetCondition(
v1.IntegrationPlatformConditionKameletCatalogAvailable,
corev1.ConditionFalse,
"IntegrationPlatformKameletCatalogAvailable",
- fmt.Sprintf("kamelet catalog %s not available, please review given camel version. Error: %s", camelVersion, err),
+ fmt.Sprintf("kamelet catalog %s not available. Error: %s", camelVersion, err),
+ )
+ } else {
+ platform.Status.SetCondition(
+ v1.IntegrationPlatformConditionKameletCatalogAvailable,
+ corev1.ConditionTrue,
+ "IntegrationPlatformKameletCatalogAvailable",
+ fmt.Sprintf("successfully installed Kamelet catalog version %s: success %d Kamelets, failed %d Kamelets",
+ camelVersion, installedKam, erroredKam),
)
-
- return platform, nil
}
- platform.Status.SetCondition(
- v1.IntegrationPlatformConditionKameletCatalogAvailable,
- corev1.ConditionTrue,
- "IntegrationPlatformKameletCatalogAvailable",
- fmt.Sprintf("successfully installed Kamelet catalog version %s: success %d Kamelets, failed %d Kamelets",
- camelVersion, installedKam, erroredKam),
- )
}
return platform, nil
diff --git a/pkg/controller/integrationplatform/create_test.go b/pkg/controller/integrationplatform/create_test.go
index c47532070..0124a81db 100644
--- a/pkg/controller/integrationplatform/create_test.go
+++ b/pkg/controller/integrationplatform/create_test.go
@@ -159,10 +159,10 @@ func TestCreateNewCatalog(t *testing.T) {
// Set the folder where to install testing kamelets
tmpDir, err := os.MkdirTemp("/tmp", "kamelets*")
+ defer os.Unsetenv(kameletDirEnv)
assert.NoError(t, err)
os.Setenv(kameletDirEnv, tmpDir)
answer, err := action.Handle(context.TODO(), &ip)
- os.Unsetenv(kameletDirEnv)
require.NoError(t, err)
assert.NotNil(t, answer)
@@ -180,6 +180,27 @@ func TestCreateNewCatalog(t *testing.T) {
require.NoError(t, err)
assert.NotEmpty(t, list.Items)
+
+ // Creating again a platform should not cause problem because any existing Kamelets file leftover
+ ip.Status = v1.IntegrationPlatformStatus{
+ IntegrationPlatformSpec: v1.IntegrationPlatformSpec{
+ Build: v1.IntegrationPlatformBuildSpec{
+ RuntimeProvider: v1.RuntimeProviderQuarkus,
+ RuntimeVersion: defaults.DefaultRuntimeVersion,
+ },
+ },
+ }
+ // Refresh client with changed IP
+ c, err = test.NewFakeClient(&ip)
+ require.NoError(t, err)
+ action.InjectClient(c)
+ answer, err = action.Handle(context.TODO(), &ip)
+ require.NoError(t, err)
+ assert.NotNil(t, answer)
+
+ assert.Equal(t, v1.IntegrationPlatformPhaseReady, answer.Status.Phase)
+ assert.Equal(t, corev1.ConditionTrue, answer.Status.GetCondition(v1.IntegrationPlatformConditionCamelCatalogAvailable).Status)
+ assert.Equal(t, corev1.ConditionTrue, answer.Status.GetCondition(v1.IntegrationPlatformConditionKameletCatalogAvailable).Status)
}
func TestCreateCatalogError(t *testing.T) {
diff --git a/pkg/controller/integrationplatform/kamelets.go b/pkg/controller/integrationplatform/kamelets.go
index 370f464e0..83cfa5d6d 100644
--- a/pkg/controller/integrationplatform/kamelets.go
+++ b/pkg/controller/integrationplatform/kamelets.go
@@ -56,7 +56,10 @@ func installKameletCatalog(ctx context.Context, c client.Client, platform *v1.In
return -1, -1, err
}
// Prepare directory to contains kamelets
- kameletDir := prepareKameletDirectory()
+ kameletDir, err := prepareKameletDirectory()
+ if err != nil {
+ return -1, -1, err
+ }
// Download Kamelet dependency
if err := downloadKameletDependency(ctx, version, kameletDir); err != nil {
return -1, -1, err
@@ -65,7 +68,6 @@ func installKameletCatalog(ctx context.Context, c client.Client, platform *v1.In
if err := extractKameletsFromDependency(ctx, version, kameletDir); err != nil {
return -1, -1, err
}
-
// Store Kamelets as Kubernetes resources
return applyKamelets(ctx, c, platform, kameletDir)
}
@@ -84,13 +86,18 @@ func prepareKameletsPermissions(ctx context.Context, c client.Client, installing
return nil
}
-func prepareKameletDirectory() string {
+func prepareKameletDirectory() (string, error) {
kameletDir := os.Getenv(kameletDirEnv)
if kameletDir == "" {
kameletDir = defaultKameletDir
}
+ // If the directory exists, it is likely a leftover from any previous Kamelet
+ // catalog installation. We should remove to be able to proceed
+ if err := os.RemoveAll(kameletDir); err != nil {
+ return kameletDirEnv, err
+ }
- return kameletDir
+ return kameletDir, nil
}
func downloadKameletDependency(ctx context.Context, version, kameletsDir string) error {
diff --git a/pkg/controller/integrationplatform/kamelets_test.go b/pkg/controller/integrationplatform/kamelets_test.go
index 7a1a79aa6..0bf31c0c2 100644
--- a/pkg/controller/integrationplatform/kamelets_test.go
+++ b/pkg/controller/integrationplatform/kamelets_test.go
@@ -106,7 +106,8 @@ func TestPrepareKameletsPermissions(t *testing.T) {
}
func TestPrepareKameletsDirectory(t *testing.T) {
- kameletDir := prepareKameletDirectory()
+ kameletDir, err := prepareKameletDirectory()
+ assert.NoError(t, err)
assert.Equal(t, defaultKameletDir, kameletDir)
}