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
commit d0366d8436c45b23661e71e79ba491c4d6001e35 Author: nferraro <ni.ferr...@gmail.com> AuthorDate: Tue Jul 23 23:21:44 2019 +0200 Fix #856: lookup destination in multiple places and add e2e tests --- e2e/files/knative1.groovy | 20 +++++++ e2e/files/knative2.groovy | 19 +++++++ e2e/files/knativech1.groovy | 20 +++++++ e2e/files/knativech2.groovy | 19 +++++++ e2e/knative_test.go | 57 +++++++++++++++++++ e2e/test_support.go | 31 +++++++++- pkg/apis/camel/v1alpha1/knative/types_support.go | 10 +--- pkg/cmd/install.go | 13 +++++ pkg/trait/knative.go | 72 +++++++++++++++--------- script/Makefile | 5 +- 10 files changed, 230 insertions(+), 36 deletions(-) diff --git a/e2e/files/knative1.groovy b/e2e/files/knative1.groovy new file mode 100644 index 0000000..b69fc82 --- /dev/null +++ b/e2e/files/knative1.groovy @@ -0,0 +1,20 @@ +/* + * 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('timer:tick') + .to('knative:endpoint/knative2') + .log('Received: ${body}') diff --git a/e2e/files/knative2.groovy b/e2e/files/knative2.groovy new file mode 100644 index 0000000..cb1c6fb --- /dev/null +++ b/e2e/files/knative2.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('knative:endpoint/knative2') + .setBody().constant("Hello from knative2") diff --git a/e2e/files/knativech1.groovy b/e2e/files/knativech1.groovy new file mode 100644 index 0000000..1a32a64 --- /dev/null +++ b/e2e/files/knativech1.groovy @@ -0,0 +1,20 @@ +/* + * 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('timer:tick') + .setBody().constant("Hello from knativech1") + .to('knative:channel/messages') diff --git a/e2e/files/knativech2.groovy b/e2e/files/knativech2.groovy new file mode 100644 index 0000000..65eeb2e --- /dev/null +++ b/e2e/files/knativech2.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('knative:channel/messages') + .log('Received: ${body}') diff --git a/e2e/knative_test.go b/e2e/knative_test.go new file mode 100644 index 0000000..371add2 --- /dev/null +++ b/e2e/knative_test.go @@ -0,0 +1,57 @@ +// +build knative + +// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "knative" + +/* +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 e2e + +import ( + "testing" + "time" + + . "github.com/onsi/gomega" + v1 "k8s.io/api/core/v1" +) + +func TestRunServiceCombo(t *testing.T) { + withNewTestNamespace(func(ns string) { + RegisterTestingT(t) + Expect(kamel("install", "-n", ns, "--trait-profile", "knative").Execute()).Should(BeNil()) + Expect(kamel("run", "-n", ns, "files/knative2.groovy").Execute()).Should(BeNil()) + Expect(kamel("run", "-n", ns, "files/knative1.groovy").Execute()).Should(BeNil()) + Eventually(integrationPodPhase(ns, "knative2"), 10*time.Minute).Should(Equal(v1.PodRunning)) + Eventually(integrationPodPhase(ns, "knative1"), 10*time.Minute).Should(Equal(v1.PodRunning)) + Eventually(integrationLogs(ns, "knative1"), 5*time.Minute).Should(ContainSubstring("Received: Hello from knative2")) + Expect(kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil()) + }) +} + +func TestRunChannelCombo(t *testing.T) { + withNewTestNamespace(func(ns string) { + RegisterTestingT(t) + Expect(createKnativeChannel(ns, "messages")()).Should(BeNil()) + Expect(kamel("install", "-n", ns, "--trait-profile", "knative").Execute()).Should(BeNil()) + Expect(kamel("run", "-n", ns, "files/knativech2.groovy").Execute()).Should(BeNil()) + Expect(kamel("run", "-n", ns, "files/knativech1.groovy").Execute()).Should(BeNil()) + Eventually(integrationPodPhase(ns, "knativech2"), 10*time.Minute).Should(Equal(v1.PodRunning)) + Eventually(integrationPodPhase(ns, "knativech1"), 10*time.Minute).Should(Equal(v1.PodRunning)) + Eventually(integrationLogs(ns, "knativech2"), 5*time.Minute).Should(ContainSubstring("Received: Hello from knativech1")) + Expect(kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil()) + }) +} diff --git a/e2e/test_support.go b/e2e/test_support.go index 134c825..5a0ca40 100644 --- a/e2e/test_support.go +++ b/e2e/test_support.go @@ -1,4 +1,4 @@ -// +build integration +// +build integration knative // To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "integration" @@ -35,6 +35,7 @@ import ( "github.com/apache/camel-k/pkg/util/log" "github.com/apache/camel-k/pkg/util/openshift" "github.com/google/uuid" + eventing "github.com/knative/eventing/pkg/apis/eventing/v1alpha1" "github.com/onsi/gomega" projectv1 "github.com/openshift/api/project/v1" "github.com/spf13/cobra" @@ -409,6 +410,34 @@ func scaleOperator(ns string, replicas int32) func() error { } /* + Knative + */ + +func createKnativeChannel(ns string, name string) func() error { + return func() error { + channel := eventing.Channel{ + TypeMeta: metav1.TypeMeta{ + Kind: "Channel", + APIVersion: eventing.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: ns, + Name: name, + }, + Spec: eventing.ChannelSpec{ + Provisioner: &v1.ObjectReference{ + APIVersion: "eventing.knative.dev/v1alpha1", + Kind: "ClusterChannelProvisioner", + Name: "in-memory", + }, + }, + } + return testClient.Create(testContext, &channel) + } +} + + +/* Namespace testing functions */ diff --git a/pkg/apis/camel/v1alpha1/knative/types_support.go b/pkg/apis/camel/v1alpha1/knative/types_support.go index 4c9e53e..f18f35b 100644 --- a/pkg/apis/camel/v1alpha1/knative/types_support.go +++ b/pkg/apis/camel/v1alpha1/knative/types_support.go @@ -24,11 +24,7 @@ import ( ) // BuildCamelServiceDefinition creates a CamelServiceDefinition from a given URL -func BuildCamelServiceDefinition(name string, serviceType CamelServiceType, rawurl string) (*CamelServiceDefinition, error) { - serviceURL, err := url.Parse(rawurl) - if err != nil { - return nil, err - } +func BuildCamelServiceDefinition(name string, serviceType CamelServiceType, serviceURL url.URL) (CamelServiceDefinition, error) { protocol := CamelProtocol(serviceURL.Scheme) definition := CamelServiceDefinition{ Name: name, @@ -42,7 +38,7 @@ func BuildCamelServiceDefinition(name string, serviceType CamelServiceType, rawu if portStr != "" { port, err := strconv.Atoi(portStr) if err != nil { - return nil, err + return CamelServiceDefinition{}, err } definition.Port = port } @@ -52,7 +48,7 @@ func BuildCamelServiceDefinition(name string, serviceType CamelServiceType, rawu } else { definition.Metadata[CamelMetaServicePath] = "/" } - return &definition, nil + return definition, nil } func defaultCamelProtocolPort(prot CamelProtocol) int { diff --git a/pkg/cmd/install.go b/pkg/cmd/install.go index 9f13bb6..166b862 100644 --- a/pkg/cmd/install.go +++ b/pkg/cmd/install.go @@ -73,6 +73,7 @@ func newCmdInstall(rootCmdOptions *RootCmdOptions) *cobra.Command { cmd.Flags().StringSliceVar(&impl.kits, "kit", nil, "Add an integration kit to build at startup") cmd.Flags().StringVar(&impl.buildStrategy, "build-strategy", "", "Set the build strategy") cmd.Flags().StringVar(&impl.buildTimeout, "build-timeout", "", "Set how long the build process can last") + cmd.Flags().StringVar(&impl.traitProfile, "trait-profile", "", "The profile to use for traits") // maven settings cmd.Flags().StringVar(&impl.localRepository, "local-repository", "", "Location of the local maven repository") @@ -112,6 +113,7 @@ type installCmdOptions struct { properties []string kits []string registry v1alpha1.IntegrationPlatformRegistrySpec + traitProfile string } // nolint: gocyclo @@ -208,6 +210,9 @@ func (o *installCmdOptions) install(_ *cobra.Command, _ []string) error { platform.Spec.Build.Timeout.Duration = d } + if o.traitProfile != "" { + platform.Spec.Profile = v1alpha1.TraitProfileByName(o.traitProfile) + } if len(o.mavenRepositories) > 0 { for _, r := range o.mavenRepositories { @@ -318,6 +323,14 @@ func (o *installCmdOptions) validate(_ *cobra.Command, _ []string) error { result = multierr.Append(result, err) } + if o.traitProfile != "" { + tp := v1alpha1.TraitProfileByName(o.traitProfile) + if tp == v1alpha1.TraitProfile("") { + err := fmt.Errorf("unknown trait profile %s", o.traitProfile) + result = multierr.Append(result, err) + } + } + return result } diff --git a/pkg/trait/knative.go b/pkg/trait/knative.go index 698bee5..6f672ff 100644 --- a/pkg/trait/knative.go +++ b/pkg/trait/knative.go @@ -19,18 +19,19 @@ package trait import ( "fmt" + "net/url" "strings" - "github.com/pkg/errors" - - "github.com/scylladb/go-set/strset" - "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" "github.com/apache/camel-k/pkg/metadata" "github.com/apache/camel-k/pkg/util/envvar" + "github.com/pkg/errors" + "github.com/scylladb/go-set/strset" knativeapi "github.com/apache/camel-k/pkg/apis/camel/v1alpha1/knative" knativeutil "github.com/apache/camel-k/pkg/util/knative" + duck "github.com/knative/pkg/apis/duck/v1alpha1" + serving "github.com/knative/serving/pkg/apis/serving/v1alpha1" ) type knativeTrait struct { @@ -210,19 +211,13 @@ func (t *knativeTrait) configureChannels(e *Environment, env *knativeapi.CamelEn if err != nil { return err } - if c == nil || c.Status.Address.Hostname == "" { - return errors.New("cannot find address of channel " + ch) + if c == nil { + return errors.Errorf("cannot find channel %s", ch) } - svc := knativeapi.CamelServiceDefinition{ - Name: ch, - Host: c.Status.Address.Hostname, - Port: 80, - Protocol: knativeapi.CamelProtocolHTTP, - ServiceType: knativeapi.CamelServiceTypeChannel, - Metadata: map[string]string{ - knativeapi.CamelMetaServicePath: "/", - }, + svc, err := buildCamelServiceDefinitionFromAddressable(ch, knativeapi.CamelServiceTypeChannel, c.Status.Address) + if err != nil { + return errors.Wrapf(err, "cannot determine address of channel %s", ch) } env.Services = append(env.Services, svc) } @@ -270,19 +265,12 @@ func (t *knativeTrait) configureEndpoints(e *Environment, env *knativeapi.CamelE if err != nil { return err } - if s == nil || s.Status.Address == nil || s.Status.Address.Hostname == "" { - return errors.New("cannot find address of endpoint " + endpoint) + if s == nil { + return errors.Errorf("cannot find endpoint %s", endpoint) } - - svc := knativeapi.CamelServiceDefinition{ - Name: endpoint, - Host: s.Status.Address.Hostname, - Port: 80, - Protocol: knativeapi.CamelProtocolHTTP, - ServiceType: knativeapi.CamelServiceTypeEndpoint, - Metadata: map[string]string{ - knativeapi.CamelMetaServicePath: "/", - }, + svc, err := buildCamelServiceDefinitionFromServiceStatus(endpoint, knativeapi.CamelServiceTypeEndpoint, s.Status) + if err != nil { + return errors.Wrapf(err, "cannot determine address of endpoint %s", endpoint) } env.Services = append(env.Services, svc) } @@ -301,3 +289,33 @@ func (t *knativeTrait) extractNames(names string) []string { return answer } + +// buildCamelServiceDefinitionFromServiceStatus creates a CamelServiceDefinition from a Knative ServiceStatus +func buildCamelServiceDefinitionFromServiceStatus(name string, serviceType knativeapi.CamelServiceType, status serving.ServiceStatus) (knativeapi.CamelServiceDefinition, error) { + // build it using the Route URL information if available + if status.URL != nil && status.URL.Host != "" { + return knativeapi.BuildCamelServiceDefinition(name, serviceType, url.URL(*status.URL)) + } + // fallback to using the addressable + if status.Address != nil { + return buildCamelServiceDefinitionFromAddressable(name, serviceType, *status.Address) + } + return knativeapi.CamelServiceDefinition{}, errors.New("cannot determine service hostname") +} + +// buildCamelServiceDefinitionFromAddressable creates a CamelServiceDefinition from a Knative Addressable +func buildCamelServiceDefinitionFromAddressable(name string, serviceType knativeapi.CamelServiceType, addressable duck.Addressable) (knativeapi.CamelServiceDefinition, error) { + // build it using the URL information if available + if addressable.URL != nil && addressable.URL.Host != "" { + return knativeapi.BuildCamelServiceDefinition(name, serviceType, url.URL(*addressable.URL)) + } + // fallback to using hostname + if addressable.Hostname == "" { + return knativeapi.CamelServiceDefinition{}, errors.New("cannot determine addressable hostname") + } + serviceURL, err := url.Parse(fmt.Sprintf("http://%s", addressable.Hostname)) + if err != nil { + return knativeapi.CamelServiceDefinition{}, err + } + return knativeapi.BuildCamelServiceDefinition(name, serviceType, *serviceURL) +} diff --git a/script/Makefile b/script/Makefile index 90e2a15..f13df4c 100644 --- a/script/Makefile +++ b/script/Makefile @@ -106,6 +106,9 @@ test: build test-integration: build go test -timeout 30m -v ./e2e/... -tags=integration +test-knative: build + go test -timeout 30m -v ./e2e/... -tags=knative + build-operator: go build $(GOFLAGS) -o camel-k ./cmd/manager/*.go @@ -124,7 +127,7 @@ build-olm: ./script/build_olm.sh $(VERSION) build-compile-integration-tests: - go test -c -tags=integration ./e2e/*.go + go test -c -tags="integration knative" ./e2e/*.go clean: # go clean fails if modules support are turned on as it tries to