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

Vcluster delete --ignore-not-found #12

Open
wants to merge 1 commit into
base: develop_bkp
Choose a base branch
from
Open
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
117 changes: 76 additions & 41 deletions cmd/vclusterctl/cmd/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ package cmd
import (
"context"
"fmt"
"github.com/loft-sh/vcluster/pkg/util/translate"
"os/exec"

"github.com/loft-sh/vcluster/pkg/util/translate"

"github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/app/localkubernetes"
"github.com/loft-sh/vcluster/cmd/vclusterctl/cmd/find"
"k8s.io/client-go/rest"
Expand All @@ -31,10 +32,11 @@ type DeleteCmd struct {
DeleteNamespace bool
AutoDeleteNamespace bool

rawConfig *clientcmdapi.Config
restConfig *rest.Config
kubeClient *kubernetes.Clientset
log log.Logger
ignoreNotFound bool
rawConfig *clientcmdapi.Config
restConfig *rest.Config
kubeClient *kubernetes.Clientset
log log.Logger
}

// NewDeleteCmd creates a new command
Expand Down Expand Up @@ -68,6 +70,7 @@ vcluster delete test --namespace test
cobraCmd.Flags().BoolVar(&cmd.KeepPVC, "keep-pvc", false, "If enabled, vcluster will not delete the persistent volume claim of the vcluster")
cobraCmd.Flags().BoolVar(&cmd.DeleteNamespace, "delete-namespace", false, "If enabled, vcluster will delete the namespace of the vcluster. In the case of multi-namespace mode, will also delete all other namespaces created by vcluster")
cobraCmd.Flags().BoolVar(&cmd.AutoDeleteNamespace, "auto-delete-namespace", true, "If enabled, vcluster will delete the namespace of the vcluster if it was created by vclusterctl. In the case of multi-namespace mode, will also delete all other namespaces created by vcluster")
cobraCmd.Flags().BoolVar(&cmd.ignoreNotFound, "ignore-not-found", false, "If enabled, vcluster will not error out in case vcluster does not exists")
return cobraCmd
}

Expand All @@ -90,7 +93,12 @@ func (cmd *DeleteCmd) Run(cobraCmd *cobra.Command, args []string) error {
// prepare client
err = cmd.prepare(args[0])
if err != nil {
return err
var errorVclusterNotFound *find.ErrorNotFoundVcluster
if cmd.ignoreNotFound && errors.As(err, &errorVclusterNotFound) {
cmd.log.Donef("vcluster %s not found in namespace %s, ignoring since --ignore-not-found flag is set", args[0], cmd.Namespace)
} else {
return err
}
}

// check if namespace
Expand All @@ -107,9 +115,15 @@ func (cmd *DeleteCmd) Run(cobraCmd *cobra.Command, args []string) error {
cmd.log.Infof("Delete vcluster %s...", args[0])
err = helm.NewClient(cmd.rawConfig, cmd.log, helmBinaryPath).Delete(args[0], cmd.Namespace)
if err != nil {
return err
var errorHelmNotFound *helm.ErrorNotFoundHelm
if cmd.ignoreNotFound && errors.As(err, &errorHelmNotFound) {
cmd.log.Donef("vcluster %s not found in namespace %s, ignoring since --ignore-not-found flag is set", args[0], cmd.Namespace)
} else {
return err
}
} else {
cmd.log.Donef("Successfully deleted virtual cluster %s in namespace %s", args[0], cmd.Namespace)
}
cmd.log.Donef("Successfully deleted virtual cluster %s in namespace %s", args[0], cmd.Namespace)

// try to delete the pvc
if !cmd.KeepPVC && !cmd.DeleteNamespace {
Expand Down Expand Up @@ -182,45 +196,66 @@ func (cmd *DeleteCmd) Run(cobraCmd *cobra.Command, args []string) error {
}

func (cmd *DeleteCmd) prepare(vClusterName string) error {
vCluster, err := find.GetVCluster(cmd.Context, vClusterName, cmd.Namespace)
if err != nil {
return err
}
if cmd.ignoreNotFound {
restConfig, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(clientcmd.NewDefaultClientConfigLoadingRules(), &clientcmd.ConfigOverrides{}).ClientConfig()
if err != nil {
return err
}
kubeClient, err := kubernetes.NewForConfig(restConfig)
if err != nil {
return err
}

// load the raw config
rawConfig, err := vCluster.ClientFactory.RawConfig()
if err != nil {
return fmt.Errorf("there is an error loading your current kube config (%v), please make sure you have access to a kubernetes cluster and the command `kubectl get namespaces` is working", err)
}
err = deleteContext(&rawConfig, find.VClusterContextName(vCluster.Name, vCluster.Namespace, vCluster.Context), vCluster.Context)
if err != nil {
return errors.Wrap(err, "delete kube context")
}
rawConfig, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(clientcmd.NewDefaultClientConfigLoadingRules(), &clientcmd.ConfigOverrides{}).RawConfig()
if err != nil {
return err
}

rawConfig.CurrentContext = vCluster.Context
restConfig, err := vCluster.ClientFactory.ClientConfig()
if err != nil {
return err
}
cmd.rawConfig = &rawConfig
cmd.kubeClient = kubeClient
cmd.restConfig = restConfig

err = localkubernetes.CleanupLocal(vClusterName, vCluster.Namespace, &rawConfig, cmd.log)
if err != nil {
cmd.log.Warnf("error cleaning up: %v", err)
}
} else {
vCluster, err := find.GetVCluster(cmd.Context, vClusterName, cmd.Namespace)
if err != nil {
return err
}

// construct proxy name
proxyName := find.VClusterConnectBackgroundProxyName(vClusterName, vCluster.Namespace, rawConfig.CurrentContext)
_ = localkubernetes.CleanupBackgroundProxy(proxyName, cmd.log)
// load the raw config
rawConfig, err := vCluster.ClientFactory.RawConfig()
if err != nil {
return fmt.Errorf("there is an error loading your current kube config (%v), please make sure you have access to a kubernetes cluster and the command `kubectl get namespaces` is working", err)
}
err = deleteContext(&rawConfig, find.VClusterContextName(vCluster.Name, vCluster.Namespace, vCluster.Context), vCluster.Context)
if err != nil {
return errors.Wrap(err, "delete kube context")
}

kubeClient, err := kubernetes.NewForConfig(restConfig)
if err != nil {
return err
}
rawConfig.CurrentContext = vCluster.Context
restConfig, err := vCluster.ClientFactory.ClientConfig()
if err != nil {
return err
}

err = localkubernetes.CleanupLocal(vClusterName, vCluster.Namespace, &rawConfig, cmd.log)
if err != nil {
cmd.log.Warnf("error cleaning up: %v", err)
}

cmd.Namespace = vCluster.Namespace
cmd.rawConfig = &rawConfig
cmd.restConfig = restConfig
cmd.kubeClient = kubeClient
// construct proxy name
proxyName := find.VClusterConnectBackgroundProxyName(vClusterName, vCluster.Namespace, rawConfig.CurrentContext)
_ = localkubernetes.CleanupBackgroundProxy(proxyName, cmd.log)

kubeClient, err := kubernetes.NewForConfig(restConfig)
if err != nil {
return err
}

cmd.Namespace = vCluster.Namespace
cmd.rawConfig = &rawConfig
cmd.restConfig = restConfig
cmd.kubeClient = kubeClient
}
return nil
}

Expand Down
13 changes: 11 additions & 2 deletions cmd/vclusterctl/cmd/find/find.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ package find
import (
"context"
"fmt"
"github.com/loft-sh/vcluster/cmd/vclusterctl/log"
"strings"
"time"

"github.com/loft-sh/vcluster/cmd/vclusterctl/log"

"github.com/loft-sh/vcluster/pkg/constants"
"github.com/pkg/errors"
appsv1 "k8s.io/api/apps/v1"
Expand Down Expand Up @@ -57,14 +58,22 @@ func GetVCluster(context, name, namespace string) (*VCluster, error) {
if err != nil {
return nil, err
} else if len(vclusters) == 0 {
return nil, fmt.Errorf("couldn't find vcluster %s", name)
return nil, &ErrorNotFoundVcluster{Name: name}
} else if len(vclusters) == 1 {
return &vclusters[0], nil
}

return nil, fmt.Errorf("multiple vclusters with name %s found, please specify a namespace via -n", name)
}

type ErrorNotFoundVcluster struct {
Name string
}

func (e *ErrorNotFoundVcluster) Error() string {
return fmt.Sprintf("couldn't find vcluster %s", e.Name)
}

func ListVClusters(context, name, namespace string) ([]VCluster, error) {
if context == "" {
var err error
Expand Down
12 changes: 10 additions & 2 deletions pkg/helm/helm.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,15 +220,23 @@ func (c *client) Delete(name, namespace string) error {
output, err := exec.Command(c.helmPath, args...).CombinedOutput()
if err != nil {
if strings.Contains(string(output), "release: not found") {
return fmt.Errorf("release '%s' was not found in namespace '%s'", name, namespace)
return &ErrorNotFoundHelm{Name: name, Namespace: namespace}
}

return fmt.Errorf("error executing helm delete: %s", string(output))
}

return nil
}

type ErrorNotFoundHelm struct {
Name string
Namespace string
}

func (e *ErrorNotFoundHelm) Error() string {
return fmt.Sprintf("release '%s' was not found in namespace '%s'", e.Name, e.Namespace)
}

func (c *client) Exists(name, namespace string) (bool, error) {
kubeConfig, err := WriteKubeConfig(c.config)
if err != nil {
Expand Down