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 17c668496efe6d0de9ae785d92e9ad4511325db9 Author: nferraro <ni.ferr...@gmail.com> AuthorDate: Sat Sep 8 01:08:40 2018 +0200 Add get and detection of current namespace --- pkg/client/cmd/get/get.go | 74 +++++++++++++++++++++++++++ pkg/client/cmd/root.go | 29 +++++++++-- pkg/client/cmd/run.go | 32 ++++++------ pkg/{client/cmd => util/kubernetes}/config.go | 25 ++++----- pkg/util/kubernetes/namespace.go | 56 ++++++++++++++++++++ 5 files changed, 186 insertions(+), 30 deletions(-) diff --git a/pkg/client/cmd/get/get.go b/pkg/client/cmd/get/get.go new file mode 100644 index 0000000..925883b --- /dev/null +++ b/pkg/client/cmd/get/get.go @@ -0,0 +1,74 @@ +/* +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 get + +import ( + "github.com/spf13/cobra" + "io/ioutil" + "text/tabwriter" + "os" + "fmt" + "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "github.com/operator-framework/operator-sdk/pkg/sdk" +) + +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 run(cmd *cobra.Command, args []string) error { + integrationList := v1alpha1.IntegrationList{ + TypeMeta: metav1.TypeMeta{ + APIVersion: v1alpha1.SchemeGroupVersion.String(), + Kind: "Integration", + }, + } + + namespace := cmd.Flag("namespace").Value.String() + + err := sdk.List(namespace, &integrationList) + 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)) + } + w.Flush() + + return nil +} + +func loadCode(fileName string) (string, error) { + content, err := ioutil.ReadFile(fileName) + if err != nil { + return "", err + } + // TODO check encoding issues + return string(content), err +} diff --git a/pkg/client/cmd/root.go b/pkg/client/cmd/root.go index e49da28..74a8f07 100644 --- a/pkg/client/cmd/root.go +++ b/pkg/client/cmd/root.go @@ -18,21 +18,43 @@ limitations under the License. package cmd import ( + "os" "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 { + KubeConfig string + Namespace string +} + + func NewKamelCommand() (*cobra.Command, error) { + options := KamelCmdOptions{} var cmd = cobra.Command{ Use: "kamel", Short: "Kamel is a awesome client tool for running Apache Camel integrations natively on Kubernetes", Long: "Apache Camel K (a.k.a. Kamel) is a lightweight integration framework\nbuilt from Apache Camel that runs natively on Kubernetes and is\nspecifically designed for serverless and microservice architectures.", } - var kubeconfig string - cmd.PersistentFlags().StringVar(&kubeconfig, "config", "", "Path to the config file to use for CLI requests") + cmd.PersistentFlags().StringVar(&options.KubeConfig, "config", "", "Path to the config file to use for CLI requests") + cmd.PersistentFlags().StringVarP(&options.Namespace, "namespace", "n", "", "Namespace to use for all operations") + + // Parse the flags before setting the defaults + cmd.ParseFlags(os.Args) + + if options.Namespace == "" { + current, err := kubernetes.GetClientCurrentNamespace(options.KubeConfig) + if err != nil { + return nil, errors.Wrap(err, "cannot get current namespace") + } + cmd.Flag("namespace").Value.Set(current) + } // Initialize the Kubernetes client to allow using the operator-sdk - err := initKubeClient(&cmd) + err := kubernetes.InitKubeClient(options.KubeConfig) if err != nil { return nil, err } @@ -40,6 +62,7 @@ func NewKamelCommand() (*cobra.Command, error) { cmd.AddCommand(NewCmdCompletion()) cmd.AddCommand(NewCmdVersion()) cmd.AddCommand(NewCmdRun()) + cmd.AddCommand(get.NewCmdGet()) return &cmd, nil } diff --git a/pkg/client/cmd/run.go b/pkg/client/cmd/run.go index ca0872a..083300d 100644 --- a/pkg/client/cmd/run.go +++ b/pkg/client/cmd/run.go @@ -32,27 +32,27 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func NewCmdRun() *cobra.Command { - impl := runCmd{} +type RunCmdOptions struct { + Language string +} +func NewCmdRun() *cobra.Command { + options := RunCmdOptions{} cmd := cobra.Command{ Use: "run [file to run]", Short: "Run a integration on Kubernetes", Long: `Deploys and execute a integration pod on Kubernetes.`, - Args: impl.validateArgs, - RunE: impl.execute, + Args: options.validateArgs, + RunE: options.run, } - cmd.Flags().StringVarP(&impl.language, "language", "l", "", "Programming Language used to write the file") + cmd.Flags().StringVarP(&options.Language, "language", "l", "", "Programming Language used to write the file") + cmd.ParseFlags(os.Args) return &cmd } -type runCmd struct { - language string -} - -func (target runCmd) validateArgs(cmd *cobra.Command, args []string) error { +func (*RunCmdOptions) validateArgs(cmd *cobra.Command, args []string) error { if len(args) != 1 { return errors.New("accepts 1 arg, received " + strconv.Itoa(len(args))) } @@ -65,12 +65,14 @@ func (target runCmd) validateArgs(cmd *cobra.Command, args []string) error { return nil } -func (target runCmd) execute(cmd *cobra.Command, args []string) error { - code, err := target.loadCode(args[0]) +func (o *RunCmdOptions) run(cmd *cobra.Command, args []string) error { + code, err := o.loadCode(args[0]) if err != nil { return err } + namespace := cmd.Flag("namespace").Value.String() + name := kubernetes.SanitizeName(args[0]) if name == "" { name = "integration" @@ -78,11 +80,11 @@ func (target runCmd) execute(cmd *cobra.Command, args []string) error { integration := v1alpha1.Integration{ TypeMeta: v1.TypeMeta{ - Kind: "Integration", + Kind: "Integration", APIVersion: v1alpha1.SchemeGroupVersion.String(), }, ObjectMeta: v1.ObjectMeta{ - Namespace: "test", // TODO discover current namespace dynamically (and with command option) + Namespace: namespace, Name: name, }, Spec: v1alpha1.IntegrationSpec{ @@ -117,7 +119,7 @@ func (target runCmd) execute(cmd *cobra.Command, args []string) error { return nil } -func (target runCmd) loadCode(fileName string) (string, error) { +func (*RunCmdOptions) loadCode(fileName string) (string, error) { content, err := ioutil.ReadFile(fileName) if err != nil { return "", err diff --git a/pkg/client/cmd/config.go b/pkg/util/kubernetes/config.go similarity index 79% rename from pkg/client/cmd/config.go rename to pkg/util/kubernetes/config.go index f7b347b..f01a8de 100644 --- a/pkg/client/cmd/config.go +++ b/pkg/util/kubernetes/config.go @@ -15,26 +15,18 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package kubernetes import ( "os/user" "path/filepath" - - "github.com/operator-framework/operator-sdk/pkg/k8sclient" - "github.com/spf13/cobra" "k8s.io/client-go/tools/clientcmd" + "github.com/operator-framework/operator-sdk/pkg/k8sclient" ) -func initKubeClient(cmd *cobra.Command) error { - kubeconfig := cmd.Flag("config").Value.String() +func InitKubeClient(kubeconfig string) error { if kubeconfig == "" { - usr, err := user.Current() - if err != nil { - return err - } - - kubeconfig = filepath.Join(usr.HomeDir, ".kube", "config") + kubeconfig = GetDefaultKubeConfigFile() } // use the current context in kubeconfig @@ -46,3 +38,12 @@ func initKubeClient(cmd *cobra.Command) error { k8sclient.CustomConfig = config return nil } + +func GetDefaultKubeConfigFile() string { + usr, err := user.Current() + if err != nil { + panic(err) // TODO handle error + } + + return filepath.Join(usr.HomeDir, ".kube", "config") +} diff --git a/pkg/util/kubernetes/namespace.go b/pkg/util/kubernetes/namespace.go new file mode 100644 index 0000000..116865d --- /dev/null +++ b/pkg/util/kubernetes/namespace.go @@ -0,0 +1,56 @@ +/* +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/client-go/tools/clientcmd" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" + clientcmdlatest "k8s.io/client-go/tools/clientcmd/api/latest" + "io/ioutil" + "github.com/pkg/errors" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +func GetClientCurrentNamespace(kubeconfig string) (string, error) { + if kubeconfig == "" { + kubeconfig = GetDefaultKubeConfigFile() + } + if kubeconfig == "" { + return "default", nil + } + + data, err := ioutil.ReadFile(kubeconfig) + if err != nil { + return "", err + } + config := clientcmdapi.NewConfig() + if len(data) == 0 { + return "", errors.New("kubernetes config file is empty") + } + + decoded, _, err := clientcmdlatest.Codec.Decode(data, &schema.GroupVersionKind{Version: clientcmdlatest.Version, Kind: "Config"}, config) + if err != nil { + return "", err + } + + clientcmdconfig := decoded.(*clientcmdapi.Config) + + cc := clientcmd.NewDefaultClientConfig(*clientcmdconfig, &clientcmd.ConfigOverrides{}) + ns, _, err := cc.Namespace() + return ns, err +}