[camel-k] branch master updated: kamel run should support adding dependencies #49

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[camel-k] branch master updated: kamel run should support adding dependencies #49

nferraro
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 6d61e5c  kamel run should support adding dependencies #49
6d61e5c is described below

commit 6d61e5c6f2874ae6fca0383b5b473280a6eb8ae8
Author: lburgazzoli <[hidden email]>
AuthorDate: Wed Sep 12 11:21:16 2018 +0200

    kamel run should support adding dependencies #49
---
 README.md                                        |   9 +-
 build/Makefile                                   |   5 +-
 pkg/apis/camel/v1alpha1/types.go                 |  13 +--
 pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go |  22 ++---
 pkg/build/api/types.go                           |   5 +-
 pkg/build/local/local_builder.go                 | 112 +++++++++++++++++------
 pkg/build/local/local_builder_test.go            |  80 ++++++++++++++++
 pkg/client/cmd/run.go                            |  11 ++-
 pkg/stub/action/integration/build.go             |   9 +-
 pkg/util/digest/digest.go                        |   4 +-
 pkg/util/maven/maven.go                          |   4 +-
 pkg/util/maven/mavent_test.go                    |  24 +++++
 pkg/util/maven/types.go                          |  39 ++++++--
 runtime/examples/dns.js                          |  12 +++
 14 files changed, 272 insertions(+), 77 deletions(-)

diff --git a/README.md b/README.md
index 228ef59..b7d7f4c 100644
--- a/README.md
+++ b/README.md
@@ -187,9 +187,16 @@ If you want to install everything you have in your source code and see it runnin
 Now you can play with Camel K:
 
 ```
-./kamel run Sample.java
+./kamel run runtime/examples/Sample.java
 ```
 
+To add additional dependencies to your routes:
+
+```
+./kamel run -d camel:dns runtime/examples/dns.js
+```
+
+
 ### Debugging and Running from IDE
 
 Sometimes it's useful to debug the code from the IDE when troubleshooting.
diff --git a/build/Makefile b/build/Makefile
index 4ff3d6e..74716be 100644
--- a/build/Makefile
+++ b/build/Makefile
@@ -17,6 +17,9 @@ build-runtime:
 dep:
  dep ensure -v
 
+generate:
+ operator-sdk generate k8s
+
 clean:
  mvn clean -f ./runtime/pom.xml
  go clean
@@ -58,4 +61,4 @@ require-kubeconfig:
  @echo "KUBERNETES_CONFIG set"
 endif
 
-.PHONY: build build-operator build-kamel build-embed-resources build-runtime dep codegen images images-build images-push test check test-integration check-integration clean
\ No newline at end of file
+.PHONY: build build-operator build-kamel build-embed-resources build-runtime dep codegen images images-build images-push test check test-integration check-integration clean
diff --git a/pkg/apis/camel/v1alpha1/types.go b/pkg/apis/camel/v1alpha1/types.go
index 324d056..c40b6b1 100644
--- a/pkg/apis/camel/v1alpha1/types.go
+++ b/pkg/apis/camel/v1alpha1/types.go
@@ -39,15 +39,16 @@ type Integration struct {
 }
 
 type IntegrationSpec struct {
- Replicas *int32     `json:"replicas,omitempty"`
- Source   SourceSpec `json:"source,omitempty"`
- Context  string     `json:"context,omitempty"`
+ Replicas     *int32     `json:"replicas,omitempty"`
+ Source       SourceSpec `json:"source,omitempty"`
+ Context      string     `json:"context,omitempty"`
+ Dependencies []string   `json:"dependencies,omitempty"`
 }
 
 type SourceSpec struct {
- Name     *string `json:"name,omitempty"`
- Content  *string `json:"content,omitempty"`
- Language *string `json:"language,omitempty"`
+ Name     string `json:"name,omitempty"`
+ Content  string `json:"content,omitempty"`
+ Language string `json:"language,omitempty"`
 }
 
 type IntegrationStatus struct {
diff --git a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
index 2e4d8d2..826918a 100644
--- a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
@@ -218,7 +218,12 @@ func (in *IntegrationSpec) DeepCopyInto(out *IntegrationSpec) {
  *out = new(int32)
  **out = **in
  }
- in.Source.DeepCopyInto(&out.Source)
+ out.Source = in.Source
+ if in.Dependencies != nil {
+ in, out := &in.Dependencies, &out.Dependencies
+ *out = make([]string, len(*in))
+ copy(*out, *in)
+ }
  return
 }
 
@@ -267,21 +272,6 @@ func (in *PropertySpec) DeepCopy() *PropertySpec {
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *SourceSpec) DeepCopyInto(out *SourceSpec) {
  *out = *in
- if in.Name != nil {
- in, out := &in.Name, &out.Name
- *out = new(string)
- **out = **in
- }
- if in.Content != nil {
- in, out := &in.Content, &out.Content
- *out = new(string)
- **out = **in
- }
- if in.Language != nil {
- in, out := &in.Language, &out.Language
- *out = new(string)
- **out = **in
- }
  return
 }
 
diff --git a/pkg/build/api/types.go b/pkg/build/api/types.go
index 5fc1395..5eba444 100644
--- a/pkg/build/api/types.go
+++ b/pkg/build/api/types.go
@@ -19,8 +19,9 @@ package api
 
 // a request to build a specific code
 type BuildSource struct {
- Identifier BuildIdentifier
- Code       Code
+ Identifier   BuildIdentifier
+ Code         Code
+ Dependencies []string
 }
 
 type BuildIdentifier struct {
diff --git a/pkg/build/local/local_builder.go b/pkg/build/local/local_builder.go
index f1ed76a..df96879 100644
--- a/pkg/build/local/local_builder.go
+++ b/pkg/build/local/local_builder.go
@@ -20,7 +20,9 @@ package local
 import (
  "context"
  "encoding/xml"
+ "fmt"
  "io/ioutil"
+ "strings"
  "time"
 
  buildv1 "github.com/openshift/api/build/v1"
@@ -106,41 +108,15 @@ func (b *localBuilder) buildCycle(ctx context.Context) {
 }
 
 func (b *localBuilder) execute(source build.BuildSource) (string, error) {
-
- project := maven.ProjectDefinition{
- Project: maven.Project{
- XMLName:           xml.Name{Local: "project"},
- XmlNs:             "http://maven.apache.org/POM/4.0.0",
- XmlNsXsi:          "http://www.w3.org/2001/XMLSchema-instance",
- XsiSchemaLocation: "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd",
- ModelVersion:      "4.0.0",
- GroupId:           "org.apache.camel.k.integration",
- ArtifactId:        "camel-k-integration",
- Version:           "1.0.0",
- Dependencies: maven.Dependencies{
- Dependencies: []maven.Dependency{
- {
- GroupId:    "org.apache.camel.k",
- ArtifactId: "camel-k-runtime-jvm",
- Version:    version.Version,
- },
- },
- },
- },
- Resources: map[string]string{
- source.Code.Name: source.Code.Content,
- },
- Env: map[string]string{
- "JAVA_MAIN_CLASS":         "org.apache.camel.k.jvm.Application",
- "CAMEL_K_ROUTES_URI":      "classpath:" + source.Code.Name,
- "CAMEL_K_ROUTES_LANGUAGE": source.Code.Language,
- },
+ project, err := generateProjectDefinition(source)
+ if err != nil {
+ return "", err
  }
-
  tarFileName, err := maven.Build(project)
  if err != nil {
  return "", err
  }
+
  logrus.Info("Created tar file ", tarFileName)
 
  image, err := b.publish(tarFileName, source)
@@ -274,3 +250,79 @@ func (b *localBuilder) publish(tarFile string, source build.BuildSource) (string
  }
  return is.Status.DockerImageRepository + ":" + source.Identifier.Digest, nil
 }
+
+func generateProjectDefinition(source build.BuildSource) (maven.ProjectDefinition, error) {
+ project := maven.ProjectDefinition{
+ Project: maven.Project{
+ XMLName:           xml.Name{Local: "project"},
+ XmlNs:             "http://maven.apache.org/POM/4.0.0",
+ XmlNsXsi:          "http://www.w3.org/2001/XMLSchema-instance",
+ XsiSchemaLocation: "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd",
+ ModelVersion:      "4.0.0",
+ GroupId:           "org.apache.camel.k.integration",
+ ArtifactId:        "camel-k-integration",
+ Version:           version.Version,
+ DependencyManagement: maven.DependencyManagement{
+ Dependencies: maven.Dependencies{
+ Dependencies: []maven.Dependency{
+ {
+ //TODO: camel version should be retrieved from an external source or provided as static version
+ GroupId:    "org.apache.camel",
+ ArtifactId: "camel-bom",
+ Version:    "2.22.1",
+ Type:       "pom",
+ Scope:      "import",
+ },
+ },
+ },
+ },
+ Dependencies: maven.Dependencies{
+ Dependencies: make([]maven.Dependency, 0),
+ },
+ },
+ Resources: map[string]string{
+ source.Code.Name: source.Code.Content,
+ },
+ Env: make(map[string]string),
+ }
+
+ //
+ // set-up dependencies
+ //
+
+ deps := &project.Project.Dependencies
+ deps.AddGAV("org.apache.camel.k", "camel-k-runtime-jvm", version.Version)
+
+ for _, d := range source.Dependencies {
+ if strings.HasPrefix(d, "camel:") {
+ artifactId := strings.TrimPrefix(d, "camel:")
+
+ if !strings.HasPrefix(artifactId, "camel-") {
+ artifactId = "camel-" + artifactId
+ }
+
+ deps.AddGAV("org.apache.camel", artifactId, "")
+ } else if strings.HasPrefix(d, "mvn:") {
+ mid := strings.TrimPrefix(d, "mvn:")
+ gav := strings.Replace(mid, "/", ":", -1)
+
+ deps.AddEncodedGAV(gav)
+ } else {
+ return maven.ProjectDefinition{}, fmt.Errorf("unknown dependency type: %s", d)
+ }
+ }
+
+ //
+ // set-up env
+ //
+
+ project.Env["JAVA_MAIN_CLASS"] = "org.apache.camel.k.jvm.Application"
+ project.Env["CAMEL_K_ROUTES_URI"] = "classpath:" + source.Code.Name
+
+ // Don't set the language if not set
+ if source.Code.Language != "" {
+ project.Env["CAMEL_K_ROUTES_LANGUAGE"] = source.Code.Language
+ }
+
+ return project, nil
+}
diff --git a/pkg/build/local/local_builder_test.go b/pkg/build/local/local_builder_test.go
new file mode 100644
index 0000000..49decab
--- /dev/null
+++ b/pkg/build/local/local_builder_test.go
@@ -0,0 +1,80 @@
+/*
+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 local
+
+import (
+ "testing"
+
+ "github.com/apache/camel-k/pkg/build/api"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestProjectGeneration(t *testing.T) {
+ source := api.BuildSource{
+ Identifier: api.BuildIdentifier{
+ Name:   "my-integration",
+ Digest: "",
+ },
+ Code: api.Code{
+ Name:     "my-code.js",
+ Content:  `from("timer:start").to("log:end")`,
+ Language: "",
+ },
+ Dependencies: []string{
+ "camel:mail",
+ "camel:camel-netty4",
+ "mvn:org.apache.camel/camel-servicenow/2.21.1",
+ "mvn:org.apache.camel/camel-salesforce",
+ },
+ }
+
+ prj, err := generateProjectDefinition(source)
+ assert.Nil(t, err)
+ assert.NotNil(t, prj)
+ assert.Equal(t, len(prj.Project.Dependencies.Dependencies), 5)
+ assert.Equal(t, prj.Project.Dependencies.Dependencies[0].ArtifactId, "camel-k-runtime-jvm")
+ assert.Equal(t, prj.Project.Dependencies.Dependencies[1].ArtifactId, "camel-mail")
+ assert.Equal(t, prj.Project.Dependencies.Dependencies[2].ArtifactId, "camel-netty4")
+ assert.Equal(t, prj.Project.Dependencies.Dependencies[3].ArtifactId, "camel-servicenow")
+ assert.Equal(t, prj.Project.Dependencies.Dependencies[3].Version, "2.21.1")
+ assert.Equal(t, prj.Project.Dependencies.Dependencies[4].ArtifactId, "camel-salesforce")
+ assert.Equal(t, prj.Project.Dependencies.Dependencies[4].Version, "")
+}
+
+func TestProjectGenerationWithFailure(t *testing.T) {
+ source := api.BuildSource{
+ Identifier: api.BuildIdentifier{
+ Name:   "my-integration",
+ Digest: "",
+ },
+ Code: api.Code{
+ Name:     "my-code.js",
+ Content:  `from("timer:start").to("log:end")`,
+ Language: "",
+ },
+ Dependencies: []string{
+ "other:mail",
+ "camel:camel-netty4",
+ "mvn:org.apache.camel/camel-servicenow/2.21.1",
+ "mvn:org.apache.camel/camel-salesforce",
+ },
+ }
+
+ _, err := generateProjectDefinition(source)
+ assert.NotNil(t, err)
+}
diff --git a/pkg/client/cmd/run.go b/pkg/client/cmd/run.go
index aacb05c..d64a653 100644
--- a/pkg/client/cmd/run.go
+++ b/pkg/client/cmd/run.go
@@ -37,12 +37,14 @@ type RunCmdOptions struct {
  *RootCmdOptions
  Language        string
  IntegrationName string
+ Dependencies    []string
 }
 
 func NewCmdRun(rootCmdOptions *RootCmdOptions) *cobra.Command {
  options := RunCmdOptions{
  RootCmdOptions: rootCmdOptions,
  }
+
  cmd := cobra.Command{
  Use:   "run [file to run]",
  Short: "Run a integration on Kubernetes",
@@ -53,7 +55,7 @@ func NewCmdRun(rootCmdOptions *RootCmdOptions) *cobra.Command {
 
  cmd.Flags().StringVarP(&options.Language, "language", "l", "", "Programming Language used to write the file")
  cmd.Flags().StringVarP(&options.IntegrationName, "name", "", "", "The integration name")
- cmd.ParseFlags(os.Args)
+ cmd.Flags().StringSliceVarP(&options.Dependencies, "dependency", "d", nil, "The integration dependency")
 
  return &cmd
 }
@@ -107,10 +109,11 @@ func (o *RunCmdOptions) run(cmd *cobra.Command, args []string) error {
  },
  Spec: v1alpha1.IntegrationSpec{
  Source: v1alpha1.SourceSpec{
- Name:     &codeName,
- Content:  &code,
- Language: &o.Language,
+ Name:     codeName,
+ Content:  code,
+ Language: o.Language,
  },
+ Dependencies: o.Dependencies,
  },
  }
 
diff --git a/pkg/stub/action/integration/build.go b/pkg/stub/action/integration/build.go
index 22f006a..373583a 100644
--- a/pkg/stub/action/integration/build.go
+++ b/pkg/stub/action/integration/build.go
@@ -55,10 +55,11 @@ func (b *BuildAction) Handle(integration *v1alpha1.Integration) error {
  b.buildManager.Start(api.BuildSource{
  Identifier: buildIdentifier,
  Code: api.Code{
- Name:     *integration.Spec.Source.Name,
- Content:  *integration.Spec.Source.Content,
- Language: *integration.Spec.Source.Language,
- }, // FIXME possible panic
+ Name:     integration.Spec.Source.Name,
+ Content:  integration.Spec.Source.Content,
+ Language: integration.Spec.Source.Language,
+ },
+ Dependencies: integration.Spec.Dependencies,
  })
  logrus.Info("Build started")
  } else if buildResult.Status == api.BuildStatusError {
diff --git a/pkg/util/digest/digest.go b/pkg/util/digest/digest.go
index 09bec1c..6f84744 100644
--- a/pkg/util/digest/digest.go
+++ b/pkg/util/digest/digest.go
@@ -34,8 +34,8 @@ func Compute(integration *v1alpha1.Integration) string {
  // Operator version is relevant
  hash.Write([]byte(version.Version))
  // Integration relevant fields
- if integration.Spec.Source.Content != nil {
- hash.Write([]byte(*integration.Spec.Source.Content))
+ if integration.Spec.Source.Content != "" {
+ hash.Write([]byte(integration.Spec.Source.Content))
  }
  // Add a letter at the beginning and use URL safe encoding
  return "v" + base64.RawURLEncoding.EncodeToString(hash.Sum(nil))
diff --git a/pkg/util/maven/maven.go b/pkg/util/maven/maven.go
index f474f58..6a0362e 100644
--- a/pkg/util/maven/maven.go
+++ b/pkg/util/maven/maven.go
@@ -168,7 +168,7 @@ func appendToTar(filePath string, tarPath string, writer *tar.Writer) error {
 }
 
 func createMavenStructure(buildDir string, project ProjectDefinition) error {
- pom, err := pomFileContent(project.Project)
+ pom, err := GeneratePomFileContent(project.Project)
  if err != nil {
  return err
  }
@@ -234,7 +234,7 @@ func envFileContent(env map[string]string) string {
  return content
 }
 
-func pomFileContent(project Project) (string, error) {
+func GeneratePomFileContent(project Project) (string, error) {
  w := &bytes.Buffer{}
  w.WriteString(xml.Header)
 
diff --git a/pkg/util/maven/mavent_test.go b/pkg/util/maven/mavent_test.go
index 3092e4a..a22ab3f 100644
--- a/pkg/util/maven/mavent_test.go
+++ b/pkg/util/maven/mavent_test.go
@@ -30,6 +30,17 @@ const expectedPom = `<?xml version="1.0" encoding="UTF-8"?>
   <groupId>org.apache.camel.k.integration</groupId>
   <artifactId>camel-k-integration</artifactId>
   <version>1.0.0</version>
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>org.apache.camel</groupId>
+        <artifactId>camel-bom</artifactId>
+        <version>2.22.1</version>
+        <type>pom</type>
+        <scope>import</scope>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
   <dependencies>
     <dependency>
       <groupId>org.apache.camel.k</groupId>
@@ -49,6 +60,19 @@ func TestPomGeneration(t *testing.T) {
  GroupId:           "org.apache.camel.k.integration",
  ArtifactId:        "camel-k-integration",
  Version:           "1.0.0",
+ DependencyManagement: DependencyManagement{
+ Dependencies: Dependencies{
+ Dependencies: []Dependency{
+ {
+ GroupId:    "org.apache.camel",
+ ArtifactId: "camel-bom",
+ Version:    "2.22.1",
+ Type:       "pom",
+ Scope:      "import",
+ },
+ },
+ },
+ },
  Dependencies: Dependencies{
  Dependencies: []Dependency{
  {
diff --git a/pkg/util/maven/types.go b/pkg/util/maven/types.go
index 1ebebe0..30a80de 100644
--- a/pkg/util/maven/types.go
+++ b/pkg/util/maven/types.go
@@ -29,27 +29,48 @@ type ProjectDefinition struct {
 }
 
 type Project struct {
- XMLName           xml.Name
- XmlNs             string       `xml:"xmlns,attr"`
- XmlNsXsi          string       `xml:"xmlns:xsi,attr"`
- XsiSchemaLocation string       `xml:"xsi:schemaLocation,attr"`
- ModelVersion      string       `xml:"modelVersion"`
- GroupId           string       `xml:"groupId"`
- ArtifactId        string       `xml:"artifactId"`
- Version           string       `xml:"version"`
- Dependencies      Dependencies `xml:"dependencies"`
+ XMLName              xml.Name
+ XmlNs                string               `xml:"xmlns,attr"`
+ XmlNsXsi             string               `xml:"xmlns:xsi,attr"`
+ XsiSchemaLocation    string               `xml:"xsi:schemaLocation,attr"`
+ ModelVersion         string               `xml:"modelVersion"`
+ GroupId              string               `xml:"groupId"`
+ ArtifactId           string               `xml:"artifactId"`
+ Version              string               `xml:"version"`
+ DependencyManagement DependencyManagement `xml:"dependencyManagement"`
+ Dependencies         Dependencies         `xml:"dependencies"`
+}
+
+type DependencyManagement struct {
+ Dependencies Dependencies `xml:"dependencies"`
 }
 
 type Dependencies struct {
  Dependencies []Dependency `xml:"dependency"`
 }
 
+func (deps *Dependencies) Add(dep Dependency) {
+ deps.Dependencies = append(deps.Dependencies, dep)
+}
+
+func (deps *Dependencies) AddGAV(groupId string, artifactId string, version string) {
+ deps.Add(NewDependency(groupId, artifactId, version))
+}
+
+func (deps *Dependencies) AddEncodedGAV(gav string) {
+ if d, err := ParseGAV(gav); err == nil {
+ // TODO: error handling
+ deps.Add(d)
+ }
+}
+
 type Dependency struct {
  GroupId    string `xml:"groupId"`
  ArtifactId string `xml:"artifactId"`
  Version    string `xml:"version,omitempty"`
  Type       string `xml:"type,omitempty"`
  Classifier string `xml:"classifier,omitempty"`
+ Scope      string `xml:"scope,omitempty"`
 }
 
 func NewDependency(groupId string, artifactId string, version string) Dependency {
diff --git a/runtime/examples/dns.js b/runtime/examples/dns.js
new file mode 100644
index 0000000..337682d
--- /dev/null
+++ b/runtime/examples/dns.js
@@ -0,0 +1,12 @@
+//
+// To run this integrations use:
+//
+//     kamel run -d camel:dns runtime/examples/dns.js
+//
+
+from('timer:dns?period=1s')
+    .routeId('dns')
+    .setHeader('dns.domain')
+        .constant('www.google.com')
+    .to('dns:ip')
+    .to('log:dns')
\ No newline at end of file