Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ require (
github.com/IBM-Cloud/bluemix-go v0.0.0-20211102075456-ffc4e11dfb16
github.com/IBM-Cloud/power-go-client v1.1.5
github.com/IBM/go-sdk-core/v4 v4.9.0
github.com/IBM/go-sdk-core/v5 v5.9.1
github.com/IBM/go-sdk-core/v5 v5.9.5
github.com/IBM/networking-go-sdk v0.14.0
github.com/IBM/platform-services-go-sdk v0.18.16
github.com/IBM/vpc-go-sdk v1.0.1
github.com/IBM/vpc-go-sdk v0.20.0
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1264
github.com/aliyun/aliyun-oss-go-sdk v2.1.8+incompatible
github.com/apparentlymart/go-cidr v1.1.0
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -101,18 +101,18 @@ github.com/IBM/go-sdk-core v1.1.0/go.mod h1:2pcx9YWsIsZ3I7kH+1amiAkXvLTZtAq9kbxs
github.com/IBM/go-sdk-core/v4 v4.5.1/go.mod h1:lTUXbqIX6/aAbSCkP6q59+dyFsTwZAc0ewRS2vJWVbg=
github.com/IBM/go-sdk-core/v4 v4.9.0 h1:OkSg5kaEfVoNuBA4IsIOz8Ur5rbGHbWxmWCZ7nK/oc0=
github.com/IBM/go-sdk-core/v4 v4.9.0/go.mod h1:DbQ+3pFoIjxGGTEiA9zQ2V0cemMNmFMkLBBnR729HKg=
github.com/IBM/go-sdk-core/v5 v5.2.0/go.mod h1:vyNdbFujJtdTj9HbihtvKwwS3k/GKSKpOx9ZIQ6MWDY=
github.com/IBM/go-sdk-core/v5 v5.4.0/go.mod h1:+MNa5Jbqb9FO7KEevo982Pb/YXr4adkyEffJlPs2TGc=
github.com/IBM/go-sdk-core/v5 v5.4.2/go.mod h1:Sn+z+qTDREQvCr+UFa22TqqfXNxx3o723y8GsfLV8e0=
github.com/IBM/go-sdk-core/v5 v5.9.1 h1:06pXbD9Rgmqqe2HA5YAeQbB4eYRRFgIoOT+Kh3cp1zo=
github.com/IBM/go-sdk-core/v5 v5.9.1/go.mod h1:axE2JrRq79gIJTjKPBwV6gWHswvVptBjbcvvCPIxARM=
github.com/IBM/go-sdk-core/v5 v5.9.5 h1:+uMyHpOyBlFFd/I0PB+7JqqXOPY2DzRR0tbBjTc4d/g=
github.com/IBM/go-sdk-core/v5 v5.9.5/go.mod h1:YlOwV9LeuclmT/qi/LAK2AsobbAP42veV0j68/rlZsE=
github.com/IBM/networking-go-sdk v0.14.0 h1:CWQufnSxynqxYORGbkSqePPSZ33fUijiwmcuZsMRv/Q=
github.com/IBM/networking-go-sdk v0.14.0/go.mod h1:8f3hEoWVUSYKbaIj7WZhdeJaseYGDSY85Iz+PqxLEbQ=
github.com/IBM/platform-services-go-sdk v0.18.16 h1:blYycstPoNtPKtu1uZe240WvzcJENy/Lzx+HMUA8bOo=
github.com/IBM/platform-services-go-sdk v0.18.16/go.mod h1:awc7TZUeGMlToSeMSaWEz34Knf0lQnuGWumcI4pcuoM=
github.com/IBM/vpc-go-sdk v0.6.0/go.mod h1:wxicPDnSTPXt1eNxSO/9KNGqOW9RMgxPoSh4gd8KJY4=
github.com/IBM/vpc-go-sdk v1.0.1 h1:D2cu4KRsM8Q8bLWz/uxp8m7nzUm33mcgDv1sD0w/E8M=
github.com/IBM/vpc-go-sdk v1.0.1/go.mod h1:bhd7r482lV30UJz46r2oRgYGawGEo+TuS41ZLIY65y0=
github.com/IBM/vpc-go-sdk v0.20.0 h1:xetXFYv/GDSOVTm2h7MSki2D9x2dpNsiwHVRmdSIrPc=
github.com/IBM/vpc-go-sdk v0.20.0/go.mod h1:YPyIfI+/qhPqlYp+I7dyx2U1GLcXgp/jzVvsZfUH4y8=
github.com/InVisionApp/go-health v2.1.0+incompatible/go.mod h1:/+Gv1o8JUsrjC6pi6MN6/CgKJo4OqZ6x77XAnImrzhg=
github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E=
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
Expand Down
128 changes: 128 additions & 0 deletions pkg/destroy/ibmcloud/disk.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package ibmcloud

import (
"net/http"
"strings"

"github.com/pkg/errors"
)

func (o *ClusterUninstaller) listDisks() ([]cloudResource, error) {
o.Logger.Infof("Listing disks")

result := []cloudResource{}
clusterOwnedTag := o.clusterLabelFilter()
options := o.vpcSvc.NewListVolumesOptions()

for {
ctx, cancel := o.contextWithTimeout()
defer cancel()
options.SetLimit(100)
resources, _, err := o.vpcSvc.ListVolumesWithContext(ctx, options)
if err != nil {
return nil, errors.Wrap(err, "Listing disks failed")
}

for _, volume := range resources.Volumes {
userTags := strings.Join(volume.UserTags, ",")
if strings.Contains(userTags, clusterOwnedTag) {
o.Logger.Debugf("Found disk: %s", *volume.ID)
result = append(result, cloudResource{
key: *volume.ID,
name: *volume.Name,
status: *volume.Status,
typeName: "disk",
id: *volume.ID,
})
}
}

//This was the last page, please exit the loop.
if resources.Next == nil {
o.Logger.Debugf("All disks fetched")
break
}

//Set the start for the next page.
start, _ := resources.GetNextStart()
o.Logger.Debugf("Listing next page %s", *start)
options.SetStart(*start)
}
return result, nil
}

func (o *ClusterUninstaller) deleteDisk(item cloudResource) error {
o.Logger.Infof("Deleting disk %s", item.id)
ctx, cancel := o.contextWithTimeout()
defer cancel()
options := o.vpcSvc.NewDeleteVolumeOptions(item.id)
details, err := o.vpcSvc.DeleteVolumeWithContext(ctx, options)

if err != nil && details.StatusCode != http.StatusNotFound {
return errors.Wrapf(err, "Failed to delete disk name=%s, id=%s.If this error continues to persist for more than 20 minutes then please try to manually cleanup the volume using - ibmcloud is vold %s", item.name, item.id, item.id)
}

if err != nil && details.StatusCode == http.StatusNotFound {
// The resource is gone
o.deletePendingItems(item.typeName, []cloudResource{item})
o.Logger.Infof("Deleted disk %s", item.id)
}

return nil
}

func (o *ClusterUninstaller) waitForDiskDeletion(item cloudResource) error {
o.Logger.Infof("Waiting for disk %s to be deleted", item.id)
var skip = false

err := o.Retry(func() (error, bool) {
ctx, cancel := o.contextWithTimeout()
defer cancel()
volumeOptions := o.vpcSvc.NewGetVolumeOptions(item.id)
_, response, err := o.vpcSvc.GetVolumeWithContext(ctx, volumeOptions)
// Keep retry, until GetVolume returns volume not found
if err != nil && response.StatusCode == http.StatusNotFound {
skip = true
return nil, skip
}
return err, false // continue retry as we are not seeing error which means volume is available
})

if err == nil && skip {
// The resource is gone
o.deletePendingItems(item.typeName, []cloudResource{item})
o.Logger.Infof("Deleted disk %s", item.id)
} else {
return errors.Wrapf(err, "Failed to delete disk name=%s, id=%s.If this error continues to persist for more than 20 minutes then please try to manually cleanup the volume using - ibmcloud is vold %s", item.name, item.id, item.id)
}

return err
}

// destroyDisks removes all disk resources that have a name prefixed
// with the cluster's infra ID.
func (o *ClusterUninstaller) destroyDisks() error {
found, err := o.listDisks()
if err != nil {
return err
}
items := o.insertPendingItems("disk", found)
for _, item := range items {
err := o.deleteDisk(item)
if err != nil {
o.errorTracker.suppressWarning(item.key, err, o.Logger)
}
}

for _, item := range items {
err := o.waitForDiskDeletion(item)
if err != nil {
o.errorTracker.suppressWarning(item.key, err, o.Logger)
}
}

if items = o.getPendingItems("disk"); len(items) > 0 {
return errors.Errorf("%d items pending", len(items))
}
return nil
}
30 changes: 30 additions & 0 deletions pkg/destroy/ibmcloud/ibmcloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ type ClusterUninstaller struct {
iamPolicyManagementSvc *iampolicymanagementv1.IamPolicyManagementV1
zonesSvc *zonesv1.ZonesV1
dnsRecordsSvc *dnsrecordsv1.DnsRecordsV1
maxRetryAttempt int

resourceGroupID string
cosInstanceID string
Expand All @@ -74,9 +75,33 @@ func New(logger logrus.FieldLogger, metadata *types.ClusterMetadata) (providers.
UserProvidedSubnets: metadata.ClusterPlatformMetadata.IBMCloud.Subnets,
UserProvidedVPC: metadata.ClusterPlatformMetadata.IBMCloud.VPC,
pendingItemTracker: newPendingItemTracker(),
maxRetryAttempt: 30,
}, nil
}

// Retry ...
func (o *ClusterUninstaller) Retry(funcToRetry func() (error, bool)) error {
var err error
var stopRetry bool
retryGap := 10
for i := 0; i < o.maxRetryAttempt; i++ {
if i > 0 {
time.Sleep(time.Duration(retryGap) * time.Second)
}
// Call function which required retry, retry is decided by function itself
err, stopRetry = funcToRetry()
if stopRetry {
break
}

if (i + 1) < o.maxRetryAttempt {
o.Logger.Infof("UNEXPECTED RESULT, Re-attempting execution .., attempt=%d, retry-gap=%d, max-retry-Attempts=%d, stopRetry=%t, error=%v", i+1,
retryGap, o.maxRetryAttempt, stopRetry, err)
}
}
return err
}

// Run is the entrypoint to start the uninstall process
func (o *ClusterUninstaller) Run() (*types.ClusterQuota, error) {
err := o.loadSDKServices()
Expand All @@ -100,6 +125,7 @@ func (o *ClusterUninstaller) destroyCluster() error {
{name: "Stop instances", execute: o.stopInstances},
}, {
{name: "Instances", execute: o.destroyInstances},
{name: "Disks", execute: o.destroyDisks},
}, {
{name: "Load Balancers", execute: o.destroyLoadBalancers},
}, {
Expand Down Expand Up @@ -403,3 +429,7 @@ func (t pendingItemTracker) deletePendingItems(itemType string, items []cloudRes
func isErrorStatus(code int64) bool {
return code != 0 && (code < 200 || code >= 300)
}

func (o *ClusterUninstaller) clusterLabelFilter() string {
return fmt.Sprintf("kubernetes-io-cluster-%s:owned", o.InfraID)
}
Loading