camel-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nferr...@apache.org
Subject [camel-k] 01/02: Allow buildless direct deploy #31
Date Thu, 13 Sep 2018 11:05:50 GMT
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 aa45c719c84053ce702fb9e8b304129b7bae5914
Author: lburgazzoli <lburgazzoli@gmail.com>
AuthorDate: Wed Sep 12 19:04:09 2018 +0200

    Allow buildless direct deploy #31
---
 deploy/resources.go                                |   5 +
 pkg/apis/camel/v1alpha1/register.go                |   2 +
 pkg/apis/camel/v1alpha1/types.go                   |  13 ++-
 pkg/apis/camel/v1alpha1/types_support.go           |  66 ++++++++++++
 pkg/build/api/types.go                             |   4 +-
 pkg/build/build_manager.go                         |  34 +++---
 pkg/build/build_manager_integration_test.go        |   4 +-
 pkg/build/local/local_builder.go                   |   4 +-
 pkg/build/local/local_builder_integration_test.go  |  16 +--
 pkg/build/local/local_builder_test.go              |   8 +-
 pkg/client/cmd/context.go                          |   3 +-
 pkg/client/cmd/context_create.go                   | 120 +++++++++++++++++++++
 .../cmd/{context_get.go => context_delete.go}      |  49 ++++-----
 pkg/client/cmd/context_edit.go                     | 101 -----------------
 pkg/client/cmd/context_get.go                      |  15 +--
 pkg/client/cmd/run.go                              |  14 +--
 pkg/stub/action/context/build.go                   |  51 +++++++--
 pkg/stub/action/context/{edit.go => initialize.go} |  27 ++---
 pkg/stub/action/context/monitor.go                 |  32 +++---
 pkg/stub/action/context/save.go                    |  46 --------
 pkg/stub/action/integration/build.go               |  28 ++++-
 pkg/stub/action/integration/initialize.go          |   2 +-
 pkg/stub/action/integration/monitor.go             |   2 +-
 pkg/stub/handler.go                                |   6 +-
 pkg/util/digest/digest.go                          |  35 +++++-
 25 files changed, 405 insertions(+), 282 deletions(-)

diff --git a/deploy/resources.go b/deploy/resources.go
index 96995ce..33d1443 100644
--- a/deploy/resources.go
+++ b/deploy/resources.go
@@ -372,6 +372,9 @@ spec:
       containers:
         - name: camel-k-operator
           image: docker.io/apache/camel-k:0.0.1-SNAPSHOT
+          ports:
+          - containerPort: 60000
+            name: metrics
           command:
           - camel-k-operator
           imagePullPolicy: Always
@@ -380,6 +383,8 @@ spec:
               valueFrom:
                 fieldRef:
                   fieldPath: metadata.namespace
+            - name: OPERATOR_NAME
+              value: "camel-k-operator"
 
 `
 	Resources["user-cluster-role.yaml"] =
diff --git a/pkg/apis/camel/v1alpha1/register.go b/pkg/apis/camel/v1alpha1/register.go
index dbbdfd7..52af408 100644
--- a/pkg/apis/camel/v1alpha1/register.go
+++ b/pkg/apis/camel/v1alpha1/register.go
@@ -46,6 +46,8 @@ func addKnownTypes(scheme *runtime.Scheme) error {
 	scheme.AddKnownTypes(SchemeGroupVersion,
 		&Integration{},
 		&IntegrationList{},
+		&IntegrationContext{},
+		&IntegrationContextList{},
 	)
 	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
 	return nil
diff --git a/pkg/apis/camel/v1alpha1/types.go b/pkg/apis/camel/v1alpha1/types.go
index c40b6b1..72da35a 100644
--- a/pkg/apis/camel/v1alpha1/types.go
+++ b/pkg/apis/camel/v1alpha1/types.go
@@ -93,6 +93,7 @@ type PropertySpec struct {
 	Name  string
 	Value string
 }
+
 type EnvironmentSpec struct {
 	Name  string
 	Value string
@@ -100,18 +101,22 @@ type EnvironmentSpec struct {
 
 type IntegrationContextStatus struct {
 	Phase  IntegrationContextPhase `json:"phase,omitempty"`
-	Digest string                  `json:"digest,omitempty"`
 	Image  string                  `json:"image,omitempty"`
-	From   int                     `json:"from,omitempty"`
+	Digest string                  `json:"digest,omitempty"`
 }
 
 type IntegrationContextPhase string
 
 const (
-	// IntegrationContextPhaseDraft --
-	IntegrationContextPhaseDraft IntegrationContextPhase = "Draft"
+	// IntegrationContextKind --
+	IntegrationContextKind string = "IntegrationContext"
+
 	// IntegrationContextPhaseBuilding --
 	IntegrationContextPhaseBuilding IntegrationContextPhase = "Building"
+	// IntegrationContextPhaseDeploying --
+	IntegrationContextPhaseDeploying IntegrationContextPhase = "Deploying"
 	// IntegrationContextPhaseReady --
 	IntegrationContextPhaseReady IntegrationContextPhase = "Ready"
+	// IntegrationContextPhaseError --
+	IntegrationContextPhaseError IntegrationContextPhase = "Error"
 )
diff --git a/pkg/apis/camel/v1alpha1/types_support.go b/pkg/apis/camel/v1alpha1/types_support.go
new file mode 100644
index 0000000..5168405
--- /dev/null
+++ b/pkg/apis/camel/v1alpha1/types_support.go
@@ -0,0 +1,66 @@
+/*
+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 v1alpha1
+
+import (
+	"fmt"
+
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+// **********************************
+//
+// Methods
+//
+// **********************************
+
+func (spec PropertySpec) String() string {
+	return fmt.Sprint("%s=%s", spec.Name, spec.Value)
+}
+
+func (spec EnvironmentSpec) String() string {
+	return fmt.Sprint("%s=%s", spec.Name, spec.Value)
+}
+
+// **********************************
+//
+// Helpers
+//
+// **********************************
+
+func NewIntegrationContext(namespace string, name string) IntegrationContext {
+	return IntegrationContext{
+		TypeMeta: metav1.TypeMeta{
+			APIVersion: SchemeGroupVersion.String(),
+			Kind:       IntegrationContextKind,
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: namespace,
+			Name:      name,
+		},
+	}
+}
+
+func NewIntegrationContextList() IntegrationContextList {
+	return IntegrationContextList{
+		TypeMeta: metav1.TypeMeta{
+			APIVersion: SchemeGroupVersion.String(),
+			Kind:       IntegrationContextKind,
+		},
+	}
+}
diff --git a/pkg/build/api/types.go b/pkg/build/api/types.go
index 5eba444..b6c178e 100644
--- a/pkg/build/api/types.go
+++ b/pkg/build/api/types.go
@@ -25,8 +25,8 @@ type BuildSource struct {
 }
 
 type BuildIdentifier struct {
-	Name   string
-	Digest string
+	Name      string
+	Qualifier string
 }
 
 type Code struct {
diff --git a/pkg/build/build_manager.go b/pkg/build/build_manager.go
index 7006053..49f04f1 100644
--- a/pkg/build/build_manager.go
+++ b/pkg/build/build_manager.go
@@ -19,50 +19,40 @@ package build
 
 import (
 	"context"
+	"sync"
+
 	"github.com/apache/camel-k/pkg/build/api"
 	"github.com/apache/camel-k/pkg/build/local"
-	"sync"
 )
 
 // main facade to the image build system
-type BuildManager struct {
-	builds  map[api.BuildIdentifier]*api.BuildResult
-	mutex   sync.Mutex
+type Manager struct {
+	builds  sync.Map
 	builder api.Builder
 }
 
-func NewBuildManager(ctx context.Context, namespace string) *BuildManager {
-	return &BuildManager{
-		builds:  make(map[api.BuildIdentifier]*api.BuildResult),
+func NewManager(ctx context.Context, namespace string) *Manager {
+	return &Manager{
 		builder: local.NewLocalBuilder(ctx, namespace),
 	}
 }
 
-func (m *BuildManager) Get(identifier api.BuildIdentifier) api.BuildResult {
-	m.mutex.Lock()
-	defer m.mutex.Unlock()
-
-	if info, present := m.builds[identifier]; !present || info == nil {
+func (m *Manager) Get(identifier api.BuildIdentifier) api.BuildResult {
+	if info, present := m.builds.Load(identifier); !present || info == nil {
 		return noBuildInfo()
 	} else {
-		return *info
+		return *info.(*api.BuildResult)
 	}
 }
 
-func (m *BuildManager) Start(source api.BuildSource) {
-	m.mutex.Lock()
-	defer m.mutex.Unlock()
-
+func (m *Manager) Start(source api.BuildSource) {
 	initialBuildInfo := initialBuildInfo(&source)
-	m.builds[source.Identifier] = &initialBuildInfo
+	m.builds.Store(source.Identifier, &initialBuildInfo)
 
 	resChannel := m.builder.Build(source)
 	go func() {
 		res := <-resChannel
-		m.mutex.Lock()
-		defer m.mutex.Unlock()
-
-		m.builds[res.Source.Identifier] = &res
+		m.builds.Store(res.Source.Identifier, &res)
 	}()
 }
 
diff --git a/pkg/build/build_manager_integration_test.go b/pkg/build/build_manager_integration_test.go
index 11deca7..e271721 100644
--- a/pkg/build/build_manager_integration_test.go
+++ b/pkg/build/build_manager_integration_test.go
@@ -32,7 +32,7 @@ import (
 
 func TestBuild(t *testing.T) {
 	ctx := context.TODO()
-	buildManager := NewBuildManager(ctx, test.GetTargetNamespace())
+	buildManager := NewManager(ctx, test.GetTargetNamespace())
 	identifier := build.BuildIdentifier{
 		Name:   "man-test",
 		Digest: digest.Random(),
@@ -62,7 +62,7 @@ func TestBuild(t *testing.T) {
 func TestFailedBuild(t *testing.T) {
 
 	ctx := context.TODO()
-	buildManager := NewBuildManager(ctx, test.GetTargetNamespace())
+	buildManager := NewManager(ctx, test.GetTargetNamespace())
 	identifier := build.BuildIdentifier{
 		Name:   "man-test-2",
 		Digest: digest.Random(),
diff --git a/pkg/build/local/local_builder.go b/pkg/build/local/local_builder.go
index cd5b7b0..127657d 100644
--- a/pkg/build/local/local_builder.go
+++ b/pkg/build/local/local_builder.go
@@ -154,7 +154,7 @@ func (b *localBuilder) publish(tarFile string, source build.BuildSource)
(string
 				Output: buildv1.BuildOutput{
 					To: &v1.ObjectReference{
 						Kind: "ImageStreamTag",
-						Name: "camel-k-" + source.Identifier.Name + ":" + source.Identifier.Digest,
+						Name: "camel-k-" + source.Identifier.Name + ":" + source.Identifier.Qualifier,
 					},
 				},
 			},
@@ -248,7 +248,7 @@ func (b *localBuilder) publish(tarFile string, source build.BuildSource)
(string
 	if is.Status.DockerImageRepository == "" {
 		return "", errors.New("dockerImageRepository not available in ImageStream")
 	}
-	return is.Status.DockerImageRepository + ":" + source.Identifier.Digest, nil
+	return is.Status.DockerImageRepository + ":" + source.Identifier.Qualifier, nil
 }
 
 func generateProjectDefinition(source build.BuildSource) (maven.ProjectDefinition, error)
{
diff --git a/pkg/build/local/local_builder_integration_test.go b/pkg/build/local/local_builder_integration_test.go
index 8c4f4a4..967a0ad 100644
--- a/pkg/build/local/local_builder_integration_test.go
+++ b/pkg/build/local/local_builder_integration_test.go
@@ -36,8 +36,8 @@ func TestBuild(t *testing.T) {
 
 	execution := builder.Build(build.BuildSource{
 		Identifier: build.BuildIdentifier{
-			Name:   "test0",
-			Digest: digest.Random(),
+			Name:      "test0",
+			Qualifier: digest.Random(),
 		},
 		Code: build.Code{
 			Content: code(),
@@ -56,8 +56,8 @@ func TestDoubleBuild(t *testing.T) {
 
 	execution1 := builder.Build(build.BuildSource{
 		Identifier: build.BuildIdentifier{
-			Name:   "test1",
-			Digest: digest.Random(),
+			Name:      "test1",
+			Qualifier: digest.Random(),
 		},
 		Code: build.Code{
 			Content: code(),
@@ -66,8 +66,8 @@ func TestDoubleBuild(t *testing.T) {
 
 	execution2 := builder.Build(build.BuildSource{
 		Identifier: build.BuildIdentifier{
-			Name:   "test2",
-			Digest: digest.Random(),
+			Name:      "test2",
+			Qualifier: digest.Random(),
 		},
 		Code: build.Code{
 			Content: code(),
@@ -88,8 +88,8 @@ func TestFailedBuild(t *testing.T) {
 
 	execution := builder.Build(build.BuildSource{
 		Identifier: build.BuildIdentifier{
-			Name:   "test3",
-			Digest: digest.Random(),
+			Name:      "test3",
+			Qualifier: digest.Random(),
 		},
 		Code: build.Code{
 			Content: code() + "-",
diff --git a/pkg/build/local/local_builder_test.go b/pkg/build/local/local_builder_test.go
index 49decab..b88567e 100644
--- a/pkg/build/local/local_builder_test.go
+++ b/pkg/build/local/local_builder_test.go
@@ -27,8 +27,8 @@ import (
 func TestProjectGeneration(t *testing.T) {
 	source := api.BuildSource{
 		Identifier: api.BuildIdentifier{
-			Name:   "my-integration",
-			Digest: "",
+			Name:      "my-integration",
+			Qualifier: "",
 		},
 		Code: api.Code{
 			Name:     "my-code.js",
@@ -59,8 +59,8 @@ func TestProjectGeneration(t *testing.T) {
 func TestProjectGenerationWithFailure(t *testing.T) {
 	source := api.BuildSource{
 		Identifier: api.BuildIdentifier{
-			Name:   "my-integration",
-			Digest: "",
+			Name:      "my-integration",
+			Qualifier: "",
 		},
 		Code: api.Code{
 			Name:     "my-code.js",
diff --git a/pkg/client/cmd/context.go b/pkg/client/cmd/context.go
index 6f1e502..949dab0 100644
--- a/pkg/client/cmd/context.go
+++ b/pkg/client/cmd/context.go
@@ -29,7 +29,8 @@ func NewCmdContext(rootCmdOptions *RootCmdOptions) *cobra.Command {
 		Long:  `Configure an Integration Context.`,
 	}
 
-	cmd.AddCommand(newContextEditCmd(rootCmdOptions))
+	cmd.AddCommand(newContextCreateCmd(rootCmdOptions))
+	cmd.AddCommand(newContextDeleteCmd(rootCmdOptions))
 	cmd.AddCommand(newContextGetCmd(rootCmdOptions))
 
 	return &cmd
diff --git a/pkg/client/cmd/context_create.go b/pkg/client/cmd/context_create.go
new file mode 100644
index 0000000..de2c1a5
--- /dev/null
+++ b/pkg/client/cmd/context_create.go
@@ -0,0 +1,120 @@
+/*
+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 cmd
+
+import (
+	"errors"
+	"fmt"
+	"strconv"
+	"strings"
+
+	"github.com/operator-framework/operator-sdk/pkg/sdk"
+
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/apache/camel-k/pkg/util/kubernetes"
+
+	"github.com/spf13/cobra"
+	k8serrors "k8s.io/apimachinery/pkg/api/errors"
+)
+
+// NewCmdContext --
+func newContextCreateCmd(rootCmdOptions *RootCmdOptions) *cobra.Command {
+	impl := &contextCreateCommand{
+		RootCmdOptions: rootCmdOptions,
+	}
+
+	cmd := cobra.Command{
+		Use:   "create",
+		Short: "Create an Integration Context",
+		Long:  `Create an Integration Context.`,
+		Args:  impl.validateArgs,
+		RunE:  impl.run,
+	}
+
+	cmd.Flags().StringSliceVarP(&impl.env, "env", "e", nil, "Add an environment variable")
+	cmd.Flags().StringSliceVarP(&impl.properties, "property", "p", nil, "Add a system property")
+	cmd.Flags().StringSliceVarP(&impl.dependencies, "dependency", "d", nil, "Add a dependency")
+
+	return &cmd
+}
+
+type contextCreateCommand struct {
+	*RootCmdOptions
+
+	env          []string
+	properties   []string
+	dependencies []string
+}
+
+func (command *contextCreateCommand) validateArgs(cmd *cobra.Command, args []string) error
{
+	if len(args) != 1 {
+		return errors.New("accepts 1 arg, received " + strconv.Itoa(len(args)))
+	}
+
+	return nil
+}
+
+func (command *contextCreateCommand) run(cmd *cobra.Command, args []string) error {
+	namespace := command.Namespace
+	name := kubernetes.SanitizeName(args[0])
+
+	ctx := v1alpha1.NewIntegrationContext(namespace, name)
+	ctx.Spec = v1alpha1.IntegrationContextSpec{
+		Dependencies: command.dependencies,
+		Environment:  make([]v1alpha1.EnvironmentSpec, 0),
+		Properties:   make([]v1alpha1.PropertySpec, 0),
+	}
+
+	for _, item := range command.env {
+		pair := strings.Split(item, "=")
+		if len(pair) == 2 {
+			ctx.Spec.Environment = append(ctx.Spec.Environment, v1alpha1.EnvironmentSpec{Name: pair[0],
Value: pair[1]})
+		}
+	}
+	for _, item := range command.properties {
+		pair := strings.Split(item, "=")
+		if len(pair) == 2 {
+			ctx.Spec.Environment = append(ctx.Spec.Environment, v1alpha1.EnvironmentSpec{Name: pair[0],
Value: pair[1]})
+		}
+	}
+
+	existed := false
+	err := sdk.Create(&ctx)
+	if err != nil && k8serrors.IsAlreadyExists(err) {
+		existed = true
+		clone := ctx.DeepCopy()
+		err = sdk.Get(clone)
+		if err != nil {
+			return err
+		}
+		ctx.ResourceVersion = clone.ResourceVersion
+		err = sdk.Update(&ctx)
+	}
+
+	if err != nil {
+		return err
+	}
+
+	if !existed {
+		fmt.Printf("integration context \"%s\" created\n", name)
+	} else {
+		fmt.Printf("integration context \"%s\" updated\n", name)
+	}
+
+	return nil
+}
diff --git a/pkg/client/cmd/context_get.go b/pkg/client/cmd/context_delete.go
similarity index 53%
copy from pkg/client/cmd/context_get.go
copy to pkg/client/cmd/context_delete.go
index 36d16c1..c4cb893 100644
--- a/pkg/client/cmd/context_get.go
+++ b/pkg/client/cmd/context_delete.go
@@ -18,57 +18,54 @@ limitations under the License.
 package cmd
 
 import (
+	"errors"
 	"fmt"
-	"os"
-	"text/tabwriter"
+	"strconv"
 
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/apache/camel-k/pkg/util/kubernetes"
 	"github.com/operator-framework/operator-sdk/pkg/sdk"
 	"github.com/spf13/cobra"
-
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
-func newContextGetCmd(rootCmdOptions *RootCmdOptions) *cobra.Command {
-	options := contextGetCommand{
+func newContextDeleteCmd(rootCmdOptions *RootCmdOptions) *cobra.Command {
+	impl := contextDeleteCommand{
 		RootCmdOptions: rootCmdOptions,
 	}
 
 	cmd := cobra.Command{
-		Use:   "get",
-		Short: "Get defined Integration Context",
-		Long:  `Get defined Integration Context.`,
-		RunE:  options.run,
+		Use:   "delete",
+		Short: "Delete an Integration Context",
+		Long:  `Delete anIntegration Context.`,
+		Args:  impl.validateArgs,
+		RunE:  impl.run,
 	}
 
 	return &cmd
 }
 
-type contextGetCommand struct {
+type contextDeleteCommand struct {
 	*RootCmdOptions
 }
 
-func (command *contextGetCommand) run(cmd *cobra.Command, args []string) error {
-	ctxList := v1alpha1.IntegrationContextList{
-		TypeMeta: metav1.TypeMeta{
-			APIVersion: v1alpha1.SchemeGroupVersion.String(),
-			Kind:       "IntegrationContext",
-		},
+func (command *contextDeleteCommand) validateArgs(cmd *cobra.Command, args []string) error
{
+	if len(args) != 1 {
+		return errors.New("accepts 1 arg, received " + strconv.Itoa(len(args)))
 	}
 
-	namespace := command.Namespace
+	return nil
+}
 
-	err := sdk.List(namespace, &ctxList)
-	if err != nil {
+func (command *contextDeleteCommand) run(cmd *cobra.Command, args []string) error {
+	name := kubernetes.SanitizeName(args[0])
+	ctx := v1alpha1.NewIntegrationContext(command.Namespace, name)
+
+	if err := sdk.Delete(&ctx); err != nil {
+		fmt.Printf("error deleting integration context %s, %s", ctx.Name, err)
 		return err
 	}
 
-	w := tabwriter.NewWriter(os.Stdout, 0, 8, 0, '\t', 0)
-	fmt.Fprintln(w, "NAME\tSTATUS")
-	for _, ctx := range ctxList.Items {
-		fmt.Fprintf(w, "%s\t%s\n", ctx.Name, string(ctx.Status.Phase))
-	}
-	w.Flush()
+	fmt.Printf("integration context %s has been deleted", ctx.Name)
 
 	return nil
 }
diff --git a/pkg/client/cmd/context_edit.go b/pkg/client/cmd/context_edit.go
deleted file mode 100644
index 18879ed..0000000
--- a/pkg/client/cmd/context_edit.go
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
-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 cmd
-
-import (
-	"errors"
-	"log"
-	"strconv"
-
-	"github.com/spf13/cobra"
-)
-
-// NewCmdContext --
-func newContextEditCmd(rootCmdOptions *RootCmdOptions) *cobra.Command {
-	impl := &contextEditCommand{
-		RootCmdOptions: rootCmdOptions,
-		discard:        false,
-		save:           true,
-		dependencies: contextResource{
-			toAdd:    make([]string, 0),
-			toRemove: make([]string, 0),
-		},
-		env: contextResource{
-			toAdd:    make([]string, 0),
-			toRemove: make([]string, 0),
-		},
-		properties: contextResource{
-			toAdd:    make([]string, 0),
-			toRemove: make([]string, 0),
-		},
-	}
-
-	cmd := cobra.Command{
-		Use:   "edit",
-		Short: "Edit an Integration Context",
-		Long:  `Edit an Integration Context.`,
-		Args:  impl.validateArgs,
-		RunE:  impl.run,
-	}
-
-	cmd.Flags().BoolVarP(&impl.discard, "discard", "x", false, "Discard the draft")
-	cmd.Flags().BoolVarP(&impl.save, "save", "s", true, "Save the context")
-
-	cmd.Flags().StringSliceVarP(&impl.env.toAdd, "env", "e", nil, "Add an environment variable")
-	cmd.Flags().StringSliceVarP(&impl.env.toRemove, "env-rm", "E", nil, "Remove an environment
variable")
-	cmd.Flags().StringSliceVarP(&impl.properties.toAdd, "property", "p", nil, "Add a system
property")
-	cmd.Flags().StringSliceVarP(&impl.properties.toRemove, "property-rm", "P", nil, "Remove
a system property")
-	cmd.Flags().StringSliceVarP(&impl.dependencies.toAdd, "dependency", "d", nil, "Add a
dependency")
-	cmd.Flags().StringSliceVarP(&impl.dependencies.toRemove, "dependency-rm", "D", nil,
"Remove a dependency")
-
-	return &cmd
-}
-
-type contextResource struct {
-	toAdd    []string
-	toRemove []string
-}
-
-type contextEditCommand struct {
-	*RootCmdOptions
-
-	env          contextResource
-	properties   contextResource
-	dependencies contextResource
-
-	// rollback the context to the state before it was edited
-	discard bool
-
-	// save the context then the operator should rebuild the image, this is
-	// set as true by default, if you want to mark a context as a draft,
-	// set it to false
-	save bool
-}
-
-func (command *contextEditCommand) validateArgs(cmd *cobra.Command, args []string) error
{
-	if len(args) != 1 {
-		return errors.New("accepts 1 arg, received " + strconv.Itoa(len(args)))
-	}
-
-	return nil
-}
-
-func (command *contextEditCommand) run(cmd *cobra.Command, args []string) error {
-	log.Printf("context=%s, config=%+v", args[0], command)
-	return nil
-}
diff --git a/pkg/client/cmd/context_get.go b/pkg/client/cmd/context_get.go
index 36d16c1..05a96ca 100644
--- a/pkg/client/cmd/context_get.go
+++ b/pkg/client/cmd/context_get.go
@@ -25,8 +25,6 @@ import (
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
 	"github.com/operator-framework/operator-sdk/pkg/sdk"
 	"github.com/spf13/cobra"
-
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
 func newContextGetCmd(rootCmdOptions *RootCmdOptions) *cobra.Command {
@@ -49,17 +47,8 @@ type contextGetCommand struct {
 }
 
 func (command *contextGetCommand) run(cmd *cobra.Command, args []string) error {
-	ctxList := v1alpha1.IntegrationContextList{
-		TypeMeta: metav1.TypeMeta{
-			APIVersion: v1alpha1.SchemeGroupVersion.String(),
-			Kind:       "IntegrationContext",
-		},
-	}
-
-	namespace := command.Namespace
-
-	err := sdk.List(namespace, &ctxList)
-	if err != nil {
+	ctxList := v1alpha1.NewIntegrationContextList()
+	if err := sdk.List(command.Namespace, &ctxList); err != nil {
 		return err
 	}
 
diff --git a/pkg/client/cmd/run.go b/pkg/client/cmd/run.go
index cee146e..312f49b 100644
--- a/pkg/client/cmd/run.go
+++ b/pkg/client/cmd/run.go
@@ -27,19 +27,20 @@ import (
 
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
 	"github.com/apache/camel-k/pkg/util/kubernetes"
+	"github.com/apache/camel-k/pkg/util/watch"
 	"github.com/operator-framework/operator-sdk/pkg/sdk"
 	"github.com/spf13/cobra"
 	k8serrors "k8s.io/apimachinery/pkg/api/errors"
 	"k8s.io/apimachinery/pkg/apis/meta/v1"
-	"github.com/apache/camel-k/pkg/util/watch"
 )
 
 type RunCmdOptions struct {
 	*RootCmdOptions
-	Language        string
-	IntegrationName string
-	Dependencies    []string
-	Wait            bool
+	IntegrationContext string
+	Language           string
+	IntegrationName    string
+	Dependencies       []string
+	Wait               bool
 }
 
 func NewCmdRun(rootCmdOptions *RootCmdOptions) *cobra.Command {
@@ -59,7 +60,7 @@ func NewCmdRun(rootCmdOptions *RootCmdOptions) *cobra.Command {
 	cmd.Flags().StringVar(&options.IntegrationName, "name", "", "The integration name")
 	cmd.Flags().StringSliceVarP(&options.Dependencies, "dependency", "d", nil, "The integration
dependency")
 	cmd.Flags().BoolVarP(&options.Wait, "wait", "w", false, "Waits for the integration to
be running")
-	cmd.ParseFlags(os.Args)
+	cmd.Flags().StringVarP(&options.IntegrationContext, "context", "x", "", "The contex
used to run the integration")
 
 	return &cmd
 }
@@ -170,6 +171,7 @@ func (o *RunCmdOptions) createIntegration(cmd *cobra.Command, args []string)
(*v
 				Language: o.Language,
 			},
 			Dependencies: o.Dependencies,
+			Context:      o.IntegrationContext,
 		},
 	}
 
diff --git a/pkg/stub/action/context/build.go b/pkg/stub/action/context/build.go
index 1541e9f..ca9b44b 100644
--- a/pkg/stub/action/context/build.go
+++ b/pkg/stub/action/context/build.go
@@ -18,29 +18,58 @@ limitations under the License.
 package action
 
 import (
-	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"context"
+
 	"github.com/operator-framework/operator-sdk/pkg/sdk"
+	"github.com/sirupsen/logrus"
+
+	"github.com/apache/camel-k/pkg/build/api"
+
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/apache/camel-k/pkg/build"
 )
 
-func NewIntegrationContextBuildAction() IntegrationContextAction {
-	return &integrationContextBuildAction{}
+func NewIntegrationContextBuildAction(ctx context.Context, namespace string) IntegrationContextAction
{
+	return &integrationContextBuildAction{
+		buildManager: build.NewManager(ctx, namespace),
+	}
 }
 
-// start edit context
 type integrationContextBuildAction struct {
+	buildManager *build.Manager
 }
 
 func (action *integrationContextBuildAction) Name() string {
-	return "Edit"
+	return "build"
 }
 
 func (action *integrationContextBuildAction) CanHandle(context *v1alpha1.IntegrationContext)
bool {
-	// TODO: implement
-	return false
+	return context.Status.Phase == v1alpha1.IntegrationContextPhaseBuilding
 }
 
-func (action *integrationContextBuildAction) Handle(integration *v1alpha1.IntegrationContext)
error {
-	target := integration.DeepCopy()
-	// TODO: implement
-	return sdk.Update(target)
+func (action *integrationContextBuildAction) Handle(context *v1alpha1.IntegrationContext)
error {
+	buildIdentifier := api.BuildIdentifier{
+		Name:      "context-" + context.Name,
+		Qualifier: context.ResourceVersion,
+	}
+
+	buildResult := action.buildManager.Get(buildIdentifier)
+	if buildResult.Status == api.BuildStatusNotRequested {
+		action.buildManager.Start(api.BuildSource{
+			Identifier:   buildIdentifier,
+			Dependencies: context.Spec.Dependencies,
+		})
+		logrus.Info("Build started")
+	} else if buildResult.Status == api.BuildStatusError {
+		target := context.DeepCopy()
+		target.Status.Phase = v1alpha1.IntegrationContextPhaseError
+		return sdk.Update(target)
+	} else if buildResult.Status == api.BuildStatusCompleted {
+		target := context.DeepCopy()
+		target.Status.Image = buildResult.Image
+		target.Status.Phase = v1alpha1.IntegrationContextPhaseReady
+		return sdk.Update(target)
+	}
+
+	return nil
 }
diff --git a/pkg/stub/action/context/edit.go b/pkg/stub/action/context/initialize.go
similarity index 56%
rename from pkg/stub/action/context/edit.go
rename to pkg/stub/action/context/initialize.go
index 871d44b..5803b38 100644
--- a/pkg/stub/action/context/edit.go
+++ b/pkg/stub/action/context/initialize.go
@@ -19,28 +19,31 @@ package action
 
 import (
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/apache/camel-k/pkg/util/digest"
 	"github.com/operator-framework/operator-sdk/pkg/sdk"
 )
 
-func NewIntegrationContextEditAction() IntegrationContextAction {
-	return &integrationContextEditAction{}
+func NewIntegrationContextInitializeAction() IntegrationContextAction {
+	return &integrationContexInitializeAction{}
 }
 
-// start edit context
-type integrationContextEditAction struct {
+type integrationContexInitializeAction struct {
 }
 
-func (action *integrationContextEditAction) Name() string {
-	return "Edit"
+func (action *integrationContexInitializeAction) Name() string {
+	return "initialize"
 }
 
-func (action *integrationContextEditAction) CanHandle(context *v1alpha1.IntegrationContext)
bool {
-	// TODO: implement
-	return false
+func (action *integrationContexInitializeAction) CanHandle(context *v1alpha1.IntegrationContext)
bool {
+	return context.Status.Phase == ""
 }
 
-func (action *integrationContextEditAction) Handle(integration *v1alpha1.IntegrationContext)
error {
-	target := integration.DeepCopy()
-	// TODO: implement
+func (action *integrationContexInitializeAction) Handle(context *v1alpha1.IntegrationContext)
error {
+	target := context.DeepCopy()
+
+	// update the status
+	target.Status.Phase = v1alpha1.IntegrationContextPhaseBuilding
+	target.Status.Digest = digest.ComputeForIntegrationContext(context)
+
 	return sdk.Update(target)
 }
diff --git a/pkg/stub/action/context/monitor.go b/pkg/stub/action/context/monitor.go
index 98843f7..138900b 100644
--- a/pkg/stub/action/context/monitor.go
+++ b/pkg/stub/action/context/monitor.go
@@ -19,28 +19,36 @@ package action
 
 import (
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/apache/camel-k/pkg/util/digest"
 	"github.com/operator-framework/operator-sdk/pkg/sdk"
+	"github.com/sirupsen/logrus"
 )
 
 func NewIntegrationContextMonitorAction() IntegrationContextAction {
-	return &integrationContexMonitorAction{}
+	return &integrationContextMonitorAction{}
 }
 
-// start edit context
-type integrationContexMonitorAction struct {
+type integrationContextMonitorAction struct {
 }
 
-func (action *integrationContexMonitorAction) Name() string {
-	return "Monitor"
+func (action *integrationContextMonitorAction) Name() string {
+	return "monitor"
 }
 
-func (action *integrationContexMonitorAction) CanHandle(context *v1alpha1.IntegrationContext)
bool {
-	// TODO: implement
-	return false
+func (action *integrationContextMonitorAction) CanHandle(context *v1alpha1.IntegrationContext)
bool {
+	return context.Status.Phase == v1alpha1.IntegrationContextPhaseReady || context.Status.Phase
== v1alpha1.IntegrationContextPhaseError
 }
 
-func (action *integrationContexMonitorAction) Handle(integration *v1alpha1.IntegrationContext)
error {
-	target := integration.DeepCopy()
-	// TODO: implement
-	return sdk.Update(target)
+func (action *integrationContextMonitorAction) Handle(context *v1alpha1.IntegrationContext)
error {
+	hash := digest.ComputeForIntegrationContext(context)
+	if hash != context.Status.Digest {
+		logrus.Info("IntegrationContext ", context.Name, " needs a rebuild")
+
+		target := context.DeepCopy()
+		target.Status.Digest = hash
+		target.Status.Phase = v1alpha1.IntegrationContextPhaseBuilding
+		return sdk.Update(target)
+	}
+
+	return nil
 }
diff --git a/pkg/stub/action/context/save.go b/pkg/stub/action/context/save.go
deleted file mode 100644
index 16d3b0e..0000000
--- a/pkg/stub/action/context/save.go
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
-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 action
-
-import (
-	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
-	"github.com/operator-framework/operator-sdk/pkg/sdk"
-)
-
-func NewIntegrationContextSaveAction() IntegrationContextAction {
-	return &integrationContexSaveAction{}
-}
-
-// start edit context
-type integrationContexSaveAction struct {
-}
-
-func (action *integrationContexSaveAction) Name() string {
-	return "Edit"
-}
-
-func (action *integrationContexSaveAction) CanHandle(context *v1alpha1.IntegrationContext)
bool {
-	// TODO: implement
-	return false
-}
-
-func (action *integrationContexSaveAction) Handle(integration *v1alpha1.IntegrationContext)
error {
-	target := integration.DeepCopy()
-	// TODO: implement
-	return sdk.Update(target)
-}
diff --git a/pkg/stub/action/integration/build.go b/pkg/stub/action/integration/build.go
index 373583a..f98930e 100644
--- a/pkg/stub/action/integration/build.go
+++ b/pkg/stub/action/integration/build.go
@@ -24,16 +24,17 @@ import (
 	"github.com/apache/camel-k/pkg/build"
 	"github.com/apache/camel-k/pkg/build/api"
 	"github.com/operator-framework/operator-sdk/pkg/sdk"
+	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 )
 
 type BuildAction struct {
-	buildManager *build.BuildManager
+	buildManager *build.Manager
 }
 
 func NewBuildAction(ctx context.Context, namespace string) IntegrationAction {
 	return &BuildAction{
-		buildManager: build.NewBuildManager(ctx, namespace),
+		buildManager: build.NewManager(ctx, namespace),
 	}
 }
 
@@ -46,9 +47,28 @@ func (b *BuildAction) CanHandle(integration *v1alpha1.Integration) bool
{
 }
 
 func (b *BuildAction) Handle(integration *v1alpha1.Integration) error {
+	if integration.Spec.Context != "" {
+		name := integration.Spec.Context
+		ctx := v1alpha1.NewIntegrationContext(integration.Namespace, name)
+
+		if err := sdk.Get(&ctx); err != nil {
+			//TODO: we may need to add a wait strategy, i.e give up after some time
+			return errors.Wrapf(err, "unable to find integration context %s, %s", ctx.Name, err)
+		}
+
+		if ctx.Status.Phase == v1alpha1.IntegrationContextPhaseReady {
+			target := integration.DeepCopy()
+			target.Status.Image = ctx.Status.Image
+			target.Status.Phase = v1alpha1.IntegrationPhaseDeploying
+			return sdk.Update(target)
+		}
+
+		return nil
+	}
+
 	buildIdentifier := api.BuildIdentifier{
-		Name:   integration.Name,
-		Digest: integration.Status.Digest,
+		Name:      integration.Name,
+		Qualifier: integration.Status.Digest,
 	}
 	buildResult := b.buildManager.Get(buildIdentifier)
 	if buildResult.Status == api.BuildStatusNotRequested {
diff --git a/pkg/stub/action/integration/initialize.go b/pkg/stub/action/integration/initialize.go
index 6caa1b3..f2747eb 100644
--- a/pkg/stub/action/integration/initialize.go
+++ b/pkg/stub/action/integration/initialize.go
@@ -48,6 +48,6 @@ func (b *InitializeAction) Handle(integration *v1alpha1.Integration) error
{
 	}
 	// update the status
 	target.Status.Phase = v1alpha1.IntegrationPhaseBuilding
-	target.Status.Digest = digest.Compute(integration)
+	target.Status.Digest = digest.ComputeForIntegration(integration)
 	return sdk.Update(target)
 }
diff --git a/pkg/stub/action/integration/monitor.go b/pkg/stub/action/integration/monitor.go
index ad14532..b12600a 100644
--- a/pkg/stub/action/integration/monitor.go
+++ b/pkg/stub/action/integration/monitor.go
@@ -42,7 +42,7 @@ func (a *MonitorAction) CanHandle(integration *v1alpha1.Integration) bool
{
 
 func (a *MonitorAction) Handle(integration *v1alpha1.Integration) error {
 
-	hash := digest.Compute(integration)
+	hash := digest.ComputeForIntegration(integration)
 	if hash != integration.Status.Digest {
 		logrus.Info("Integration ", integration.Name, " needs a rebuild")
 
diff --git a/pkg/stub/handler.go b/pkg/stub/handler.go
index 5c927cf..d90d776 100644
--- a/pkg/stub/handler.go
+++ b/pkg/stub/handler.go
@@ -36,7 +36,11 @@ func NewHandler(ctx context.Context, namespace string) sdk.Handler {
 			iaction.NewDeployAction(),
 			iaction.NewMonitorAction(),
 		},
-		integrationContextActionPool: []caction.IntegrationContextAction{},
+		integrationContextActionPool: []caction.IntegrationContextAction{
+			caction.NewIntegrationContextInitializeAction(),
+			caction.NewIntegrationContextBuildAction(ctx, namespace),
+			caction.NewIntegrationContextMonitorAction(),
+		},
 	}
 }
 
diff --git a/pkg/util/digest/digest.go b/pkg/util/digest/digest.go
index 6f84744..103a6f1 100644
--- a/pkg/util/digest/digest.go
+++ b/pkg/util/digest/digest.go
@@ -27,16 +27,45 @@ import (
 	"github.com/apache/camel-k/version"
 )
 
-// Compute a digest of the fields that are relevant for the deployment
+// ComputeForIntegration a digest of the fields that are relevant for the deployment
 // Produces a digest that can be used as docker image tag
-func Compute(integration *v1alpha1.Integration) string {
+func ComputeForIntegration(integration *v1alpha1.Integration) string {
 	hash := sha256.New()
 	// Operator version is relevant
 	hash.Write([]byte(version.Version))
-	// Integration relevant fields
+	// Integration Context is relevant
+	hash.Write([]byte(integration.Spec.Context))
+
+	// Integration code
 	if integration.Spec.Source.Content != "" {
 		hash.Write([]byte(integration.Spec.Source.Content))
 	}
+	// Integration dependencies
+	for _, item := range integration.Spec.Dependencies {
+		hash.Write([]byte(item))
+	}
+
+	// Add a letter at the beginning and use URL safe encoding
+	return "v" + base64.RawURLEncoding.EncodeToString(hash.Sum(nil))
+}
+
+// ComputeForIntegrationContext a digest of the fields that are relevant for the deployment
+// Produces a digest that can be used as docker image tag
+func ComputeForIntegrationContext(integration *v1alpha1.IntegrationContext) string {
+	hash := sha256.New()
+	// Operator version is relevant
+	hash.Write([]byte(version.Version))
+
+	for _, item := range integration.Spec.Dependencies {
+		hash.Write([]byte(item))
+	}
+	for _, item := range integration.Spec.Environment {
+		hash.Write([]byte(item.String()))
+	}
+	for _, item := range integration.Spec.Properties {
+		hash.Write([]byte(item.String()))
+	}
+
 	// Add a letter at the beginning and use URL safe encoding
 	return "v" + base64.RawURLEncoding.EncodeToString(hash.Sum(nil))
 }


Mime
View raw message