Repository: apache/camel-k
Pull request #859 (2019-07-24 07:56:32)

Add --verbose to lint for preventing hangs visibility


Patch:
diff --git a/.gitignore b/.gitignore
index 2513a3296..35ad0f8bf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -126,6 +126,7 @@ Session.vim
 tags
 
 ### VisualStudioCode ###
+.vscode
 .vscode/*
 !.vscode/settings.json
 !.vscode/tasks.json
diff --git a/pkg/apis/camel/v1alpha1/knative/types_support.go b/pkg/apis/camel/v1alpha1/knative/types_support.go
index 4c9e53eb0..f18f35b22 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 9f13bb652..166b86285 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/dependencies.go b/pkg/trait/dependencies.go
index 2fd1a56ff..453806c8d 100644
--- a/pkg/trait/dependencies.go
+++ b/pkg/trait/dependencies.go
@@ -50,7 +50,7 @@ func (t *dependenciesTrait) Apply(e *Environment) error {
 			util.StringSliceUniqueAdd(&dependencies, dep)
 		}
 	}
-	for _, s := range e.Integration.Spec.Sources {
+	for _, s := range e.Integration.Sources() {
 		meta := metadata.Extract(e.CamelCatalog, s)
 
 		switch s.InferLanguage() {
diff --git a/pkg/trait/knative.go b/pkg/trait/knative.go
index 698bee5f9..f1d84db32 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 := buildServiceDefinition(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 := buildServiceDefinitionFromStatus(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
 }
+
+// buildServiceDefinitionFromStatus creates a CamelServiceDefinition from a Knative ServiceStatus
+func buildServiceDefinitionFromStatus(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 buildServiceDefinition(name, serviceType, *status.Address)
+	}
+	return knativeapi.CamelServiceDefinition{}, errors.New("cannot determine service hostname")
+}
+
+// buildServiceDefinition creates a CamelServiceDefinition from a Knative Addressable
+func buildServiceDefinition(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 90e2a153a..5b1759fdd 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 
@@ -152,7 +155,7 @@ dep:
 	go mod tidy
 
 lint:
-	GOGC=$(LINT_GOGC) golangci-lint run --deadline $(LINT_DEADLINE)
+	GOGC=$(LINT_GOGC) golangci-lint run --verbose --deadline $(LINT_DEADLINE)
 
 images: test
 	mkdir -p build/_maven_output


Test patch:
diff --git a/e2e/files/knative1.groovy b/e2e/files/knative1.groovy
new file mode 100644
index 000000000..b69fc824e
--- /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 000000000..cb1c6fbda
--- /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 000000000..1a32a6488
--- /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 000000000..65eeb2eb9
--- /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 000000000..371add2f9
--- /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 134c825fa..5a0ca4050 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"
@@ -408,6 +409,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/trait/dependencies_test.go b/pkg/trait/dependencies_test.go
index 3744264d6..e795fa803 100644
--- a/pkg/trait/dependencies_test.go
+++ b/pkg/trait/dependencies_test.go
@@ -125,3 +125,51 @@ func TestIntegrationCustomDeps(t *testing.T) {
 		e.Integration.Status.Dependencies,
 	)
 }
+
+func TestIntegrationAutoGeneratedDeps(t *testing.T) {
+	catalog, err := test.DefaultCatalog()
+	assert.Nil(t, err)
+
+	e := &Environment{
+		CamelCatalog: catalog,
+		Integration: &v1alpha1.Integration{
+			Spec: v1alpha1.IntegrationSpec{
+				Sources: []v1alpha1.SourceSpec{
+					{
+						DataSpec: v1alpha1.DataSpec{
+							Name:    "Request.java",
+							Content: `from("direct:foo").to("log:bar");`,
+						},
+						Language: v1alpha1.LanguageJavaSource,
+					},
+				},
+			},
+			Status: v1alpha1.IntegrationStatus{
+				Phase: v1alpha1.IntegrationPhaseInitialization,
+				GeneratedSources: []v1alpha1.SourceSpec{
+					{
+						DataSpec: v1alpha1.DataSpec{
+							Name:    "RequestAuto.xml",
+							Content: `<rests xmlns="http://camel.apache.org/schema/spring"><rest path="/camel/"></rest></rests>`,
+						},
+						Language: v1alpha1.LanguageXML,
+					},
+				},
+			},
+		},
+	}
+
+	trait := newDependenciesTrait()
+	enabled, err := trait.Configure(e)
+	assert.Nil(t, err)
+	assert.True(t, enabled)
+
+	err = trait.Apply(e)
+	assert.Nil(t, err)
+	assert.ElementsMatch(
+		t,
+		[]string{"camel:direct", "camel:log", "mvn:org.apache.camel.k/camel-k-loader-java", "mvn:org.apache.camel.k/camel-k-loader-xml",
+			"mvn:org.apache.camel.k/camel-k-runtime-main"},
+		e.Integration.Status.Dependencies,
+	)
+}