From 38482fa31d56d96f6c8136378a4cdd2b1a567e36 Mon Sep 17 00:00:00 2001 From: Bryan Cox Date: Thu, 27 Oct 2022 12:59:29 -0400 Subject: [PATCH] Delete NodePool Secrets when machines terminate --- .../nodepool/nodepool_controller.go | 122 +++++++++++++----- 1 file changed, 89 insertions(+), 33 deletions(-) diff --git a/hypershift-operator/controllers/nodepool/nodepool_controller.go b/hypershift-operator/controllers/nodepool/nodepool_controller.go index e06bb4a34ef..58addc90692 100644 --- a/hypershift-operator/controllers/nodepool/nodepool_controller.go +++ b/hypershift-operator/controllers/nodepool/nodepool_controller.go @@ -869,6 +869,7 @@ func deleteMachineHealthCheck(ctx context.Context, c client.Client, mhc *capiv1. } func (r *NodePoolReconciler) delete(ctx context.Context, nodePool *hyperv1.NodePool, controlPlaneNamespace string) error { + allMachinesTerminiated := false md := machineDeployment(nodePool, controlPlaneNamespace) ms := machineSet(nodePool, controlPlaneNamespace) mhc := machineHealthCheck(nodePool, controlPlaneNamespace) @@ -903,27 +904,37 @@ func (r *NodePoolReconciler) delete(ctx context.Context, nodePool *hyperv1.NodeP return fmt.Errorf("failed to delete ConfigMaps with nodePool label: %w", err) } - // // Delete all secrets related to the NodePool - // if err := r.deleteNodePoolSecrets(ctx, nodePool); err != nil { - // return fmt.Errorf("failed to delete NodePool secrets: %w", err) - // } + if nodePool.Spec.Platform.AWS != nil { + for !allMachinesTerminiated { + time.Sleep(5 * time.Second) + allMachinesTerminiated, err = r.allMachinesTerminated(nodePool) + if err != nil { + return err + } + } + } + + // Delete all secrets related to the NodePool + if err := r.deleteNodePoolSecrets(ctx, nodePool); err != nil { + return fmt.Errorf("failed to delete NodePool secrets: %w", err) + } return nil } -// // deleteNodePoolSecrets deletes any secret belonging to this NodePool (ex. token Secret and userdata Secret) -// func (r *NodePoolReconciler) deleteNodePoolSecrets(ctx context.Context, nodePool *hyperv1.NodePool) error { -// secrets, err := r.listSecrets(ctx, nodePool) -// if err != nil { -// return fmt.Errorf("failed to list secrets: %w", err) -// } -// for k := range secrets { -// if err := r.Delete(ctx, &secrets[k]); err != nil && !apierrors.IsNotFound(err) { -// return fmt.Errorf("failed to delete secret: %w", err) -// } -// } -// return nil -// } +// deleteNodePoolSecrets deletes any secret belonging to this NodePool (ex. token Secret and userdata Secret) +func (r *NodePoolReconciler) deleteNodePoolSecrets(ctx context.Context, nodePool *hyperv1.NodePool) error { + secrets, err := r.listSecrets(ctx, nodePool) + if err != nil { + return fmt.Errorf("failed to list secrets: %w", err) + } + for k := range secrets { + if err := r.Delete(ctx, &secrets[k]); err != nil && !apierrors.IsNotFound(err) { + return fmt.Errorf("failed to delete secret: %w", err) + } + } + return nil +} func reconcileUserDataSecret(userDataSecret *corev1.Secret, nodePool *hyperv1.NodePool, CA, token []byte, ignEndpoint string, proxy *configv1.Proxy) error { // The token secret controller deletes expired token Secrets. @@ -1756,22 +1767,22 @@ func enqueueParentNodePool(obj client.Object) []reconcile.Request { } } -// func (r *NodePoolReconciler) listSecrets(ctx context.Context, nodePool *hyperv1.NodePool) ([]corev1.Secret, error) { -// secretList := &corev1.SecretList{} -// if err := r.List(ctx, secretList); err != nil { -// return nil, fmt.Errorf("failed to list secrets: %w", err) -// } -// filtered := []corev1.Secret{} -// for i, secret := range secretList.Items { -// if secret.GetAnnotations() != nil { -// if annotation, ok := secret.GetAnnotations()[nodePoolAnnotation]; ok && -// annotation == client.ObjectKeyFromObject(nodePool).String() { -// filtered = append(filtered, secretList.Items[i]) -// } -// } -// } -// return filtered, nil -// } +func (r *NodePoolReconciler) listSecrets(ctx context.Context, nodePool *hyperv1.NodePool) ([]corev1.Secret, error) { + secretList := &corev1.SecretList{} + if err := r.List(ctx, secretList); err != nil { + return nil, fmt.Errorf("failed to list secrets: %w", err) + } + filtered := []corev1.Secret{} + for i, secret := range secretList.Items { + if secret.GetAnnotations() != nil { + if annotation, ok := secret.GetAnnotations()[nodePoolAnnotation]; ok && + annotation == client.ObjectKeyFromObject(nodePool).String() { + filtered = append(filtered, secretList.Items[i]) + } + } + } + return filtered, nil +} func (r *NodePoolReconciler) listMachineTemplates(nodePool *hyperv1.NodePool) ([]client.Object, error) { machineTemplateList := &unstructured.UnstructuredList{} @@ -2026,3 +2037,48 @@ func (r *NodePoolReconciler) doesCPODecompressAndDecodeConfig(ctx context.Contex _, managesDecompressAndDecodeConfig := supportutil.ImageLabels(controlPlaneOperatorImageMetadata)[controlPlaneOperatorManagesDecompressAndDecodeConfig] return managesDecompressAndDecodeConfig, nil } + +func (r *NodePoolReconciler) allMachinesTerminated(nodePool *hyperv1.NodePool) (bool, error) { + machineSetList := &unstructured.UnstructuredList{} + var gvk schema.GroupVersionKind + var err error + + switch nodePool.Spec.Platform.Type { + // Define the desired template type and mutateTemplate function. + case hyperv1.AWSPlatform: + gvk, err = apiutil.GVKForObject(&capiaws.AWSMachineList{}, api.Scheme) + if err != nil { + return false, err + } + default: + // need a default path that returns a value that does not cause the hypershift operator to crash + // if no explicit machineSet is defined safe to assume none exist + return true, nil + } + + machineSetList.SetGroupVersionKind(schema.GroupVersionKind{ + Group: gvk.Group, + Kind: gvk.Kind, + Version: gvk.Version, + }) + + if err := r.List(context.Background(), machineSetList); err != nil { + return false, fmt.Errorf("failed to list MachineSet: %w", err) + } + + var filteredMachines []client.Object + for i, machineSet := range machineSetList.Items { + if machineSet.GetAnnotations() != nil { + if annotation, ok := machineSet.GetAnnotations()[nodePoolAnnotation]; ok && + annotation == client.ObjectKeyFromObject(nodePool).String() { + filteredMachines = append(filteredMachines, &machineSetList.Items[i]) + } + } + } + + if len(filteredMachines) > 0 { + return false, nil + } + + return true, nil +}