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 }