@@ -101,7 +101,7 @@ func ResourceStorageBucket() *schema.Resource {
101
101
Type: schema.TypeBool,
102
102
Optional: true,
103
103
Default: false,
104
- Description: `When deleting a bucket, this boolean option will delete all contained objects. If you try to delete a bucket that contains objects, Terraform will fail that run.`,
104
+ Description: `When deleting a bucket, this boolean option will delete all contained objects, or anywhereCaches (if any) . If you try to delete a bucket that contains objects or anywhereCaches , Terraform will fail that run.`,
105
105
},
106
106
107
107
"labels": {
@@ -590,6 +590,98 @@ func labelKeyValidator(val interface{}, key string) (warns []string, errs []erro
590
590
return
591
591
}
592
592
593
+ func getAnywhereCacheListResult(config *transport_tpg.Config, bucket string) ([]interface{}, error) {
594
+ // Define the cache list URL
595
+ cacheListUrl := fmt.Sprintf("https://storage.googleapis.com/storage/v1/b/%s/anywhereCaches/", bucket)
596
+
597
+ // Send request to get resource list
598
+ res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
599
+ Config: config,
600
+ Method: "GET",
601
+ Project: config.Project,
602
+ RawURL: cacheListUrl,
603
+ UserAgent: config.UserAgent,
604
+ })
605
+ if err != nil {
606
+ return nil, err
607
+ }
608
+
609
+ resourceList, ok := res["items"]
610
+ if !ok {
611
+ return nil, nil // No cache exists, return nil list and no error
612
+ }
613
+
614
+ rl, ok := resourceList.([]interface{})
615
+ if !ok {
616
+ return nil, fmt.Errorf("unexpected type for resource list: %T", resourceList)
617
+ }
618
+
619
+ return rl, nil
620
+ }
621
+
622
+ func deleteAnywhereCacheIfAny(config *transport_tpg.Config, bucket string) error {
623
+ // Get the initial list of Anywhere Caches
624
+ cacheList, err := getAnywhereCacheListResult(config, bucket)
625
+ if err != nil {
626
+ return err
627
+ }
628
+
629
+ // If no cache exists initially, return early
630
+ if len(cacheList) == 0 {
631
+ return nil
632
+ }
633
+
634
+ // Iterate over each object in the resource list
635
+ for _, item := range cacheList {
636
+ // Ensure the item is a map
637
+ obj, ok := item.(map[string]interface{})
638
+ if !ok {
639
+ return fmt.Errorf("unexpected type for resource list item: %T", item)
640
+ }
641
+
642
+ // Check the state of the object
643
+ state, ok := obj["state"].(string)
644
+ if !ok {
645
+ continue // If state is not a string, skip this item
646
+ }
647
+ if state != "running" && state != "paused" {
648
+ continue
649
+ }
650
+
651
+ // Disable the cache if state is running or paused
652
+ anywhereCacheId, ok := obj["anywhereCacheId"].(string)
653
+ if !ok {
654
+ return fmt.Errorf("missing or invalid anywhereCacheId: %v", obj)
655
+ }
656
+ disableUrl := fmt.Sprintf("https://storage.googleapis.com/storage/v1/b/%s/anywhereCaches/%s/disable", bucket, anywhereCacheId)
657
+ _, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
658
+ Config: config,
659
+ Method: "POST",
660
+ Project: config.Project,
661
+ RawURL: disableUrl,
662
+ UserAgent: config.UserAgent,
663
+ })
664
+ if err != nil {
665
+ return err
666
+ }
667
+ }
668
+ time.Sleep(80 * time.Minute) // It takes around 70 minutes of time for cache to finally delete post it disable time.
669
+
670
+ // Post this time, we check again!
671
+ // Get the list of Anywhere Caches after the sleep
672
+ cacheList, err = getAnywhereCacheList(config, bucket)
673
+ if err != nil {
674
+ return err
675
+ }
676
+
677
+ // Check if the cache list is now empty
678
+ if len(cacheList) == 0 {
679
+ return nil
680
+ }
681
+
682
+ return fmt.Errorf("error while disabling the cache!")
683
+ }
684
+
593
685
func resourceDataplexLabelDiffSuppress(k, old, new string, d *schema.ResourceData) bool {
594
686
if strings.HasPrefix(k, resourceDataplexGoogleProvidedLabelPrefix) && new == "" {
595
687
return true
@@ -992,8 +1084,13 @@ func resourceStorageBucketDelete(d *schema.ResourceData, meta interface{}) error
992
1084
break
993
1085
}
994
1086
995
- if len(res.Items) == 0 {
996
- break // 0 items, bucket empty
1087
+ cacheList, cacheListErr := getAnywhereCacheListResult(config, bucket)
1088
+ if cacheListErr != nil {
1089
+ return cacheListErr
1090
+ }
1091
+
1092
+ if len(res.Items) == 0 and len(cacheList) == 0 {
1093
+ break // 0 items and no caches, bucket empty
997
1094
}
998
1095
999
1096
if d.Get("retention_policy.0.is_locked").(bool) {
@@ -1011,10 +1108,11 @@ func resourceStorageBucketDelete(d *schema.ResourceData, meta interface{}) error
1011
1108
}
1012
1109
1013
1110
if !d.Get("force_destroy").(bool) {
1014
- deleteErr := fmt.Errorf("Error trying to delete bucket %s containing objects without `force_destroy` set to true", bucket)
1111
+ deleteErr := fmt.Errorf("Error trying to delete bucket %s without `force_destroy` set to true", bucket)
1015
1112
log.Printf("Error! %s : %s\n\n", bucket, deleteErr)
1016
1113
return deleteErr
1017
1114
}
1115
+
1018
1116
// GCS requires that a bucket be empty (have no objects or object
1019
1117
// versions) before it can be deleted.
1020
1118
log.Printf("[DEBUG] GCS Bucket attempting to forceDestroy\n\n")
@@ -1046,6 +1144,12 @@ func resourceStorageBucketDelete(d *schema.ResourceData, meta interface{}) error
1046
1144
})
1047
1145
}
1048
1146
1147
+ // While we wait our objects to be deleted in background, delete the cache if any!
1148
+ err = deleteAnywhereCacheIfAny(config, bucket)
1149
+ if err != nil {
1150
+ return fmt.Errorf("Error deleting the caches on the bucket %s : %v", bucket, err)
1151
+ }
1152
+
1049
1153
// Wait for everything to finish.
1050
1154
wp.StopWait()
1051
1155
}
0 commit comments