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)
}