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 2023/08/22 12:15:11 UTC

[camel-k] 02/06: fix(ctrl): allow rebuild after configmap/secret change

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 e928b678606b580dc5e41db189c475aa1ed8f6fb
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Fri Aug 11 11:56:37 2023 +0200

    fix(ctrl): allow rebuild after configmap/secret change
    
    * kamel rebuild command will rollout a new deployment reflecting the changes
    
    Ref #1235
---
 pkg/controller/integration/build_kit.go            |  4 +--
 .../integration/integration_controller.go          |  3 +-
 pkg/controller/integration/monitor.go              | 32 ++++++++++++++++++----
 pkg/util/digest/digest.go                          | 16 ++++++++++-
 pkg/util/digest/digest_test.go                     |  6 ++--
 5 files changed, 48 insertions(+), 13 deletions(-)

diff --git a/pkg/controller/integration/build_kit.go b/pkg/controller/integration/build_kit.go
index a110218d9..a2f3f4238 100644
--- a/pkg/controller/integration/build_kit.go
+++ b/pkg/controller/integration/build_kit.go
@@ -46,8 +46,8 @@ func (action *buildKitAction) CanHandle(integration *v1.Integration) bool {
 func (action *buildKitAction) Handle(ctx context.Context, integration *v1.Integration) (*v1.Integration, error) {
 	// TODO: we may need to add a timeout strategy, i.e give up after some time in case of an unrecoverable error.
 
-	// Check if the Integration has changed and requires a rebuild
-	hash, err := digest.ComputeForIntegration(integration)
+	secrets, configmaps := getIntegrationSecretsAndConfigmaps(ctx, action.client, integration)
+	hash, err := digest.ComputeForIntegration(integration, configmaps, secrets)
 	if err != nil {
 		return nil, err
 	}
diff --git a/pkg/controller/integration/integration_controller.go b/pkg/controller/integration/integration_controller.go
index 54af147c2..e39249c91 100644
--- a/pkg/controller/integration/integration_controller.go
+++ b/pkg/controller/integration/integration_controller.go
@@ -384,7 +384,8 @@ func (r *reconcileIntegration) Reconcile(ctx context.Context, request reconcile.
 }
 
 func (r *reconcileIntegration) update(ctx context.Context, base *v1.Integration, target *v1.Integration, log *log.Logger) error {
-	d, err := digest.ComputeForIntegration(target)
+	secrets, configmaps := getIntegrationSecretsAndConfigmaps(ctx, r.client, target)
+	d, err := digest.ComputeForIntegration(target, configmaps, secrets)
 	if err != nil {
 		return err
 	}
diff --git a/pkg/controller/integration/monitor.go b/pkg/controller/integration/monitor.go
index c9c1ccc5e..471b1fbda 100644
--- a/pkg/controller/integration/monitor.go
+++ b/pkg/controller/integration/monitor.go
@@ -36,9 +36,11 @@ import (
 	servingv1 "knative.dev/serving/pkg/apis/serving/v1"
 
 	v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
+	"github.com/apache/camel-k/v2/pkg/client"
 	"github.com/apache/camel-k/v2/pkg/trait"
 	"github.com/apache/camel-k/v2/pkg/util/digest"
 	"github.com/apache/camel-k/v2/pkg/util/kubernetes"
+	utilResource "github.com/apache/camel-k/v2/pkg/util/resource"
 )
 
 func NewMonitorAction() Action {
@@ -64,7 +66,7 @@ func (action *monitorAction) Handle(ctx context.Context, integration *v1.Integra
 	// so handle it differently from the rest
 	if isInInitializationFailed(integration.Status) {
 		// Only check if the Integration requires a rebuild
-		return action.checkDigestAndRebuild(integration, nil)
+		return action.checkDigestAndRebuild(ctx, integration, nil)
 	}
 
 	// At that staged the Integration must have a Kit
@@ -80,7 +82,7 @@ func (action *monitorAction) Handle(ctx context.Context, integration *v1.Integra
 	}
 
 	// Check if the Integration requires a rebuild
-	if changed, err := action.checkDigestAndRebuild(integration, kit); err != nil {
+	if changed, err := action.checkDigestAndRebuild(ctx, integration, kit); err != nil {
 		return nil, err
 	} else if changed != nil {
 		return changed, nil
@@ -175,10 +177,9 @@ func isInInitializationFailed(status v1.IntegrationStatus) bool {
 	return false
 }
 
-func (action *monitorAction) checkDigestAndRebuild(
-	integration *v1.Integration, kit *v1.IntegrationKit,
-) (*v1.Integration, error) {
-	hash, err := digest.ComputeForIntegration(integration)
+func (action *monitorAction) checkDigestAndRebuild(ctx context.Context, integration *v1.Integration, kit *v1.IntegrationKit) (*v1.Integration, error) {
+	secrets, configmaps := getIntegrationSecretsAndConfigmaps(ctx, action.client, integration)
+	hash, err := digest.ComputeForIntegration(integration, configmaps, secrets)
 	if err != nil {
 		return nil, err
 	}
@@ -203,6 +204,25 @@ func (action *monitorAction) checkDigestAndRebuild(
 	return nil, nil
 }
 
+func getIntegrationSecretsAndConfigmaps(ctx context.Context, client client.Client, integration *v1.Integration) ([]*corev1.Secret, []*corev1.ConfigMap) {
+	configmaps := make([]*corev1.ConfigMap, 0)
+	secrets := make([]*corev1.Secret, 0)
+	if integration.Spec.Traits.Mount != nil {
+		for _, c := range integration.Spec.Traits.Mount.Configs {
+			if conf, parseErr := utilResource.ParseConfig(c); parseErr == nil {
+				if conf.StorageType() == utilResource.StorageTypeConfigmap {
+					configmap := kubernetes.LookupConfigmap(ctx, client, integration.Namespace, conf.Name())
+					configmaps = append(configmaps, configmap)
+				} else if conf.StorageType() == utilResource.StorageTypeSecret {
+					secret := kubernetes.LookupSecret(ctx, client, integration.Namespace, conf.Name())
+					secrets = append(secrets, secret)
+				}
+			}
+		}
+	}
+	return secrets, configmaps
+}
+
 type controller interface {
 	checkReadyCondition(ctx context.Context) (bool, error)
 	getPodSpec() corev1.PodSpec
diff --git a/pkg/util/digest/digest.go b/pkg/util/digest/digest.go
index 8f252998e..ed5e8331d 100644
--- a/pkg/util/digest/digest.go
+++ b/pkg/util/digest/digest.go
@@ -36,15 +36,17 @@ import (
 	"github.com/apache/camel-k/v2/pkg/util"
 	"github.com/apache/camel-k/v2/pkg/util/defaults"
 	"github.com/apache/camel-k/v2/pkg/util/dsl"
+	corev1 "k8s.io/api/core/v1"
 )
 
 const (
+	// IntegrationDigestEnvVar --
 	IntegrationDigestEnvVar = "CAMEL_K_DIGEST"
 )
 
 // ComputeForIntegration a digest of the fields that are relevant for the deployment
 // Produces a digest that can be used as docker image tag.
-func ComputeForIntegration(integration *v1.Integration) (string, error) {
+func ComputeForIntegration(integration *v1.Integration, configmaps []*corev1.ConfigMap, secrets []*corev1.Secret) (string, error) {
 	hash := sha256.New()
 	// Integration version is relevant
 	if _, err := hash.Write([]byte(integration.Status.Version)); err != nil {
@@ -134,6 +136,18 @@ func ComputeForIntegration(integration *v1.Integration) (string, error) {
 		}
 	}
 
+	// Configmap and secret content
+	for _, cm := range configmaps {
+		if _, err := hash.Write([]byte(cm.String())); err != nil {
+			return "", err
+		}
+	}
+	for _, s := range secrets {
+		if _, err := hash.Write([]byte(s.String())); err != nil {
+			return "", err
+		}
+	}
+
 	// Add a letter at the beginning and use URL safe encoding
 	digest := "v" + base64.RawURLEncoding.EncodeToString(hash.Sum(nil))
 	return digest, nil
diff --git a/pkg/util/digest/digest_test.go b/pkg/util/digest/digest_test.go
index f015b576e..3139b88c3 100644
--- a/pkg/util/digest/digest_test.go
+++ b/pkg/util/digest/digest_test.go
@@ -27,13 +27,13 @@ import (
 
 func TestDigestUsesAnnotations(t *testing.T) {
 	it := v1.Integration{}
-	digest1, err := ComputeForIntegration(&it)
+	digest1, err := ComputeForIntegration(&it, nil, nil)
 	assert.NoError(t, err)
 
 	it.Annotations = map[string]string{
 		"another.annotation": "hello",
 	}
-	digest2, err := ComputeForIntegration(&it)
+	digest2, err := ComputeForIntegration(&it, nil, nil)
 	assert.NoError(t, err)
 	assert.Equal(t, digest1, digest2)
 
@@ -41,7 +41,7 @@ func TestDigestUsesAnnotations(t *testing.T) {
 		"another.annotation":                   "hello",
 		"trait.camel.apache.org/cron.fallback": "true",
 	}
-	digest3, err := ComputeForIntegration(&it)
+	digest3, err := ComputeForIntegration(&it, nil, nil)
 	assert.NoError(t, err)
 	assert.NotEqual(t, digest1, digest3)
 }