github.com/openshift/installer@v1.4.17/pkg/destroy/gcp/serviceaccount.go (about) 1 package gcp 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/pkg/errors" 8 "google.golang.org/api/iam/v1" 9 "k8s.io/apimachinery/pkg/util/sets" 10 11 "github.com/openshift/installer/pkg/types/gcp" 12 ) 13 14 // listServiceAccounts retrieves all service accounts with a display name prefixed with the cluster's 15 // infra ID. Filtering is done client side because the API doesn't offer filtering for service accounts. 16 func (o *ClusterUninstaller) listServiceAccounts(ctx context.Context) ([]cloudResource, error) { 17 o.Logger.Debugf("Listing service accounts") 18 19 result := []cloudResource{} 20 sas, err := o.listClusterServiceAccount(ctx) 21 if err != nil { 22 errors.Wrapf(err, "failed to fetch service accounts for the cluster") 23 } 24 for _, item := range sas { 25 o.Logger.Debugf("Found service account: %s", item.Name) 26 result = append(result, cloudResource{ 27 key: item.Name, 28 name: item.Name, 29 url: item.Email, 30 typeName: "serviceaccount", 31 quota: []gcp.QuotaUsage{{ 32 Metric: &gcp.Metric{ 33 Service: gcp.ServiceIAMAPI, 34 Limit: "quota/service-account-count", 35 }, 36 Amount: 1, 37 }}, 38 }) 39 } 40 return result, nil 41 } 42 43 func (o *ClusterUninstaller) listClusterServiceAccount(ctx context.Context) ([]*iam.ServiceAccount, error) { 44 ctx, cancel := context.WithTimeout(ctx, defaultTimeout) 45 defer cancel() 46 result := []*iam.ServiceAccount{} 47 req := o.iamSvc.Projects.ServiceAccounts.List(fmt.Sprintf("projects/%s", o.ProjectID)).Fields("accounts(name,displayName,email),nextPageToken") 48 err := req.Pages(ctx, func(list *iam.ListServiceAccountsResponse) error { 49 for idx, item := range list.Accounts { 50 if o.isClusterResource(item.Email) || o.isClusterResource(item.DisplayName) { 51 result = append(result, list.Accounts[idx]) 52 } 53 } 54 return nil 55 }) 56 if err != nil { 57 return nil, errors.Wrapf(err, "failed to fetch service accounts") 58 } 59 return result, nil 60 } 61 62 func (o *ClusterUninstaller) deleteServiceAccount(ctx context.Context, item cloudResource) error { 63 o.Logger.Debugf("Deleting service account %s", item.name) 64 ctx, cancel := context.WithTimeout(ctx, defaultTimeout) 65 defer cancel() 66 _, err := o.iamSvc.Projects.ServiceAccounts.Delete(item.name).Context(ctx).Do() 67 if err != nil && !isNoOp(err) { 68 return errors.Wrapf(err, "failed to delete service account %s", item.name) 69 } 70 o.deletePendingItems(item.typeName, []cloudResource{item}) 71 o.Logger.Infof("Deleted service account %s", item.name) 72 return nil 73 } 74 75 // destroyServiceAccounts removes service accounts with a display name prefixed 76 // with the cluster's infra ID. 77 func (o *ClusterUninstaller) destroyServiceAccounts(ctx context.Context) error { 78 found, err := o.listServiceAccounts(ctx) 79 if err != nil { 80 return err 81 } 82 items := o.insertPendingItems("serviceaccount", found) 83 if len(items) == 0 { 84 return nil 85 } 86 87 // Remove service accounts from project policy 88 policy, err := o.getProjectIAMPolicy(ctx) 89 if err != nil { 90 return err 91 } 92 emails := sets.NewString() 93 for _, item := range items { 94 emails.Insert(item.url) 95 } 96 if o.clearIAMPolicyBindings(policy, emails, o.Logger) { 97 err = o.setProjectIAMPolicy(ctx, policy) 98 if err != nil { 99 o.errorTracker.suppressWarning("iampolicy", err, o.Logger) 100 return errors.Errorf("%d items pending", len(items)) 101 } 102 o.Logger.Infof("Deleted IAM project role bindings") 103 } 104 105 for _, item := range items { 106 err := o.deleteServiceAccount(ctx, item) 107 if err != nil { 108 o.errorTracker.suppressWarning(item.key, err, o.Logger) 109 } 110 } 111 if items = o.getPendingItems("serviceaccount"); len(items) > 0 { 112 return errors.Errorf("%d items pending", len(items)) 113 } 114 return nil 115 }