Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(k8s): add kubeconfig commands #757

Merged
merged 20 commits into from
Mar 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Retrieve the kubeconfig for a specified cluster.

USAGE:
scw k8s kubeconfig get <cluster-id> [arg=value ...]

ARGS:
cluster-id Cluster ID from which to retrieve the kubeconfig
[region] Region to target. If none is passed will use default region from the config

FLAGS:
-h, --help help for get

GLOBAL FLAGS:
-D, --debug Enable debug mode
-o, --output string Output format: json or human
-p, --profile string The config profile to use
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Retrieve the kubeconfig for a specified cluster and write it on disk. It will merge the new kubeconfig in the file pointed by the KUBECONFIG variable. If empty it will default to $HOME/.kube/config.

USAGE:
scw k8s kubeconfig install <cluster-id> [arg=value ...]

ARGS:
cluster-id Cluster ID from which to retrieve the kubeconfig
[region] Region to target. If none is passed will use default region from the config
Sh4d1 marked this conversation as resolved.
Show resolved Hide resolved
Sh4d1 marked this conversation as resolved.
Show resolved Hide resolved

FLAGS:
-h, --help help for install

GLOBAL FLAGS:
-D, --debug Enable debug mode
-o, --output string Output format: json or human
-p, --profile string The config profile to use
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Remove specified cluster from kubeconfig file specified by the KUBECONFIG env, if empty it will default to $HOME/.kube/config.

USAGE:
scw k8s kubeconfig uninstall <cluster-id> [arg=value ...]

ARGS:
cluster-id Cluster ID from which to uninstall the kubeconfig
Sh4d1 marked this conversation as resolved.
Show resolved Hide resolved

FLAGS:
-h, --help help for uninstall

GLOBAL FLAGS:
-D, --debug Enable debug mode
-o, --output string Output format: json or human
-p, --profile string The config profile to use
19 changes: 19 additions & 0 deletions cmd/scw/testdata/test-all-usage-k8s-kubeconfig-usage.stderr.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Manage your Kubernetes Kapsule cluster's kubeconfig files

USAGE:
scw k8s kubeconfig <command>

AVAILABLE COMMANDS:
get Retrieve a kubeconfig
install Install a kubeconfig
uninstall Uninstall a kubeconfig

FLAGS:
-h, --help help for kubeconfig

GLOBAL FLAGS:
-D, --debug Enable debug mode
-o, --output string Output format: json or human
-p, --profile string The config profile to use

Use "scw k8s kubeconfig [command] --help" for more information about a command.
1 change: 1 addition & 0 deletions cmd/scw/testdata/test-all-usage-k8s-usage.stderr.golden
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ AVAILABLE COMMANDS:
pool A pool is a virtual group of nodes in a cluster
node A node is the representation of a Scaleway instance in a cluster
version A version is a Kubernetes version
kubeconfig Manage your Kubernetes Kapsule cluster's kubeconfig files

FLAGS:
-h, --help help for k8s
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ require (
github.com/stretchr/testify v1.4.0
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
gopkg.in/yaml.v2 v2.2.5 // indirect
gopkg.in/yaml.v2 v2.2.7
)
5 changes: 2 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVc
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM=
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
Expand Down Expand Up @@ -93,5 +92,5 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
4 changes: 4 additions & 0 deletions internal/namespaces/k8s/v1beta4/custom.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ func GetCommands() *core.Commands {
cmds := GetGeneratedCommands()
cmds.Merge(core.NewCommands(
k8sVersionGetCommand(),
k8sKubeconfigCommand(),
k8sKubeconfigGetCommand(),
k8sKubeconfigInstallCommand(),
k8sKubeconfigUninstallCommand(),
))

human.RegisterMarshalerFunc(k8s.ClusterStatus(0), human.BindAttributesMarshalFunc(clusterStatusAttributes))
Expand Down
13 changes: 13 additions & 0 deletions internal/namespaces/k8s/v1beta4/custom_kubeconfig.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package k8s

import (
"github.com/scaleway/scaleway-cli/internal/core"
)

func k8sKubeconfigCommand() *core.Command {
return &core.Command{
Short: `Manage your Kubernetes Kapsule cluster's kubeconfig files`,
Namespace: "k8s",
Resource: "kubeconfig",
}
}
55 changes: 55 additions & 0 deletions internal/namespaces/k8s/v1beta4/custom_kubeconfig_get.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package k8s

import (
"context"
"reflect"

"github.com/scaleway/scaleway-cli/internal/core"
k8s "github.com/scaleway/scaleway-sdk-go/api/k8s/v1beta4"
"github.com/scaleway/scaleway-sdk-go/scw"
)

type k8sKubeconfigGetRequest struct {
Sh4d1 marked this conversation as resolved.
Show resolved Hide resolved
ClusterID string
Region scw.Region
}

func k8sKubeconfigGetCommand() *core.Command {
Sh4d1 marked this conversation as resolved.
Show resolved Hide resolved
return &core.Command{
Short: `Retrieve a kubeconfig`,
Long: `Retrieve the kubeconfig for a specified cluster.`,
Namespace: "k8s",
Verb: "get",
Resource: "kubeconfig",
ArgsType: reflect.TypeOf(k8sKubeconfigGetRequest{}),
ArgSpecs: core.ArgSpecs{
{
Name: "cluster-id",
Short: "Cluster ID from which to retrieve the kubeconfig",
Required: true,
Positional: true,
},
core.RegionArgSpec(),
},
Run: k8sKubeconfigGetRun,
}
}

func k8sKubeconfigGetRun(ctx context.Context, argsI interface{}) (i interface{}, e error) {
Sh4d1 marked this conversation as resolved.
Show resolved Hide resolved
request := argsI.(*k8sKubeconfigGetRequest)

kubeconfigRequest := &k8s.GetClusterKubeConfigRequest{
Region: request.Region,
ClusterID: request.ClusterID,
}

client := core.ExtractClient(ctx)
apiK8s := k8s.NewAPI(client)

kubeconfig, err := apiK8s.GetClusterKubeConfig(kubeconfigRequest)
if err != nil {
return nil, err
}

return string(kubeconfig.GetRaw()), nil
}
28 changes: 28 additions & 0 deletions internal/namespaces/k8s/v1beta4/custom_kubeconfig_get_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package k8s

import (
"testing"

"github.com/alecthomas/assert"
"github.com/scaleway/scaleway-cli/internal/core"
k8s "github.com/scaleway/scaleway-sdk-go/api/k8s/v1beta4"
)

func Test_GetKubeconfig(t *testing.T) {
Sh4d1 marked this conversation as resolved.
Show resolved Hide resolved
////
// Simple use cases
////
t.Run("simple", core.Test(&core.TestConfig{
Commands: GetCommands(),
BeforeFunc: createClusterAndWaitAndKubeconfig("Cluster", "Kubeconfig", kapsuleVersion),
Cmd: "scw k8s kubeconfig get {{ .Cluster.ID }}",
Check: core.TestCheckCombine(
core.TestCheckGolden(),
func(t *testing.T, ctx *core.CheckFuncCtx) {
assert.Equal(t, ctx.Result.(string), string(ctx.Meta["Kubeconfig"].(*k8s.Kubeconfig).GetRaw()))
},
core.TestCheckExitCode(0),
),
AfterFunc: deleteCluster("Cluster"),
}))
}
63 changes: 63 additions & 0 deletions internal/namespaces/k8s/v1beta4/custom_kubeconfig_helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package k8s

import (
"context"
"io/ioutil"
"os"
"path"
"runtime"
"strings"

"github.com/scaleway/scaleway-cli/internal/core"
k8s "github.com/scaleway/scaleway-sdk-go/api/k8s/v1beta4"
"gopkg.in/yaml.v2"
)

// get the path to the wanted kubeconfig on disk
// either the file pointed by the KUBECONFIG env variable (first one in case of a list)
// or the $HOME/.kube/config
func getKubeconfigPath(ctx context.Context) (string, error) {
var kubeconfigPath string
kubeconfigEnv := core.ExtractEnv(ctx, "KUBECONFIG")
if kubeconfigEnv != "" {
if runtime.GOOS == "windows" {
kubeconfigPath = strings.Split(kubeconfigEnv, ";")[0] // list is separated by ; on windows
} else {
kubeconfigPath = strings.Split(kubeconfigEnv, ":")[0] // list is separated by : on linux/macos
}
} else {
homeDir, err := os.UserHomeDir()
if err != nil {
return "", err
}
kubeconfigPath = path.Join(homeDir, kubeLocationDir, "config")
}

return kubeconfigPath, nil
}

func openAndUnmarshalKubeconfig(kubeconfigPath string) (*k8s.Kubeconfig, error) {
// getting the existing file
file, err := ioutil.ReadFile(kubeconfigPath)
if err != nil {
return nil, err
}

var kubeconfig k8s.Kubeconfig

err = yaml.Unmarshal(file, &kubeconfig)
if err != nil {
return nil, err
}

return &kubeconfig, nil
}

func marshalAndWriteKubeconfig(kubeconfig *k8s.Kubeconfig, kubeconfigPath string) error {
newKubeconfig, err := yaml.Marshal(*kubeconfig)
if err != nil {
return err
}

return ioutil.WriteFile(kubeconfigPath, newKubeconfig, 0644)
}
Loading