You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ts...@apache.org on 2022/09/15 04:37:18 UTC

[camel-k] branch main updated: feat(cli): Allow to set build publish strategy options from install cmd

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

tsato 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 166d5894e feat(cli): Allow to set build publish strategy options from install cmd
166d5894e is described below

commit 166d5894ed3453de414e0fde330887debdaf3113
Author: Nicolas Filotto <nf...@talend.com>
AuthorDate: Mon Sep 12 15:19:39 2022 +0200

    feat(cli): Allow to set build publish strategy options from install cmd
---
 e2e/namespace/install/cli/install_test.go |  15 ++++
 pkg/builder/buildah.go                    |  12 +++
 pkg/builder/builder_support.go            |  69 +++++++++++++++
 pkg/builder/kaniko.go                     |  22 +++++
 pkg/cmd/install.go                        | 140 +++++++++++++++++-------------
 pkg/cmd/install_test.go                   |  21 +----
 pkg/platform/defaults.go                  |   2 +-
 7 files changed, 203 insertions(+), 78 deletions(-)

diff --git a/e2e/namespace/install/cli/install_test.go b/e2e/namespace/install/cli/install_test.go
index aee7732c9..5bac8129c 100644
--- a/e2e/namespace/install/cli/install_test.go
+++ b/e2e/namespace/install/cli/install_test.go
@@ -173,3 +173,18 @@ func TestInstallDebugLogging(t *testing.T) {
 		Eventually(logs).Should(ContainSubstring("DEBUG level messages will be logged"))
 	})
 }
+
+func TestInstallWithPublishStrategyOptions(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		operatorID := fmt.Sprintf("camel-k-%s", ns)
+		Expect(KamelInstallWithID(operatorID, ns, "--build-publish-strategy", "Kaniko", "--build-publish-strategy-option", "KanikoExecutorImage=foo", "--build-publish-strategy-option", "KanikoWarmerImage=bar").Execute()).To(Succeed())
+		Eventually(OperatorPod(ns)).ShouldNot(BeNil())
+		Eventually(Platform(ns)).ShouldNot(BeNil())
+		Eventually(func() map[string]string {
+			return Platform(ns)().Spec.Build.PublishStrategyOptions
+		}).Should(HaveKeyWithValue("KanikoExecutorImage", "foo"))
+		Eventually(func() map[string]string {
+			return Platform(ns)().Spec.Build.PublishStrategyOptions
+		}).Should(HaveKeyWithValue("KanikoWarmerImage", "bar"))
+	})
+}
diff --git a/pkg/builder/buildah.go b/pkg/builder/buildah.go
index ae3fe9e17..71d35a56f 100644
--- a/pkg/builder/buildah.go
+++ b/pkg/builder/buildah.go
@@ -20,3 +20,15 @@ package builder
 const BuildahPlatform = "BuildahPlatform"
 const BuildahImage = "BuildahImage"
 const BuildahDefaultImageName = "quay.io/buildah/stable"
+
+var buildahSupportedOptions = map[string]PublishStrategyOption{
+	BuildahPlatform: {
+		Name:        BuildahPlatform,
+		description: "The attribute platform for buildah",
+	},
+	BuildahImage: {
+		Name:         BuildahImage,
+		description:  "The docker image to use for Buildah",
+		defaultValue: BuildahDefaultImageName,
+	},
+}
diff --git a/pkg/builder/builder_support.go b/pkg/builder/builder_support.go
new file mode 100644
index 000000000..455d5641c
--- /dev/null
+++ b/pkg/builder/builder_support.go
@@ -0,0 +1,69 @@
+/*
+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 builder
+
+import (
+	"fmt"
+
+	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
+)
+
+type PublishStrategyOption struct {
+	Name         string
+	description  string
+	defaultValue string
+}
+
+func (o *PublishStrategyOption) ToString() string {
+	if o.defaultValue == "" {
+		return fmt.Sprintf("%s: %s", o.Name, o.description)
+	}
+	return fmt.Sprintf("%s: %s, default %s", o.Name, o.description, o.defaultValue)
+}
+
+// GetSupportedPublishStrategyOptions provides the supported options for the given strategy. Returns nil if no options are supported.
+func GetSupportedPublishStrategyOptions(strategy v1.IntegrationPlatformBuildPublishStrategy) []PublishStrategyOption {
+	var supportedOptions map[string]PublishStrategyOption
+	switch strategy {
+	case v1.IntegrationPlatformBuildPublishStrategyKaniko:
+		supportedOptions = kanikoSupportedOptions
+	case v1.IntegrationPlatformBuildPublishStrategyBuildah:
+		supportedOptions = buildahSupportedOptions
+	default:
+		return nil
+	}
+	result := make([]PublishStrategyOption, 0, len(supportedOptions))
+	for _, value := range supportedOptions {
+		result = append(result, value)
+	}
+	return result
+}
+
+// IsSupportedPublishStrategyOption indicates whether the given option name is supported for the given strategy.
+func IsSupportedPublishStrategyOption(strategy v1.IntegrationPlatformBuildPublishStrategy, name string) bool {
+	var supportedOption bool
+	switch strategy {
+	case v1.IntegrationPlatformBuildPublishStrategyKaniko:
+		_, supportedOption = kanikoSupportedOptions[name]
+	case v1.IntegrationPlatformBuildPublishStrategyBuildah:
+		_, supportedOption = buildahSupportedOptions[name]
+	default:
+		supportedOption = false
+	}
+	return supportedOption
+}
diff --git a/pkg/builder/kaniko.go b/pkg/builder/kaniko.go
index 16e95a1ca..5800cfb60 100644
--- a/pkg/builder/kaniko.go
+++ b/pkg/builder/kaniko.go
@@ -25,3 +25,25 @@ const KanikoExecutorImage = "KanikoExecutorImage"
 const KanikoWarmerImage = "KanikoWarmerImage"
 const KanikoDefaultExecutorImageName = "gcr.io/kaniko-project/executor"
 const KanikoDefaultWarmerImageName = "gcr.io/kaniko-project/warmer"
+
+var kanikoSupportedOptions = map[string]PublishStrategyOption{
+	KanikoPVCName: {
+		Name:        KanikoPVCName,
+		description: "The name of the PersistentVolumeClaim",
+	},
+	KanikoBuildCacheEnabled: {
+		Name:         KanikoBuildCacheEnabled,
+		description:  "To enable or disable the Kaniko cache",
+		defaultValue: "false",
+	},
+	KanikoExecutorImage: {
+		Name:         KanikoExecutorImage,
+		description:  "The docker image of the Kaniko executor",
+		defaultValue: KanikoDefaultExecutorImageName,
+	},
+	KanikoWarmerImage: {
+		Name:         KanikoWarmerImage,
+		description:  "The docker image of the Kaniko warmer",
+		defaultValue: KanikoDefaultWarmerImageName,
+	},
+}
diff --git a/pkg/cmd/install.go b/pkg/cmd/install.go
index 3a86bd435..7819a8816 100644
--- a/pkg/cmd/install.go
+++ b/pkg/cmd/install.go
@@ -108,16 +108,12 @@ func newCmdInstall(rootCmdOptions *RootCmdOptions) (*cobra.Command, *installCmdO
 	cmd.Flags().String("operator-image-pull-policy", "", "Set the operator ImagePullPolicy used for the operator deployment")
 	cmd.Flags().String("build-strategy", "", "Set the build strategy")
 	cmd.Flags().String("build-publish-strategy", "", "Set the build publish strategy")
+	cmd.Flags().StringArray("build-publish-strategy-option", nil, "Add a build publish strategy option, as <name=value>")
 	cmd.Flags().String("build-timeout", "", "Set how long the build process can last")
 	cmd.Flags().String("trait-profile", "", "The profile to use for traits")
 
 	// Kaniko
-	cmd.Flags().Bool("kaniko-build-cache", false, "To enable or disable the Kaniko cache")
-	cmd.Flags().String("kaniko-executor-image", "", "The docker image of the Kaniko executor")
-	cmd.Flags().String("kaniko-warmer-image", "", "The docker image of the Kaniko warmer")
-
-	// Buildah
-	cmd.Flags().String("buildah-image", "", "The docker image to use for Buildah")
+	cmd.Flags().Bool("kaniko-build-cache", false, "To enable or disable the Kaniko cache. Deprecated use --build-publish-strategy-option KanikoBuildCacheEnabled=true instead")
 
 	// OLM
 	cmd.Flags().Bool("olm", true, "Try to install everything via OLM (Operator Lifecycle Manager) if available")
@@ -171,47 +167,46 @@ func newCmdInstall(rootCmdOptions *RootCmdOptions) (*cobra.Command, *installCmdO
 
 type installCmdOptions struct {
 	*RootCmdOptions
-	Wait                     bool     `mapstructure:"wait"`
-	BuildahImage             string   `mapstructure:"buildah-image"`
-	ClusterSetupOnly         bool     `mapstructure:"cluster-setup"`
-	SkipOperatorSetup        bool     `mapstructure:"skip-operator-setup"`
-	SkipClusterSetup         bool     `mapstructure:"skip-cluster-setup"`
-	SkipRegistrySetup        bool     `mapstructure:"skip-registry-setup"`
-	SkipDefaultKameletsSetup bool     `mapstructure:"skip-default-kamelets-setup"`
-	ExampleSetup             bool     `mapstructure:"example"`
-	Global                   bool     `mapstructure:"global"`
-	KanikoBuildCache         bool     `mapstructure:"kaniko-build-cache"`
-	KanikoExecutorImage      string   `mapstructure:"kaniko-executor-image"`
-	KanikoWarmerImage        string   `mapstructure:"kaniko-warmer-image"`
-	Save                     bool     `mapstructure:"save" kamel:"omitsave"`
-	Force                    bool     `mapstructure:"force"`
-	Olm                      bool     `mapstructure:"olm"`
-	ClusterType              string   `mapstructure:"cluster-type"`
-	OutputFormat             string   `mapstructure:"output"`
-	RuntimeVersion           string   `mapstructure:"runtime-version"`
-	BaseImage                string   `mapstructure:"base-image"`
-	OperatorID               string   `mapstructure:"operator-id"`
-	OperatorImage            string   `mapstructure:"operator-image"`
-	OperatorImagePullPolicy  string   `mapstructure:"operator-image-pull-policy"`
-	BuildStrategy            string   `mapstructure:"build-strategy"`
-	BuildPublishStrategy     string   `mapstructure:"build-publish-strategy"`
-	BuildTimeout             string   `mapstructure:"build-timeout"`
-	MavenExtensions          []string `mapstructure:"maven-extensions"`
-	MavenLocalRepository     string   `mapstructure:"maven-local-repository"`
-	MavenProperties          []string `mapstructure:"maven-properties"`
-	MavenRepositories        []string `mapstructure:"maven-repositories"`
-	MavenSettings            string   `mapstructure:"maven-settings"`
-	MavenCASecret            string   `mapstructure:"maven-ca-secret"`
-	MavenCLIOptions          []string `mapstructure:"maven-cli-options"`
-	HealthPort               int32    `mapstructure:"health-port"`
-	Monitoring               bool     `mapstructure:"monitoring"`
-	MonitoringPort           int32    `mapstructure:"monitoring-port"`
-	TraitProfile             string   `mapstructure:"trait-profile"`
-	Tolerations              []string `mapstructure:"tolerations"`
-	NodeSelectors            []string `mapstructure:"node-selectors"`
-	ResourcesRequirements    []string `mapstructure:"operator-resources"`
-	LogLevel                 string   `mapstructure:"log-level"`
-	EnvVars                  []string `mapstructure:"operator-env-vars"`
+	Wait                     bool `mapstructure:"wait"`
+	ClusterSetupOnly         bool `mapstructure:"cluster-setup"`
+	SkipOperatorSetup        bool `mapstructure:"skip-operator-setup"`
+	SkipClusterSetup         bool `mapstructure:"skip-cluster-setup"`
+	SkipRegistrySetup        bool `mapstructure:"skip-registry-setup"`
+	SkipDefaultKameletsSetup bool `mapstructure:"skip-default-kamelets-setup"`
+	ExampleSetup             bool `mapstructure:"example"`
+	Global                   bool `mapstructure:"global"`
+	// Deprecated: use the BuildPublishStrategyOption "KanikoBuildCacheEnabled" instead
+	KanikoBuildCache            bool     `mapstructure:"kaniko-build-cache"`
+	Save                        bool     `mapstructure:"save" kamel:"omitsave"`
+	Force                       bool     `mapstructure:"force"`
+	Olm                         bool     `mapstructure:"olm"`
+	ClusterType                 string   `mapstructure:"cluster-type"`
+	OutputFormat                string   `mapstructure:"output"`
+	RuntimeVersion              string   `mapstructure:"runtime-version"`
+	BaseImage                   string   `mapstructure:"base-image"`
+	OperatorID                  string   `mapstructure:"operator-id"`
+	OperatorImage               string   `mapstructure:"operator-image"`
+	OperatorImagePullPolicy     string   `mapstructure:"operator-image-pull-policy"`
+	BuildStrategy               string   `mapstructure:"build-strategy"`
+	BuildPublishStrategy        string   `mapstructure:"build-publish-strategy"`
+	BuildPublishStrategyOptions []string `mapstructure:"build-publish-strategy-options"`
+	BuildTimeout                string   `mapstructure:"build-timeout"`
+	MavenExtensions             []string `mapstructure:"maven-extensions"`
+	MavenLocalRepository        string   `mapstructure:"maven-local-repository"`
+	MavenProperties             []string `mapstructure:"maven-properties"`
+	MavenRepositories           []string `mapstructure:"maven-repositories"`
+	MavenSettings               string   `mapstructure:"maven-settings"`
+	MavenCASecret               string   `mapstructure:"maven-ca-secret"`
+	MavenCLIOptions             []string `mapstructure:"maven-cli-options"`
+	HealthPort                  int32    `mapstructure:"health-port"`
+	Monitoring                  bool     `mapstructure:"monitoring"`
+	MonitoringPort              int32    `mapstructure:"monitoring-port"`
+	TraitProfile                string   `mapstructure:"trait-profile"`
+	Tolerations                 []string `mapstructure:"tolerations"`
+	NodeSelectors               []string `mapstructure:"node-selectors"`
+	ResourcesRequirements       []string `mapstructure:"operator-resources"`
+	LogLevel                    string   `mapstructure:"log-level"`
+	EnvVars                     []string `mapstructure:"operator-env-vars"`
 
 	registry         v1.RegistrySpec
 	registryAuth     registry.Auth
@@ -489,20 +484,14 @@ func (o *installCmdOptions) install(cobraCmd *cobra.Command, _ []string) error {
 				}
 			}
 		}
-
-		if platform.Spec.Build.PublishStrategy == v1.IntegrationPlatformBuildPublishStrategyKaniko {
-			kanikoBuildCacheFlag := cobraCmd.Flags().Lookup("kaniko-build-cache")
-			if kanikoBuildCacheFlag.Changed {
-				platform.Spec.Build.AddOption(builder.KanikoBuildCacheEnabled, strconv.FormatBool(o.KanikoBuildCache))
-			}
-			if o.KanikoExecutorImage != "" {
-				platform.Spec.Build.AddOption(builder.KanikoExecutorImage, o.KanikoExecutorImage)
-			}
-			if o.KanikoWarmerImage != "" {
-				platform.Spec.Build.AddOption(builder.KanikoWarmerImage, o.KanikoWarmerImage)
+		if platform.Spec.Build.PublishStrategy == v1.IntegrationPlatformBuildPublishStrategyKaniko && cobraCmd.Flags().Lookup("kaniko-build-cache").Changed {
+			fmt.Fprintln(cobraCmd.OutOrStdout(), "Warn: the flag --kaniko-build-cache is deprecated, use --build-publish-strategy-option KanikoBuildCacheEnabled=true instead")
+			platform.Spec.Build.AddOption(builder.KanikoBuildCacheEnabled, strconv.FormatBool(o.KanikoBuildCache))
+		}
+		if len(o.BuildPublishStrategyOptions) > 0 {
+			if err = o.addBuildPublishStrategyOptions(&platform.Spec.Build); err != nil {
+				return err
 			}
-		} else if platform.Spec.Build.PublishStrategy == v1.IntegrationPlatformBuildPublishStrategyBuildah && o.BuildahImage != "" {
-			platform.Spec.Build.AddOption(builder.BuildahImage, o.BuildahImage)
 		}
 		// Always create a platform in the namespace where the operator is located
 		err = install.ObjectOrCollect(o.Context, c, namespace, collection, o.Force, platform)
@@ -734,6 +723,37 @@ func (o *installCmdOptions) validate(_ *cobra.Command, _ []string) error {
 	return result
 }
 
+// addBuildPublishStrategyOptions parses and adds all the build publish strategy options to the given IntegrationPlatformBuildSpec.
+func (o *installCmdOptions) addBuildPublishStrategyOptions(build *v1.IntegrationPlatformBuildSpec) error {
+	for _, option := range o.BuildPublishStrategyOptions {
+		kv := strings.Split(option, "=")
+		if len(kv) == 2 {
+			key := kv[0]
+			if builder.IsSupportedPublishStrategyOption(build.PublishStrategy, key) {
+				build.AddOption(key, kv[1])
+			} else {
+				return fmt.Errorf("build publish strategy option '%s' not supported. %s", option, supportedOptionsAsString(build.PublishStrategy))
+			}
+		} else {
+			return fmt.Errorf("build publish strategy option '%s' not in the expected format (name=value)", option)
+		}
+	}
+	return nil
+}
+
+// supportedOptionsAsString provides all the supported options for the given strategy as string.
+func supportedOptionsAsString(strategy v1.IntegrationPlatformBuildPublishStrategy) string {
+	options := builder.GetSupportedPublishStrategyOptions(strategy)
+	if len(options) == 0 {
+		return fmt.Sprintf("no options are supported for the strategy '%s'.", strategy)
+	}
+	var sb strings.Builder
+	for _, supportedOption := range builder.GetSupportedPublishStrategyOptions(strategy) {
+		sb.WriteString(fmt.Sprintf("* %s\n", supportedOption.ToString()))
+	}
+	return fmt.Sprintf("\n\nSupported options for the strategy '%s':\n\n%s", strategy, sb.String())
+}
+
 func decodeMavenSettings(mavenSettings string) (v1.ValueSource, error) {
 	sub := make([]string, 0)
 	rex := regexp.MustCompile(`^(configmap|secret):([a-zA-Z0-9][a-zA-Z0-9-]*)(/([a-zA-Z0-9].*))?$`)
diff --git a/pkg/cmd/install_test.go b/pkg/cmd/install_test.go
index 27007a60a..71a9e357e 100644
--- a/pkg/cmd/install_test.go
+++ b/pkg/cmd/install_test.go
@@ -164,25 +164,12 @@ func TestInstallKanikoBuildCacheFlag(t *testing.T) {
 	assert.Equal(t, true, installCmdOptions.KanikoBuildCache)
 }
 
-func TestInstallKanikoExecutorImage(t *testing.T) {
+func TestInstallBuildPublishStrategyOptions(t *testing.T) {
 	installCmdOptions, rootCmd, _ := initializeInstallCmdOptions(t)
-	_, err := test.ExecuteCommand(rootCmd, cmdInstall, "--kaniko-executor-image", "some-executor-image")
+	_, err := test.ExecuteCommand(rootCmd, cmdInstall, "--build-publish-strategy-option", "foo1=bar1", "--build-publish-strategy-option", "foo2=bar2")
 	assert.Nil(t, err)
-	assert.Equal(t, "some-executor-image", installCmdOptions.KanikoExecutorImage)
-}
-
-func TestInstallKanikoWarmerImage(t *testing.T) {
-	installCmdOptions, rootCmd, _ := initializeInstallCmdOptions(t)
-	_, err := test.ExecuteCommand(rootCmd, cmdInstall, "--kaniko-warmer-image", "some-warmer-image")
-	assert.Nil(t, err)
-	assert.Equal(t, "some-warmer-image", installCmdOptions.KanikoWarmerImage)
-}
-
-func TestInstallBuildahImage(t *testing.T) {
-	installCmdOptions, rootCmd, _ := initializeInstallCmdOptions(t)
-	_, err := test.ExecuteCommand(rootCmd, cmdInstall, "--buildah-image", "some-buildah-image")
-	assert.Nil(t, err)
-	assert.Equal(t, "some-buildah-image", installCmdOptions.BuildahImage)
+	assert.Equal(t, "foo1=bar1", installCmdOptions.BuildPublishStrategyOptions[0])
+	assert.Equal(t, "foo2=bar2", installCmdOptions.BuildPublishStrategyOptions[1])
 }
 
 func TestInstallLocalRepositoryFlag(t *testing.T) {
diff --git a/pkg/platform/defaults.go b/pkg/platform/defaults.go
index bbe974659..9e41d82cc 100644
--- a/pkg/platform/defaults.go
+++ b/pkg/platform/defaults.go
@@ -217,7 +217,7 @@ func setPlatformDefaults(p *v1.IntegrationPlatform, verbose bool) error {
 			Duration: 5 * time.Minute,
 		}
 	}
-	_, cacheEnabled := p.Status.Build.PublishStrategyOptions["KanikoBuildCache"]
+	_, cacheEnabled := p.Status.Build.PublishStrategyOptions[builder.KanikoBuildCacheEnabled]
 	if p.Status.Build.PublishStrategy == v1.IntegrationPlatformBuildPublishStrategyKaniko && !cacheEnabled {
 		// Default to disabling Kaniko cache warmer
 		// Using the cache warmer pod seems unreliable with the current Kaniko version