github.com/openshift/installer@v1.4.17/pkg/destroy/powervs/securitygroup.go (about) 1 package powervs 2 3 import ( 4 "context" 5 "fmt" 6 "math" 7 "net/http" 8 "strings" 9 "time" 10 11 "github.com/IBM/go-sdk-core/v5/core" 12 "github.com/IBM/vpc-go-sdk/vpcv1" 13 "k8s.io/apimachinery/pkg/util/wait" 14 ) 15 16 const securityGroupTypeName = "security group" 17 18 // listSecurityGroups lists security groups in the vpc. 19 func (o *ClusterUninstaller) listSecurityGroups() (cloudResources, error) { 20 o.Logger.Debugf("Listing security groups") 21 22 ctx, cancel := o.contextWithTimeout() 23 defer cancel() 24 25 select { 26 case <-ctx.Done(): 27 o.Logger.Debugf("listSecurityGroups: case <-ctx.Done()") 28 return nil, o.Context.Err() // we're cancelled, abort 29 default: 30 } 31 32 options := o.vpcSvc.NewListSecurityGroupsOptions() 33 resources, _, err := o.vpcSvc.ListSecurityGroupsWithContext(ctx, options) 34 35 if err != nil { 36 return nil, fmt.Errorf("failed to list security groups: %w", err) 37 } 38 39 var foundOne = false 40 41 result := []cloudResource{} 42 for _, securityGroup := range resources.SecurityGroups { 43 if strings.Contains(*securityGroup.Name, o.InfraID) { 44 foundOne = true 45 o.Logger.Debugf("listSecurityGroups: FOUND: %s, %s", *securityGroup.ID, *securityGroup.Name) 46 result = append(result, cloudResource{ 47 key: *securityGroup.ID, 48 name: *securityGroup.Name, 49 status: "", 50 typeName: securityGroupTypeName, 51 id: *securityGroup.ID, 52 }) 53 } 54 } 55 if !foundOne { 56 o.Logger.Debugf("listSecurityGroups: NO matching security group against: %s", o.InfraID) 57 for _, securityGroup := range resources.SecurityGroups { 58 o.Logger.Debugf("listSecurityGroups: security group: %s", *securityGroup.Name) 59 } 60 } 61 62 return cloudResources{}.insert(result...), nil 63 } 64 65 func (o *ClusterUninstaller) deleteSecurityGroup(item cloudResource) error { 66 var getOptions *vpcv1.GetSecurityGroupOptions 67 var response *core.DetailedResponse 68 var err error 69 70 ctx, cancel := o.contextWithTimeout() 71 defer cancel() 72 73 select { 74 case <-ctx.Done(): 75 o.Logger.Debugf("deleteSecurityGroup: case <-ctx.Done()") 76 return o.Context.Err() // we're cancelled, abort 77 default: 78 } 79 80 getOptions = o.vpcSvc.NewGetSecurityGroupOptions(item.id) 81 _, response, err = o.vpcSvc.GetSecurityGroup(getOptions) 82 83 if err != nil && response != nil && response.StatusCode == http.StatusNotFound { 84 // The resource is gone 85 o.deletePendingItems(item.typeName, []cloudResource{item}) 86 o.Logger.Infof("Deleted Security Group %q", item.name) 87 return nil 88 } 89 if err != nil && response != nil && response.StatusCode == http.StatusInternalServerError { 90 o.Logger.Infof("deleteSecurityGroup: internal server error") 91 return nil 92 } 93 94 deleteOptions := o.vpcSvc.NewDeleteSecurityGroupOptions(item.id) 95 96 _, err = o.vpcSvc.DeleteSecurityGroupWithContext(ctx, deleteOptions) 97 if err != nil { 98 return fmt.Errorf("failed to delete security group %s: %w", item.name, err) 99 } 100 101 o.Logger.Infof("Deleted Security Group %q", item.name) 102 o.deletePendingItems(item.typeName, []cloudResource{item}) 103 104 return nil 105 } 106 107 // destroySecurityGroups removes all security group resources that have a name prefixed 108 // with the cluster's infra ID. 109 func (o *ClusterUninstaller) destroySecurityGroups() error { 110 firstPassList, err := o.listSecurityGroups() 111 if err != nil { 112 return err 113 } 114 115 if len(firstPassList.list()) == 0 { 116 return nil 117 } 118 119 items := o.insertPendingItems(securityGroupTypeName, firstPassList.list()) 120 121 ctx, cancel := o.contextWithTimeout() 122 defer cancel() 123 124 for _, item := range items { 125 select { 126 case <-ctx.Done(): 127 o.Logger.Debugf("destroySecurityGroups: case <-ctx.Done()") 128 return o.Context.Err() // we're cancelled, abort 129 default: 130 } 131 132 backoff := wait.Backoff{ 133 Duration: 15 * time.Second, 134 Factor: 1.1, 135 Cap: leftInContext(ctx), 136 Steps: math.MaxInt32} 137 err = wait.ExponentialBackoffWithContext(ctx, backoff, func(context.Context) (bool, error) { 138 err2 := o.deleteSecurityGroup(item) 139 if err2 == nil { 140 return true, err2 141 } 142 o.errorTracker.suppressWarning(item.key, err2, o.Logger) 143 return false, err2 144 }) 145 if err != nil { 146 o.Logger.Fatal("destroySecurityGroups: ExponentialBackoffWithContext (destroy) returns ", err) 147 } 148 } 149 150 if items = o.getPendingItems(securityGroupTypeName); len(items) > 0 { 151 for _, item := range items { 152 o.Logger.Debugf("destroyServiceInstances: found %s in pending items", item.name) 153 } 154 return fmt.Errorf("destroySecurityGroups: %d undeleted items pending", len(items)) 155 } 156 157 backoff := wait.Backoff{ 158 Duration: 15 * time.Second, 159 Factor: 1.1, 160 Cap: leftInContext(ctx), 161 Steps: math.MaxInt32} 162 err = wait.ExponentialBackoffWithContext(ctx, backoff, func(context.Context) (bool, error) { 163 secondPassList, err2 := o.listSecurityGroups() 164 if err2 != nil { 165 return false, err2 166 } 167 if len(secondPassList) == 0 { 168 // We finally don't see any remaining instances! 169 return true, nil 170 } 171 for _, item := range secondPassList { 172 o.Logger.Debugf("destroySecurityGroups: found %s in second pass", item.name) 173 } 174 return false, nil 175 }) 176 if err != nil { 177 o.Logger.Fatal("destroySecurityGroups: ExponentialBackoffWithContext (list) returns ", err) 178 } 179 180 return nil 181 }