Implement kubernetes context create

Signed-off-by: aiordache <anca.iordache@docker.com>
This commit is contained in:
aiordache 2021-01-22 13:41:57 +01:00 committed by Guillaume Tardif
parent d53d437bbc
commit 849707016b
6 changed files with 139 additions and 22 deletions
api/context/store
cli/cmd/context
go.mod
kube
charts/kubernetes
context.go

View File

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

View File

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

View File

@ -33,30 +33,25 @@ func init() {
extraCommands = append(extraCommands, createKubeCommand)
extraHelp = append(extraHelp, `
Create a Kubernetes context:
$ docker context create kubernetes CONTEXT [flags]
(see docker context create kubernetes --help)
$ docker context create k8s CONTEXT [flags]
(see docker context create k8s --help)
`)
}
func createKubeCommand() *cobra.Command {
var opts kube.ContextParams
cmd := &cobra.Command{
Use: "kubernetes CONTEXT [flags]",
Use: "k8s CONTEXT [flags]",
Short: "Create context for a Kubernetes Cluster",
Args: cobra.ExactArgs(1),
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)
},
}
addDescriptionFlag(cmd, &opts.Description)
cmd.Flags().StringVar(&opts.Endpoint, "endpoint", "", "The endpoint of the Kubernetes manager")
cmd.Flags().BoolVar(&opts.FromEnvironment, "from-env", true, "Get endpoint and creds from env vars")
cmd.Flags().StringVar(&opts.KubeconfigPath, "kubeconfig", "", "The endpoint of the Kubernetes manager")
cmd.Flags().BoolVar(&opts.FromEnvironment, "from-env", false, "Get endpoint and creds from env vars")
return cmd
}
@ -65,13 +60,9 @@ func runCreateKube(ctx context.Context, contextName string, opts kube.ContextPar
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)
}
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
k8s.io/api v0.20.1
k8s.io/apimachinery v0.20.1
k8s.io/client-go v0.20.1
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
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
type ContextParams struct {
Name string
ContextName string
Description string
Endpoint string
KubeconfigPath string
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
}