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/03/27 06:39:55 UTC

(camel-k) branch main updated: fix(ctrl): report error on traits failure

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


The following commit(s) were added to refs/heads/main by this push:
     new 43326394a fix(ctrl): report error on traits failure
43326394a is described below

commit 43326394a2453d0d0bc1f5a22137812bc0267dd9
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Tue Mar 26 15:59:57 2024 +0100

    fix(ctrl): report error on traits failure
    
    Closes #5084
---
 pkg/controller/integration/monitor.go      |   5 +-
 pkg/controller/integration/monitor_test.go | 153 +++++++++++++++++++++++++++++
 2 files changed, 157 insertions(+), 1 deletion(-)

diff --git a/pkg/controller/integration/monitor.go b/pkg/controller/integration/monitor.go
index 2c526be94..063eedcb4 100644
--- a/pkg/controller/integration/monitor.go
+++ b/pkg/controller/integration/monitor.go
@@ -125,7 +125,10 @@ func (action *monitorAction) Handle(ctx context.Context, integration *v1.Integra
 	// Run traits that are enabled for the phase
 	environment, err := trait.Apply(ctx, action.client, integration, kit)
 	if err != nil {
-		return nil, err
+		integration.Status.Phase = v1.IntegrationPhaseError
+		integration.SetReadyCondition(corev1.ConditionFalse,
+			v1.IntegrationConditionInitializationFailedReason, err.Error())
+		return integration, err
 	}
 
 	return action.monitorPods(ctx, environment, integration)
diff --git a/pkg/controller/integration/monitor_test.go b/pkg/controller/integration/monitor_test.go
index fcd3423d8..5d444bf3d 100644
--- a/pkg/controller/integration/monitor_test.go
+++ b/pkg/controller/integration/monitor_test.go
@@ -21,17 +21,23 @@ import (
 	"context"
 	"testing"
 
+	appsv1 "k8s.io/api/apps/v1"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/utils/pointer"
 
 	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/util/defaults"
+	"github.com/apache/camel-k/v2/pkg/util/digest"
 	"github.com/apache/camel-k/v2/pkg/util/kubernetes"
+	"github.com/apache/camel-k/v2/pkg/util/log"
 	"github.com/apache/camel-k/v2/pkg/util/test"
 
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 func TestGetIntegrationSecretAndConfigmapResourceVersions(t *testing.T) {
@@ -83,3 +89,150 @@ func TestGetIntegrationSecretAndConfigmapResourceVersions(t *testing.T) {
 	assert.NotEqual(t, "", configmaps[0])
 	assert.NotEqual(t, "", secrets[0])
 }
+
+func TestMonitorIntegration(t *testing.T) {
+	c, it, err := nominalEnvironment()
+	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.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)
+}
+
+func TestMonitorFailureIntegration(t *testing.T) {
+	c, it, err := nominalEnvironment()
+	require.NoError(t, err)
+
+	// simulate a trait execution failure
+	it.Status.RuntimeVersion = "0.0.0"
+
+	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.Error(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.IntegrationConditionInitializationFailedReason, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Reason)
+}
+
+func nominalEnvironment() (client.Client, *v1.Integration, error) {
+	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,
+			},
+		},
+	}
+	platform := &v1.IntegrationPlatform{
+		TypeMeta: metav1.TypeMeta{
+			APIVersion: v1.SchemeGroupVersion.String(),
+			Kind:       v1.IntegrationPlatformKind,
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "ns",
+			Name:      "camel-k",
+		},
+		Status: v1.IntegrationPlatformStatus{
+			Phase: v1.IntegrationPlatformPhaseReady,
+		},
+	}
+	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, platform, it, kit, pod)
+	return c, it, err
+}