Skip to content

Commit 0e51b8e

Browse files
modular-magicianChris Stephens
andauthored
Add 'resources' reading and 'location_id' setting on Firebase P… (#3319) (#1919)
* Add FirebaseLocation fine grained resource * Updates for firebase finalize location Removed the custom decoder and replaced with the "fine grain" resource operator "nested_query". Updated the import_id so that importing wouldn't crash terraform Co-authored-by: Chris Stephens <[email protected]> Signed-off-by: Modular Magician <[email protected]> Co-authored-by: Chris Stephens <[email protected]>
1 parent 8a8f20e commit 0e51b8e

File tree

7 files changed

+421
-6
lines changed

7 files changed

+421
-6
lines changed

.changelog/3319.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:new-resource
2+
firebase: Added new `firebase_project_location` resource to finalize the firebase location.
3+
```

google-beta/provider.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -587,9 +587,9 @@ func Provider() terraform.ResourceProvider {
587587
return provider
588588
}
589589

590-
// Generated resources: 135
590+
// Generated resources: 136
591591
// Generated IAM resources: 54
592-
// Total generated resources: 189
592+
// Total generated resources: 190
593593
func ResourceMap() map[string]*schema.Resource {
594594
resourceMap, _ := ResourceMapWithErrors()
595595
return resourceMap
@@ -700,6 +700,7 @@ func ResourceMapWithErrors() (map[string]*schema.Resource, error) {
700700
"google_dns_policy": resourceDNSPolicy(),
701701
"google_filestore_instance": resourceFilestoreInstance(),
702702
"google_firebase_project": resourceFirebaseProject(),
703+
"google_firebase_project_location": resourceFirebaseProjectLocation(),
703704
"google_firestore_index": resourceFirestoreIndex(),
704705
"google_game_services_realm": resourceGameServicesRealm(),
705706
"google_game_services_game_server_cluster": resourceGameServicesGameServerCluster(),

google-beta/resource_firebase_project.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ func resourceFirebaseProjectCreate(d *schema.ResourceData, meta interface{}) err
7979
}
8080

8181
// Store the ID now
82-
id, err := replaceVars(d, config, "projects/{{project}}/{{name}}")
82+
id, err := replaceVars(d, config, "projects/{{project}}")
8383
if err != nil {
8484
return fmt.Errorf("Error constructing id: %s", err)
8585
}
@@ -103,7 +103,7 @@ func resourceFirebaseProjectCreate(d *schema.ResourceData, meta interface{}) err
103103
func resourceFirebaseProjectRead(d *schema.ResourceData, meta interface{}) error {
104104
config := meta.(*Config)
105105

106-
url, err := replaceVars(d, config, "{{FirebaseBasePath}}projects/{{project}}/{{name}}")
106+
url, err := replaceVars(d, config, "{{FirebaseBasePath}}projects/{{project}}")
107107
if err != nil {
108108
return err
109109
}
@@ -150,7 +150,7 @@ func resourceFirebaseProjectImport(d *schema.ResourceData, meta interface{}) ([]
150150
}
151151

152152
// Replace import id for the resource id
153-
id, err := replaceVars(d, config, "projects/{{project}}/{{name}}")
153+
id, err := replaceVars(d, config, "projects/{{project}}")
154154
if err != nil {
155155
return nil, fmt.Errorf("Error constructing id: %s", err)
156156
}
Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
// ----------------------------------------------------------------------------
2+
//
3+
// *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
4+
//
5+
// ----------------------------------------------------------------------------
6+
//
7+
// This file is automatically generated by Magic Modules and manual
8+
// changes will be clobbered when the file is regenerated.
9+
//
10+
// Please read more about how to change this file in
11+
// .github/CONTRIBUTING.md.
12+
//
13+
// ----------------------------------------------------------------------------
14+
15+
package google
16+
17+
import (
18+
"fmt"
19+
"log"
20+
"reflect"
21+
"time"
22+
23+
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
24+
)
25+
26+
func resourceFirebaseProjectLocation() *schema.Resource {
27+
return &schema.Resource{
28+
Create: resourceFirebaseProjectLocationCreate,
29+
Read: resourceFirebaseProjectLocationRead,
30+
Delete: resourceFirebaseProjectLocationDelete,
31+
32+
Importer: &schema.ResourceImporter{
33+
State: resourceFirebaseProjectLocationImport,
34+
},
35+
36+
Timeouts: &schema.ResourceTimeout{
37+
Create: schema.DefaultTimeout(10 * time.Minute),
38+
Delete: schema.DefaultTimeout(4 * time.Minute),
39+
},
40+
41+
Schema: map[string]*schema.Schema{
42+
"location_id": {
43+
Type: schema.TypeString,
44+
Required: true,
45+
ForceNew: true,
46+
Description: `The ID of the default GCP resource location for the Project. The location must be one of the available GCP
47+
resource locations.`,
48+
},
49+
"project": {
50+
Type: schema.TypeString,
51+
Optional: true,
52+
Computed: true,
53+
ForceNew: true,
54+
},
55+
},
56+
}
57+
}
58+
59+
func resourceFirebaseProjectLocationCreate(d *schema.ResourceData, meta interface{}) error {
60+
config := meta.(*Config)
61+
62+
obj := make(map[string]interface{})
63+
locationIdProp, err := expandFirebaseProjectLocationLocationId(d.Get("location_id"), d, config)
64+
if err != nil {
65+
return err
66+
} else if v, ok := d.GetOkExists("location_id"); !isEmptyValue(reflect.ValueOf(locationIdProp)) && (ok || !reflect.DeepEqual(v, locationIdProp)) {
67+
obj["locationId"] = locationIdProp
68+
}
69+
70+
url, err := replaceVars(d, config, "{{FirebaseBasePath}}projects/{{project}}/defaultLocation:finalize")
71+
if err != nil {
72+
return err
73+
}
74+
75+
log.Printf("[DEBUG] Creating new ProjectLocation: %#v", obj)
76+
project, err := getProject(d, config)
77+
if err != nil {
78+
return err
79+
}
80+
res, err := sendRequestWithTimeout(config, "POST", project, url, obj, d.Timeout(schema.TimeoutCreate))
81+
if err != nil {
82+
return fmt.Errorf("Error creating ProjectLocation: %s", err)
83+
}
84+
85+
// Store the ID now
86+
id, err := replaceVars(d, config, "projects/{{project}}")
87+
if err != nil {
88+
return fmt.Errorf("Error constructing id: %s", err)
89+
}
90+
d.SetId(id)
91+
92+
err = firebaseOperationWaitTime(
93+
config, res, project, "Creating ProjectLocation",
94+
int(d.Timeout(schema.TimeoutCreate).Minutes()))
95+
96+
if err != nil {
97+
// The resource didn't actually create
98+
d.SetId("")
99+
return fmt.Errorf("Error waiting to create ProjectLocation: %s", err)
100+
}
101+
102+
log.Printf("[DEBUG] Finished creating ProjectLocation %q: %#v", d.Id(), res)
103+
104+
return resourceFirebaseProjectLocationRead(d, meta)
105+
}
106+
107+
func resourceFirebaseProjectLocationRead(d *schema.ResourceData, meta interface{}) error {
108+
config := meta.(*Config)
109+
110+
url, err := replaceVars(d, config, "{{FirebaseBasePath}}projects/{{project}}")
111+
if err != nil {
112+
return err
113+
}
114+
115+
project, err := getProject(d, config)
116+
if err != nil {
117+
return err
118+
}
119+
res, err := sendRequest(config, "GET", project, url, nil)
120+
if err != nil {
121+
return handleNotFoundError(err, d, fmt.Sprintf("FirebaseProjectLocation %q", d.Id()))
122+
}
123+
124+
res, err = flattenNestedFirebaseProjectLocation(d, meta, res)
125+
if err != nil {
126+
return err
127+
}
128+
129+
if res == nil {
130+
// Object isn't there any more - remove it from the state.
131+
log.Printf("[DEBUG] Removing FirebaseProjectLocation because it couldn't be matched.")
132+
d.SetId("")
133+
return nil
134+
}
135+
136+
if err := d.Set("project", project); err != nil {
137+
return fmt.Errorf("Error reading ProjectLocation: %s", err)
138+
}
139+
140+
if err := d.Set("location_id", flattenFirebaseProjectLocationLocationId(res["locationId"], d, config)); err != nil {
141+
return fmt.Errorf("Error reading ProjectLocation: %s", err)
142+
}
143+
144+
return nil
145+
}
146+
147+
func resourceFirebaseProjectLocationDelete(d *schema.ResourceData, meta interface{}) error {
148+
log.Printf("[WARNING] Firebase ProjectLocation resources"+
149+
" cannot be deleted from GCP. The resource %s will be removed from Terraform"+
150+
" state, but will still be present on the server.", d.Id())
151+
d.SetId("")
152+
153+
return nil
154+
}
155+
156+
func resourceFirebaseProjectLocationImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
157+
config := meta.(*Config)
158+
if err := parseImportId([]string{
159+
"projects/(?P<project>[^/]+)",
160+
"(?P<project>[^/]+)",
161+
}, d, config); err != nil {
162+
return nil, err
163+
}
164+
165+
// Replace import id for the resource id
166+
id, err := replaceVars(d, config, "projects/{{project}}")
167+
if err != nil {
168+
return nil, fmt.Errorf("Error constructing id: %s", err)
169+
}
170+
d.SetId(id)
171+
172+
return []*schema.ResourceData{d}, nil
173+
}
174+
175+
func flattenFirebaseProjectLocationLocationId(v interface{}, d *schema.ResourceData, config *Config) interface{} {
176+
return v
177+
}
178+
179+
func expandFirebaseProjectLocationLocationId(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
180+
return v, nil
181+
}
182+
183+
func flattenNestedFirebaseProjectLocation(d *schema.ResourceData, meta interface{}, res map[string]interface{}) (map[string]interface{}, error) {
184+
var v interface{}
185+
var ok bool
186+
187+
v, ok = res["resources"]
188+
if !ok || v == nil {
189+
// It's possible that there is only one of these resources and
190+
// that res represents that resource.
191+
v = res
192+
}
193+
194+
switch v.(type) {
195+
case []interface{}:
196+
break
197+
case map[string]interface{}:
198+
// Construct list out of single nested resource
199+
v = []interface{}{v}
200+
default:
201+
return nil, fmt.Errorf("expected list or map for value resources. Actual value: %v", v)
202+
}
203+
204+
_, item, err := resourceFirebaseProjectLocationFindNestedObjectInList(d, meta, v.([]interface{}))
205+
if err != nil {
206+
return nil, err
207+
}
208+
return item, nil
209+
}
210+
211+
func resourceFirebaseProjectLocationFindNestedObjectInList(d *schema.ResourceData, meta interface{}, items []interface{}) (index int, item map[string]interface{}, err error) {
212+
213+
// Search list for this resource.
214+
for idx, itemRaw := range items {
215+
if itemRaw == nil {
216+
continue
217+
}
218+
item := itemRaw.(map[string]interface{})
219+
220+
log.Printf("[DEBUG] Found item for resource %q: %#v)", d.Id(), item)
221+
return idx, item, nil
222+
}
223+
return -1, nil, nil
224+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// ----------------------------------------------------------------------------
2+
//
3+
// *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
4+
//
5+
// ----------------------------------------------------------------------------
6+
//
7+
// This file is automatically generated by Magic Modules and manual
8+
// changes will be clobbered when the file is regenerated.
9+
//
10+
// Please read more about how to change this file in
11+
// .github/CONTRIBUTING.md.
12+
//
13+
// ----------------------------------------------------------------------------
14+
15+
package google
16+
17+
import (
18+
"testing"
19+
20+
"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
21+
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
22+
)
23+
24+
func TestAccFirebaseProjectLocation_firebaseProjectLocationBasicExample(t *testing.T) {
25+
t.Parallel()
26+
27+
context := map[string]interface{}{
28+
"org_id": getTestOrgFromEnv(t),
29+
"random_suffix": acctest.RandString(10),
30+
}
31+
32+
resource.Test(t, resource.TestCase{
33+
PreCheck: func() { testAccPreCheck(t) },
34+
Providers: testAccProvidersOiCS,
35+
Steps: []resource.TestStep{
36+
{
37+
Config: testAccFirebaseProjectLocation_firebaseProjectLocationBasicExample(context),
38+
},
39+
},
40+
})
41+
}
42+
43+
func testAccFirebaseProjectLocation_firebaseProjectLocationBasicExample(context map[string]interface{}) string {
44+
return Nprintf(`
45+
resource "google_project" "default" {
46+
provider = google-beta
47+
48+
project_id = "tf-test%{random_suffix}"
49+
name = "tf-test%{random_suffix}"
50+
org_id = "%{org_id}"
51+
}
52+
53+
resource "google_firebase_project" "default" {
54+
provider = google-beta
55+
project = google_project.default.project_id
56+
}
57+
58+
resource "google_firebase_project_location" "basic" {
59+
provider = google-beta
60+
project = google_firebase_project.default.project
61+
62+
location_id = "us-central"
63+
}
64+
`, context)
65+
}

website/docs/r/firebase_project.html.markdown

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ The following arguments are supported:
7777

7878
In addition to the arguments listed above, the following computed attributes are exported:
7979

80-
* `id` - an identifier for the resource with format `projects/{{project}}/{{name}}`
80+
* `id` - an identifier for the resource with format `projects/{{project}}`
8181

8282
* `project_number` -
8383
The number of the google project that firebase is enabled on.

0 commit comments

Comments
 (0)