Skip to content

Commit

Permalink
Add AppleApp to Firebase. (#6630)
Browse files Browse the repository at this point in the history
* Update api.yaml

* Update api.yaml

* Update api.yaml

* Update api.yaml

* Update terraform.yaml

* Create firebase_apple_app_basic.tf.erb

* Responding to tylerg-dev's comments

* Fixing the failing TestAccFirebaseAppleApp_firebaseAppleAppBasicExample test

* Add a handwritten sweeper to hard-delete the AppleApp

* Fix typo in update_mask

* Fix var name in test

* Add delete request body

* Change appId to app_id in the sweeper delete url

* Use custom_delete for deleting the AppleApp resource

* Update api.yaml

* Remove the repeated block in terraform.api

* Add a 5 sec in the post_delete template

* Move the 5 sec delay to the custom delete code

* Add "Optional" to the deletion_policy description.

* Address melinath@ comments

* Add a manual update test

* Remove unnecessary randomness. Also, move attributes to the vars section so they show up in docs.

* Update mmv1/products/firebase/terraform.yaml

Co-authored-by: Stephen Lewis (Burrows) <stephen.r.burrows@gmail.com>

* Update mmv1/products/firebase/terraform.yaml

Co-authored-by: Stephen Lewis (Burrows) <stephen.r.burrows@gmail.com>

* Update mmv1/products/firebase/terraform.yaml

Co-authored-by: Stephen Lewis (Burrows) <stephen.r.burrows@gmail.com>

* Update mmv1/third_party/terraform/tests/resource_firebase_apple_app_update_test.go.erb

Co-authored-by: Stephen Lewis (Burrows) <stephen.r.burrows@gmail.com>

* Update mmv1/third_party/terraform/tests/resource_firebase_apple_app_update_test.go.erb

Co-authored-by: Stephen Lewis (Burrows) <stephen.r.burrows@gmail.com>

* Update mmv1/third_party/terraform/tests/resource_firebase_apple_app_update_test.go.erb

Co-authored-by: Stephen Lewis (Burrows) <stephen.r.burrows@gmail.com>

* Adding back the test_vars_overrides.

Co-authored-by: Stephen Lewis (Burrows) <stephen.r.burrows@gmail.com>
  • Loading branch information
mraouffouad and melinath authored Nov 15, 2022
1 parent 336d650 commit 2fecbdf
Show file tree
Hide file tree
Showing 6 changed files with 293 additions and 6 deletions.
82 changes: 76 additions & 6 deletions mmv1/products/firebase/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ objects:
A Google Cloud Firebase instance. This enables Firebase resources on a given google project.
Since a FirebaseProject is actually also a GCP Project, a FirebaseProject uses underlying GCP
identifiers (most importantly, the projectId) as its own for easy interop with GCP APIs.
Once Firebase has been added to a Google Project it cannot be removed.
references: !ruby/object:Api::Resource::ReferenceLinks
guides:
Expand Down Expand Up @@ -79,10 +78,8 @@ objects:
input: true
description: |
Sets the default Google Cloud Platform (GCP) resource location for the specified FirebaseProject.
This method creates an App Engine application with a default Cloud Storage bucket, located in the specified
locationId. This location must be one of the available GCP resource locations.
After the default GCP resource location is finalized, or if it was already set, it cannot be changed.
The default GCP resource location for the specified FirebaseProject might already be set because either the
GCP Project already has an App Engine application or defaultLocation.finalize was previously called with a
Expand Down Expand Up @@ -150,8 +147,7 @@ objects:
name: appId
output: true
description: |
Immutable. The globally unique, Firebase-assigned identifier of the App.
The globally unique, Firebase-assigned identifier of the App.
This identifier should be treated as an opaque token, as the data format is not specified.
- !ruby/object:Api::Type::Array
name: appUrls
Expand Down Expand Up @@ -219,10 +215,84 @@ objects:
name: appId
output: true
description: |
Immutable. The globally unique, Firebase-assigned identifier of the App.
The globally unique, Firebase-assigned identifier of the App.
This identifier should be treated as an opaque token, as the data format is not specified.
- !ruby/object:Api::Type::String
name: packageName
description: |
Immutable. The canonical package name of the Android app as would appear in the Google Play
Developer Console.
- !ruby/object:Api::Resource
name: 'AppleApp'
min_version: beta
base_url: projects/{{project}}/iosApps
self_link: '{{name}}'
update_verb: :PATCH
delete_verb: :POST
delete_url: 'projects/{{project}}/iosApps/{{app_id}}:remove'
update_mask: true
description: |
A Google Cloud Firebase Apple application instance
references: !ruby/object:Api::Resource::ReferenceLinks
guides:
'Official Documentation':
'https://firebase.google.com/docs/ios/setup'
api: 'https://firebase.google.com/docs/projects/api/reference/rest/v1beta1/projects.iosApps'
async: !ruby/object:Api::OpAsync
actions: ["create", "delete"]
operation: !ruby/object:Api::OpAsync::Operation
path: 'name'
base_url: '{{op_id}}'
wait_ms: 1000
result: !ruby/object:Api::OpAsync::Result
path: 'response'
resource_inside_response: true
status: !ruby/object:Api::OpAsync::Status
path: 'done'
complete: true
allowed:
- true
- false
error: !ruby/object:Api::OpAsync::Error
path: 'error'
message: 'message'
parameters:
- !ruby/object:Api::Type::String
name: 'deletion_policy'
description: |
(Optional) Set to `ABANDON` to allow the AppleApp to be untracked from terraform state
rather than deleted upon `terraform destroy`. This is useful because the AppleApp may be
serving traffic. Set to `DELETE` to delete the AppleApp. Default to `DELETE`.
input: true
url_param_only: true
default_value: DELETE
properties:
- !ruby/object:Api::Type::String
name: name
description: |
The fully qualified resource name of the App, for example:
projects/projectId/iosApps/appId
output: true
- !ruby/object:Api::Type::String
name: displayName
required: true
description: |
The user-assigned display name of the App.
- !ruby/object:Api::Type::String
name: appId
output: true
description: |
The globally unique, Firebase-assigned identifier of the App.
This identifier should be treated as an opaque token, as the data format is not specified.
- !ruby/object:Api::Type::String
name: bundleId
description: |
The canonical bundle ID of the Apple app as it would appear in the Apple AppStore.
- !ruby/object:Api::Type::String
name: appStoreId
description: |
The automatically generated Apple ID assigned to the Apple app by Apple in the Apple App Store.
- !ruby/object:Api::Type::String
name: teamId
description: |
The Apple Developer Team ID associated with the App in the App Store.
35 changes: 35 additions & 0 deletions mmv1/products/firebase/terraform.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,41 @@ overrides: !ruby/object:Overrides::ResourceOverrides
custom_code: !ruby/object:Provider::Terraform::CustomCode
custom_import: templates/terraform/custom_import/self_link_as_name.erb
custom_delete: templates/terraform/custom_delete/firebase_app_deletion_policy.erb
AppleApp: !ruby/object:Overrides::Terraform::ResourceOverride
import_format: ["projects/{{project}}/iosApps/{{appId}}", "iosApps/{{appId}}", "{{appId}}"]
autogen_async: true
skip_sweeper: true # Skip sweeper generation and use hard-delete in hand-written sweeper
examples:
- !ruby/object:Provider::Terraform::Examples
name: "firebase_apple_app_basic"
min_version: "beta"
primary_resource_id: "default"
vars:
display_name: "Display Name Basic"
bundle_id: "apple.app.12345"
test_env_vars:
org_id: :ORG_ID
project_id: :PROJECT_NAME
- !ruby/object:Provider::Terraform::Examples
name: "firebase_apple_app_full"
min_version: "beta"
primary_resource_id: "full"
vars:
display_name: "Display Name Full"
bundle_id: "apple.app.12345"
app_store_id: "12345"
team_id: "9987654321" # Has to be a 10-digit number.
test_env_vars:
org_id: :ORG_ID
project_id: :PROJECT_NAME
test_vars_overrides:
app_store_id: "12345"
team_id: "9987654321"
ignore_read_extra:
- project
custom_code: !ruby/object:Provider::Terraform::CustomCode
custom_import: templates/terraform/custom_import/self_link_as_name.erb
custom_delete: templates/terraform/custom_delete/firebase_app_deletion_policy.erb
# This is for copying files over
files: !ruby/object:Provider::Config::Files
# These files have templating (ERB) code that will be run.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
resource "google_firebase_apple_app" "default" {
provider = google-beta
project = "<%= ctx[:test_env_vars]['project_id'] %>"
display_name = "<%= ctx[:vars]['display_name'] %>"
bundle_id = "<%= ctx[:vars]['bundle_id'] %>"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
resource "google_firebase_apple_app" "full" {
provider = google-beta
project = "<%= ctx[:test_env_vars]['project_id'] %>"
display_name = "<%= ctx[:vars]['display_name'] %>"
bundle_id = "<%= ctx[:vars]['bundle_id'] %>"
app_store_id = "<%= ctx[:vars]['app_store_id'] %>"
team_id = "<%= ctx[:vars]['team_id'] %>"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// ----------------------------------------------------------------------------
//
// *** HANDWRITTEN CODE *** Type: MMv1 ***
//
// ----------------------------------------------------------------------------

package google

import (
"context"
"log"
"strings"
"testing"

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

func init() {
resource.AddTestSweepers("FirebaseAppleApp", &resource.Sweeper{
Name: "FirebaseAppleApp",
F: testSweepFirebaseAppleApp,
})
}

// At the time of writing, the CI only passes us-central1 as the region
func testSweepFirebaseAppleApp(region string) error {
resourceName := "FirebaseAppleApp"
log.Printf("[INFO][SWEEPER_LOG] Starting sweeper for %s", resourceName)

config, err := sharedConfigForRegion(region)
if err != nil {
log.Printf("[INFO][SWEEPER_LOG] error getting shared config for region: %s", err)
return err
}

err = config.LoadAndValidate(context.Background())
if err != nil {
log.Printf("[INFO][SWEEPER_LOG] error loading: %s", err)
return err
}

t := &testing.T{}
billingId := getTestBillingAccountFromEnv(t)

// Setup variables to replace in list template
d := &ResourceDataMock{
FieldsInSchema: map[string]interface{}{
"project": config.Project,
"region": region,
"location": region,
"zone": "-",
"billing_account": billingId,
},
}

listTemplate := strings.Split("https://firebase.googleapis.com/v1beta1/projects/{{project}}/iosApps", "?")[0]
listUrl, err := replaceVars(d, config, listTemplate)
if err != nil {
log.Printf("[INFO][SWEEPER_LOG] error preparing sweeper list url: %s", err)
return nil
}

res, err := sendRequest(config, "GET", config.Project, listUrl, config.userAgent, nil)
if err != nil {
log.Printf("[INFO][SWEEPER_LOG] Error in response from request %s: %s", listUrl, err)
return nil
}

resourceList, ok := res["appleApps"]
if !ok {
log.Printf("[INFO][SWEEPER_LOG] Nothing found in response.")
return nil
}

rl := resourceList.([]interface{})

log.Printf("[INFO][SWEEPER_LOG] Found %d items in %s list response.", len(rl), resourceName)
// Keep count of items that aren't sweepable for logging.
nonPrefixCount := 0
for _, ri := range rl {
obj := ri.(map[string]interface{})
if obj["name"] == nil {
log.Printf("[INFO][SWEEPER_LOG] %s resource name was nil", resourceName)
return nil
}

name := GetResourceNameFromSelfLink(obj["name"].(string))
// Skip resources that shouldn't be sweeped
if !isSweepableTestResource(name) {
nonPrefixCount++
continue
}

deleteTemplate := "https://firebase.googleapis.com/v1beta1/projects/{{project}}/iosApps/{{app_id}}:remove"
deleteUrl, err := replaceVars(d, config, deleteTemplate)
if err != nil {
log.Printf("[INFO][SWEEPER_LOG] error preparing delete url: %s", err)
return nil
}
deleteUrl = deleteUrl + name

body := make(map[string]interface{})
body["immediate"] = true

// Don't wait on operations as we may have a lot to delete
_, err = sendRequest(config, "DELETE", config.Project, deleteUrl, config.userAgent, body)
if err != nil {
log.Printf("[INFO][SWEEPER_LOG] Error deleting for url %s : %s", deleteUrl, err)
} else {
log.Printf("[INFO][SWEEPER_LOG] Sent delete request for %s resource: %s", resourceName, name)
}
}

if nonPrefixCount > 0 {
log.Printf("[INFO][SWEEPER_LOG] %d items were non-sweepable and skipped.", nonPrefixCount)
}

return nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<% autogen_exception -%>
package google
<% unless version == 'ga' -%>

import (
"testing"

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

func TestAccFirebaseAppleApp_update(t *testing.T) {
t.Parallel()
context := map[string]interface{}{
"project_id": getTestProjectFromEnv(),
"bundle_id": "apple.app.12345",
"random_suffix": randString(t, 10),
"display_name": "Display Name N",
}
vcrTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProvidersOiCS,
Steps: []resource.TestStep{
{
Config: testAccFirebaseAppleApp(context, 12345, "1"),
},
{
Config: testAccFirebaseAppleApp(context, 67890, "2"),
},
},
})
}

func testAccFirebaseAppleApp(context map[string]interface{}, appStoreId int, delta string) string {
context["display_name"] = context["display_name"].(string) + delta
context["app_store_id"] = appStoreId
context["team_id"] = "123456789" + delta
return 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}"
}
`, context)
}

<% end -%>

0 comments on commit 2fecbdf

Please sign in to comment.