ILB for appliances example (#122)

* rename infrastructure folder to networking

* example WIP: VPCs

* move ip forwarding to its own variable in compute-vm module

* add per-instance metadata support to compute-vm module

* ipip tunnels on linux savepoint

* simple multinic gateways example

* remove stale files

* resolve conflicts

* update diagram

* rename folder

* use a template for gw cloud config, rename some resources and files

* Update README.md

* Update README.md

* add basic plan tests for all networking e2e examples

* fix test for foundations/environments e2e example

* fix shared vpc e2 example count error in gke node service account permissions

* use module path for assets in onprem e2e example

* use project id from module in ilb e2e example

* add mising boilerplates in tests

* run examples tests in ci

* update module's README

* rename ilb example

* Update README.md

* fix rp_filter configuration

* README

* Update README.md

* Update README.md

* Update README.md

* update CHANGELOG

* update CHANGELOG

* Update README.md
This commit is contained in:
Ludovico Magnocavallo 2020-08-15 10:12:43 +02:00 committed by GitHub
parent a008b1a561
commit f62b9362a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
80 changed files with 1201 additions and 75 deletions

View File

@ -35,6 +35,16 @@ steps:
env:
- PATH=/usr/local/bin:/usr/bin:/bin:/builder/home/.local/bin
- TF_CLI_CONFIG_FILE=/workspace/.ci/.terraformrc
- name: python:3-alpine
id: test-environments
entrypoint: pytest
args:
- -v
- tests/foundations
- tests/networking
env:
- PATH=/usr/local/bin:/usr/bin:/bin:/builder/home/.local/bin
- TF_CLI_CONFIG_FILE=/workspace/.ci/.terraformrc
substitutions:
_TERRAFORM_VERSION: 0.12.20

View File

@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
## [Unreleased]
## [3.0.0] - 2020-08-15
- **incompatible change** the top-level `infrastructure` folder has been renamed to `networking`
- add end-to-end example for ILB as next hop
- add basic tests for `foundations` and `networking` end-to-end examples
## [2.8.0] - 2020-08-01
- fine-grained Cloud DNS IAM via Service Directory example
@ -156,7 +162,8 @@ All notable changes to this project will be documented in this file.
- merge development branch with suite of new modules and end-to-end examples
[Unreleased]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v2.8.0...HEAD
[Unreleased]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v3.0.0...HEAD
[3.0.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v2.8.0...v3.0.0
[2.8.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v2.7.1...v2.8.0
[2.7.1]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v2.7.0...v2.7.1
[2.7.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v2.6.0...v2.7.0

View File

@ -2,8 +2,7 @@
This repository provides **end-to-end examples** and a **suite of Terraform modules** for Google Cloud, which support different use cases:
- starter kits used to bootstrap real-world cloud foundations and infrastructure
- reference examples used to deep dive on network patterns or product features
- starter kits used to bootstrap real-world cloud foundations, and reference examples used to deep dive on network patterns or product features
- composable modules that support quick prototyping and testing
- a comprehensive source of lean modules that lend themselves well to changes
@ -13,16 +12,16 @@ Both the examples and modules require some measure of Terraform skills to be use
## End-to-end examples
The examples in this repository are split in two main sections: **foundational examples** that bootstrap the organizational hierarchy and automation prerequisites, and **infrastructure scenarios** that implement core networking patterns or features.
The examples in this repository are split in several main sections: **foundational examples** that bootstrap the organizational hierarchy and automation prerequisites, **networking examples** that implement core patterns or features, **data solutions examples** that demonstrate how to integrate data services in complete scenarios, and **cloud operations examples** that leverage specific products to meet specific operational needs.
Currently available examples:
- **foundations** - [single level hierarchy](./foundations/environments/) (environments), [multiple level hierarchy](./foundations/business-units/) (business units + environments)
- **infrastructure** - [hub and spoke via peering](./infrastructure/hub-and-spoke-peering/), [hub and spoke via VPN](./infrastructure/hub-and-spoke-vpn/), [DNS and Google Private Access for on-premises](./infrastructure/onprem-google-access-dns/), [Shared VPC with GKE support](./infrastructure/shared-vpc-gke/)
- **networking** - [hub and spoke via peering](./networking/hub-and-spoke-peering/), [hub and spoke via VPN](./networking/hub-and-spoke-vpn/), [DNS and Google Private Access for on-premises](./networking/onprem-google-access-dns/), [Shared VPC with GKE support](./networking/shared-vpc-gke/), [ILB as next hop](./networking/ilb-next-hop)
- **data solutions** - [GCE/GCS CMEK via centralized Cloud KMS](./data-solutions/cmek-via-centralized-kms/), [Cloud Storage to Bigquery with Cloud Dataflow](./data-solutions/gcs-to-bq-with-dataflow/)
- **cloud operations** - [Resource tracking and remediation via Cloud Asset feeds](.//cloud-operations/asset-inventory-feed-remediation), [Granular Cloud DNS IAM via Service Directory](./cloud-operations/dns-fine-grained-iam)
For more information see the README files in the [foundations](./foundations/), [infrastructure](./infrastructure/), [data solutions](./data-solutions/) and [cloud operations](./cloud-operations/) folders.
For more information see the README files in the [foundations](./foundations/), [networking](./networking/), [data solutions](./data-solutions/) and [cloud operations](./cloud-operations/) folders.
## Modules

View File

@ -147,6 +147,7 @@ module "instance-group" {
| *attached_disk_defaults* | Defaults for attached disks options. | <code title="object&#40;&#123;&#10;auto_delete &#61; bool&#10;mode &#61; string&#10;type &#61; string&#10;source &#61; string&#10;&#125;&#41;">object({...})</code> | | <code title="&#123;&#10;auto_delete &#61; true&#10;source &#61; null&#10;mode &#61; &#34;READ_WRITE&#34;&#10;type &#61; &#34;pd-ssd&#34;&#10;&#125;">...</code> |
| *attached_disks* | Additional disks, if options is null defaults will be used in its place. | <code title="list&#40;object&#40;&#123;&#10;name &#61; string&#10;image &#61; string&#10;size &#61; string&#10;options &#61; object&#40;&#123;&#10;auto_delete &#61; bool&#10;mode &#61; string&#10;source &#61; string&#10;type &#61; string&#10;&#125;&#41;&#10;&#125;&#41;&#41;">list(object({...}))</code> | | <code title="">[]</code> |
| *boot_disk* | Boot disk properties. | <code title="object&#40;&#123;&#10;image &#61; string&#10;size &#61; number&#10;type &#61; string&#10;&#125;&#41;">object({...})</code> | | <code title="&#123;&#10;image &#61; &#34;projects&#47;debian-cloud&#47;global&#47;images&#47;family&#47;debian-10&#34;&#10;type &#61; &#34;pd-ssd&#34;&#10;size &#61; 10&#10;&#125;">...</code> |
| *can_ip_forward* | Enable IP forwarding. | <code title="">bool</code> | | <code title="">false</code> |
| *encryption* | Encryption options. Only one of kms_key_self_link and disk_encryption_key_raw may be set. If needed, you can specify to encrypt or not the boot disk. | <code title="object&#40;&#123;&#10;encrypt_boot &#61; bool&#10;disk_encryption_key_raw &#61; string&#10;kms_key_self_link &#61; string&#10;&#125;&#41;">object({...})</code> | | <code title="">null</code> |
| *group* | Define this variable to create an instance group for instances. Disabled for template use. | <code title="object&#40;&#123;&#10;named_ports &#61; map&#40;number&#41;&#10;&#125;&#41;">object({...})</code> | | <code title="">null</code> |
| *hostname* | Instance FQDN name. | <code title="">string</code> | | <code title="">null</code> |
@ -156,8 +157,9 @@ module "instance-group" {
| *instance_type* | Instance type. | <code title="">string</code> | | <code title="">f1-micro</code> |
| *labels* | Instance labels. | <code title="map&#40;string&#41;">map(string)</code> | | <code title="">{}</code> |
| *metadata* | Instance metadata. | <code title="map&#40;string&#41;">map(string)</code> | | <code title="">{}</code> |
| *metadata_list* | List of instance metadata that will be cycled through. Ignored for template use. | <code title="list&#40;map&#40;string&#41;&#41;">list(map(string))</code> | | <code title="">[]</code> |
| *min_cpu_platform* | Minimum CPU platform. | <code title="">string</code> | | <code title="">null</code> |
| *options* | Instance options. | <code title="object&#40;&#123;&#10;allow_stopping_for_update &#61; bool&#10;can_ip_forward &#61; bool&#10;deletion_protection &#61; bool&#10;preemptible &#61; bool&#10;&#125;&#41;">object({...})</code> | | <code title="&#123;&#10;allow_stopping_for_update &#61; true&#10;can_ip_forward &#61; false&#10;deletion_protection &#61; false&#10;preemptible &#61; false&#10;&#125;">...</code> |
| *options* | Instance options. | <code title="object&#40;&#123;&#10;allow_stopping_for_update &#61; bool&#10;deletion_protection &#61; bool&#10;preemptible &#61; bool&#10;&#125;&#41;">object({...})</code> | | <code title="&#123;&#10;allow_stopping_for_update &#61; true&#10;deletion_protection &#61; false&#10;preemptible &#61; false&#10;&#125;">...</code> |
| *scratch_disks* | Scratch disks configuration. | <code title="object&#40;&#123;&#10;count &#61; number&#10;interface &#61; string&#10;&#125;&#41;">object({...})</code> | | <code title="&#123;&#10;count &#61; 0&#10;interface &#61; &#34;NVME&#34;&#10;&#125;">...</code> |
| *service_account* | Service account email. Unused if service account is auto-created. | <code title="">string</code> | | <code title="">null</code> |
| *service_account_create* | Auto-create service account. | <code title="">bool</code> | | <code title="">false</code> |

View File

@ -94,11 +94,13 @@ resource "google_compute_instance" "default" {
tags = var.tags
machine_type = var.instance_type
min_cpu_platform = var.min_cpu_platform
can_ip_forward = var.options.can_ip_forward
can_ip_forward = var.can_ip_forward
allow_stopping_for_update = var.options.allow_stopping_for_update
deletion_protection = var.options.deletion_protection
metadata = var.metadata
labels = var.labels
metadata = merge(
var.metadata, try(element(var.metadata_list, each.value), {})
)
dynamic attached_disk {
for_each = {
@ -199,7 +201,7 @@ resource "google_compute_instance_template" "default" {
tags = var.tags
machine_type = var.instance_type
min_cpu_platform = var.min_cpu_platform
can_ip_forward = var.options.can_ip_forward
can_ip_forward = var.can_ip_forward
metadata = var.metadata
labels = var.labels

View File

@ -60,6 +60,12 @@ variable "boot_disk" {
}
}
variable "can_ip_forward" {
description = "Enable IP forwarding."
type = bool
default = false
}
variable "encryption" {
description = "Encryption options. Only one of kms_key_self_link and disk_encryption_key_raw may be set. If needed, you can specify to encrypt or not the boot disk."
type = object({
@ -120,6 +126,12 @@ variable "metadata" {
default = {}
}
variable "metadata_list" {
description = "List of instance metadata that will be cycled through. Ignored for template use."
type = list(map(string))
default = []
}
variable "min_cpu_platform" {
description = "Minimum CPU platform."
type = string
@ -148,13 +160,11 @@ variable "options" {
description = "Instance options."
type = object({
allow_stopping_for_update = bool
can_ip_forward = bool
deletion_protection = bool
preemptible = bool
})
default = {
allow_stopping_for_update = true
can_ip_forward = false
deletion_protection = false
preemptible = false
}

View File

@ -97,9 +97,9 @@ module "vpc-sc" {
| access_policy_title | Access Policy title to be created. | <code title="">string</code> | ✓ | |
| org_id | Organization id in nnnnnn format. | <code title="">number</code> | ✓ | |
| *access_level_perimeters* | Enforced mode -> Access Level -> Perimeters mapping. Enforced mode can be 'enforced' or 'dry_run' | <code title="map&#40;map&#40;list&#40;string&#41;&#41;&#41;">map(map(list(string)))</code> | | <code title="">{}</code> |
| *access_levels* | Access Levels. | <code title="map&#40;object&#40;&#123;&#10;combining_function &#61; string&#10;conditions &#61; list&#40;object&#40;&#123;&#10;ip_subnetworks &#61; list&#40;string&#41;&#10;members &#61; list&#40;string&#41;&#10;negate &#61; string&#10;&#125;&#41;&#41;&#10;&#125;&#41;&#41;">map(object({...}))</code> | | <code title="">{}</code> |
| *access_levels* | Access Levels. | <code title="map&#40;object&#40;&#123;&#10;combining_function &#61; string&#10;conditions &#61; list&#40;object&#40;&#123;&#10;ip_subnetworks &#61; list&#40;string&#41;&#10;members &#61; list&#40;string&#41;&#10;negate &#61; string&#10;&#125;&#41;&#41;&#10;&#125;&#41;&#41;">map(object({...}))</code> | | <code title="">{}</code> |
| *perimeter_projects* | Perimeter -> Enforced Mode -> Projects Number mapping. Enforced mode can be 'enforced' or 'dry_run'. | <code title="map&#40;map&#40;list&#40;number&#41;&#41;&#41;">map(map(list(number)))</code> | | <code title="">{}</code> |
| *perimeters* | Set of Perimeters. | <code title="map&#40;object&#40;&#123;&#10;type &#61; string&#10;dry_run_config &#61; object&#40;&#123;&#10;restricted_services &#61; list&#40;string&#41;&#10;vpc_accessible_services &#61; list&#40;string&#41;&#10;&#125;&#41;&#10;enforced_config &#61; object&#40;&#123;&#10;restricted_services &#61; list&#40;string&#41;&#10;vpc_accessible_services &#61; list&#40;string&#41;&#10;&#125;&#41;&#10;&#125;&#41;&#41;">map(object({...}))</code> | | <code title="">{}</code> |
| *perimeters* | Set of Perimeters. | <code title="map&#40;object&#40;&#123;&#10;type &#61; string&#10;dry_run_config &#61; object&#40;&#123;&#10;restricted_services &#61; list&#40;string&#41;&#10;vpc_accessible_services &#61; list&#40;string&#41;&#10;&#125;&#41;&#10;enforced_config &#61; object&#40;&#123;&#10;restricted_services &#61; list&#40;string&#41;&#10;vpc_accessible_services &#61; list&#40;string&#41;&#10;&#125;&#41;&#10;&#125;&#41;&#41;">map(object({...}))</code> | | <code title="">{}</code> |
## Outputs

View File

@ -28,6 +28,12 @@ The emulated on-premises environment can be used to test access to different ser
<br clear="left">
### Shared VPC with GKE and per-subnet support
<a href="./shared-vpc-gke/" title="Shared VPC with GKE"><img src="./shared-vpc-gke/diagram.png" align="left" width="280px"></a> This [example](./shared-vpc-gke/) shows how to configure a Shared VPC, including the specific IAM configurations needed for GKE, and to give different level of access to the VPC subnets to different identities.
It is meant to be used as a starting point for most Shared VPC configurations, and to be integrated to the above examples where Shared VPC is needed in more complex network topologies.
<br clear="left">
### ILB as next hop
<a href="./ilb-next-hop/" title="ILB as next hop"><img src="./ilb-next-hop/diagram.png" align="left" width="280px"></a> This [example](./ilb-next-hop/) allows testing [ILB as next hop](https://cloud.google.com/load-balancing/docs/internal/ilb-next-hop-overview) using simple Linux gateway VMS between two VPCs, to emulate virtual appliances. An optional additional ILB can be enabled to test multiple load balancer configurations and hashing.

View File

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

View File

Before

Width:  |  Height:  |  Size: 148 KiB

After

Width:  |  Height:  |  Size: 148 KiB

View File

Before

Width:  |  Height:  |  Size: 195 KiB

After

Width:  |  Height:  |  Size: 195 KiB

View File

@ -0,0 +1,79 @@
# Internal Load Balancer as Next Hop
This example bootstraps a minimal infrastructure for testing [ILB as next hop](https://cloud.google.com/load-balancing/docs/internal/ilb-next-hop-overview), using simple Linux gateway VMS between two VPCs to emulate virtual appliances.
The following diagram shows the resources created by this example
![High-level diagram](diagram.png "High-level diagram")
Two ILBs are configured on the primary and secondary interfaces of gateway VMs with active health checks, but only the single one is used as next hop by default to simplify testing. The second (right-side) VPC has default routes that point to the gateway VMs, to also use the right-side ILB as next hop set the `ilb_right_enable` variable to `true`.
## Testing
Since ILBs as next hops only forward TCP and UDP traffic, simple tests use `curl` on clients to send HTTP requests. To make this practical, test VMs on both VPCs have `nginx` pre-installed and active on port 80.
On the gateways, `iftop` is installed by default to quickly monitor traffic passing forwarded across VPCs.
Session affinity on the ILB backend services can be changed using `gcloud compute backend-services update` on each of the ILBs, or by setting the `ilb_session_affinity` variable to update both ILBs.
Simple `/root/start.sh` and `/root/stop.sh` scripts are pre-installed on both gateways to configure `iptables` so that health check requests are rejected and re-enabled, to quickly simulate removing instances from the ILB backends.
Some scenarios to test:
- short-lived connections with session affinity set to the default of `NONE`, then to `CLIENT_IP`
- long-lived connections, failing health checks on the active gateway while the connection is active
### Useful commands (adjust names and addresses to match)
Create a large file on a destination VM (eg `ilb-test-vm-right-1`) to test long-running connections.
```bash
dd if=/dev/zero of=/var/www/html/test.txt bs=10M count=100 status=progress
```
Run curl from a source VM (eg `ilb-test-vm-left-1`) to send requests to a destination VM artifically slowing traffic.
```
curl -0 --output /dev/null --limit-rate 10k 10.0.1.3/test.txt
```
Monitor traffic from a source VM (eg `ilb-test-vm-left-1`) on the gateways.
```bash
iftop -n -F 10.0.0.3/32
```
Poll summary health status for a backend.
```bash
watch '\
gcloud compute backend-services get-health ilb-test-ilb-right \
--region europe-west1 \
--flatten status.healthStatus \
--format "value(status.healthStatus.ipAddress, status.healthStatus.healthState)" \
'
```
A sample testing session using `tmux`:
<a href="https://raw.githubusercontent.com/terraform-google-modules/cloud-foundation-fabric/master/networking/ilb-next-hop/test_session.png" title="Test session screenshot"><img src="./test_session.png" width="640px" alt="Test session screenshot"></img>
<!-- BEGIN TFDOC -->
## Variables
| name | description | type | required | default |
|---|---|:---: |:---:|:---:|
| project_id | Existing project id. | <code title="">string</code> | ✓ | |
| *ilb_right_enable* | Route right to left traffic through ILB. | <code title="">bool</code> | | <code title="">false</code> |
| *ilb_session_affinity* | Session affinity configuration for ILBs. | <code title="">string</code> | | <code title="">CLIENT_IP</code> |
| *ip_ranges* | IP CIDR ranges used for VPC subnets. | <code title="map&#40;string&#41;">map(string)</code> | | <code title="&#123;&#10;left &#61; &#34;10.0.0.0&#47;24&#34;&#10;right &#61; &#34;10.0.1.0&#47;24&#34;&#10;&#125;">...</code> |
| *prefix* | Prefix used for resource names. | <code title="">string</code> | | <code title="">ilb-test</code> |
| *project_create* | Create project instead of using an existing one. | <code title="">bool</code> | | <code title="">false</code> |
| *region* | Region used for resources. | <code title="">string</code> | | <code title="">europe-west1</code> |
## Outputs
| name | description | sensitive |
|---|---|:---:|
| addresses | Internal addresses of created VMS. | |
<!-- END TFDOC -->

View File

@ -0,0 +1,72 @@
#cloud-config
# Copyright 2020 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.
write_files:
- path: /etc/sysctl.conf
permissions: "0644"
owner: root
content: |
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
# https://tldp.org/HOWTO/Adv-Routing-HOWTO/lartc.kernel.rpf.html
net.ipv4.conf.all.rp_filter = 2
net.ipv4.conf.ens4.rp_filter = 2
net.ipv4.conf.ens5.rp_filter = 2
- path: /etc/netplan/99-nic2-routing.yaml
permissions: "0644"
owner: root
content: |
network:
ethernets:
ens5:
dhcp4: true
routes:
- to: 0.0.0.0/0
via: ${gw_right}
table: 102
routing-policy:
- from: ${ip_cidr_right}
to: 35.191.0.0/16
table: 102
- from: ${ip_cidr_right}
to: 130.211.0.0/22
table: 102
version: 2
- path: /root/start.sh
permissions: "0755"
owner: root
content: |
#!/bin/bash
iptables -D INPUT -s 35.191.0.0/16 -j REJECT
iptables -D INPUT -s 130.211.0.0/22 -j REJECT
- path: /root/stop.sh
permissions: "0755"
owner: root
content: |
#!/bin/bash
iptables -I INPUT -s 35.191.0.0/16 -j REJECT
iptables -I INPUT -s 130.211.0.0/22 -j REJECT
package_update: true
package_upgrade: true
package_reboot_if_required: true
packages:
- iftop
- tcpdump
runcmd:
- sysctl -p
- netplan apply

View File

@ -0,0 +1,20 @@
# Copyright 2020 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.
terraform {
backend "gcs" {
bucket = ""
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

View File

@ -0,0 +1,106 @@
/**
* Copyright 2020 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 "gw" {
source = "../../modules/compute-vm"
project_id = module.project.project_id
region = var.region
name = "${local.prefix}gw"
instance_type = "f1-micro"
boot_disk = {
image = "projects/ubuntu-os-cloud/global/images/family/ubuntu-2004-lts",
type = "pd-ssd",
size = 10
}
network_interfaces = [
{
network = module.vpc-left.self_link
subnetwork = values(module.vpc-left.subnet_self_links)[0],
nat = false,
addresses = null
},
{
network = module.vpc-right.self_link
subnetwork = values(module.vpc-right.subnet_self_links)[0],
nat = false,
addresses = null
}
]
tags = ["ssh"]
can_ip_forward = true
metadata = {
user-data = templatefile("${path.module}/assets/gw.yaml", {
gw_right = cidrhost(var.ip_ranges.right, 1)
ip_cidr_right = var.ip_ranges.right
})
}
service_account = try(
module.service-accounts.emails["${local.prefix}gce-vm"], null
)
service_account_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
instance_count = 2
group = { named_ports = null }
}
module "ilb-left" {
source = "../../modules/net-ilb"
project_id = module.project.project_id
region = var.region
name = "${local.prefix}ilb-left"
network = module.vpc-left.self_link
subnetwork = values(module.vpc-left.subnet_self_links)[0]
address = local.addresses.ilb-left
ports = null
backend_config = {
session_affinity = var.ilb_session_affinity
timeout_sec = null
connection_draining_timeout_sec = null
}
backends = [{
failover = false
group = module.gw.group.self_link
balancing_mode = "CONNECTION"
}]
health_check_config = {
type = "tcp", check = { port = 22 }, config = {}, logging = true
}
}
module "ilb-right" {
source = "../../modules/net-ilb"
project_id = module.project.project_id
region = var.region
name = "${local.prefix}ilb-right"
network = module.vpc-right.self_link
subnetwork = values(module.vpc-right.subnet_self_links)[0]
address = local.addresses.ilb-right
ports = null
backend_config = {
session_affinity = var.ilb_session_affinity
timeout_sec = null
connection_draining_timeout_sec = null
}
backends = [{
failover = false
group = module.gw.group.self_link
balancing_mode = "CONNECTION"
}]
health_check_config = {
type = "tcp", check = { port = 22 }, config = {}, logging = true
}
}

View File

@ -0,0 +1,64 @@
/**
* Copyright 2020 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 {
addresses = {
for k, v in module.addresses.internal_addresses :
trimprefix(k, local.prefix) => v.address
}
prefix = var.prefix == null || var.prefix == "" ? "" : "${var.prefix}-"
}
module "project" {
source = "../../modules/project"
name = var.project_id
project_create = var.project_create
services = [
"compute.googleapis.com",
"dns.googleapis.com",
]
service_config = {
disable_on_destroy = false
disable_dependent_services = false
}
}
module "service-accounts" {
source = "../../modules/iam-service-accounts"
project_id = module.project.project_id
names = ["${local.prefix}gce-vm"]
iam_project_roles = {
(var.project_id) = [
"roles/logging.logWriter",
"roles/monitoring.metricWriter",
]
}
}
module "addresses" {
source = "../../modules/net-address"
project_id = module.project.project_id
internal_addresses = {
"${local.prefix}ilb-left" = {
region = var.region,
subnetwork = values(module.vpc-left.subnet_self_links)[0]
},
"${local.prefix}ilb-right" = {
region = var.region,
subnetwork = values(module.vpc-right.subnet_self_links)[0]
}
}
}

View File

@ -0,0 +1,20 @@
/**
* Copyright 2020 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 "addresses" {
description = "Internal addresses of created VMS."
value = null
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

@ -0,0 +1,59 @@
/**
* Copyright 2020 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 "ilb_right_enable" {
description = "Route right to left traffic through ILB."
type = bool
default = false
}
variable "ilb_session_affinity" {
description = "Session affinity configuration for ILBs."
type = string
default = "CLIENT_IP"
}
variable "ip_ranges" {
description = "IP CIDR ranges used for VPC subnets."
type = map(string)
default = {
left = "10.0.0.0/24"
right = "10.0.1.0/24"
}
}
variable "prefix" {
description = "Prefix used for resource names."
type = string
default = "ilb-test"
}
variable "project_create" {
description = "Create project instead of using an existing one."
type = bool
default = false
}
variable "project_id" {
description = "Existing project id."
type = string
}
variable "region" {
description = "Region used for resources."
type = string
default = "europe-west1"
}

View File

@ -0,0 +1,17 @@
# 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.
terraform {
required_version = ">= 0.12.6"
}

View File

@ -0,0 +1,73 @@
/**
* Copyright 2020 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 {
vm_startup_script = <<END
apt update
apt upgrade -y
apt install -y nginx tcpdump
END
}
module "vm-left" {
source = "../../modules/compute-vm"
project_id = module.project.project_id
region = var.region
name = "${local.prefix}vm-left"
instance_type = "f1-micro"
network_interfaces = [
{
network = module.vpc-left.self_link
subnetwork = values(module.vpc-left.subnet_self_links)[0],
nat = false,
addresses = null
}
]
tags = ["ssh"]
metadata = {
startup-script = local.vm_startup_script
}
service_account = try(
module.service-accounts.emails["${local.prefix}gce-vm"], null
)
service_account_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
instance_count = 2
}
module "vm-right" {
source = "../../modules/compute-vm"
project_id = module.project.project_id
region = var.region
name = "${local.prefix}vm-right"
instance_type = "f1-micro"
network_interfaces = [
{
network = module.vpc-right.self_link
subnetwork = values(module.vpc-right.subnet_self_links)[0],
nat = false,
addresses = null
}
]
tags = ["ssh"]
metadata = {
startup-script = local.vm_startup_script
}
service_account = try(
module.service-accounts.emails["${local.prefix}gce-vm"], null
)
service_account_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
instance_count = 2
}

View File

@ -0,0 +1,55 @@
/**
* Copyright 2020 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 "vpc-left" {
source = "../../modules/net-vpc"
project_id = module.project.project_id
name = "${local.prefix}left"
subnets = [
{
ip_cidr_range = var.ip_ranges.left
name = "${local.prefix}left"
region = var.region
secondary_ip_range = {}
},
]
routes = {
to-right = {
dest_range = var.ip_ranges.right
priority = null
tags = null
next_hop_type = "ilb"
next_hop = module.ilb-left.forwarding_rule.self_link
}
}
}
module "firewall-left" {
source = "../../modules/net-vpc-firewall"
project_id = module.project.project_id
network = module.vpc-left.name
admin_ranges_enabled = true
admin_ranges = values(var.ip_ranges)
ssh_source_ranges = ["35.235.240.0/20", "35.191.0.0/16", "130.211.0.0/22"]
}
module "nat-left" {
source = "../../modules/net-cloudnat"
project_id = module.project.project_id
region = var.region
name = "${local.prefix}left"
router_network = module.vpc-left.name
}

View File

@ -0,0 +1,69 @@
/**
* Copyright 2020 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 "vpc-right" {
source = "../../modules/net-vpc"
project_id = module.project.project_id
name = "${local.prefix}right"
subnets = [
{
ip_cidr_range = var.ip_ranges.right
name = "${local.prefix}right"
region = var.region
secondary_ip_range = {}
},
]
routes = {
to-left-ilb = {
dest_range = var.ip_ranges.left
priority = var.ilb_right_enable ? 900 : 1100
tags = null
next_hop_type = "ilb"
next_hop = module.ilb-right.forwarding_rule.self_link
}
to-left-gw-1 = {
dest_range = var.ip_ranges.left
priority = null
tags = null
next_hop_type = "instance"
next_hop = module.gw.instances.0.self_link
}
to-left-gw-2 = {
dest_range = var.ip_ranges.left
priority = null
tags = null
next_hop_type = "instance"
next_hop = module.gw.instances.1.self_link
}
}
}
module "firewall-right" {
source = "../../modules/net-vpc-firewall"
project_id = module.project.project_id
network = module.vpc-right.name
admin_ranges_enabled = true
admin_ranges = values(var.ip_ranges)
ssh_source_ranges = ["35.235.240.0/20", "35.191.0.0/16", "130.211.0.0/22"]
}
module "nat-right" {
source = "../../modules/net-cloudnat"
project_id = module.project.project_id
region = var.region
name = "${local.prefix}right"
router_network = module.vpc-right.name
}

View File

Before

Width:  |  Height:  |  Size: 140 KiB

After

Width:  |  Height:  |  Size: 140 KiB

View File

@ -205,7 +205,7 @@ module "vm-test" {
module "config-onprem" {
source = "../../modules/cloud-config-container/onprem"
config_variables = { dns_forwarder_address = var.dns_forwarder_address }
coredns_config = "assets/Corefile"
coredns_config = "${path.module}/assets/Corefile"
local_ip_cidr_range = var.ip_ranges.onprem
vpn_config = {
peer_ip = module.vpn.address

View File

@ -6,33 +6,18 @@ The sample has been purposefully kept simple so that it can be used as a basis f
![High-level diagram](diagram.png "High-level diagram")
## Managed resources and services
## Applying the example
This sample creates several distinct groups of resources:
The example cannot be applied from scratch with a single `terraform apply` command, as Terraform is unable to manage Shared VPC project registration for multiple projects, before those are created and exist in state. To apply the example from scratch, follow this order:
- projects
- host project
- service project configured for GKE clusters
- service project configured for GCE instances
- networking
- the shared VPC network
- one subnet with secondary ranges for GKE clusters
- one subnet for GCE instances
- firewall rules for [SSH access via IAP](https://cloud.google.com/iap/docs/using-tcp-forwarding) and open communication within the VPC
- Cloud NAT service
- IAM
- one service account for the bastion CGE instance
- one service account for the GKE nodes
- optional owner role bindings on each project
- optional [OS Login](https://cloud.google.com/compute/docs/oslogin/) role bindings on the GCE service project
- role bindings to allow the GCE instance and GKE nodes logging and monitoring write access
- role binding to allow the GCE instance cluster access
- DNS
- one private zone
- GCE
- one instance used to access the internal GKE cluster
- GKE
- one private cluster with one nodepool
```bash
tf apply \
-target module.project-svc-gce \
-target module.project-svc-gke
tf apply
```
Once the first command has run successfully, the service projects exist in state and can be referenced by the multiple resource in the host project module that manages project registration.
## Accessing the bastion instance and GKE cluster

View File

Before

Width:  |  Height:  |  Size: 93 KiB

After

Width:  |  Height:  |  Size: 93 KiB

View File

@ -26,6 +26,13 @@ module "project-host" {
prefix = var.prefix
name = "net"
services = concat(var.project_services, ["dns.googleapis.com"])
shared_vpc_config = {
enabled = true
service_projects = [
module.project-svc-gce.project_id,
module.project-svc-gke.project_id
]
}
iam_roles = [
"roles/container.hostServiceAgentUser", "roles/owner"
]
@ -70,11 +77,15 @@ module "project-svc-gke" {
services = var.project_services
iam_roles = [
"roles/container.developer",
"roles/logging.logWriter",
"roles/monitoring.metricWriter",
"roles/owner",
]
iam_members = {
"roles/owner" = var.owners_gke
"roles/container.developer" = [module.vm-bastion.service_account_iam_email]
"roles/container.developer" = [module.vm-bastion.service_account_iam_email],
"roles/logging.logWriter" = [module.service-account-gke-node.iam_email],
"roles/monitoring.metricWriter" = [module.service-account-gke-node.iam_email],
"roles/owner" = var.owners_gke
}
}
@ -85,14 +96,9 @@ module "project-svc-gke" {
# subnet IAM bindings control which identities can use the individual subnets
module "vpc-shared" {
source = "../../modules/net-vpc"
project_id = module.project-host.project_id
name = "shared-vpc"
shared_vpc_host = true
shared_vpc_service_projects = [
module.project-svc-gce.project_id,
module.project-svc-gke.project_id
]
source = "../../modules/net-vpc"
project_id = module.project-host.project_id
name = "shared-vpc"
subnets = [
{
ip_cidr_range = var.ip_ranges.gce
@ -236,10 +242,4 @@ module "service-account-gke-node" {
source = "../../modules/iam-service-accounts"
project_id = module.project-svc-gke.project_id
names = ["gke-node"]
iam_project_roles = {
(module.project-svc-gke.project_id) = [
"roles/logging.logWriter",
"roles/monitoring.metricWriter",
]
}
}

View File

@ -22,22 +22,35 @@ import tftest
BASEDIR = os.path.dirname(os.path.dirname(__file__))
@pytest.fixture(scope='session')
def e2e_plan_runner(plan_runner):
"Returns a function to run Terraform plan on an end-to-end fixture."
def run_plan(fixture_path, targets=None):
"Runs Terraform plan on an end-to-end module using defaults, returns data."
_, modules = plan_runner(fixture_path, is_module=False, targets=targets)
resources = [r for m in modules.values() for r in m]
return modules, resources
return run_plan
@pytest.fixture(scope='session')
def plan_runner():
"Returns a function to run Terraform plan on a fixture."
def run_plan(fixture_path, is_module=True, **tf_vars):
def run_plan(fixture_path, is_module=True, targets=None, **tf_vars):
"Runs Terraform plan and returns parsed output"
tf = tftest.TerraformTest(fixture_path, BASEDIR,
os.environ.get('TERRAFORM', 'terraform'))
tf.setup()
plan = tf.plan(output=True, tf_vars=tf_vars)
plan = tf.plan(output=True, tf_vars=tf_vars, targets=targets)
root_module = plan.planned_values['root_module']['child_modules'][0]
if is_module:
return (plan, root_module['resources'])
modules = dict((mod['address'], mod['resources'])
for mod in root_module['child_modules'])
return (plan, modules)
return plan, modules
return run_plan
@ -53,6 +66,6 @@ def apply_runner():
tf.setup()
apply = tf.apply(tf_vars=tf_vars)
output = tf.output(json_format=True)
return (apply, output)
return apply, output
return run_apply

View File

@ -18,10 +18,8 @@ module "test" {
source = "../../../../foundations/environments"
billing_account_id = var.billing_account_id
environments = var.environments
iam_assets_editors = var.iam_assets_editors
iam_assets_owners = var.iam_assets_owners
iam_audit_viewers = var.iam_audit_viewers
iam_sharedsvc_owners = var.iam_sharedsvc_owners
iam_shared_owners = var.iam_shared_owners
iam_terraform_owners = var.iam_terraform_owners
iam_xpn_config = var.iam_xpn_config
organization_id = var.organization_id

View File

@ -22,22 +22,12 @@ variable "environments" {
default = ["test", "prod"]
}
variable "iam_assets_editors" {
type = list(string)
default = ["user:assets-ed-1@example.org", "user:assets-ed-2@example.org"]
}
variable "iam_assets_owners" {
type = list(string)
default = ["user:assets-own-1@example.org", "user:assets-own-2@example.org"]
}
variable "iam_audit_viewers" {
type = list(string)
default = ["user:audit-1@example.org", "user:audit2@example.org"]
}
variable "iam_sharedsvc_owners" {
variable "iam_shared_owners" {
type = list(string)
default = ["user:shared-1@example.org", "user:shared-2@example.org"]
}

View File

@ -27,4 +27,6 @@ module "test" {
group = var.group
iam_roles = var.iam_roles
iam_members = var.iam_members
metadata = var.metadata
metadata_list = var.metadata_list
}

View File

@ -34,6 +34,16 @@ variable "instance_count" {
default = 1
}
variable "metadata" {
type = map(string)
default = {}
}
variable "metadata_list" {
type = list(map(string))
default = []
}
variable "network_interfaces" {
type = list(object({
nat = bool

View File

@ -0,0 +1,34 @@
# Copyright 2020 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')
def test_default(plan_runner):
_, resources = plan_runner(FIXTURES_DIR, metadata='{a=1, b=2}')
assert resources[0]['values']['metadata'] == {'a': '1', 'b': '2'}
def test_multi(plan_runner):
_, resources = plan_runner(FIXTURES_DIR, instance_count=3,
metadata='{a=1, b=2}',
metadata_list='[{c=3}, {c=4}]')
assert resources[0]['values']['metadata'] == {'a': '1', 'b': '2', 'c': '3'}
assert resources[1]['values']['metadata'] == {'a': '1', 'b': '2', 'c': '4'}
assert resources[2]['values']['metadata'] == {'a': '1', 'b': '2', 'c': '3'}

View File

@ -0,0 +1,13 @@
# Copyright 2020 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.

View File

@ -0,0 +1,13 @@
# Copyright 2020 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.

View File

@ -0,0 +1,20 @@
/**
* Copyright 2020 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 = "../../../../networking/hub-and-spoke-peering"
project_id = var.project_id
}

View File

@ -0,0 +1,18 @@
# Copyright 2020 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.
variable "project_id" {
type = string
default = "project-1"
}

View File

@ -0,0 +1,27 @@
# Copyright 2020 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')
def test_resources(e2e_plan_runner):
"Test that plan works and the numbers of resources is as expected."
modules, resources = e2e_plan_runner(FIXTURES_DIR)
assert len(modules) == 18
assert len(resources) == 57

View File

@ -0,0 +1,13 @@
# Copyright 2020 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.

View File

@ -0,0 +1,20 @@
/**
* Copyright 2020 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 = "../../../../networking/hub-and-spoke-vpn"
project_id = var.project_id
}

View File

@ -0,0 +1,18 @@
# Copyright 2020 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.
variable "project_id" {
type = string
default = "project-1"
}

View File

@ -0,0 +1,27 @@
# Copyright 2020 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')
def test_resources(e2e_plan_runner):
"Test that plan works and the numbers of resources is as expected."
modules, resources = e2e_plan_runner(FIXTURES_DIR)
assert len(modules) == 17
assert len(resources) == 70

View File

@ -0,0 +1,13 @@
# Copyright 2020 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.

View File

@ -0,0 +1,21 @@
/**
* Copyright 2020 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 = "../../../../networking/ilb-next-hop"
project_create = var.project_create
project_id = var.project_id
}

View File

@ -0,0 +1,23 @@
# Copyright 2020 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.
variable "project_create" {
type = bool
default = true
}
variable "project_id" {
type = string
default = "project-1"
}

View File

@ -0,0 +1,27 @@
# Copyright 2020 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')
def test_resources(e2e_plan_runner):
"Test that plan works and the numbers of resources is as expected."
modules, resources = e2e_plan_runner(FIXTURES_DIR)
assert len(modules) == 14
assert len(resources) == 41

View File

@ -0,0 +1,13 @@
# Copyright 2020 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.

View File

@ -0,0 +1,20 @@
/**
* Copyright 2020 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 = "../../../../networking/onprem-google-access-dns"
project_id = var.project_id
}

View File

@ -0,0 +1,18 @@
# Copyright 2020 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.
variable "project_id" {
type = string
default = "project-1"
}

View File

@ -0,0 +1,27 @@
# Copyright 2020 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')
def test_resources(e2e_plan_runner):
"Test that plan works and the numbers of resources is as expected."
modules, resources = e2e_plan_runner(FIXTURES_DIR)
assert len(modules) == 11
assert len(resources) == 34

View File

@ -0,0 +1,13 @@
# Copyright 2020 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.

View File

@ -0,0 +1,22 @@
/**
* Copyright 2020 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 = "../../../../networking/shared-vpc-gke"
billing_account_id = var.billing_account_id
prefix = var.prefix
root_node = var.root_node
}

View File

@ -0,0 +1,28 @@
# Copyright 2020 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.
variable "billing_account_id" {
type = string
default = "ABCDE-12345-ABCDE"
}
variable "prefix" {
type = string
default = "test"
}
variable "root_node" {
type = string
default = "organizations/0123456789"
}

View File

@ -0,0 +1,30 @@
# Copyright 2020 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')
def test_resources(e2e_plan_runner):
"Test that plan works and the numbers of resources is as expected."
modules, resources = e2e_plan_runner(FIXTURES_DIR, targets=[
"module.test.module.project-svc-gce",
"module.test.module.project-svc-gke"
])
assert len(modules) == 4
assert len(resources) == 16

View File

@ -1,3 +1,3 @@
pytest>=4.6.0
PyYAML>=5.3
tftest>=1.5.0
tftest>=1.5.1