github.com/openshift/installer@v1.4.17/pkg/destroy/ibmcloud/securitygroup.go (about) 1 package ibmcloud 2 3 import ( 4 "net/http" 5 "reflect" 6 "strings" 7 8 "github.com/IBM/vpc-go-sdk/vpcv1" 9 "github.com/pkg/errors" 10 ) 11 12 const ( 13 securityGroupTypeName = "security group" 14 securityGroupRuleTypeName = "security group rule" 15 ) 16 17 // listSecurityGroups lists security groups in the vpc 18 func (o *ClusterUninstaller) listSecurityGroups() (cloudResources, error) { 19 o.Logger.Debugf("Listing security groups") 20 ctx, cancel := o.contextWithTimeout() 21 defer cancel() 22 23 options := o.vpcSvc.NewListSecurityGroupsOptions() 24 resources, _, err := o.vpcSvc.ListSecurityGroupsWithContext(ctx, options) 25 if err != nil { 26 return nil, errors.Wrapf(err, "Failed to list security groups") 27 } 28 29 result := []cloudResource{} 30 for _, securityGroup := range resources.SecurityGroups { 31 if strings.Contains(*securityGroup.Name, o.InfraID) { 32 result = append(result, cloudResource{ 33 key: *securityGroup.ID, 34 name: *securityGroup.Name, 35 status: "", 36 typeName: securityGroupTypeName, 37 id: *securityGroup.ID, 38 }) 39 } 40 } 41 42 return cloudResources{}.insert(result...), nil 43 } 44 45 func (o *ClusterUninstaller) listSecurityGroupRules(securityGroupID string) (cloudResources, error) { 46 o.Logger.Debugf("Listing security group rules for %q", securityGroupID) 47 ctx, cancel := o.contextWithTimeout() 48 defer cancel() 49 50 options := o.vpcSvc.NewListSecurityGroupRulesOptions(securityGroupID) 51 resources, _, err := o.vpcSvc.ListSecurityGroupRulesWithContext(ctx, options) 52 if err != nil { 53 return nil, errors.Wrapf(err, "Failed to list security group rules for %q", securityGroupID) 54 } 55 56 result := []cloudResource{} 57 for _, securityGroupRule := range resources.Rules { 58 switch reflect.TypeOf(securityGroupRule).String() { 59 60 case "*vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolAll": 61 { 62 rule := securityGroupRule.(*vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolAll) 63 result = append(result, cloudResource{ 64 key: *rule.ID, 65 name: *rule.ID, 66 status: "", 67 typeName: securityGroupRuleTypeName, 68 id: *rule.ID, 69 }) 70 } 71 case "*vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolIcmp": 72 { 73 rule := securityGroupRule.(*vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolIcmp) 74 result = append(result, cloudResource{ 75 key: *rule.ID, 76 name: *rule.ID, 77 status: "", 78 typeName: securityGroupRuleTypeName, 79 id: *rule.ID, 80 }) 81 } 82 case "*vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolTcpudp": 83 { 84 rule := securityGroupRule.(*vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolTcpudp) 85 result = append(result, cloudResource{ 86 key: *rule.ID, 87 name: *rule.ID, 88 status: "", 89 typeName: securityGroupRuleTypeName, 90 id: *rule.ID, 91 }) 92 } 93 default: 94 { 95 o.Logger.Debugf("Unknown rule: %q", securityGroupRule) 96 } 97 } 98 } 99 100 return cloudResources{}.insert(result...), nil 101 } 102 103 func (o *ClusterUninstaller) deleteSecurityGroup(item cloudResource) error { 104 o.Logger.Debugf("Deleting security group %q", item.name) 105 ctx, cancel := o.contextWithTimeout() 106 defer cancel() 107 108 found, err := o.listSecurityGroupRules(item.id) 109 if err != nil { 110 return err 111 } 112 113 rules := o.insertPendingItems(securityGroupRuleTypeName, found.list()) 114 115 for _, rule := range rules { 116 if _, ok := found[rule.key]; !ok { 117 // This item has finished deletion. 118 o.deletePendingItems(rule.typeName, []cloudResource{rule}) 119 o.Logger.Infof("Deleted security group rule %q", rule.name) 120 continue 121 } 122 err = o.deleteSecurityGroupRule(rule, item.id) 123 if err != nil { 124 o.errorTracker.suppressWarning(rule.key, err, o.Logger) 125 } 126 } 127 128 if rules = o.getPendingItems(securityGroupRuleTypeName); len(rules) > 0 { 129 return errors.Errorf("%d items pending", len(rules)) 130 } 131 132 options := o.vpcSvc.NewDeleteSecurityGroupOptions(item.id) 133 details, err := o.vpcSvc.DeleteSecurityGroupWithContext(ctx, options) 134 135 if err != nil && details != nil && details.StatusCode == http.StatusNotFound { 136 // The resource is gone 137 o.deletePendingItems(item.typeName, []cloudResource{item}) 138 o.Logger.Infof("Deleted security group %q", item.name) 139 return nil 140 } 141 142 if err != nil && details != nil && details.StatusCode != http.StatusNotFound { 143 return errors.Wrapf(err, "Failed to delete security group %s", item.name) 144 } 145 146 return nil 147 } 148 149 func (o *ClusterUninstaller) deleteSecurityGroupRule(item cloudResource, securityGroupID string) error { 150 o.Logger.Debugf("Deleting security group rule %q", item.name) 151 ctx, cancel := o.contextWithTimeout() 152 defer cancel() 153 154 options := o.vpcSvc.NewDeleteSecurityGroupRuleOptions(securityGroupID, item.id) 155 details, err := o.vpcSvc.DeleteSecurityGroupRuleWithContext(ctx, options) 156 if err != nil && details != nil && details.StatusCode == http.StatusNotFound { 157 // The resource is gone 158 o.deletePendingItems(item.typeName, []cloudResource{item}) 159 o.Logger.Infof("Deleted security group rule %q", item.name) 160 return nil 161 } 162 163 if err != nil && details != nil && details.StatusCode != http.StatusNotFound { 164 return errors.Wrapf(err, "Failed to delete security group rule %s", item.name) 165 } 166 167 return nil 168 } 169 170 // destroySecurityGroups removes all security group resources that have a name prefixed 171 // with the cluster's infra ID. 172 func (o *ClusterUninstaller) destroySecurityGroups() error { 173 if o.UserProvidedVPC == "" { 174 o.Logger.Info("Skipping deletion of security groups with generated VPC") 175 return nil 176 } 177 178 found, err := o.listSecurityGroups() 179 if err != nil { 180 return err 181 } 182 183 items := o.insertPendingItems(securityGroupTypeName, found.list()) 184 185 for _, item := range items { 186 if _, ok := found[item.key]; !ok { 187 // This item has finished deletion. 188 o.deletePendingItems(item.typeName, []cloudResource{item}) 189 o.Logger.Infof("Deleted security group %q", item.name) 190 continue 191 } 192 err = o.deleteSecurityGroup(item) 193 if err != nil { 194 o.errorTracker.suppressWarning(item.key, err, o.Logger) 195 } 196 } 197 198 if items = o.getPendingItems(securityGroupTypeName); len(items) > 0 { 199 return errors.Errorf("%d items pending", len(items)) 200 } 201 return nil 202 }