11/*
2- Copyright 2019 Google LLC
2+ Copyright 2019-2024 Google LLC
33
44Licensed under the Apache License, Version 2.0 (the "License");
55you may not use this file except in compliance with the License.
@@ -29,6 +29,8 @@ import (
2929
3030 asset "cloud.google.com/go/asset/apiv1"
3131 "cloud.google.com/go/asset/apiv1/assetpb"
32+ container "cloud.google.com/go/container/apiv1"
33+ "cloud.google.com/go/container/apiv1/containerpb"
3234 securitycenter "cloud.google.com/go/securitycenter/apiv1"
3335 "cloud.google.com/go/securitycenter/apiv1/securitycenterpb"
3436 "golang.org/x/net/context"
@@ -240,7 +242,7 @@ func getRegexListFromEnv(envVariableName string) []*regexp.Regexp {
240242 logger .Printf ("Got Regex list [%s] from [%s] env variable" , regexList , envVariableName )
241243 }
242244
243- //build Regexes
245+ // build Regexes
244246 for _ , r := range regexList {
245247 result , err := regexp .Compile (r )
246248 if err != nil {
@@ -381,7 +383,7 @@ func getBillingAccountSinkServiceOrTerminateExecution(ctx context.Context, clien
381383 return loggingService .BillingAccounts .Sinks
382384}
383385
384- func getSCCNotificationServiceOrTerminateExecution (ctx context.Context , client * http. Client ) * securitycenter.Client {
386+ func getSCCNotificationServiceOrTerminateExecution (ctx context.Context ) * securitycenter.Client {
385387 logger .Println ("Try to get SCC Notification Service" )
386388 securitycenterClient , err := securitycenter .NewClient (ctx )
387389 if err != nil {
@@ -391,7 +393,7 @@ func getSCCNotificationServiceOrTerminateExecution(ctx context.Context, client *
391393 return securitycenterClient
392394}
393395
394- func getAssetServiceOrTerminateExecution (ctx context.Context , client * http. Client ) * asset.Client {
396+ func getAssetServiceOrTerminateExecution (ctx context.Context ) * asset.Client {
395397 logger .Println ("Try to get Asset Service" )
396398 assetService , err := asset .NewClient (ctx )
397399 if err != nil {
@@ -401,6 +403,16 @@ func getAssetServiceOrTerminateExecution(ctx context.Context, client *http.Clien
401403 return assetService
402404}
403405
406+ func getContainerServiceOrTerminateExecution (ctx context.Context ) * container.ClusterManagerClient {
407+ logger .Println ("Try to get Container Service" )
408+ containerService , err := container .NewClusterManagerClient (ctx )
409+ if err != nil {
410+ logger .Fatalf ("Failed to get Container Service with error [%s], terminate execution" , err .Error ())
411+ }
412+ logger .Println ("Got Container Service" )
413+ return containerService
414+ }
415+
404416func getFirewallPoliciesServiceOrTerminateExecution (ctx context.Context , client * http.Client ) * compute.FirewallPoliciesService {
405417 logger .Println ("Try to get Firewall Policies Service" )
406418 computeService , err := compute .NewService (ctx , option .WithHTTPClient (client ))
@@ -426,12 +438,13 @@ func invoke(ctx context.Context) {
426438 cloudResourceManagerService := getResourceManagerServiceOrTerminateExecution (ctx , client )
427439 folderService := getFolderServiceOrTerminateExecution (ctx , client )
428440 tagKeyService := getTagKeysServiceOrTerminateExecution (ctx , client )
429- sccService := getSCCNotificationServiceOrTerminateExecution (ctx , client )
441+ sccService := getSCCNotificationServiceOrTerminateExecution (ctx )
430442 tagValuesService := getTagValuesServiceOrTerminateExecution (ctx , client )
431- feedsService := getAssetServiceOrTerminateExecution (ctx , client )
443+ feedsService := getAssetServiceOrTerminateExecution (ctx )
432444 billingSinkService := getBillingAccountSinkServiceOrTerminateExecution (ctx , client )
433445 firewallPoliciesService := getFirewallPoliciesServiceOrTerminateExecution (ctx , client )
434446 endpointService := getServiceManagementServiceOrTerminateExecution (ctx , client )
447+ containerService := getContainerServiceOrTerminateExecution (ctx )
435448
436449 removeLien := func (name string ) {
437450 logger .Printf ("Try to remove lien [%s]" , name )
@@ -576,7 +589,7 @@ func invoke(ctx context.Context) {
576589 return
577590 }
578591 for _ , sink := range sinkList .Sinks {
579- if sink .Name != "_Required" && sink .Name != "_Default" && billingSinkAgeFilter (sink ) && checkIfNameIncluded (sink .ResourceName , targetBillingSinks ) {
592+ if sink .Name != "_Required" && sink .Name != "_Default" && billingSinkAgeFilter (sink ) && checkIfNameIncluded (sink .ResourceName , targetBillingSinks ) {
580593 _ , err = billingSinkService .Delete (sink .ResourceName ).Context (ctx ).Do ()
581594 if err != nil {
582595 logger .Printf ("Failed to delete billing account log sink [%s] from billing account [%s], error [%s]" , sink .ResourceName , billing , err .Error ())
@@ -611,6 +624,48 @@ func invoke(ctx context.Context) {
611624 return err
612625 }
613626
627+ removeProjectClusters := func (projectId string ) int {
628+ logger .Printf ("Try to remove clusters for [%s]" , projectId )
629+ reqLCR := & containerpb.ListClustersRequest {Parent : fmt .Sprintf ("projects/%s/locations/*" , projectId )}
630+ listResponse , err := containerService .ListClusters (ctx , reqLCR )
631+ if err != nil {
632+ logger .Printf ("Failed to list clusters for [%s], error [%s]" , projectId , err .Error ())
633+ return 0
634+ }
635+
636+ logger .Printf ("Got [%d] clusters for project [%s]" , len (listResponse .Clusters ), projectId )
637+ if len (listResponse .Clusters ) == 0 {
638+ return 0
639+ }
640+
641+ var pendingDeletion int = 0
642+ for _ , cluster := range listResponse .Clusters {
643+ switch clusterStatus := cluster .Status .String (); clusterStatus {
644+ case "DEGRADED" :
645+ fallthrough
646+ case "RUNNING" :
647+ logger .Printf ("Deleting cluster %s status: %s" , cluster .Name , clusterStatus )
648+ reqDCR := & containerpb.DeleteClusterRequest {Name : fmt .Sprintf ("projects/%s/locations/%s/clusters/%s" , projectId , cluster .Location , cluster .Name )}
649+ _ , err := containerService .DeleteCluster (ctx , reqDCR )
650+ if err != nil {
651+ logger .Printf ("Failed to delete cluster [%s] for [%s], error [%s]" , cluster .Name , projectId , err .Error ())
652+ } else {
653+ pendingDeletion ++
654+ }
655+ case "PROVISIONING" :
656+ fallthrough
657+ case "RECONCILING" :
658+ fallthrough
659+ case "STOPPING" :
660+ logger .Printf ("Deferring cluster %s status: %s" , cluster .Name , clusterStatus )
661+ pendingDeletion ++
662+ default :
663+ logger .Printf ("Ignoring cluster %s status: %s" , cluster .Name , clusterStatus )
664+ }
665+ }
666+ return pendingDeletion
667+ }
668+
614669 removeProjectEndpoints := func (projectId string ) {
615670 logger .Printf ("Try to remove endpoints for [%s]" , projectId )
616671 listResponse , err := endpointService .Services .List ().ProducerProjectId (projectId ).Do ()
@@ -638,6 +693,9 @@ func invoke(ctx context.Context) {
638693
639694 cleanupProjectById := func (projectId string ) {
640695 logger .Printf ("Try to remove project [%s]" , projectId )
696+ if clusters := removeProjectClusters (projectId ); clusters != 0 {
697+ logger .Printf ("Defer removing project [%s], %d clusters marked for deletion" , projectId , clusters )
698+ }
641699 err := removeProjectById (projectId )
642700 if err != nil {
643701 removeProjectEndpoints (projectId )
@@ -738,7 +796,7 @@ func invoke(ctx context.Context) {
738796 removeSCCNotifications (organizationId )
739797 }
740798
741- //Only delete Feeds from deleted projects
799+ // Only delete Feeds from deleted projects
742800 if cleanUpCaiFeeds {
743801 removeFeedsByName (organizationId )
744802 }
0 commit comments