2021-03-04 19:16:40 +00:00
/ *
Copyright the Velero contributors .
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 uninstall
import (
"context"
"fmt"
"time"
"github.com/pkg/errors"
"github.com/spf13/cobra"
2021-03-24 01:00:38 +00:00
"github.com/spf13/pflag"
corev1 "k8s.io/api/core/v1"
2021-07-29 14:01:13 +00:00
apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
2021-06-09 14:07:56 +00:00
apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
2021-03-24 01:00:38 +00:00
apierrors "k8s.io/apimachinery/pkg/api/errors"
2021-07-29 14:01:13 +00:00
"k8s.io/apimachinery/pkg/api/meta"
2021-03-04 19:16:40 +00:00
"k8s.io/apimachinery/pkg/labels"
2021-03-24 01:00:38 +00:00
kubeerrs "k8s.io/apimachinery/pkg/util/errors"
2021-03-04 19:16:40 +00:00
"k8s.io/apimachinery/pkg/util/wait"
2021-06-09 14:07:56 +00:00
kbclient "sigs.k8s.io/controller-runtime/pkg/client"
2021-03-04 19:16:40 +00:00
"github.com/vmware-tanzu/velero/pkg/client"
"github.com/vmware-tanzu/velero/pkg/cmd"
2021-03-24 01:00:38 +00:00
"github.com/vmware-tanzu/velero/pkg/cmd/cli"
2021-03-04 19:16:40 +00:00
"github.com/vmware-tanzu/velero/pkg/install"
)
2021-03-24 01:00:38 +00:00
// uninstallOptions collects all the options for uninstalling Velero from a Kubernetes cluster.
type uninstallOptions struct {
2021-08-17 15:55:22 +00:00
wait bool // deprecated
force bool
2021-03-24 01:00:38 +00:00
}
// BindFlags adds command line values to the options struct.
func ( o * uninstallOptions ) BindFlags ( flags * pflag . FlagSet ) {
2021-08-17 15:55:22 +00:00
flags . BoolVar ( & o . wait , "wait" , o . wait , "Wait for Velero uninstall to be ready. Optional. Deprecated." )
2021-03-24 01:00:38 +00:00
flags . BoolVar ( & o . force , "force" , o . force , "Forces the Velero uninstall. Optional." )
}
// NewCommand creates a cobra command.
func NewCommand ( f client . Factory ) * cobra . Command {
o := & uninstallOptions { }
c := & cobra . Command {
Use : "uninstall" ,
Short : "Uninstall Velero" ,
2021-03-25 20:36:49 +00:00
Long : ` Uninstall Velero along with the CRDs and clusterrolebinding .
2021-03-24 01:00:38 +00:00
The ' -- namespace ' flag can be used to specify the namespace where velero is installed ( default : velero ) .
Use ' -- force ' to skip the prompt confirming if you want to uninstall Velero .
` ,
2021-03-25 20:36:49 +00:00
Example : ` # velero uninstall --namespace staging ` ,
2021-03-24 01:00:38 +00:00
Run : func ( c * cobra . Command , args [ ] string ) {
2021-08-17 15:55:22 +00:00
if o . wait {
fmt . Println ( "Warning: the \"--wait\" option is deprecated and will be removed in a future release. The uninstall command always waits for the uninstall to complete." )
}
2021-03-24 01:00:38 +00:00
// Confirm if not asked to force-skip confirmation
if ! o . force {
fmt . Println ( "You are about to uninstall Velero." )
if ! cli . GetConfirmation ( ) {
// Don't do anything unless we get confirmation
return
}
}
2021-06-09 14:07:56 +00:00
kbClient , err := f . KubebuilderClient ( )
2021-03-24 01:00:38 +00:00
cmd . CheckError ( err )
2021-08-17 15:55:22 +00:00
cmd . CheckError ( Run ( context . Background ( ) , kbClient , f . Namespace ( ) ) )
2021-03-24 01:00:38 +00:00
} ,
2021-03-04 19:16:40 +00:00
}
2021-03-24 01:00:38 +00:00
o . BindFlags ( c . Flags ( ) )
return c
}
// Run removes all components that were deployed using the Velero install command
2021-08-17 15:55:22 +00:00
func Run ( ctx context . Context , kbClient kbclient . Client , namespace string ) error {
// The CRDs cannot be removed until the namespace is deleted to avoid the problem in issue #3974 so if the namespace deletion fails we error out here
if err := deleteNamespace ( ctx , kbClient , namespace ) ; err != nil {
fmt . Printf ( "Errors while attempting to uninstall Velero: %q \n" , err )
return err
2021-03-04 19:16:40 +00:00
}
2021-08-17 15:55:22 +00:00
var errs [ ] error
2021-06-09 14:07:56 +00:00
// ClusterRoleBinding
2021-03-24 01:00:38 +00:00
crb := install . ClusterRoleBinding ( namespace )
2021-08-17 15:55:22 +00:00
key := kbclient . ObjectKey { Name : crb . Name }
2021-06-09 14:07:56 +00:00
if err := kbClient . Get ( ctx , key , crb ) ; err != nil {
2021-03-24 01:00:38 +00:00
if apierrors . IsNotFound ( err ) {
2021-06-09 14:07:56 +00:00
fmt . Printf ( "Velero ClusterRoleBinding %q does not exist, skipping.\n" , crb . Name )
2021-03-24 01:00:38 +00:00
} else {
errs = append ( errs , errors . WithStack ( err ) )
}
2021-06-09 14:07:56 +00:00
} else {
if err := kbClient . Delete ( ctx , crb ) ; err != nil {
errs = append ( errs , errors . WithStack ( err ) )
}
2021-03-24 01:00:38 +00:00
}
// CRDs
2021-07-29 14:01:13 +00:00
veleroLabelSelector := labels . SelectorFromSet ( install . Labels ( ) )
opts := [ ] kbclient . DeleteAllOfOption {
kbclient . InNamespace ( namespace ) ,
kbclient . MatchingLabelsSelector {
Selector : veleroLabelSelector ,
2021-06-09 14:07:56 +00:00
} ,
2021-03-04 19:16:40 +00:00
}
2021-07-29 14:01:13 +00:00
v1CRDsRemoved := false
v1crd := & apiextv1 . CustomResourceDefinition { }
if err := kbClient . DeleteAllOf ( ctx , v1crd , opts ... ) ; err != nil {
if meta . IsNoMatchError ( err ) {
fmt . Println ( "V1 Velero CRDs not found, skipping..." )
2021-06-09 14:07:56 +00:00
} else {
2021-07-29 14:01:13 +00:00
errs = append ( errs , errors . WithStack ( err ) )
}
} else {
v1CRDsRemoved = true
}
// Remove any old Velero v1beta1 CRDs hanging around.
v1beta1crd := & apiextv1beta1 . CustomResourceDefinition { }
if err := kbClient . DeleteAllOf ( ctx , v1beta1crd , opts ... ) ; err != nil {
if meta . IsNoMatchError ( err ) {
if ! v1CRDsRemoved {
// Only mention this if there were no V1 CRDs removed
fmt . Println ( "V1Beta1 Velero CRDs not found, skipping..." )
2021-03-24 01:00:38 +00:00
}
2021-07-29 14:01:13 +00:00
} else {
errs = append ( errs , errors . WithStack ( err ) )
2021-03-04 19:16:40 +00:00
}
}
2021-08-17 15:55:22 +00:00
if kubeerrs . NewAggregate ( errs ) != nil {
fmt . Printf ( "Errors while attempting to uninstall Velero: %q \n" , kubeerrs . NewAggregate ( errs ) )
return kubeerrs . NewAggregate ( errs )
}
2021-03-04 19:16:40 +00:00
2021-08-17 15:55:22 +00:00
fmt . Println ( "Velero uninstalled ⛵" )
return nil
}
2021-03-24 01:00:38 +00:00
2021-08-17 15:55:22 +00:00
func deleteNamespace ( ctx context . Context , kbClient kbclient . Client , namespace string ) error {
ns := & corev1 . Namespace { }
key := kbclient . ObjectKey { Name : namespace }
if err := kbClient . Get ( ctx , key , ns ) ; err != nil {
if apierrors . IsNotFound ( err ) {
fmt . Printf ( "Velero namespace %q does not exist, skipping.\n" , namespace )
return nil
2021-03-04 19:16:40 +00:00
}
2021-08-17 15:55:22 +00:00
return err
}
2021-03-04 19:16:40 +00:00
2021-08-17 15:55:22 +00:00
if err := kbClient . Delete ( ctx , ns ) ; err != nil {
if apierrors . IsNotFound ( err ) {
fmt . Printf ( "Velero namespace %q does not exist, skipping.\n" , namespace )
return nil
}
return err
2021-03-04 19:16:40 +00:00
}
2021-08-17 15:55:22 +00:00
fmt . Printf ( "Waiting for velero namespace %q to be deleted\n" , namespace )
ctx , cancel := context . WithCancel ( ctx )
defer cancel ( )
var err error
checkFunc := func ( ) {
if err = kbClient . Get ( ctx , key , ns ) ; err != nil {
if apierrors . IsNotFound ( err ) {
fmt . Print ( "\n" )
err = nil
}
cancel ( )
return
}
fmt . Print ( "." )
2021-03-24 01:00:38 +00:00
}
2021-08-17 15:55:22 +00:00
// Must wait until the namespace is deleted to avoid the issue https://github.com/vmware-tanzu/velero/issues/3974
wait . Until ( checkFunc , 5 * time . Millisecond , ctx . Done ( ) )
if err != nil {
return err
}
fmt . Printf ( "Velero namespace %q deleted\n" , namespace )
2021-03-24 01:00:38 +00:00
return nil
2021-03-04 19:16:40 +00:00
}