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/01/02 08:24:08 UTC

(camel-k) branch main updated: fix(ctrl): failing Deployment reported in Integration

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 1449c19d0 fix(ctrl): failing Deployment reported in Integration
1449c19d0 is described below

commit 1449c19d0baeeecf36160f6b1efde0c1722f996c
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Fri Dec 22 15:35:00 2023 +0100

    fix(ctrl): failing Deployment reported in Integration
    
    Closes #4974
---
 e2e/commonwithcustominstall/deployment_test.go   | 77 ++++++++++++++++++++++++
 pkg/controller/integration/monitor.go            | 14 +++--
 pkg/controller/integration/monitor_deployment.go | 13 +++-
 3 files changed, 95 insertions(+), 9 deletions(-)

diff --git a/e2e/commonwithcustominstall/deployment_test.go b/e2e/commonwithcustominstall/deployment_test.go
new file mode 100644
index 000000000..ddd19f9dc
--- /dev/null
+++ b/e2e/commonwithcustominstall/deployment_test.go
@@ -0,0 +1,77 @@
+//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 commonwithcustominstall
+
+import (
+	"testing"
+
+	. "github.com/onsi/gomega"
+	corev1 "k8s.io/api/core/v1"
+	"os/exec"
+
+	. "github.com/apache/camel-k/v2/e2e/support"
+	v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
+)
+
+func TestDeploymentFailureShouldReportIntegrationCondition(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		op := "camel-k-failing-deploy"
+		nsRestr := "restr"
+		Expect(KamelInstallWithID(op, ns, "--global", "--force").Execute()).To(Succeed())
+		// Create restricted namespace
+		ExpectExecSucceed(t,
+			exec.Command(
+				"kubectl",
+				"create",
+				"ns",
+				nsRestr,
+			),
+		)
+		ExpectExecSucceed(t,
+			exec.Command(
+				"kubectl",
+				"label",
+				"--overwrite",
+				"ns",
+				nsRestr,
+				"pod-security.kubernetes.io/enforce=baseline",
+				"pod-security.kubernetes.io/enforce-version=latest",
+				"pod-security.kubernetes.io/enforce=restricted",
+				"pod-security.kubernetes.io/warn-version=latest",
+				"pod-security.kubernetes.io/audit=restricted",
+				"pod-security.kubernetes.io/audit-version=latest",
+			),
+		)
+		// Create an Integration into a restricted namespace
+		name := RandomizedSuffixName("java-fail")
+		Expect(KamelRunWithID(op, ns, "files/Java.java", "--name", name, "-n", nsRestr).Execute()).To(Succeed())
+		// Check the error is reported into the Integration
+		Eventually(IntegrationPhase(nsRestr, name), TestTimeoutMedium).Should(Equal(v1.IntegrationPhaseError))
+		Eventually(IntegrationCondition(nsRestr, name, v1.IntegrationConditionReady)().Status).
+			Should(Equal(corev1.ConditionFalse))
+		Eventually(IntegrationCondition(nsRestr, name, v1.IntegrationConditionReady)().Message).
+			Should(ContainSubstring("is forbidden: violates PodSecurity"))
+		// Clean up
+		Eventually(DeleteIntegrations(nsRestr)).Should(Equal(0))
+	})
+}
diff --git a/pkg/controller/integration/monitor.go b/pkg/controller/integration/monitor.go
index dfcb30d37..7c5a6b7c6 100644
--- a/pkg/controller/integration/monitor.go
+++ b/pkg/controller/integration/monitor.go
@@ -265,7 +265,7 @@ func (action *monitorAction) newController(env *trait.Environment, integration *
 		obj = getUpdatedController(env, &appsv1.Deployment{})
 		deploy, ok := obj.(*appsv1.Deployment)
 		if !ok {
-			return nil, fmt.Errorf("type assertion failed: %v", obj)
+			return nil, fmt.Errorf("type assertion failed, not a Deployment: %v", obj)
 		}
 		controller = &deploymentController{
 			obj:         deploy,
@@ -275,7 +275,7 @@ func (action *monitorAction) newController(env *trait.Environment, integration *
 		obj = getUpdatedController(env, &servingv1.Service{})
 		svc, ok := obj.(*servingv1.Service)
 		if !ok {
-			return nil, fmt.Errorf("type assertion failed: %v", obj)
+			return nil, fmt.Errorf("type assertion failed, not a Knative Service: %v", obj)
 		}
 		controller = &knativeServiceController{
 			obj:         svc,
@@ -285,7 +285,7 @@ func (action *monitorAction) newController(env *trait.Environment, integration *
 		obj = getUpdatedController(env, &batchv1.CronJob{})
 		cj, ok := obj.(*batchv1.CronJob)
 		if !ok {
-			return nil, fmt.Errorf("type assertion failed: %v", obj)
+			return nil, fmt.Errorf("type assertion failed, not a CronJob: %v", obj)
 		}
 		controller = &cronJobController{
 			obj:         cj,
@@ -322,9 +322,11 @@ func (action *monitorAction) updateIntegrationPhaseAndReadyCondition(
 	readyPods, unreadyPods := filterPodsByReadyStatus(environment, runningPods, controller.getPodSpec())
 
 	if done, err := controller.checkReadyCondition(ctx); done || err != nil {
-		// There may be pods that are not ready but still probable for getting error messages.
-		// Ignore returned error from probing as it's expected when the ctrl obj is not ready.
-		_ = action.probeReadiness(ctx, environment, integration, unreadyPods, readyPods)
+		if len(readyPods) > 0 || len(unreadyPods) > 0 {
+			// There may be pods that are not ready but still probable for getting error messages.
+			// Ignore returned error from probing as it's expected when the ctrl obj is not ready.
+			_ = action.probeReadiness(ctx, environment, integration, unreadyPods, readyPods)
+		}
 		return err
 	}
 	if done := checkPodStatuses(integration, pendingPods, runningPods); done {
diff --git a/pkg/controller/integration/monitor_deployment.go b/pkg/controller/integration/monitor_deployment.go
index ac387fc78..55b7797c7 100644
--- a/pkg/controller/integration/monitor_deployment.go
+++ b/pkg/controller/integration/monitor_deployment.go
@@ -37,9 +37,16 @@ var _ controller = &deploymentController{}
 
 func (c *deploymentController) checkReadyCondition(ctx context.Context) (bool, error) {
 	// Check the Deployment progression
-	if progressing := kubernetes.GetDeploymentCondition(*c.obj, appsv1.DeploymentProgressing); progressing != nil &&
-		progressing.Status == corev1.ConditionFalse &&
-		progressing.Reason == "ProgressDeadlineExceeded" {
+	progressing := kubernetes.GetDeploymentCondition(*c.obj, appsv1.DeploymentProgressing)
+	replicaFailure := kubernetes.GetDeploymentCondition(*c.obj, appsv1.DeploymentReplicaFailure)
+
+	if replicaFailure != nil && replicaFailure.Status == corev1.ConditionTrue {
+		c.integration.Status.Phase = v1.IntegrationPhaseError
+		c.integration.SetReadyConditionError(replicaFailure.Message)
+		return true, nil
+	}
+
+	if progressing != nil && progressing.Status == corev1.ConditionFalse && progressing.Reason == "ProgressDeadlineExceeded" {
 		c.integration.Status.Phase = v1.IntegrationPhaseError
 		c.integration.SetReadyConditionError(progressing.Message)
 		return true, nil