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 }