This is an automated email from the ASF dual-hosted git repository.

lburgazzoli pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit 21caae8ff53055dff840f3d6f19ff562fbfff148
Author: nferraro <ni.ferr...@gmail.com>
AuthorDate: Tue Sep 25 12:30:22 2018 +0200

    Add IntegrationPlatform CRD
---
 cmd/camel-k-operator/camel_k_operator.go           |   1 +
 deploy/crd-integration-platform.yaml               |  17 ++++
 deploy/platform-cr.yaml                            |   6 ++
 deploy/resources.go                                |  31 ++++++
 pkg/apis/camel/v1alpha1/register.go                |   2 +
 pkg/apis/camel/v1alpha1/types.go                   |  76 ++++++++++++++
 pkg/apis/camel/v1alpha1/types_support.go           |  10 ++
 pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go   | 110 ++++++++++++++++++++
 pkg/client/cmd/install.go                          |   4 +-
 pkg/install/cluster.go                             |   5 +
 pkg/install/{operator.go => common.go}             |  39 ++-----
 pkg/install/operator.go                            |  56 +----------
 pkg/platform/build.go                              |  91 +++++++++++++++++
 .../integration/action.go => platform/doc.go}      |  20 +---
 pkg/platform/get.go                                |  53 ++++++++++
 pkg/stub/action/context/action.go                  |   6 +-
 pkg/stub/action/context/build.go                   |  73 ++++----------
 pkg/stub/action/context/initialize.go              |  25 +++--
 pkg/stub/action/context/monitor.go                 |  17 ++--
 pkg/stub/action/integration/action.go              |   6 +-
 pkg/stub/action/integration/build.go               |   6 +-
 pkg/stub/action/integration/deploy.go              |  16 +--
 pkg/stub/action/integration/initialize.go          |  13 ++-
 pkg/stub/action/integration/monitor.go             |   5 +-
 pkg/stub/action/integration/util.go                |  19 +++-
 pkg/stub/action/{context => platform}/action.go    |  11 +-
 pkg/stub/action/platform/create.go                 |  54 ++++++++++
 pkg/stub/action/platform/initialize.go             | 112 +++++++++++++++++++++
 pkg/stub/action/platform/start.go                  |  79 +++++++++++++++
 pkg/stub/handler.go                                |  53 ++++++----
 pkg/util/openshift/register.go                     |   2 +-
 31 files changed, 803 insertions(+), 215 deletions(-)

diff --git a/cmd/camel-k-operator/camel_k_operator.go 
b/cmd/camel-k-operator/camel_k_operator.go
index 32ee754..79ae793 100644
--- a/cmd/camel-k-operator/camel_k_operator.go
+++ b/cmd/camel-k-operator/camel_k_operator.go
@@ -62,6 +62,7 @@ func main() {
 
        watch(resource, "Integration", namespace, resyncPeriod)
        watch(resource, "IntegrationContext", namespace, resyncPeriod)
+       watch(resource, "IntegrationPlatform", namespace, resyncPeriod)
 
        sdk.Handle(stub.NewHandler(ctx, namespace))
        sdk.Run(ctx)
diff --git a/deploy/crd-integration-platform.yaml 
b/deploy/crd-integration-platform.yaml
new file mode 100644
index 0000000..ccba19c
--- /dev/null
+++ b/deploy/crd-integration-platform.yaml
@@ -0,0 +1,17 @@
+apiVersion: apiextensions.k8s.io/v1beta1
+kind: CustomResourceDefinition
+metadata:
+  name: integrationplatforms.camel.apache.org
+  labels:
+    app: "camel-k"
+spec:
+  group: camel.apache.org
+  names:
+    kind: IntegrationPlatform
+    listKind: IntegrationPlatformList
+    plural: integrationplatforms
+    singular: integrationplatform
+    shortNames:
+    - ip
+  scope: Namespaced
+  version: v1alpha1
diff --git a/deploy/platform-cr.yaml b/deploy/platform-cr.yaml
new file mode 100644
index 0000000..cdf13ff
--- /dev/null
+++ b/deploy/platform-cr.yaml
@@ -0,0 +1,6 @@
+apiVersion: camel.apache.org/v1alpha1
+kind: IntegrationPlatform
+metadata:
+  name: camel-k
+  labels:
+    app: "camel-k"
diff --git a/deploy/resources.go b/deploy/resources.go
index 7a9888f..7749be3 100644
--- a/deploy/resources.go
+++ b/deploy/resources.go
@@ -2123,6 +2123,27 @@ spec:
   version: v1alpha1
 
 `
+       Resources["crd-integration-platform.yaml"] =
+               `
+apiVersion: apiextensions.k8s.io/v1beta1
+kind: CustomResourceDefinition
+metadata:
+  name: integrationplatforms.camel.apache.org
+  labels:
+    app: "camel-k"
+spec:
+  group: camel.apache.org
+  names:
+    kind: IntegrationPlatform
+    listKind: IntegrationPlatformList
+    plural: integrationplatforms
+    singular: integrationplatform
+    shortNames:
+    - ip
+  scope: Namespaced
+  version: v1alpha1
+
+`
        Resources["crd-integration.yaml"] =
                `
 apiVersion: apiextensions.k8s.io/v1beta1
@@ -2436,6 +2457,16 @@ status:
   loadBalancer: {}
 
 `
+       Resources["platform-cr.yaml"] =
+               `
+apiVersion: camel.apache.org/v1alpha1
+kind: IntegrationPlatform
+metadata:
+  name: camel-k
+  labels:
+    app: "camel-k"
+
+`
        Resources["platform-integration-context-core.yaml"] =
                `
 apiVersion: camel.apache.org/v1alpha1
diff --git a/pkg/apis/camel/v1alpha1/register.go 
b/pkg/apis/camel/v1alpha1/register.go
index 460dd4c..7ef6212 100644
--- a/pkg/apis/camel/v1alpha1/register.go
+++ b/pkg/apis/camel/v1alpha1/register.go
@@ -49,6 +49,8 @@ func addKnownTypes(scheme *runtime.Scheme) error {
                &IntegrationList{},
                &IntegrationContext{},
                &IntegrationContextList{},
+               &IntegrationPlatform{},
+               &IntegrationPlatformList{},
        )
        metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
        return nil
diff --git a/pkg/apis/camel/v1alpha1/types.go b/pkg/apis/camel/v1alpha1/types.go
index 80ebe59..fa27617 100644
--- a/pkg/apis/camel/v1alpha1/types.go
+++ b/pkg/apis/camel/v1alpha1/types.go
@@ -150,3 +150,79 @@ const (
        // IntegrationContextPhaseError --
        IntegrationContextPhaseError IntegrationContextPhase = "Error"
 )
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// IntegrationPlatformList --
+type IntegrationPlatformList struct {
+       metav1.TypeMeta `json:",inline"`
+       metav1.ListMeta `json:"metadata"`
+       Items           []IntegrationPlatform `json:"items"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// IntegrationPlatform --
+type IntegrationPlatform struct {
+       metav1.TypeMeta   `json:",inline"`
+       metav1.ObjectMeta `json:"metadata"`
+       Spec              IntegrationPlatformSpec   `json:"spec"`
+       Status            IntegrationPlatformStatus `json:"status,omitempty"`
+}
+
+// IntegrationPlatformSpec --
+type IntegrationPlatformSpec struct {
+       Cluster IntegrationPlatformCluster   `json:"cluster,omitempty"`
+       Build   IntegrationPlatformBuildSpec `json:"build,omitempty"`
+}
+
+// IntegrationPlatformCluster is the kind of orchestration cluster the 
platform is installed into
+type IntegrationPlatformCluster string
+
+const (
+       // IntegrationPlatformClusterOpenShift is used when targeting a 
OpenShift cluster
+       IntegrationPlatformClusterOpenShift = "OpenShift"
+       // IntegrationPlatformClusterKubernetes is used when targeting a 
Kubernetes cluster
+       IntegrationPlatformClusterKubernetes = "Kubernetes"
+)
+
+// IntegrationPlatformBuildSpec contains platform related build information
+type IntegrationPlatformBuildSpec struct {
+       PublishStrategy IntegrationPlatformBuildPublishStrategy 
`json:"publishStrategy,omitempty"`
+       Registry        string                                  
`json:"registry,omitempty"`
+}
+
+// IntegrationPlatformBuildPublishStrategy enumerates all implemented build 
strategies
+type IntegrationPlatformBuildPublishStrategy string
+
+const (
+       // IntegrationPlatformBuildPublishStrategyS2I performs a OpenShift 
binary S2I build
+       IntegrationPlatformBuildPublishStrategyS2I = "S2I"
+
+       // IntegrationPlatformBuildPublishStrategyKaniko performs
+       IntegrationPlatformBuildPublishStrategyKaniko = "Kaniko"
+)
+
+// IntegrationPlatformStatus --
+type IntegrationPlatformStatus struct {
+       Phase IntegrationPlatformPhase `json:"phase,omitempty"`
+}
+
+// IntegrationPlatformPhase --
+type IntegrationPlatformPhase string
+
+const (
+       // IntegrationPlatformKind --
+       IntegrationPlatformKind string = "IntegrationPlatform"
+
+       // IntegrationPlatformPhaseCreating --
+       IntegrationPlatformPhaseCreating IntegrationPlatformPhase = "Creating"
+       // IntegrationPlatformPhaseStarting --
+       IntegrationPlatformPhaseStarting IntegrationPlatformPhase = "Starting"
+       // IntegrationPlatformPhaseReady --
+       IntegrationPlatformPhaseReady IntegrationPlatformPhase = "Ready"
+       // IntegrationPlatformPhaseError --
+       IntegrationPlatformPhaseError IntegrationPlatformPhase = "Error"
+       // IntegrationPlatformPhaseDuplicate --
+       IntegrationPlatformPhaseDuplicate IntegrationPlatformPhase = "Duplicate"
+)
diff --git a/pkg/apis/camel/v1alpha1/types_support.go 
b/pkg/apis/camel/v1alpha1/types_support.go
index 39eb11d..fa4cceb 100644
--- a/pkg/apis/camel/v1alpha1/types_support.go
+++ b/pkg/apis/camel/v1alpha1/types_support.go
@@ -39,6 +39,16 @@ func (spec ConfigurationSpec) String() string {
 //
 // **********************************
 
+// NewIntegrationPlatformList --
+func NewIntegrationPlatformList() IntegrationPlatformList {
+       return IntegrationPlatformList{
+               TypeMeta: metav1.TypeMeta{
+                       APIVersion: SchemeGroupVersion.String(),
+                       Kind:       IntegrationPlatformKind,
+               },
+       }
+}
+
 // NewIntegrationList --
 func NewIntegrationList() IntegrationList {
        return IntegrationList{
diff --git a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go 
b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
index 0784edc..57ff452 100644
--- a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
@@ -211,6 +211,116 @@ func (in *IntegrationList) DeepCopyObject() 
runtime.Object {
 }
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
+func (in *IntegrationPlatform) DeepCopyInto(out *IntegrationPlatform) {
+       *out = *in
+       out.TypeMeta = in.TypeMeta
+       in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+       out.Spec = in.Spec
+       out.Status = in.Status
+       return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, 
creating a new IntegrationPlatform.
+func (in *IntegrationPlatform) DeepCopy() *IntegrationPlatform {
+       if in == nil {
+               return nil
+       }
+       out := new(IntegrationPlatform)
+       in.DeepCopyInto(out)
+       return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, 
creating a new runtime.Object.
+func (in *IntegrationPlatform) DeepCopyObject() runtime.Object {
+       if c := in.DeepCopy(); c != nil {
+               return c
+       }
+       return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
+func (in *IntegrationPlatformBuildSpec) DeepCopyInto(out 
*IntegrationPlatformBuildSpec) {
+       *out = *in
+       return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, 
creating a new IntegrationPlatformBuildSpec.
+func (in *IntegrationPlatformBuildSpec) DeepCopy() 
*IntegrationPlatformBuildSpec {
+       if in == nil {
+               return nil
+       }
+       out := new(IntegrationPlatformBuildSpec)
+       in.DeepCopyInto(out)
+       return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
+func (in *IntegrationPlatformList) DeepCopyInto(out *IntegrationPlatformList) {
+       *out = *in
+       out.TypeMeta = in.TypeMeta
+       out.ListMeta = in.ListMeta
+       if in.Items != nil {
+               in, out := &in.Items, &out.Items
+               *out = make([]IntegrationPlatform, len(*in))
+               for i := range *in {
+                       (*in)[i].DeepCopyInto(&(*out)[i])
+               }
+       }
+       return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, 
creating a new IntegrationPlatformList.
+func (in *IntegrationPlatformList) DeepCopy() *IntegrationPlatformList {
+       if in == nil {
+               return nil
+       }
+       out := new(IntegrationPlatformList)
+       in.DeepCopyInto(out)
+       return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, 
creating a new runtime.Object.
+func (in *IntegrationPlatformList) DeepCopyObject() runtime.Object {
+       if c := in.DeepCopy(); c != nil {
+               return c
+       }
+       return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
+func (in *IntegrationPlatformSpec) DeepCopyInto(out *IntegrationPlatformSpec) {
+       *out = *in
+       out.Build = in.Build
+       return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, 
creating a new IntegrationPlatformSpec.
+func (in *IntegrationPlatformSpec) DeepCopy() *IntegrationPlatformSpec {
+       if in == nil {
+               return nil
+       }
+       out := new(IntegrationPlatformSpec)
+       in.DeepCopyInto(out)
+       return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
+func (in *IntegrationPlatformStatus) DeepCopyInto(out 
*IntegrationPlatformStatus) {
+       *out = *in
+       return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, 
creating a new IntegrationPlatformStatus.
+func (in *IntegrationPlatformStatus) DeepCopy() *IntegrationPlatformStatus {
+       if in == nil {
+               return nil
+       }
+       out := new(IntegrationPlatformStatus)
+       in.DeepCopyInto(out)
+       return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
 func (in *IntegrationSpec) DeepCopyInto(out *IntegrationSpec) {
        *out = *in
        if in.Replicas != nil {
diff --git a/pkg/client/cmd/install.go b/pkg/client/cmd/install.go
index 2ca05ba..0d20021 100644
--- a/pkg/client/cmd/install.go
+++ b/pkg/client/cmd/install.go
@@ -35,7 +35,7 @@ func newCmdInstall(rootCmdOptions *RootCmdOptions) 
*cobra.Command {
        cmd := cobra.Command{
                Use:   "install",
                Short: "Install Camel K on a Kubernetes cluster",
-               Long:  `Installs Camel K on a Kubernetes or Openshift cluster.`,
+               Long:  `Installs Camel K on a Kubernetes or OpenShift cluster.`,
                RunE:  options.install,
        }
 
@@ -69,7 +69,7 @@ func (o *installCmdOptions) install(cmd *cobra.Command, args 
[]string) error {
                        return err
                }
 
-               err = install.PlatformContexts(namespace)
+               err = install.Platform(namespace)
                if err != nil {
                        return err
                }
diff --git a/pkg/install/cluster.go b/pkg/install/cluster.go
index 855d8f6..dea1dee 100644
--- a/pkg/install/cluster.go
+++ b/pkg/install/cluster.go
@@ -32,6 +32,11 @@ import (
 // SetupClusterwideResources --
 func SetupClusterwideResources() error {
 
+       // Install CRD for Integration Platform (if needed)
+       if err := installCRD("IntegrationPlatform", 
"crd-integration-platform.yaml"); err != nil {
+               return err
+       }
+
        // Install CRD for Integration Context (if needed)
        if err := installCRD("IntegrationContext", 
"crd-integration-context.yaml"); err != nil {
                return err
diff --git a/pkg/install/operator.go b/pkg/install/common.go
similarity index 66%
copy from pkg/install/operator.go
copy to pkg/install/common.go
index 58aed65..bef7f6f 100644
--- a/pkg/install/operator.go
+++ b/pkg/install/common.go
@@ -26,42 +26,18 @@ import (
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
-// Operator --
-func Operator(namespace string) error {
-       return installResources(namespace,
-               "operator-service-account.yaml",
-               "operator-role-openshift.yaml", // TODO distinguish between 
Openshift and Kubernetes
-               "operator-role-binding.yaml",
-               "operator-deployment.yaml",
-               "operator-service.yaml",
-       )
-}
-
-// PlatformContexts --
-func PlatformContexts(namespace string) error {
-       return installResources(namespace,
-               "platform-integration-context-core.yaml",
-               "platform-integration-context-groovy.yaml",
-       )
-}
-
-// Example --
-func Example(namespace string) error {
-       return installResources(namespace,
-               "cr-example.yaml",
-       )
-}
-
-func installResources(namespace string, names ...string) error {
+// Resources installs named resources from the project resource directory
+func Resources(namespace string, names ...string) error {
        for _, name := range names {
-               if err := installResource(namespace, name); err != nil {
+               if err := Resource(namespace, name); err != nil {
                        return err
                }
        }
        return nil
 }
 
-func installResource(namespace string, name string) error {
+// Resource installs a single named resource from the project resource 
directory
+func Resource(namespace string, name string) error {
        obj, err := kubernetes.LoadResourceFromYaml(deploy.Resources[name])
        if err != nil {
                return err
@@ -77,10 +53,13 @@ func installResource(namespace string, name string) error {
                if obj.GetObjectKind().GroupVersionKind().Kind == "Service" {
                        return nil
                }
-               // Don't recreate integration contexts
+               // Don't recreate integration contexts or platforms
                if obj.GetObjectKind().GroupVersionKind().Kind == 
v1alpha1.IntegrationContextKind {
                        return nil
                }
+               if obj.GetObjectKind().GroupVersionKind().Kind == 
v1alpha1.IntegrationPlatformKind {
+                       return nil
+               }
                return sdk.Update(obj)
        }
        return err
diff --git a/pkg/install/operator.go b/pkg/install/operator.go
index 58aed65..0f6039c 100644
--- a/pkg/install/operator.go
+++ b/pkg/install/operator.go
@@ -17,18 +17,9 @@ limitations under the License.
 
 package install
 
-import (
-       "github.com/apache/camel-k/deploy"
-       "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"
-       "k8s.io/apimachinery/pkg/api/errors"
-       metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-)
-
 // Operator --
 func Operator(namespace string) error {
-       return installResources(namespace,
+       return Resources(namespace,
                "operator-service-account.yaml",
                "operator-role-openshift.yaml", // TODO distinguish between 
Openshift and Kubernetes
                "operator-role-binding.yaml",
@@ -37,51 +28,14 @@ func Operator(namespace string) error {
        )
 }
 
-// PlatformContexts --
-func PlatformContexts(namespace string) error {
-       return installResources(namespace,
-               "platform-integration-context-core.yaml",
-               "platform-integration-context-groovy.yaml",
-       )
+// Platform installs the platform custom resource
+func Platform(namespace string) error {
+       return Resource(namespace,"platform-cr.yaml")
 }
 
 // Example --
 func Example(namespace string) error {
-       return installResources(namespace,
+       return Resources(namespace,
                "cr-example.yaml",
        )
 }
-
-func installResources(namespace string, names ...string) error {
-       for _, name := range names {
-               if err := installResource(namespace, name); err != nil {
-                       return err
-               }
-       }
-       return nil
-}
-
-func installResource(namespace string, name string) error {
-       obj, err := kubernetes.LoadResourceFromYaml(deploy.Resources[name])
-       if err != nil {
-               return err
-       }
-
-       if metaObject, ok := obj.(metav1.Object); ok {
-               metaObject.SetNamespace(namespace)
-       }
-
-       err = sdk.Create(obj)
-       if err != nil && errors.IsAlreadyExists(err) {
-               // Don't recreate Service object
-               if obj.GetObjectKind().GroupVersionKind().Kind == "Service" {
-                       return nil
-               }
-               // Don't recreate integration contexts
-               if obj.GetObjectKind().GroupVersionKind().Kind == 
v1alpha1.IntegrationContextKind {
-                       return nil
-               }
-               return sdk.Update(obj)
-       }
-       return err
-}
diff --git a/pkg/platform/build.go b/pkg/platform/build.go
new file mode 100644
index 0000000..994ced6
--- /dev/null
+++ b/pkg/platform/build.go
@@ -0,0 +1,91 @@
+/*
+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 platform
+
+import (
+       "context"
+       "errors"
+       "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+       "github.com/apache/camel-k/pkg/build"
+       "github.com/apache/camel-k/pkg/build/assemble"
+       "github.com/apache/camel-k/pkg/build/publish"
+       "github.com/operator-framework/operator-sdk/pkg/sdk"
+       metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+// buildManager is the current build manager
+// Note: it cannot be changed at runtime, needs a operator restart
+var buildManager *build.Manager
+
+// GetPlatformBuildManager returns a suitable build manager for the current 
platform
+func GetPlatformBuildManager(ctx context.Context, namespace string) 
(*build.Manager, error) {
+       if buildManager != nil {
+               return buildManager, nil
+       }
+       pl, err := GetCurrentPlatform(namespace)
+       if err != nil {
+               return nil, err
+       }
+
+       assembler := assemble.NewMavenAssembler(ctx)
+       if pl.Spec.Build.PublishStrategy == 
v1alpha1.IntegrationPlatformBuildPublishStrategyS2I {
+               publisher := publish.NewS2IIncrementalPublisher(ctx, namespace, 
newContextLister(namespace))
+               buildManager = build.NewManager(ctx, assembler, publisher)
+       }
+
+       if buildManager == nil {
+               return nil, errors.New("unsupported platform configuration")
+       }
+       return buildManager, nil
+}
+
+// =================================================================
+
+type contextLister struct {
+       namespace string
+}
+
+func newContextLister(namespace string) contextLister {
+       return contextLister{
+               namespace: namespace,
+       }
+}
+
+func (l contextLister) ListPublishedImages() ([]publish.PublishedImage, error) 
{
+       list := v1alpha1.NewIntegrationContextList()
+
+       err := sdk.List(l.namespace, &list, 
sdk.WithListOptions(&metav1.ListOptions{}))
+       if err != nil {
+               return nil, err
+       }
+       images := make([]publish.PublishedImage, 0)
+       for _, ctx := range list.Items {
+               if ctx.Status.Phase != v1alpha1.IntegrationContextPhaseReady || 
ctx.Labels == nil {
+                       continue
+               }
+               if ctxType, present := 
ctx.Labels["camel.apache.org/context.type"]; !present || ctxType != "platform" {
+                       continue
+               }
+
+               images = append(images, publish.PublishedImage{
+                       Image:     ctx.Status.Image,
+                       Classpath: ctx.Status.Classpath,
+               })
+       }
+       return images, nil
+}
diff --git a/pkg/stub/action/integration/action.go b/pkg/platform/doc.go
similarity index 65%
copy from pkg/stub/action/integration/action.go
copy to pkg/platform/doc.go
index 9e4a69c..74e5c18 100644
--- a/pkg/stub/action/integration/action.go
+++ b/pkg/platform/doc.go
@@ -15,21 +15,5 @@ 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"
-)
-
-// IntegrationAction --
-type IntegrationAction interface {
-
-       // a user friendly name for the action
-       Name() string
-
-       // returns true if the action can handle the integration
-       CanHandle(integration *v1alpha1.Integration) bool
-
-       // executes the handling function
-       Handle(integration *v1alpha1.Integration) error
-}
+// Package platform allows to retrieve information about the current installed 
platform
+package platform
diff --git a/pkg/platform/get.go b/pkg/platform/get.go
new file mode 100644
index 0000000..0da7163
--- /dev/null
+++ b/pkg/platform/get.go
@@ -0,0 +1,53 @@
+/*
+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 platform
+
+import (
+       "errors"
+       "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+       "github.com/operator-framework/operator-sdk/pkg/sdk"
+)
+
+// GetCurrentPlatform returns the currently installed platform
+func GetCurrentPlatform(namespace string) (*v1alpha1.IntegrationPlatform, 
error) {
+       lst, err := ListPlatforms(namespace)
+       if err != nil {
+               return nil, err
+       }
+
+       for _, platform := range lst.Items {
+               if IsActive(&platform) {
+                       return &platform, nil
+               }
+       }
+       return nil, errors.New("no active integration platforms found in the 
namespace")
+}
+
+// ListPlatforms returns all platforms installed in a given namespace (only 
one will be active)
+func ListPlatforms(namespace string) (*v1alpha1.IntegrationPlatformList, 
error) {
+       lst := v1alpha1.NewIntegrationPlatformList()
+       if err := sdk.List(namespace, &lst); err != nil {
+               return nil, err
+       }
+       return &lst, nil
+}
+
+// IsActive determines if the given platform is being used
+func IsActive(p *v1alpha1.IntegrationPlatform) bool {
+       return p.Status.Phase != "" && p.Status.Phase != 
v1alpha1.IntegrationPlatformPhaseDuplicate
+}
diff --git a/pkg/stub/action/context/action.go 
b/pkg/stub/action/context/action.go
index 23b0f10..97f35c4 100644
--- a/pkg/stub/action/context/action.go
+++ b/pkg/stub/action/context/action.go
@@ -15,14 +15,14 @@ See the License for the specific language governing 
permissions and
 limitations under the License.
 */
 
-package action
+package context
 
 import (
        "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
 )
 
-// IntegrationContextAction --
-type IntegrationContextAction interface {
+// Action --
+type Action interface {
 
        // a user friendly name for the action
        Name() string
diff --git a/pkg/stub/action/context/build.go b/pkg/stub/action/context/build.go
index a0ab58f..875114b 100644
--- a/pkg/stub/action/context/build.go
+++ b/pkg/stub/action/context/build.go
@@ -15,12 +15,11 @@ See the License for the specific language governing 
permissions and
 limitations under the License.
 */
 
-package action
+package context
 
 import (
        "context"
-       "github.com/apache/camel-k/pkg/build/assemble"
-       "github.com/apache/camel-k/pkg/build/publish"
+       "github.com/apache/camel-k/pkg/platform"
 
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 
@@ -31,49 +30,52 @@ import (
        "github.com/apache/camel-k/pkg/build"
 )
 
-// NewIntegrationContextBuildAction creates a new build handling action for 
the context
-func NewIntegrationContextBuildAction(ctx context.Context, namespace string) 
IntegrationContextAction {
-       assembler := assemble.NewMavenAssembler(ctx)
-       publisher := publish.NewS2IIncrementalPublisher(ctx, namespace, 
newContextLister(namespace))
-       manager := build.NewManager(ctx, assembler, publisher)
-
-       return &integrationContextBuildAction{
-               buildManager: manager,
+// NewBuildAction creates a new build handling action for the context
+func NewBuildAction(ctx context.Context) Action {
+       return &buildAction{
+               ctx,
        }
 }
 
-type integrationContextBuildAction struct {
-       buildManager *build.Manager
+type buildAction struct {
+       context.Context
 }
 
-func (action *integrationContextBuildAction) Name() string {
+func (action *buildAction) Name() string {
        return "build"
 }
 
-func (action *integrationContextBuildAction) CanHandle(context 
*v1alpha1.IntegrationContext) bool {
+func (action *buildAction) CanHandle(context *v1alpha1.IntegrationContext) 
bool {
        return context.Status.Phase == v1alpha1.IntegrationContextPhaseBuilding
 }
 
-func (action *integrationContextBuildAction) Handle(context 
*v1alpha1.IntegrationContext) error {
+func (action *buildAction) Handle(context *v1alpha1.IntegrationContext) error {
+       buildManager, err := platform.GetPlatformBuildManager(action.Context, 
context.Namespace)
+       if err != nil {
+               return err
+       }
+
        buildIdentifier := build.Identifier{
                Name:      "context-" + context.Name,
                Qualifier: context.ResourceVersion,
        }
 
-       buildResult := action.buildManager.Get(buildIdentifier)
+       buildResult := buildManager.Get(buildIdentifier)
        if buildResult.Status == build.StatusNotRequested {
-               action.buildManager.Start(build.Request{
+               buildManager.Start(build.Request{
                        Identifier:   buildIdentifier,
                        Dependencies: context.Spec.Dependencies,
                })
                logrus.Info("Build started")
        } else if buildResult.Status == build.StatusError {
                target := context.DeepCopy()
+               logrus.Info("Context ", target.Name, " transitioning to state 
", v1alpha1.IntegrationContextPhaseError)
                target.Status.Phase = v1alpha1.IntegrationContextPhaseError
                return sdk.Update(target)
        } else if buildResult.Status == build.StatusCompleted {
                target := context.DeepCopy()
                target.Status.Image = buildResult.Image
+               logrus.Info("Context ", target.Name, " transitioning to state 
", v1alpha1.IntegrationContextPhaseReady)
                target.Status.Phase = v1alpha1.IntegrationContextPhaseReady
 
                target.Status.Classpath = make([]string, 
len(buildResult.Classpath))
@@ -93,7 +95,7 @@ func (action *integrationContextBuildAction) Handle(context 
*v1alpha1.Integratio
 }
 
 // informIntegrations triggers the processing of all integrations waiting for 
this context to be built
-func (action *integrationContextBuildAction) informIntegrations(context 
*v1alpha1.IntegrationContext) error {
+func (action *buildAction) informIntegrations(context 
*v1alpha1.IntegrationContext) error {
        list := v1alpha1.NewIntegrationList()
        err := sdk.List(context.Namespace, &list, 
sdk.WithListOptions(&metav1.ListOptions{}))
        if err != nil {
@@ -116,37 +118,4 @@ func (action *integrationContextBuildAction) 
informIntegrations(context *v1alpha
        return nil
 }
 
-// =================================================================
-
-type contextLister struct {
-       namespace string
-}
-
-func newContextLister(namespace string) contextLister {
-       return contextLister{
-               namespace: namespace,
-       }
-}
-
-func (l contextLister) ListPublishedImages() ([]publish.PublishedImage, error) 
{
-       list := v1alpha1.NewIntegrationContextList()
-       err := sdk.List(l.namespace, &list, 
sdk.WithListOptions(&metav1.ListOptions{}))
-       if err != nil {
-               return nil, err
-       }
-       images := make([]publish.PublishedImage, 0)
-       for _, ctx := range list.Items {
-               if ctx.Status.Phase != v1alpha1.IntegrationContextPhaseReady || 
ctx.Labels == nil {
-                       continue
-               }
-               if ctxType, present := 
ctx.Labels["camel.apache.org/context.type"]; !present || ctxType != "platform" {
-                       continue
-               }
 
-               images = append(images, publish.PublishedImage{
-                       Image:     ctx.Status.Image,
-                       Classpath: ctx.Status.Classpath,
-               })
-       }
-       return images, nil
-}
diff --git a/pkg/stub/action/context/initialize.go 
b/pkg/stub/action/context/initialize.go
index 64d7647..6f7108e 100644
--- a/pkg/stub/action/context/initialize.go
+++ b/pkg/stub/action/context/initialize.go
@@ -15,34 +15,43 @@ See the License for the specific language governing 
permissions and
 limitations under the License.
 */
 
-package action
+package context
 
 import (
        "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+       "github.com/apache/camel-k/pkg/platform"
        "github.com/apache/camel-k/pkg/util/digest"
        "github.com/operator-framework/operator-sdk/pkg/sdk"
+       "github.com/sirupsen/logrus"
 )
 
-// NewIntegrationContextInitializeAction creates a new initialization handling 
action for the context
-func NewIntegrationContextInitializeAction() IntegrationContextAction {
-       return &integrationContextInitializeAction{}
+// NewInitializeAction creates a new initialization handling action for the 
context
+func NewInitializeAction() Action {
+       return &initializeAction{}
 }
 
-type integrationContextInitializeAction struct {
+type initializeAction struct {
 }
 
-func (action *integrationContextInitializeAction) Name() string {
+func (action *initializeAction) Name() string {
        return "initialize"
 }
 
-func (action *integrationContextInitializeAction) CanHandle(context 
*v1alpha1.IntegrationContext) bool {
+func (action *initializeAction) CanHandle(context 
*v1alpha1.IntegrationContext) bool {
        return context.Status.Phase == ""
 }
 
-func (action *integrationContextInitializeAction) Handle(context 
*v1alpha1.IntegrationContext) error {
+func (action *initializeAction) Handle(context *v1alpha1.IntegrationContext) 
error {
+       // The integration platform needs to be initialized before starting to 
create contexts
+       if _, err := platform.GetCurrentPlatform(context.Namespace); err != nil 
{
+               logrus.Info("Waiting for a integration platform to be 
initialized")
+               return nil
+       }
+
        target := context.DeepCopy()
 
        // update the status
+       logrus.Info("Context ", target.Name, " transitioning to state ", 
v1alpha1.IntegrationContextPhaseBuilding)
        target.Status.Phase = v1alpha1.IntegrationContextPhaseBuilding
        target.Status.Digest = digest.ComputeForIntegrationContext(context)
 
diff --git a/pkg/stub/action/context/monitor.go 
b/pkg/stub/action/context/monitor.go
index e30a1ea..f090ffb 100644
--- a/pkg/stub/action/context/monitor.go
+++ b/pkg/stub/action/context/monitor.go
@@ -15,7 +15,7 @@ See the License for the specific language governing 
permissions and
 limitations under the License.
 */
 
-package action
+package context
 
 import (
        "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
@@ -24,29 +24,30 @@ import (
        "github.com/sirupsen/logrus"
 )
 
-// NewIntegrationContextMonitorAction creates a new monitoring handling action 
for the context
-func NewIntegrationContextMonitorAction() IntegrationContextAction {
-       return &integrationContextMonitorAction{}
+// NewMonitorAction creates a new monitoring handling action for the context
+func NewMonitorAction() Action {
+       return &monitorAction{}
 }
 
-type integrationContextMonitorAction struct {
+type monitorAction struct {
 }
 
-func (action *integrationContextMonitorAction) Name() string {
+func (action *monitorAction) Name() string {
        return "monitor"
 }
 
-func (action *integrationContextMonitorAction) CanHandle(context 
*v1alpha1.IntegrationContext) bool {
+func (action *monitorAction) CanHandle(context *v1alpha1.IntegrationContext) 
bool {
        return context.Status.Phase == v1alpha1.IntegrationContextPhaseReady || 
context.Status.Phase == v1alpha1.IntegrationContextPhaseError
 }
 
-func (action *integrationContextMonitorAction) Handle(context 
*v1alpha1.IntegrationContext) error {
+func (action *monitorAction) 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
+               logrus.Info("Context ", target.Name, " transitioning to state 
", v1alpha1.IntegrationContextPhaseBuilding)
                target.Status.Phase = v1alpha1.IntegrationContextPhaseBuilding
                return sdk.Update(target)
        }
diff --git a/pkg/stub/action/integration/action.go 
b/pkg/stub/action/integration/action.go
index 9e4a69c..729ec5c 100644
--- a/pkg/stub/action/integration/action.go
+++ b/pkg/stub/action/integration/action.go
@@ -15,14 +15,14 @@ See the License for the specific language governing 
permissions and
 limitations under the License.
 */
 
-package action
+package integration
 
 import (
        "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
 )
 
-// IntegrationAction --
-type IntegrationAction interface {
+// Action --
+type Action interface {
 
        // a user friendly name for the action
        Name() string
diff --git a/pkg/stub/action/integration/build.go 
b/pkg/stub/action/integration/build.go
index 20cd506..e107642 100644
--- a/pkg/stub/action/integration/build.go
+++ b/pkg/stub/action/integration/build.go
@@ -15,10 +15,11 @@ See the License for the specific language governing 
permissions and
 limitations under the License.
 */
 
-package action
+package integration
 
 import (
        "fmt"
+       "github.com/sirupsen/logrus"
 
        "github.com/apache/camel-k/pkg/util"
        "github.com/apache/camel-k/pkg/util/digest"
@@ -30,7 +31,7 @@ import (
 )
 
 // NewBuildAction create an action that handles integration build
-func NewBuildAction(namespace string) IntegrationAction {
+func NewBuildAction(namespace string) Action {
        return &buildAction{
                namespace: namespace,
        }
@@ -76,6 +77,7 @@ func (action *buildAction) Handle(integration 
*v1alpha1.Integration) error {
                        target := integration.DeepCopy()
                        target.Status.Image = ctx.Status.Image
                        target.Spec.Context = ctx.Name
+                       logrus.Info("Integration ", target.Name, " 
transitioning to state ", v1alpha1.IntegrationPhaseDeploying)
                        target.Status.Phase = v1alpha1.IntegrationPhaseDeploying
                        target.Status.Digest = 
digest.ComputeForIntegration(target)
                        return sdk.Update(target)
diff --git a/pkg/stub/action/integration/deploy.go 
b/pkg/stub/action/integration/deploy.go
index a679bbd..8067b3c 100644
--- a/pkg/stub/action/integration/deploy.go
+++ b/pkg/stub/action/integration/deploy.go
@@ -15,10 +15,11 @@ See the License for the specific language governing 
permissions and
 limitations under the License.
 */
 
-package action
+package integration
 
 import (
        "fmt"
+       "github.com/sirupsen/logrus"
        "strings"
 
        "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
@@ -31,7 +32,7 @@ import (
 )
 
 // NewDeployAction create an action that handles integration deploy
-func NewDeployAction() IntegrationAction {
+func NewDeployAction() Action {
        return &deployAction{}
 }
 
@@ -60,7 +61,11 @@ func (action *deployAction) Handle(integration 
*v1alpha1.Integration) error {
                return err
        }
 
-       return nil
+       target := integration.DeepCopy()
+       logrus.Info("Integration ", target.Name, " transitioning to state ", 
v1alpha1.IntegrationPhaseRunning)
+       target.Status.Phase = v1alpha1.IntegrationPhaseRunning
+
+       return sdk.Update(target)
 }
 
 // **********************************
@@ -313,8 +318,5 @@ func createOrUpdateDeployment(ctx 
*v1alpha1.IntegrationContext, integration *v1a
                return errors.Wrap(err, "could not create or replace deployment 
for integration "+integration.Name)
        }
 
-       target := integration.DeepCopy()
-       target.Status.Phase = v1alpha1.IntegrationPhaseRunning
-
-       return sdk.Update(target)
+       return nil
 }
diff --git a/pkg/stub/action/integration/initialize.go 
b/pkg/stub/action/integration/initialize.go
index 44bac89..d9ab6c0 100644
--- a/pkg/stub/action/integration/initialize.go
+++ b/pkg/stub/action/integration/initialize.go
@@ -15,9 +15,11 @@ See the License for the specific language governing 
permissions and
 limitations under the License.
 */
 
-package action
+package integration
 
 import (
+       "github.com/apache/camel-k/pkg/platform"
+       "github.com/sirupsen/logrus"
        "sort"
 
        "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
@@ -27,7 +29,7 @@ import (
 )
 
 // NewInitializeAction creates a new inititialize action
-func NewInitializeAction() IntegrationAction {
+func NewInitializeAction() Action {
        return &initializeAction{}
 }
 
@@ -46,6 +48,12 @@ func (action *initializeAction) CanHandle(integration 
*v1alpha1.Integration) boo
 
 // Handle handles the integratios
 func (action *initializeAction) Handle(integration *v1alpha1.Integration) 
error {
+       // The integration platform needs to be ready before starting to create 
integrations
+       if pl, err := platform.GetCurrentPlatform(integration.Namespace); err 
!= nil || pl.Status.Phase != v1alpha1.IntegrationPlatformPhaseReady {
+               logrus.Info("Waiting for a integration platform to be ready")
+               return nil
+       }
+
        target := integration.DeepCopy()
        // set default values
        if target.Spec.Replicas == nil {
@@ -67,6 +75,7 @@ func (action *initializeAction) Handle(integration 
*v1alpha1.Integration) error
        // sort the dependencies to get always the same list if they don't 
change
        sort.Strings(target.Spec.Dependencies)
        // update the status
+       logrus.Info("Integration ", target.Name, " transitioning to state ", 
v1alpha1.IntegrationPhaseBuilding)
        target.Status.Phase = v1alpha1.IntegrationPhaseBuilding
        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 483212e..ebdb420 100644
--- a/pkg/stub/action/integration/monitor.go
+++ b/pkg/stub/action/integration/monitor.go
@@ -15,7 +15,7 @@ See the License for the specific language governing 
permissions and
 limitations under the License.
 */
 
-package action
+package integration
 
 import (
        "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
@@ -25,7 +25,7 @@ import (
 )
 
 // NewMonitorAction creates a new monitoring action for an integration
-func NewMonitorAction() IntegrationAction {
+func NewMonitorAction() Action {
        return &monitorAction{}
 }
 
@@ -49,6 +49,7 @@ func (action *monitorAction) Handle(integration 
*v1alpha1.Integration) error {
 
                target := integration.DeepCopy()
                target.Status.Digest = hash
+               logrus.Info("Integration ", target.Name, " transitioning to 
state ", v1alpha1.IntegrationPhaseBuilding)
                target.Status.Phase = v1alpha1.IntegrationPhaseBuilding
                return sdk.Update(target)
        }
diff --git a/pkg/stub/action/integration/util.go 
b/pkg/stub/action/integration/util.go
index 33c3787..ab9cf79 100644
--- a/pkg/stub/action/integration/util.go
+++ b/pkg/stub/action/integration/util.go
@@ -1,4 +1,21 @@
-package action
+/*
+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 integration
 
 import (
        "fmt"
diff --git a/pkg/stub/action/context/action.go 
b/pkg/stub/action/platform/action.go
similarity index 82%
copy from pkg/stub/action/context/action.go
copy to pkg/stub/action/platform/action.go
index 23b0f10..cb9ba4c 100644
--- a/pkg/stub/action/context/action.go
+++ b/pkg/stub/action/platform/action.go
@@ -15,21 +15,20 @@ See the License for the specific language governing 
permissions and
 limitations under the License.
 */
 
-package action
+package platform
 
 import (
        "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
 )
 
-// IntegrationContextAction --
-type IntegrationContextAction interface {
-
+// Action --
+type Action interface {
        // a user friendly name for the action
        Name() string
 
        // returns true if the action can handle the integration context
-       CanHandle(integration *v1alpha1.IntegrationContext) bool
+       CanHandle(platform *v1alpha1.IntegrationPlatform) bool
 
        // executes the handling function
-       Handle(integration *v1alpha1.IntegrationContext) error
+       Handle(platform *v1alpha1.IntegrationPlatform) error
 }
diff --git a/pkg/stub/action/platform/create.go 
b/pkg/stub/action/platform/create.go
new file mode 100644
index 0000000..c313ccf
--- /dev/null
+++ b/pkg/stub/action/platform/create.go
@@ -0,0 +1,54 @@
+/*
+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 platform
+
+import (
+       "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+       "github.com/apache/camel-k/pkg/install"
+       "github.com/operator-framework/operator-sdk/pkg/sdk"
+       "github.com/sirupsen/logrus"
+)
+
+// NewCreateAction returns a action that creates resources needed by the 
platform
+func NewCreateAction() Action {
+       return &createAction{}
+}
+
+type createAction struct {
+}
+
+func (action *createAction) Name() string {
+       return "create"
+}
+
+func (action *createAction) CanHandle(platform *v1alpha1.IntegrationPlatform) 
bool {
+       return platform.Status.Phase == 
v1alpha1.IntegrationPlatformPhaseCreating
+}
+
+func (action *createAction) Handle(platform *v1alpha1.IntegrationPlatform) 
error {
+       err := install.Resources(platform.Namespace, 
"platform-integration-context-core.yaml", 
"platform-integration-context-groovy.yaml")
+       if err != nil {
+               return err
+       }
+
+       target := platform.DeepCopy()
+       logrus.Info("Platform ", target.Name, " transitioning to state ", 
v1alpha1.IntegrationPlatformPhaseStarting)
+       target.Status.Phase = v1alpha1.IntegrationPlatformPhaseStarting
+
+       return sdk.Update(target)
+}
diff --git a/pkg/stub/action/platform/initialize.go 
b/pkg/stub/action/platform/initialize.go
new file mode 100644
index 0000000..4215daa
--- /dev/null
+++ b/pkg/stub/action/platform/initialize.go
@@ -0,0 +1,112 @@
+/*
+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 platform
+
+import (
+       "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+       platformutils "github.com/apache/camel-k/pkg/platform"
+       "github.com/operator-framework/operator-sdk/pkg/k8sclient"
+       "github.com/operator-framework/operator-sdk/pkg/sdk"
+       "github.com/sirupsen/logrus"
+       "k8s.io/apimachinery/pkg/api/errors"
+)
+
+// NewInitializeAction returns a action that initializes the platform 
configuration when not provided by the user
+func NewInitializeAction() Action {
+       return &initializeAction{}
+}
+
+type initializeAction struct {
+}
+
+func (action *initializeAction) Name() string {
+       return "initialize"
+}
+
+func (action *initializeAction) CanHandle(platform 
*v1alpha1.IntegrationPlatform) bool {
+       return platform.Status.Phase == "" || platform.Status.Phase == 
v1alpha1.IntegrationPlatformPhaseDuplicate
+}
+
+func (action *initializeAction) Handle(platform *v1alpha1.IntegrationPlatform) 
error {
+       target := platform.DeepCopy()
+
+       duplicate, err := action.isDuplicate(platform)
+       if err != nil {
+               return err
+       }
+       if duplicate {
+               // another platform already present in the namespace
+               if platform.Status.Phase != 
v1alpha1.IntegrationPlatformPhaseDuplicate {
+                       target := platform.DeepCopy()
+                       logrus.Info("Platform ", target.Name, " transitioning 
to state ", v1alpha1.IntegrationPlatformPhaseDuplicate)
+                       target.Status.Phase = 
v1alpha1.IntegrationPlatformPhaseDuplicate
+                       return sdk.Update(target)
+               }
+               return nil
+       }
+
+       // update missing fields in the resource
+       if target.Spec.Cluster == "" {
+               // determine the kind of cluster the platform in installed into
+               if openshift, err := action.isOpenshift(); err != nil {
+                       return err
+               } else if openshift {
+                       target.Spec.Cluster = 
v1alpha1.IntegrationPlatformClusterOpenShift
+               } else {
+                       target.Spec.Cluster = 
v1alpha1.IntegrationPlatformClusterKubernetes
+               }
+       }
+
+       if target.Spec.Build.PublishStrategy == "" {
+               if target.Spec.Cluster == 
v1alpha1.IntegrationPlatformClusterOpenShift {
+                       target.Spec.Build.PublishStrategy = 
v1alpha1.IntegrationPlatformBuildPublishStrategyS2I
+               } else {
+                       target.Spec.Build.PublishStrategy = 
v1alpha1.IntegrationPlatformBuildPublishStrategyKaniko
+                       // TODO discover registry location
+               }
+       }
+
+       // next status
+       logrus.Info("Platform ", target.Name, " transitioning to state ", 
v1alpha1.IntegrationPlatformPhaseCreating)
+       target.Status.Phase = v1alpha1.IntegrationPlatformPhaseCreating
+       return sdk.Update(target)
+}
+
+func (action *initializeAction) isOpenshift() (bool, error) {
+       _, err := 
k8sclient.GetKubeClient().Discovery().ServerResourcesForGroupVersion("image.openshift.io/v1")
+       if err != nil && errors.IsNotFound(err) {
+               return false, nil
+       } else if err != nil {
+               return false, err
+       }
+       return true, nil
+}
+
+func (action *initializeAction) isDuplicate(thisPlatform 
*v1alpha1.IntegrationPlatform) (bool, error) {
+       platforms, err := platformutils.ListPlatforms(thisPlatform.Namespace)
+       if err != nil {
+               return false, err
+       }
+       for _, platform := range platforms.Items {
+               if platform.Name != thisPlatform.Name && 
platformutils.IsActive(&platform) {
+                       return true, nil
+               }
+       }
+
+       return false, nil
+}
diff --git a/pkg/stub/action/platform/start.go 
b/pkg/stub/action/platform/start.go
new file mode 100644
index 0000000..e56ba09
--- /dev/null
+++ b/pkg/stub/action/platform/start.go
@@ -0,0 +1,79 @@
+/*
+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 platform
+
+import (
+       "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+       "github.com/operator-framework/operator-sdk/pkg/sdk"
+       "github.com/sirupsen/logrus"
+)
+
+// NewStartAction returns a action that waits for all required platform 
resources to start
+func NewStartAction() Action {
+       return &startAction{}
+}
+
+type startAction struct {
+}
+
+func (action *startAction) Name() string {
+       return "start"
+}
+
+func (action *startAction) CanHandle(platform *v1alpha1.IntegrationPlatform) 
bool {
+       return platform.Status.Phase == 
v1alpha1.IntegrationPlatformPhaseStarting || platform.Status.Phase == 
v1alpha1.IntegrationPlatformPhaseError
+}
+
+func (action *startAction) Handle(platform *v1alpha1.IntegrationPlatform) 
error {
+
+       coreStatus, err := action.getContextReady(platform.Namespace, "core")
+       if err != nil {
+               return err
+       }
+
+       groovyStatus, err := action.getContextReady(platform.Namespace, 
"groovy")
+       if err != nil {
+               return err
+       }
+
+       if coreStatus == v1alpha1.IntegrationContextPhaseError || groovyStatus 
== v1alpha1.IntegrationContextPhaseError {
+               if platform.Status.Phase != 
v1alpha1.IntegrationPlatformPhaseError {
+                       target := platform.DeepCopy()
+                       logrus.Info("Platform ", target.Name, " transitioning 
to state ", v1alpha1.IntegrationPlatformPhaseError)
+                       target.Status.Phase = 
v1alpha1.IntegrationPlatformPhaseError
+                       return sdk.Update(target)
+               }
+               return nil
+       } else if coreStatus == v1alpha1.IntegrationContextPhaseReady && 
groovyStatus == v1alpha1.IntegrationContextPhaseReady {
+               target := platform.DeepCopy()
+               logrus.Info("Platform ", target.Name, " transitioning to state 
", v1alpha1.IntegrationPlatformPhaseReady)
+               target.Status.Phase = v1alpha1.IntegrationPlatformPhaseReady
+               return sdk.Update(target)
+       }
+
+       // wait
+       return nil
+}
+
+func (action *startAction) getContextReady(namespace string, name string) 
(v1alpha1.IntegrationContextPhase, error) {
+       ctx := v1alpha1.NewIntegrationContext(namespace, name)
+       if err := sdk.Get(&ctx); err != nil {
+               return "", err
+       }
+       return ctx.Status.Phase, nil
+}
diff --git a/pkg/stub/handler.go b/pkg/stub/handler.go
index cb78d7b..18ae691 100644
--- a/pkg/stub/handler.go
+++ b/pkg/stub/handler.go
@@ -18,44 +18,50 @@ limitations under the License.
 package stub
 
 import (
-       "context"
-
+       ctx "context"
        "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+       "github.com/apache/camel-k/pkg/stub/action/platform"
 
-       caction "github.com/apache/camel-k/pkg/stub/action/context"
-       iaction "github.com/apache/camel-k/pkg/stub/action/integration"
+       "github.com/apache/camel-k/pkg/stub/action/context"
+       "github.com/apache/camel-k/pkg/stub/action/integration"
        "github.com/operator-framework/operator-sdk/pkg/sdk"
        "github.com/sirupsen/logrus"
 )
 
 // NewHandler --
-func NewHandler(ctx context.Context, namespace string) sdk.Handler {
+func NewHandler(ctx ctx.Context, namespace string) sdk.Handler {
        return &handler{
-               integrationActionPool: []iaction.IntegrationAction{
-                       iaction.NewInitializeAction(),
-                       iaction.NewBuildAction(namespace),
-                       iaction.NewDeployAction(),
-                       iaction.NewMonitorAction(),
+               integrationActionPool: []integration.Action{
+                       integration.NewInitializeAction(),
+                       integration.NewBuildAction(namespace),
+                       integration.NewDeployAction(),
+                       integration.NewMonitorAction(),
+               },
+               integrationContextActionPool: []context.Action{
+                       context.NewInitializeAction(),
+                       context.NewBuildAction(ctx),
+                       context.NewMonitorAction(),
                },
-               integrationContextActionPool: 
[]caction.IntegrationContextAction{
-                       caction.NewIntegrationContextInitializeAction(),
-                       caction.NewIntegrationContextBuildAction(ctx, 
namespace),
-                       caction.NewIntegrationContextMonitorAction(),
+               integrationPlatformActionPool: []platform.Action{
+                       platform.NewInitializeAction(),
+                       platform.NewCreateAction(),
+                       platform.NewStartAction(),
                },
        }
 }
 
 type handler struct {
-       integrationActionPool        []iaction.IntegrationAction
-       integrationContextActionPool []caction.IntegrationContextAction
+       integrationActionPool         []integration.Action
+       integrationContextActionPool  []context.Action
+       integrationPlatformActionPool []platform.Action
 }
 
-func (h *handler) Handle(ctx context.Context, event sdk.Event) error {
+func (h *handler) Handle(ctx ctx.Context, event sdk.Event) error {
        switch o := event.Object.(type) {
        case *v1alpha1.Integration:
                for _, a := range h.integrationActionPool {
                        if a.CanHandle(o) {
-                               logrus.Info("Invoking action ", a.Name(), " on 
integration ", o.Name)
+                               logrus.Debug("Invoking action ", a.Name(), " on 
integration ", o.Name)
                                if err := a.Handle(o); err != nil {
                                        return err
                                }
@@ -64,7 +70,16 @@ func (h *handler) Handle(ctx context.Context, event 
sdk.Event) error {
        case *v1alpha1.IntegrationContext:
                for _, a := range h.integrationContextActionPool {
                        if a.CanHandle(o) {
-                               logrus.Info("Invoking action ", a.Name(), " on 
context ", o.Name)
+                               logrus.Debug("Invoking action ", a.Name(), " on 
context ", o.Name)
+                               if err := a.Handle(o); err != nil {
+                                       return err
+                               }
+                       }
+               }
+       case *v1alpha1.IntegrationPlatform:
+               for _, a := range h.integrationPlatformActionPool {
+                       if a.CanHandle(o) {
+                               logrus.Debug("Invoking action ", a.Name(), " on 
platform ", o.Name)
                                if err := a.Handle(o); err != nil {
                                        return err
                                }
diff --git a/pkg/util/openshift/register.go b/pkg/util/openshift/register.go
index 83b08aa..373e42e 100644
--- a/pkg/util/openshift/register.go
+++ b/pkg/util/openshift/register.go
@@ -29,7 +29,7 @@ import (
        "k8s.io/apimachinery/pkg/runtime"
 )
 
-// Register all Openshift types that we want to manage.
+// Register all OpenShift types that we want to manage.
 func init() {
        k8sutil.AddToSDKScheme(addKnownTypes)
 }

Reply via email to