You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by as...@apache.org on 2019/11/28 07:40:52 UTC

[camel-k] 05/07: Fix #613: Add pull-secret trait

This is an automated email from the ASF dual-hosted git repository.

astefanutti pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit a7fa8de9605d0b7d76c61f520d8b6324442b353c
Author: Nicola Ferraro <ni...@gmail.com>
AuthorDate: Tue Nov 26 13:26:04 2019 +0100

    Fix #613: Add pull-secret trait
---
 docs/modules/ROOT/nav.adoc                      |  1 +
 docs/modules/ROOT/pages/traits/pull-secret.adoc | 46 +++++++++++++
 docs/modules/ROOT/pages/traits/traits.adoc      |  1 +
 pkg/trait/pull_secret.go                        | 88 +++++++++++++++++++++++++
 pkg/trait/pull_secret_test.go                   | 81 +++++++++++++++++++++++
 pkg/trait/trait_catalog.go                      |  6 ++
 pkg/util/kubernetes/collection.go               | 10 +++
 7 files changed, 233 insertions(+)

diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc
index 732df79..468165c 100644
--- a/docs/modules/ROOT/nav.adoc
+++ b/docs/modules/ROOT/nav.adoc
@@ -35,6 +35,7 @@
 ** xref:traits/owner.adoc[Owner]
 ** xref:traits/probes.adoc[Probes]
 ** xref:traits/prometheus.adoc[Prometheus]
+** xref:traits/pull-secret.adoc[Pull Secret]
 ** xref:traits/quarkus.adoc[Quarkus]
 ** xref:traits/rest-dsl.adoc[Rest Dsl]
 ** xref:traits/route.adoc[Route]
diff --git a/docs/modules/ROOT/pages/traits/pull-secret.adoc b/docs/modules/ROOT/pages/traits/pull-secret.adoc
new file mode 100755
index 0000000..bfafe02
--- /dev/null
+++ b/docs/modules/ROOT/pages/traits/pull-secret.adoc
@@ -0,0 +1,46 @@
+= Pull Secret Trait
+
+// Start of autogenerated code - DO NOT EDIT! (description)
+The Pull Secret trait sets a pull secret on the pod,
+to allow Kubernetes to retrieve the container image from an external registry.
+
+The pull secret can be specified manually or, in case you've configured authentication for an external container registry
+on the `IntegrationPlatform`, the same secret is used to pull images.
+
+It's enabled by default whenever you configure authentication for an external container registry,
+so it assumes that external registries are private.
+
+If your registry does not need authentication for pulling images, you can disable this trait.
+
+
+This trait is available in the following profiles: **Kubernetes, Knative, OpenShift**.
+
+// End of autogenerated code - DO NOT EDIT! (description)
+// Start of autogenerated code - DO NOT EDIT! (configuration)
+== Configuration
+
+Trait properties can be specified when running any integration with the CLI:
+```
+kamel run --trait pull-secret.[key]=[value] integration.groovy
+```
+The following configuration options are available:
+
+[cols="2,1,5a"]
+|===
+|Property | Type | Description
+
+| pull-secret.enabled
+| bool
+| Can be used to enable or disable a trait. All traits share this common property.
+
+| pull-secret.secret-name
+| string
+| The pull secret name to set on the Pod. If left empty this is automatically taken from the `IntegrationPlatform` registry configuration.
+
+| pull-secret.auto
+| bool
+| Automatically configures the platform registry secret on the pod if it is of type `kubernetes.io/dockerconfigjson`.
+
+|===
+
+// End of autogenerated code - DO NOT EDIT! (configuration)
diff --git a/docs/modules/ROOT/pages/traits/traits.adoc b/docs/modules/ROOT/pages/traits/traits.adoc
index ce8e90b..3a3d043 100644
--- a/docs/modules/ROOT/pages/traits/traits.adoc
+++ b/docs/modules/ROOT/pages/traits/traits.adoc
@@ -53,6 +53,7 @@ See the trait description pages for more information on a specific trait:
 * xref:traits/owner.adoc[Owner Trait]
 * xref:traits/probes.adoc[Probes Trait]
 * xref:traits/prometheus.adoc[Prometheus Trait]
+* xref:traits/pull-secret.adoc[Pull Secret Trait]
 * xref:traits/quarkus.adoc[Quarkus Trait]
 * xref:traits/rest-dsl.adoc[Rest Dsl Trait]
 * xref:traits/route.adoc[Route Trait]
diff --git a/pkg/trait/pull_secret.go b/pkg/trait/pull_secret.go
new file mode 100644
index 0000000..db79632
--- /dev/null
+++ b/pkg/trait/pull_secret.go
@@ -0,0 +1,88 @@
+/*
+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 trait
+
+import (
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	v1 "k8s.io/api/core/v1"
+	"sigs.k8s.io/controller-runtime/pkg/client"
+)
+
+// The Pull Secret trait sets a pull secret on the pod,
+// to allow Kubernetes to retrieve the container image from an external registry.
+//
+// The pull secret can be specified manually or, in case you've configured authentication for an external container registry
+// on the `IntegrationPlatform`, the same secret is used to pull images.
+//
+// It's enabled by default whenever you configure authentication for an external container registry,
+// so it assumes that external registries are private.
+//
+// If your registry does not need authentication for pulling images, you can disable this trait.
+//
+// +camel-k:trait=pull-secret
+type pullSecretTrait struct {
+	BaseTrait `property:",squash"`
+	// The pull secret name to set on the Pod. If left empty this is automatically taken from the `IntegrationPlatform` registry configuration.
+	SecretName string `property:"secret-name"`
+	// Automatically configures the platform registry secret on the pod if it is of type `kubernetes.io/dockerconfigjson`.
+	Auto *bool `property:"auto"`
+}
+
+func newPullSecretTrait() *pullSecretTrait {
+	return &pullSecretTrait{
+		BaseTrait: newBaseTrait("pull-secret"),
+	}
+}
+
+func (t *pullSecretTrait) Configure(e *Environment) (bool, error) {
+	if t.Enabled != nil && !*t.Enabled {
+		return false, nil
+	}
+
+	if !e.IntegrationInPhase(v1alpha1.IntegrationPhaseDeploying) {
+		return false, nil
+	}
+
+	if t.Auto == nil || *t.Auto {
+		if t.SecretName == "" {
+			secret := e.Platform.Spec.Build.Registry.Secret
+			if secret != "" {
+				key := client.ObjectKey{Namespace: e.Platform.Namespace, Name: secret}
+				obj := v1.Secret{}
+				if err := t.client.Get(t.ctx, key, &obj); err != nil {
+					return false, err
+				}
+				if obj.Type == v1.SecretTypeDockerConfigJson {
+					t.SecretName = secret
+				}
+			}
+		}
+	}
+
+	return t.SecretName != "", nil
+}
+
+func (t *pullSecretTrait) Apply(e *Environment) error {
+	e.Resources.VisitPodSpec(func(p *v1.PodSpec) {
+		p.ImagePullSecrets = append(p.ImagePullSecrets, v1.LocalObjectReference{
+			Name: t.SecretName,
+		})
+	})
+
+	return nil
+}
diff --git a/pkg/trait/pull_secret_test.go b/pkg/trait/pull_secret_test.go
new file mode 100644
index 0000000..1321dd2
--- /dev/null
+++ b/pkg/trait/pull_secret_test.go
@@ -0,0 +1,81 @@
+/*
+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 trait
+
+import (
+	"testing"
+
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/apache/camel-k/pkg/util/kubernetes"
+	appsv1 "k8s.io/api/apps/v1"
+	v1 "k8s.io/api/core/v1"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestPullSecret(t *testing.T) {
+	e := &Environment{}
+	e.Integration = &v1alpha1.Integration{
+		Status: v1alpha1.IntegrationStatus{
+			Phase: v1alpha1.IntegrationPhaseDeploying,
+		},
+	}
+
+	deployment := appsv1.Deployment{
+		Spec: appsv1.DeploymentSpec{
+			Template: v1.PodTemplateSpec{
+				Spec: v1.PodSpec{},
+			},
+		},
+	}
+	e.Resources = kubernetes.NewCollection(&deployment)
+
+	trait := newPullSecretTrait()
+	trait.SecretName = "xxxy"
+	enabled, err := trait.Configure(e)
+	assert.Nil(t, err)
+	assert.True(t, enabled)
+
+	err = trait.Apply(e)
+	assert.Nil(t, err)
+	assert.Contains(t, deployment.Spec.Template.Spec.ImagePullSecrets, v1.LocalObjectReference{Name: "xxxy"})
+}
+
+func TestPullSecretDoesNothingWhenNotSetOnPlatform(t *testing.T) {
+	e := &Environment{}
+	e.Integration = &v1alpha1.Integration{
+		Status: v1alpha1.IntegrationStatus{
+			Phase: v1alpha1.IntegrationPhaseDeploying,
+		},
+	}
+	e.Platform = &v1alpha1.IntegrationPlatform{}
+
+	deployment := appsv1.Deployment{
+		Spec: appsv1.DeploymentSpec{
+			Template: v1.PodTemplateSpec{
+				Spec: v1.PodSpec{},
+			},
+		},
+	}
+	e.Resources = kubernetes.NewCollection(&deployment)
+
+	trait := newPullSecretTrait()
+	enabled, err := trait.Configure(e)
+	assert.Nil(t, err)
+	assert.False(t, enabled)
+}
diff --git a/pkg/trait/trait_catalog.go b/pkg/trait/trait_catalog.go
index ee7f698..57c5880 100644
--- a/pkg/trait/trait_catalog.go
+++ b/pkg/trait/trait_catalog.go
@@ -54,6 +54,7 @@ type Catalog struct {
 	tProbes           Trait
 	tQuarkus          Trait
 	tContainer        Trait
+	tPullSecret		  Trait
 }
 
 // NewCatalog creates a new trait Catalog
@@ -83,6 +84,7 @@ func NewCatalog(ctx context.Context, c client.Client) *Catalog {
 		tProbes:           newProbesTrait(),
 		tQuarkus:          newQuarkusTrait(),
 		tContainer:        newContainerTrait(),
+		tPullSecret:       newPullSecretTrait(),
 	}
 
 	for _, t := range catalog.allTraits() {
@@ -121,6 +123,7 @@ func (c *Catalog) allTraits() []Trait {
 		c.tProbes,
 		c.tQuarkus,
 		c.tContainer,
+		c.tPullSecret,
 	}
 }
 
@@ -152,6 +155,7 @@ func (c *Catalog) TraitsForProfile(profile v1alpha1.TraitProfile) []Trait {
 			c.tAffinity,
 			c.tService,
 			c.tContainer,
+			c.tPullSecret,
 			c.tJolokia,
 			c.tPrometheus,
 			c.tClasspath,
@@ -175,6 +179,7 @@ func (c *Catalog) TraitsForProfile(profile v1alpha1.TraitProfile) []Trait {
 			c.tAffinity,
 			c.tService,
 			c.tContainer,
+			c.tPullSecret,
 			c.tJolokia,
 			c.tPrometheus,
 			c.tClasspath,
@@ -199,6 +204,7 @@ func (c *Catalog) TraitsForProfile(profile v1alpha1.TraitProfile) []Trait {
 			c.tAffinity,
 			c.tKnativeService,
 			c.tContainer,
+			c.tPullSecret,
 			c.tJolokia,
 			c.tPrometheus,
 			c.tClasspath,
diff --git a/pkg/util/kubernetes/collection.go b/pkg/util/kubernetes/collection.go
index eb6a00d..4c10184 100644
--- a/pkg/util/kubernetes/collection.go
+++ b/pkg/util/kubernetes/collection.go
@@ -306,6 +306,16 @@ func (c *Collection) VisitContainer(visitor func(container *corev1.Container)) {
 	})
 }
 
+// VisitPodSpec executes the visitor function on all PodSpec inside deployments or other resources
+func (c *Collection) VisitPodSpec(visitor func(container *corev1.PodSpec)) {
+	c.VisitDeployment(func(d *appsv1.Deployment) {
+		visitor(&d.Spec.Template.Spec)
+	})
+	c.VisitKnativeConfigurationSpec(func(cs *servingv1.ConfigurationSpec) {
+		visitor(&cs.Template.Spec.PodSpec)
+	})
+}
+
 // VisitKnativeConfigurationSpec executes the visitor function on all knative ConfigurationSpec inside serving Services
 func (c *Collection) VisitKnativeConfigurationSpec(visitor func(container *servingv1.ConfigurationSpec)) {
 	c.VisitKnativeService(func(s *serving.Service) {