You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by pc...@apache.org on 2023/05/09 10:41:11 UTC

[camel-k] branch main updated: fix(#4336): Restrict Knative binding provider execution

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

pcongiusti 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 a1c6c6978 fix(#4336): Restrict Knative binding provider execution
a1c6c6978 is described below

commit a1c6c69783618c2d25977b8c16e6102db81aa84c
Author: Christoph Deppisch <cd...@redhat.com>
AuthorDate: Mon May 8 20:54:44 2023 +0200

    fix(#4336): Restrict Knative binding provider execution
    
    - Only run the binding provider when Knative is installed on the cluster
    - Only run the binding provider when referencing a known Knative resource (e.g. broker, channel, service)
---
 pkg/util/bindings/knative_ref.go      |  28 ++++++
 pkg/util/bindings/knative_ref_test.go | 155 ++++++++++++++++++++++++++++++++++
 2 files changed, 183 insertions(+)

diff --git a/pkg/util/bindings/knative_ref.go b/pkg/util/bindings/knative_ref.go
index 2859692a4..0bd0d7bcf 100644
--- a/pkg/util/bindings/knative_ref.go
+++ b/pkg/util/bindings/knative_ref.go
@@ -25,6 +25,8 @@ import (
 	v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
 	knativeapis "github.com/apache/camel-k/v2/pkg/apis/camel/v1/knative"
 	v1alpha1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1alpha1"
+	corev1 "k8s.io/api/core/v1"
+	"k8s.io/apimachinery/pkg/runtime/schema"
 
 	"github.com/apache/camel-k/v2/pkg/util/knative"
 	"github.com/apache/camel-k/v2/pkg/util/uri"
@@ -46,6 +48,17 @@ func (k KnativeRefBindingProvider) Translate(ctx BindingContext, endpointCtx End
 		return nil, nil
 	}
 
+	if ok, err := isKnownKnativeResource(e.Ref); !ok {
+		// only operates on known Knative endpoint resources (e.g. channels, brokers)
+		return nil, err
+	}
+
+	if knativeInstalled, _ := knative.IsInstalled(ctx.Client); !knativeInstalled {
+		// works only when Knative is installed
+		return nil, fmt.Errorf("integration referencing Knative endpoint '%s' that cannot run, "+
+			"because Knative is not installed on the cluster", e.Ref.Name)
+	}
+
 	serviceType, err := knative.GetServiceType(*e.Ref)
 	if err != nil {
 		return nil, err
@@ -97,6 +110,21 @@ func (k KnativeRefBindingProvider) Translate(ctx BindingContext, endpointCtx End
 	}, nil
 }
 
+func isKnownKnativeResource(ref *corev1.ObjectReference) (bool, error) {
+	gv, err := schema.ParseGroupVersion(ref.APIVersion)
+	if err != nil {
+		return false, err
+	}
+
+	for _, endpoint := range knative.KnownEndpointKinds {
+		if endpoint.Group == gv.Group && endpoint.Kind == ref.Kind {
+			return true, nil
+		}
+	}
+
+	return false, nil
+}
+
 // Order --.
 func (k KnativeRefBindingProvider) Order() int {
 	// Executes as last, as it can be used as fallback for all unknown object references
diff --git a/pkg/util/bindings/knative_ref_test.go b/pkg/util/bindings/knative_ref_test.go
new file mode 100644
index 000000000..9d06ebed3
--- /dev/null
+++ b/pkg/util/bindings/knative_ref_test.go
@@ -0,0 +1,155 @@
+/*
+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 bindings
+
+import (
+	"context"
+	"fmt"
+	"testing"
+
+	"github.com/apache/camel-k/v2/pkg/util/test"
+	"github.com/stretchr/testify/assert"
+	v1 "k8s.io/api/core/v1"
+
+	camelv1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
+)
+
+func TestKnativeRefBinding(t *testing.T) {
+	testcases := []struct {
+		endpoint camelv1.Endpoint
+		uri      string
+	}{
+		{
+			endpoint: camelv1.Endpoint{
+				Ref: &v1.ObjectReference{
+					Kind:       "Broker",
+					Name:       "default",
+					APIVersion: "eventing.knative.dev/v1",
+				},
+			},
+			uri: "knative:event?apiVersion=eventing.knative.dev%2Fv1&kind=Broker&name=default",
+		},
+		{
+			endpoint: camelv1.Endpoint{
+				Ref: &v1.ObjectReference{
+					Kind:       "Channel",
+					Name:       "mychannel",
+					APIVersion: "messaging.knative.dev/v1",
+				},
+			},
+			uri: "knative:channel/mychannel?apiVersion=messaging.knative.dev%2Fv1&kind=Channel",
+		},
+		{
+			endpoint: camelv1.Endpoint{
+				Ref: &v1.ObjectReference{
+					Kind:       "Service",
+					Name:       "myservice",
+					APIVersion: "serving.knative.dev/v1",
+				},
+			},
+			uri: "knative:endpoint/myservice?apiVersion=serving.knative.dev%2Fv1&kind=Service",
+		},
+	}
+
+	for i, tc := range testcases {
+		t.Run(fmt.Sprintf("test-%d-%s", i, tc.endpoint.Ref.Kind), func(t *testing.T) {
+			ctx, cancel := context.WithCancel(context.Background())
+			defer cancel()
+
+			client, err := test.NewFakeClient()
+			assert.NoError(t, err)
+
+			bindingContext := BindingContext{
+				Ctx:       ctx,
+				Client:    client,
+				Namespace: "test",
+				Profile:   camelv1.TraitProfileKnative,
+			}
+
+			binding, err := KnativeRefBindingProvider{}.Translate(bindingContext, EndpointContext{
+				Type: camelv1.EndpointTypeSink,
+			}, tc.endpoint)
+			assert.NoError(t, err)
+			assert.NotNil(t, binding)
+			assert.Equal(t, tc.uri, binding.URI)
+			assert.Equal(t, camelv1.Traits{}, binding.Traits)
+		})
+	}
+}
+
+func TestUnsupportedKnativeResource(t *testing.T) {
+	ctx, cancel := context.WithCancel(context.Background())
+	defer cancel()
+
+	client, err := test.NewFakeClient()
+	assert.NoError(t, err)
+
+	bindingContext := BindingContext{
+		Ctx:       ctx,
+		Client:    client,
+		Namespace: "test",
+		Profile:   camelv1.TraitProfileKnative,
+	}
+
+	endpoint := camelv1.Endpoint{
+		Ref: &v1.ObjectReference{
+			Kind:       "Unknown",
+			Name:       "default",
+			APIVersion: "eventing.knative.dev/v1",
+		},
+	}
+
+	binding, err := KnativeRefBindingProvider{}.Translate(bindingContext, EndpointContext{
+		Type: camelv1.EndpointTypeSink,
+	}, endpoint)
+	assert.NoError(t, err)
+	assert.Nil(t, binding)
+}
+
+func TestKnativeNotInstalled(t *testing.T) {
+	ctx, cancel := context.WithCancel(context.Background())
+	defer cancel()
+
+	client, err := test.NewFakeClient()
+	assert.NoError(t, err)
+
+	// disable the knative service api
+	fakeClient := client.(*test.FakeClient) //nolint
+	fakeClient.DisableAPIGroupDiscovery("serving.knative.dev/v1")
+
+	bindingContext := BindingContext{
+		Ctx:       ctx,
+		Client:    client,
+		Namespace: "test",
+		Profile:   camelv1.TraitProfileKnative,
+	}
+
+	endpoint := camelv1.Endpoint{
+		Ref: &v1.ObjectReference{
+			Kind:       "Broker",
+			Name:       "default",
+			APIVersion: "eventing.knative.dev/v1",
+		},
+	}
+
+	binding, err := KnativeRefBindingProvider{}.Translate(bindingContext, EndpointContext{
+		Type: camelv1.EndpointTypeSink,
+	}, endpoint)
+	assert.Error(t, err, "integration referencing Knative endpoint 'default' that cannot run, because Knative is not installed on the cluster")
+	assert.Nil(t, binding)
+}