github.com/openshift/installer@v1.4.17/pkg/destroy/ibmcloud/instance.go (about)

     1  package ibmcloud
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"strings"
     7  
     8  	"github.com/IBM/go-sdk-core/v5/core"
     9  	"github.com/IBM/vpc-go-sdk/vpcv1"
    10  	"github.com/pkg/errors"
    11  )
    12  
    13  const (
    14  	instanceTypeName       = "instance"
    15  	instanceActionTypeName = "instance action"
    16  )
    17  
    18  func (o *ClusterUninstaller) listInstances() (cloudResources, error) {
    19  	o.Logger.Debugf("Listing virtual service instances")
    20  	ctx, cancel := o.contextWithTimeout()
    21  	defer cancel()
    22  
    23  	options := o.vpcSvc.NewListInstancesOptions()
    24  	if len(o.UserProvidedVPC) > 0 {
    25  		options.SetVPCName(o.UserProvidedVPC)
    26  	} else {
    27  		options.SetVPCName(fmt.Sprintf("%s-vpc", o.InfraID))
    28  	}
    29  	resources, _, err := o.vpcSvc.ListInstancesWithContext(ctx, options)
    30  	if err != nil {
    31  		return nil, err
    32  	}
    33  
    34  	result := []cloudResource{}
    35  	for _, instance := range resources.Instances {
    36  		if strings.Contains(*instance.Name, o.InfraID) {
    37  			result = append(result, cloudResource{
    38  				key:      *instance.ID,
    39  				name:     *instance.Name,
    40  				status:   *instance.Status,
    41  				typeName: "instance",
    42  				id:       *instance.ID,
    43  			})
    44  		}
    45  	}
    46  	return cloudResources{}.insert(result...), nil
    47  }
    48  
    49  // stopInstances searches for instances in the vpc that have a name that starts with
    50  // the infra ID prefix and are not yet stopped. It then stops each instance found.
    51  func (o *ClusterUninstaller) stopInstances() error {
    52  	found, err := o.listInstances()
    53  	if err != nil {
    54  		return err
    55  	}
    56  
    57  	items := o.insertPendingItems(instanceActionTypeName, found.list())
    58  	for _, item := range items {
    59  		if _, ok := found[item.key]; !ok {
    60  			// This item has been removed.
    61  			o.deletePendingItems(instanceActionTypeName, []cloudResource{item})
    62  			o.Logger.Warnf("Instance %q not found", item.name)
    63  			continue
    64  		}
    65  		err := o.stopInstance(item)
    66  		if err != nil {
    67  			o.errorTracker.suppressWarning(item.key, err, o.Logger)
    68  		}
    69  	}
    70  
    71  	if items = o.getPendingItems(instanceActionTypeName); len(items) > 0 {
    72  		return errors.Errorf("%d items pending", len(items))
    73  	}
    74  	return nil
    75  }
    76  
    77  func (o *ClusterUninstaller) stopInstance(item cloudResource) error {
    78  	if item.status == vpcv1.InstanceStatusStoppingConst {
    79  		o.Logger.Debugf("Waiting for instance %q to stop", item.name)
    80  		return nil
    81  	}
    82  
    83  	if item.status == vpcv1.InstanceStatusStoppedConst {
    84  		o.Logger.Infof("Stopped instance %q", item.name)
    85  		o.deletePendingItems(instanceActionTypeName, []cloudResource{item})
    86  		return nil
    87  	}
    88  
    89  	o.Logger.Debugf("Stopping instance %q", item.name)
    90  	ctx, cancel := o.contextWithTimeout()
    91  	defer cancel()
    92  
    93  	options := &vpcv1.CreateInstanceActionOptions{
    94  		InstanceID: core.StringPtr(item.id),
    95  		Type:       core.StringPtr(vpcv1.CreateInstanceActionOptionsTypeStopConst),
    96  	}
    97  
    98  	_, _, err := o.vpcSvc.CreateInstanceActionWithContext(ctx, options)
    99  	if err != nil {
   100  		return errors.Wrapf(err, "Failed to stop instance %q", item.name)
   101  	}
   102  
   103  	return nil
   104  }
   105  
   106  func (o *ClusterUninstaller) deleteInstance(item cloudResource) error {
   107  	if item.status == vpcv1.InstanceStatusDeletingConst {
   108  		o.Logger.Debugf("Waiting for instance %q to delete", item.name)
   109  		return nil
   110  	}
   111  
   112  	o.Logger.Debugf("Deleting instance %q", item.name)
   113  	ctx, cancel := o.contextWithTimeout()
   114  	defer cancel()
   115  
   116  	options := o.vpcSvc.NewDeleteInstanceOptions(item.id)
   117  	details, err := o.vpcSvc.DeleteInstanceWithContext(ctx, options)
   118  
   119  	if err != nil && details != nil && details.StatusCode == http.StatusNotFound {
   120  		// The resource is gone
   121  		o.deletePendingItems(item.typeName, []cloudResource{item})
   122  		o.Logger.Infof("Deleted instance %q", item.name)
   123  		return nil
   124  	}
   125  
   126  	if err != nil && details != nil && details.StatusCode != http.StatusNotFound {
   127  		return errors.Wrapf(err, "Failed to delete instance %q", item.name)
   128  	}
   129  
   130  	return nil
   131  }
   132  
   133  // destroyInstances searches for instances that have a name that starts with
   134  // the cluster's infra ID.
   135  func (o *ClusterUninstaller) destroyInstances() error {
   136  	found, err := o.listInstances()
   137  	if err != nil {
   138  		return err
   139  	}
   140  
   141  	items := o.insertPendingItems(instanceTypeName, found.list())
   142  	for _, item := range items {
   143  		if _, ok := found[item.key]; !ok {
   144  			// This item has finished deletion.
   145  			o.deletePendingItems(item.typeName, []cloudResource{item})
   146  			o.Logger.Infof("Deleted instance %q", item.name)
   147  			continue
   148  		}
   149  		err := o.deleteInstance(item)
   150  		if err != nil {
   151  			o.errorTracker.suppressWarning(item.key, err, o.Logger)
   152  		}
   153  	}
   154  
   155  	if items = o.getPendingItems(instanceTypeName); len(items) > 0 {
   156  		return errors.Errorf("%d items pending", len(items))
   157  	}
   158  	return nil
   159  }