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:
committed by
GitHub
parent
a119ce2d88
commit
d2015b0bc3
@@ -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)
|
||||
|
||||
|
||||
@@ -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"]
|
||||
}
|
||||
|
||||
@@ -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).
|
||||
|
||||
|
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 105 KiB |
@@ -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
|
||||
|
Before Width: | Height: | Size: 154 KiB After Width: | Height: | Size: 154 KiB |
@@ -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
|
||||
|
||||
@@ -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({ peer_ip = string shared_secret = string type = string peer_ip2 = string shared_secret2 = string })">object({…})</code> | ✓ | |
|
||||
| [vpn_config](variables.tf#L35) | VPN configuration, type must be one of 'dynamic' or 'static'. | <code title="object({ peer_ip = string shared_secret = string type = optional(string, "static") peer_ip2 = optional(string) shared_secret2 = optional(string) })">object({…})</code> | ✓ | |
|
||||
| [config_variables](variables.tf#L17) | Additional variables used to render the cloud-config and CoreDNS templates. | <code>map(any)</code> | | <code>{}</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>"192.168.192.0/24"</code> |
|
||||
| [test_instance](variables-instance.tf#L17) | Test/development instance attributes, leave null to skip creation. | <code title="object({ project_id = string zone = string name = string type = string network = string subnetwork = string })">object({…})</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({ disks = map(object({ read_only = bool size = number })) image = string metadata = map(string) nat = bool service_account_roles = list(string) tags = list(string) })">object({…})</code> | | <code title="{ disks = {} image = null metadata = {} nat = false service_account_roles = [ "roles/logging.logWriter", "roles/monitoring.metricWriter" ] tags = ["ssh"] }">{…}</code> |
|
||||
| [vpn_dynamic_config](variables.tf#L46) | BGP configuration for dynamic VPN, ignored if VPN type is 'static'. | <code title="object({ local_bgp_asn = number local_bgp_address = string peer_bgp_asn = number peer_bgp_address = string local_bgp_asn2 = number local_bgp_address2 = string peer_bgp_asn2 = number peer_bgp_address2 = string })">object({…})</code> | | <code title="{ local_bgp_asn = 64514 local_bgp_address = "169.254.1.2" peer_bgp_asn = 64513 peer_bgp_address = "169.254.1.1" local_bgp_asn2 = 64514 local_bgp_address2 = "169.254.2.2" peer_bgp_asn2 = 64520 peer_bgp_address2 = "169.254.2.1" }">{…}</code> |
|
||||
| [vpn_static_ranges](variables.tf#L70) | Remote CIDR ranges for static VPN, ignored if VPN type is 'dynamic'. | <code>list(string)</code> | | <code>["10.0.0.0/8"]</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 -->
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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({ owner = string permissions = string })">object({…})</code> | | <code title="{ owner = "root" permissions = "0644" }">{…}</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(object({ content = string owner = string permissions = string }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [test_instance](variables-instance.tf#L17) | Test/development instance attributes, leave null to skip creation. | <code title="object({ project_id = string zone = string name = string type = string network = string subnetwork = string })">object({…})</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({ disks = map(object({ read_only = bool size = number })) image = string metadata = map(string) nat = bool service_account_roles = list(string) tags = list(string) })">object({…})</code> | | <code title="{ disks = {} image = null metadata = {} nat = false service_account_roles = [ "roles/logging.logWriter", "roles/monitoring.metricWriter" ] tags = ["ssh"] }">{…}</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 -->
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
../instance.tf
|
||||
@@ -1 +0,0 @@
|
||||
../outputs-instance.tf
|
||||
@@ -1 +0,0 @@
|
||||
../variables-instance.tf
|
||||
@@ -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 -->
|
||||
|
||||
|
||||
@@ -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 -->
|
||||
|
||||
|
||||
@@ -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"]
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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({ project_id = string keyring = string location = string key = string })">object({…})</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({ project_id = string zone = string name = string type = string network = string subnetwork = string })">object({…})</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({ disks = map(object({ read_only = bool size = number })) image = string metadata = map(string) nat = bool service_account_roles = list(string) tags = list(string) })">object({…})</code> | | <code title="{ disks = {} image = null metadata = {} nat = false service_account_roles = [ "roles/logging.logWriter", "roles/monitoring.metricWriter" ] tags = ["ssh"] }">{…}</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 -->
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
../instance.tf
|
||||
@@ -1 +0,0 @@
|
||||
../outputs-instance.tf
|
||||
@@ -1 +0,0 @@
|
||||
../variables-instance.tf
|
||||
@@ -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(object({ content = string owner = string permissions = string }))">map(object({…}))</code> | | <code>null</code> |
|
||||
| [nginx_image](variables.tf#L27) | Nginx container image to use. | <code>string</code> | | <code>"nginx:1.23.1"</code> |
|
||||
| [runcmd_post](variables.tf#L33) | Extra commands to run after starting nginx. | <code>list(string)</code> | | <code>[]</code> |
|
||||
| [runcmd_pre](variables.tf#L39) | Extra commands to run before starting nginx. | <code>list(string)</code> | | <code>[]</code> |
|
||||
| [users](variables.tf#L45) | Additional list of usernames to be created. | <code title="list(object({ username = string, uid = number, }))">list(object({…}))</code> | | <code title="[ ]">[…]</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(object({ content = string owner = optional(string, "root") permissions = optional(string, "0644") }))">map(object({…}))</code> | | <code>{}</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>"nginx:1.23.1"</code> |
|
||||
|
||||
## Outputs
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
24
modules/cloud-config-container/nginx-tls/assets/default.conf
Normal file
24
modules/cloud-config-container/nginx-tls/assets/default.conf
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
}
|
||||
@@ -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
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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 = [
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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(string)</code> | | <code>[]</code> |
|
||||
| [runcmd_pre](variables.tf#L69) | Extra commands to run before starting nginx. | <code>list(string)</code> | | <code>[]</code> |
|
||||
| [test_instance](variables-instance.tf#L17) | Test/development instance attributes, leave null to skip creation. | <code title="object({ project_id = string zone = string name = string type = string network = string subnetwork = string })">object({…})</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({ disks = map(object({ read_only = bool size = number })) image = string metadata = map(string) nat = bool service_account_roles = list(string) tags = list(string) })">object({…})</code> | | <code title="{ disks = {} image = null metadata = {} nat = false service_account_roles = [ "roles/logging.logWriter", "roles/monitoring.metricWriter" ] tags = ["ssh"] }">{…}</code> |
|
||||
| [users](variables.tf#L75) | List of additional usernames to be created. | <code title="list(object({ username = string, uid = number, }))">list(object({…}))</code> | | <code title="[ ]">[…]</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 -->
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
../instance.tf
|
||||
@@ -1 +0,0 @@
|
||||
../outputs-instance.tf
|
||||
@@ -1 +0,0 @@
|
||||
../variables-instance.tf
|
||||
@@ -1 +0,0 @@
|
||||
../instance.tf
|
||||
@@ -1 +0,0 @@
|
||||
../outputs-instance.tf
|
||||
@@ -1 +0,0 @@
|
||||
../variables-instance.tf
|
||||
@@ -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
|
||||
})
|
||||
}
|
||||
@@ -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(object({ content = string owner = string permissions = string }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [test_instance](variables-instance.tf#L17) | Test/development instance attributes, leave null to skip creation. | <code title="object({ project_id = string zone = string name = string type = string network = string subnetwork = string })">object({…})</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({ disks = map(object({ read_only = bool size = number })) image = string metadata = map(string) nat = bool service_account_roles = list(string) tags = list(string) })">object({…})</code> | | <code title="{ disks = {} image = null metadata = {} nat = false service_account_roles = [ "roles/logging.logWriter", "roles/monitoring.metricWriter" ] tags = ["ssh"] }">{…}</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 -->
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
../instance.tf
|
||||
@@ -1 +0,0 @@
|
||||
../outputs-instance.tf
|
||||
@@ -1 +0,0 @@
|
||||
../variables-instance.tf
|
||||
@@ -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({ owner = string permissions = string })">object({…})</code> | | <code title="{ owner = "root" permissions = "0644" }">{…}</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(object({ content = string owner = string permissions = string }))">map(object({…}))</code> | | <code>{}</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({ project_id = string zone = string name = string type = string network = string subnetwork = string })">object({…})</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({ disks = map(object({ read_only = bool size = number })) image = string metadata = map(string) nat = bool service_account_roles = list(string) tags = list(string) })">object({…})</code> | | <code title="{ disks = {} image = null metadata = {} nat = false service_account_roles = [ "roles/logging.logWriter", "roles/monitoring.metricWriter" ] tags = ["ssh"] }">{…}</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 -->
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
../instance.tf
|
||||
@@ -1 +0,0 @@
|
||||
../outputs-instance.tf
|
||||
@@ -1 +0,0 @@
|
||||
../variables-instance.tf
|
||||
@@ -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"]
|
||||
}
|
||||
}
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user