diff --git a/.kitchen.yml b/.kitchen.yml index 1617025d..c2149000 100644 --- a/.kitchen.yml +++ b/.kitchen.yml @@ -110,3 +110,16 @@ suites: backend: local controls: - gcloud + - name: "submodule_network_peering" + driver: + name: "terraform" + command_timeout: 1800 + root_module_directory: test/fixtures/submodule_network_peering/ + verifier: + name: terraform + color: true + systems: + - name: local + backend: local + controls: + - gcloud diff --git a/CHANGELOG.md b/CHANGELOG.md index 93d9fab7..d6f311cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning][semver-site]. ## [Unreleased] +## [1.5.0] - 2019-11-06 + +### Added + +- Added submodule `network-peering` [#101] + ## [1.4.3] - 2019-10-31 ### Fixed @@ -146,7 +152,8 @@ and this project adheres to [Semantic Versioning][semver-site]. - Subnets within the VPC - Secondary ranges for the subnets (if applicable) -[Unreleased]: https://github.com/terraform-google-modules/terraform-google-network/compare/v1.4.3...HEAD +[Unreleased]: https://github.com/terraform-google-modules/terraform-google-network/compare/v1.5.0...HEAD +[1.5.0]: https://github.com/terraform-google-modules/terraform-google-network/compare/v1.4.3...v1.5.0 [1.4.3]: https://github.com/terraform-google-modules/terraform-google-network/compare/v1.4.2...v1.4.3 [1.4.2]: https://github.com/terraform-google-modules/terraform-google-network/compare/v1.4.1...v1.4.2 [1.4.1]: https://github.com/terraform-google-modules/terraform-google-network/compare/v1.4.0...v1.4.1 @@ -164,6 +171,7 @@ and this project adheres to [Semantic Versioning][semver-site]. [0.2.0]: https://github.com/terraform-google-modules/terraform-google-network/compare/v0.1.0...v0.2.0 [0.1.0]: https://github.com/terraform-google-modules/terraform-google-network/releases/tag/v0.1.0 +[#101]: https://github.com/terraform-google-modules/terraform-google-network/pull/101 [#95]: https://github.com/terraform-google-modules/terraform-google-network/issues/95 [#94]: https://github.com/terraform-google-modules/terraform-google-network/pull/94 [#92]: https://github.com/terraform-google-modules/terraform-google-network/issues/92 diff --git a/CODEOWNERS b/CODEOWNERS index 2ac4555d..3a0760e1 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -5,3 +5,5 @@ /modules/fabric-net-svpc-access/ @terraform-google-modules/cft-fabric /modules/fabric-net-firewall/ @terraform-google-modules/cft-fabric /examples/submodule_firewall/ @terraform-google-modules/cft-fabric +/modules/network-peering/ @terraform-google-modules/cft-fabric +/examples/submodule_network_peering/ @terraform-google-modules/cft-fabric diff --git a/examples/submodule_network_peering/.gitignore b/examples/submodule_network_peering/.gitignore new file mode 100644 index 00000000..1e49b3a6 --- /dev/null +++ b/examples/submodule_network_peering/.gitignore @@ -0,0 +1 @@ +.tfvars diff --git a/examples/submodule_network_peering/README.md b/examples/submodule_network_peering/README.md new file mode 100644 index 00000000..4cc9dfda --- /dev/null +++ b/examples/submodule_network_peering/README.md @@ -0,0 +1,19 @@ +# Simple VPC Network Peering + +This example creates a VPC Network peering between two VPCs. + + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|:----:|:-----:|:-----:| +| project\_id | The project ID to put the resources in | string | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| peering1 | Peering1 module output. | +| peering2 | Peering2 module output. | + + diff --git a/examples/submodule_network_peering/main.tf b/examples/submodule_network_peering/main.tf new file mode 100644 index 00000000..e71ad1d3 --- /dev/null +++ b/examples/submodule_network_peering/main.tf @@ -0,0 +1,54 @@ +/** + * Copyright 2019 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 "local-network" { + source = "../../" + project_id = var.project_id + network_name = "local-network" + subnets = [] +} + +module "peer-network-1" { + source = "../../" + project_id = var.project_id + network_name = "peer-network-1" + subnets = [] +} + +module "peer-network-2" { + source = "../../" + project_id = var.project_id + network_name = "peer-network-2" + subnets = [] +} + +module "peering-1" { + source = "../../modules/network-peering" + + local_network = module.local-network.network_self_link + peer_network = module.peer-network-1.network_self_link + export_local_custom_routes = true +} + +module "peering-2" { + source = "../../modules/network-peering" + + local_network = module.local-network.network_self_link + peer_network = module.peer-network-2.network_self_link + export_local_custom_routes = true + + module_depends_on = [module.peering-1.complete] +} diff --git a/examples/submodule_network_peering/outputs.tf b/examples/submodule_network_peering/outputs.tf new file mode 100644 index 00000000..0beb8220 --- /dev/null +++ b/examples/submodule_network_peering/outputs.tf @@ -0,0 +1,25 @@ +/** + * Copyright 2019 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 "peering1" { + description = "Peering1 module output." + value = module.peering-1 +} + +output "peering2" { + description = "Peering2 module output." + value = module.peering-2 +} diff --git a/examples/submodule_network_peering/variables.tf b/examples/submodule_network_peering/variables.tf new file mode 100644 index 00000000..87cb7f64 --- /dev/null +++ b/examples/submodule_network_peering/variables.tf @@ -0,0 +1,20 @@ +/** + * Copyright 2019 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 "project_id" { + description = "The project ID to put the resources in" + type = string +} diff --git a/examples/submodule_network_peering/versions.tf b/examples/submodule_network_peering/versions.tf new file mode 100644 index 00000000..1fe4caaa --- /dev/null +++ b/examples/submodule_network_peering/versions.tf @@ -0,0 +1,19 @@ +/** + * Copyright 2019 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. + */ + +terraform { + required_version = "~> 0.12.0" +} diff --git a/modules/network-peering/README.md b/modules/network-peering/README.md new file mode 100644 index 00000000..ba4d811b --- /dev/null +++ b/modules/network-peering/README.md @@ -0,0 +1,66 @@ +# Google Network Peering + +This module allows creation of a [VPC Network Peering](https://cloud.google.com/vpc/docs/vpc-peering) between two networks. + +The resources created/managed by this module are: + +- one network peering from `local network` to `peer network` +- one network peering from `peer network` to `local network` + +## Usage + +Basic usage of this module is as follows: + +```hcl +module "peering" { + source = "terraform-google-modules/terraform-google-network/google//modules/network-peering" + + prefix = "name-prefix" + local_network = "" + peer_network = "" +} +``` + +If you need to create more than one peering for the same VPC Network `(A -> B, A -> C)` you have to use output from the first module as a dependency for the second one to keep order of peering creation (It is not currently possible to create more than one peering connection for a VPC Network at the same time). + +```hcl +module "peering-a-b" { + source = "terraform-google-modules/terraform-google-network/google//modules/network-peering" + + prefix = "name-prefix" + local_network = "" + peer_network = "" +} + +module "peering-a-c" { + source = "terraform-google-modules/terraform-google-network/google//modules/network-peering" + + prefix = "name-prefix" + local_network = "" + peer_network = "" + + module_depends_on = module.peering-a-b.complete +} +``` + + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|:----:|:-----:|:-----:| +| export\_local\_custom\_routes | Export custom routes to peer network from local network. | bool | `"false"` | no | +| export\_peer\_custom\_routes | Export custom routes to local network from peer network. | bool | `"false"` | no | +| local\_network | Resource link of the network to add a peering to. | string | n/a | yes | +| module\_depends\_on | List of modules or resources this module depends on. | list | `` | no | +| peer\_network | Resource link of the peer network. | string | n/a | yes | +| prefix | Name prefix for the network peerings | string | `"network-peering"` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| complete | Output to be used as a module dependency. | +| local\_network\_peering | Network peering resource. | +| peer\_network\_peering | Peer network peering resource. | + + diff --git a/modules/network-peering/main.tf b/modules/network-peering/main.tf new file mode 100644 index 00000000..722734b8 --- /dev/null +++ b/modules/network-peering/main.tf @@ -0,0 +1,52 @@ +/** + * Copyright 2019 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 { + local_network_name = element(reverse(split("/", var.local_network)), 0) + peer_network_name = element(reverse(split("/", var.peer_network)), 0) +} + +resource "google_compute_network_peering" "local_network_peering" { + provider = "google-beta" + name = "${var.prefix}-${local.local_network_name}-${local.peer_network_name}" + network = var.local_network + peer_network = var.peer_network + export_custom_routes = var.export_local_custom_routes + import_custom_routes = var.export_peer_custom_routes + + depends_on = ["null_resource.module_depends_on"] +} + +resource "google_compute_network_peering" "peer_network_peering" { + provider = "google-beta" + name = "${var.prefix}-${local.peer_network_name}-${local.local_network_name}" + network = var.peer_network + peer_network = var.local_network + export_custom_routes = var.export_peer_custom_routes + import_custom_routes = var.export_local_custom_routes + + depends_on = ["null_resource.module_depends_on", "google_compute_network_peering.local_network_peering"] +} + +resource "null_resource" "module_depends_on" { + triggers = { + value = length(var.module_depends_on) + } +} + +resource "null_resource" "complete" { + depends_on = ["google_compute_network_peering.local_network_peering", "google_compute_network_peering.peer_network_peering"] +} diff --git a/modules/network-peering/outputs.tf b/modules/network-peering/outputs.tf new file mode 100644 index 00000000..2f760622 --- /dev/null +++ b/modules/network-peering/outputs.tf @@ -0,0 +1,30 @@ +/** + * Copyright 2019 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 "local_network_peering" { + description = "Network peering resource." + value = google_compute_network_peering.local_network_peering +} + +output "peer_network_peering" { + description = "Peer network peering resource." + value = google_compute_network_peering.peer_network_peering +} + +output "complete" { + description = "Output to be used as a module dependency." + value = null_resource.complete.id +} diff --git a/modules/network-peering/providers.tf b/modules/network-peering/providers.tf new file mode 100644 index 00000000..0be11bfd --- /dev/null +++ b/modules/network-peering/providers.tf @@ -0,0 +1,19 @@ +/** + * Copyright 2019 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. + */ + +provider "google-beta" { + version = "~> 2.8" +} diff --git a/modules/network-peering/variables.tf b/modules/network-peering/variables.tf new file mode 100644 index 00000000..b528440f --- /dev/null +++ b/modules/network-peering/variables.tf @@ -0,0 +1,49 @@ +/** + * Copyright 2019 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 "prefix" { + description = "Name prefix for the network peerings" + type = string + default = "network-peering" +} + +variable "local_network" { + description = "Resource link of the network to add a peering to." + type = string +} + +variable "peer_network" { + description = "Resource link of the peer network." + type = string +} + +variable "export_peer_custom_routes" { + description = "Export custom routes to local network from peer network." + type = bool + default = false +} + +variable "export_local_custom_routes" { + description = "Export custom routes to peer network from local network." + type = bool + default = false +} + +variable "module_depends_on" { + description = "List of modules or resources this module depends on." + type = list + default = [] +} diff --git a/modules/network-peering/versions.tf b/modules/network-peering/versions.tf new file mode 100644 index 00000000..29704272 --- /dev/null +++ b/modules/network-peering/versions.tf @@ -0,0 +1,19 @@ +/** + * Copyright 2019 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. + */ + +terraform { + required_version = ">= 0.12" +} diff --git a/test/fixtures/submodule_network_peering/main.tf b/test/fixtures/submodule_network_peering/main.tf new file mode 100644 index 00000000..b3c459e0 --- /dev/null +++ b/test/fixtures/submodule_network_peering/main.tf @@ -0,0 +1,20 @@ +/** + * Copyright 2019 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 "peerings" { + source = "../../../examples/submodule_network_peering" + project_id = var.project_id +} diff --git a/test/fixtures/submodule_network_peering/outputs.tf b/test/fixtures/submodule_network_peering/outputs.tf new file mode 100644 index 00000000..13fb41f5 --- /dev/null +++ b/test/fixtures/submodule_network_peering/outputs.tf @@ -0,0 +1,23 @@ +/** + * Copyright 2019 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 "project_id" { + value = var.project_id +} + +output "peerings" { + value = module.peerings +} diff --git a/test/fixtures/submodule_network_peering/variables.tf b/test/fixtures/submodule_network_peering/variables.tf new file mode 100644 index 00000000..89e4e578 --- /dev/null +++ b/test/fixtures/submodule_network_peering/variables.tf @@ -0,0 +1,19 @@ +/** + * Copyright 2019 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 "project_id" { + description = "The GCP project to use for integration tests" +} diff --git a/test/integration/submodule_firewall/inspec.yml b/test/integration/submodule_firewall/inspec.yml index 7e69b529..fc75b013 100644 --- a/test/integration/submodule_firewall/inspec.yml +++ b/test/integration/submodule_firewall/inspec.yml @@ -1,4 +1,4 @@ -name: simple_project +name: submodule_firewall depends: - name: inspec-gcp git: https://github.com/inspec/inspec-gcp.git diff --git a/test/integration/submodule_network_peering/controls/gcloud.rb b/test/integration/submodule_network_peering/controls/gcloud.rb new file mode 100644 index 00000000..894e46dc --- /dev/null +++ b/test/integration/submodule_network_peering/controls/gcloud.rb @@ -0,0 +1,107 @@ +# Copyright 2019 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 +# +# https://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. + +project_id = attribute('project_id') +peerings = attribute('peerings') + +control "gcloud" do + title "gcloud configuration" + peerings.each do |key, value| + local_network_peering = value['local_network_peering'] + peer_network_peering = value['peer_network_peering'] + local_network_self_link = local_network_peering['network'] + peer_network_self_link = peer_network_peering['network'] + local_network_name = local_network_self_link.split('/')[-1] + peer_network_name = peer_network_self_link.split('/')[-1] + + describe command("gcloud compute networks peerings list --project=#{project_id} --network=#{local_network_name} --format=json") do + its(:exit_status) { should eq 0 } + its(:stderr) { should eq '' } + + let(:data) do + if subject.exit_status == 0 + JSON.parse(subject.stdout) + else + {} + end + end + + describe "local VPC peering" do + it "should exist" do + expect(data[0]['peerings'].select{|x| x['name'] == local_network_peering['name']}).not_to be_empty + end + it "should be active" do + expect(data[0]['peerings'].select{|x| x['name'] == local_network_peering['name']}[0]['state']).to eq( + "ACTIVE" + ) + end + it "should be connected to #{peer_network_name} network" do + expect(data[0]['peerings'].select{|x| x['name'] == local_network_peering['name']}[0]['network']).to eq( + peer_network_self_link + ) + end + it "should export custom routes" do + expect(data[0]['peerings'].select{|x| x['name'] == local_network_peering['name']}[0]['exportCustomRoutes']).to eq( + true + ) + end + it "should not import custom routes" do + expect(data[0]['peerings'].select{|x| x['name'] == local_network_peering['name']}[0]['importCustomRoutes']).to eq( + false + ) + end + end + + end + + describe command("gcloud compute networks peerings list --project=#{project_id} --network=#{peer_network_name} --format=json") do + its(:exit_status) { should eq 0 } + its(:stderr) { should eq '' } + + let(:data) do + if subject.exit_status == 0 + JSON.parse(subject.stdout) + else + {} + end + end + + describe "peer VPC peering" do + it "should exist" do + expect(data[0]['peerings'].select{|x| x['name'] == peer_network_peering['name']}).not_to be_empty + end + it "should be active" do + expect(data[0]['peerings'].select{|x| x['name'] == peer_network_peering['name']}[0]['state']).to eq( + "ACTIVE" + ) + end + it "should be connected to #{local_network_name} network" do + expect(data[0]['peerings'].select{|x| x['name'] == peer_network_peering['name']}[0]['network']).to eq( + local_network_self_link + ) + end + it "should not export custom routes" do + expect(data[0]['peerings'].select{|x| x['name'] == peer_network_peering['name']}[0]['exportCustomRoutes']).to eq( + false + ) + end + it "should import custom routes" do + expect(data[0]['peerings'].select{|x| x['name'] == peer_network_peering['name']}[0]['importCustomRoutes']).to eq( + true + ) + end + end + end + end +end diff --git a/test/integration/submodule_network_peering/inspec.yml b/test/integration/submodule_network_peering/inspec.yml new file mode 100644 index 00000000..55de6b25 --- /dev/null +++ b/test/integration/submodule_network_peering/inspec.yml @@ -0,0 +1,8 @@ +name: submodule_network_peering +attributes: + - name: project_id + required: true + type: string + - name: peerings + type: hash + required: true