Skip to content

Commit 97429dd

Browse files
Add support for apiConsumerDataLocation, apiConsumerDataEncryptionKeyName, and controlPlaneEncryptionKeyName in Apigee Organization. (#10412) (#7245)
[upstream:afc8edcc2789e270a220de2f39e0586a42e9f1ad] Signed-off-by: Modular Magician <[email protected]>
1 parent f38e30f commit 97429dd

File tree

4 files changed

+259
-0
lines changed

4 files changed

+259
-0
lines changed

.changelog/10412.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
apigee: add support for `api_consumer_data_location`, `api_consumer_data_encryption_key_name`, and `control_plane_encryption_key_name` in `google_apigee_organization`
3+
```

google-beta/services/apigee/resource_apigee_organization.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,20 @@ func ResourceApigeeOrganization() *schema.Resource {
6262
ForceNew: true,
6363
Description: `Primary GCP region for analytics data storage. For valid values, see [Create an Apigee organization](https://cloud.google.com/apigee/docs/api-platform/get-started/create-org).`,
6464
},
65+
"api_consumer_data_encryption_key_name": {
66+
Type: schema.TypeString,
67+
Optional: true,
68+
ForceNew: true,
69+
Description: `Cloud KMS key name used for encrypting API consumer data.`,
70+
},
71+
"api_consumer_data_location": {
72+
Type: schema.TypeString,
73+
Optional: true,
74+
ForceNew: true,
75+
Description: `This field is needed only for customers using non-default data residency regions.
76+
Apigee stores some control plane data only in single region.
77+
This field determines which single region Apigee should use.`,
78+
},
6579
"authorized_network": {
6680
Type: schema.TypeString,
6781
Optional: true,
@@ -76,6 +90,13 @@ Valid only when 'RuntimeType' is set to CLOUD. The value can be updated only whe
7690
ForceNew: true,
7791
Description: `Billing type of the Apigee organization. See [Apigee pricing](https://cloud.google.com/apigee/pricing).`,
7892
},
93+
"control_plane_encryption_key_name": {
94+
Type: schema.TypeString,
95+
Optional: true,
96+
ForceNew: true,
97+
Description: `Cloud KMS key name used for encrypting control plane data that is stored in a multi region.
98+
Only used for the data residency region "US" or "EU".`,
99+
},
79100
"description": {
80101
Type: schema.TypeString,
81102
Optional: true,
@@ -205,6 +226,24 @@ func resourceApigeeOrganizationCreate(d *schema.ResourceData, meta interface{})
205226
} else if v, ok := d.GetOkExists("analytics_region"); !tpgresource.IsEmptyValue(reflect.ValueOf(analyticsRegionProp)) && (ok || !reflect.DeepEqual(v, analyticsRegionProp)) {
206227
obj["analyticsRegion"] = analyticsRegionProp
207228
}
229+
apiConsumerDataLocationProp, err := expandApigeeOrganizationApiConsumerDataLocation(d.Get("api_consumer_data_location"), d, config)
230+
if err != nil {
231+
return err
232+
} else if v, ok := d.GetOkExists("api_consumer_data_location"); !tpgresource.IsEmptyValue(reflect.ValueOf(apiConsumerDataLocationProp)) && (ok || !reflect.DeepEqual(v, apiConsumerDataLocationProp)) {
233+
obj["apiConsumerDataLocation"] = apiConsumerDataLocationProp
234+
}
235+
apiConsumerDataEncryptionKeyNameProp, err := expandApigeeOrganizationApiConsumerDataEncryptionKeyName(d.Get("api_consumer_data_encryption_key_name"), d, config)
236+
if err != nil {
237+
return err
238+
} else if v, ok := d.GetOkExists("api_consumer_data_encryption_key_name"); !tpgresource.IsEmptyValue(reflect.ValueOf(apiConsumerDataEncryptionKeyNameProp)) && (ok || !reflect.DeepEqual(v, apiConsumerDataEncryptionKeyNameProp)) {
239+
obj["apiConsumerDataEncryptionKeyName"] = apiConsumerDataEncryptionKeyNameProp
240+
}
241+
controlPlaneEncryptionKeyNameProp, err := expandApigeeOrganizationControlPlaneEncryptionKeyName(d.Get("control_plane_encryption_key_name"), d, config)
242+
if err != nil {
243+
return err
244+
} else if v, ok := d.GetOkExists("control_plane_encryption_key_name"); !tpgresource.IsEmptyValue(reflect.ValueOf(controlPlaneEncryptionKeyNameProp)) && (ok || !reflect.DeepEqual(v, controlPlaneEncryptionKeyNameProp)) {
245+
obj["controlPlaneEncryptionKeyName"] = controlPlaneEncryptionKeyNameProp
246+
}
208247
authorizedNetworkProp, err := expandApigeeOrganizationAuthorizedNetwork(d.Get("authorized_network"), d, config)
209248
if err != nil {
210249
return err
@@ -355,6 +394,15 @@ func resourceApigeeOrganizationRead(d *schema.ResourceData, meta interface{}) er
355394
if err := d.Set("analytics_region", flattenApigeeOrganizationAnalyticsRegion(res["analyticsRegion"], d, config)); err != nil {
356395
return fmt.Errorf("Error reading Organization: %s", err)
357396
}
397+
if err := d.Set("api_consumer_data_location", flattenApigeeOrganizationApiConsumerDataLocation(res["apiConsumerDataLocation"], d, config)); err != nil {
398+
return fmt.Errorf("Error reading Organization: %s", err)
399+
}
400+
if err := d.Set("api_consumer_data_encryption_key_name", flattenApigeeOrganizationApiConsumerDataEncryptionKeyName(res["apiConsumerDataEncryptionKeyName"], d, config)); err != nil {
401+
return fmt.Errorf("Error reading Organization: %s", err)
402+
}
403+
if err := d.Set("control_plane_encryption_key_name", flattenApigeeOrganizationControlPlaneEncryptionKeyName(res["controlPlaneEncryptionKeyName"], d, config)); err != nil {
404+
return fmt.Errorf("Error reading Organization: %s", err)
405+
}
358406
if err := d.Set("authorized_network", flattenApigeeOrganizationAuthorizedNetwork(res["authorizedNetwork"], d, config)); err != nil {
359407
return fmt.Errorf("Error reading Organization: %s", err)
360408
}
@@ -414,6 +462,24 @@ func resourceApigeeOrganizationUpdate(d *schema.ResourceData, meta interface{})
414462
} else if v, ok := d.GetOkExists("analytics_region"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, analyticsRegionProp)) {
415463
obj["analyticsRegion"] = analyticsRegionProp
416464
}
465+
apiConsumerDataLocationProp, err := expandApigeeOrganizationApiConsumerDataLocation(d.Get("api_consumer_data_location"), d, config)
466+
if err != nil {
467+
return err
468+
} else if v, ok := d.GetOkExists("api_consumer_data_location"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, apiConsumerDataLocationProp)) {
469+
obj["apiConsumerDataLocation"] = apiConsumerDataLocationProp
470+
}
471+
apiConsumerDataEncryptionKeyNameProp, err := expandApigeeOrganizationApiConsumerDataEncryptionKeyName(d.Get("api_consumer_data_encryption_key_name"), d, config)
472+
if err != nil {
473+
return err
474+
} else if v, ok := d.GetOkExists("api_consumer_data_encryption_key_name"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, apiConsumerDataEncryptionKeyNameProp)) {
475+
obj["apiConsumerDataEncryptionKeyName"] = apiConsumerDataEncryptionKeyNameProp
476+
}
477+
controlPlaneEncryptionKeyNameProp, err := expandApigeeOrganizationControlPlaneEncryptionKeyName(d.Get("control_plane_encryption_key_name"), d, config)
478+
if err != nil {
479+
return err
480+
} else if v, ok := d.GetOkExists("control_plane_encryption_key_name"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, controlPlaneEncryptionKeyNameProp)) {
481+
obj["controlPlaneEncryptionKeyName"] = controlPlaneEncryptionKeyNameProp
482+
}
417483
authorizedNetworkProp, err := expandApigeeOrganizationAuthorizedNetwork(d.Get("authorized_network"), d, config)
418484
if err != nil {
419485
return err
@@ -598,6 +664,18 @@ func flattenApigeeOrganizationAnalyticsRegion(v interface{}, d *schema.ResourceD
598664
return v
599665
}
600666

667+
func flattenApigeeOrganizationApiConsumerDataLocation(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
668+
return v
669+
}
670+
671+
func flattenApigeeOrganizationApiConsumerDataEncryptionKeyName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
672+
return v
673+
}
674+
675+
func flattenApigeeOrganizationControlPlaneEncryptionKeyName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
676+
return v
677+
}
678+
601679
func flattenApigeeOrganizationAuthorizedNetwork(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
602680
return v
603681
}
@@ -684,6 +762,18 @@ func expandApigeeOrganizationAnalyticsRegion(v interface{}, d tpgresource.Terraf
684762
return v, nil
685763
}
686764

765+
func expandApigeeOrganizationApiConsumerDataLocation(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
766+
return v, nil
767+
}
768+
769+
func expandApigeeOrganizationApiConsumerDataEncryptionKeyName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
770+
return v, nil
771+
}
772+
773+
func expandApigeeOrganizationControlPlaneEncryptionKeyName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
774+
return v, nil
775+
}
776+
687777
func expandApigeeOrganizationAuthorizedNetwork(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
688778
return v, nil
689779
}

google-beta/services/apigee/resource_apigee_organization_generated_test.go

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,157 @@ resource "google_apigee_organization" "org" {
593593
`, context)
594594
}
595595

596+
func TestAccApigeeOrganization_apigeeOrganizationDrzTestExample(t *testing.T) {
597+
acctest.SkipIfVcr(t)
598+
t.Parallel()
599+
600+
context := map[string]interface{}{
601+
"org_id": envvar.GetTestOrgFromEnv(t),
602+
"billing_account": envvar.GetTestBillingAccountFromEnv(t),
603+
"random_suffix": acctest.RandString(t, 10),
604+
}
605+
606+
acctest.VcrTest(t, resource.TestCase{
607+
PreCheck: func() { acctest.AccTestPreCheck(t) },
608+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t),
609+
CheckDestroy: testAccCheckApigeeOrganizationDestroyProducer(t),
610+
Steps: []resource.TestStep{
611+
{
612+
Config: testAccApigeeOrganization_apigeeOrganizationDrzTestExample(context),
613+
},
614+
{
615+
ResourceName: "google_apigee_organization.org",
616+
ImportState: true,
617+
ImportStateVerify: true,
618+
ImportStateVerifyIgnore: []string{"project_id", "retention"},
619+
},
620+
},
621+
})
622+
}
623+
624+
func testAccApigeeOrganization_apigeeOrganizationDrzTestExample(context map[string]interface{}) string {
625+
return acctest.Nprintf(`
626+
provider "google-beta" {
627+
apigee_custom_endpoint = "https://eu-apigee.googleapis.com/v1/"
628+
}
629+
630+
resource "google_project" "project" {
631+
provider = google-beta
632+
633+
project_id = "tf-test%{random_suffix}"
634+
name = "tf-test%{random_suffix}"
635+
org_id = "%{org_id}"
636+
billing_account = "%{billing_account}"
637+
}
638+
639+
resource "google_project_service" "apigee" {
640+
provider = google-beta
641+
642+
project = google_project.project.project_id
643+
service = "apigee.googleapis.com"
644+
}
645+
646+
resource "google_project_service" "compute" {
647+
provider = google-beta
648+
649+
project = google_project.project.project_id
650+
service = "compute.googleapis.com"
651+
}
652+
653+
resource "google_project_service" "servicenetworking" {
654+
provider = google-beta
655+
656+
project = google_project.project.project_id
657+
service = "servicenetworking.googleapis.com"
658+
}
659+
660+
resource "google_project_service" "kms" {
661+
provider = google-beta
662+
663+
project = google_project.project.project_id
664+
service = "cloudkms.googleapis.com"
665+
}
666+
667+
resource "google_compute_network" "apigee_network" {
668+
provider = google-beta
669+
670+
name = "apigee-network"
671+
project = google_project.project.project_id
672+
depends_on = [google_project_service.compute]
673+
}
674+
675+
resource "google_compute_global_address" "apigee_range" {
676+
provider = google-beta
677+
678+
name = "apigee-range"
679+
purpose = "VPC_PEERING"
680+
address_type = "INTERNAL"
681+
prefix_length = 16
682+
network = google_compute_network.apigee_network.id
683+
project = google_project.project.project_id
684+
}
685+
686+
resource "google_service_networking_connection" "apigee_vpc_connection" {
687+
provider = google-beta
688+
689+
network = google_compute_network.apigee_network.id
690+
service = "servicenetworking.googleapis.com"
691+
reserved_peering_ranges = [google_compute_global_address.apigee_range.name]
692+
depends_on = [google_project_service.servicenetworking]
693+
}
694+
695+
resource "google_kms_key_ring" "apigee_keyring" {
696+
provider = google-beta
697+
698+
name = "apigee-keyring"
699+
location = "europe-central2"
700+
project = google_project.project.project_id
701+
depends_on = [google_project_service.kms]
702+
}
703+
704+
resource "google_kms_crypto_key" "apigee_key" {
705+
provider = google-beta
706+
707+
name = "apigee-key"
708+
key_ring = google_kms_key_ring.apigee_keyring.id
709+
}
710+
711+
resource "google_project_service_identity" "apigee_sa" {
712+
provider = google-beta
713+
714+
project = google_project.project.project_id
715+
service = google_project_service.apigee.service
716+
}
717+
718+
resource "google_kms_crypto_key_iam_member" "apigee_sa_keyuser" {
719+
provider = google-beta
720+
721+
crypto_key_id = google_kms_crypto_key.apigee_key.id
722+
role = "roles/cloudkms.cryptoKeyEncrypterDecrypter"
723+
724+
member = "serviceAccount:${google_project_service_identity.apigee_sa.email}"
725+
}
726+
727+
resource "google_apigee_organization" "org" {
728+
provider = google-beta
729+
730+
api_consumer_data_location = "europe-central2"
731+
project_id = google_project.project.project_id
732+
authorized_network = google_compute_network.apigee_network.id
733+
billing_type = "PAYG"
734+
runtime_database_encryption_key_name = google_kms_crypto_key.apigee_key.id
735+
api_consumer_data_encryption_key_name = google_kms_crypto_key.apigee_key.id
736+
retention = "MINIMUM"
737+
738+
depends_on = [
739+
google_service_networking_connection.apigee_vpc_connection,
740+
google_project_service.apigee,
741+
google_kms_crypto_key_iam_member.apigee_sa_keyuser,
742+
]
743+
}
744+
`, context)
745+
}
746+
596747
func testAccCheckApigeeOrganizationDestroyProducer(t *testing.T) func(s *terraform.State) error {
597748
return func(s *terraform.State) error {
598749
for name, rs := range s.RootModule().Resources {

website/docs/r/apigee_organization.html.markdown

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,21 @@ The following arguments are supported:
209209
(Optional)
210210
Primary GCP region for analytics data storage. For valid values, see [Create an Apigee organization](https://cloud.google.com/apigee/docs/api-platform/get-started/create-org).
211211

212+
* `api_consumer_data_location` -
213+
(Optional)
214+
This field is needed only for customers using non-default data residency regions.
215+
Apigee stores some control plane data only in single region.
216+
This field determines which single region Apigee should use.
217+
218+
* `api_consumer_data_encryption_key_name` -
219+
(Optional)
220+
Cloud KMS key name used for encrypting API consumer data.
221+
222+
* `control_plane_encryption_key_name` -
223+
(Optional)
224+
Cloud KMS key name used for encrypting control plane data that is stored in a multi region.
225+
Only used for the data residency region "US" or "EU".
226+
212227
* `authorized_network` -
213228
(Optional)
214229
Compute Engine network used for Service Networking to be peered with Apigee runtime instances.

0 commit comments

Comments
 (0)