Skip to content

Commit

Permalink
Add apikeys to Firebase apps (#8689) (#6127)
Browse files Browse the repository at this point in the history
Signed-off-by: Modular Magician <[email protected]>
  • Loading branch information
modular-magician authored Aug 21, 2023
1 parent 379da6c commit 85969e4
Show file tree
Hide file tree
Showing 13 changed files with 442 additions and 25 deletions.
3 changes: 3 additions & 0 deletions .changelog/8689.txt
Original file line number Diff line number Diff line change
@@ -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`.
```
35 changes: 35 additions & 0 deletions google-beta/services/firebase/resource_firebase_android_app.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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")
}
Expand Down Expand Up @@ -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
}
Expand All @@ -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
}
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
35 changes: 35 additions & 0 deletions google-beta/services/firebase/resource_firebase_apple_app.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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 {
Expand All @@ -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, ",")})
Expand Down Expand Up @@ -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
}
Expand All @@ -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
}
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
Loading

0 comments on commit 85969e4

Please sign in to comment.