nicolaferraro closed pull request #61: Allow buildless direct deploy
URL: https://github.com/apache/camel-k/pull/61
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/deploy/crd-integration-context.yaml 
b/deploy/crd-integration-context.yaml
index 612c848..fbbbf49 100644
--- a/deploy/crd-integration-context.yaml
+++ b/deploy/crd-integration-context.yaml
@@ -11,5 +11,7 @@ spec:
     listKind: IntegrationContextList
     plural: integrationcontexts
     singular: integrationcontext
+    shortNames:
+    - ictx
   scope: Namespaced
   version: v1alpha1
diff --git a/deploy/crd-integration.yaml b/deploy/crd-integration.yaml
index 1cdbcc6..115d995 100644
--- a/deploy/crd-integration.yaml
+++ b/deploy/crd-integration.yaml
@@ -11,5 +11,7 @@ spec:
     listKind: IntegrationList
     plural: integrations
     singular: integration
+    shortNames:
+    - it
   scope: Namespaced
   version: v1alpha1
diff --git a/deploy/resources.go b/deploy/resources.go
index 96995ce..3b40638 100644
--- a/deploy/resources.go
+++ b/deploy/resources.go
@@ -39,6 +39,8 @@ spec:
     listKind: IntegrationContextList
     plural: integrationcontexts
     singular: integrationcontext
+    shortNames:
+    - ictx
   scope: Namespaced
   version: v1alpha1
 
@@ -58,6 +60,8 @@ spec:
     listKind: IntegrationList
     plural: integrations
     singular: integration
+    shortNames:
+    - it
   scope: Namespaced
   version: v1alpha1
 
@@ -372,6 +376,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 +387,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_delete.go b/pkg/client/cmd/context_delete.go
new file mode 100644
index 0000000..c4cb893
--- /dev/null
+++ b/pkg/client/cmd/context_delete.go
@@ -0,0 +1,71 @@
+/*
+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"
+
+       "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"
+)
+
+func newContextDeleteCmd(rootCmdOptions *RootCmdOptions) *cobra.Command {
+       impl := contextDeleteCommand{
+               RootCmdOptions: rootCmdOptions,
+       }
+
+       cmd := cobra.Command{
+               Use:   "delete",
+               Short: "Delete an Integration Context",
+               Long:  `Delete anIntegration Context.`,
+               Args:  impl.validateArgs,
+               RunE:  impl.run,
+       }
+
+       return &cmd
+}
+
+type contextDeleteCommand struct {
+       *RootCmdOptions
+}
+
+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)))
+       }
+
+       return 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
+       }
+
+       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))
 }


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services

Reply via email to