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  }