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

add dry run delete #1897

Merged
merged 1 commit into from
Apr 3, 2023
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
3 changes: 3 additions & 0 deletions cmd/sonobuoy/app/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ type deleteFlags struct {
wait int
kubeconfig Kubeconfig
waitOutput WaitOutputMode
dryRun bool
}

func NewCmdDelete() *cobra.Command {
Expand All @@ -49,6 +50,7 @@ func NewCmdDelete() *cobra.Command {
AddNamespaceFlag(&f.namespace, cmd.Flags())
AddRBACModeFlags(&f.rbacMode, cmd.Flags(), DetectRBACMode)
AddDeleteAllFlag(&f.deleteAll, cmd.Flags())
AddDryRunFlag(&f.dryRun, cmd.Flags())
AddDeleteWaitFlag(&f.wait, cmd.Flags())
if features.Enabled(features.WaitOutputProgressByDefault) {
AddWaitOutputFlag(&f.waitOutput, cmd.Flags(), ProgressOutputMode)
Expand Down Expand Up @@ -84,6 +86,7 @@ func deleteSonobuoyRun(f *deleteFlags) func(cmd *cobra.Command, args []string) {
DeleteAll: f.deleteAll,
Wait: time.Duration(f.wait) * time.Minute,
WaitOutput: f.waitOutput.String(),
DryRun: f.dryRun,
}

if err := sbc.Delete(deleteCfg); err != nil {
Expand Down
64 changes: 48 additions & 16 deletions pkg/client/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func (c *SonobuoyClient) Delete(cfg *DeleteConfig) error {
}

conditions := []ConditionFuncWithProgress{}
nsCondition, err := cleanupNamespace(cfg.Namespace, client)
nsCondition, err := cleanupNamespace(cfg.Namespace, client, cfg)
if err != nil {
return err
}
Expand All @@ -76,7 +76,7 @@ func (c *SonobuoyClient) Delete(cfg *DeleteConfig) error {
}

if cfg.DeleteAll {
e2eCondition, err := cleanupE2E(client)
e2eCondition, err := cleanupE2E(client, cfg)
if err != nil {
return err
}
Expand Down Expand Up @@ -119,11 +119,12 @@ func (c *SonobuoyClient) Delete(cfg *DeleteConfig) error {
return nil
}

func cleanupNamespace(namespace string, client kubernetes.Interface) (ConditionFuncWithProgress, error) {
func cleanupNamespace(namespace string, client kubernetes.Interface, cfg *DeleteConfig) (ConditionFuncWithProgress, error) {
// Delete the namespace
log := logrus.WithFields(logrus.Fields{
"kind": "namespace",
"namespace": namespace,
"dry-run": cfg.DryRun,
})

nsDeletedCondition := func() (string, bool, error) {
Expand All @@ -141,8 +142,12 @@ func cleanupNamespace(namespace string, client kubernetes.Interface) (ConditionF
}
return "Requested namespace returned nil but was not recognized as having been deleted. Report this as a bug.", false, err
}
var dryRun []string
if cfg.DryRun {
dryRun = append(dryRun, metav1.DryRunAll)
}

err := client.CoreV1().Namespaces().Delete(context.TODO(), namespace, metav1.DeleteOptions{})
err := client.CoreV1().Namespaces().Delete(context.TODO(), namespace, metav1.DeleteOptions{DryRun: dryRun})
if err := logDelete(log, err); err != nil {
return nsDeletedCondition, errors.Wrap(err, "couldn't delete namespace")
}
Expand All @@ -167,7 +172,12 @@ func deleteRBAC(client kubernetes.Interface, cfg *DeleteConfig) (ConditionFuncWi
)
}

deleteOpts := metav1.DeleteOptions{}
var dryRun []string
if cfg.DryRun {
dryRun = append(dryRun, metav1.DryRunAll)
}

deleteOpts := metav1.DeleteOptions{DryRun: dryRun}
listOpts := metav1.ListOptions{
LabelSelector: metav1.FormatLabelSelector(selector),
}
Expand All @@ -178,10 +188,7 @@ func deleteRBAC(client kubernetes.Interface, cfg *DeleteConfig) (ConditionFuncWi
return fmt.Sprintf("Error encountered when checking for ClusterRoleBindings: %v", err), false, err
}
if len(clusterBindingList.Items) > 0 {
names := []string{}
for _, i := range clusterBindingList.Items {
names = append(names, i.Name)
}
var names []string
return fmt.Sprintf("Still found %v ClusterRoleBindings to delete: %v", len(names), names), false, nil
}

Expand All @@ -190,7 +197,7 @@ func deleteRBAC(client kubernetes.Interface, cfg *DeleteConfig) (ConditionFuncWi
return fmt.Sprintf("Error encountered when checking for ClusterRoleBindings: %v", err), false, err
}
if len(clusterRoleList.Items) > 0 {
names := []string{}
var names []string
for _, i := range clusterRoleList.Items {
names = append(names, i.Name)
}
Expand All @@ -202,14 +209,34 @@ func deleteRBAC(client kubernetes.Interface, cfg *DeleteConfig) (ConditionFuncWi
return "Deleted all ClusterRoles and ClusterRoleBindings.", true, nil
}

err := client.RbacV1().ClusterRoleBindings().DeleteCollection(context.TODO(), deleteOpts, listOpts)
if err := logDelete(logrus.WithField("kind", "clusterrolebindings"), err); err != nil {
forDeletion := make(map[string][]string)

clusterRoleBindingsList, err := client.RbacV1().ClusterRoleBindings().List(context.TODO(), listOpts)
if err != nil {
return rbacDeleteCondition, errors.Wrap(err, "failed to fetch cluster role bindings for deletion")
}
for _, crb := range clusterRoleBindingsList.Items {
var names []string
names = append(names, crb.Name)
forDeletion["cluster-role-bindings"] = names
}
err = client.RbacV1().ClusterRoleBindings().DeleteCollection(context.TODO(), deleteOpts, listOpts)
if err := logDelete(logrus.WithFields(logrus.Fields{"kind": "clusterrolebindings", "names": forDeletion["cluster-role-bindings"], "dry-run": cfg.DryRun}), err); err != nil {
return rbacDeleteCondition, errors.Wrap(err, "failed to delete cluster role binding")
}

// ClusterRole and ClusterRole bindings aren't namespaced, so delete them manually
clusterRolesList, err := client.RbacV1().ClusterRoles().List(context.TODO(), listOpts)
if err != nil {
return rbacDeleteCondition, errors.Wrap(err, "failed to fetch cluster roles for deletion")
}
for _, cr := range clusterRolesList.Items {
var names []string
names = append(names, cr.Name)
forDeletion["cluster-roles"] = names
}
err = client.RbacV1().ClusterRoles().DeleteCollection(context.TODO(), deleteOpts, listOpts)
if err := logDelete(logrus.WithField("kind", "clusterroles"), err); err != nil {
if err := logDelete(logrus.WithFields(logrus.Fields{"kind": "clusterroles", "names": forDeletion["cluster-roles"], "dry-run": cfg.DryRun}), err); err != nil {
return rbacDeleteCondition, errors.Wrap(err, "failed to delete cluster role")
}

Expand All @@ -224,7 +251,7 @@ func isE2ENamespace(ns v1.Namespace) bool {
return hasE2EFrameworkLabel && hasE2ERunLabel
}

func cleanupE2E(client kubernetes.Interface) (ConditionFuncWithProgress, error) {
func cleanupE2E(client kubernetes.Interface, cfg *DeleteConfig) (ConditionFuncWithProgress, error) {
// Delete any dangling E2E namespaces
// There currently isn't a way to associate namespaces with a particular test run so this
// will delete namespaces associated with any e2e test run by checking the namespace's labels.
Expand All @@ -233,7 +260,7 @@ func cleanupE2E(client kubernetes.Interface) (ConditionFuncWithProgress, error)
if err != nil {
return "Error encountered when checking namespaces for deletion.", false, errors.Wrap(err, "failed to list namespaces")
}
names := []string{}
var names []string
for _, namespace := range namespaces.Items {
if isE2ENamespace(namespace) {
names = append(names, namespace.Name)
Expand All @@ -255,8 +282,13 @@ func cleanupE2E(client kubernetes.Interface) (ConditionFuncWithProgress, error)
log := logrus.WithFields(logrus.Fields{
"kind": "namespace",
"namespace": namespace.Name,
"dry-run": cfg.DryRun,
})
err := client.CoreV1().Namespaces().Delete(context.TODO(), namespace.Name, metav1.DeleteOptions{})
var dryRun []string
if cfg.DryRun {
dryRun = append(dryRun, metav1.DryRunAll)
}
err := client.CoreV1().Namespaces().Delete(context.TODO(), namespace.Name, metav1.DeleteOptions{DryRun: dryRun})
if err := logDelete(log, err); err != nil {
return e2eNamespaceCondition, errors.Wrap(err, "couldn't delete namespace")
}
Expand Down
1 change: 1 addition & 0 deletions pkg/client/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ type DeleteConfig struct {
DeleteAll bool
Wait time.Duration
WaitOutput string
DryRun bool
}

// Validate checks the config to determine if it is valid.
Expand Down