github.com/openshift/installer@v1.4.17/pkg/destroy/powervs/power-sshkey.go (about)

     1  package powervs
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"math"
     7  	"strings"
     8  	"time"
     9  
    10  	"github.com/IBM-Cloud/power-go-client/power/models"
    11  	"k8s.io/apimachinery/pkg/util/wait"
    12  )
    13  
    14  const powerSSHKeyTypeName = "powerSshKey"
    15  
    16  // listPowerSSHKeys lists ssh keys in the Power server.
    17  func (o *ClusterUninstaller) listPowerSSHKeys() (cloudResources, error) {
    18  	o.Logger.Debugf("Listing Power SSHKeys")
    19  
    20  	if o.keyClient == nil {
    21  		o.Logger.Infof("Skipping deleting Power sshkeys because no service instance was found")
    22  		result := []cloudResource{}
    23  		return cloudResources{}.insert(result...), nil
    24  	}
    25  
    26  	ctx, cancel := o.contextWithTimeout()
    27  	defer cancel()
    28  
    29  	select {
    30  	case <-ctx.Done():
    31  		o.Logger.Debugf("listPowerSSHKeys: case <-ctx.Done()")
    32  		return nil, o.Context.Err() // we're cancelled, abort
    33  	default:
    34  	}
    35  
    36  	var sshKeys *models.SSHKeys
    37  	var err error
    38  
    39  	sshKeys, err = o.keyClient.GetAll()
    40  	if err != nil {
    41  		return nil, fmt.Errorf("failed to list Power sshkeys: %w", err)
    42  	}
    43  
    44  	var sshKey *models.SSHKey
    45  	var foundOne = false
    46  
    47  	result := []cloudResource{}
    48  	for _, sshKey = range sshKeys.SSHKeys {
    49  		if strings.Contains(*sshKey.Name, o.InfraID) {
    50  			foundOne = true
    51  			o.Logger.Debugf("listPowerSSHKeys: FOUND: %v", *sshKey.Name)
    52  			result = append(result, cloudResource{
    53  				key:      *sshKey.Name,
    54  				name:     *sshKey.Name,
    55  				status:   "",
    56  				typeName: powerSSHKeyTypeName,
    57  				id:       *sshKey.Name,
    58  			})
    59  		}
    60  	}
    61  	if !foundOne {
    62  		o.Logger.Debugf("listPowerSSHKeys: NO matching sshKey against: %s", o.InfraID)
    63  		for _, sshKey := range sshKeys.SSHKeys {
    64  			o.Logger.Debugf("listPowerSSHKeys: sshKey: %s", *sshKey.Name)
    65  		}
    66  	}
    67  
    68  	return cloudResources{}.insert(result...), nil
    69  }
    70  
    71  func (o *ClusterUninstaller) deletePowerSSHKey(item cloudResource) error {
    72  	var err error
    73  
    74  	ctx, cancel := o.contextWithTimeout()
    75  	defer cancel()
    76  
    77  	select {
    78  	case <-ctx.Done():
    79  		o.Logger.Debugf("deletePowerSSHKey: case <-ctx.Done()")
    80  		return o.Context.Err() // we're cancelled, abort
    81  	default:
    82  	}
    83  
    84  	_, err = o.keyClient.Get(item.id)
    85  	if err != nil {
    86  		o.deletePendingItems(item.typeName, []cloudResource{item})
    87  		o.Logger.Infof("Deleted Power SSHKey %q", item.name)
    88  		return nil
    89  	}
    90  
    91  	err = o.keyClient.Delete(item.id)
    92  	if err != nil {
    93  		return fmt.Errorf("failed to delete Power sshKey %s: %w", item.name, err)
    94  	}
    95  
    96  	o.Logger.Infof("Deleted Power SSHKey %q", item.name)
    97  	o.deletePendingItems(item.typeName, []cloudResource{item})
    98  
    99  	return nil
   100  }
   101  
   102  // destroyPowerSSHKeys removes all ssh keys that have a name prefixed
   103  // with the cluster's infra ID.
   104  func (o *ClusterUninstaller) destroyPowerSSHKeys() error {
   105  	firstPassList, err := o.listPowerSSHKeys()
   106  	if err != nil {
   107  		return err
   108  	}
   109  
   110  	if len(firstPassList.list()) == 0 {
   111  		return nil
   112  	}
   113  
   114  	items := o.insertPendingItems(powerSSHKeyTypeName, firstPassList.list())
   115  
   116  	ctx, cancel := o.contextWithTimeout()
   117  	defer cancel()
   118  
   119  	for _, item := range items {
   120  		select {
   121  		case <-ctx.Done():
   122  			o.Logger.Debugf("destroyPowerSSHKeys: case <-ctx.Done()")
   123  			return o.Context.Err() // we're cancelled, abort
   124  		default:
   125  		}
   126  
   127  		backoff := wait.Backoff{
   128  			Duration: 15 * time.Second,
   129  			Factor:   1.1,
   130  			Cap:      leftInContext(ctx),
   131  			Steps:    math.MaxInt32}
   132  		err = wait.ExponentialBackoffWithContext(ctx, backoff, func(context.Context) (bool, error) {
   133  			err2 := o.deletePowerSSHKey(item)
   134  			if err2 == nil {
   135  				return true, err2
   136  			}
   137  			o.errorTracker.suppressWarning(item.key, err2, o.Logger)
   138  			return false, err2
   139  		})
   140  		if err != nil {
   141  			o.Logger.Fatal("destroyPowerSSHKeys: ExponentialBackoffWithContext (destroy) returns ", err)
   142  		}
   143  	}
   144  
   145  	if items = o.getPendingItems(powerSSHKeyTypeName); len(items) > 0 {
   146  		for _, item := range items {
   147  			o.Logger.Debugf("destroyPowerSSHKeys: found %s in pending items", item.name)
   148  		}
   149  		return fmt.Errorf("destroyPowerSSHKeys: %d undeleted items pending", len(items))
   150  	}
   151  
   152  	backoff := wait.Backoff{
   153  		Duration: 15 * time.Second,
   154  		Factor:   1.1,
   155  		Cap:      leftInContext(ctx),
   156  		Steps:    math.MaxInt32}
   157  	err = wait.ExponentialBackoffWithContext(ctx, backoff, func(context.Context) (bool, error) {
   158  		secondPassList, err2 := o.listPowerSSHKeys()
   159  		if err2 != nil {
   160  			return false, err2
   161  		}
   162  		if len(secondPassList) == 0 {
   163  			// We finally don't see any remaining instances!
   164  			return true, nil
   165  		}
   166  		for _, item := range secondPassList {
   167  			o.Logger.Debugf("destroyPowerSSHKeys: found %s in second pass", item.name)
   168  		}
   169  		return false, nil
   170  	})
   171  	if err != nil {
   172  		o.Logger.Fatal("destroyPowerSSHKeys: ExponentialBackoffWithContext (list) returns ", err)
   173  	}
   174  
   175  	return nil
   176  }