diff --git a/modules/apigee-organization/README.md b/modules/apigee-organization/README.md new file mode 100644 index 000000000..b62950f40 --- /dev/null +++ b/modules/apigee-organization/README.md @@ -0,0 +1,125 @@ +# Google Apigee Organization Module + +This module allows managing a single Apigee organization and its environments and environmentgroups. + +## Examples + +### Apigee X Evaluation Organization + +```hcl +module "apigee-organization" { + source = "./modules/apigee-organization" + project_id = "my-project" + analytics_region = "us-central1" + runtime_type = "CLOUD" + authorized_network = "my-vpc" + apigee_environments = [ + "eval1", + "eval2" + ] + apigee_envgroups = { + eval = { + environments = [ + "eval1", + "eval2" + ] + hostnames = [ + "eval.api.example.com" + ] + } + } +} +# tftest:modules=1:resources=6 +``` + +### Apigee X Paid Organization + +```hcl +module "apigee-organization" { + source = "./modules/apigee-organization" + project_id = "my-project" + analytics_region = "us-central1" + runtime_type = "CLOUD" + authorized_network = "my-vpc" + database_encryption_key = "my-data-key" + apigee_environments = [ + "dev1", + "dev2", + "test1", + "test2" + ] + apigee_envgroups = { + dev = { + environments = [ + "dev1", + "dev2" + ] + hostnames = [ + "dev.api.example.com" + ] + } + test = { + environments = [ + "test1", + "test2" + ] + hostnames = [ + "test.api.example.com" + ] + } + } +} +# tftest:modules=1:resources=11 +``` + +### Apigee hybrid Organization + +```hcl +module "apigee-organization" { + source = "./modules/apigee-organization" + project_id = "my-project" + analytics_region = "us-central1" + runtime_type = "HYBRID" + apigee_environments = [ + "eval1", + "eval2" + ] + apigee_envgroups = { + eval = { + environments = [ + "eval1", + "eval2" + ] + hostnames = [ + "eval.api.example.com" + ] + } + } +} +# tftest:modules=1:resources=6 +``` + + +## Variables + +| name | description | type | required | default | +|---|---|:---: |:---:|:---:| +| analytics_region | Analytics Region for the Apigee Organization (immutable). See https://cloud.google.com/apigee/docs/api-platform/get-started/install-cli. | string | ✓ | | +| project_id | Project ID to host this Apigee organization (will also become the Apigee Org name). | string | ✓ | | +| runtime_type | None | string | ✓ | | +| *apigee_envgroups* | Apigee Environment Groups. | map(object({...})) | | {} | +| *apigee_environments* | Apigee Environment Names. | list(string) | | [] | +| *authorized_network* | VPC network self link (requires service network peering enabled (Used in Apigee X only). | string | | null | +| *database_encryption_key* | Cloud KMS key self link (e.g. `projects/foo/locations/us/keyRings/bar/cryptoKeys/baz`) used for encrypting the data that is stored and replicated across runtime instances (immutable, used in Apigee X only). | string | | null | +| *description* | Description of the Apigee Organization. | string | | Apigee Organization created by tf module | +| *display_name* | Display Name of the Apigee Organization. | string | | null | + +## Outputs + +| name | description | sensitive | +|---|---|:---:| +| org | Apigee Organization. | | +| org_ca_certificate | Apigee organization CA certificate. | | +| org_id | Apigee Organization ID. | | +| subscription_type | Apigee subscription type. | | + diff --git a/modules/apigee-organization/main.tf b/modules/apigee-organization/main.tf new file mode 100644 index 000000000..b1c134814 --- /dev/null +++ b/modules/apigee-organization/main.tf @@ -0,0 +1,55 @@ +/** + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +locals { + env_envgroup_pairs = flatten([ + for eg_name, eg in var.apigee_envgroups : [ + for e in eg.environments : { + envgroup = eg_name + env = e + } + ] + ]) +} + +resource "google_apigee_organization" "apigee_org" { + project_id = var.project_id + analytics_region = var.analytics_region + display_name = var.display_name + description = var.description + runtime_type = var.runtime_type + authorized_network = var.authorized_network + runtime_database_encryption_key_name = var.database_encryption_key +} + +resource "google_apigee_environment" "apigee_env" { + for_each = toset(var.apigee_environments) + org_id = google_apigee_organization.apigee_org.id + name = each.key +} + +resource "google_apigee_envgroup" "apigee_envgroup" { + for_each = var.apigee_envgroups + org_id = google_apigee_organization.apigee_org.id + name = each.key + hostnames = each.value.hostnames +} + +resource "google_apigee_envgroup_attachment" "env_to_envgroup_attachment" { + for_each = { for pair in local.env_envgroup_pairs : "${pair.envgroup}-${pair.env}" => pair } + envgroup_id = google_apigee_envgroup.apigee_envgroup[each.value.envgroup].id + environment = google_apigee_environment.apigee_env[each.value.env].name +} \ No newline at end of file diff --git a/modules/apigee-organization/outputs.tf b/modules/apigee-organization/outputs.tf new file mode 100644 index 000000000..6ff012500 --- /dev/null +++ b/modules/apigee-organization/outputs.tf @@ -0,0 +1,35 @@ +/** + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +output "org" { + description = "Apigee Organization." + value = google_apigee_organization.apigee_org +} + +output "org_ca_certificate" { + description = "Apigee organization CA certificate." + value = google_apigee_organization.apigee_org.ca_certificate +} + +output "org_id" { + description = "Apigee Organization ID." + value = google_apigee_organization.apigee_org.id +} + +output "subscription_type" { + description = "Apigee subscription type." + value = google_apigee_organization.apigee_org.subscription_type +} diff --git a/modules/apigee-organization/variables.tf b/modules/apigee-organization/variables.tf new file mode 100644 index 000000000..eff016c8c --- /dev/null +++ b/modules/apigee-organization/variables.tf @@ -0,0 +1,75 @@ +/** + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +variable "authorized_network" { + description = "VPC network self link (requires service network peering enabled (Used in Apigee X only)." + type = string + default = null +} + +variable "analytics_region" { + description = "Analytics Region for the Apigee Organization (immutable). See https://cloud.google.com/apigee/docs/api-platform/get-started/install-cli." + type = string +} + +variable "apigee_envgroups" { + description = "Apigee Environment Groups." + type = map(object({ + environments = list(string) + hostnames = list(string) + })) + default = {} +} + +variable "apigee_environments" { + description = "Apigee Environment Names." + type = list(string) + default = [] +} + +variable "database_encryption_key" { + description = "Cloud KMS key self link (e.g. `projects/foo/locations/us/keyRings/bar/cryptoKeys/baz`) used for encrypting the data that is stored and replicated across runtime instances (immutable, used in Apigee X only)." + type = string + default = null +} + +variable "description" { + description = "Description of the Apigee Organization." + type = string + default = "Apigee Organization created by tf module" +} + +variable "display_name" { + description = "Display Name of the Apigee Organization." + type = string + default = null +} + +variable "project_id" { + description = "Project ID to host this Apigee organization (will also become the Apigee Org name)." + type = string +} + +variable "runtime_type" { + type = string + + validation { + condition = contains(["CLOUD", "HYBRID"], var.runtime_type) + error_message = "Allowed values for runtime_type \"CLOUD\" or \"HYBRID\"." + } +} + + diff --git a/modules/apigee-x-instance/README.md b/modules/apigee-x-instance/README.md new file mode 100644 index 000000000..371f8f0b7 --- /dev/null +++ b/modules/apigee-x-instance/README.md @@ -0,0 +1,67 @@ +# Google Apigee X Instance Module + +This module allows managing a single Apigee X instance and its environment attachments. + +## Examples + +### Apigee X Evaluation Instance + +```hcl +module "apigee-x-instance" { + source = "./modules/apigee-x-instance" + name = "my-us-instance" + region = "us-central1" + cidr_mask = 22 + + apigee_org_id = "my-project" + apigee_environments = [ + "eval1", + "eval2" + ] +} +# tftest:modules=1:resources=3 +``` + +### Apigee X Paid Instance + +```hcl +module "apigee-x-instance" { + source = "./modules/apigee-x-instance" + name = "my-us-instance" + region = "us-central1" + cidr_mask = 16 + disk_encryption_key = "my-disk-key" + + apigee_org_id = "my-project" + apigee_environments = [ + "dev1", + "dev2", + "test1", + "test2" + ] +} +# tftest:modules=1:resources=5 +``` + + +## Variables + +| name | description | type | required | default | +|---|---|:---: |:---:|:---:| +| apigee_org_id | Apigee Organization ID | string | ✓ | | +| cidr_mask | CIDR mask for the Apigee instance | number | ✓ | | +| name | Apigee instance name. | string | ✓ | | +| region | Compute region. | string | ✓ | | +| *apigee_envgroups* | Apigee Environment Groups. | map(object({...})) | | {} | +| *apigee_environments* | Apigee Environment Names. | list(string) | | [] | +| *disk_encryption_key* | Customer Managed Encryption Key (CMEK) self link (e.g. `projects/foo/locations/us/keyRings/bar/cryptoKeys/baz`) used for disk and volume encryption (required for PAID Apigee Orgs only). | string | | null | + +## Outputs + +| name | description | sensitive | +|---|---|:---:| +| endpoint | Internal endpoint of the Apigee instance. | | +| id | Apigee instance ID. | | +| instance | Apigee instance. | | +| port | Port number of the internal endpoint of the Apigee instance. | | + diff --git a/modules/apigee-x-instance/main.tf b/modules/apigee-x-instance/main.tf new file mode 100644 index 000000000..9c3008283 --- /dev/null +++ b/modules/apigee-x-instance/main.tf @@ -0,0 +1,29 @@ +/** + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +resource "google_apigee_instance" "apigee_instance" { + org_id = var.apigee_org_id + name = var.name + location = var.region + peering_cidr_range = "SLASH_${var.cidr_mask}" + disk_encryption_key_name = var.disk_encryption_key +} + +resource "google_apigee_instance_attachment" "apigee_instance_attchment" { + for_each = toset(var.apigee_environments) + instance_id = google_apigee_instance.apigee_instance.id + environment = each.key +} diff --git a/modules/apigee-x-instance/outputs.tf b/modules/apigee-x-instance/outputs.tf new file mode 100644 index 000000000..0f2d5d6bb --- /dev/null +++ b/modules/apigee-x-instance/outputs.tf @@ -0,0 +1,35 @@ +/** + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * limitations under the License. + * See the License for the specific language governing permissions and + */ + +output "endpoint" { + description = "Internal endpoint of the Apigee instance." + value = google_apigee_instance.apigee_instance.host +} + +output "id" { + description = "Apigee instance ID." + value = google_apigee_instance.apigee_instance.id +} + +output "instance" { + description = "Apigee instance." + value = google_apigee_instance.apigee_instance +} + +output "port" { + description = "Port number of the internal endpoint of the Apigee instance." + value = google_apigee_instance.apigee_instance.port +} diff --git a/modules/apigee-x-instance/variables.tf b/modules/apigee-x-instance/variables.tf new file mode 100644 index 000000000..219ee7d6a --- /dev/null +++ b/modules/apigee-x-instance/variables.tf @@ -0,0 +1,60 @@ +/** + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +variable "apigee_envgroups" { + description = "Apigee Environment Groups." + type = map(object({ + environments = list(string) + hostnames = list(string) + })) + default = {} +} + +variable "apigee_environments" { + description = "Apigee Environment Names." + type = list(string) + default = [] +} + +variable "apigee_org_id" { + description = "Apigee Organization ID" + type = string +} + +variable "cidr_mask" { + description = "CIDR mask for the Apigee instance" + type = number + validation { + condition = contains([16, 20, 22], var.cidr_mask) + error_message = "Invalid CIDR mask; Allowed values for cidr_mask: [16, 20, 22]." + } +} + +variable "disk_encryption_key" { + description = "Customer Managed Encryption Key (CMEK) self link (e.g. `projects/foo/locations/us/keyRings/bar/cryptoKeys/baz`) used for disk and volume encryption (required for PAID Apigee Orgs only)." + type = string + default = null +} + +variable "name" { + description = "Apigee instance name." + type = string +} + +variable "region" { + description = "Compute region." + type = string +} diff --git a/tests/modules/apigee_organization/__init__.py b/tests/modules/apigee_organization/__init__.py new file mode 100644 index 000000000..d46dbae5e --- /dev/null +++ b/tests/modules/apigee_organization/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2021 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/tests/modules/apigee_organization/fixture/main.tf b/tests/modules/apigee_organization/fixture/main.tf new file mode 100644 index 000000000..7f5aa1649 --- /dev/null +++ b/tests/modules/apigee_organization/fixture/main.tf @@ -0,0 +1,38 @@ +/** + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +module "test" { + source = "../../../../modules/apigee-organization" + project_id = "my-project" + analytics_region = var.analytics_region + runtime_type = "CLOUD" + authorized_network = var.network + apigee_environments = [ + "eval1", + "eval2" + ] + apigee_envgroups = { + eval = { + environments = [ + "eval1", + "eval2" + ] + hostnames = [ + "eval.api.example.com" + ] + } + } +} diff --git a/tests/modules/apigee_organization/fixture/variables.tf b/tests/modules/apigee_organization/fixture/variables.tf new file mode 100644 index 000000000..3e9109347 --- /dev/null +++ b/tests/modules/apigee_organization/fixture/variables.tf @@ -0,0 +1,25 @@ +/** + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +variable "analytics_region" { + type = string + default = "europe-west1" +} + +variable "network" { + type = string + default = "apigee-vpc" +} \ No newline at end of file diff --git a/tests/modules/apigee_organization/test_plan.py b/tests/modules/apigee_organization/test_plan.py new file mode 100644 index 000000000..680d3cab3 --- /dev/null +++ b/tests/modules/apigee_organization/test_plan.py @@ -0,0 +1,49 @@ +# Copyright 2021 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import os +import pytest + + +FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'fixture') + + +@pytest.fixture +def resources(plan_runner): + _, resources = plan_runner(FIXTURES_DIR) + return resources + + +def test_resource_count(resources): + "Test number of resources created." + assert len(resources) == 6 + + +def test_envgroup_attachment(resources): + "Test Apigee Envgroup Attachments." + attachments = [r['values'] for r in resources if r['type'] + == 'google_apigee_envgroup_attachment'] + assert len(attachments) == 2 + assert set(a['environment'] for a in attachments) == set(['eval1', 'eval2']) + + +def test_envgroup(resources): + "Test env group." + envgroups = [r['values'] for r in resources if r['type'] + == 'google_apigee_envgroup'] + assert len(envgroups) == 1 + assert envgroups[0]['name'] == 'eval' + assert len(envgroups[0]['hostnames']) == 1 + assert envgroups[0]['hostnames'][0] == 'eval.api.example.com' diff --git a/tests/modules/apigee_x_instance/__init__.py b/tests/modules/apigee_x_instance/__init__.py new file mode 100644 index 000000000..d46dbae5e --- /dev/null +++ b/tests/modules/apigee_x_instance/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2021 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/tests/modules/apigee_x_instance/fixture/main.tf b/tests/modules/apigee_x_instance/fixture/main.tf new file mode 100644 index 000000000..7a4b73b55 --- /dev/null +++ b/tests/modules/apigee_x_instance/fixture/main.tf @@ -0,0 +1,28 @@ +/** + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +module "apigee-x-instance" { + source = "../../../../modules/apigee-x-instance" + name = var.name + region = var.region + cidr_mask = 22 + + apigee_org_id = "my-project" + apigee_environments = [ + "eval1", + "eval2" + ] +} \ No newline at end of file diff --git a/tests/modules/apigee_x_instance/fixture/variables.tf b/tests/modules/apigee_x_instance/fixture/variables.tf new file mode 100644 index 000000000..603ec5085 --- /dev/null +++ b/tests/modules/apigee_x_instance/fixture/variables.tf @@ -0,0 +1,25 @@ +/** + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +variable "name" { + type = string + default = "my-test-instance" +} + +variable "region" { + type = string + default = "europe-west1" +} \ No newline at end of file diff --git a/tests/modules/apigee_x_instance/test_plan.py b/tests/modules/apigee_x_instance/test_plan.py new file mode 100644 index 000000000..4b3a9256d --- /dev/null +++ b/tests/modules/apigee_x_instance/test_plan.py @@ -0,0 +1,50 @@ +# Copyright 2021 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import os +import pytest + + +FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'fixture') + + +@pytest.fixture +def resources(plan_runner): + _, resources = plan_runner(FIXTURES_DIR) + return resources + + +def test_resource_count(resources): + "Test number of resources created." + assert len(resources) == 3 + + +def test_instance_attachment(resources): + "Test Apigee Instance Attachments." + attachments = [r['values'] for r in resources if r['type'] + == 'google_apigee_instance_attachment'] + assert len(attachments) == 2 + assert set(a['environment'] for a in attachments) == set(['eval1', 'eval2']) + + +def test_instance(resources): + "Test Instance." + instances = [r['values'] for r in resources if r['type'] + == 'google_apigee_instance'] + assert len(instances) == 1 + assert instances[0]['peering_cidr_range'] == 'SLASH_22' + assert instances[0]['name'] == 'my-test-instance' + assert instances[0]['location'] == 'europe-west1' +