diff --git a/flytectl/cmd/sandbox/start.go b/flytectl/cmd/sandbox/start.go index 95edcff8dd..2023806dd5 100644 --- a/flytectl/cmd/sandbox/start.go +++ b/flytectl/cmd/sandbox/start.go @@ -27,6 +27,7 @@ import ( cmdCore "github.com/flyteorg/flytectl/cmd/core" "github.com/flyteorg/flytectl/pkg/docker" "github.com/flyteorg/flytectl/pkg/util" + "k8s.io/client-go/tools/clientcmd" ) const ( @@ -70,6 +71,8 @@ Usage sandboxSupportedVersion = "v0.10.0" diskPressureTaint = "node.kubernetes.io/disk-pressure" taintEffect = "NoSchedule" + sandboxContextName = "flyte-sandbox" + sandboxDockerContext = "default" ) type ExecResult struct { @@ -104,6 +107,10 @@ func startSandboxCluster(ctx context.Context, args []string, cmdCtx cmdCore.Comm if err != nil { return err } + if err = updateLocalKubeContext(); err != nil { + return err + } + if err := watchFlyteDeployment(ctx, k8sClient.CoreV1()); err != nil { return err } @@ -112,6 +119,17 @@ func startSandboxCluster(ctx context.Context, args []string, cmdCtx cmdCore.Comm return nil } +func updateLocalKubeContext() error { + localConfigAccess := clientcmd.NewDefaultPathOptions() + + dockerConfigAccess := &clientcmd.PathOptions{ + GlobalFile: docker.Kubeconfig, + LoadingRules: clientcmd.NewDefaultClientConfigLoadingRules(), + } + + return k8s.CopyKubeContext(dockerConfigAccess, localConfigAccess, sandboxDockerContext, sandboxContextName) +} + func startSandbox(ctx context.Context, cli docker.Docker, reader io.Reader) (*bufio.Scanner, error) { fmt.Printf("%v Bootstrapping a brand new flyte cluster... %v %v\n", emoji.FactoryWorker, emoji.Hammer, emoji.Wrench) diff --git a/flytectl/cmd/sandbox/start_test.go b/flytectl/cmd/sandbox/start_test.go index d15ee17ef4..ca64917914 100644 --- a/flytectl/cmd/sandbox/start_test.go +++ b/flytectl/cmd/sandbox/start_test.go @@ -40,17 +40,17 @@ clusters: extension: audience: foo other: bar - name: foo-cluster + name: default contexts: - context: - cluster: foo-cluster - user: foo-user + cluster: default + user: default namespace: bar - name: foo-context -current-context: foo-context + name: default +current-context: default kind: Config users: -- name: foo-user +- name: default user: exec: apiVersion: client.authentication.k8s.io/v1alpha1 diff --git a/flytectl/cmd/sandbox/teardown.go b/flytectl/cmd/sandbox/teardown.go index 3d42e7c7c5..bce078b788 100644 --- a/flytectl/cmd/sandbox/teardown.go +++ b/flytectl/cmd/sandbox/teardown.go @@ -12,6 +12,8 @@ import ( "github.com/enescakir/emoji" cmdCore "github.com/flyteorg/flytectl/cmd/core" + "github.com/flyteorg/flytectl/pkg/k8s" + "k8s.io/client-go/tools/clientcmd" ) const ( @@ -48,6 +50,14 @@ func tearDownSandbox(ctx context.Context, cli docker.Docker) error { if err := configutil.ConfigCleanup(); err != nil { fmt.Printf("Config cleanup failed. Which Failed due to %v \n ", err) } + if err := removeSandboxKubeContext(); err != nil { + fmt.Printf("Kubecontext cleanup failed. Which Failed due to %v \n ", err) + } fmt.Printf("%v %v Sandbox cluster is removed successfully. \n", emoji.Broom, emoji.Broom) return nil } + +func removeSandboxKubeContext() error { + localConfigAccess := clientcmd.NewDefaultPathOptions() + return k8s.RemoveKubeContext(localConfigAccess, sandboxContextName) +} diff --git a/flytectl/pkg/k8s/k8s.go b/flytectl/pkg/k8s/k8s.go index f17082dbe0..74086d76a2 100644 --- a/flytectl/pkg/k8s/k8s.go +++ b/flytectl/pkg/k8s/k8s.go @@ -1,12 +1,14 @@ package k8s import ( + "fmt" "os" "github.com/pkg/errors" "k8s.io/client-go/kubernetes" corev1 "k8s.io/client-go/kubernetes/typed/core/v1" "k8s.io/client-go/tools/clientcmd" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" ) type K8s interface { @@ -31,3 +33,71 @@ func GetK8sClient(cfg, master string) (K8s, error) { } return Client, nil } + +// CopyKubeContext copies context fromContext part of fromConfigAccess to toContext part of toConfigAccess. +func CopyKubeContext(fromConfigAccess, toConfigAccess clientcmd.ConfigAccess, fromContext, toContext string) error { + _, err := toConfigAccess.GetStartingConfig() + if err != nil { + return err + } + + fromStartingConfig, err := fromConfigAccess.GetStartingConfig() + if err != nil { + return err + } + _, exists := fromStartingConfig.Contexts[fromContext] + if !exists { + return fmt.Errorf("context %v doesn't exist", fromContext) + } + + toStartingConfig, err := toConfigAccess.GetStartingConfig() + if err != nil { + return err + } + + _, exists = toStartingConfig.Contexts[toContext] + if exists { + fmt.Printf("context %v already exist. Overwriting it\n", toContext) + } else { + toStartingConfig.Contexts[toContext] = clientcmdapi.NewContext() + } + + toStartingConfig.Clusters[toContext] = fromStartingConfig.Clusters[fromContext] + toStartingConfig.Clusters[toContext].LocationOfOrigin = toConfigAccess.GetDefaultFilename() + toStartingConfig.AuthInfos[toContext] = fromStartingConfig.AuthInfos[fromContext] + toStartingConfig.AuthInfos[toContext].LocationOfOrigin = toConfigAccess.GetDefaultFilename() + toStartingConfig.Contexts[toContext].Cluster = toContext + toStartingConfig.Contexts[toContext].AuthInfo = toContext + toStartingConfig.CurrentContext = toContext + + if err := clientcmd.ModifyConfig(toConfigAccess, *toStartingConfig, true); err != nil { + return err + } + + fmt.Printf("context modified for %q and switched over to it.\n", toContext) + return nil +} + +// RemoveKubeContext removes the contextToRemove from the kubeContext pointed to be fromConfigAccess +func RemoveKubeContext(fromConfigAccess clientcmd.ConfigAccess, contextToRemove string) error { + fromStartingConfig, err := fromConfigAccess.GetStartingConfig() + if err != nil { + return err + } + _, exists := fromStartingConfig.Contexts[contextToRemove] + if !exists { + return fmt.Errorf("context %v doesn't exist", contextToRemove) + } + + delete(fromStartingConfig.Clusters, contextToRemove) + delete(fromStartingConfig.AuthInfos, contextToRemove) + delete(fromStartingConfig.Contexts, contextToRemove) + fromStartingConfig.CurrentContext = "" + + if err := clientcmd.ModifyConfig(fromConfigAccess, *fromStartingConfig, true); err != nil { + return err + } + + fmt.Printf("context removed for %q.\n", contextToRemove) + return nil +}