Skip to content

Commit eda36c9

Browse files
Add unique index support in Firestore (#14682) (#24163)
[upstream:bdbcf3a3c90e028c6732668cebfc45d3a7340792] Signed-off-by: Modular Magician <[email protected]>
1 parent b2ba7a1 commit eda36c9

File tree

5 files changed

+132
-0
lines changed

5 files changed

+132
-0
lines changed

.changelog/14682.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
firestore: added `unique` field to `google_firestore_index` resource
3+
```

google/services/firestore/resource_firestore_index.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,13 @@ with the same dimension.`,
204204
Description: `The scope at which a query is run. Default value: "COLLECTION" Possible values: ["COLLECTION", "COLLECTION_GROUP", "COLLECTION_RECURSIVE"]`,
205205
Default: "COLLECTION",
206206
},
207+
"unique": {
208+
Type: schema.TypeBool,
209+
Computed: true,
210+
Optional: true,
211+
ForceNew: true,
212+
Description: `Whether it is an unique index. Unique index ensures all values for the indexed field(s) are unique across documents.`,
213+
},
207214
"name": {
208215
Type: schema.TypeString,
209216
Computed: true,
@@ -265,6 +272,12 @@ func resourceFirestoreIndexCreate(d *schema.ResourceData, meta interface{}) erro
265272
} else if v, ok := d.GetOkExists("multikey"); !tpgresource.IsEmptyValue(reflect.ValueOf(multikeyProp)) && (ok || !reflect.DeepEqual(v, multikeyProp)) {
266273
obj["multikey"] = multikeyProp
267274
}
275+
uniqueProp, err := expandFirestoreIndexUnique(d.Get("unique"), d, config)
276+
if err != nil {
277+
return err
278+
} else if v, ok := d.GetOkExists("unique"); !tpgresource.IsEmptyValue(reflect.ValueOf(uniqueProp)) && (ok || !reflect.DeepEqual(v, uniqueProp)) {
279+
obj["unique"] = uniqueProp
280+
}
268281
fieldsProp, err := expandFirestoreIndexFields(d.Get("fields"), d, config)
269282
if err != nil {
270283
return err
@@ -406,6 +419,9 @@ func resourceFirestoreIndexRead(d *schema.ResourceData, meta interface{}) error
406419
if err := d.Set("multikey", flattenFirestoreIndexMultikey(res["multikey"], d, config)); err != nil {
407420
return fmt.Errorf("Error reading Index: %s", err)
408421
}
422+
if err := d.Set("unique", flattenFirestoreIndexUnique(res["unique"], d, config)); err != nil {
423+
return fmt.Errorf("Error reading Index: %s", err)
424+
}
409425
if err := d.Set("fields", flattenFirestoreIndexFields(res["fields"], d, config)); err != nil {
410426
return fmt.Errorf("Error reading Index: %s", err)
411427
}
@@ -524,6 +540,10 @@ func flattenFirestoreIndexMultikey(v interface{}, d *schema.ResourceData, config
524540
return v
525541
}
526542

543+
func flattenFirestoreIndexUnique(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
544+
return v
545+
}
546+
527547
func flattenFirestoreIndexFields(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
528548
if v == nil {
529549
return v
@@ -621,6 +641,10 @@ func expandFirestoreIndexMultikey(v interface{}, d tpgresource.TerraformResource
621641
return v, nil
622642
}
623643

644+
func expandFirestoreIndexUnique(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
645+
return v, nil
646+
}
647+
624648
func expandFirestoreIndexFields(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
625649
l := v.([]interface{})
626650
req := make([]interface{}, 0, len(l))

google/services/firestore/resource_firestore_index_generated_meta.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@ fields:
1717
- field: 'multikey'
1818
- field: 'name'
1919
- field: 'query_scope'
20+
- field: 'unique'

google/services/firestore/resource_firestore_index_generated_test.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,69 @@ resource "google_firestore_index" "my-index" {
390390
`, context)
391391
}
392392

393+
func TestAccFirestoreIndex_firestoreIndexUniqueExample(t *testing.T) {
394+
t.Parallel()
395+
396+
context := map[string]interface{}{
397+
"project_id": envvar.GetTestProjectFromEnv(),
398+
"random_suffix": acctest.RandString(t, 10),
399+
}
400+
401+
acctest.VcrTest(t, resource.TestCase{
402+
PreCheck: func() { acctest.AccTestPreCheck(t) },
403+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
404+
CheckDestroy: testAccCheckFirestoreIndexDestroyProducer(t),
405+
Steps: []resource.TestStep{
406+
{
407+
Config: testAccFirestoreIndex_firestoreIndexUniqueExample(context),
408+
},
409+
{
410+
ResourceName: "google_firestore_index.my-index",
411+
ImportState: true,
412+
ImportStateVerify: true,
413+
ImportStateVerifyIgnore: []string{"collection", "database"},
414+
},
415+
},
416+
})
417+
}
418+
419+
func testAccFirestoreIndex_firestoreIndexUniqueExample(context map[string]interface{}) string {
420+
return acctest.Nprintf(`
421+
resource "google_firestore_database" "database" {
422+
project = "%{project_id}"
423+
name = "tf-test-database-id-unique%{random_suffix}"
424+
location_id = "nam5"
425+
type = "FIRESTORE_NATIVE"
426+
database_edition = "ENTERPRISE"
427+
428+
delete_protection_state = "DELETE_PROTECTION_DISABLED"
429+
deletion_policy = "DELETE"
430+
}
431+
432+
resource "google_firestore_index" "my-index" {
433+
project = "%{project_id}"
434+
database = google_firestore_database.database.name
435+
collection = "atestcollection"
436+
437+
api_scope = "MONGODB_COMPATIBLE_API"
438+
query_scope = "COLLECTION_GROUP"
439+
multikey = true
440+
density = "DENSE"
441+
unique = true
442+
443+
fields {
444+
field_path = "name"
445+
order = "ASCENDING"
446+
}
447+
448+
fields {
449+
field_path = "description"
450+
order = "DESCENDING"
451+
}
452+
}
453+
`, context)
454+
}
455+
393456
func testAccCheckFirestoreIndexDestroyProducer(t *testing.T) func(s *terraform.State) error {
394457
return func(s *terraform.State) error {
395458
for name, rs := range s.RootModule().Resources {

website/docs/r/firestore_index.html.markdown

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,43 @@ resource "google_firestore_index" "my-index" {
239239
}
240240
}
241241
```
242+
## Example Usage - Firestore Index Unique
243+
244+
245+
```hcl
246+
resource "google_firestore_database" "database" {
247+
project = "my-project-name"
248+
name = "database-id-unique"
249+
location_id = "nam5"
250+
type = "FIRESTORE_NATIVE"
251+
database_edition = "ENTERPRISE"
252+
253+
delete_protection_state = "DELETE_PROTECTION_DISABLED"
254+
deletion_policy = "DELETE"
255+
}
256+
257+
resource "google_firestore_index" "my-index" {
258+
project = "my-project-name"
259+
database = google_firestore_database.database.name
260+
collection = "atestcollection"
261+
262+
api_scope = "MONGODB_COMPATIBLE_API"
263+
query_scope = "COLLECTION_GROUP"
264+
multikey = true
265+
density = "DENSE"
266+
unique = true
267+
268+
fields {
269+
field_path = "name"
270+
order = "ASCENDING"
271+
}
272+
273+
fields {
274+
field_path = "description"
275+
order = "DESCENDING"
276+
}
277+
}
278+
```
242279

243280
## Argument Reference
244281

@@ -285,6 +322,10 @@ The following arguments are supported:
285322
(Optional)
286323
Optional. Whether the index is multikey. By default, the index is not multikey. For non-multikey indexes, none of the paths in the index definition reach or traverse an array, except via an explicit array index. For multikey indexes, at most one of the paths in the index definition reach or traverse an array, except via an explicit array index. Violations will result in errors. Note this field only applies to indexes with MONGODB_COMPATIBLE_API ApiScope.
287324

325+
* `unique` -
326+
(Optional)
327+
Whether it is an unique index. Unique index ensures all values for the indexed field(s) are unique across documents.
328+
288329
* `project` - (Optional) The ID of the project in which the resource belongs.
289330
If it is not provided, the provider project is used.
290331

0 commit comments

Comments
 (0)