diff --git a/.changelog/8689.txt b/.changelog/8689.txt new file mode 100644 index 0000000000..d8df2859c4 --- /dev/null +++ b/.changelog/8689.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +firebase: added `api_key_id` field to `google_firebase_web_app`, `google_firebase_android_app`, and `google_firebase_apple_app`. +``` diff --git a/google-beta/services/firebase/resource_firebase_android_app.go b/google-beta/services/firebase/resource_firebase_android_app.go index 28d8a41dbc..6cf26250b2 100644 --- a/google-beta/services/firebase/resource_firebase_android_app.go +++ b/google-beta/services/firebase/resource_firebase_android_app.go @@ -53,6 +53,14 @@ func ResourceFirebaseAndroidApp() *schema.Resource { Required: true, Description: `The user-assigned display name of the AndroidApp.`, }, + "api_key_id": { + Type: schema.TypeString, + Computed: true, + Optional: true, + Description: `The globally unique, Google-assigned identifier (UID) for the Firebase API key associated with the AndroidApp. +If apiKeyId is not set during creation, then Firebase automatically associates an apiKeyId with the AndroidApp. +This auto-associated key may be an existing valid key or, if no valid key exists, a new one will be provisioned.`, + }, "package_name": { Type: schema.TypeString, Optional: true, @@ -144,6 +152,12 @@ func resourceFirebaseAndroidAppCreate(d *schema.ResourceData, meta interface{}) } else if v, ok := d.GetOkExists("sha256_hashes"); !tpgresource.IsEmptyValue(reflect.ValueOf(sha256HashesProp)) && (ok || !reflect.DeepEqual(v, sha256HashesProp)) { obj["sha256Hashes"] = sha256HashesProp } + apiKeyIdProp, err := expandFirebaseAndroidAppApiKeyId(d.Get("api_key_id"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("api_key_id"); !tpgresource.IsEmptyValue(reflect.ValueOf(apiKeyIdProp)) && (ok || !reflect.DeepEqual(v, apiKeyIdProp)) { + obj["apiKeyId"] = apiKeyIdProp + } etagProp, err := expandFirebaseAndroidAppEtag(d.Get("etag"), d, config) if err != nil { return err @@ -286,6 +300,9 @@ func resourceFirebaseAndroidAppRead(d *schema.ResourceData, meta interface{}) er if err := d.Set("sha256_hashes", flattenFirebaseAndroidAppSha256Hashes(res["sha256Hashes"], d, config)); err != nil { return fmt.Errorf("Error reading AndroidApp: %s", err) } + if err := d.Set("api_key_id", flattenFirebaseAndroidAppApiKeyId(res["apiKeyId"], d, config)); err != nil { + return fmt.Errorf("Error reading AndroidApp: %s", err) + } if err := d.Set("etag", flattenFirebaseAndroidAppEtag(res["etag"], d, config)); err != nil { return fmt.Errorf("Error reading AndroidApp: %s", err) } @@ -333,6 +350,12 @@ func resourceFirebaseAndroidAppUpdate(d *schema.ResourceData, meta interface{}) } else if v, ok := d.GetOkExists("sha256_hashes"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, sha256HashesProp)) { obj["sha256Hashes"] = sha256HashesProp } + apiKeyIdProp, err := expandFirebaseAndroidAppApiKeyId(d.Get("api_key_id"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("api_key_id"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, apiKeyIdProp)) { + obj["apiKeyId"] = apiKeyIdProp + } etagProp, err := expandFirebaseAndroidAppEtag(d.Get("etag"), d, config) if err != nil { return err @@ -364,6 +387,10 @@ func resourceFirebaseAndroidAppUpdate(d *schema.ResourceData, meta interface{}) updateMask = append(updateMask, "sha256Hashes") } + if d.HasChange("api_key_id") { + updateMask = append(updateMask, "apiKeyId") + } + if d.HasChange("etag") { updateMask = append(updateMask, "etag") } @@ -515,6 +542,10 @@ func flattenFirebaseAndroidAppSha256Hashes(v interface{}, d *schema.ResourceData return v } +func flattenFirebaseAndroidAppApiKeyId(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + func flattenFirebaseAndroidAppEtag(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { return v } @@ -535,6 +566,10 @@ func expandFirebaseAndroidAppSha256Hashes(v interface{}, d tpgresource.Terraform return v, nil } +func expandFirebaseAndroidAppApiKeyId(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + func expandFirebaseAndroidAppEtag(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { return v, nil } diff --git a/google-beta/services/firebase/resource_firebase_android_app_generated_test.go b/google-beta/services/firebase/resource_firebase_android_app_generated_test.go index 0443cb8b27..e2bd4f7915 100644 --- a/google-beta/services/firebase/resource_firebase_android_app_generated_test.go +++ b/google-beta/services/firebase/resource_firebase_android_app_generated_test.go @@ -35,7 +35,6 @@ func TestAccFirebaseAndroidApp_firebaseAndroidAppBasicExample(t *testing.T) { t.Parallel() context := map[string]interface{}{ - "org_id": envvar.GetTestOrgFromEnv(t), "project_id": envvar.GetTestProjectFromEnv(), "package_name": "android.package.app" + acctest.RandString(t, 4), "display_name": "tf-test Display Name Basic", @@ -73,6 +72,65 @@ resource "google_firebase_android_app" "basic" { `, context) } +func TestAccFirebaseAndroidApp_firebaseAndroidAppCustomApiKeyExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "project_id": envvar.GetTestProjectFromEnv(), + "package_name": "android.package.app" + acctest.RandString(t, 4), + "display_name": "tf-test Display Name", + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckFirebaseAndroidAppDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccFirebaseAndroidApp_firebaseAndroidAppCustomApiKeyExample(context), + }, + { + ResourceName: "google_firebase_android_app.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"project", "deletion_policy"}, + }, + }, + }) +} + +func testAccFirebaseAndroidApp_firebaseAndroidAppCustomApiKeyExample(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_firebase_android_app" "default" { + provider = google-beta + project = "%{project_id}" + display_name = "%{display_name}" + package_name = "%{package_name}" + sha1_hashes = ["2145bdf698b8715039bd0e83f2069bed435ac21c"] + sha256_hashes = ["2145bdf698b8715039bd0e83f2069bed435ac21ca1b2c3d4e5f6123456789abc"] + api_key_id = google_apikeys_key.android.uid +} + +resource "google_apikeys_key" "android" { + provider = google-beta + + name = "tf-test-api-key%{random_suffix}" + display_name = "%{display_name}" + project = "%{project_id}" + + restrictions { + android_key_restrictions { + allowed_applications { + package_name = "%{package_name}" + sha1_fingerprint = "2145bdf698b8715039bd0e83f2069bed435ac21c" + } + } + } +} +`, context) +} + func testAccCheckFirebaseAndroidAppDestroyProducer(t *testing.T) func(s *terraform.State) error { return func(s *terraform.State) error { for name, rs := range s.RootModule().Resources { diff --git a/google-beta/services/firebase/resource_firebase_android_app_update_test.go b/google-beta/services/firebase/resource_firebase_android_app_update_test.go index 4ff6343c3f..ed1d5515be 100644 --- a/google-beta/services/firebase/resource_firebase_android_app_update_test.go +++ b/google-beta/services/firebase/resource_firebase_android_app_update_test.go @@ -23,25 +23,62 @@ func TestAccFirebaseAndroidApp_update(t *testing.T) { ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), Steps: []resource.TestStep{ { - Config: testAccFirebaseAndroidApp(context, ""), + Config: testAccFirebaseAndroidApp(context, "", "key1"), }, { - Config: testAccFirebaseAndroidApp(context, "2"), + Config: testAccFirebaseAndroidApp(context, "2", "key2"), }, }, }) } -func testAccFirebaseAndroidApp(context map[string]interface{}, update string) string { +func testAccFirebaseAndroidApp(context map[string]interface{}, update string, apiKeyLabel string) string { context["display_name"] = context["display_name"].(string) + update + context["api_key_label"] = apiKeyLabel return acctest.Nprintf(` resource "google_firebase_android_app" "update" { - provider = google-beta - project = "%{project_id}" - package_name = "%{package_name}" - display_name = "%{display_name} %{random_suffix}" - sha1_hashes = ["2145bdf698b8715039bd0e83f2069bed435ac21c"] - sha256_hashes = ["2145bdf698b8715039bd0e83f2069bed435ac21ca1b2c3d4e5f6123456789abc"] + provider = google-beta + project = "%{project_id}" + + package_name = "%{package_name}" + display_name = "%{display_name} %{random_suffix}" + sha1_hashes = ["2145bdf698b8715039bd0e83f2069bed435ac21c"] + sha256_hashes = ["2145bdf698b8715039bd0e83f2069bed435ac21ca1b2c3d4e5f6123456789abc"] + api_key_id = google_apikeys_key.%{api_key_label}.uid +} + +resource "google_apikeys_key" "key1" { + provider = google-beta + project = "%{project_id}" + + name = "tf-test-api-key1%{random_suffix}" + display_name = "Test api key 1" + + restrictions { + android_key_restrictions { + allowed_applications { + package_name = "%{package_name}" + sha1_fingerprint = "2145bdf698b8715039bd0e83f2069bed435ac21c" + } + } + } +} + +resource "google_apikeys_key" "key2" { + provider = google-beta + project = "%{project_id}" + + name = "tf-test-api-key2%{random_suffix}" + display_name = "Test api key 2" + + restrictions { + android_key_restrictions { + allowed_applications { + package_name = "%{package_name}" + sha1_fingerprint = "2145bdf698b8715039bd0e83f2069bed435ac21c" + } + } + } } `, context) } diff --git a/google-beta/services/firebase/resource_firebase_apple_app.go b/google-beta/services/firebase/resource_firebase_apple_app.go index e30220c962..334092ca65 100644 --- a/google-beta/services/firebase/resource_firebase_apple_app.go +++ b/google-beta/services/firebase/resource_firebase_apple_app.go @@ -59,6 +59,14 @@ func ResourceFirebaseAppleApp() *schema.Resource { Required: true, Description: `The user-assigned display name of the App.`, }, + "api_key_id": { + Type: schema.TypeString, + Computed: true, + Optional: true, + Description: `The globally unique, Google-assigned identifier (UID) for the Firebase API key associated with the AppleApp. +If apiKeyId is not set during creation, then Firebase automatically associates an apiKeyId with the AppleApp. +This auto-associated key may be an existing valid key or, if no valid key exists, a new one will be provisioned.`, + }, "app_store_id": { Type: schema.TypeString, Optional: true, @@ -132,6 +140,12 @@ func resourceFirebaseAppleAppCreate(d *schema.ResourceData, meta interface{}) er } else if v, ok := d.GetOkExists("team_id"); !tpgresource.IsEmptyValue(reflect.ValueOf(teamIdProp)) && (ok || !reflect.DeepEqual(v, teamIdProp)) { obj["teamId"] = teamIdProp } + apiKeyIdProp, err := expandFirebaseAppleAppApiKeyId(d.Get("api_key_id"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("api_key_id"); !tpgresource.IsEmptyValue(reflect.ValueOf(apiKeyIdProp)) && (ok || !reflect.DeepEqual(v, apiKeyIdProp)) { + obj["apiKeyId"] = apiKeyIdProp + } url, err := tpgresource.ReplaceVars(d, config, "{{FirebaseBasePath}}projects/{{project}}/iosApps") if err != nil { @@ -268,6 +282,9 @@ func resourceFirebaseAppleAppRead(d *schema.ResourceData, meta interface{}) erro if err := d.Set("team_id", flattenFirebaseAppleAppTeamId(res["teamId"], d, config)); err != nil { return fmt.Errorf("Error reading AppleApp: %s", err) } + if err := d.Set("api_key_id", flattenFirebaseAppleAppApiKeyId(res["apiKeyId"], d, config)); err != nil { + return fmt.Errorf("Error reading AppleApp: %s", err) + } return nil } @@ -306,6 +323,12 @@ func resourceFirebaseAppleAppUpdate(d *schema.ResourceData, meta interface{}) er } else if v, ok := d.GetOkExists("team_id"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, teamIdProp)) { obj["teamId"] = teamIdProp } + apiKeyIdProp, err := expandFirebaseAppleAppApiKeyId(d.Get("api_key_id"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("api_key_id"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, apiKeyIdProp)) { + obj["apiKeyId"] = apiKeyIdProp + } url, err := tpgresource.ReplaceVars(d, config, "{{FirebaseBasePath}}projects/{{project}}/iosApps/{{app_id}}") if err != nil { @@ -326,6 +349,10 @@ func resourceFirebaseAppleAppUpdate(d *schema.ResourceData, meta interface{}) er if d.HasChange("team_id") { updateMask = append(updateMask, "teamId") } + + if d.HasChange("api_key_id") { + updateMask = append(updateMask, "apiKeyId") + } // updateMask is a URL parameter but not present in the schema, so ReplaceVars // won't set it url, err = transport_tpg.AddQueryParams(url, map[string]string{"updateMask": strings.Join(updateMask, ",")}) @@ -474,6 +501,10 @@ func flattenFirebaseAppleAppTeamId(v interface{}, d *schema.ResourceData, config return v } +func flattenFirebaseAppleAppApiKeyId(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + func expandFirebaseAppleAppDisplayName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { return v, nil } @@ -489,3 +520,7 @@ func expandFirebaseAppleAppAppStoreId(v interface{}, d tpgresource.TerraformReso func expandFirebaseAppleAppTeamId(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { return v, nil } + +func expandFirebaseAppleAppApiKeyId(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} diff --git a/google-beta/services/firebase/resource_firebase_apple_app_generated_test.go b/google-beta/services/firebase/resource_firebase_apple_app_generated_test.go index 39ff013116..e89a1feb9b 100644 --- a/google-beta/services/firebase/resource_firebase_apple_app_generated_test.go +++ b/google-beta/services/firebase/resource_firebase_apple_app_generated_test.go @@ -108,6 +108,21 @@ resource "google_firebase_apple_app" "full" { bundle_id = "apple.app.12345%{random_suffix}" app_store_id = "%{app_store_id}" team_id = "%{team_id}" + api_key_id = google_apikeys_key.apple.uid +} + +resource "google_apikeys_key" "apple" { + provider = google-beta + + name = "tf-test-api-key%{random_suffix}" + display_name = "%{display_name}" + project = "%{project_id}" + + restrictions { + ios_key_restrictions { + allowed_bundle_ids = ["apple.app.12345%{random_suffix}"] + } + } } `, context) } diff --git a/google-beta/services/firebase/resource_firebase_apple_app_update_test.go b/google-beta/services/firebase/resource_firebase_apple_app_update_test.go index effc698b82..309e70dba8 100644 --- a/google-beta/services/firebase/resource_firebase_apple_app_update_test.go +++ b/google-beta/services/firebase/resource_firebase_apple_app_update_test.go @@ -23,27 +23,58 @@ func TestAccFirebaseAppleApp_update(t *testing.T) { ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), Steps: []resource.TestStep{ { - Config: testAccFirebaseAppleApp(context, 12345, "1"), + Config: testAccFirebaseAppleApp(context, 12345, "1", "key1"), }, { - Config: testAccFirebaseAppleApp(context, 67890, "2"), + Config: testAccFirebaseAppleApp(context, 67890, "2", "key2"), }, }, }) } -func testAccFirebaseAppleApp(context map[string]interface{}, appStoreId int, delta string) string { +func testAccFirebaseAppleApp(context map[string]interface{}, appStoreId int, delta string, apiKeyLabel string) string { context["display_name"] = context["display_name"].(string) + delta context["app_store_id"] = appStoreId context["team_id"] = "123456789" + delta + context["api_key_label"] = apiKeyLabel return acctest.Nprintf(` resource "google_firebase_apple_app" "update" { - provider = google-beta - project = "%{project_id}" - bundle_id = "%{bundle_id}" - display_name = "%{display_name} %{random_suffix}" - app_store_id = "%{app_store_id}" - team_id = "%{team_id}" + provider = google-beta + project = "%{project_id}" + + bundle_id = "%{bundle_id}" + display_name = "%{display_name} %{random_suffix}" + app_store_id = "%{app_store_id}" + team_id = "%{team_id}" + api_key_id = google_apikeys_key.%{api_key_label}.uid +} + +resource "google_apikeys_key" "key1" { + provider = google-beta + project = "%{project_id}" + + name = "tf-test-api-key1%{random_suffix}" + display_name = "Test api key 1" + + restrictions { + ios_key_restrictions { + allowed_bundle_ids = ["%{bundle_id}"] + } + } +} + +resource "google_apikeys_key" "key2" { + provider = google-beta + project = "%{project_id}" + + name = "tf-test-api-key2%{random_suffix}" + display_name = "Test api key 2" + + restrictions { + ios_key_restrictions { + allowed_bundle_ids = ["%{bundle_id}"] + } + } } `, context) } diff --git a/google-beta/services/firebase/resource_firebase_web_app.go b/google-beta/services/firebase/resource_firebase_web_app.go index 568b369562..da73621f23 100644 --- a/google-beta/services/firebase/resource_firebase_web_app.go +++ b/google-beta/services/firebase/resource_firebase_web_app.go @@ -53,6 +53,14 @@ func ResourceFirebaseWebApp() *schema.Resource { Required: true, Description: `The user-assigned display name of the App.`, }, + "api_key_id": { + Type: schema.TypeString, + Computed: true, + Optional: true, + Description: `The globally unique, Google-assigned identifier (UID) for the Firebase API key associated with the WebApp. +If apiKeyId is not set during creation, then Firebase automatically associates an apiKeyId with the WebApp. +This auto-associated key may be an existing valid key or, if no valid key exists, a new one will be provisioned.`, + }, "app_id": { Type: schema.TypeString, Computed: true, @@ -106,6 +114,12 @@ func resourceFirebaseWebAppCreate(d *schema.ResourceData, meta interface{}) erro } else if v, ok := d.GetOkExists("display_name"); !tpgresource.IsEmptyValue(reflect.ValueOf(displayNameProp)) && (ok || !reflect.DeepEqual(v, displayNameProp)) { obj["displayName"] = displayNameProp } + apiKeyIdProp, err := expandFirebaseWebAppApiKeyId(d.Get("api_key_id"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("api_key_id"); !tpgresource.IsEmptyValue(reflect.ValueOf(apiKeyIdProp)) && (ok || !reflect.DeepEqual(v, apiKeyIdProp)) { + obj["apiKeyId"] = apiKeyIdProp + } url, err := tpgresource.ReplaceVars(d, config, "{{FirebaseBasePath}}projects/{{project}}/webApps") if err != nil { @@ -236,6 +250,9 @@ func resourceFirebaseWebAppRead(d *schema.ResourceData, meta interface{}) error if err := d.Set("app_urls", flattenFirebaseWebAppAppUrls(res["appUrls"], d, config)); err != nil { return fmt.Errorf("Error reading WebApp: %s", err) } + if err := d.Set("api_key_id", flattenFirebaseWebAppApiKeyId(res["apiKeyId"], d, config)); err != nil { + return fmt.Errorf("Error reading WebApp: %s", err) + } return nil } @@ -262,6 +279,12 @@ func resourceFirebaseWebAppUpdate(d *schema.ResourceData, meta interface{}) erro } else if v, ok := d.GetOkExists("display_name"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, displayNameProp)) { obj["displayName"] = displayNameProp } + apiKeyIdProp, err := expandFirebaseWebAppApiKeyId(d.Get("api_key_id"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("api_key_id"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, apiKeyIdProp)) { + obj["apiKeyId"] = apiKeyIdProp + } url, err := tpgresource.ReplaceVars(d, config, "{{FirebaseBasePath}}projects/{{project}}/webApps/{{app_id}}") if err != nil { @@ -274,6 +297,10 @@ func resourceFirebaseWebAppUpdate(d *schema.ResourceData, meta interface{}) erro if d.HasChange("display_name") { updateMask = append(updateMask, "displayName") } + + if d.HasChange("api_key_id") { + updateMask = append(updateMask, "apiKeyId") + } // updateMask is a URL parameter but not present in the schema, so ReplaceVars // won't set it url, err = transport_tpg.AddQueryParams(url, map[string]string{"updateMask": strings.Join(updateMask, ",")}) @@ -414,6 +441,14 @@ func flattenFirebaseWebAppAppUrls(v interface{}, d *schema.ResourceData, config return v } +func flattenFirebaseWebAppApiKeyId(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + func expandFirebaseWebAppDisplayName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { return v, nil } + +func expandFirebaseWebAppApiKeyId(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} diff --git a/google-beta/services/firebase/resource_firebase_web_app_generated_test.go b/google-beta/services/firebase/resource_firebase_web_app_generated_test.go index ff6ce78cc8..a099afcef4 100644 --- a/google-beta/services/firebase/resource_firebase_web_app_generated_test.go +++ b/google-beta/services/firebase/resource_firebase_web_app_generated_test.go @@ -116,6 +116,57 @@ resource "google_storage_bucket_object" "default" { `, context) } +func TestAccFirebaseWebApp_firebaseWebAppCustomApiKeyExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "project_id": envvar.GetTestProjectFromEnv(), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckFirebaseWebAppDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccFirebaseWebApp_firebaseWebAppCustomApiKeyExample(context), + }, + { + ResourceName: "google_firebase_web_app.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"project", "deletion_policy"}, + }, + }, + }) +} + +func testAccFirebaseWebApp_firebaseWebAppCustomApiKeyExample(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_firebase_web_app" "default" { + provider = google-beta + project = "%{project_id}" + display_name = "Display Name%{random_suffix}" + api_key_id = google_apikeys_key.web.uid + deletion_policy = "DELETE" +} + +resource "google_apikeys_key" "web" { + provider = google-beta + project = "%{project_id}" + name = "tf-test-api-key%{random_suffix}" + display_name = "Display Name%{random_suffix}" + + restrictions { + browser_key_restrictions { + allowed_referrers = ["*"] + } + } +} +`, context) +} + func testAccCheckFirebaseWebAppDestroyProducer(t *testing.T) func(s *terraform.State) error { return func(s *terraform.State) error { for name, rs := range s.RootModule().Resources { diff --git a/google-beta/services/firebase/resource_firebase_web_app_test.go b/google-beta/services/firebase/resource_firebase_web_app_test.go index 2901fbf613..0b502c5ca7 100644 --- a/google-beta/services/firebase/resource_firebase_web_app_test.go +++ b/google-beta/services/firebase/resource_firebase_web_app_test.go @@ -37,7 +37,7 @@ func TestAccFirebaseWebApp_firebaseWebAppFull(t *testing.T) { Source: "hashicorp/google-beta", }, }, - Config: testAccFirebaseWebApp_firebaseWebAppFull(context, ""), + Config: testAccFirebaseWebApp_firebaseWebAppFull(context, "", "key1"), }, { ExternalProviders: map[string]resource.ExternalProvider{ @@ -46,7 +46,7 @@ func TestAccFirebaseWebApp_firebaseWebAppFull(t *testing.T) { Source: "hashicorp/google-beta", }, }, - Config: testAccFirebaseWebApp_firebaseWebAppFull(context, "2"), + Config: testAccFirebaseWebApp_firebaseWebAppFull(context, "2", "key2"), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet("data.google_firebase_web_app_config.default", "api_key"), resource.TestCheckResourceAttrSet("data.google_firebase_web_app_config.default", "auth_domain"), @@ -55,11 +55,11 @@ func TestAccFirebaseWebApp_firebaseWebAppFull(t *testing.T) { }, { ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - Config: testAccFirebaseWebApp_firebaseWebAppFull(context, ""), + Config: testAccFirebaseWebApp_firebaseWebAppFull(context, "", "key1"), }, { ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - Config: testAccFirebaseWebApp_firebaseWebAppFull(context, "2"), + Config: testAccFirebaseWebApp_firebaseWebAppFull(context, "2", "key2"), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet("data.google_firebase_web_app_config.default", "api_key"), resource.TestCheckResourceAttrSet("data.google_firebase_web_app_config.default", "auth_domain"), @@ -70,8 +70,9 @@ func TestAccFirebaseWebApp_firebaseWebAppFull(t *testing.T) { }) } -func testAccFirebaseWebApp_firebaseWebAppFull(context map[string]interface{}, update string) string { +func testAccFirebaseWebApp_firebaseWebAppFull(context map[string]interface{}, update string, apiKeyLabel string) string { context["display_name"] = context["display_name"].(string) + update + context["api_key_label"] = apiKeyLabel return acctest.Nprintf(` resource "google_project" "default" { provider = google-beta @@ -89,10 +90,37 @@ resource "google_firebase_project" "default" { project = google_project.default.project_id } +resource "google_apikeys_key" "key1" { + provider = google-beta + name = "tf-test-api-key1%{random_suffix}" + display_name = "Test api key 1" + project = google_project.default.project_id + + restrictions { + browser_key_restrictions { + allowed_referrers = ["*"] + } + } +} + +resource "google_apikeys_key" "key2" { + provider = google-beta + name = "tf-test-api-key2%{random_suffix}" + display_name = "Test api key 2" + project = google_project.default.project_id + + restrictions { + browser_key_restrictions { + allowed_referrers = ["*"] + } + } +} + resource "google_firebase_web_app" "default" { provider = google-beta project = google_project.default.project_id display_name = "%{display_name} %{random_suffix}" + api_key_id = google_apikeys_key.%{api_key_label}.uid depends_on = [google_firebase_project.default] } diff --git a/website/docs/r/firebase_android_app.html.markdown b/website/docs/r/firebase_android_app.html.markdown index 5b40d3d30a..9df4c177a8 100644 --- a/website/docs/r/firebase_android_app.html.markdown +++ b/website/docs/r/firebase_android_app.html.markdown @@ -38,11 +38,42 @@ resource "google_firebase_android_app" "basic" { provider = google-beta project = "my-project-name" display_name = "Display Name Basic" - package_name = "" + package_name = "android.package.app" sha1_hashes = ["2145bdf698b8715039bd0e83f2069bed435ac21c"] sha256_hashes = ["2145bdf698b8715039bd0e83f2069bed435ac21ca1b2c3d4e5f6123456789abc"] } ``` +## Example Usage - Firebase Android App Custom Api Key + + +```hcl +resource "google_firebase_android_app" "default" { + provider = google-beta + project = "my-project-name" + display_name = "Display Name" + package_name = "android.package.app" + sha1_hashes = ["2145bdf698b8715039bd0e83f2069bed435ac21c"] + sha256_hashes = ["2145bdf698b8715039bd0e83f2069bed435ac21ca1b2c3d4e5f6123456789abc"] + api_key_id = google_apikeys_key.android.uid +} + +resource "google_apikeys_key" "android" { + provider = google-beta + + name = "api-key" + display_name = "Display Name" + project = "my-project-name" + + restrictions { + android_key_restrictions { + allowed_applications { + package_name = "android.package.app" + sha1_fingerprint = "2145bdf698b8715039bd0e83f2069bed435ac21c" + } + } + } +} +``` ## Argument Reference @@ -70,6 +101,12 @@ The following arguments are supported: (Optional) The SHA256 certificate hashes for the AndroidApp. +* `api_key_id` - + (Optional) + The globally unique, Google-assigned identifier (UID) for the Firebase API key associated with the AndroidApp. + If apiKeyId is not set during creation, then Firebase automatically associates an apiKeyId with the AndroidApp. + This auto-associated key may be an existing valid key or, if no valid key exists, a new one will be provisioned. + * `project` - (Optional) The ID of the project in which the resource belongs. If it is not provided, the provider project is used. diff --git a/website/docs/r/firebase_apple_app.html.markdown b/website/docs/r/firebase_apple_app.html.markdown index 2f9313f564..b654140e13 100644 --- a/website/docs/r/firebase_apple_app.html.markdown +++ b/website/docs/r/firebase_apple_app.html.markdown @@ -52,6 +52,21 @@ resource "google_firebase_apple_app" "full" { bundle_id = "apple.app.12345" app_store_id = "12345" team_id = "9987654321" + api_key_id = google_apikeys_key.apple.uid +} + +resource "google_apikeys_key" "apple" { + provider = google-beta + + name = "api-key" + display_name = "Display Name Full" + project = "my-project-name" + + restrictions { + ios_key_restrictions { + allowed_bundle_ids = ["apple.app.12345"] + } + } } ``` @@ -80,6 +95,12 @@ The following arguments are supported: (Optional) The Apple Developer Team ID associated with the App in the App Store. +* `api_key_id` - + (Optional) + The globally unique, Google-assigned identifier (UID) for the Firebase API key associated with the AppleApp. + If apiKeyId is not set during creation, then Firebase automatically associates an apiKeyId with the AppleApp. + This auto-associated key may be an existing valid key or, if no valid key exists, a new one will be provisioned. + * `project` - (Optional) The ID of the project in which the resource belongs. If it is not provided, the provider project is used. diff --git a/website/docs/r/firebase_web_app.html.markdown b/website/docs/r/firebase_web_app.html.markdown index cb81e6bf67..3fa314eeb9 100644 --- a/website/docs/r/firebase_web_app.html.markdown +++ b/website/docs/r/firebase_web_app.html.markdown @@ -87,6 +87,31 @@ resource "google_storage_bucket_object" "default" { }) } ``` +## Example Usage - Firebase Web App Custom Api Key + + +```hcl +resource "google_firebase_web_app" "default" { + provider = google-beta + project = "my-project-name" + display_name = "Display Name" + api_key_id = google_apikeys_key.web.uid + deletion_policy = "DELETE" +} + +resource "google_apikeys_key" "web" { + provider = google-beta + project = "my-project-name" + name = "api-key" + display_name = "Display Name" + + restrictions { + browser_key_restrictions { + allowed_referrers = ["*"] + } + } +} +``` ## Argument Reference @@ -101,6 +126,12 @@ The following arguments are supported: - - - +* `api_key_id` - + (Optional) + The globally unique, Google-assigned identifier (UID) for the Firebase API key associated with the WebApp. + If apiKeyId is not set during creation, then Firebase automatically associates an apiKeyId with the WebApp. + This auto-associated key may be an existing valid key or, if no valid key exists, a new one will be provisioned. + * `project` - (Optional) The ID of the project in which the resource belongs. If it is not provided, the provider project is used.