Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cloud Storage for Firebase provider #4951

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
3 changes: 3 additions & 0 deletions .changelog/6899.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-resource
google_firebase_storage_bucket
```
4 changes: 4 additions & 0 deletions google-beta/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ type Config struct {
FilestoreBasePath string
FirebaseBasePath string
FirebaseHostingBasePath string
FirebaseStorageBasePath string
FirestoreBasePath string
GameServicesBasePath string
GKEBackupBasePath string
Expand Down Expand Up @@ -333,6 +334,7 @@ const EssentialContactsBasePathKey = "EssentialContacts"
const FilestoreBasePathKey = "Filestore"
const FirebaseBasePathKey = "Firebase"
const FirebaseHostingBasePathKey = "FirebaseHosting"
const FirebaseStorageBasePathKey = "FirebaseStorage"
const FirestoreBasePathKey = "Firestore"
const GameServicesBasePathKey = "GameServices"
const GKEBackupBasePathKey = "GKEBackup"
Expand Down Expand Up @@ -439,6 +441,7 @@ var DefaultBasePaths = map[string]string{
FilestoreBasePathKey: "https://file.googleapis.com/v1beta1/",
FirebaseBasePathKey: "https://firebase.googleapis.com/v1beta1/",
FirebaseHostingBasePathKey: "https://firebasehosting.googleapis.com/v1beta1/",
FirebaseStorageBasePathKey: "https://firebasestorage.googleapis.com/v1beta/",
FirestoreBasePathKey: "https://firestore.googleapis.com/v1/",
GameServicesBasePathKey: "https://gameservices.googleapis.com/v1beta/",
GKEBackupBasePathKey: "https://gkebackup.googleapis.com/v1/",
Expand Down Expand Up @@ -1321,6 +1324,7 @@ func ConfigureBasePaths(c *Config) {
c.FilestoreBasePath = DefaultBasePaths[FilestoreBasePathKey]
c.FirebaseBasePath = DefaultBasePaths[FirebaseBasePathKey]
c.FirebaseHostingBasePath = DefaultBasePaths[FirebaseHostingBasePathKey]
c.FirebaseStorageBasePath = DefaultBasePaths[FirebaseStorageBasePathKey]
c.FirestoreBasePath = DefaultBasePaths[FirestoreBasePathKey]
c.GameServicesBasePath = DefaultBasePaths[GameServicesBasePathKey]
c.GKEBackupBasePath = DefaultBasePaths[GKEBackupBasePathKey]
Expand Down
1 change: 1 addition & 0 deletions google-beta/config_test_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ func configureTestBasePaths(c *Config, url string) {
c.FilestoreBasePath = url
c.FirebaseBasePath = url
c.FirebaseHostingBasePath = url
c.FirebaseStorageBasePath = url
c.FirestoreBasePath = url
c.GameServicesBasePath = url
c.GKEBackupBasePath = url
Expand Down
14 changes: 12 additions & 2 deletions google-beta/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,14 @@ func Provider() *schema.Provider {
"GOOGLE_FIREBASE_HOSTING_CUSTOM_ENDPOINT",
}, DefaultBasePaths[FirebaseHostingBasePathKey]),
},
"firebase_storage_custom_endpoint": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validateCustomEndpoint,
DefaultFunc: schema.MultiEnvDefaultFunc([]string{
"GOOGLE_FIREBASE_STORAGE_CUSTOM_ENDPOINT",
}, DefaultBasePaths[FirebaseStorageBasePathKey]),
},
"firestore_custom_endpoint": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -1047,9 +1055,9 @@ func Provider() *schema.Provider {
return provider
}

// Generated resources: 288
// Generated resources: 289
// Generated IAM resources: 189
// Total generated resources: 477
// Total generated resources: 478
func ResourceMap() map[string]*schema.Resource {
resourceMap, _ := ResourceMapWithErrors()
return resourceMap
Expand Down Expand Up @@ -1349,6 +1357,7 @@ func ResourceMapWithErrors() (map[string]*schema.Resource, error) {
"google_firebase_apple_app": resourceFirebaseAppleApp(),
"google_firebase_hosting_site": resourceFirebaseHostingSite(),
"google_firebase_hosting_channel": resourceFirebaseHostingChannel(),
"google_firebase_storage_bucket": resourceFirebaseStorageBucket(),
"google_firestore_index": resourceFirestoreIndex(),
"google_firestore_document": resourceFirestoreDocument(),
"google_game_services_realm": resourceGameServicesRealm(),
Expand Down Expand Up @@ -1814,6 +1823,7 @@ func providerConfigure(ctx context.Context, d *schema.ResourceData, p *schema.Pr
config.FilestoreBasePath = d.Get("filestore_custom_endpoint").(string)
config.FirebaseBasePath = d.Get("firebase_custom_endpoint").(string)
config.FirebaseHostingBasePath = d.Get("firebase_hosting_custom_endpoint").(string)
config.FirebaseStorageBasePath = d.Get("firebase_storage_custom_endpoint").(string)
config.FirestoreBasePath = d.Get("firestore_custom_endpoint").(string)
config.GameServicesBasePath = d.Get("game_services_custom_endpoint").(string)
config.GKEBackupBasePath = d.Get("gke_backup_custom_endpoint").(string)
Expand Down
211 changes: 211 additions & 0 deletions google-beta/resource_firebase_storage_bucket.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
// ----------------------------------------------------------------------------
//
// *** AUTO GENERATED CODE *** Type: MMv1 ***
//
// ----------------------------------------------------------------------------
//
// This file is automatically generated by Magic Modules and manual
// changes will be clobbered when the file is regenerated.
//
// Please read more about how to change this file in
// .github/CONTRIBUTING.md.
//
// ----------------------------------------------------------------------------

package google

import (
"fmt"
"log"
"time"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func resourceFirebaseStorageBucket() *schema.Resource {
return &schema.Resource{
Create: resourceFirebaseStorageBucketCreate,
Read: resourceFirebaseStorageBucketRead,
Delete: resourceFirebaseStorageBucketDelete,

Importer: &schema.ResourceImporter{
State: resourceFirebaseStorageBucketImport,
},

Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(20 * time.Minute),
Delete: schema.DefaultTimeout(20 * time.Minute),
},

Schema: map[string]*schema.Schema{
"bucket_id": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Description: `Required. Immutable. The ID of the underlying Google Cloud Storage bucket`,
},
"name": {
Type: schema.TypeString,
Computed: true,
Description: `Resource name of the bucket in the format projects/PROJECT_IDENTIFIER/buckets/BUCKET_ID`,
},
"project": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
},
UseJSONNumber: true,
}
}

func resourceFirebaseStorageBucketCreate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
userAgent, err := generateUserAgentString(d, config.userAgent)
if err != nil {
return err
}

obj := make(map[string]interface{})

url, err := replaceVars(d, config, "{{FirebaseStorageBasePath}}projects/{{project}}/buckets/{{bucket_id}}:addFirebase")
if err != nil {
return err
}

log.Printf("[DEBUG] Creating new Bucket: %#v", obj)
billingProject := ""

project, err := getProject(d, config)
if err != nil {
return fmt.Errorf("Error fetching project for Bucket: %s", err)
}
billingProject = project

// err == nil indicates that the billing_project value was found
if bp, err := getBillingProject(d, config); err == nil {
billingProject = bp
}

res, err := sendRequestWithTimeout(config, "POST", billingProject, url, userAgent, obj, d.Timeout(schema.TimeoutCreate))
if err != nil {
return fmt.Errorf("Error creating Bucket: %s", err)
}
if err := d.Set("name", flattenFirebaseStorageBucketName(res["name"], d, config)); err != nil {
return fmt.Errorf(`Error setting computed identity field "name": %s`, err)
}

// Store the ID now
id, err := replaceVars(d, config, "projects/{{project}}/buckets/{{bucket_id}}")
if err != nil {
return fmt.Errorf("Error constructing id: %s", err)
}
d.SetId(id)

log.Printf("[DEBUG] Finished creating Bucket %q: %#v", d.Id(), res)

return resourceFirebaseStorageBucketRead(d, meta)
}

func resourceFirebaseStorageBucketRead(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
userAgent, err := generateUserAgentString(d, config.userAgent)
if err != nil {
return err
}

url, err := replaceVars(d, config, "{{FirebaseStorageBasePath}}projects/{{project}}/buckets/{{bucket_id}}")
if err != nil {
return err
}

billingProject := ""

project, err := getProject(d, config)
if err != nil {
return fmt.Errorf("Error fetching project for Bucket: %s", err)
}
billingProject = project

// err == nil indicates that the billing_project value was found
if bp, err := getBillingProject(d, config); err == nil {
billingProject = bp
}

res, err := sendRequest(config, "GET", billingProject, url, userAgent, nil)
if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("FirebaseStorageBucket %q", d.Id()))
}

if err := d.Set("project", project); err != nil {
return fmt.Errorf("Error reading Bucket: %s", err)
}

if err := d.Set("name", flattenFirebaseStorageBucketName(res["name"], d, config)); err != nil {
return fmt.Errorf("Error reading Bucket: %s", err)
}

return nil
}

func resourceFirebaseStorageBucketDelete(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
userAgent, err := generateUserAgentString(d, config.userAgent)
if err != nil {
return err
}

billingProject := ""

project, err := getProject(d, config)
if err != nil {
return fmt.Errorf("Error fetching project for Bucket: %s", err)
}
billingProject = project

url, err := replaceVars(d, config, "{{FirebaseStorageBasePath}}projects/{{project}}/buckets/{{bucket_id}}:removeFirebase")
if err != nil {
return err
}

var obj map[string]interface{}
log.Printf("[DEBUG] Deleting Bucket %q", d.Id())

// err == nil indicates that the billing_project value was found
if bp, err := getBillingProject(d, config); err == nil {
billingProject = bp
}

res, err := sendRequestWithTimeout(config, "POST", billingProject, url, userAgent, obj, d.Timeout(schema.TimeoutDelete))
if err != nil {
return handleNotFoundError(err, d, "Bucket")
}

log.Printf("[DEBUG] Finished deleting Bucket %q: %#v", d.Id(), res)
return nil
}

func resourceFirebaseStorageBucketImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
config := meta.(*Config)
if err := parseImportId([]string{
"projects/(?P<project>[^/]+)/buckets/(?P<bucket_id>[^/]+)",
"(?P<project>[^/]+)/(?P<bucket_id>[^/]+)",
"(?P<bucket_id>[^/]+)",
}, d, config); err != nil {
return nil, err
}

// Replace import id for the resource id
id, err := replaceVars(d, config, "projects/{{project}}/buckets/{{bucket_id}}")
if err != nil {
return nil, fmt.Errorf("Error constructing id: %s", err)
}
d.SetId(id)

return []*schema.ResourceData{d}, nil
}

func flattenFirebaseStorageBucketName(v interface{}, d *schema.ResourceData, config *Config) interface{} {
return v
}
100 changes: 100 additions & 0 deletions google-beta/resource_firebase_storage_bucket_generated_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// ----------------------------------------------------------------------------
//
// *** AUTO GENERATED CODE *** Type: MMv1 ***
//
// ----------------------------------------------------------------------------
//
// This file is automatically generated by Magic Modules and manual
// changes will be clobbered when the file is regenerated.
//
// Please read more about how to change this file in
// .github/CONTRIBUTING.md.
//
// ----------------------------------------------------------------------------

package google

import (
"fmt"
"strings"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)

func TestAccFirebaseStorageBucket_firebasestorageBucketBasicExample(t *testing.T) {
t.Parallel()

context := map[string]interface{}{
"project_id": getTestProjectFromEnv(),
"random_suffix": randString(t, 10),
}

vcrTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProvidersOiCS,
CheckDestroy: testAccCheckFirebaseStorageBucketDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccFirebaseStorageBucket_firebasestorageBucketBasicExample(context),
},
{
ResourceName: "google_firebase_storage_bucket.default",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"bucket_id"},
},
},
})
}

func testAccFirebaseStorageBucket_firebasestorageBucketBasicExample(context map[string]interface{}) string {
return Nprintf(`
resource "google_storage_bucket" "default" {
provider = google-beta
name = "tf_test_test_bucket%{random_suffix}"
location = "US"
uniform_bucket_level_access = true
}

resource "google_firebase_storage_bucket" "default" {
provider = google-beta
project = "%{project_id}"
bucket_id = google_storage_bucket.default.id
}
`, context)
}

func testAccCheckFirebaseStorageBucketDestroyProducer(t *testing.T) func(s *terraform.State) error {
return func(s *terraform.State) error {
for name, rs := range s.RootModule().Resources {
if rs.Type != "google_firebase_storage_bucket" {
continue
}
if strings.HasPrefix(name, "data.") {
continue
}

config := googleProviderConfig(t)

url, err := replaceVarsForTest(config, rs, "{{FirebaseStorageBasePath}}projects/{{project}}/buckets/{{bucket_id}}")
if err != nil {
return err
}

billingProject := ""

if config.BillingProject != "" {
billingProject = config.BillingProject
}

_, err = sendRequest(config, "GET", billingProject, url, config.userAgent, nil)
if err == nil {
return fmt.Errorf("FirebaseStorageBucket still exists at %s", url)
}
}

return nil
}
}
Loading