Skip to content

Commit 813ea75

Browse files
Spanner MR CMEK Integration (#11319) (#19846)
[upstream:b0450ba0e17ac08ac7e07aa3bbb6eeea51785db4] Signed-off-by: Modular Magician <[email protected]>
1 parent 8b1f58b commit 813ea75

File tree

4 files changed

+86
-2
lines changed

4 files changed

+86
-2
lines changed

.changelog/11319.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
spanner: added `kmsKeyNames` to encryptionConfig of Database
3+
```

google/services/spanner/resource_spanner_database.go

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,10 +162,22 @@ whereas setting “enableDropProtection” to true protects the database from de
162162
Schema: map[string]*schema.Schema{
163163
"kms_key_name": {
164164
Type: schema.TypeString,
165-
Required: true,
165+
Optional: true,
166166
ForceNew: true,
167167
Description: `Fully qualified name of the KMS key to use to encrypt this database. This key must exist
168168
in the same location as the Spanner Database.`,
169+
ExactlyOneOf: []string{"encryption_config.0.kms_key_name", "encryption_config.0.kms_key_names"},
170+
},
171+
"kms_key_names": {
172+
Type: schema.TypeList,
173+
Optional: true,
174+
ForceNew: true,
175+
Description: `Fully qualified name of the KMS keys to use to encrypt this database. The keys must exist
176+
in the same locations as the Spanner Database.`,
177+
Elem: &schema.Schema{
178+
Type: schema.TypeString,
179+
},
180+
ExactlyOneOf: []string{"encryption_config.0.kms_key_name", "encryption_config.0.kms_key_names"},
169181
},
170182
},
171183
},
@@ -821,12 +833,46 @@ func flattenSpannerDatabaseEncryptionConfig(v interface{}, d *schema.ResourceDat
821833
transformed := make(map[string]interface{})
822834
transformed["kms_key_name"] =
823835
flattenSpannerDatabaseEncryptionConfigKmsKeyName(original["kmsKeyName"], d, config)
836+
transformed["kms_key_names"] =
837+
flattenSpannerDatabaseEncryptionConfigKmsKeyNames(original["kmsKeyNames"], d, config)
824838
return []interface{}{transformed}
825839
}
826840
func flattenSpannerDatabaseEncryptionConfigKmsKeyName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
827841
return v
828842
}
829843

844+
func flattenSpannerDatabaseEncryptionConfigKmsKeyNames(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
845+
// Ignore `kms_key_names` if `kms_key_name` is set, because that field takes precedence.
846+
_, kmsNameSet := d.GetOk("encryption_config.0.kms_key_name")
847+
if kmsNameSet {
848+
return nil
849+
}
850+
851+
rawConfigValue := d.Get("encryption_config.0.kms_key_names")
852+
853+
// Convert config value to []string
854+
configValue, err := tpgresource.InterfaceSliceToStringSlice(rawConfigValue)
855+
if err != nil {
856+
log.Printf("[ERROR] Failed to convert config value: %s", err)
857+
return v
858+
}
859+
860+
// Convert v to []string
861+
apiStringValue, err := tpgresource.InterfaceSliceToStringSlice(v)
862+
if err != nil {
863+
log.Printf("[ERROR] Failed to convert API value: %s", err)
864+
return v
865+
}
866+
867+
sortedStrings, err := tpgresource.SortStringsByConfigOrder(configValue, apiStringValue)
868+
if err != nil {
869+
log.Printf("[ERROR] Could not sort API response value: %s", err)
870+
return v
871+
}
872+
873+
return sortedStrings
874+
}
875+
830876
func flattenSpannerDatabaseDatabaseDialect(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
831877
return v
832878
}
@@ -870,13 +916,24 @@ func expandSpannerDatabaseEncryptionConfig(v interface{}, d tpgresource.Terrafor
870916
transformed["kmsKeyName"] = transformedKmsKeyName
871917
}
872918

919+
transformedKmsKeyNames, err := expandSpannerDatabaseEncryptionConfigKmsKeyNames(original["kms_key_names"], d, config)
920+
if err != nil {
921+
return nil, err
922+
} else if val := reflect.ValueOf(transformedKmsKeyNames); val.IsValid() && !tpgresource.IsEmptyValue(val) {
923+
transformed["kmsKeyNames"] = transformedKmsKeyNames
924+
}
925+
873926
return transformed, nil
874927
}
875928

876929
func expandSpannerDatabaseEncryptionConfigKmsKeyName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
877930
return v, nil
878931
}
879932

933+
func expandSpannerDatabaseEncryptionConfigKmsKeyNames(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
934+
return v, nil
935+
}
936+
880937
func expandSpannerDatabaseDatabaseDialect(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
881938
return v, nil
882939
}

google/tpgresource/utils.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,25 @@ func ExpandStringMap(d TerraformResourceData, key string) map[string]string {
240240
return ConvertStringMap(v.(map[string]interface{}))
241241
}
242242

243+
// InterfaceSliceToStringSlice converts a []interface{} containing strings to []string
244+
func InterfaceSliceToStringSlice(v interface{}) ([]string, error) {
245+
interfaceSlice, ok := v.([]interface{})
246+
if !ok {
247+
return nil, fmt.Errorf("expected []interface{}, got %T", v)
248+
}
249+
250+
stringSlice := make([]string, len(interfaceSlice))
251+
for i, item := range interfaceSlice {
252+
strItem, ok := item.(string)
253+
if !ok {
254+
return nil, fmt.Errorf("expected string, got %T at index %d", item, i)
255+
}
256+
stringSlice[i] = strItem
257+
}
258+
259+
return stringSlice, nil
260+
}
261+
243262
// SortStringsByConfigOrder takes a slice of map[string]interface{} from a TF config
244263
// and API data, and returns a new slice containing the API data, reorderd to match
245264
// the TF config as closely as possible (with new items at the end of the list.)

website/docs/r/spanner_database.html.markdown

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,10 +131,15 @@ When the field is set to false, deleting the database is allowed.
131131
<a name="nested_encryption_config"></a>The `encryption_config` block supports:
132132

133133
* `kms_key_name` -
134-
(Required)
134+
(Optional)
135135
Fully qualified name of the KMS key to use to encrypt this database. This key must exist
136136
in the same location as the Spanner Database.
137137

138+
* `kms_key_names` -
139+
(Optional)
140+
Fully qualified name of the KMS keys to use to encrypt this database. The keys must exist
141+
in the same locations as the Spanner Database.
142+
138143
## Attributes Reference
139144

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

0 commit comments

Comments
 (0)