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 d827ed238bd6a072ce5f145c62a3afc8e999a872
Author: nferraro <ni.ferr...@gmail.com>
AuthorDate: Mon Sep 10 11:19:55 2018 +0200

    Add kamel install (docker image still incomplete)
---
 build/Makefile                                     |   5 +-
 build/embed_resources.sh                           |  47 ++++++
 deploy/operator-role-binding.yaml                  |  11 ++
 deploy/{rbac.yaml => operator-role.yaml}           |  18 +--
 deploy/operator-service-account.yaml               |   4 +
 deploy/operator.yaml                               |   5 +-
 deploy/resources.go                                | 180 +++++++++++++++++++++
 deploy/user-cluster-role.yaml                      |  12 ++
 pkg/build/local/local_builder.go                   |  31 +---
 pkg/client/cmd/{get => }/get.go                    |   2 +-
 pkg/client/cmd/install.go                          |  58 +++++++
 pkg/client/cmd/root.go                             |  11 +-
 pkg/install/cluster.go                             | 124 ++++++++++++++
 pkg/install/cluster_integration_test.go            |  36 +++++
 pkg/{client/cmd/get/get.go => install/operator.go} |  59 ++++---
 pkg/util/kubernetes/customclient/customclient.go   |  44 +++++
 pkg/util/kubernetes/customclient/scheme.go         |  98 +++++++++++
 pkg/util/kubernetes/loader.go                      |  40 +++++
 18 files changed, 706 insertions(+), 79 deletions(-)

diff --git a/build/Makefile b/build/Makefile
index d8d2b7a..eb1a16c 100644
--- a/build/Makefile
+++ b/build/Makefile
@@ -1,6 +1,6 @@
 VERSION := $(shell ./build/get_version.sh)
 
-build: build-runtime build-operator build-kamel
+build: build-runtime build-embed-resources build-operator build-kamel
 
 build-operator:
        go build -o camel-k-operator ./cmd/camel-k-operator/*.go
@@ -8,6 +8,9 @@ build-operator:
 build-kamel:
        go build -o kamel ./cmd/kamel/*.go
 
+build-embed-resources:
+       ./build/embed_resources.sh deploy
+
 build-runtime:
        mvn clean install -f ./runtime/pom.xml
 
diff --git a/build/embed_resources.sh b/build/embed_resources.sh
new file mode 100755
index 0000000..3ca6385
--- /dev/null
+++ b/build/embed_resources.sh
@@ -0,0 +1,47 @@
+#!/bin/sh
+
+if [[ $# -ne 1 ]] ; then
+    echo "Error invoking embed_resources.sh: directory argument required"
+    exit 1
+fi
+
+location=$(dirname $0)
+destdir=$location/../$1
+destfile=$location/../$1/resources.go
+
+cat > $destfile << EOM
+/*
+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.
+*/
+
+// Code generated by build/embed_resources.sh. DO NOT EDIT.
+
+package deploy
+
+var Resources map[string]string
+
+func init() {
+       Resources = make(map[string]string)
+
+EOM
+
+for f in $(ls $destdir | grep ".yaml"); do
+       printf "Resources[\"$f\"] =\n\`\n" >> $destfile
+       cat $destdir/$f >> $destfile
+       printf "\n\`\n" >> $destfile
+done
+
+printf "\n}\n" >> $destfile
\ No newline at end of file
diff --git a/deploy/operator-role-binding.yaml 
b/deploy/operator-role-binding.yaml
new file mode 100644
index 0000000..eb4c712
--- /dev/null
+++ b/deploy/operator-role-binding.yaml
@@ -0,0 +1,11 @@
+kind: RoleBinding
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+  name: camel-k-operator
+subjects:
+- kind: ServiceAccount
+  name: camel-k-operator
+roleRef:
+  kind: Role
+  name: camel-k-operator
+  apiGroup: rbac.authorization.k8s.io
\ No newline at end of file
diff --git a/deploy/rbac.yaml b/deploy/operator-role.yaml
similarity index 60%
rename from deploy/rbac.yaml
rename to deploy/operator-role.yaml
index e1cb15f..7dea8d3 100644
--- a/deploy/rbac.yaml
+++ b/deploy/operator-role.yaml
@@ -1,7 +1,7 @@
 kind: Role
 apiVersion: rbac.authorization.k8s.io/v1beta1
 metadata:
-  name: camel-k
+  name: camel-k-operator
 rules:
 - apiGroups:
   - camel.apache.org
@@ -29,18 +29,4 @@ rules:
   - replicasets
   - statefulsets
   verbs:
-  - "*"
-
----
-
-kind: RoleBinding
-apiVersion: rbac.authorization.k8s.io/v1beta1
-metadata:
-  name: default-account-camel-k
-subjects:
-- kind: ServiceAccount
-  name: default
-roleRef:
-  kind: Role
-  name: camel-k
-  apiGroup: rbac.authorization.k8s.io
+  - "*"
\ No newline at end of file
diff --git a/deploy/operator-service-account.yaml 
b/deploy/operator-service-account.yaml
new file mode 100644
index 0000000..eb771aa
--- /dev/null
+++ b/deploy/operator-service-account.yaml
@@ -0,0 +1,4 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: camel-k-operator
\ No newline at end of file
diff --git a/deploy/operator.yaml b/deploy/operator.yaml
index 863b21c..265b76d 100644
--- a/deploy/operator.yaml
+++ b/deploy/operator.yaml
@@ -2,6 +2,8 @@ apiVersion: apps/v1
 kind: Deployment
 metadata:
   name: camel-k-operator
+  labels:
+    app: "camel-k"
 spec:
   replicas: 1
   selector:
@@ -12,6 +14,7 @@ spec:
       labels:
         name: camel-k-operator
     spec:
+      serviceAccountName: camel-k-operator
       containers:
         - name: camel-k-operator
           image: docker.io/apache/camel-k:0.0.1-SNAPSHOT
@@ -20,7 +23,7 @@ spec:
             name: metrics
           command:
           - camel-k-operator
-          imagePullPolicy: Always
+          imagePullPolicy: IfNotPresent
           env:
             - name: WATCH_NAMESPACE
               valueFrom:
diff --git a/deploy/resources.go b/deploy/resources.go
new file mode 100644
index 0000000..1048333
--- /dev/null
+++ b/deploy/resources.go
@@ -0,0 +1,180 @@
+/*
+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.
+*/
+
+// Code generated by build/embed_resources.sh. DO NOT EDIT.
+
+package deploy
+
+var Resources map[string]string
+
+func init() {
+       Resources = make(map[string]string)
+
+Resources["crd.yaml"] =
+`
+apiVersion: apiextensions.k8s.io/v1beta1
+kind: CustomResourceDefinition
+metadata:
+  name: integrations.camel.apache.org
+spec:
+  group: camel.apache.org
+  names:
+    kind: Integration
+    listKind: IntegrationList
+    plural: integrations
+    singular: integration
+  scope: Namespaced
+  version: v1alpha1
+
+`
+Resources["cr.yaml"] =
+`
+apiVersion: "camel.apache.org/v1alpha1"
+kind: "Integration"
+metadata:
+  name: "example"
+spec:
+  replicas: 1
+  source:
+    code: |-
+      package kamel;
+
+      import org.apache.camel.builder.RouteBuilder;
+
+      public class Routes extends RouteBuilder {
+
+          @Override
+          public void configure() throws Exception {
+              from("timer:tick")
+                .setBody(constant("Hello World!!!"))
+                .to("log:info");
+          }
+
+      }
+
+`
+Resources["operator-role-binding.yaml"] =
+`
+kind: RoleBinding
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+  name: camel-k-operator
+subjects:
+- kind: ServiceAccount
+  name: camel-k-operator
+roleRef:
+  kind: Role
+  name: camel-k-operator
+  apiGroup: rbac.authorization.k8s.io
+`
+Resources["operator-role.yaml"] =
+`
+kind: Role
+apiVersion: rbac.authorization.k8s.io/v1beta1
+metadata:
+  name: camel-k-operator
+rules:
+- apiGroups:
+  - camel.apache.org
+  resources:
+  - "*"
+  verbs:
+  - "*"
+- apiGroups:
+  - ""
+  resources:
+  - pods
+  - services
+  - endpoints
+  - persistentvolumeclaims
+  - events
+  - configmaps
+  - secrets
+  verbs:
+  - "*"
+- apiGroups:
+  - apps
+  resources:
+  - deployments
+  - daemonsets
+  - replicasets
+  - statefulsets
+  verbs:
+  - "*"
+`
+Resources["operator-service-account.yaml"] =
+`
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: camel-k-operator
+`
+Resources["operator.yaml"] =
+`
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: camel-k-operator
+  labels:
+    app: "camel-k"
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      name: camel-k-operator
+  template:
+    metadata:
+      labels:
+        name: camel-k-operator
+    spec:
+      serviceAccountName: camel-k-operator
+      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: IfNotPresent
+          env:
+            - name: WATCH_NAMESPACE
+              valueFrom:
+                fieldRef:
+                  fieldPath: metadata.namespace
+            - name: OPERATOR_NAME
+              value: "camel-k-operator"
+
+`
+Resources["user-cluster-role.yaml"] =
+`
+kind: ClusterRole
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: camel-k:edit
+  labels:
+    # Add these permissions to the "admin" and "edit" default roles.
+    rbac.authorization.k8s.io/aggregate-to-admin: "true"
+    rbac.authorization.k8s.io/aggregate-to-edit: "true"
+rules:
+- apiGroups: ["camel.apache.org"]
+  resources: ["*"]
+  verbs: ["*"]
+
+`
+
+}
diff --git a/deploy/user-cluster-role.yaml b/deploy/user-cluster-role.yaml
new file mode 100644
index 0000000..2fde6d1
--- /dev/null
+++ b/deploy/user-cluster-role.yaml
@@ -0,0 +1,12 @@
+kind: ClusterRole
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: camel-k:edit
+  labels:
+    # Add these permissions to the "admin" and "edit" default roles.
+    rbac.authorization.k8s.io/aggregate-to-admin: "true"
+    rbac.authorization.k8s.io/aggregate-to-edit: "true"
+rules:
+- apiGroups: ["camel.apache.org"]
+  resources: ["*"]
+  verbs: ["*"]
diff --git a/pkg/build/local/local_builder.go b/pkg/build/local/local_builder.go
index 98830d6..d37a56e 100644
--- a/pkg/build/local/local_builder.go
+++ b/pkg/build/local/local_builder.go
@@ -27,9 +27,6 @@ import (
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
        "k8s.io/api/core/v1"
        "github.com/operator-framework/operator-sdk/pkg/sdk"
-       "k8s.io/client-go/rest"
-       "github.com/operator-framework/operator-sdk/pkg/k8sclient"
-       "k8s.io/apimachinery/pkg/runtime/schema"
        imagev1 "github.com/openshift/api/image/v1"
        "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
        "github.com/operator-framework/operator-sdk/pkg/util/k8sutil"
@@ -39,6 +36,7 @@ import (
        "github.com/apache/camel-k/pkg/util/kubernetes"
        "github.com/apache/camel-k/version"
        "github.com/apache/camel-k/pkg/util/maven"
+       "github.com/apache/camel-k/pkg/util/kubernetes/customclient"
 )
 
 type localBuilder struct {
@@ -203,34 +201,17 @@ func (b *localBuilder) publish(tarFile string, source 
build.BuildSource) (string
                return "", errors.Wrap(err, "cannot create image stream")
        }
 
-       inConfig := k8sclient.GetKubeConfig()
-       config := rest.CopyConfig(inConfig)
-       config.GroupVersion = &schema.GroupVersion{
-               Group:   "build.openshift.io",
-               Version: "v1",
-       }
-       config.APIPath = "/apis"
-       config.AcceptContentTypes = "application/json"
-       config.ContentType = "application/json"
-
-       // this gets used for discovery and error handling types
-       config.NegotiatedSerializer = basicNegotiatedSerializer{}
-       if config.UserAgent == "" {
-               config.UserAgent = rest.DefaultKubernetesUserAgent()
-       }
-
-       restClient, err := rest.RESTClientFor(config)
+       resource, err := ioutil.ReadFile(tarFile)
        if err != nil {
-               return "", err
+               return "", errors.Wrap(err, "cannot fully read tar file 
"+tarFile)
        }
 
-       resource, err := ioutil.ReadFile(tarFile)
+       restClient, err := customclient.GetClientFor("build.openshift.io", "v1")
        if err != nil {
-               return "", errors.Wrap(err, "cannot fully read tar file 
"+tarFile)
+               return "", err
        }
 
-       result := restClient.
-               Post().
+       result := restClient.Post().
                Namespace(b.namespace).
                Body(resource).
                Resource("buildconfigs").
diff --git a/pkg/client/cmd/get/get.go b/pkg/client/cmd/get.go
similarity index 99%
copy from pkg/client/cmd/get/get.go
copy to pkg/client/cmd/get.go
index 6702145..39a45d9 100644
--- a/pkg/client/cmd/get/get.go
+++ b/pkg/client/cmd/get.go
@@ -15,7 +15,7 @@ See the License for the specific language governing 
permissions and
 limitations under the License.
 */
 
-package get
+package cmd
 
 import (
        "github.com/spf13/cobra"
diff --git a/pkg/client/cmd/install.go b/pkg/client/cmd/install.go
new file mode 100644
index 0000000..edeece4
--- /dev/null
+++ b/pkg/client/cmd/install.go
@@ -0,0 +1,58 @@
+/*
+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 (
+       "github.com/spf13/cobra"
+       installutils "github.com/apache/camel-k/pkg/install"
+       "fmt"
+       "k8s.io/apimachinery/pkg/api/errors"
+)
+
+type InstallCmdOptions struct {
+}
+
+func NewCmdInstall() *cobra.Command {
+       options := InstallCmdOptions{}
+       cmd := cobra.Command{
+               Use:   "install",
+               Short: "Install Camel K on a Kubernetes cluster",
+               Long:  `Installs Camel K on a Kubernetes or Openshift cluster.`,
+               RunE:  options.install,
+       }
+       return &cmd
+}
+
+func (o *InstallCmdOptions) install(cmd *cobra.Command, args []string) error {
+       err := installutils.SetupClusterwideResources()
+       if err != nil && errors.IsForbidden(err) {
+               // TODO explain that this is a one time operation and add a 
flag to do cluster-level operations only when logged as admin
+               fmt.Println("Current user is not authorized to create 
cluster-wide objects like custom resource definitions or cluster roles: ", err)
+               fmt.Println("Please login as cluster-admin to continue the 
installation.")
+               return nil // TODO better error handling: if here we return err 
the help page is shown
+       }
+
+       namespace := cmd.Flag("namespace").Value.String()
+
+       err = installutils.InstallOperator(namespace)
+       if err != nil {
+               return err
+       }
+       fmt.Println("Camel K installed in namespace", namespace)
+       return nil
+}
diff --git a/pkg/client/cmd/root.go b/pkg/client/cmd/root.go
index 74a8f07..4014a20 100644
--- a/pkg/client/cmd/root.go
+++ b/pkg/client/cmd/root.go
@@ -19,20 +19,22 @@ package cmd
 
 import (
        "os"
+
+       "github.com/apache/camel-k/pkg/client/cmd/run"
+       "github.com/apache/camel-k/pkg/client/cmd/version"
        "github.com/spf13/cobra"
        "github.com/apache/camel-k/pkg/client/cmd/get"
        "github.com/apache/camel-k/pkg/util/kubernetes"
        "github.com/pkg/errors"
 )
 
-type KamelCmdOptions struct {
+type rootCmdOptions struct {
        KubeConfig      string
        Namespace       string
 }
 
-
 func NewKamelCommand() (*cobra.Command, error) {
-       options := KamelCmdOptions{}
+       options := rootCmdOptions{}
        var cmd = cobra.Command{
                Use:   "kamel",
                Short: "Kamel is a awesome client tool for running Apache Camel 
integrations natively on Kubernetes",
@@ -62,7 +64,8 @@ func NewKamelCommand() (*cobra.Command, error) {
        cmd.AddCommand(NewCmdCompletion())
        cmd.AddCommand(NewCmdVersion())
        cmd.AddCommand(NewCmdRun())
-       cmd.AddCommand(get.NewCmdGet())
+       cmd.AddCommand(NewCmdGet())
+       cmd.AddCommand(NewCmdInstall())
 
        return &cmd, nil
 }
diff --git a/pkg/install/cluster.go b/pkg/install/cluster.go
new file mode 100644
index 0000000..a6b60d5
--- /dev/null
+++ b/pkg/install/cluster.go
@@ -0,0 +1,124 @@
+/*
+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 install
+
+import (
+       "github.com/operator-framework/operator-sdk/pkg/k8sclient"
+       "github.com/apache/camel-k/deploy"
+       "k8s.io/apimachinery/pkg/util/yaml"
+       "github.com/apache/camel-k/pkg/util/kubernetes/customclient"
+       "k8s.io/apimachinery/pkg/api/errors"
+       "github.com/apache/camel-k/pkg/util/kubernetes"
+       "github.com/operator-framework/operator-sdk/pkg/sdk"
+       "k8s.io/api/rbac/v1"
+       metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+func SetupClusterwideResources() error {
+       // Installing CRD
+       crdInstalled, err := isCRDInstalled()
+       if err != nil {
+               return err
+       }
+       if !crdInstalled {
+               if err := installCRD(); err != nil {
+                       return err
+               }
+       }
+
+       // Installing ClusterRole
+       clusterRoleInstalled, err := isClusterRoleInstalled()
+       if err != nil {
+               return err
+       }
+       if !clusterRoleInstalled {
+               err := installClusterRole()
+               if err != nil {
+                       return err
+               }
+       }
+
+       return nil
+}
+
+func isCRDInstalled() (bool, error) {
+       lst, err := 
k8sclient.GetKubeClient().Discovery().ServerResourcesForGroupVersion("camel.apache.org/v1alpha1")
+       if err != nil && errors.IsNotFound(err) {
+               return false, nil
+       } else if err != nil {
+               return false, err
+       }
+       for _, res := range lst.APIResources {
+               if res.Kind == "Integration" {
+                       return true, nil
+               }
+       }
+       return false, nil
+}
+
+func installCRD() error {
+       crd := []byte(deploy.Resources["crd.yaml"])
+       crdJson, err := yaml.ToJSON(crd)
+       if err != nil {
+               return err
+       }
+       restClient, err := customclient.GetClientFor("apiextensions.k8s.io", 
"v1beta1")
+       if err != nil {
+               return err
+       }
+       // Post using dynamic client
+       result := restClient.
+               Post().
+               Body(crdJson).
+               Resource("customresourcedefinitions").
+               Do()
+       // Check result
+       if result.Error() != nil && !errors.IsAlreadyExists(result.Error()) {
+               return result.Error()
+       }
+
+       return nil
+}
+
+func isClusterRoleInstalled() (bool, error) {
+       clusterRole := v1.ClusterRole{
+               TypeMeta: metav1.TypeMeta{
+                       Kind:       "ClusterRole",
+                       APIVersion: "rbac.authorization.k8s.io/v1",
+               },
+               ObjectMeta: metav1.ObjectMeta{
+                       Name: "camel-k:edit",
+               },
+       }
+       err := sdk.Get(&clusterRole)
+       if err != nil && errors.IsNotFound(err) {
+               return false, nil
+       } else if err != nil {
+               return false, err
+       }
+       return true, nil
+}
+
+func installClusterRole() error {
+       obj, err := 
kubernetes.LoadResourceFromYaml(deploy.Resources["user-cluster-role.yaml"])
+       if err != nil {
+               return err
+       }
+
+       return sdk.Create(obj)
+}
diff --git a/pkg/install/cluster_integration_test.go 
b/pkg/install/cluster_integration_test.go
new file mode 100644
index 0000000..df9f93c
--- /dev/null
+++ b/pkg/install/cluster_integration_test.go
@@ -0,0 +1,36 @@
+/*
+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 install
+
+import (
+       "testing"
+       "github.com/stretchr/testify/assert"
+)
+
+func TestInstallation(t *testing.T) {
+       err := SetupClusterwideResources()
+       assert.Nil(t, err)
+
+       installedCRD, err := isCRDInstalled()
+       assert.Nil(t, err)
+       assert.True(t, installedCRD)
+
+       installedClusterRole, err := isClusterRoleInstalled()
+       assert.Nil(t, err)
+       assert.True(t, installedClusterRole)
+}
diff --git a/pkg/client/cmd/get/get.go b/pkg/install/operator.go
similarity index 51%
rename from pkg/client/cmd/get/get.go
rename to pkg/install/operator.go
index 6702145..ad6d5d6 100644
--- a/pkg/client/cmd/get/get.go
+++ b/pkg/install/operator.go
@@ -15,50 +15,47 @@ See the License for the specific language governing 
permissions and
 limitations under the License.
 */
 
-package get
+package install
 
 import (
-       "github.com/spf13/cobra"
-       "text/tabwriter"
-       "os"
-       "fmt"
-       "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
-       metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+       "github.com/apache/camel-k/deploy"
        "github.com/operator-framework/operator-sdk/pkg/sdk"
+       "github.com/apache/camel-k/pkg/util/kubernetes"
+       "k8s.io/apimachinery/pkg/api/errors"
+       metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
-func NewCmdGet() *cobra.Command {
-       cmd := cobra.Command{
-               Use:   "get",
-               Short: "Get all integrations deployed on Kubernetes",
-               Long:  `Get the status of all integrations deployed on on 
Kubernetes.`,
-               RunE:  run,
-       }
-
-       return &cmd
+func InstallOperator(namespace string) error {
+       return installResources(namespace,
+               "operator-service-account.yaml",
+               "operator-role.yaml",
+               "operator-role-binding.yaml",
+               "operator.yaml",
+       )
 }
 
-func run(cmd *cobra.Command, args []string) error {
-       integrationList := v1alpha1.IntegrationList{
-               TypeMeta: metav1.TypeMeta{
-                       APIVersion: v1alpha1.SchemeGroupVersion.String(),
-                       Kind:       "Integration",
-               },
+func installResources(namespace string, names ...string) error {
+       for _, name := range names {
+               if err := installResource(namespace, name); err != nil {
+                       return err
+               }
        }
+       return nil
+}
 
-       namespace := cmd.Flag("namespace").Value.String()
-
-       err := sdk.List(namespace, &integrationList)
+func installResource(namespace string, name string) error {
+       obj, err := kubernetes.LoadResourceFromYaml(deploy.Resources[name])
        if err != nil {
                return err
        }
 
-       w := tabwriter.NewWriter(os.Stdout, 0, 8, 0, '\t', 0)
-       fmt.Fprintln(w, "NAME\tSTATUS")
-       for _, integration := range integrationList.Items {
-               fmt.Fprintln(w, 
integration.Name+"\t"+string(integration.Status.Phase))
+       if kObj, ok := obj.(metav1.Object); ok {
+               kObj.SetNamespace(namespace)
        }
-       w.Flush()
 
-       return nil
+       err = sdk.Create(obj)
+       if err != nil && errors.IsAlreadyExists(err) {
+               return sdk.Update(obj)
+       }
+       return err
 }
diff --git a/pkg/util/kubernetes/customclient/customclient.go 
b/pkg/util/kubernetes/customclient/customclient.go
new file mode 100644
index 0000000..9dc0735
--- /dev/null
+++ b/pkg/util/kubernetes/customclient/customclient.go
@@ -0,0 +1,44 @@
+/*
+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 customclient
+
+import (
+       "k8s.io/client-go/rest"
+       "k8s.io/apimachinery/pkg/runtime/schema"
+       "github.com/operator-framework/operator-sdk/pkg/k8sclient"
+)
+
+func GetClientFor(group string, version string) (*rest.RESTClient, error) {
+       inConfig := k8sclient.GetKubeConfig()
+       config := rest.CopyConfig(inConfig)
+       config.GroupVersion = &schema.GroupVersion{
+               Group:   group,
+               Version: version,
+       }
+       config.APIPath = "/apis"
+       config.AcceptContentTypes = "application/json"
+       config.ContentType = "application/json"
+
+       // this gets used for discovery and error handling types
+       config.NegotiatedSerializer = basicNegotiatedSerializer{}
+       if config.UserAgent == "" {
+               config.UserAgent = rest.DefaultKubernetesUserAgent()
+       }
+
+       return rest.RESTClientFor(config)
+}
diff --git a/pkg/util/kubernetes/customclient/scheme.go 
b/pkg/util/kubernetes/customclient/scheme.go
new file mode 100644
index 0000000..f20496d
--- /dev/null
+++ b/pkg/util/kubernetes/customclient/scheme.go
@@ -0,0 +1,98 @@
+/*
+Copyright 2018 The Kubernetes Authors.
+
+Licensed 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 customclient
+
+import (
+       metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+       "k8s.io/apimachinery/pkg/runtime"
+       "k8s.io/apimachinery/pkg/runtime/schema"
+       "k8s.io/apimachinery/pkg/runtime/serializer"
+       "k8s.io/apimachinery/pkg/runtime/serializer/json"
+       "k8s.io/apimachinery/pkg/runtime/serializer/versioning"
+)
+
+var watchScheme = runtime.NewScheme()
+var basicScheme = runtime.NewScheme()
+var deleteScheme = runtime.NewScheme()
+var parameterScheme = runtime.NewScheme()
+var deleteOptionsCodec = serializer.NewCodecFactory(deleteScheme)
+var dynamicParameterCodec = runtime.NewParameterCodec(parameterScheme)
+
+var versionV1 = schema.GroupVersion{Version: "v1"}
+
+func init() {
+       metav1.AddToGroupVersion(watchScheme, versionV1)
+       metav1.AddToGroupVersion(basicScheme, versionV1)
+       metav1.AddToGroupVersion(parameterScheme, versionV1)
+       metav1.AddToGroupVersion(deleteScheme, versionV1)
+}
+
+var watchJsonSerializerInfo = runtime.SerializerInfo{
+       MediaType:        "application/json",
+       EncodesAsText:    true,
+       Serializer:       json.NewSerializer(json.DefaultMetaFactory, 
watchScheme, watchScheme, false),
+       PrettySerializer: json.NewSerializer(json.DefaultMetaFactory, 
watchScheme, watchScheme, true),
+       StreamSerializer: &runtime.StreamSerializerInfo{
+               EncodesAsText: true,
+               Serializer:    json.NewSerializer(json.DefaultMetaFactory, 
watchScheme, watchScheme, false),
+               Framer:        json.Framer,
+       },
+}
+
+// watchNegotiatedSerializer is used to read the wrapper of the watch stream
+type watchNegotiatedSerializer struct{}
+
+var watchNegotiatedSerializerInstance = watchNegotiatedSerializer{}
+
+func (s watchNegotiatedSerializer) SupportedMediaTypes() 
[]runtime.SerializerInfo {
+       return []runtime.SerializerInfo{watchJsonSerializerInfo}
+}
+
+func (s watchNegotiatedSerializer) EncoderForVersion(encoder runtime.Encoder, 
gv runtime.GroupVersioner) runtime.Encoder {
+       return versioning.NewDefaultingCodecForScheme(watchScheme, encoder, 
nil, gv, nil)
+}
+
+func (s watchNegotiatedSerializer) DecoderToVersion(decoder runtime.Decoder, 
gv runtime.GroupVersioner) runtime.Decoder {
+       return versioning.NewDefaultingCodecForScheme(watchScheme, nil, 
decoder, nil, gv)
+}
+
+// basicNegotiatedSerializer is used to handle discovery and error handling 
serialization
+type basicNegotiatedSerializer struct{}
+
+func (s basicNegotiatedSerializer) SupportedMediaTypes() 
[]runtime.SerializerInfo {
+       return []runtime.SerializerInfo{
+               {
+                       MediaType:        "application/json",
+                       EncodesAsText:    true,
+                       Serializer:       
json.NewSerializer(json.DefaultMetaFactory, basicScheme, basicScheme, false),
+                       PrettySerializer: 
json.NewSerializer(json.DefaultMetaFactory, basicScheme, basicScheme, true),
+                       StreamSerializer: &runtime.StreamSerializerInfo{
+                               EncodesAsText: true,
+                               Serializer:    
json.NewSerializer(json.DefaultMetaFactory, basicScheme, basicScheme, false),
+                               Framer:        json.Framer,
+                       },
+               },
+       }
+}
+
+func (s basicNegotiatedSerializer) EncoderForVersion(encoder runtime.Encoder, 
gv runtime.GroupVersioner) runtime.Encoder {
+       return versioning.NewDefaultingCodecForScheme(watchScheme, encoder, 
nil, gv, nil)
+}
+
+func (s basicNegotiatedSerializer) DecoderToVersion(decoder runtime.Decoder, 
gv runtime.GroupVersioner) runtime.Decoder {
+       return versioning.NewDefaultingCodecForScheme(watchScheme, nil, 
decoder, nil, gv)
+}
\ No newline at end of file
diff --git a/pkg/util/kubernetes/loader.go b/pkg/util/kubernetes/loader.go
new file mode 100644
index 0000000..c1cfc5a
--- /dev/null
+++ b/pkg/util/kubernetes/loader.go
@@ -0,0 +1,40 @@
+/*
+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 kubernetes
+
+import (
+       "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
+       "github.com/operator-framework/operator-sdk/pkg/util/k8sutil"
+       "k8s.io/apimachinery/pkg/util/yaml"
+       "k8s.io/apimachinery/pkg/runtime"
+)
+
+func LoadResourceFromYaml(data string) (runtime.Object, error) {
+       role := []byte(data)
+       roleJson, err := yaml.ToJSON(role)
+       if err != nil {
+               return nil, err
+       }
+       u := unstructured.Unstructured{}
+       err = u.UnmarshalJSON(roleJson)
+       if err != nil {
+               return nil, err
+       }
+
+       return k8sutil.RuntimeObjectFromUnstructured(&u)
+}

Reply via email to