You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by nf...@apache.org on 2020/11/03 23:40:54 UTC
[camel-k] branch master updated: Fix #751: add guard to global
operator
This is an automated email from the ASF dual-hosted git repository.
nferraro pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel-k.git
The following commit(s) were added to refs/heads/master by this push:
new 9dac8ad Fix #751: add guard to global operator
9dac8ad is described below
commit 9dac8adb53471364b81f72f10ace1233e38c444d
Author: nicolaferraro <ni...@gmail.com>
AuthorDate: Mon Nov 2 16:25:12 2020 +0100
Fix #751: add guard to global operator
---
e2e/builder/global_test.go | 19 ++++++++++++-
pkg/cmd/operator/operator.go | 3 +-
pkg/controller/build/build_controller.go | 8 ++++++
.../integration/integration_controller.go | 9 ++++++
.../integrationkit/integrationkit_controller.go | 8 ++++++
.../integrationplatform_controller.go | 9 ++++++
pkg/controller/kamelet/kamelet_controller.go | 9 ++++++
.../kameletbinding/kamelet_binding_controller.go | 9 ++++++
pkg/platform/operator.go | 33 ++++++++++++++++++++++
9 files changed, 105 insertions(+), 2 deletions(-)
diff --git a/e2e/builder/global_test.go b/e2e/builder/global_test.go
index 8d38d85..f257149 100644
--- a/e2e/builder/global_test.go
+++ b/e2e/builder/global_test.go
@@ -26,6 +26,7 @@ import (
"testing"
. "github.com/apache/camel-k/e2e/support"
+ "github.com/apache/camel-k/pkg/platform"
"github.com/apache/camel-k/pkg/util/openshift"
. "github.com/onsi/gomega"
"github.com/stretchr/testify/assert"
@@ -46,7 +47,7 @@ func TestRunGlobalInstall(t *testing.T) {
WithNewTestNamespace(t, func(ns string) {
Expect(Kamel("install", "-n", ns, "--global").Execute()).Should(BeNil())
- // NS2
+ // NS2: namespace without operator
WithNewTestNamespace(t, func(ns2 string) {
Expect(Kamel("install", "-n", ns2, "--skip-operator-setup", "--olm=false").Execute()).Should(BeNil())
@@ -54,6 +55,22 @@ func TestRunGlobalInstall(t *testing.T) {
Eventually(IntegrationPodPhase(ns2, "java"), TestTimeoutMedium).Should(Equal(v1.PodRunning))
Eventually(IntegrationLogs(ns2, "java"), TestTimeoutShort).Should(ContainSubstring("Magicstring!"))
Expect(Kamel("delete", "--all", "-n", ns2).Execute()).Should(BeNil())
+
+ Expect(ConfigMap(ns2, platform.OperatorLockName)()).Should(BeNil(), "No locking configmap expected")
+ })
+
+ // NS3: namespace with its own operator
+ WithNewTestNamespace(t, func(ns3 string) {
+ Expect(Kamel("install", "-n", ns3, "--olm=false").Execute()).Should(BeNil())
+
+ Expect(Kamel("run", "-n", ns3, "files/Java.java").Execute()).Should(BeNil())
+ Eventually(IntegrationPodPhase(ns3, "java"), TestTimeoutMedium).Should(Equal(v1.PodRunning))
+ Eventually(IntegrationLogs(ns3, "java"), TestTimeoutShort).Should(ContainSubstring("Magicstring!"))
+ Expect(Kamel("delete", "--all", "-n", ns3).Execute()).Should(BeNil())
+
+ Expect(ConfigMap(ns3, platform.OperatorLockName)()).ShouldNot(BeNil(),
+ "OperatorSDK is expected to use configmaps for locking: if this changes (e.g. using Leases) we should update our guard logic",
+ )
})
Expect(Kamel("uninstall", "-n", ns, "--skip-crd", "--skip-cluster-roles").Execute()).Should(BeNil())
diff --git a/pkg/cmd/operator/operator.go b/pkg/cmd/operator/operator.go
index 9eec07e..b11c021 100644
--- a/pkg/cmd/operator/operator.go
+++ b/pkg/cmd/operator/operator.go
@@ -26,6 +26,7 @@ import (
"runtime"
"time"
+ "github.com/apache/camel-k/pkg/platform"
corev1 "k8s.io/api/core/v1"
typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
"k8s.io/client-go/tools/record"
@@ -91,7 +92,7 @@ func Run() {
}
// Become the leader before proceeding
- err = leader.Become(context.TODO(), "camel-k-lock")
+ err = leader.Become(context.TODO(), platform.OperatorLockName)
if err != nil {
if err == leader.ErrNoNamespace {
log.Info("Local run detected, leader election is disabled")
diff --git a/pkg/controller/build/build_controller.go b/pkg/controller/build/build_controller.go
index d9e771f..30a0e04 100644
--- a/pkg/controller/build/build_controller.go
+++ b/pkg/controller/build/build_controller.go
@@ -138,6 +138,14 @@ func (r *ReconcileBuild) Reconcile(request reconcile.Request) (reconcile.Result,
ctx := context.TODO()
+ // Make sure the operator is allowed to act on namespace
+ if ok, err := platform.IsOperatorAllowedOnNamespace(ctx, r.client, request.Namespace); err != nil {
+ return reconcile.Result{}, err
+ } else if !ok {
+ rlog.Info("Ignoring request because namespace is locked")
+ return reconcile.Result{}, nil
+ }
+
// Fetch the Build instance
var instance v1.Build
diff --git a/pkg/controller/integration/integration_controller.go b/pkg/controller/integration/integration_controller.go
index 8170a37..3d94b87 100644
--- a/pkg/controller/integration/integration_controller.go
+++ b/pkg/controller/integration/integration_controller.go
@@ -21,6 +21,7 @@ import (
"context"
camelevent "github.com/apache/camel-k/pkg/event"
+ "github.com/apache/camel-k/pkg/platform"
appsv1 "k8s.io/api/apps/v1"
"k8s.io/api/batch/v1beta1"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
@@ -236,6 +237,14 @@ func (r *ReconcileIntegration) Reconcile(request reconcile.Request) (reconcile.R
ctx := context.TODO()
+ // Make sure the operator is allowed to act on namespace
+ if ok, err := platform.IsOperatorAllowedOnNamespace(ctx, r.client, request.Namespace); err != nil {
+ return reconcile.Result{}, err
+ } else if !ok {
+ rlog.Info("Ignoring request because namespace is locked")
+ return reconcile.Result{}, nil
+ }
+
// Fetch the Integration instance
var instance v1.Integration
diff --git a/pkg/controller/integrationkit/integrationkit_controller.go b/pkg/controller/integrationkit/integrationkit_controller.go
index d16def6..aaa87fe 100644
--- a/pkg/controller/integrationkit/integrationkit_controller.go
+++ b/pkg/controller/integrationkit/integrationkit_controller.go
@@ -171,6 +171,14 @@ func (r *ReconcileIntegrationKit) Reconcile(request reconcile.Request) (reconcil
ctx := context.TODO()
+ // Make sure the operator is allowed to act on namespace
+ if ok, err := platform.IsOperatorAllowedOnNamespace(ctx, r.client, request.Namespace); err != nil {
+ return reconcile.Result{}, err
+ } else if !ok {
+ rlog.Info("Ignoring request because namespace is locked")
+ return reconcile.Result{}, nil
+ }
+
var instance v1.IntegrationKit
// Fetch the IntegrationKit instance
diff --git a/pkg/controller/integrationplatform/integrationplatform_controller.go b/pkg/controller/integrationplatform/integrationplatform_controller.go
index 6412ba7..9a0d99d 100644
--- a/pkg/controller/integrationplatform/integrationplatform_controller.go
+++ b/pkg/controller/integrationplatform/integrationplatform_controller.go
@@ -22,6 +22,7 @@ import (
"time"
camelevent "github.com/apache/camel-k/pkg/event"
+ "github.com/apache/camel-k/pkg/platform"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/tools/record"
@@ -111,6 +112,14 @@ func (r *ReconcileIntegrationPlatform) Reconcile(request reconcile.Request) (rec
ctx := context.TODO()
+ // Make sure the operator is allowed to act on namespace
+ if ok, err := platform.IsOperatorAllowedOnNamespace(ctx, r.client, request.Namespace); err != nil {
+ return reconcile.Result{}, err
+ } else if !ok {
+ rlog.Info("Ignoring request because namespace is locked")
+ return reconcile.Result{}, nil
+ }
+
// Fetch the IntegrationPlatform instance
var instance v1.IntegrationPlatform
diff --git a/pkg/controller/kamelet/kamelet_controller.go b/pkg/controller/kamelet/kamelet_controller.go
index 0522a59..22d7548 100644
--- a/pkg/controller/kamelet/kamelet_controller.go
+++ b/pkg/controller/kamelet/kamelet_controller.go
@@ -24,6 +24,7 @@ import (
"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
"github.com/apache/camel-k/pkg/client"
camelevent "github.com/apache/camel-k/pkg/event"
+ "github.com/apache/camel-k/pkg/platform"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/tools/record"
@@ -109,6 +110,14 @@ func (r *ReconcileKamelet) Reconcile(request reconcile.Request) (reconcile.Resul
ctx := context.TODO()
+ // Make sure the operator is allowed to act on namespace
+ if ok, err := platform.IsOperatorAllowedOnNamespace(ctx, r.client, request.Namespace); err != nil {
+ return reconcile.Result{}, err
+ } else if !ok {
+ rlog.Info("Ignoring request because namespace is locked")
+ return reconcile.Result{}, nil
+ }
+
// Fetch the Kamelet instance
var instance v1alpha1.Kamelet
diff --git a/pkg/controller/kameletbinding/kamelet_binding_controller.go b/pkg/controller/kameletbinding/kamelet_binding_controller.go
index dbebfc3..bbc84cb 100644
--- a/pkg/controller/kameletbinding/kamelet_binding_controller.go
+++ b/pkg/controller/kameletbinding/kamelet_binding_controller.go
@@ -25,6 +25,7 @@ import (
"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
"github.com/apache/camel-k/pkg/client"
camelevent "github.com/apache/camel-k/pkg/event"
+ "github.com/apache/camel-k/pkg/platform"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/tools/record"
@@ -119,6 +120,14 @@ func (r *ReconcileKameletBinding) Reconcile(request reconcile.Request) (reconcil
ctx := context.TODO()
+ // Make sure the operator is allowed to act on namespace
+ if ok, err := platform.IsOperatorAllowedOnNamespace(ctx, r.client, request.Namespace); err != nil {
+ return reconcile.Result{}, err
+ } else if !ok {
+ rlog.Info("Ignoring request because namespace is locked")
+ return reconcile.Result{}, nil
+ }
+
// Fetch the KameletBinding instance
var instance v1alpha1.KameletBinding
diff --git a/pkg/platform/operator.go b/pkg/platform/operator.go
index 82ed950..d0ff38b 100644
--- a/pkg/platform/operator.go
+++ b/pkg/platform/operator.go
@@ -32,6 +32,8 @@ const operatorWatchNamespaceEnvVariable = "WATCH_NAMESPACE"
const operatorNamespaceEnvVariable = "NAMESPACE"
const operatorPodNameEnvVariable = "POD_NAME"
+const OperatorLockName = "camel-k-lock"
+
// GetCurrentOperatorImage returns the image currently used by the running operator if present (when running out of cluster, it may be absent).
func GetCurrentOperatorImage(ctx context.Context, c client.Client) (string, error) {
podNamespace := GetOperatorNamespace()
@@ -80,3 +82,34 @@ func GetOperatorPodName() string {
}
return ""
}
+
+// IsNamespaceLocked tells if the namespace contains a lock indicating that an operator owns it
+func IsNamespaceLocked(ctx context.Context, c client.Client, namespace string) (bool, error) {
+ if namespace == "" {
+ return false, nil
+ }
+
+ cm := v1.ConfigMap{}
+ key := client.ObjectKey{
+ Namespace: namespace,
+ Name: OperatorLockName,
+ }
+ if err := c.Get(ctx, key, &cm); err != nil && k8serrors.IsNotFound(err) {
+ return false, nil
+ } else if err != nil {
+ return true, err
+ }
+ return true, nil
+}
+
+// IsOperatorAllowedOnNamespace returns true if the current operator is allowed to react on changes in the given namespace
+func IsOperatorAllowedOnNamespace(ctx context.Context, c client.Client, namespace string) (bool, error) {
+ if !IsCurrentOperatorGlobal() {
+ return true, nil
+ }
+ alreadyOwned, err := IsNamespaceLocked(ctx, c, namespace)
+ if err != nil {
+ return false, err
+ }
+ return !alreadyOwned, nil
+}