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
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -147,6 +147,7 @@ module "instance-group" {
|
|||
| *attached_disk_defaults* | Defaults for attached disks options. | <code title="object({ auto_delete = bool mode = string type = string source = string })">object({...})</code> | | <code title="{ auto_delete = true source = null mode = "READ_WRITE" type = "pd-ssd" }">...</code> |
|
||||
| *attached_disks* | Additional disks, if options is null defaults will be used in its place. | <code title="list(object({ name = string image = string size = string options = object({ auto_delete = bool mode = string source = string type = string }) }))">list(object({...}))</code> | | <code title="">[]</code> |
|
||||
| *boot_disk* | Boot disk properties. | <code title="object({ image = string size = number type = string })">object({...})</code> | | <code title="{ image = "projects/debian-cloud/global/images/family/debian-10" type = "pd-ssd" size = 10 }">...</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({ encrypt_boot = bool disk_encryption_key_raw = string kms_key_self_link = string })">object({...})</code> | | <code title="">null</code> |
|
||||
| *group* | Define this variable to create an instance group for instances. Disabled for template use. | <code title="object({ named_ports = map(number) })">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(string)">map(string)</code> | | <code title="">{}</code> |
|
||||
| *metadata* | Instance metadata. | <code title="map(string)">map(string)</code> | | <code title="">{}</code> |
|
||||
| *metadata_list* | List of instance metadata that will be cycled through. Ignored for template use. | <code title="list(map(string))">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({ allow_stopping_for_update = bool can_ip_forward = bool deletion_protection = bool preemptible = bool })">object({...})</code> | | <code title="{ allow_stopping_for_update = true can_ip_forward = false deletion_protection = false preemptible = false }">...</code> |
|
||||
| *options* | Instance options. | <code title="object({ allow_stopping_for_update = bool deletion_protection = bool preemptible = bool })">object({...})</code> | | <code title="{ allow_stopping_for_update = true deletion_protection = false preemptible = false }">...</code> |
|
||||
| *scratch_disks* | Scratch disks configuration. | <code title="object({ count = number interface = string })">object({...})</code> | | <code title="{ count = 0 interface = "NVME" }">...</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> |
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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(map(list(string)))">map(map(list(string)))</code> | | <code title="">{}</code> |
|
||||
| *access_levels* | Access Levels. | <code title="map(object({ combining_function = string conditions = list(object({ ip_subnetworks = list(string) members = list(string) negate = string })) }))">map(object({...}))</code> | | <code title="">{}</code> |
|
||||
| *access_levels* | Access Levels. | <code title="map(object({ combining_function = string conditions = list(object({ ip_subnetworks = list(string) members = list(string) negate = string })) }))">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(map(list(number)))">map(map(list(number)))</code> | | <code title="">{}</code> |
|
||||
| *perimeters* | Set of Perimeters. | <code title="map(object({ type = string dry_run_config = object({ restricted_services = list(string) vpc_accessible_services = list(string) }) enforced_config = object({ restricted_services = list(string) vpc_accessible_services = list(string) }) }))">map(object({...}))</code> | | <code title="">{}</code> |
|
||||
| *perimeters* | Set of Perimeters. | <code title="map(object({ type = string dry_run_config = object({ restricted_services = list(string) vpc_accessible_services = list(string) }) enforced_config = object({ restricted_services = list(string) vpc_accessible_services = list(string) }) }))">map(object({...}))</code> | | <code title="">{}</code> |
|
||||
|
||||
## Outputs
|
||||
|
||||
|
|
|
@ -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.
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 148 KiB After Width: | Height: | Size: 148 KiB |
Before Width: | Height: | Size: 195 KiB After Width: | Height: | Size: 195 KiB |
|
@ -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(string)">map(string)</code> | | <code title="{ left = "10.0.0.0/24" right = "10.0.1.0/24" }">...</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 -->
|
|
@ -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
|
|
@ -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 = ""
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 88 KiB |
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
After Width: | Height: | Size: 32 KiB |
|
@ -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"
|
||||
}
|
|
@ -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"
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
Before Width: | Height: | Size: 140 KiB After Width: | Height: | Size: 140 KiB |
|
@ -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
|
|
@ -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
|
||||
|
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 93 KiB |
|
@ -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",
|
||||
]
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"]
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'}
|
|
@ -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.
|
|
@ -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.
|
|
@ -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
|
||||
}
|
|
@ -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"
|
||||
}
|
|
@ -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
|
|
@ -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.
|
|
@ -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
|
||||
}
|
|
@ -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"
|
||||
}
|
|
@ -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
|
|
@ -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.
|
|
@ -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
|
||||
}
|
|
@ -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"
|
||||
}
|
|
@ -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
|
|
@ -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.
|
|
@ -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
|
||||
}
|
|
@ -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"
|
||||
}
|
|
@ -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
|
|
@ -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.
|
|
@ -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
|
||||
}
|
|
@ -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"
|
||||
}
|
|
@ -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
|
|
@ -1,3 +1,3 @@
|
|||
pytest>=4.6.0
|
||||
PyYAML>=5.3
|
||||
tftest>=1.5.0
|
||||
tftest>=1.5.1
|
||||
|
|