Merge pull request #1175 from aiordache/kube_context_create

Refactor kubernetes context create
This commit is contained in:
Guillaume Tardif 2021-01-26 17:09:03 +01:00 committed by GitHub
commit 0d778fbf48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 138 additions and 21 deletions

View File

@ -57,7 +57,8 @@ type EcsContext struct {
// KubeContext is the context for a kube backend // KubeContext is the context for a kube backend
type KubeContext struct { type KubeContext struct {
Endpoint string `json:",omitempty"` ContextName string `json:",omitempty"`
KubeconfigPath string `json:",omitempty"`
FromEnvironment bool FromEnvironment bool
} }

View File

@ -57,7 +57,7 @@ const (
LocalContextType = "local" LocalContextType = "local"
// KubeContextType is the endpoint key in the context endpoints for a new // KubeContextType is the endpoint key in the context endpoints for a new
// kube backend // kube backend
KubeContextType = "kubernetes" KubeContextType = "kube"
) )
const ( const (

View File

@ -33,8 +33,8 @@ func init() {
extraCommands = append(extraCommands, createKubeCommand) extraCommands = append(extraCommands, createKubeCommand)
extraHelp = append(extraHelp, ` extraHelp = append(extraHelp, `
Create a Kubernetes context: Create a Kubernetes context:
$ docker context create kubernetes CONTEXT [flags] $ docker context create k8s CONTEXT [flags]
(see docker context create kubernetes --help) (see docker context create k8s --help)
`) `)
} }
@ -45,18 +45,13 @@ func createKubeCommand() *cobra.Command {
Short: "Create context for a Kubernetes Cluster", Short: "Create context for a Kubernetes Cluster",
Args: cobra.ExactArgs(1), Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
opts.Name = args[0]
if opts.Endpoint != "" {
opts.FromEnvironment = false
}
return runCreateKube(cmd.Context(), args[0], opts) return runCreateKube(cmd.Context(), args[0], opts)
}, },
} }
addDescriptionFlag(cmd, &opts.Description) addDescriptionFlag(cmd, &opts.Description)
cmd.Flags().StringVar(&opts.Endpoint, "endpoint", "", "The endpoint of the Kubernetes manager") cmd.Flags().StringVar(&opts.KubeconfigPath, "kubeconfig", "", "The endpoint of the Kubernetes manager")
cmd.Flags().BoolVar(&opts.FromEnvironment, "from-env", true, "Get endpoint and creds from env vars") cmd.Flags().BoolVar(&opts.FromEnvironment, "from-env", false, "Get endpoint and creds from env vars")
return cmd return cmd
} }
@ -65,13 +60,9 @@ func runCreateKube(ctx context.Context, contextName string, opts kube.ContextPar
return errors.Wrapf(errdefs.ErrAlreadyExists, "context %q", contextName) return errors.Wrapf(errdefs.ErrAlreadyExists, "context %q", contextName)
} }
contextData, description := createContextData(opts) contextData, description, err := opts.CreateContextData()
if err != nil {
return err
}
return createDockerContext(ctx, contextName, store.KubeContextType, description, contextData) return createDockerContext(ctx, contextName, store.KubeContextType, description, contextData)
} }
func createContextData(opts kube.ContextParams) (interface{}, string) {
return store.KubeContext{
Endpoint: opts.Endpoint,
FromEnvironment: opts.FromEnvironment,
}, opts.Description
}

1
go.mod
View File

@ -64,6 +64,7 @@ require (
helm.sh/helm/v3 v3.5.0 helm.sh/helm/v3 v3.5.0
k8s.io/api v0.20.1 k8s.io/api v0.20.1
k8s.io/apimachinery v0.20.1 k8s.io/apimachinery v0.20.1
k8s.io/client-go v0.20.1
sigs.k8s.io/kustomize/kyaml v0.10.5 sigs.k8s.io/kustomize/kyaml v0.10.5
) )

View File

@ -0,0 +1,50 @@
// +build kube
/*
Copyright 2020 Docker Compose CLI 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 kubernetes
import (
"fmt"
"os"
"k8s.io/client-go/tools/clientcmd"
)
func ListAvailableKubeConfigContexts(kubeconfig string) ([]string, error) {
config, err := clientcmd.NewDefaultPathOptions().GetStartingConfig()
if err != nil {
return nil, err
}
if kubeconfig != "" {
f, err := os.Stat(kubeconfig)
if os.IsNotExist(err) {
return nil, err
}
if f.IsDir() {
return nil, fmt.Errorf("%s not a config file", kubeconfig)
}
config = clientcmd.GetConfigFromFileOrDie(kubeconfig)
}
contexts := []string{}
for k := range config.Contexts {
contexts = append(contexts, k)
}
return contexts, nil
}

View File

@ -18,10 +18,84 @@
package kube package kube
import (
"github.com/AlecAivazis/survey/v2/terminal"
"github.com/docker/compose-cli/api/context/store"
"github.com/docker/compose-cli/api/errdefs"
"github.com/docker/compose-cli/utils/prompt"
"github.com/docker/compose-cli/kube/charts/kubernetes"
)
// ContextParams options for creating a Kubernetes context // ContextParams options for creating a Kubernetes context
type ContextParams struct { type ContextParams struct {
Name string ContextName string
Description string Description string
Endpoint string KubeconfigPath string
FromEnvironment bool FromEnvironment bool
} }
func (cp ContextParams) CreateContextData() (interface{}, string, error) {
if cp.FromEnvironment {
// we use the current kubectl context from a $KUBECONFIG path
return store.KubeContext{
FromEnvironment: cp.FromEnvironment,
}, cp.Description, nil
}
user := prompt.User{}
selectContext := func() error {
contexts, err := kubernetes.ListAvailableKubeConfigContexts(cp.KubeconfigPath)
if err != nil {
return err
}
selected, err := user.Select("Select kubeconfig context", contexts)
if err != nil {
if err == terminal.InterruptErr {
return errdefs.ErrCanceled
}
return err
}
cp.ContextName = contexts[selected]
return nil
}
if cp.KubeconfigPath != "" {
err := selectContext()
if err != nil {
return nil, "", err
}
} else {
// interactive
var options []string
var actions []func() error
options = append(options, "Context from kubeconfig file")
actions = append(actions, selectContext)
options = append(options, "Kubernetes environment variables")
actions = append(actions, func() error {
cp.FromEnvironment = true
return nil
})
selected, err := user.Select("Create a Docker context using:", options)
if err != nil {
if err == terminal.InterruptErr {
return nil, "", errdefs.ErrCanceled
}
return nil, "", err
}
err = actions[selected]()
if err != nil {
return nil, "", err
}
}
return store.KubeContext{
ContextName: cp.ContextName,
KubeconfigPath: cp.KubeconfigPath,
FromEnvironment: cp.FromEnvironment,
}, cp.Description, nil
}