Skip to content

Commit

Permalink
fix(binding): don't panic if no binding available
Browse files Browse the repository at this point in the history
Closes #5953
  • Loading branch information
squakez committed Nov 23, 2024
1 parent c1d464e commit 5745436
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 5 deletions.
96 changes: 96 additions & 0 deletions pkg/controller/kameletbinding/initialize_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
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 kameletbinding

import (
"context"
"testing"

corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/ptr"

v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
"github.com/apache/camel-k/v2/pkg/apis/camel/v1alpha1"

"github.com/apache/camel-k/v2/pkg/util/log"
"github.com/apache/camel-k/v2/pkg/util/test"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestNewKLBUnsupportedRef(t *testing.T) {
svc := &corev1.Service{
TypeMeta: metav1.TypeMeta{
Kind: "Service",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "my-svc",
Namespace: "ns",
},
Spec: corev1.ServiceSpec{
Ports: []corev1.ServicePort{},
Selector: map[string]string{
v1.IntegrationLabel: "my-klb",
},
},
}
klb := &v1alpha1.KameletBinding{
TypeMeta: metav1.TypeMeta{
APIVersion: v1alpha1.SchemeGroupVersion.String(),
Kind: v1alpha1.KameletBindingKind,
},
ObjectMeta: metav1.ObjectMeta{
Namespace: "ns",
Name: "my-klb",
},
Spec: v1alpha1.KameletBindingSpec{
Source: v1alpha1.Endpoint{
URI: ptr.To("timer:tick"),
},
Sink: v1alpha1.Endpoint{
Ref: &corev1.ObjectReference{
APIVersion: svc.APIVersion,
Kind: svc.Kind,
Namespace: svc.Namespace,
Name: svc.Name,
},
},
},
}
c, err := test.NewFakeClient(klb)
require.NoError(t, err)

a := NewInitializeAction()
a.InjectLogger(log.Log)
a.InjectClient(c)
assert.Equal(t, "initialize", a.Name())
assert.True(t, a.CanHandle(klb))
handledKlb, err := a.Handle(context.TODO(), klb)
require.Error(t, err)
assert.Equal(t, "could not find any suitable binding provider for v1/Service my-svc in namespace ns. "+
"Bindings available: [\"kamelet\" \"knative-uri\" \"strimzi\" \"camel-uri\" \"knative-ref\"]", err.Error())
assert.Equal(t, v1alpha1.KameletBindingPhaseError, handledKlb.Status.Phase)
cond := handledKlb.Status.GetCondition(v1alpha1.KameletBindingIntegrationConditionError)
assert.NotNil(t, cond)
assert.Equal(t, corev1.ConditionFalse, cond.Status)
assert.Equal(t, "could not find any suitable binding provider for v1/Service my-svc in namespace ns. "+
"Bindings available: [\"kamelet\" \"knative-uri\" \"strimzi\" \"camel-uri\" \"knative-ref\"]", cond.Message)
}
6 changes: 3 additions & 3 deletions pkg/controller/kameletbinding/integration.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,16 +105,16 @@ func CreateIntegrationFor(ctx context.Context, c client.Client, binding *v1alpha

from, err := bindings.TranslateV1alpha1(bindingContext, endpointTypeSourceContext, binding.Spec.Source)
if err != nil {
return nil, fmt.Errorf("could not determine source URI: %w", err)
return nil, err
}
to, err := bindings.TranslateV1alpha1(bindingContext, endpointTypeSinkContext, binding.Spec.Sink)
if err != nil {
return nil, fmt.Errorf("could not determine sink URI: %w", err)
return nil, err
}
// error handler is optional
errorHandler, err := maybeErrorHandler(binding.Spec.ErrorHandler, bindingContext)
if err != nil {
return nil, fmt.Errorf("could not determine error handler: %w", err)
return nil, err
}

steps := make([]*bindings.Binding, 0, len(binding.Spec.Steps))
Expand Down
15 changes: 13 additions & 2 deletions pkg/util/bindings/catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,17 +102,28 @@ func validateEndpoint(ctx BindingContext, e v1.Endpoint) error {
// TranslateV1alpha1 execute all chained binding providers, returning the first success or the first error.
// Deprecated.
func TranslateV1alpha1(ctx V1alpha1BindingContext, endpointCtx V1alpha1EndpointContext, endpoint v1alpha1.Endpoint) (*Binding, error) {
availableBindings := make([]string, len(v1alpha1BindingProviders))
if err := validateEndpointV1alpha1(ctx, endpoint); err != nil {
return nil, err
}

for _, bp := range v1alpha1BindingProviders {
for i, bp := range v1alpha1BindingProviders {
availableBindings[i] = bp.ID()
b, err := bp.Translate(ctx, endpointCtx, endpoint)
if b != nil || err != nil {
return b, err
}
}
return nil, nil

// If no success we return an error with the actual list of available binding providers
var errorMessage string
if endpoint.Ref != nil {
errorMessage = fmt.Sprintf("could not find any suitable binding provider for %s/%s %s in namespace %s. Bindings available: %q",
endpoint.Ref.APIVersion, endpoint.Ref.Kind, endpoint.Ref.Name, endpoint.Ref.Namespace, availableBindings)
} else if ptr.Deref(endpoint.URI, "") != "" {
errorMessage = fmt.Sprintf("could not find any suitable binding provider for %s", *endpoint.URI)
}
return nil, fmt.Errorf(errorMessage)
}

// Deprecated.
Expand Down

0 comments on commit 5745436

Please sign in to comment.