This is an automated email from the ASF dual-hosted git repository. lburgazzoli pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/camel-k.git
commit f312d55bd9f1ffe9277efb381a0c043724adb852 Author: nferraro <ni.ferr...@gmail.com> AuthorDate: Tue Jun 4 16:47:36 2019 +0200 Fix #703: automatically configure global build strategy --- pkg/cmd/install.go | 12 +++-- pkg/controller/build/schedule_pod.go | 21 ++++++++ pkg/controller/integrationplatform/initialize.go | 12 +++-- pkg/install/serviceaccount.go | 67 ++++++++++++++++++++++++ pkg/platform/operator.go | 10 ++++ 5 files changed, 116 insertions(+), 6 deletions(-) diff --git a/pkg/cmd/install.go b/pkg/cmd/install.go index ab91a9e..65d6b67 100644 --- a/pkg/cmd/install.go +++ b/pkg/cmd/install.go @@ -60,6 +60,7 @@ func newCmdInstall(rootCmdOptions *RootCmdOptions) *cobra.Command { cmd.Flags().BoolVarP(&impl.wait, "wait", "w", false, "Waits for the platform to be running") cmd.Flags().BoolVar(&impl.clusterSetupOnly, "cluster-setup", false, "Execute cluster-wide operations only (may require admin rights)") + cmd.Flags().BoolVar(&impl.skipOperatorSetup, "skip-operator-setup", false, "Do not install the operator in the namespace (in case there's a global one)") cmd.Flags().BoolVar(&impl.skipClusterSetup, "skip-cluster-setup", false, "Skip the cluster-setup phase") cmd.Flags().BoolVar(&impl.exampleSetup, "example", false, "Install example integration") @@ -98,6 +99,7 @@ type installCmdOptions struct { *RootCmdOptions wait bool clusterSetupOnly bool + skipOperatorSetup bool skipClusterSetup bool exampleSetup bool outputFormat string @@ -149,9 +151,13 @@ func (o *installCmdOptions) install(_ *cobra.Command, _ []string) error { namespace := o.Namespace - err = install.OperatorOrCollect(o.Context, c, namespace, o.operatorImage, collection) - if err != nil { - return err + if !o.skipOperatorSetup { + err = install.OperatorOrCollect(o.Context, c, namespace, o.operatorImage, collection) + if err != nil { + return err + } + } else { + fmt.Println("Camel K operator installation skipped") } platform, err := install.PlatformOrCollect(o.Context, c, namespace, o.registry, collection) diff --git a/pkg/controller/build/schedule_pod.go b/pkg/controller/build/schedule_pod.go index 212e0f6..60a9278 100644 --- a/pkg/controller/build/schedule_pod.go +++ b/pkg/controller/build/schedule_pod.go @@ -22,6 +22,7 @@ import ( "sync" "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" + "github.com/apache/camel-k/pkg/install" "github.com/apache/camel-k/pkg/platform" "github.com/apache/camel-k/pkg/util/defaults" @@ -105,6 +106,11 @@ func (action *schedulePodAction) Handle(ctx context.Context, build *v1alpha1.Bui return err } + // Ensure service account is present + if err := action.ensureServiceAccount(ctx, pod); err != nil { + return errors.Wrap(err, "cannot ensure service account is present") + } + err = action.client.Delete(ctx, pod) if err != nil && !k8serrors.IsNotFound(err) { return errors.Wrap(err, "cannot delete build pod") @@ -122,6 +128,21 @@ func (action *schedulePodAction) Handle(ctx context.Context, build *v1alpha1.Bui return action.client.Status().Update(ctx, target) } +func (action *schedulePodAction) ensureServiceAccount(ctx context.Context, buildPod *corev1.Pod) error { + sa := corev1.ServiceAccount{} + saKey := k8sclient.ObjectKey{ + Name: "camel-k-operator", + Namespace: buildPod.Namespace, + } + + err := action.client.Get(ctx, saKey, &sa) + if err != nil && k8serrors.IsNotFound(err) { + // Create a proper service account + return install.ServiceAccountRoles(ctx, action.client, buildPod.Namespace) + } + return err +} + func newBuildPod(build *v1alpha1.Build, operatorImage string) *corev1.Pod { builderImage := operatorImage if builderImage == "" { diff --git a/pkg/controller/integrationplatform/initialize.go b/pkg/controller/integrationplatform/initialize.go index f8c2f9b..d8cea6e 100644 --- a/pkg/controller/integrationplatform/initialize.go +++ b/pkg/controller/integrationplatform/initialize.go @@ -93,11 +93,17 @@ func (action *initializeAction) Handle(ctx context.Context, ip *v1alpha1.Integra } if target.Spec.Build.BuildStrategy == "" { - if target.Spec.Build.PublishStrategy == v1alpha1.IntegrationPlatformBuildPublishStrategyKaniko { - // The build output has to be shared with Kaniko via a persistent volume + // If the operator is global, a global build strategy should be used + if platform.IsCurrentOperatorGlobal() { + // The only global strategy we have for now target.Spec.Build.BuildStrategy = v1alpha1.IntegrationPlatformBuildStrategyPod } else { - target.Spec.Build.BuildStrategy = v1alpha1.IntegrationPlatformBuildStrategyRoutine + if target.Spec.Build.PublishStrategy == v1alpha1.IntegrationPlatformBuildPublishStrategyKaniko { + // The build output has to be shared with Kaniko via a persistent volume + target.Spec.Build.BuildStrategy = v1alpha1.IntegrationPlatformBuildStrategyPod + } else { + target.Spec.Build.BuildStrategy = v1alpha1.IntegrationPlatformBuildStrategyRoutine + } } } diff --git a/pkg/install/serviceaccount.go b/pkg/install/serviceaccount.go new file mode 100644 index 0000000..7a9cf9f --- /dev/null +++ b/pkg/install/serviceaccount.go @@ -0,0 +1,67 @@ +/* +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 install + +import ( + "context" + "github.com/apache/camel-k/pkg/client" + "github.com/apache/camel-k/pkg/util/knative" + "github.com/apache/camel-k/pkg/util/openshift" +) + +// ServiceAccountRoles installs the service account and related roles in the given namespace +func ServiceAccountRoles(ctx context.Context, c client.Client, namespace string) error { + isOpenshift, err := openshift.IsOpenShift(c) + if err != nil { + return err + } + if isOpenshift { + if err := installServiceAccountRolesOpenshift(ctx, c, namespace); err != nil { + return err + } + } else { + if err := installServiceAccountRolesKubernetes(ctx, c, namespace); err != nil { + return err + } + } + // Install Knative resources if required + isKnative, err := knative.IsInstalled(ctx, c) + if err != nil { + return err + } + if isKnative { + return installKnative(ctx, c, namespace, nil) + } + return nil +} + +func installServiceAccountRolesOpenshift(ctx context.Context, c client.Client, namespace string) error { + return ResourcesOrCollect(ctx, c, namespace, nil, IdentityResourceCustomizer, + "operator-service-account.yaml", + "operator-role-openshift.yaml", + "operator-role-binding.yaml", + ) +} + +func installServiceAccountRolesKubernetes(ctx context.Context, c client.Client, namespace string) error { + return ResourcesOrCollect(ctx, c, namespace, nil, IdentityResourceCustomizer, + "operator-service-account.yaml", + "operator-role-kubernetes.yaml", + "operator-role-binding.yaml", + ) +} diff --git a/pkg/platform/operator.go b/pkg/platform/operator.go index f180cd9..2ffd051 100644 --- a/pkg/platform/operator.go +++ b/pkg/platform/operator.go @@ -21,11 +21,13 @@ import ( "context" "errors" "os" + "strings" v1 "k8s.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/client" ) +const operatorWatchNamespaceEnvVariable = "WATCH_NAMESPACE" const operatorNamespaceEnvVariable = "NAMESPACE" const operatorPodNameEnvVariable = "POD_NAME" @@ -55,3 +57,11 @@ func GetCurrentOperatorImage(ctx context.Context, c client.Client) (string, erro } return pod.Spec.Containers[0].Image, nil } + +// IsCurrentOperatorGlobal returns true if the operator is configured to watch all namespaces +func IsCurrentOperatorGlobal() bool { + if watchNamespace, envSet := os.LookupEnv(operatorWatchNamespaceEnvVariable); !envSet || strings.TrimSpace(watchNamespace) == "" { + return true + } + return false +}