Assorted module fixes (#1045)

* net-ilb-l7 use both neg types in backends

* run example tests on cloud-config-container modules

* streamline nginx-tls cos module

* add tests for cos modules

* tfdoc

* onprem needs fixing, links

* disable test

* test
This commit is contained in:
Ludovico Magnocavallo
2022-12-10 15:40:15 +01:00
committed by GitHub
parent a119ce2d88
commit d2015b0bc3
78 changed files with 309 additions and 561 deletions

View File

@@ -8,7 +8,7 @@ Currently available blueprints:
- **data solutions** - [GCE and GCS CMEK via centralized Cloud KMS](./data-solutions/cmek-via-centralized-kms), [Cloud Composer version 2 private instance, supporting Shared VPC and external CMEK key](./data-solutions/composer-2), [Cloud SQL instance with multi-region read replicas](./data-solutions/cloudsql-multiregion), [Data Platform](./data-solutions/data-platform-foundations), [Spinning up a foundation data pipeline on Google Cloud using Cloud Storage, Dataflow and BigQuery](./data-solutions/gcs-to-bq-with-least-privileges), [#SQL Server Always On Groups blueprint](./data-solutions/sqlserver-alwayson), [Data Playground](./data-solutions/data-playground)
- **factories** - [The why and the how of Resource Factories](./factories), [Google Cloud Identity Group Factory](./factories/cloud-identity-group-factory), [Google Cloud BQ Factory](./factories/bigquery-factory), [Google Cloud VPC Firewall Factory](./factories/net-vpc-firewall-yaml), [Minimal Project Factory](./factories/project-factory)
- **GKE** - [Binary Authorization Pipeline Blueprint](./gke/binauthz), [Storage API](./gke/binauthz/image), [Multi-cluster mesh on GKE (fleet API)](./gke/multi-cluster-mesh-gke-fleet-api), [GKE Multitenant Blueprint](./gke/multitenant-fleet), [Shared VPC with GKE support](./networking/shared-vpc-gke/)
- **networking** - [Decentralized firewall management](./networking/decentralized-firewall), [Decentralized firewall validator](./networking/decentralized-firewall/validator), [Network filtering with Squid](./networking/filtering-proxy), [Network filtering with Squid with isolated VPCs using Private Service Connect](./networking/filtering-proxy-psc), [HTTP Load Balancer with Cloud Armor](./networking/glb-and-armor), [Hub and Spoke via VPN](./networking/hub-and-spoke-vpn), [Hub and Spoke via VPC Peering](./networking/hub-and-spoke-peering), [Internal Load Balancer as Next Hop](./networking/ilb-next-hop), [On-prem DNS and Google Private Access](./networking/onprem-google-access-dns), [Calling a private Cloud Function from On-premises](./networking/private-cloud-function-from-onprem), [Hybrid connectivity to on-premise services through PSC](./networking/psc-hybrid), [PSC Producer](./networking/psc-hybrid/psc-producer), [PSC Consumer](./networking/psc-hybrid/psc-consumer), [Shared VPC with optional GKE cluster](./networking/shared-vpc-gke)
- **networking** - [Decentralized firewall management](./networking/decentralized-firewall), [Decentralized firewall validator](./networking/decentralized-firewall/validator), [Network filtering with Squid](./networking/filtering-proxy), [Network filtering with Squid with isolated VPCs using Private Service Connect](./networking/filtering-proxy-psc), [HTTP Load Balancer with Cloud Armor](./networking/glb-and-armor), [Hub and Spoke via VPN](./networking/hub-and-spoke-vpn), [Hub and Spoke via VPC Peering](./networking/hub-and-spoke-peering), [Internal Load Balancer as Next Hop](./networking/ilb-next-hop), On-prem DNS and Google Private Access, [Calling a private Cloud Function from On-premises](./networking/private-cloud-function-from-onprem), [Hybrid connectivity to on-premise services through PSC](./networking/psc-hybrid), [PSC Producer](./networking/psc-hybrid/psc-producer), [PSC Consumer](./networking/psc-hybrid/psc-consumer), [Shared VPC with optional GKE cluster](./networking/shared-vpc-gke)
- **serverless** - [Creating multi-region deployments for API Gateway](./serverless/api-gateway)
- **third party solutions** - [OpenShift on GCP user-provisioned infrastructure](./third-party-solutions/openshift), [Wordpress deployment on Cloud Run](./third-party-solutions/wordpress/cloudrun)

View File

@@ -146,13 +146,11 @@ module "cf-healthchecker" {
name = "cf-healthchecker"
region = var.region
bucket_name = module.cf-restarter.bucket_name
bundle_config = {
source_dir = "${path.module}/function/healthchecker"
output_path = "healthchecker.zip"
}
service_account = module.service-account-healthchecker.email
function_config = {
entry_point = "HealthCheck"
ingress_settings = null
@@ -161,7 +159,6 @@ module "cf-healthchecker" {
runtime = "go116"
timeout = 300
}
environment_variables = {
FILTER = "name = nginx-*"
GRACE_PERIOD = var.grace_period
@@ -171,7 +168,6 @@ module "cf-healthchecker" {
TCP_PORT = var.tcp_port
TIMEOUT = var.timeout
}
vpc_connector = {
create = true
name = "hc-connector"
@@ -230,23 +226,25 @@ resource "google_cloud_scheduler_job" "healthcheck-job" {
module "cos-nginx" {
source = "../../../modules/cloud-config-container/nginx"
test_instance = {
project_id = module.project.project_id
zone = "${var.region}-b"
name = "nginx-test"
type = "f1-micro"
}
module "test-vm" {
source = "../../../modules/compute-vm"
project_id = module.project.project_id
zone = "${var.region}-b"
name = "nginx-test"
boot_disk = {
image = "projects/cos-cloud/global/images/family/cos-stable"
type = "pd-ssd"
size = 10
}
metadata = {
user-data = module.cos-nginx.cloud_config
google-logging-enabled = true
}
network_interfaces = [{
network = module.vpc.self_link
subnetwork = module.vpc.subnet_self_links["${var.region}/apps"]
}
test_instance_defaults = {
disks = {}
image = null
metadata = {}
nat = false
service_account_roles = [
"roles/logging.logWriter",
"roles/monitoring.metricWriter"
]
tags = ["ssh"]
}
}]
tags = ["ssh"]
}

View File

@@ -49,19 +49,20 @@ The blueprint shows how to implement spoke transitivity via BGP advertisements,
<!--
### Nginx-based reverse proxy cluster
<a href="./_deprecated/nginx-reverse-proxy-cluster/" title="Nginx-based reverse proxy cluster"><img src="./_deprecated/nginx-reverse-proxy-cluster/reverse-proxy.png" align="left" width="280px"></a> This [blueprint](./nginx-reverse-proxy-cluster/) how to deploy an autoscaling reverse proxy cluster using Nginx, based on regional Managed Instance Groups. The autoscaling is driven by Nginx current connections metric, sent by Cloud Ops Agent.
<a href="./__need_fixing/nginx-reverse-proxy-cluster/" title="Nginx-based reverse proxy cluster"><img src="./_deprecated/nginx-reverse-proxy-cluster/reverse-proxy.png" align="left" width="280px"></a> This [blueprint](./nginx-reverse-proxy-cluster/) how to deploy an autoscaling reverse proxy cluster using Nginx, based on regional Managed Instance Groups. The autoscaling is driven by Nginx current connections metric, sent by Cloud Ops Agent.
<br clear="left">
-->
### DNS and Private Access for On-premises
<a href="./onprem-google-access-dns/" title="DNS and Private Access for On-premises"><img src="./onprem-google-access-dns/diagram.png" align="left" width="280px"></a> This [blueprint](./onprem-google-access-dns/) uses an emulated on-premises environment running in Docker containers inside a GCE instance, to allow testing specific features like DNS policies, DNS forwarding zones across VPN, and Private Access for On-premises hosts.
<a href="./__need_fixing/onprem-google-access-dns/" title="DNS and Private Access for On-premises"><img src="./onprem-google-access-dns/diagram.png" align="left" width="280px"></a> This [blueprint](./onprem-google-access-dns/) uses an emulated on-premises environment running in Docker containers inside a GCE instance, to allow testing specific features like DNS policies, DNS forwarding zones across VPN, and Private Access for On-premises hosts.
The emulated on-premises environment can be used to test access to different services from outside Google Cloud, by implementing a VPN connection and BGP to Google CLoud via Strongswan and Bird.
<br clear="left">
-->
### Calling a private Cloud Function from on-premises
<a href="./private-cloud-function-from-onprem/" title="Private Cloud Function from On-premises"><img src="./private-cloud-function-from-onprem/diagram.png" align="left" width="280px"></a> This [blueprint](./private-cloud-function-from-onprem/) shows how to invoke a [private Google Cloud Function](https://cloud.google.com/functions/docs/networking/network-settings) from the on-prem environment via a [Private Service Connect endpoint](https://cloud.google.com/vpc/docs/private-service-connect#benefits-apis).

View File

@@ -1,6 +1,6 @@
# On-prem DNS and Google Private Access
This blueprint leverages the [on prem in a box](../../../modules/cloud-config-container/onprem) module to bootstrap an emulated on-premises environment on GCP, then connects it via VPN and sets up BGP and DNS so that several specific features can be tested:
This blueprint leverages the on prem in a box module to bootstrap an emulated on-premises environment on GCP, then connects it via VPN and sets up BGP and DNS so that several specific features can be tested:
- [Cloud DNS forwarding zone](https://cloud.google.com/dns/docs/overview#fz-targets) to on-prem
- DNS forwarding from on-prem via a [Cloud DNS inbound policy](https://cloud.google.com/dns/docs/policies#create-in)
@@ -30,7 +30,7 @@ The Cloud DNS inbound policy reserves an IP address in the VPC, which is used by
### Find out the forwarder entry point address
Run this gcloud command to (find out the address assigned to the inbound forwarder)[https://cloud.google.com/dns/docs/policies#list-in-entrypoints]:
Run this gcloud command to [find out the address assigned to the inbound forwarder](https://cloud.google.com/dns/docs/policies#list-in-entrypoints):
```bash
gcloud compute addresses list --project [your project id]
@@ -199,7 +199,7 @@ curl www.onprem.example.org -s |grep h1
A single pre-existing project is used in this blueprint to keep variables and complexity to a minimum, in a real world scenarios each spoke would probably use a separate project.
The VPN-s used to connect to the on-premises environment do not account for HA, upgrading to use HA VPN is reasonably simple by using the relevant [module](../../../modules/net-vpn-ha).
The VPN-s used to connect to the on-premises environment do not account for HA, upgrading to use HA VPN is reasonably simple by using the relevant [module](../../../../modules/net-vpn-ha).
<!-- BEGIN TFDOC -->
## Variables

View File

Before

Width:  |  Height:  |  Size: 154 KiB

After

Width:  |  Height:  |  Size: 154 KiB

View File

@@ -1,6 +1,6 @@
# Instance Configuration via `cloud-config`
This set of modules creates specialized [cloud-config](https://cloud.google.com/container-optimized-os/docs/how-to/run-container-instance#starting_a_docker_container_via_cloud-config) configurations, which are designed for use with [Container Optimized OS](https://cloud.google.com/container-optimized-os/docs) (the [onprem module](./onprem/) is the only exception) but can also be used as a basis for other image types or cloud providers.
This set of modules creates specialized [cloud-config](https://cloud.google.com/container-optimized-os/docs/how-to/run-container-instance#starting_a_docker_container_via_cloud-config) configurations, which are designed for use with [Container Optimized OS](https://cloud.google.com/container-optimized-os/docs) (the onprem module is the only exception) but can also be used as a basis for other image types or cloud providers.
These modules are designed for several use cases:
@@ -14,8 +14,8 @@ These modules are designed for several use cases:
- [CoreDNS](./coredns)
- [MySQL](./mysql)
- [Nginx](./nginx)
- [On-prem in Docker](./onprem)
- [Squid forward proxy](./squid)
- On-prem in Docker (*needs fixing*)
## Using the modules
@@ -23,8 +23,6 @@ All modules are designed to be as lightweight as possible, so that specialized m
To use the modules with instances or instance templates, simply set use their `cloud_config` output for the `user-data` metadata. When updating the metadata after a variable change remember to manually restart the instances that use a module's output, or the changes won't effect the running system.
For convenience when developing or prototyping infrastructure, an optional test instance is included in all modules. If it's not needed, the linked `*instance.tf` files can be removed from the modules without harm.
## TODO
- [ ] convert all `xxx_config` variables to use file content instead of path

View File

@@ -10,18 +10,14 @@ The emulated on-premises infrastructure is composed of:
- an Nginx container serving a simple static web page
- a [generic Linux container](./docker-images/toolbox) used as a jump host inside the on-premises network
A [complete scenario using this module](../../../blueprints/networking/onprem-google-access-dns) is available in the networking blueprints.
A complete scenario using this module is available in the networking blueprints.
The module renders the generated cloud config in the `cloud_config` output, to be used in instances or instance templates via the `user-data` metadata.
For convenience during development or for simple use cases, the module can optionally manage a single instance via the `test_instance` variable. If the instance is not needed the `instance*tf` files can be safely removed. Refer to the [top-level README](../README.md) for more details on the included instance.
## Examples
### Static VPN
The test instance is optional, as described above.
```hcl
module "cloud-vpn" {
source = "./fabric/modules/net-vpn-static"
@@ -32,29 +28,43 @@ module "cloud-vpn" {
remote_ranges = ["192.168.192.0/24"]
tunnels = {
remote-0 = {
peer_ip = module.on-prem.external_address
peer_ip = module.vm.external_ip
traffic_selectors = { local = ["0.0.0.0/0"], remote = null }
}
}
}
module "on-prem" {
source = "./fabric/modules/cos-container/on-prem"
name = "onprem"
source = "./fabric/modules/cloud-config-container/onprem"
vpn_config = {
type = "static"
peer_ip = module.cloud-vpn.address
shared_secret = module.cloud-vpn.random_secret
}
test_instance = {
project_id = "my-project"
zone = "europe-west1-b"
name = "cos-coredns"
type = "f1-micro"
network = "default"
subnetwork = "https://www.googleapis.com/compute/v1/projects/my-project/regions/europe-west1/subnetworks/my-subnet"
}
}
module "vm" {
source = "./fabric/modules/compute-vm"
project_id = "my-project"
zone = "europe-west8-b"
name = "cos-nginx-tls"
network_interfaces = [{
nat = true
network = "default"
subnetwork = "gce"
}]
metadata = {
user-data = module.on-prem.cloud_config
google-logging-enabled = true
}
boot_disk = {
image = "projects/cos-cloud/global/images/family/cos-stable"
type = "pd-ssd"
size = 10
}
tags = ["ssh"]
}
# tftest skip
```
<!-- BEGIN TFDOC -->
@@ -62,12 +72,10 @@ module "on-prem" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [vpn_config](variables.tf#L35) | VPN configuration, type must be one of 'dynamic' or 'static'. | <code title="object&#40;&#123;&#10; peer_ip &#61; string&#10; shared_secret &#61; string&#10; type &#61; string&#10; peer_ip2 &#61; string&#10; shared_secret2 &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | |
| [vpn_config](variables.tf#L35) | VPN configuration, type must be one of 'dynamic' or 'static'. | <code title="object&#40;&#123;&#10; peer_ip &#61; string&#10; shared_secret &#61; string&#10; type &#61; optional&#40;string, &#34;static&#34;&#41;&#10; peer_ip2 &#61; optional&#40;string&#41;&#10; shared_secret2 &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | |
| [config_variables](variables.tf#L17) | Additional variables used to render the cloud-config and CoreDNS templates. | <code>map&#40;any&#41;</code> | | <code>&#123;&#125;</code> |
| [coredns_config](variables.tf#L23) | CoreDNS configuration path, if null default will be used. | <code>string</code> | | <code>null</code> |
| [local_ip_cidr_range](variables.tf#L29) | IP CIDR range used for the Docker onprem network. | <code>string</code> | | <code>&#34;192.168.192.0&#47;24&#34;</code> |
| [test_instance](variables-instance.tf#L17) | Test/development instance attributes, leave null to skip creation. | <code title="object&#40;&#123;&#10; project_id &#61; string&#10; zone &#61; string&#10; name &#61; string&#10; type &#61; string&#10; network &#61; string&#10; subnetwork &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [test_instance_defaults](variables-instance.tf#L30) | Test/development instance defaults used for optional configuration. If image is null, COS stable will be used. | <code title="object&#40;&#123;&#10; disks &#61; map&#40;object&#40;&#123;&#10; read_only &#61; bool&#10; size &#61; number&#10; &#125;&#41;&#41;&#10; image &#61; string&#10; metadata &#61; map&#40;string&#41;&#10; nat &#61; bool&#10; service_account_roles &#61; list&#40;string&#41;&#10; tags &#61; list&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; disks &#61; &#123;&#125;&#10; image &#61; null&#10; metadata &#61; &#123;&#125;&#10; nat &#61; false&#10; service_account_roles &#61; &#91;&#10; &#34;roles&#47;logging.logWriter&#34;,&#10; &#34;roles&#47;monitoring.metricWriter&#34;&#10; &#93;&#10; tags &#61; &#91;&#34;ssh&#34;&#93;&#10;&#125;">&#123;&#8230;&#125;</code> |
| [vpn_dynamic_config](variables.tf#L46) | BGP configuration for dynamic VPN, ignored if VPN type is 'static'. | <code title="object&#40;&#123;&#10; local_bgp_asn &#61; number&#10; local_bgp_address &#61; string&#10; peer_bgp_asn &#61; number&#10; peer_bgp_address &#61; string&#10; local_bgp_asn2 &#61; number&#10; local_bgp_address2 &#61; string&#10; peer_bgp_asn2 &#61; number&#10; peer_bgp_address2 &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; local_bgp_asn &#61; 64514&#10; local_bgp_address &#61; &#34;169.254.1.2&#34;&#10; peer_bgp_asn &#61; 64513&#10; peer_bgp_address &#61; &#34;169.254.1.1&#34;&#10; local_bgp_asn2 &#61; 64514&#10; local_bgp_address2 &#61; &#34;169.254.2.2&#34;&#10; peer_bgp_asn2 &#61; 64520&#10; peer_bgp_address2 &#61; &#34;169.254.2.1&#34;&#10;&#125;">&#123;&#8230;&#125;</code> |
| [vpn_static_ranges](variables.tf#L70) | Remote CIDR ranges for static VPN, ignored if VPN type is 'dynamic'. | <code>list&#40;string&#41;</code> | | <code>&#91;&#34;10.0.0.0&#47;8&#34;&#93;</code> |
@@ -76,7 +84,5 @@ module "on-prem" {
| name | description | sensitive |
|---|---|:---:|
| [cloud_config](outputs.tf#L17) | Rendered cloud-config file to be passed as user-data instance metadata. | |
| [test_instance](outputs-instance.tf#L17) | Optional test instance name and address. | |
<!-- END TFDOC -->

View File

@@ -37,9 +37,9 @@ variable "vpn_config" {
type = object({
peer_ip = string
shared_secret = string
type = string
peer_ip2 = string
shared_secret2 = string
type = optional(string, "static")
peer_ip2 = optional(string)
shared_secret2 = optional(string)
})
}

View File

@@ -27,14 +27,27 @@ module "cos-coredns" {
source = "./fabric/modules/cloud-config-container/coredns"
}
# use it as metadata in a compute instance or template
module "vm-coredns" {
source = "./fabric/modules/compute-vm"
module "vm" {
source = "./fabric/modules/compute-vm"
project_id = "my-project"
zone = "europe-west8-b"
name = "cos-coredns"
network_interfaces = [{
network = "default"
subnetwork = "gce"
}]
metadata = {
user-data = module.cos-coredns.cloud_config
google-logging-enabled = true
}
boot_disk = {
image = "projects/cos-cloud/global/images/family/cos-stable"
type = "pd-ssd"
size = 10
}
tags = ["dns", "ssh"]
}
# tftest modules=1 resources=1
```
### Custom CoreDNS configuration
@@ -51,25 +64,9 @@ module "cos-coredns" {
owner = null
permissions = "0644"
}
}
}
```
### CoreDNS instance
This example shows how to create the single instance optionally managed by the module, providing all required attributes in the `test_instance` variable. The instance is purposefully kept simple and should only be used in development, or when designing infrastructures.
```hcl
module "cos-coredns" {
source = "./fabric/modules/cloud-config-container/coredns"
test_instance = {
project_id = "my-project"
zone = "europe-west1-b"
name = "cos-coredns"
type = "f1-micro"
network = "default"
subnetwork = "https://www.googleapis.com/compute/v1/projects/my-project/regions/europe-west1/subnetworks/my-subnet"
}
}
# tftest modules=0 resources=0
```
<!-- BEGIN TFDOC -->
@@ -82,14 +79,11 @@ module "cos-coredns" {
| [coredns_config](variables.tf#L29) | CoreDNS configuration path, if null default will be used. | <code>string</code> | | <code>null</code> |
| [file_defaults](variables.tf#L35) | Default owner and permissions for files. | <code title="object&#40;&#123;&#10; owner &#61; string&#10; permissions &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; owner &#61; &#34;root&#34;&#10; permissions &#61; &#34;0644&#34;&#10;&#125;">&#123;&#8230;&#125;</code> |
| [files](variables.tf#L47) | Map of extra files to create on the instance, path as key. Owner and permissions will use defaults if null. | <code title="map&#40;object&#40;&#123;&#10; content &#61; string&#10; owner &#61; string&#10; permissions &#61; string&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [test_instance](variables-instance.tf#L17) | Test/development instance attributes, leave null to skip creation. | <code title="object&#40;&#123;&#10; project_id &#61; string&#10; zone &#61; string&#10; name &#61; string&#10; type &#61; string&#10; network &#61; string&#10; subnetwork &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [test_instance_defaults](variables-instance.tf#L30) | Test/development instance defaults used for optional configuration. If image is null, COS stable will be used. | <code title="object&#40;&#123;&#10; disks &#61; map&#40;object&#40;&#123;&#10; read_only &#61; bool&#10; size &#61; number&#10; &#125;&#41;&#41;&#10; image &#61; string&#10; metadata &#61; map&#40;string&#41;&#10; nat &#61; bool&#10; service_account_roles &#61; list&#40;string&#41;&#10; tags &#61; list&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; disks &#61; &#123;&#125;&#10; image &#61; null&#10; metadata &#61; &#123;&#125;&#10; nat &#61; false&#10; service_account_roles &#61; &#91;&#10; &#34;roles&#47;logging.logWriter&#34;,&#10; &#34;roles&#47;monitoring.metricWriter&#34;&#10; &#93;&#10; tags &#61; &#91;&#34;ssh&#34;&#93;&#10;&#125;">&#123;&#8230;&#125;</code> |
## Outputs
| name | description | sensitive |
|---|---|:---:|
| [cloud_config](outputs.tf#L17) | Rendered cloud-config file to be passed as user-data instance metadata. | |
| [test_instance](outputs-instance.tf#L17) | Optional test instance name and address. | |
<!-- END TFDOC -->

View File

@@ -1 +0,0 @@
../instance.tf

View File

@@ -1 +0,0 @@
../outputs-instance.tf

View File

@@ -1 +0,0 @@
../variables-instance.tf

View File

@@ -12,31 +12,27 @@ This example will create a `cloud-config` that starts [Envoy Proxy](https://www.
```hcl
module "cos-envoy" {
source = "./fabric/modules/cos-generic-metadata"
source = "./fabric/modules/cloud-config-container/cos-generic-metadata"
container_image = "envoyproxy/envoy:v1.14.1"
container_name = "envoy"
container_args = "-c /etc/envoy/envoy.yaml --log-level info --allow-unknown-static-fields"
container_volumes = [
{ host = "/etc/envoy/envoy.yaml", container = "/etc/envoy/envoy.yaml" }
]
docker_args = "--network host --pid host"
# file paths are mocked to run this example in tests
files = {
"/var/run/envoy/customize.sh" = {
content = file("customize.sh")
content = file("/dev/null") # file("customize.sh")
owner = "root"
permissions = "0744"
}
"/etc/envoy/envoy.yaml" = {
content = file("envoy.yaml")
content = file("/dev/null") # file("envoy.yaml")
owner = "root"
permissions = "0644"
}
}
run_commands = [
"iptables -t nat -N ENVOY_IN_REDIRECT",
"iptables -t nat -A ENVOY_IN_REDIRECT -p tcp -j REDIRECT --to-port 15001",
@@ -46,14 +42,13 @@ module "cos-envoy" {
"systemctl daemon-reload",
"systemctl start envoy",
]
users = [
{
username = "envoy",
uid = 1337
}
]
users = [{
username = "envoy",
uid = 1337
}]
}
# tftest modules=0 resources=0
```
<!-- BEGIN TFDOC -->

View File

@@ -11,38 +11,31 @@ This module depends on the [`cos-generic-metadata` module](../cos-generic-metada
### Default configuration
```hcl
# Envoy TD config
module "cos-envoy-td" {
source = "./fabric/modules/cloud-config-container/envoy-traffic-director"
}
# COS VM
module "vm-cos" {
module "vm" {
source = "./fabric/modules/compute-vm"
project_id = local.project_id
zone = local.zone
project_id = "my-project"
zone = "europe-west8-b"
name = "cos-envoy-td"
network_interfaces = [{
network = local.vpc.self_link,
subnetwork = local.vpc.subnet_self_link,
nat = false,
addresses = null
network = "default"
subnetwork = "gce"
}]
tags = ["ssh", "http"]
metadata = {
user-data = module.cos-envoy-td.cloud_config
google-logging-enabled = true
}
boot_disk = {
image = "projects/cos-cloud/global/images/family/cos-stable"
type = "pd-ssd"
size = 10
}
service_account_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
tags = ["http-server", "ssh"]
}
# tftest modules=1 resources=1
```
<!-- BEGIN TFDOC -->

View File

@@ -1,101 +0,0 @@
/**
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
resource "google_service_account" "default" {
count = var.test_instance == null ? 0 : 1
project = var.test_instance.project_id
account_id = "fabric-container-${var.test_instance.name}"
display_name = "Managed by the cos Terraform module."
}
resource "google_project_iam_member" "default" {
for_each = (
var.test_instance == null
? toset([])
: toset(var.test_instance_defaults.service_account_roles)
)
project = var.test_instance.project_id
role = each.value
member = "serviceAccount:${google_service_account.default[0].email}"
}
resource "google_compute_disk" "disks" {
for_each = (
var.test_instance == null
? {}
: var.test_instance_defaults.disks
)
project = var.test_instance.project_id
zone = var.test_instance.zone
name = each.key
type = "pd-ssd"
size = each.value.size
}
resource "google_compute_instance" "default" {
count = var.test_instance == null ? 0 : 1
project = var.test_instance.project_id
zone = var.test_instance.zone
name = var.test_instance.name
description = "Managed by the cos Terraform module."
tags = var.test_instance_defaults.tags
machine_type = (
var.test_instance.type == null ? "f1-micro" : var.test_instance.type
)
metadata = merge(var.test_instance_defaults.metadata, {
user-data = local.cloud_config
})
dynamic "attached_disk" {
for_each = var.test_instance_defaults.disks
iterator = disk
content {
device_name = disk.key
mode = disk.value.read_only ? "READ_ONLY" : "READ_WRITE"
source = google_compute_disk.disks[disk.key].name
}
}
boot_disk {
initialize_params {
type = "pd-ssd"
image = (
var.test_instance_defaults.image == null
? "projects/cos-cloud/global/images/family/cos-stable"
: var.test_instance_defaults.image
)
size = 10
}
}
network_interface {
network = var.test_instance.network
subnetwork = var.test_instance.subnetwork
dynamic "access_config" {
for_each = var.test_instance_defaults.nat ? [""] : []
iterator = config
content {
nat_ip = null
}
}
}
service_account {
email = google_service_account.default[0].email
scopes = ["https://www.googleapis.com/auth/cloud-platform"]
}
}

View File

@@ -26,18 +26,31 @@ This example will create a `cloud-config` that uses the container's default conf
```hcl
module "cos-mysql" {
source = "./fabric/modules/cos-container/mysql"
source = "./fabric/modules/cloud-config-container/mysql"
mysql_password = "foo"
}
# use it as metadata in a compute instance or template
module "vm-mysql" {
source = "./fabric/modules/compute-vm"
module "vm" {
source = "./fabric/modules/compute-vm"
project_id = "my-project"
zone = "europe-west8-b"
name = "cos-mysql"
network_interfaces = [{
network = "default"
subnetwork = "gce"
}]
metadata = {
user-data = module.cos-mysql.cloud_config
google-logging-enabled = true
}
boot_disk = {
image = "projects/cos-cloud/global/images/family/cos-stable"
type = "pd-ssd"
size = 10
}
tags = ["mysql", "ssh"]
}
# tftest modules=1 resources=1
```
### Custom MySQL configuration and KMS encrypted password
@@ -46,7 +59,7 @@ This example will create a `cloud-config` that uses a custom MySQL configuration
```hcl
module "cos-mysql" {
source = "./fabric/modules/cos-container/mysql"
source = "./fabric/modules/cloud-config-container/mysql"
mysql_config = "./my.cnf"
mysql_password = "CiQAsd7WY=="
kms_config = {
@@ -56,25 +69,7 @@ module "cos-mysql" {
key = "mysql"
}
}
```
### MySQL instance
This example shows how to create the single instance optionally managed by the module, providing all required attributes in the `test_instance` variable. The instance is purposefully kept simple and should only be used in development, or when designing infrastructures.
```hcl
module "cos-mysql" {
source = "./fabric/modules/cos-container/mysql"
mysql_password = "foo"
test_instance = {
project_id = "my-project"
zone = "europe-west1-b"
name = "cos-mysql"
type = "n1-standard-1"
network = "default"
subnetwork = "https://www.googleapis.com/compute/v1/projects/my-project/regions/europe-west1/subnetworks/my-subnet"
}
}
# tftest modules=0 resources=0
```
<!-- BEGIN TFDOC -->
@@ -89,14 +84,11 @@ module "cos-mysql" {
| [kms_config](variables.tf#L35) | Optional KMS configuration to decrypt passed-in password. Leave null if a plaintext password is used. | <code title="object&#40;&#123;&#10; project_id &#61; string&#10; keyring &#61; string&#10; location &#61; string&#10; key &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [mysql_config](variables.tf#L46) | MySQL configuration file content, if null container default will be used. | <code>string</code> | | <code>null</code> |
| [mysql_data_disk](variables.tf#L52) | MySQL data disk name in /dev/disk/by-id/ including the google- prefix. If null the boot disk will be used for data. | <code>string</code> | | <code>null</code> |
| [test_instance](variables-instance.tf#L17) | Test/development instance attributes, leave null to skip creation. | <code title="object&#40;&#123;&#10; project_id &#61; string&#10; zone &#61; string&#10; name &#61; string&#10; type &#61; string&#10; network &#61; string&#10; subnetwork &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [test_instance_defaults](variables-instance.tf#L30) | Test/development instance defaults used for optional configuration. If image is null, COS stable will be used. | <code title="object&#40;&#123;&#10; disks &#61; map&#40;object&#40;&#123;&#10; read_only &#61; bool&#10; size &#61; number&#10; &#125;&#41;&#41;&#10; image &#61; string&#10; metadata &#61; map&#40;string&#41;&#10; nat &#61; bool&#10; service_account_roles &#61; list&#40;string&#41;&#10; tags &#61; list&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; disks &#61; &#123;&#125;&#10; image &#61; null&#10; metadata &#61; &#123;&#125;&#10; nat &#61; false&#10; service_account_roles &#61; &#91;&#10; &#34;roles&#47;logging.logWriter&#34;,&#10; &#34;roles&#47;monitoring.metricWriter&#34;&#10; &#93;&#10; tags &#61; &#91;&#34;ssh&#34;&#93;&#10;&#125;">&#123;&#8230;&#125;</code> |
## Outputs
| name | description | sensitive |
|---|---|:---:|
| [cloud_config](outputs.tf#L17) | Rendered cloud-config file to be passed as user-data instance metadata. | |
| [test_instance](outputs-instance.tf#L17) | Optional test instance name and address. | |
<!-- END TFDOC -->

View File

@@ -1 +0,0 @@
../instance.tf

View File

@@ -1 +0,0 @@
../outputs-instance.tf

View File

@@ -1 +0,0 @@
../variables-instance.tf

View File

@@ -1,48 +1,37 @@
# Containerized Nginx with self-signed TLS on Container Optimized OS
This module manages a `cloud-config` configuration that starts a containerized Nginx with a self-signed TLS cert on Container Optimized OS.
This can be useful if you need quickly a VM or instance group answering HTTPS for prototyping.
This module manages a `cloud-config` configuration that starts a containerized Nginx with a self-signed TLS cert on Container Optimized OS. This can be useful if you need quickly a VM or instance group answering HTTPS for prototyping.
The generated cloud config is rendered in the `cloud_config` output, and is meant to be used in instances or instance templates via the `user-data` metadata.
This module depends on the [`cos-generic-metadata` module](../cos-generic-metadata) being in the parent folder. If you change its location be sure to adjust the `source` attribute in `main.tf`.
## Examples
### Default configuration
## Example
```hcl
# Nginx with self-signed TLS config
module "cos-nginx-tls" {
source = "./fabric/modules/cloud-config-container/nginx-tls"
}
# COS VM
module "vm-nginx-tls" {
source = "./fabric/modules/compute-vm"
project_id = local.project_id
zone = local.zone
project_id = "my-project"
zone = "europe-west8-b"
name = "cos-nginx-tls"
network_interfaces = [{
network = local.vpc.self_link,
subnetwork = local.vpc.subnet_self_link,
nat = false,
addresses = null
network = "default"
subnetwork = "gce"
}]
metadata = {
user-data = module.cos-nginx-tls.cloud_config
google-logging-enabled = true
}
boot_disk = {
image = "projects/cos-cloud/global/images/family/cos-stable"
type = "pd-ssd"
size = 10
}
service_account_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
tags = ["http-server", "https-server", "ssh"]
}
# tftest modules=1 resources=1
```
<!-- BEGIN TFDOC -->
@@ -50,11 +39,9 @@ module "vm-nginx-tls" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [files](variables.tf#L17) | Map of extra files to create on the instance, path as key. Owner and permissions will use defaults if null. | <code title="map&#40;object&#40;&#123;&#10; content &#61; string&#10; owner &#61; string&#10; permissions &#61; string&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>null</code> |
| [nginx_image](variables.tf#L27) | Nginx container image to use. | <code>string</code> | | <code>&#34;nginx:1.23.1&#34;</code> |
| [runcmd_post](variables.tf#L33) | Extra commands to run after starting nginx. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [runcmd_pre](variables.tf#L39) | Extra commands to run before starting nginx. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [users](variables.tf#L45) | Additional list of usernames to be created. | <code title="list&#40;object&#40;&#123;&#10; username &#61; string,&#10; uid &#61; number,&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code title="&#91;&#10;&#93;">&#91;&#8230;&#93;</code> |
| [files](variables.tf#L17) | Map of extra files to create on the instance, path as key. Owner and permissions will use defaults if null. | <code title="map&#40;object&#40;&#123;&#10; content &#61; string&#10; owner &#61; optional&#40;string, &#34;root&#34;&#41;&#10; permissions &#61; optional&#40;string, &#34;0644&#34;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [hello](variables.tf#L28) | Behave like the nginx hello image by returning plain text informative responses. | <code>bool</code> | | <code>true</code> |
| [image](variables.tf#L35) | Nginx container image to use. | <code>string</code> | | <code>&#34;nginx:1.23.1&#34;</code> |
## Outputs

View File

@@ -0,0 +1,63 @@
#cloud-config
# Copyright 2022 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.
users:
- name: nginx
uid: 2000
write_files:
- path: /var/lib/docker/daemon.json
permissions: "0644"
owner: root
content: |
{
"live-restore": true,
"storage-driver": "overlay2",
"log-opts": {
"max-size": "1024m"
}
}
# nginx container service
- path: /etc/systemd/system/nginx.service
permissions: "0644"
owner: root
content: |
[Unit]
Description=Start nginx container
After=gcr-online.target docker.socket
Wants=gcr-online.target docker.socket docker-events-collector.service
[Service]
Environment="HOME=/home/nginx"
ExecStart=/usr/bin/docker run --rm --name=nginx \
--network host --pid host \
-v /etc/nginx/conf.d:/etc/nginx/conf.d \
-v /etc/ssl:/etc/ssl \
${image}
ExecStop=/usr/bin/docker stop nginx
%{ for k, v in files ~}
- path: ${k}
owner: ${v.owner}
permissions: "${v.permissions}"
content: |
${indent(6, v.content)}
%{ endfor ~}
runcmd:
- iptables -I INPUT 1 -p tcp -m tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
- iptables -I INPUT 1 -p tcp -m tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT
- /var/run/nginx/customize.sh
- systemctl daemon-reload
- systemctl start nginx

View File

@@ -13,8 +13,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
FQDN=$(curl -s -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/hostname)
FQDN=$(\
curl -s -H "Metadata-Flavor: Google" \
http://metadata/computeMetadata/v1/instance/hostname)
HOSTNAME=$(echo $FQDN | cut -d"." -f1)
openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 -subj /CN=$HOSTNAME/ -addext "subjectAltName = DNS:$FQDN" -keyout /etc/ssl/self-signed.key -out /etc/ssl/self-signed.crt
openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 \
-subj /CN=$HOSTNAME/ -addext "subjectAltName = DNS:$FQDN" \
-keyout /etc/ssl/self-signed.key -out /etc/ssl/self-signed.crt
chgrp nginx /etc/ssl/self-signed.key -out /etc/ssl/self-signed.crt
sed -i "s/HOSTNAME/${HOSTNAME}/" /etc/nginx/conf.d/default.conf

View File

@@ -0,0 +1,24 @@
server {
listen 80;
listen 443 ssl;
server_name HOSTNAME;
ssl_certificate /etc/ssl/self-signed.crt;
ssl_certificate_key /etc/ssl/self-signed.key;
location / {
{% if hello %}
default_type text/plain;
expires -1;
return 200 'Server address: $server_addr:$server_port\nServer name: $hostname\nDate: $time_local\nURI: $request_uri\nRequest ID: $request_id\n';
{% else %}
root /usr/share/nginx/html;
index index.html index.htm;
{% endif %}
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}

View File

@@ -1,20 +0,0 @@
server {
listen 80;
listen 443 ssl;
server_name HOSTNAME;
ssl_certificate /etc/ssl/self-signed.crt;
ssl_certificate_key /etc/ssl/self-signed.key;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}

View File

@@ -1,70 +0,0 @@
/**
* Copyright 2022 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 {
default_files = {
"/var/run/nginx/customize.sh" = {
content = file("${path.module}/files/customize.sh")
owner = "root"
permissions = "0744"
}
"/etc/nginx/conf.d/default.conf" = {
content = file("${path.module}/files/default.conf")
owner = "root"
permissions = "0644"
}
}
files = var.files != null ? merge(local.default_files, var.files) : local.default_files
}
module "cos-envoy-td" {
source = "../cos-generic-metadata"
authenticate_gcr = true
users = concat([
{
username = "nginx"
uid = 2000
}
], var.users)
run_as_first_user = false
boot_commands = [
"systemctl start node-problem-detector",
]
container_image = var.nginx_image
container_name = "nginx"
container_args = ""
container_volumes = [
{ host = "/etc/nginx/conf.d", container = "/etc/nginx/conf.d" },
{ host = "/etc/ssl", container = "/etc/ssl" },
]
docker_args = "--network host --pid host"
files = local.files
run_commands = concat(var.runcmd_pre, [
"iptables -I INPUT 1 -p tcp -m tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT",
"iptables -I INPUT 1 -p tcp -m tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT",
"/var/run/nginx/customize.sh",
"systemctl daemon-reload",
"systemctl start nginx",
], var.runcmd_post)
}

View File

@@ -16,5 +16,23 @@
output "cloud_config" {
description = "Rendered cloud-config file to be passed as user-data instance metadata."
value = module.cos-envoy-td.cloud_config
value = templatefile("${path.module}/assets/cloud-config.yaml", {
files = merge(
{
"/var/run/nginx/customize.sh" = {
content = file("${path.module}/assets/customize.sh")
owner = "root"
permissions = "0744"
}
"/etc/nginx/conf.d/default.conf" = {
content = templatefile(
"${path.module}/assets/default.conf", { hello = var.hello }
)
owner = "root"
permissions = "0644"
}
}, var.files
)
image = var.image
})
}

View File

@@ -18,38 +18,22 @@ variable "files" {
description = "Map of extra files to create on the instance, path as key. Owner and permissions will use defaults if null."
type = map(object({
content = string
owner = string
permissions = string
owner = optional(string, "root")
permissions = optional(string, "0644")
}))
default = null
default = {}
nullable = false
}
variable "nginx_image" {
variable "hello" {
description = "Behave like the nginx hello image by returning plain text informative responses."
type = bool
default = true
nullable = false
}
variable "image" {
description = "Nginx container image to use."
type = string
default = "nginx:1.23.1"
}
variable "runcmd_post" {
description = "Extra commands to run after starting nginx."
type = list(string)
default = []
}
variable "runcmd_pre" {
description = "Extra commands to run before starting nginx."
type = list(string)
default = []
}
variable "users" {
description = "Additional list of usernames to be created."
type = list(object({
username = string,
uid = number,
}))
default = [
]
}

View File

@@ -27,32 +27,27 @@ module "cos-nginx" {
source = "./fabric/modules/cloud-config-container/nginx"
}
# use it as metadata in a compute instance or template
module "vm-nginx" {
source = "./fabric/modules/compute-vm"
module "vm-nginx-tls" {
source = "./fabric/modules/compute-vm"
project_id = "my-project"
zone = "europe-west8-b"
name = "cos-nginx"
network_interfaces = [{
network = "default"
subnetwork = "gce"
}]
metadata = {
user-data = module.cos-nginx.cloud_config
google-logging-enabled = true
}
}
```
### Nginx instance
This example shows how to create the single instance optionally managed by the module, providing all required attributes in the `test_instance` variable. The instance is purposefully kept simple and should only be used in development, or when designing infrastructures.
```hcl
module "cos-nginx" {
source = "./fabric/modules/cloud-config-container/nginx"
test_instance = {
project_id = "my-project"
zone = "europe-west1-b"
name = "cos-nginx"
type = "f1-micro"
network = "default"
subnetwork = "https://www.googleapis.com/compute/v1/projects/my-project/regions/europe-west1/subnetworks/my-subnet"
boot_disk = {
image = "projects/cos-cloud/global/images/family/cos-stable"
type = "pd-ssd"
size = 10
}
tags = ["http-server", "ssh"]
}
# tftest modules=1 resources=1
```
<!-- BEGIN TFDOC -->
@@ -68,8 +63,6 @@ module "cos-nginx" {
| [nginx_config](variables.tf#L57) | Nginx configuration path, if null container default will be used. | <code>string</code> | | <code>null</code> |
| [runcmd_post](variables.tf#L63) | Extra commands to run after starting nginx. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [runcmd_pre](variables.tf#L69) | Extra commands to run before starting nginx. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [test_instance](variables-instance.tf#L17) | Test/development instance attributes, leave null to skip creation. | <code title="object&#40;&#123;&#10; project_id &#61; string&#10; zone &#61; string&#10; name &#61; string&#10; type &#61; string&#10; network &#61; string&#10; subnetwork &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [test_instance_defaults](variables-instance.tf#L30) | Test/development instance defaults used for optional configuration. If image is null, COS stable will be used. | <code title="object&#40;&#123;&#10; disks &#61; map&#40;object&#40;&#123;&#10; read_only &#61; bool&#10; size &#61; number&#10; &#125;&#41;&#41;&#10; image &#61; string&#10; metadata &#61; map&#40;string&#41;&#10; nat &#61; bool&#10; service_account_roles &#61; list&#40;string&#41;&#10; tags &#61; list&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; disks &#61; &#123;&#125;&#10; image &#61; null&#10; metadata &#61; &#123;&#125;&#10; nat &#61; false&#10; service_account_roles &#61; &#91;&#10; &#34;roles&#47;logging.logWriter&#34;,&#10; &#34;roles&#47;monitoring.metricWriter&#34;&#10; &#93;&#10; tags &#61; &#91;&#34;ssh&#34;&#93;&#10;&#125;">&#123;&#8230;&#125;</code> |
| [users](variables.tf#L75) | List of additional usernames to be created. | <code title="list&#40;object&#40;&#123;&#10; username &#61; string,&#10; uid &#61; number,&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code title="&#91;&#10;&#93;">&#91;&#8230;&#93;</code> |
## Outputs
@@ -77,6 +70,5 @@ module "cos-nginx" {
| name | description | sensitive |
|---|---|:---:|
| [cloud_config](outputs.tf#L17) | Rendered cloud-config file to be passed as user-data instance metadata. | |
| [test_instance](outputs-instance.tf#L17) | Optional test instance name and address. | |
<!-- END TFDOC -->

View File

@@ -1 +0,0 @@
../instance.tf

View File

@@ -1 +0,0 @@
../outputs-instance.tf

View File

@@ -1 +0,0 @@
../variables-instance.tf

View File

@@ -1 +0,0 @@
../instance.tf

View File

@@ -1 +0,0 @@
../outputs-instance.tf

View File

@@ -1 +0,0 @@
../variables-instance.tf

View File

@@ -1,28 +0,0 @@
/**
* Copyright 2022 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 "test_instance" {
description = "Optional test instance name and address."
value = (var.test_instance == null ? {} : {
address = google_compute_instance.default[0].network_interface.0.network_ip
name = google_compute_instance.default[0].name
nat_address = try(
google_compute_instance.default[0].network_interface.0.access_config.0.nat_ip,
null
)
service_account = google_service_account.default[0].email
})
}

View File

@@ -9,7 +9,6 @@ This NVA can be used to interconnect up to 8 VPCs.
### Simple example
```hcl
# Interfaces configuration
locals {
network_interfaces = [
{
@@ -28,41 +27,40 @@ locals {
routes = ["10.0.0.0/9"]
subnetwork = "prod_vpc_nva_subnet_self_link"
}
]
}
# NVA config
module "nva-cloud-config" {
source = "../../../cloud-foundation-fabric/modules/cloud-config-container/simple-nva"
module "cos-nva" {
source = "./fabric/modules/cloud-config-container/simple-nva"
enable_health_checks = true
network_interfaces = local.network_interfaces
files = {
"/var/lib/cloud/scripts/per-boot/firewall-rules.sh" = {
content = file("./your_path/to/firewall-rules.sh")
owner = "root"
permissions = 0700
}
}
# files = {
# "/var/lib/cloud/scripts/per-boot/firewall-rules.sh" = {
# content = file("./your_path/to/firewall-rules.sh")
# owner = "root"
# permissions = 0700
# }
# }
}
# COS VM
module "nva" {
source = "../../modules/compute-vm"
project_id = "myproject"
instance_type = "e2-standard-2"
name = "nva"
can_ip_forward = true
zone = "europe-west8-a"
tags = ["nva"]
module "vm" {
source = "./fabric/modules/compute-vm"
project_id = "my-project"
zone = "europe-west8-b"
name = "cos-nva"
network_interfaces = local.network_interfaces
metadata = {
user-data = module.cos-nva.cloud_config
google-logging-enabled = true
}
boot_disk = {
image = "projects/cos-cloud/global/images/family/cos-stable"
type = "pd-ssd"
size = 10
type = "pd-balanced"
}
metadata = {
user-data = module.nva-cloud-config.cloud_config
}
tags = ["nva", "ssh"]
}
# tftest modules=1 resources=1
```
<!-- BEGIN TFDOC -->
@@ -74,14 +72,11 @@ module "nva" {
| [cloud_config](variables.tf#L17) | Cloud config template path. If null default will be used. | <code>string</code> | | <code>null</code> |
| [enable_health_checks](variables.tf#L23) | Configures routing to enable responses to health check probes. | <code>bool</code> | | <code>false</code> |
| [files](variables.tf#L29) | Map of extra files to create on the instance, path as key. Owner and permissions will use defaults if null. | <code title="map&#40;object&#40;&#123;&#10; content &#61; string&#10; owner &#61; string&#10; permissions &#61; string&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [test_instance](variables-instance.tf#L17) | Test/development instance attributes, leave null to skip creation. | <code title="object&#40;&#123;&#10; project_id &#61; string&#10; zone &#61; string&#10; name &#61; string&#10; type &#61; string&#10; network &#61; string&#10; subnetwork &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [test_instance_defaults](variables-instance.tf#L30) | Test/development instance defaults used for optional configuration. If image is null, COS stable will be used. | <code title="object&#40;&#123;&#10; disks &#61; map&#40;object&#40;&#123;&#10; read_only &#61; bool&#10; size &#61; number&#10; &#125;&#41;&#41;&#10; image &#61; string&#10; metadata &#61; map&#40;string&#41;&#10; nat &#61; bool&#10; service_account_roles &#61; list&#40;string&#41;&#10; tags &#61; list&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; disks &#61; &#123;&#125;&#10; image &#61; null&#10; metadata &#61; &#123;&#125;&#10; nat &#61; false&#10; service_account_roles &#61; &#91;&#10; &#34;roles&#47;logging.logWriter&#34;,&#10; &#34;roles&#47;monitoring.metricWriter&#34;&#10; &#93;&#10; tags &#61; &#91;&#34;ssh&#34;&#93;&#10;&#125;">&#123;&#8230;&#125;</code> |
## Outputs
| name | description | sensitive |
|---|---|:---:|
| [cloud_config](outputs.tf#L17) | Rendered cloud-config file to be passed as user-data instance metadata. | |
| [test_instance](outputs-instance.tf#L17) | Optional test instance name and address. | |
<!-- END TFDOC -->

View File

@@ -1 +0,0 @@
../instance.tf

View File

@@ -1 +0,0 @@
../outputs-instance.tf

View File

@@ -1 +0,0 @@
../variables-instance.tf

View File

@@ -25,38 +25,31 @@ This example will create a `cloud-config` that allows any client in the 10.0.0.0
```hcl
module "cos-squid" {
source = "./fabric/modules/cloud-config-container/squid"
whitelist = [".github.com"]
allow = [".github.com"]
clients = ["10.0.0.0/8"]
}
# use it as metadata in a compute instance or template
module "vm-squid" {
source = "./fabric/modules/compute-vm"
module "vm" {
source = "./fabric/modules/compute-vm"
project_id = "my-project"
zone = "europe-west8-b"
name = "cos-squid"
network_interfaces = [{
network = "default"
subnetwork = "gce"
}]
metadata = {
user-data = module.cos-squid.cloud_config
google-logging-enabled = true
}
}
```
### Test Squid instance
This example shows how to create the single instance optionally managed by the module, providing all required attributes in the `test_instance` variable. The instance is purposefully kept simple and should only be used in development, or when designing infrastructures.
```hcl
module "cos-squid" {
source = "./fabric/modules/cloud-config-container/squid"
whitelist = ["github.com"]
clients = ["10.0.0.0/8"]
test_instance = {
project_id = "my-project"
zone = "europe-west1-b"
name = "cos-squid"
type = "f1-micro"
network = "default"
subnetwork = "https://www.googleapis.com/compute/v1/projects/my-project/regions/europe-west1/subnetworks/my-subnet"
boot_disk = {
image = "projects/cos-cloud/global/images/family/cos-stable"
type = "pd-ssd"
size = 10
}
tags = ["http-server", "ssh"]
}
# tftest modules=1 resources=1
```
<!-- BEGIN TFDOC -->
@@ -73,14 +66,11 @@ module "cos-squid" {
| [file_defaults](variables.tf#L58) | Default owner and permissions for files. | <code title="object&#40;&#123;&#10; owner &#61; string&#10; permissions &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; owner &#61; &#34;root&#34;&#10; permissions &#61; &#34;0644&#34;&#10;&#125;">&#123;&#8230;&#125;</code> |
| [files](variables.tf#L70) | Map of extra files to create on the instance, path as key. Owner and permissions will use defaults if null. | <code title="map&#40;object&#40;&#123;&#10; content &#61; string&#10; owner &#61; string&#10; permissions &#61; string&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [squid_config](variables.tf#L80) | Squid configuration path, if null default will be used. | <code>string</code> | | <code>null</code> |
| [test_instance](variables-instance.tf#L17) | Test/development instance attributes, leave null to skip creation. | <code title="object&#40;&#123;&#10; project_id &#61; string&#10; zone &#61; string&#10; name &#61; string&#10; type &#61; string&#10; network &#61; string&#10; subnetwork &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [test_instance_defaults](variables-instance.tf#L30) | Test/development instance defaults used for optional configuration. If image is null, COS stable will be used. | <code title="object&#40;&#123;&#10; disks &#61; map&#40;object&#40;&#123;&#10; read_only &#61; bool&#10; size &#61; number&#10; &#125;&#41;&#41;&#10; image &#61; string&#10; metadata &#61; map&#40;string&#41;&#10; nat &#61; bool&#10; service_account_roles &#61; list&#40;string&#41;&#10; tags &#61; list&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; disks &#61; &#123;&#125;&#10; image &#61; null&#10; metadata &#61; &#123;&#125;&#10; nat &#61; false&#10; service_account_roles &#61; &#91;&#10; &#34;roles&#47;logging.logWriter&#34;,&#10; &#34;roles&#47;monitoring.metricWriter&#34;&#10; &#93;&#10; tags &#61; &#91;&#34;ssh&#34;&#93;&#10;&#125;">&#123;&#8230;&#125;</code> |
## Outputs
| name | description | sensitive |
|---|---|:---:|
| [cloud_config](outputs.tf#L17) | Rendered cloud-config file to be passed as user-data instance metadata. | |
| [test_instance](outputs-instance.tf#L17) | Optional test instance name and address. | |
<!-- END TFDOC -->

View File

@@ -1 +0,0 @@
../instance.tf

View File

@@ -1 +0,0 @@
../outputs-instance.tf

View File

@@ -1 +0,0 @@
../variables-instance.tf

View File

@@ -1,54 +0,0 @@
/**
* Copyright 2022 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 "test_instance" {
description = "Test/development instance attributes, leave null to skip creation."
type = object({
project_id = string
zone = string
name = string
type = string
network = string
subnetwork = string
})
default = null
}
variable "test_instance_defaults" {
description = "Test/development instance defaults used for optional configuration. If image is null, COS stable will be used."
type = object({
disks = map(object({
read_only = bool
size = number
}))
image = string
metadata = map(string)
nat = bool
service_account_roles = list(string)
tags = list(string)
})
default = {
disks = {}
image = null
metadata = {}
nat = false
service_account_roles = [
"roles/logging.logWriter",
"roles/monitoring.metricWriter"
]
tags = ["ssh"]
}
}

View File

@@ -23,6 +23,9 @@ locals {
},
{
for k, v in google_compute_network_endpoint_group.default : k => v.id
},
{
for k, v in google_compute_region_network_endpoint_group.default : k => v.id
}
)
hc_ids = {

View File

@@ -16,4 +16,4 @@ def test_resources(e2e_plan_runner):
"Test that plan works and the numbers of resources is as expected."
modules, resources = e2e_plan_runner()
assert len(modules) == 10
assert len(resources) == 34
assert len(resources) == 31

View File

@@ -20,8 +20,9 @@ import marko
import pytest
FABRIC_ROOT = Path(__file__).parents[2]
MODULES_PATH = FABRIC_ROOT / 'modules/'
BLUEPRINTS_PATH = FABRIC_ROOT / 'blueprints/'
MODULES_PATH = FABRIC_ROOT / 'modules/'
SUBMODULES_PATH = MODULES_PATH / 'cloud-config-container'
FILE_TEST_RE = re.compile(r'# tftest file (\w+) ([\S]+)')
@@ -32,6 +33,7 @@ File = collections.namedtuple('File', 'path content')
def pytest_generate_tests(metafunc):
if 'example' in metafunc.fixturenames:
modules = [x for x in MODULES_PATH.iterdir() if x.is_dir()]
modules.extend(x for x in SUBMODULES_PATH.iterdir() if x.is_dir())
modules.extend(x for x in BLUEPRINTS_PATH.glob("*/*") if x.is_dir())
modules.sort()
examples = []
@@ -46,7 +48,7 @@ def pytest_generate_tests(metafunc):
last_header = None
files = {}
#first pass: collect all tftest tagged files
# first pass: collect all tftest tagged files
for child in doc.children:
if isinstance(child, marko.block.FencedCode):
code = child.children[0].children