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/12/03 14:04:38 UTC
[camel-k] branch master updated: Fix #1675: use kamelets in the
operator namespace
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 66660a3 Fix #1675: use kamelets in the operator namespace
66660a3 is described below
commit 66660a33669ac55d08d773b537a0d728467848ae
Author: nicolaferraro <ni...@gmail.com>
AuthorDate: Tue Dec 1 15:57:36 2020 +0100
Fix #1675: use kamelets in the operator namespace
---
deploy/resources.go | 16 ++++++
.../user-global-kamelet-viewer-role-binding.yaml | 31 +++++++++++
deploy/user-global-kamelet-viewer-role.yaml | 32 +++++++++++
e2e/common/files/timer-kamelet-usage.groovy | 19 +++++++
e2e/common/global_kamelet_test.go | 63 ++++++++++++++++++++++
pkg/cmd/operator/operator.go | 6 ++-
pkg/controller/kameletbinding/initialize.go | 3 +-
pkg/install/kamelets.go | 8 +++
pkg/install/optional.go | 23 ++++++--
pkg/kamelet/repository/repository.go | 15 ++++++
pkg/trait/kamelets.go | 5 +-
11 files changed, 213 insertions(+), 8 deletions(-)
diff --git a/deploy/resources.go b/deploy/resources.go
index 4767929..a67c4fb 100644
--- a/deploy/resources.go
+++ b/deploy/resources.go
@@ -351,6 +351,20 @@ var assets = func() http.FileSystem {
compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x53\xc1\x8e\xdb\x36\x10\xbd\xf3\x2b\x1e\xa4\x4b\x52\xac\xe5\xb6\xa7\x42\x3d\xb9\x9b\xdd\x56\x68\x60\x03\x2b\xa7\x41\x50\xf4\x40\x8b\x63\x69\xb0\x14\xa9\x0e\xa9\x55\xb6\x5f\x5f\x90\xb6\x37\x5e\x14\x3d\x04\x08\x6f\x24\x87\x6f\xde\x9b\xf7\x58\x62\xf5\xed\x96\x2a\xf1\x9e\x3b\x72\x81\x0c\xa2\x47\x1c\x08\x9b\x49\x77\x03\xa1\xf5\xc7\xb8\x68\x21\xdc\xfb\xd9\x19\x1d\xd9\x3b\xbc\xd9\xb4\xf7\x6f\x31\x3b\x43\x02\xef\x08\x5e\x [...]
},
+ "/user-global-kamelet-viewer-role-binding.yaml": &vfsgen۰CompressedFileInfo{
+ name: "user-global-kamelet-viewer-role-binding.yaml",
+ modTime: time.Time{},
+ uncompressedSize: 1250,
+
+ compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x53\xcd\x6e\xda\x4c\x14\xdd\xcf\x53\x1c\xe1\x4d\x22\x81\xf9\xbe\xae\x2a\x77\x45\x12\x68\xad\x46\x20\x61\xd2\x28\xcb\x8b\x7d\xb1\x6f\xb1\x67\xdc\x99\x71\x1c\xfa\xf4\xd5\x18\xc8\x8f\x2a\xb5\xaa\x94\xd9\x20\x34\x77\xce\xcf\x3d\xc7\x11\x26\xef\x77\x54\x84\x5b\xc9\x59\x3b\x2e\xe0\x0d\x7c\xc5\x98\xb5\x94\x57\x8c\xcc\xec\x7c\x4f\x96\xb1\x30\x9d\x2e\xc8\x8b\xd1\xb8\x98\x65\x8b\x4b\x74\xba\x60\x0b\xa3\x19\xc6\xa2\x31\x96\x [...]
+ },
+ "/user-global-kamelet-viewer-role.yaml": &vfsgen۰CompressedFileInfo{
+ name: "user-global-kamelet-viewer-role.yaml",
+ modTime: time.Time{},
+ uncompressedSize: 1166,
+
+ compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x53\x4f\x6f\xfa\x46\x14\xbc\xef\xa7\x18\xe1\x4b\x22\x81\x69\x7b\xaa\xe8\x89\x26\xd0\x5a\x8d\x40\xc2\xa4\x51\x8e\x8b\xfd\xb0\x9f\x58\xef\xba\x6f\xd7\x38\xf4\xd3\x57\x6b\x4c\x43\xf4\xbb\x66\x2f\xeb\x3f\xe3\x37\x33\x3b\xe3\x04\xb3\xef\x5b\x2a\xc1\x0b\x17\x64\x3d\x95\x08\x0e\xa1\x26\x2c\x5b\x5d\xd4\x84\xdc\x1d\x43\xaf\x85\xb0\x76\x9d\x2d\x75\x60\x67\xf1\xb0\xcc\xd7\x8f\xe8\x6c\x49\x02\x67\x09\x4e\xd0\x38\x21\x95\xa0\x [...]
+ },
}
fs["/"].(*vfsgen۰DirInfo).entries = []os.FileInfo{
fs["/addons"].(os.FileInfo),
@@ -390,6 +404,8 @@ var assets = func() http.FileSystem {
fs["/templates"].(os.FileInfo),
fs["/traits.yaml"].(os.FileInfo),
fs["/user-cluster-role.yaml"].(os.FileInfo),
+ fs["/user-global-kamelet-viewer-role-binding.yaml"].(os.FileInfo),
+ fs["/user-global-kamelet-viewer-role.yaml"].(os.FileInfo),
}
fs["/addons"].(*vfsgen۰DirInfo).entries = []os.FileInfo{
fs["/addons/master"].(os.FileInfo),
diff --git a/deploy/user-global-kamelet-viewer-role-binding.yaml b/deploy/user-global-kamelet-viewer-role-binding.yaml
new file mode 100644
index 0000000..62fd38a
--- /dev/null
+++ b/deploy/user-global-kamelet-viewer-role-binding.yaml
@@ -0,0 +1,31 @@
+# ---------------------------------------------------------------------------
+# 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.
+# ---------------------------------------------------------------------------
+
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+ name: camel-k-kamelet-viewer
+ labels:
+ app: "camel-k"
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: Role
+ name: camel-k-kamelet-viewer
+subjects:
+- apiGroup: rbac.authorization.k8s.io
+ kind: Group
+ name: system:authenticated
diff --git a/deploy/user-global-kamelet-viewer-role.yaml b/deploy/user-global-kamelet-viewer-role.yaml
new file mode 100644
index 0000000..80bc061
--- /dev/null
+++ b/deploy/user-global-kamelet-viewer-role.yaml
@@ -0,0 +1,32 @@
+# ---------------------------------------------------------------------------
+# 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.
+# ---------------------------------------------------------------------------
+
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+ name: camel-k-kamelet-viewer
+ labels:
+ app: "camel-k"
+rules:
+- apiGroups:
+ - "camel.apache.org"
+ resources:
+ - kamelets
+ verbs:
+ - get
+ - list
+ - watch
diff --git a/e2e/common/files/timer-kamelet-usage.groovy b/e2e/common/files/timer-kamelet-usage.groovy
new file mode 100644
index 0000000..11ad5bb
--- /dev/null
+++ b/e2e/common/files/timer-kamelet-usage.groovy
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+from('kamelet:my-own-timer-source?message=Hello+world')
+ .to('log:info?showAll=false')
diff --git a/e2e/common/global_kamelet_test.go b/e2e/common/global_kamelet_test.go
new file mode 100644
index 0000000..4886820
--- /dev/null
+++ b/e2e/common/global_kamelet_test.go
@@ -0,0 +1,63 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "integration"
+
+/*
+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 common
+
+import (
+ "os"
+ "testing"
+
+ . "github.com/apache/camel-k/e2e/support"
+ "github.com/apache/camel-k/pkg/util/openshift"
+ . "github.com/onsi/gomega"
+ "github.com/stretchr/testify/assert"
+ v1 "k8s.io/api/core/v1"
+)
+
+func TestRunGlobalKamelet(t *testing.T) {
+ forceGlobalTest := os.Getenv("CAMEL_K_FORCE_GLOBAL_TEST") == "true"
+ if !forceGlobalTest {
+ ocp, err := openshift.IsOpenShift(TestClient)
+ assert.Nil(t, err)
+ if ocp {
+ t.Skip("Prefer not to run on OpenShift to avoid giving more permissions to the user running tests")
+ return
+ }
+ }
+
+ WithNewTestNamespace(t, func(ns string) {
+ Expect(Kamel("install", "-n", ns, "--global").Execute()).Should(BeNil())
+
+ Expect(CreateTimerKamelet(ns, "my-own-timer-source")()).Should(BeNil())
+
+ // NS2: namespace without operator
+ WithNewTestNamespace(t, func(ns2 string) {
+ Expect(Kamel("install", "-n", ns2, "--skip-operator-setup", "--olm=false").Execute()).Should(BeNil())
+
+ Expect(Kamel("run", "-n", ns2, "files/timer-kamelet-usage.groovy").Execute()).Should(BeNil())
+ Eventually(IntegrationPodPhase(ns2, "timer-kamelet-usage"), TestTimeoutMedium).Should(Equal(v1.PodRunning))
+ Eventually(IntegrationLogs(ns2, "timer-kamelet-usage"), TestTimeoutShort).Should(ContainSubstring("Hello world"))
+ Expect(Kamel("delete", "--all", "-n", ns2).Execute()).Should(BeNil())
+ })
+
+ Expect(Kamel("uninstall", "-n", ns, "--skip-cluster-roles=false", "--skip-cluster-role-bindings=false").Execute()).Should(BeNil())
+ })
+}
diff --git a/pkg/cmd/operator/operator.go b/pkg/cmd/operator/operator.go
index 2b1cc54..fb4a7c2 100644
--- a/pkg/cmd/operator/operator.go
+++ b/pkg/cmd/operator/operator.go
@@ -65,7 +65,8 @@ func printVersion() {
}
// Run starts the Camel K operator
-func Run(healthPort, monitoringPort int32) {rand.Seed(time.Now().UTC().UnixNano())
+func Run(healthPort, monitoringPort int32) {
+ rand.Seed(time.Now().UTC().UnixNano())
flag.Parse()
@@ -151,7 +152,8 @@ func Run(healthPort, monitoringPort int32) {rand.Seed(time.Now().UTC().UnixNano(
// Try to register the OpenShift CLI Download link if possible
installCtx, installCancel := context.WithTimeout(context.TODO(), 1*time.Minute)
defer installCancel()
- install.OperatorStartupOptionalTools(installCtx, c, namespace, log)
+ operatorNamespace := os.Getenv("NAMESPACE")
+ install.OperatorStartupOptionalTools(installCtx, c, namespace, operatorNamespace, log)
// Setup all Controllers
if err := controller.AddToManager(mgr); err != nil {
diff --git a/pkg/controller/kameletbinding/initialize.go b/pkg/controller/kameletbinding/initialize.go
index 7235cd9..66fc329 100644
--- a/pkg/controller/kameletbinding/initialize.go
+++ b/pkg/controller/kameletbinding/initialize.go
@@ -23,6 +23,7 @@ import (
"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
"github.com/apache/camel-k/pkg/kamelet/repository"
+ "github.com/apache/camel-k/pkg/platform"
"github.com/apache/camel-k/pkg/util/kubernetes"
"github.com/apache/camel-k/pkg/util/patch"
"github.com/pkg/errors"
@@ -109,7 +110,7 @@ func (action *initializeAction) findIcon(ctx context.Context, binding *v1alpha1.
return "", nil
}
- repo, err := repository.New(ctx, action.client, binding.Namespace)
+ repo, err := repository.New(ctx, action.client, binding.Namespace, platform.GetOperatorNamespace())
if err != nil {
return "", err
}
diff --git a/pkg/install/kamelets.go b/pkg/install/kamelets.go
index 07fb006..7298820 100644
--- a/pkg/install/kamelets.go
+++ b/pkg/install/kamelets.go
@@ -89,3 +89,11 @@ func KameletCatalog(ctx context.Context, c client.Client, namespace string) erro
return nil
}
+
+// KameletViewerRole installs the role that allows any user ro access kamelets in the global namespace
+func KameletViewerRole(ctx context.Context, c client.Client, namespace string) error {
+ if err := Resource(ctx, c, namespace, true, IdentityResourceCustomizer, "user-global-kamelet-viewer-role.yaml"); err != nil {
+ return err
+ }
+ return Resource(ctx, c, namespace, true, IdentityResourceCustomizer, "user-global-kamelet-viewer-role-binding.yaml")
+}
diff --git a/pkg/install/optional.go b/pkg/install/optional.go
index 0571844..e7019f4 100644
--- a/pkg/install/optional.go
+++ b/pkg/install/optional.go
@@ -26,7 +26,7 @@ import (
)
// OperatorStartupOptionalTools tries to install optional tools at operator startup and warns if something goes wrong
-func OperatorStartupOptionalTools(ctx context.Context, c client.Client, namespace string, log logr.Logger) {
+func OperatorStartupOptionalTools(ctx context.Context, c client.Client, namespace string, operatorNamespace string, log logr.Logger) {
// Try to register the OpenShift CLI Download link if possible
if err := OpenShiftConsoleDownloadLink(ctx, c); err != nil {
@@ -45,12 +45,29 @@ func OperatorStartupOptionalTools(ctx context.Context, c client.Client, namespac
}
}
- // Try to install Kamelet Catalog automatically if operator is namespace scoped
+ // Try to install Kamelet Catalog automatically
+ var kameletNamespace string
+ globalOperator := false
if namespace != "" && !strings.Contains(namespace, ",") {
- if err := KameletCatalog(ctx, c, namespace); err != nil {
+ kameletNamespace = namespace
+ } else {
+ kameletNamespace = operatorNamespace
+ globalOperator = true
+ }
+
+ if kameletNamespace != "" {
+ if err := KameletCatalog(ctx, c, kameletNamespace); err != nil {
log.Info("Cannot install bundled Kamelet Catalog: skipping.")
log.V(8).Info("Error while installing bundled Kamelet Catalog", "error", err)
}
+
+ if globalOperator {
+ // Make sure that Kamelets installed in operator namespace can be used by others
+ if err := KameletViewerRole(ctx, c, kameletNamespace); err != nil {
+ log.Info("Cannot install global Kamelet viewer role: skipping.")
+ log.V(8).Info("Error while installing global Kamelet viewer role", "error", err)
+ }
+ }
}
}
diff --git a/pkg/kamelet/repository/repository.go b/pkg/kamelet/repository/repository.go
index a0f8a1b..721b887 100644
--- a/pkg/kamelet/repository/repository.go
+++ b/pkg/kamelet/repository/repository.go
@@ -53,6 +53,7 @@ type KameletRepository interface {
// If one namespace defines an IntegrationPlatform (only the first IntegrationPlatform in state "Ready" found),
// then all kamelet repository URIs defined in the IntegrationPlatform are included.
func New(ctx context.Context, client camel.Interface, namespaces ...string) (KameletRepository, error) {
+ namespaces = makeDistinctNonEmpty(namespaces)
platform, err := lookupPlatform(ctx, client, namespaces...)
if err != nil {
return nil, err
@@ -64,6 +65,7 @@ func New(ctx context.Context, client camel.Interface, namespaces ...string) (Kam
// Kamelets are first looked up in all the given namespaces, in the order they appear,
// then repositories defined in the platform are looked up.
func NewForPlatform(ctx context.Context, client camel.Interface, platform *v1.IntegrationPlatform, namespaces ...string) (KameletRepository, error) {
+ namespaces = makeDistinctNonEmpty(namespaces)
repoImpls := make([]KameletRepository, 0)
for _, namespace := range namespaces {
// Add first a namespace local repository for each namespace
@@ -176,3 +178,16 @@ func newFromURI(uri string) (KameletRepository, error) {
}
return nil, fmt.Errorf("invalid uri: %s", uri)
}
+
+func makeDistinctNonEmpty(names []string) []string {
+ res := make([]string, 0, len(names))
+ presence := make(map[string]bool, len(names))
+ for _, n := range names {
+ if n == "" || presence[n] {
+ continue
+ }
+ presence[n] = true
+ res = append(res, n)
+ }
+ return res
+}
diff --git a/pkg/trait/kamelets.go b/pkg/trait/kamelets.go
index 13c5bee..390c754 100644
--- a/pkg/trait/kamelets.go
+++ b/pkg/trait/kamelets.go
@@ -30,6 +30,7 @@ import (
kameletutils "github.com/apache/camel-k/pkg/kamelet"
"github.com/apache/camel-k/pkg/kamelet/repository"
"github.com/apache/camel-k/pkg/metadata"
+ "github.com/apache/camel-k/pkg/platform"
"github.com/apache/camel-k/pkg/util"
"github.com/apache/camel-k/pkg/util/digest"
"github.com/apache/camel-k/pkg/util/flow"
@@ -132,7 +133,7 @@ func (t *kameletsTrait) Apply(e *Environment) error {
func (t *kameletsTrait) addKamelets(e *Environment) error {
kameletKeys := t.getKameletKeys()
if len(kameletKeys) > 0 {
- repo, err := repository.NewForPlatform(e.C, e.Client, e.Platform, e.Integration.Namespace)
+ repo, err := repository.NewForPlatform(e.C, e.Client, e.Platform, e.Integration.Namespace, platform.GetOperatorNamespace())
if err != nil {
return err
}
@@ -170,7 +171,7 @@ func (t *kameletsTrait) addKamelets(e *Environment) error {
func (t *kameletsTrait) configureApplicationProperties(e *Environment) error {
if len(t.getKameletKeys()) > 0 {
- repo, err := repository.NewForPlatform(e.C, e.Client, e.Platform, e.Integration.Namespace)
+ repo, err := repository.NewForPlatform(e.C, e.Client, e.Platform, e.Integration.Namespace, platform.GetOperatorNamespace())
if err != nil {
return err
}