Merge branch 'master' into projects-ds-new-version

This commit is contained in:
Aleksandr Averbukh
2023-02-18 21:38:53 +01:00
1009 changed files with 30803 additions and 25569 deletions

View File

@@ -7,11 +7,11 @@ Note: this module will integrated into a general-purpose load balancing module i
## Example
```hcl
module "neg" {
source = "./fabric/modules/net-neg"
source = "./fabric/modules/__experimental/net-neg/"
project_id = "myproject"
name = "myneg"
network = module.vpc.self_link
subnetwork = module.vpc.subnet_self_links["europe-west1/default"]
network = var.vpc.self_link
subnetwork = var.subnet.self_link
zone = "europe-west1-b"
endpoints = [
for instance in module.vm.instances :
@@ -22,6 +22,7 @@ module "neg" {
}
]
}
# tftest skip
```
<!-- BEGIN TFDOC -->

View File

@@ -17,11 +17,11 @@ terraform {
required_providers {
google = {
source = "hashicorp/google"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
google-beta = {
source = "hashicorp/google-beta"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
}
}

View File

@@ -1,4 +1,4 @@
# Api Gateway
# API Gateway
This module allows creating an API with its associated API config and API gateway. It also allows you grant IAM roles on the created resources.
# Examples
@@ -6,55 +6,55 @@ This module allows creating an API with its associated API config and API gatewa
## Basic example
```hcl
module "gateway" {
source = "./fabric/modules/api-gateway"
project_id = "my-project"
api_id = "api"
region = "europe-west1"
spec = <<EOT
source = "./fabric/modules/api-gateway"
project_id = "my-project"
api_id = "api"
region = "europe-west1"
spec = <<EOT
# The OpenAPI spec contents
# ...
EOT
}
# tftest modules=1 resources=4
# tftest modules=1 resources=4 inventory=basic.yaml
```
## Basic example + customer service account
## Use existing service account
```hcl
module "gateway" {
source = "./fabric/modules/api-gateway"
project_id = "my-project"
api_id = "api"
region = "europe-west1"
spec = <<EOT
# The OpenAPI spec contents
# ...
EOT
service_account_email = "sa@my-project.iam.gserviceaccount.com"
iam = {
"roles/apigateway.admin" = [ "user:user@example.com" ]
"roles/apigateway.admin" = ["user:user@example.com"]
}
}
# tftest modules=1 resources=7
```
## Basic example + service account creation
```hcl
module "gateway" {
source = "./fabric/modules/api-gateway"
project_id = "my-project"
api_id = "api"
region = "europe-west1"
spec = <<EOT
spec = <<EOT
# The OpenAPI spec contents
# ...
EOT
}
# tftest modules=1 resources=7 inventory=existing-sa.yaml
```
## Create service account
```hcl
module "gateway" {
source = "./fabric/modules/api-gateway"
project_id = "my-project"
api_id = "api"
region = "europe-west1"
service_account_create = true
iam = {
"roles/apigateway.admin" = [ "user:mirene@google.com" ]
"roles/apigateway.viewer" = [ "user:mirene@google.com" ]
"roles/apigateway.admin" = ["user:mirene@google.com"]
"roles/apigateway.viewer" = ["user:mirene@google.com"]
}
spec = <<EOT
# The OpenAPI spec contents
# ...
EOT
}
# tftest modules=1 resources=11
# tftest modules=1 resources=11 inventory=create-sa.yaml
```
<!-- BEGIN TFDOC -->

View File

@@ -17,11 +17,11 @@ terraform {
required_providers {
google = {
source = "hashicorp/google"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
google-beta = {
source = "hashicorp/google-beta"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
}
}

View File

@@ -27,11 +27,15 @@ module "apigee" {
apis-test = {
display_name = "APIs test"
description = "APIs Test"
deployment_type = "ARCHIVE"
api_proxy_type = "PROGRAMMABLE"
envgroups = ["test"]
}
apis-prod = {
display_name = "APIs prod"
description = "APIs prod"
deployment_type = "PROXY"
api_proxy_type = "CONFIGURABLE"
envgroups = ["prod"]
iam = {
"roles/viewer" = ["group:devops@myorg.com"]
@@ -40,14 +44,16 @@ module "apigee" {
}
instances = {
instance-test-ew1 = {
region = "europe-west1"
environments = ["apis-test"]
psa_ip_cidr_range = "10.0.4.0/22"
region = "europe-west1"
environments = ["apis-test"]
runtime_ip_cidr_range = "10.0.4.0/22"
troubleshooting_ip_cidr_range = "10.1.1.0.0/28"
}
instance-prod-ew3 = {
region = "europe-west3"
environments = ["apis-prod"]
psa_ip_cidr_range = "10.0.5.0/22"
region = "europe-west3"
environments = ["apis-prod"]
runtime_ip_cidr_range = "10.0.8.0/22"
troubleshooting_ip_cidr_range = "10.1.16.0/28"
}
}
endpoint_attachments = {
@@ -71,10 +77,10 @@ module "apigee" {
source = "./fabric/modules/apigee"
project_id = "my-project"
organization = {
display_name = "My Organization"
description = "My Organization"
runtime_type = "HYBRID"
analytics_region = "europe-west1"
display_name = "My Organization"
description = "My Organization"
runtime_type = "HYBRID"
analytics_region = "europe-west1"
}
envgroups = {
test = ["test.example.com"]
@@ -82,14 +88,14 @@ module "apigee" {
}
environments = {
apis-test = {
display_name = "APIs test"
description = "APIs Test"
envgroups = ["test"]
display_name = "APIs test"
description = "APIs Test"
envgroups = ["test"]
}
apis-prod = {
display_name = "APIs prod"
description = "APIs prod"
envgroups = ["prod"]
display_name = "APIs prod"
description = "APIs prod"
envgroups = ["prod"]
iam = {
"roles/viewer" = ["group:devops@myorg.com"]
}
@@ -120,9 +126,9 @@ module "apigee" {
project_id = "my-project"
environments = {
apis-test = {
display_name = "APIs test"
description = "APIs Test"
envgroups = ["test"]
display_name = "APIs test"
description = "APIs Test"
envgroups = ["test"]
}
}
}
@@ -137,9 +143,10 @@ module "apigee" {
project_id = "my-project"
instances = {
instance-test-ew1 = {
region = "europe-west1"
environments = ["apis-test"]
psa_ip_cidr_range = "10.0.4.0/22"
region = "europe-west1"
environments = ["apis-test"]
runtime_ip_cidr_range = "10.0.4.0/22"
troubleshooting_ip_cidr_range = "10.1.1.0/28"
}
}
}
@@ -169,23 +176,24 @@ module "apigee" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [project_id](variables.tf#L75) | Project ID. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L78) | Project ID. | <code>string</code> | ✓ | |
| [endpoint_attachments](variables.tf#L17) | Endpoint attachments. | <code title="map&#40;object&#40;&#123;&#10; region &#61; string&#10; service_attachment &#61; string&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>null</code> |
| [envgroups](variables.tf#L26) | Environment groups (NAME => [HOSTNAMES]). | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>null</code> |
| [environments](variables.tf#L32) | Environments. | <code title="map&#40;object&#40;&#123;&#10; display_name &#61; optional&#40;string&#41;&#10; description &#61; optional&#40;string, &#34;Terraform-managed&#34;&#41;&#10; node_config &#61; optional&#40;object&#40;&#123;&#10; min_node_count &#61; optional&#40;number&#41;&#10; max_node_count &#61; optional&#40;number&#41;&#10; &#125;&#41;&#41;&#10; iam &#61; optional&#40;map&#40;list&#40;string&#41;&#41;&#41;&#10; envgroups &#61; list&#40;string&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>null</code> |
| [instances](variables.tf#L47) | Instances. | <code title="map&#40;object&#40;&#123;&#10; display_name &#61; optional&#40;string&#41;&#10; description &#61; optional&#40;string, &#34;Terraform-managed&#34;&#41;&#10; region &#61; string&#10; environments &#61; list&#40;string&#41;&#10; psa_ip_cidr_range &#61; string&#10; disk_encryption_key &#61; optional&#40;string&#41;&#10; consumer_accept_list &#61; optional&#40;list&#40;string&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>null</code> |
| [organization](variables.tf#L61) | Apigee organization. If set to null the organization must already exist. | <code title="object&#40;&#123;&#10; display_name &#61; optional&#40;string&#41;&#10; description &#61; optional&#40;string, &#34;Terraform-managed&#34;&#41;&#10; authorized_network &#61; optional&#40;string&#41;&#10; runtime_type &#61; optional&#40;string, &#34;CLOUD&#34;&#41;&#10; billing_type &#61; optional&#40;string&#41;&#10; database_encryption_key &#61; optional&#40;string&#41;&#10; analytics_region &#61; optional&#40;string, &#34;europe-west1&#34;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [environments](variables.tf#L32) | Environments. | <code title="map&#40;object&#40;&#123;&#10; display_name &#61; optional&#40;string&#41;&#10; description &#61; optional&#40;string, &#34;Terraform-managed&#34;&#41;&#10; deployment_type &#61; optional&#40;string&#41;&#10; api_proxy_type &#61; optional&#40;string&#41;&#10; node_config &#61; optional&#40;object&#40;&#123;&#10; min_node_count &#61; optional&#40;number&#41;&#10; max_node_count &#61; optional&#40;number&#41;&#10; &#125;&#41;&#41;&#10; iam &#61; optional&#40;map&#40;list&#40;string&#41;&#41;&#41;&#10; envgroups &#61; list&#40;string&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>null</code> |
| [instances](variables.tf#L49) | Instances. | <code title="map&#40;object&#40;&#123;&#10; display_name &#61; optional&#40;string&#41;&#10; description &#61; optional&#40;string, &#34;Terraform-managed&#34;&#41;&#10; region &#61; string&#10; environments &#61; list&#40;string&#41;&#10; runtime_ip_cidr_range &#61; string&#10; troubleshooting_ip_cidr_range &#61; string&#10; disk_encryption_key &#61; optional&#40;string&#41;&#10; consumer_accept_list &#61; optional&#40;list&#40;string&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>null</code> |
| [organization](variables.tf#L64) | Apigee organization. If set to null the organization must already exist. | <code title="object&#40;&#123;&#10; display_name &#61; optional&#40;string&#41;&#10; description &#61; optional&#40;string, &#34;Terraform-managed&#34;&#41;&#10; authorized_network &#61; optional&#40;string&#41;&#10; runtime_type &#61; optional&#40;string, &#34;CLOUD&#34;&#41;&#10; billing_type &#61; optional&#40;string&#41;&#10; database_encryption_key &#61; optional&#40;string&#41;&#10; analytics_region &#61; optional&#40;string, &#34;europe-west1&#34;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
## Outputs
| name | description | sensitive |
|---|---|:---:|
| [envgroups](outputs.tf#L17) | Environment groups. | |
| [environments](outputs.tf#L22) | Environment. | |
| [instances](outputs.tf#L27) | Instances. | |
| [org_id](outputs.tf#L32) | Organization ID. | |
| [org_name](outputs.tf#L37) | Organization name. | |
| [organization](outputs.tf#L42) | Organization. | |
| [service_attachments](outputs.tf#L47) | Service attachments. | |
| [endpoint_attachment_hosts](outputs.tf#L17) | Endpoint hosts. | |
| [envgroups](outputs.tf#L22) | Environment groups. | |
| [environments](outputs.tf#L27) | Environment. | |
| [instances](outputs.tf#L32) | Instances. | |
| [org_id](outputs.tf#L37) | Organization ID. | |
| [org_name](outputs.tf#L42) | Organization name. | |
| [organization](outputs.tf#L47) | Organization. | |
| [service_attachments](outputs.tf#L52) | Service attachments. | |
<!-- END TFDOC -->

View File

@@ -40,10 +40,12 @@ resource "google_apigee_envgroup" "envgroups" {
}
resource "google_apigee_environment" "environments" {
for_each = local.environments
name = each.key
display_name = each.value.display_name
description = each.value.description
for_each = local.environments
name = each.key
display_name = each.value.display_name
description = each.value.description
deployment_type = each.value.deployment_type
api_proxy_type = each.value.api_proxy_type
dynamic "node_config" {
for_each = try(each.value.node_config, null) != null ? [""] : []
content {
@@ -91,7 +93,7 @@ resource "google_apigee_instance" "instances" {
description = each.value.description
location = each.value.region
org_id = local.org_id
ip_range = each.value.psa_ip_cidr_range
ip_range = "${each.value.runtime_ip_cidr_range},${each.value.troubleshooting_ip_cidr_range}"
disk_encryption_key_name = each.value.disk_encryption_key
consumer_accept_list = each.value.consumer_accept_list
}

View File

@@ -14,6 +14,11 @@
* limitations under the License.
*/
output "endpoint_attachment_hosts" {
description = "Endpoint hosts."
value = { for k, v in google_apigee_endpoint_attachment.endpoint_attachments : k => v.host }
}
output "envgroups" {
description = "Environment groups."
value = try(google_apigee_envgroup.envgroups, null)

View File

@@ -32,8 +32,10 @@ variable "envgroups" {
variable "environments" {
description = "Environments."
type = map(object({
display_name = optional(string)
description = optional(string, "Terraform-managed")
display_name = optional(string)
description = optional(string, "Terraform-managed")
deployment_type = optional(string)
api_proxy_type = optional(string)
node_config = optional(object({
min_node_count = optional(number)
max_node_count = optional(number)
@@ -47,13 +49,14 @@ variable "environments" {
variable "instances" {
description = "Instances."
type = map(object({
display_name = optional(string)
description = optional(string, "Terraform-managed")
region = string
environments = list(string)
psa_ip_cidr_range = string
disk_encryption_key = optional(string)
consumer_accept_list = optional(list(string))
display_name = optional(string)
description = optional(string, "Terraform-managed")
region = string
environments = list(string)
runtime_ip_cidr_range = string
troubleshooting_ip_cidr_range = string
disk_encryption_key = optional(string)
consumer_accept_list = optional(list(string))
}))
default = null
}

View File

@@ -17,11 +17,11 @@ terraform {
required_providers {
google = {
source = "hashicorp/google"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
google-beta = {
source = "hashicorp/google-beta"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
}
}

View File

@@ -17,11 +17,11 @@ terraform {
required_providers {
google = {
source = "hashicorp/google"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
google-beta = {
source = "hashicorp/google-beta"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
}
}

View File

@@ -21,7 +21,7 @@ The access variables are split into `access` and `access_identities` variables,
module "bigquery-dataset" {
source = "./fabric/modules/bigquery-dataset"
project_id = "my-project"
id = "my-dataset"
id = "my-dataset"
access = {
reader-group = { role = "READER", type = "group" }
owner = { role = "OWNER", type = "user" }
@@ -46,7 +46,7 @@ Access configuration can also be specified via IAM instead of basic roles via th
module "bigquery-dataset" {
source = "./fabric/modules/bigquery-dataset"
project_id = "my-project"
id = "my-dataset"
id = "my-dataset"
iam = {
"roles/bigquery.dataOwner" = ["user:user1@example.org"]
}
@@ -67,6 +67,7 @@ module "bigquery-dataset" {
default_table_expiration_ms = 3600000
default_partition_expiration_ms = null
delete_contents_on_destroy = false
max_time_travel_hours = 168
}
}
# tftest modules=1 resources=1
@@ -178,7 +179,7 @@ module "bigquery-dataset" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [id](variables.tf#L69) | Dataset id. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L100) | Id of the project where datasets will be created. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L97) | Id of the project where datasets will be created. | <code>string</code> | ✓ | |
| [access](variables.tf#L17) | Map of access rules with role and identity type. Keys are arbitrary and must match those in the `access_identities` variable, types are `domain`, `group`, `special_group`, `user`, `view`. | <code title="map&#40;object&#40;&#123;&#10; role &#61; string&#10; type &#61; string&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [access_identities](variables.tf#L33) | Map of access identities used for basic access roles. View identities have the format 'project_id\|dataset_id\|table_id'. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [dataset_access](variables.tf#L39) | Set access in the dataset resource instead of using separate resources. | <code>bool</code> | | <code>false</code> |
@@ -188,9 +189,9 @@ module "bigquery-dataset" {
| [iam](variables.tf#L63) | IAM bindings in {ROLE => [MEMBERS]} format. Mutually exclusive with the access_* variables used for basic roles. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [labels](variables.tf#L74) | Dataset labels. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [location](variables.tf#L80) | Dataset location. | <code>string</code> | | <code>&#34;EU&#34;</code> |
| [options](variables.tf#L86) | Dataset options. | <code title="object&#40;&#123;&#10; default_table_expiration_ms &#61; number&#10; default_partition_expiration_ms &#61; number&#10; delete_contents_on_destroy &#61; bool&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; default_table_expiration_ms &#61; null&#10; default_partition_expiration_ms &#61; null&#10; delete_contents_on_destroy &#61; false&#10;&#125;">&#123;&#8230;&#125;</code> |
| [tables](variables.tf#L105) | Table definitions. Options and partitioning default to null. Partitioning can only use `range` or `time`, set the unused one to null. | <code title="map&#40;object&#40;&#123;&#10; friendly_name &#61; string&#10; labels &#61; map&#40;string&#41;&#10; options &#61; object&#40;&#123;&#10; clustering &#61; list&#40;string&#41;&#10; encryption_key &#61; string&#10; expiration_time &#61; number&#10; &#125;&#41;&#10; partitioning &#61; object&#40;&#123;&#10; field &#61; string&#10; range &#61; object&#40;&#123;&#10; end &#61; number&#10; interval &#61; number&#10; start &#61; number&#10; &#125;&#41;&#10; time &#61; object&#40;&#123;&#10; expiration_ms &#61; number&#10; type &#61; string&#10; &#125;&#41;&#10; &#125;&#41;&#10; schema &#61; string&#10; deletion_protection &#61; bool&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [views](variables.tf#L133) | View definitions. | <code title="map&#40;object&#40;&#123;&#10; friendly_name &#61; string&#10; labels &#61; map&#40;string&#41;&#10; query &#61; string&#10; use_legacy_sql &#61; bool&#10; deletion_protection &#61; bool&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [options](variables.tf#L86) | Dataset options. | <code title="object&#40;&#123;&#10; default_table_expiration_ms &#61; optional&#40;number, null&#41;&#10; default_partition_expiration_ms &#61; optional&#40;number, null&#41;&#10; delete_contents_on_destroy &#61; optional&#40;bool, false&#41;&#10; max_time_travel_hours &#61; optional&#40;number, 168&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [tables](variables.tf#L102) | Table definitions. Options and partitioning default to null. Partitioning can only use `range` or `time`, set the unused one to null. | <code title="map&#40;object&#40;&#123;&#10; friendly_name &#61; string&#10; labels &#61; map&#40;string&#41;&#10; options &#61; object&#40;&#123;&#10; clustering &#61; list&#40;string&#41;&#10; encryption_key &#61; string&#10; expiration_time &#61; number&#10; &#125;&#41;&#10; partitioning &#61; object&#40;&#123;&#10; field &#61; string&#10; range &#61; object&#40;&#123;&#10; end &#61; number&#10; interval &#61; number&#10; start &#61; number&#10; &#125;&#41;&#10; time &#61; object&#40;&#123;&#10; expiration_ms &#61; number&#10; type &#61; string&#10; &#125;&#41;&#10; &#125;&#41;&#10; schema &#61; string&#10; deletion_protection &#61; bool&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [views](variables.tf#L130) | View definitions. | <code title="map&#40;object&#40;&#123;&#10; friendly_name &#61; string&#10; labels &#61; map&#40;string&#41;&#10; query &#61; string&#10; use_legacy_sql &#61; bool&#10; deletion_protection &#61; bool&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
## Outputs

View File

@@ -42,7 +42,7 @@ resource "google_bigquery_dataset" "default" {
delete_contents_on_destroy = var.options.delete_contents_on_destroy
default_table_expiration_ms = var.options.default_table_expiration_ms
default_partition_expiration_ms = var.options.default_partition_expiration_ms
max_time_travel_hours = var.options.max_time_travel_hours
dynamic "access" {
for_each = var.dataset_access ? local.access_domain : {}
content {

View File

@@ -86,15 +86,12 @@ variable "location" {
variable "options" {
description = "Dataset options."
type = object({
default_table_expiration_ms = number
default_partition_expiration_ms = number
delete_contents_on_destroy = bool
default_table_expiration_ms = optional(number, null)
default_partition_expiration_ms = optional(number, null)
delete_contents_on_destroy = optional(bool, false)
max_time_travel_hours = optional(number, 168)
})
default = {
default_table_expiration_ms = null
default_partition_expiration_ms = null
delete_contents_on_destroy = false
}
default = {}
}
variable "project_id" {

View File

@@ -17,11 +17,11 @@ terraform {
required_providers {
google = {
source = "hashicorp/google"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
google-beta = {
source = "hashicorp/google-beta"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
}
}

View File

@@ -4,9 +4,7 @@ This module allows managing a single BigTable instance, including access configu
## TODO
- [ ] support bigtable_gc_policy
- [ ] support bigtable_app_profile
- [ ] support cluster replicas
- [ ] support IAM for tables
## Examples
@@ -16,25 +14,147 @@ This module allows managing a single BigTable instance, including access configu
```hcl
module "bigtable-instance" {
source = "./fabric/modules/bigtable-instance"
project_id = "my-project"
name = "instance"
cluster_id = "instance"
zone = "europe-west1-b"
tables = {
test1 = null,
test2 = {
split_keys = ["a", "b", "c"]
column_family = null
source = "./fabric/modules/bigtable-instance"
project_id = "my-project"
name = "instance"
clusters = {
my-cluster = {
zone = "europe-west1-b"
}
}
iam = {
tables = {
test1 = {},
test2 = {
split_keys = ["a", "b", "c"]
}
}
iam = {
"roles/bigtable.user" = ["user:viewer@testdomain.com"]
}
}
# tftest modules=1 resources=4
```
### Instance with tables and column families
```hcl
module "bigtable-instance" {
source = "./fabric/modules/bigtable-instance"
project_id = "my-project"
name = "instance"
clusters = {
my-cluster = {
zone = "europe-west1-b"
}
}
tables = {
test1 = {},
test2 = {
split_keys = ["a", "b", "c"]
column_families = {
cf1 = {}
cf2 = {}
cf3 = {}
}
}
test3 = {
column_families = {
cf1 = {}
}
}
}
}
# tftest modules=1 resources=4
```
### Instance with replication enabled
```hcl
module "bigtable-instance" {
source = "./fabric/modules/bigtable-instance"
project_id = "my-project"
name = "instance"
clusters = {
first-cluster = {
zone = "europe-west1-b"
}
second-cluster = {
zone = "europe-southwest1-a"
}
third-cluster = {
zone = "us-central1-b"
}
}
}
# tftest modules=1 resources=1
```
### Instance with garbage collection policy
```hcl
module "bigtable-instance" {
source = "./fabric/modules/bigtable-instance"
project_id = "my-project"
name = "instance"
clusters = {
my-cluster = {
zone = "europe-west1-b"
}
}
tables = {
test1 = {
column_families = {
cf1 = {
gc_policy = {
deletion_policy = "ABANDON"
max_age = "18h"
}
}
cf2 = {}
}
}
}
}
# tftest modules=1 resources=3
```
### Instance with default garbage collection policy
The default garbage collection policy is applied to any column family that does
not specify a `gc_policy`. If a column family specifies a `gc_policy`, the
default garbage collection policy is ignored for that column family.
```hcl
module "bigtable-instance" {
source = "./fabric/modules/bigtable-instance"
project_id = "my-project"
name = "instance"
clusters = {
my-cluster = {
zone = "europe-west1-b"
}
}
default_gc_policy = {
deletion_policy = "ABANDON"
max_age = "18h"
max_version = 7
}
tables = {
test1 = {
column_families = {
cf1 = {}
cf2 = {}
}
}
}
}
# tftest modules=1 resources=4
```
### Instance with static number of nodes
If you are not using autoscaling settings, you must set a specific number of nodes with the variable `num_nodes`.
@@ -45,9 +165,12 @@ module "bigtable-instance" {
source = "./fabric/modules/bigtable-instance"
project_id = "my-project"
name = "instance"
cluster_id = "instance"
zone = "europe-west1-b"
num_nodes = 5
clusters = {
my-cluster = {
zone = "europe-west1-b"
num_nodes = 5
}
}
}
# tftest modules=1 resources=1
```
@@ -59,16 +182,21 @@ If you use autoscaling, you should not set the variable `num_nodes`.
```hcl
module "bigtable-instance" {
source = "./fabric/modules/bigtable-instance"
project_id = "my-project"
name = "instance"
cluster_id = "instance"
zone = "europe-southwest1-b"
autoscaling_config = {
min_nodes = 3
max_nodes = 7
cpu_target = 70
source = "./fabric/modules/bigtable-instance"
project_id = "my-project"
name = "instance"
clusters = {
my-cluster = {
zone = "europe-southwest1-b"
autoscaling = {
min_nodes = 3
max_nodes = 7
cpu_target = 70
}
}
}
}
# tftest modules=1 resources=1
```
@@ -78,17 +206,20 @@ module "bigtable-instance" {
```hcl
module "bigtable-instance" {
source = "./fabric/modules/bigtable-instance"
project_id = "my-project"
name = "instance"
cluster_id = "instance"
zone = "europe-southwest1-a"
storage_type = "SSD"
autoscaling_config = {
min_nodes = 3
max_nodes = 7
cpu_target = 70
storage_target = 4096
source = "./fabric/modules/bigtable-instance"
project_id = "my-project"
name = "instance"
clusters = {
my-cluster = {
zone = "europe-southwest1-a"
storage_type = "SSD"
autoscaling = {
min_nodes = 3
max_nodes = 7
cpu_target = 70
storage_target = 4096
}
}
}
}
# tftest modules=1 resources=1
@@ -99,19 +230,16 @@ module "bigtable-instance" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [name](variables.tf#L56) | The name of the Cloud Bigtable instance. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L67) | Id of the project where datasets will be created. | <code>string</code> | ✓ | |
| [zone](variables.tf#L99) | The zone to create the Cloud Bigtable cluster in. | <code>string</code> | ✓ | |
| [autoscaling_config](variables.tf#L17) | Settings for autoscaling of the instance. If you set this variable, the variable num_nodes is ignored. | <code title="object&#40;&#123;&#10; min_nodes &#61; number&#10; max_nodes &#61; number&#10; cpu_target &#61; number,&#10; storage_target &#61; optional&#40;number, null&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [cluster_id](variables.tf#L28) | The ID of the Cloud Bigtable cluster. | <code>string</code> | | <code>&#34;europe-west1&#34;</code> |
| [deletion_protection](variables.tf#L34) | Whether or not to allow Terraform to destroy the instance. Unless this field is set to false in Terraform state, a terraform destroy or terraform apply that would delete the instance will fail. | <code></code> | | <code>true</code> |
| [display_name](variables.tf#L39) | The human-readable display name of the Bigtable instance. | <code></code> | | <code>null</code> |
| [iam](variables.tf#L44) | IAM bindings for topic in {ROLE => [MEMBERS]} format. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [instance_type](variables.tf#L50) | (deprecated) The instance type to create. One of 'DEVELOPMENT' or 'PRODUCTION'. | <code>string</code> | | <code>null</code> |
| [num_nodes](variables.tf#L61) | The number of nodes in your Cloud Bigtable cluster. This value is ignored if you are using autoscaling. | <code>number</code> | | <code>1</code> |
| [storage_type](variables.tf#L72) | The storage type to use. | <code>string</code> | | <code>&#34;SSD&#34;</code> |
| [table_options_defaults](variables.tf#L78) | Default option of tables created in the BigTable instance. | <code title="object&#40;&#123;&#10; split_keys &#61; list&#40;string&#41;&#10; column_family &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; split_keys &#61; &#91;&#93;&#10; column_family &#61; null&#10;&#125;">&#123;&#8230;&#125;</code> |
| [tables](variables.tf#L90) | Tables to be created in the BigTable instance, options can be null. | <code title="map&#40;object&#40;&#123;&#10; split_keys &#61; list&#40;string&#41;&#10; column_family &#61; string&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [clusters](variables.tf#L17) | Clusters to be created in the BigTable instance. Set more than one cluster to enable replication. If you set autoscaling, num_nodes will be ignored. | <code title="map&#40;object&#40;&#123;&#10; zone &#61; optional&#40;string&#41;&#10; storage_type &#61; optional&#40;string&#41;&#10; num_nodes &#61; optional&#40;number&#41;&#10; autoscaling &#61; optional&#40;object&#40;&#123;&#10; min_nodes &#61; number&#10; max_nodes &#61; number&#10; cpu_target &#61; number&#10; storage_target &#61; optional&#40;number&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | ✓ | |
| [name](variables.tf#L78) | The name of the Cloud Bigtable instance. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L83) | Id of the project where datasets will be created. | <code>string</code> | ✓ | |
| [default_autoscaling](variables.tf#L33) | Default settings for autoscaling of clusters. This will be the default autoscaling for any cluster not specifying any autoscaling details. | <code title="object&#40;&#123;&#10; min_nodes &#61; number&#10; max_nodes &#61; number&#10; cpu_target &#61; number&#10; storage_target &#61; optional&#40;number&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [default_gc_policy](variables.tf#L44) | Default garbage collection policy, to be applied to all column families and all tables. Can be override in the tables variable for specific column families. | <code title="object&#40;&#123;&#10; deletion_policy &#61; optional&#40;string&#41;&#10; gc_rules &#61; optional&#40;string&#41;&#10; mode &#61; optional&#40;string&#41;&#10; max_age &#61; optional&#40;string&#41;&#10; max_version &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [deletion_protection](variables.tf#L56) | Whether or not to allow Terraform to destroy the instance. Unless this field is set to false in Terraform state, a terraform destroy or terraform apply that would delete the instance will fail. | <code></code> | | <code>true</code> |
| [display_name](variables.tf#L61) | The human-readable display name of the Bigtable instance. | <code></code> | | <code>null</code> |
| [iam](variables.tf#L66) | IAM bindings for topic in {ROLE => [MEMBERS]} format. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [instance_type](variables.tf#L72) | (deprecated) The instance type to create. One of 'DEVELOPMENT' or 'PRODUCTION'. | <code>string</code> | | <code>null</code> |
| [tables](variables.tf#L88) | Tables to be created in the BigTable instance. | <code title="map&#40;object&#40;&#123;&#10; split_keys &#61; optional&#40;list&#40;string&#41;, &#91;&#93;&#41;&#10; column_families &#61; optional&#40;map&#40;object&#40;&#10; &#123;&#10; gc_policy &#61; optional&#40;object&#40;&#123;&#10; deletion_policy &#61; optional&#40;string&#41;&#10; gc_rules &#61; optional&#40;string&#41;&#10; mode &#61; optional&#40;string&#41;&#10; max_age &#61; optional&#40;string&#41;&#10; max_version &#61; optional&#40;string&#41;&#10; &#125;&#41;, null&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
## Outputs

View File

@@ -15,34 +15,53 @@
*/
locals {
tables = {
for k, v in var.tables : k => v != null ? v : var.table_options_defaults
gc_pairs = flatten([
for table, table_obj in var.tables : [
for cf, cf_obj in table_obj.column_families : {
table = table
column_family = cf
gc_policy = cf_obj.gc_policy == null ? var.default_gc_policy : cf_obj.gc_policy
}
]
])
clusters_autoscaling = {
for cluster_id, cluster in var.clusters : cluster_id => {
zone = cluster.zone
storage_type = cluster.storage_type
num_nodes = cluster.autoscaling == null && var.default_autoscaling == null ? cluster.num_nodes : null
autoscaling = cluster.autoscaling == null ? var.default_autoscaling : cluster.autoscaling
}
}
num_nodes = var.autoscaling_config == null ? var.num_nodes : null
}
resource "google_bigtable_instance" "default" {
project = var.project_id
name = var.name
cluster {
cluster_id = var.cluster_id
zone = var.zone
storage_type = var.storage_type
num_nodes = local.num_nodes
dynamic "autoscaling_config" {
for_each = var.autoscaling_config == null ? [] : [""]
content {
min_nodes = var.autoscaling_config.min_nodes
max_nodes = var.autoscaling_config.max_nodes
cpu_target = var.autoscaling_config.cpu_target
storage_target = var.autoscaling_config.storage_target
instance_type = var.instance_type
display_name = var.display_name == null ? var.display_name : var.name
deletion_protection = var.deletion_protection
dynamic "cluster" {
for_each = local.clusters_autoscaling
content {
cluster_id = cluster.key
zone = cluster.value.zone
storage_type = cluster.value.storage_type
num_nodes = cluster.value.num_nodes
dynamic "autoscaling_config" {
for_each = cluster.value.autoscaling == null ? [] : [""]
content {
min_nodes = cluster.value.autoscaling.min_nodes
max_nodes = cluster.value.autoscaling.max_nodes
cpu_target = cluster.value.autoscaling.cpu_target
storage_target = cluster.value.autoscaling.storage_target
}
}
}
}
instance_type = var.instance_type
display_name = var.display_name == null ? var.display_name : var.name
deletion_protection = var.deletion_protection
}
resource "google_bigtable_instance_iam_binding" "default" {
@@ -54,17 +73,44 @@ resource "google_bigtable_instance_iam_binding" "default" {
}
resource "google_bigtable_table" "default" {
for_each = local.tables
for_each = var.tables
project = var.project_id
instance_name = google_bigtable_instance.default.name
name = each.key
split_keys = each.value.split_keys
dynamic "column_family" {
for_each = each.value.column_family != null ? [""] : []
for_each = each.value.column_families
content {
family = each.value.column_family
family = column_family.key
}
}
}
resource "google_bigtable_gc_policy" "default" {
for_each = { for k, v in local.gc_pairs : k => v if v.gc_policy != null }
table = each.value.table
column_family = each.value.column_family
instance_name = google_bigtable_instance.default.name
project = var.project_id
gc_rules = try(each.value.gc_policy.gc_rules, null)
mode = try(each.value.gc_policy.mode, null)
deletion_policy = try(each.value.gc_policy.deletion_policy, null)
dynamic "max_age" {
for_each = try(each.value.gc_policy.max_age, null) != null ? [""] : []
content {
duration = each.value.gc_policy.max_age
}
}
dynamic "max_version" {
for_each = try(each.value.gc_policy.max_version, null) != null ? [""] : []
content {
number = each.value.gc_policy.max_version
}
}
}

View File

@@ -14,21 +14,43 @@
* limitations under the License.
*/
variable "autoscaling_config" {
description = "Settings for autoscaling of the instance. If you set this variable, the variable num_nodes is ignored."
variable "clusters" {
description = "Clusters to be created in the BigTable instance. Set more than one cluster to enable replication. If you set autoscaling, num_nodes will be ignored."
nullable = false
type = map(object({
zone = optional(string)
storage_type = optional(string)
num_nodes = optional(number)
autoscaling = optional(object({
min_nodes = number
max_nodes = number
cpu_target = number
storage_target = optional(number)
}))
}))
}
variable "default_autoscaling" {
description = "Default settings for autoscaling of clusters. This will be the default autoscaling for any cluster not specifying any autoscaling details."
type = object({
min_nodes = number
max_nodes = number
cpu_target = number,
storage_target = optional(number, null)
cpu_target = number
storage_target = optional(number)
})
default = null
}
variable "cluster_id" {
description = "The ID of the Cloud Bigtable cluster."
type = string
default = "europe-west1"
variable "default_gc_policy" {
description = "Default garbage collection policy, to be applied to all column families and all tables. Can be override in the tables variable for specific column families."
type = object({
deletion_policy = optional(string)
gc_rules = optional(string)
mode = optional(string)
max_age = optional(string)
max_version = optional(string)
})
default = null
}
variable "deletion_protection" {
@@ -58,45 +80,26 @@ variable "name" {
type = string
}
variable "num_nodes" {
description = "The number of nodes in your Cloud Bigtable cluster. This value is ignored if you are using autoscaling."
type = number
default = 1
}
variable "project_id" {
description = "Id of the project where datasets will be created."
type = string
}
variable "storage_type" {
description = "The storage type to use."
type = string
default = "SSD"
}
variable "table_options_defaults" {
description = "Default option of tables created in the BigTable instance."
type = object({
split_keys = list(string)
column_family = string
})
default = {
split_keys = []
column_family = null
}
}
variable "tables" {
description = "Tables to be created in the BigTable instance, options can be null."
description = "Tables to be created in the BigTable instance."
nullable = false
type = map(object({
split_keys = list(string)
column_family = string
split_keys = optional(list(string), [])
column_families = optional(map(object(
{
gc_policy = optional(object({
deletion_policy = optional(string)
gc_rules = optional(string)
mode = optional(string)
max_age = optional(string)
max_version = optional(string)
}), null)
})), {})
}))
default = {}
}
variable "zone" {
description = "The zone to create the Cloud Bigtable cluster in."
type = string
}

View File

@@ -17,11 +17,11 @@ terraform {
required_providers {
google = {
source = "hashicorp/google"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
google-beta = {
source = "hashicorp/google-beta"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
}
}

View File

@@ -29,7 +29,7 @@ module "budget" {
]
email_recipients = {
project_id = "my-project"
emails = ["user@example.com"]
emails = ["user@example.com"]
}
}
# tftest modules=1 resources=2

View File

@@ -17,11 +17,11 @@ terraform {
required_providers {
google = {
source = "hashicorp/google"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
google-beta = {
source = "hashicorp/google-beta"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
}
}

View File

@@ -8,8 +8,8 @@ This module simplifies the creation of a Binary Authorization policy, attestors
```hcl
module "binauthz" {
source = "./fabric/modules/binauthz"
project_id = "my_project"
source = "./fabric/modules/binauthz"
project_id = "my_project"
global_policy_evaluation_mode = "DISABLE"
default_admission_rule = {
evaluation_mode = "ALWAYS_DENY"
@@ -18,16 +18,16 @@ module "binauthz" {
}
cluster_admission_rules = {
"europe-west1-c.cluster" = {
evaluation_mode = "REQUIRE_ATTESTATION"
enforcement_mode = "ENFORCED_BLOCK_AND_AUDIT_LOG"
attestors = [ "test" ]
evaluation_mode = "REQUIRE_ATTESTATION"
enforcement_mode = "ENFORCED_BLOCK_AND_AUDIT_LOG"
attestors = ["test"]
}
}
attestors_config = {
"test": {
note_reference = null
pgp_public_keys = [
<<EOT
"test" : {
note_reference = null
pgp_public_keys = [
<<EOT
mQENBFtP0doBCADF+joTiXWKVuP8kJt3fgpBSjT9h8ezMfKA4aXZctYLx5wslWQl
bB7Iu2ezkECNzoEeU7WxUe8a61pMCh9cisS9H5mB2K2uM4Jnf8tgFeXn3akJDVo0
oR1IC+Dp9mXbRSK3MAvKkOwWlG99sx3uEdvmeBRHBOO+grchLx24EThXFOyP9Fk6
@@ -44,11 +44,11 @@ module "binauthz" {
qoIRW6y0+UlAc+MbqfL0ziHDOAmcqz1GnROg
=6Bvm
EOT
]
pkix_public_keys = null
iam = {
"roles/viewer" = ["user:user1@my_org.com"]
}
]
pkix_public_keys = null
iam = {
"roles/viewer" = ["user:user1@my_org.com"]
}
}
}
}

View File

@@ -17,11 +17,11 @@ terraform {
required_providers {
google = {
source = "hashicorp/google"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
google-beta = {
source = "hashicorp/google-beta"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
}
}

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

@@ -17,11 +17,11 @@ terraform {
required_providers {
google = {
source = "hashicorp/google"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
google-beta = {
source = "hashicorp/google-beta"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
}
}

View File

@@ -24,17 +24,30 @@ This example will create a `cloud-config` that uses the module's defaults, creat
```hcl
module "cos-coredns" {
source = "./fabric/modules/cloud-config-container/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
@@ -43,7 +56,7 @@ This example will create a `cloud-config` using a custom CoreDNS configuration,
```hcl
module "cos-coredns" {
source = "./fabric/modules/cloud-config-container/coredns"
source = "./fabric/modules/cloud-config-container/coredns"
coredns_config = "./fabric/modules/cloud-config-container/coredns/Corefile-hosts"
files = {
"/etc/coredns/example.hosts" = {
@@ -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

@@ -17,11 +17,11 @@ terraform {
required_providers {
google = {
source = "hashicorp/google"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
google-beta = {
source = "hashicorp/google-beta"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
}
}

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

@@ -17,11 +17,11 @@ terraform {
required_providers {
google = {
source = "hashicorp/google"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
google-beta = {
source = "hashicorp/google-beta"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
}
}

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

@@ -17,11 +17,11 @@ terraform {
required_providers {
google = {
source = "hashicorp/google"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
google-beta = {
source = "hashicorp/google-beta"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
}
}

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,35 +59,17 @@ 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 = {
kms_config = {
project_id = "my-project"
keyring = "test-cos"
location = "europe-west1"
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

@@ -17,11 +17,11 @@ terraform {
required_providers {
google = {
source = "hashicorp/google"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
google-beta = {
source = "hashicorp/google-beta"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
}
}

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

@@ -17,11 +17,11 @@ terraform {
required_providers {
google = {
source = "hashicorp/google"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
google-beta = {
source = "hashicorp/google-beta"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
}
}

View File

@@ -24,35 +24,30 @@ This example will create a `cloud-config` that uses the module's defaults, creat
```hcl
module "cos-nginx" {
source = "./fabric/modules/cloud-config-container/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

@@ -17,11 +17,11 @@ terraform {
required_providers {
google = {
source = "hashicorp/google"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
google-beta = {
source = "hashicorp/google-beta"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
}
}

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

@@ -17,16 +17,18 @@
IF_NAME=$1
IP_LB=$(ip r show table local | grep "$IF_NAME proto 66" | cut -f 2 -d " ")
# If there's a load balancer for this IF...
if [ ! -z $IP_LB ]
then
IF_NUMBER=$(echo $IF_NAME | sed -e s/eth//)
IF_GW=$(curl http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/$IF_NUMBER/gateway -H "Metadata-Flavor: Google")
IF_IP=$(curl http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/$IF_NUMBER/ip -H "Metadata-Flavor: Google")
IF_NETMASK=$(curl http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/$IF_NUMBER/subnetmask -H "Metadata-Flavor: Google")
IF_IP_PREFIX=$(/var/run/nva/ipprefix_by_netmask.sh $IF_NETMASK)
grep -qxF "$((200 + $IF_NUMBER)) hc-$IF_NAME" /etc/iproute2/rt_tables || echo "$((200 + $IF_NUMBER)) hc-$IF_NAME" >>/etc/iproute2/rt_tables
ip route add $IF_GW src $IF_IP dev $IF_NAME table hc-$IF_NAME
ip route add default via $IF_GW dev $IF_NAME table hc-$IF_NAME
ip rule add from $IP_LB/32 table hc-$IF_NAME
fi
# Sleep while there's no load balancer IP route for this IF
while [ -z $IP_LB ] ; do
sleep 2
IP_LB=$(ip r show table local | grep "$IF_NAME proto 66" | cut -f 2 -d " ")
done
IF_NUMBER=$(echo $IF_NAME | sed -e s/eth//)
IF_GW=$(curl http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/$IF_NUMBER/gateway -H "Metadata-Flavor: Google")
IF_IP=$(curl http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/$IF_NUMBER/ip -H "Metadata-Flavor: Google")
IF_NETMASK=$(curl http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/$IF_NUMBER/subnetmask -H "Metadata-Flavor: Google")
IF_IP_PREFIX=$(/var/run/nva/ipprefix_by_netmask.sh $IF_NETMASK)
grep -qxF "$((200 + $IF_NUMBER)) hc-$IF_NAME" /etc/iproute2/rt_tables || echo "$((200 + $IF_NUMBER)) hc-$IF_NAME" >>/etc/iproute2/rt_tables
ip route add $IF_GW src $IF_IP dev $IF_NAME table hc-$IF_NAME
ip route add default via $IF_GW dev $IF_NAME table hc-$IF_NAME
ip rule add from $IP_LB/32 table hc-$IF_NAME

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

@@ -17,11 +17,11 @@ terraform {
required_providers {
google = {
source = "hashicorp/google"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
google-beta = {
source = "hashicorp/google-beta"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
}
}

View File

@@ -24,39 +24,32 @@ 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"]
clients = ["10.0.0.0/8"]
source = "./fabric/modules/cloud-config-container/squid"
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

@@ -17,11 +17,11 @@ terraform {
required_providers {
google = {
source = "hashicorp/google"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
google-beta = {
source = "hashicorp/google-beta"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
}
}

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

@@ -16,10 +16,10 @@ This deploys a Cloud Function with an HTTP endpoint, using a pre-existing GCS bu
```hcl
module "cf-http" {
source = "./fabric/modules/cloud-function"
project_id = "my-project"
name = "test-cf-http"
bucket_name = "test-cf-bundles"
source = "./fabric/modules/cloud-function"
project_id = "my-project"
name = "test-cf-http"
bucket_name = "test-cf-bundles"
bundle_config = {
source_dir = "fabric/assets/"
output_path = "bundle.zip"
@@ -31,11 +31,11 @@ module "cf-http" {
Analogous example using 2nd generation Cloud Functions
```hcl
module "cf-http" {
source = "./fabric/modules/cloud-function"
v2 = true
project_id = "my-project"
name = "test-cf-http"
bucket_name = "test-cf-bundles"
source = "./fabric/modules/cloud-function"
v2 = true
project_id = "my-project"
name = "test-cf-http"
bucket_name = "test-cf-bundles"
bundle_config = {
source_dir = "fabric/assets/"
output_path = "bundle.zip"
@@ -111,15 +111,15 @@ To allow anonymous access to the function, grant the `roles/cloudfunctions.invok
```hcl
module "cf-http" {
source = "./fabric/modules/cloud-function"
project_id = "my-project"
name = "test-cf-http"
bucket_name = "test-cf-bundles"
source = "./fabric/modules/cloud-function"
project_id = "my-project"
name = "test-cf-http"
bucket_name = "test-cf-bundles"
bundle_config = {
source_dir = "fabric/assets/"
output_path = "bundle.zip"
}
iam = {
iam = {
"roles/cloudfunctions.invoker" = ["allUsers"]
}
}
@@ -132,15 +132,15 @@ You can have the module auto-create the GCS bucket used for deployment via the `
```hcl
module "cf-http" {
source = "./fabric/modules/cloud-function"
project_id = "my-project"
name = "test-cf-http"
bucket_name = "test-cf-bundles"
source = "./fabric/modules/cloud-function"
project_id = "my-project"
name = "test-cf-http"
bucket_name = "test-cf-bundles"
bucket_config = {
lifecycle_delete_age_days = 1
}
bundle_config = {
source_dir = "fabric/assets/"
source_dir = "fabric/assets/"
}
}
# tftest modules=1 resources=3
@@ -152,10 +152,10 @@ To use a custom service account managed by the module, set `service_account_crea
```hcl
module "cf-http" {
source = "./fabric/modules/cloud-function"
project_id = "my-project"
name = "test-cf-http"
bucket_name = "test-cf-bundles"
source = "./fabric/modules/cloud-function"
project_id = "my-project"
name = "test-cf-http"
bucket_name = "test-cf-bundles"
bundle_config = {
source_dir = "fabric/assets/"
output_path = "bundle.zip"
@@ -169,10 +169,10 @@ To use an externally managed service account, pass its email in `service_account
```hcl
module "cf-http" {
source = "./fabric/modules/cloud-function"
project_id = "my-project"
name = "test-cf-http"
bucket_name = "test-cf-bundles"
source = "./fabric/modules/cloud-function"
project_id = "my-project"
name = "test-cf-http"
bucket_name = "test-cf-bundles"
bundle_config = {
source_dir = "fabric/assets/"
output_path = "bundle.zip"
@@ -188,10 +188,10 @@ In order to help prevent `archive_zip.output_md5` from changing cross platform (
```hcl
module "cf-http" {
source = "./fabric/modules/cloud-function"
project_id = "my-project"
name = "test-cf-http"
bucket_name = "test-cf-bundles"
source = "./fabric/modules/cloud-function"
project_id = "my-project"
name = "test-cf-http"
bucket_name = "test-cf-bundles"
bundle_config = {
source_dir = "fabric/assets"
output_path = "bundle.zip"
@@ -207,10 +207,10 @@ This deploys a Cloud Function with an HTTP endpoint, using a pre-existing GCS bu
```hcl
module "cf-http" {
source = "./fabric/modules/cloud-function"
project_id = "my-project"
name = "test-cf-http"
bucket_name = "test-cf-bundles"
source = "./fabric/modules/cloud-function"
project_id = "my-project"
name = "test-cf-http"
bucket_name = "test-cf-bundles"
build_worker_pool = "projects/my-project/locations/europe-west1/workerPools/my_build_worker_pool"
bundle_config = {
source_dir = "fabric/assets"

View File

@@ -17,11 +17,11 @@ terraform {
required_providers {
google = {
source = "hashicorp/google"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
google-beta = {
source = "hashicorp/google-beta"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
}
}

View File

@@ -46,7 +46,7 @@ module "group" {
]
managers = [
"user3@example.com"
]
]
}
# tftest modules=1 resources=5
```

View File

@@ -17,11 +17,11 @@ terraform {
required_providers {
google = {
source = "hashicorp/google"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
google-beta = {
source = "hashicorp/google-beta"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
}
}

View File

@@ -14,18 +14,18 @@ module "cloud_run" {
project_id = "my-project"
name = "hello"
containers = [{
image = "us-docker.pkg.dev/cloudrun/container/hello"
image = "us-docker.pkg.dev/cloudrun/container/hello"
options = {
command = null
args = null
env = {
"VAR1": "VALUE1",
"VAR2": "VALUE2",
env = {
"VAR1" : "VALUE1",
"VAR2" : "VALUE2",
}
env_from = null
}
ports = null
resources = null
ports = null
resources = null
volume_mounts = null
}]
}
@@ -42,18 +42,18 @@ module "cloud_run" {
containers = [{
image = "us-docker.pkg.dev/cloudrun/container/hello"
options = {
command = null
args = null
env = null
env_from = {
"CREDENTIALS": {
command = null
args = null
env = null
env_from = {
"CREDENTIALS" : {
name = "credentials"
key = "1"
key = "1"
}
}
}
ports = null
resources = null
ports = null
resources = null
volume_mounts = null
}]
}
@@ -64,26 +64,26 @@ module "cloud_run" {
```hcl
module "cloud_run" {
source = "./fabric/modules/cloud-run"
project_id = var.project_id
name = "hello"
region = var.region
source = "./fabric/modules/cloud-run"
project_id = var.project_id
name = "hello"
region = var.region
revision_name = "green"
containers = [{
image = "us-docker.pkg.dev/cloudrun/container/hello"
options = null
ports = null
resources = null
image = "us-docker.pkg.dev/cloudrun/container/hello"
options = null
ports = null
resources = null
volume_mounts = {
"credentials": "/credentials"
"credentials" : "/credentials"
}
}]
volumes = [
{
name = "credentials"
name = "credentials"
secret_name = "credentials"
items = [{
key = "1"
key = "1"
path = "v1.txt"
}]
}
@@ -98,9 +98,9 @@ This deploys a Cloud Run service with traffic split between two revisions.
```hcl
module "cloud_run" {
source = "./fabric/modules/cloud-run"
project_id = "my-project"
name = "hello"
source = "./fabric/modules/cloud-run"
project_id = "my-project"
name = "hello"
revision_name = "green"
containers = [{
image = "us-docker.pkg.dev/cloudrun/container/hello"
@@ -110,7 +110,7 @@ module "cloud_run" {
volume_mounts = null
}]
traffic = {
"blue" = 25
"blue" = 25
"green" = 75
}
}
@@ -159,8 +159,8 @@ module "cloud_run" {
}]
audit_log_triggers = [
{
service_name = "cloudresourcemanager.googleapis.com"
method_name = "SetIamPolicy"
service_name = "cloudresourcemanager.googleapis.com"
method_name = "SetIamPolicy"
}
]
}

View File

@@ -17,11 +17,11 @@ terraform {
required_providers {
google = {
source = "hashicorp/google"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
google-beta = {
source = "hashicorp/google-beta"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
}
}

View File

@@ -88,7 +88,7 @@ module "db" {
# generatea password for user1
user1 = null
# assign a password to user2
user2 = "mypassword"
user2 = "mypassword"
}
}
# tftest modules=1 resources=6
@@ -146,27 +146,29 @@ module "db" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [database_version](variables.tf#L49) | Database type and version to create. | <code>string</code> | ✓ | |
| [name](variables.tf#L102) | Name of primary instance. | <code>string</code> | ✓ | |
| [network](variables.tf#L107) | VPC self link where the instances will be deployed. Private Service Networking must be enabled and configured in this VPC. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L122) | The ID of the project where this instances will be created. | <code>string</code> | ✓ | |
| [region](variables.tf#L127) | Region of the primary instance. | <code>string</code> | ✓ | |
| [tier](variables.tf#L147) | The machine type to use for the instances. | <code>string</code> | ✓ | |
| [authorized_networks](variables.tf#L17) | Map of NAME=>CIDR_RANGE to allow to connect to the database(s). | <code>map&#40;string&#41;</code> | | <code>null</code> |
| [availability_type](variables.tf#L23) | Availability type for the primary replica. Either `ZONAL` or `REGIONAL`. | <code>string</code> | | <code>&#34;ZONAL&#34;</code> |
| [backup_configuration](variables.tf#L29) | Backup settings for primary instance. Will be automatically enabled if using MySQL with one or more replicas. | <code title="object&#40;&#123;&#10; enabled &#61; bool&#10; binary_log_enabled &#61; bool&#10; start_time &#61; string&#10; location &#61; string&#10; log_retention_days &#61; number&#10; retention_count &#61; number&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; enabled &#61; false&#10; binary_log_enabled &#61; false&#10; start_time &#61; &#34;23:00&#34;&#10; location &#61; null&#10; log_retention_days &#61; 7&#10; retention_count &#61; 7&#10;&#125;">&#123;&#8230;&#125;</code> |
| [databases](variables.tf#L54) | Databases to create once the primary instance is created. | <code>list&#40;string&#41;</code> | | <code>null</code> |
| [deletion_protection](variables.tf#L60) | Allow terraform to delete instances. | <code>bool</code> | | <code>false</code> |
| [disk_size](variables.tf#L66) | Disk size in GB. Set to null to enable autoresize. | <code>number</code> | | <code>null</code> |
| [disk_type](variables.tf#L72) | The type of data disk: `PD_SSD` or `PD_HDD`. | <code>string</code> | | <code>&#34;PD_SSD&#34;</code> |
| [encryption_key_name](variables.tf#L78) | The full path to the encryption key used for the CMEK disk encryption of the primary instance. | <code>string</code> | | <code>null</code> |
| [flags](variables.tf#L84) | Map FLAG_NAME=>VALUE for database-specific tuning. | <code>map&#40;string&#41;</code> | | <code>null</code> |
| [ipv4_enabled](variables.tf#L90) | Add a public IP address to database instance. | <code>bool</code> | | <code>false</code> |
| [labels](variables.tf#L96) | Labels to be attached to all instances. | <code>map&#40;string&#41;</code> | | <code>null</code> |
| [prefix](variables.tf#L112) | Optional prefix used to generate instance names. | <code>string</code> | | <code>null</code> |
| [replicas](variables.tf#L132) | Map of NAME=> {REGION, KMS_KEY} for additional read replicas. Set to null to disable replica creation. | <code title="map&#40;object&#40;&#123;&#10; region &#61; string&#10; encryption_key_name &#61; string&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [root_password](variables.tf#L141) | Root password of the Cloud SQL instance. Required for MS SQL Server. | <code>string</code> | | <code>null</code> |
| [users](variables.tf#L152) | Map of users to create in the primary instance (and replicated to other replicas) in the format USER=>PASSWORD. For MySQL, anything afterr the first `@` (if persent) will be used as the user's host. Set PASSWORD to null if you want to get an autogenerated password. | <code>map&#40;string&#41;</code> | | <code>null</code> |
| [database_version](variables.tf#L61) | Database type and version to create. | <code>string</code> | ✓ | |
| [name](variables.tf#L114) | Name of primary instance. | <code>string</code> | ✓ | |
| [network](variables.tf#L119) | VPC self link where the instances will be deployed. Private Service Networking must be enabled and configured in this VPC. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L140) | The ID of the project where this instances will be created. | <code>string</code> | ✓ | |
| [region](variables.tf#L145) | Region of the primary instance. | <code>string</code> | ✓ | |
| [tier](variables.tf#L165) | The machine type to use for the instances. | <code>string</code> | ✓ | |
| [allocated_ip_ranges](variables.tf#L17) | (Optional)The name of the allocated ip range for the private ip CloudSQL instance. For example: \"google-managed-services-default\". If set, the instance ip will be created in the allocated range. The range name must comply with RFC 1035. Specifically, the name must be 1-63 characters long and match the regular expression a-z?. | <code title="object&#40;&#123;&#10; primary &#61; optional&#40;string&#41;&#10; replica &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [authorized_networks](variables.tf#L26) | Map of NAME=>CIDR_RANGE to allow to connect to the database(s). | <code>map&#40;string&#41;</code> | | <code>null</code> |
| [availability_type](variables.tf#L32) | Availability type for the primary replica. Either `ZONAL` or `REGIONAL`. | <code>string</code> | | <code>&#34;ZONAL&#34;</code> |
| [backup_configuration](variables.tf#L38) | Backup settings for primary instance. Will be automatically enabled if using MySQL with one or more replicas. | <code title="object&#40;&#123;&#10; enabled &#61; optional&#40;bool, false&#41;&#10; binary_log_enabled &#61; optional&#40;bool, false&#41;&#10; start_time &#61; optional&#40;string, &#34;23:00&#34;&#41;&#10; location &#61; optional&#40;string&#41;&#10; log_retention_days &#61; optional&#40;number, 7&#41;&#10; point_in_time_recovery_enabled &#61; optional&#40;bool&#41;&#10; retention_count &#61; optional&#40;number, 7&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; enabled &#61; false&#10; binary_log_enabled &#61; false&#10; start_time &#61; &#34;23:00&#34;&#10; location &#61; null&#10; log_retention_days &#61; 7&#10; point_in_time_recovery_enabled &#61; null&#10; retention_count &#61; 7&#10;&#125;">&#123;&#8230;&#125;</code> |
| [databases](variables.tf#L66) | Databases to create once the primary instance is created. | <code>list&#40;string&#41;</code> | | <code>null</code> |
| [deletion_protection](variables.tf#L72) | Allow terraform to delete instances. | <code>bool</code> | | <code>false</code> |
| [disk_size](variables.tf#L78) | Disk size in GB. Set to null to enable autoresize. | <code>number</code> | | <code>null</code> |
| [disk_type](variables.tf#L84) | The type of data disk: `PD_SSD` or `PD_HDD`. | <code>string</code> | | <code>&#34;PD_SSD&#34;</code> |
| [encryption_key_name](variables.tf#L90) | The full path to the encryption key used for the CMEK disk encryption of the primary instance. | <code>string</code> | | <code>null</code> |
| [flags](variables.tf#L96) | Map FLAG_NAME=>VALUE for database-specific tuning. | <code>map&#40;string&#41;</code> | | <code>null</code> |
| [ipv4_enabled](variables.tf#L102) | Add a public IP address to database instance. | <code>bool</code> | | <code>false</code> |
| [labels](variables.tf#L108) | Labels to be attached to all instances. | <code>map&#40;string&#41;</code> | | <code>null</code> |
| [postgres_client_certificates](variables.tf#L124) | Map of cert keys connect to the application(s) using public IP. | <code>list&#40;string&#41;</code> | | <code>null</code> |
| [prefix](variables.tf#L130) | Optional prefix used to generate instance names. | <code>string</code> | | <code>null</code> |
| [replicas](variables.tf#L150) | Map of NAME=> {REGION, KMS_KEY} for additional read replicas. Set to null to disable replica creation. | <code title="map&#40;object&#40;&#123;&#10; region &#61; string&#10; encryption_key_name &#61; string&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [root_password](variables.tf#L159) | Root password of the Cloud SQL instance. Required for MS SQL Server. | <code>string</code> | | <code>null</code> |
| [users](variables.tf#L170) | Map of users to create in the primary instance (and replicated to other replicas) in the format USER=>PASSWORD. For MySQL, anything afterr the first `@` (if persent) will be used as the user's host. Set PASSWORD to null if you want to get an autogenerated password. | <code>map&#40;string&#41;</code> | | <code>null</code> |
## Outputs
@@ -181,8 +183,9 @@ module "db" {
| [ips](outputs.tf#L61) | IP addresses of all instances. | |
| [name](outputs.tf#L69) | Name of the primary instance. | |
| [names](outputs.tf#L74) | Names of all instances. | |
| [self_link](outputs.tf#L82) | Self link of the primary instance. | |
| [self_links](outputs.tf#L87) | Self links of all instances. | |
| [user_passwords](outputs.tf#L95) | Map of containing the password of all users created through terraform. | |
| [postgres_client_certificates](outputs.tf#L82) | The CA Certificate used to connect to the SQL Instance via SSL. | |
| [self_link](outputs.tf#L88) | Self link of the primary instance. | |
| [self_links](outputs.tf#L93) | Self links of all instances. | |
| [user_passwords](outputs.tf#L101) | Map of containing the password of all users created through terraform. | ✓ |
<!-- END TFDOC -->

View File

@@ -61,8 +61,9 @@ resource "google_sql_database_instance" "primary" {
user_labels = var.labels
ip_configuration {
ipv4_enabled = var.ipv4_enabled
private_network = var.network
ipv4_enabled = var.ipv4_enabled
private_network = var.network
allocated_ip_range = var.allocated_ip_ranges.primary
dynamic "authorized_networks" {
for_each = var.authorized_networks != null ? var.authorized_networks : {}
iterator = network
@@ -87,6 +88,7 @@ resource "google_sql_database_instance" "primary" {
)
start_time = var.backup_configuration.start_time
location = var.backup_configuration.location
point_in_time_recovery_enabled = var.backup_configuration.point_in_time_recovery_enabled
transaction_log_retention_days = var.backup_configuration.log_retention_days
backup_retention_settings {
retained_backups = var.backup_configuration.retention_count
@@ -126,8 +128,9 @@ resource "google_sql_database_instance" "replicas" {
user_labels = var.labels
ip_configuration {
ipv4_enabled = var.ipv4_enabled
private_network = var.network
ipv4_enabled = var.ipv4_enabled
private_network = var.network
allocated_ip_range = var.allocated_ip_ranges.replica
dynamic "authorized_networks" {
for_each = var.authorized_networks != null ? var.authorized_networks : {}
iterator = network
@@ -175,3 +178,10 @@ resource "google_sql_user" "users" {
host = each.value.host
password = each.value.password
}
resource "google_sql_ssl_cert" "postgres_client_certificates" {
for_each = var.postgres_client_certificates != null ? toset(var.postgres_client_certificates) : toset([])
provider = google-beta
instance = google_sql_database_instance.primary.name
common_name = each.key
}

View File

@@ -79,6 +79,12 @@ output "names" {
}
}
output "postgres_client_certificates" {
description = "The CA Certificate used to connect to the SQL Instance via SSL."
value = google_sql_ssl_cert.postgres_client_certificates
sensitive = true
}
output "self_link" {
description = "Self link of the primary instance."
value = google_sql_database_instance.primary.self_link

View File

@@ -14,6 +14,15 @@
* limitations under the License.
*/
variable "allocated_ip_ranges" {
description = "(Optional)The name of the allocated ip range for the private ip CloudSQL instance. For example: \"google-managed-services-default\". If set, the instance ip will be created in the allocated range. The range name must comply with RFC 1035. Specifically, the name must be 1-63 characters long and match the regular expression a-z?."
type = object({
primary = optional(string)
replica = optional(string)
})
default = {}
nullable = false
}
variable "authorized_networks" {
description = "Map of NAME=>CIDR_RANGE to allow to connect to the database(s)."
type = map(string)
@@ -28,21 +37,24 @@ variable "availability_type" {
variable "backup_configuration" {
description = "Backup settings for primary instance. Will be automatically enabled if using MySQL with one or more replicas."
nullable = false
type = object({
enabled = bool
binary_log_enabled = bool
start_time = string
location = string
log_retention_days = number
retention_count = number
enabled = optional(bool, false)
binary_log_enabled = optional(bool, false)
start_time = optional(string, "23:00")
location = optional(string)
log_retention_days = optional(number, 7)
point_in_time_recovery_enabled = optional(bool)
retention_count = optional(number, 7)
})
default = {
enabled = false
binary_log_enabled = false
start_time = "23:00"
location = null
log_retention_days = 7
retention_count = 7
enabled = false
binary_log_enabled = false
start_time = "23:00"
location = null
log_retention_days = 7
point_in_time_recovery_enabled = null
retention_count = 7
}
}
@@ -109,6 +121,12 @@ variable "network" {
type = string
}
variable "postgres_client_certificates" {
description = "Map of cert keys connect to the application(s) using public IP."
type = list(string)
default = null
}
variable "prefix" {
description = "Optional prefix used to generate instance names."
type = string

View File

@@ -17,11 +17,11 @@ terraform {
required_providers {
google = {
source = "hashicorp/google"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
google-beta = {
source = "hashicorp/google-beta"
version = ">= 4.40.0" # tftest
version = ">= 4.50.0" # tftest
}
}
}

View File

@@ -243,9 +243,9 @@ module "nginx-mig" {
target_size = 3
instance_template = module.nginx-template.template.self_link
update_policy = {
minimal_action = "REPLACE"
type = "PROACTIVE"
min_ready_sec = 30
minimal_action = "REPLACE"
type = "PROACTIVE"
min_ready_sec = 30
max_surge = {
fixed = 1
}
@@ -321,7 +321,7 @@ module "nginx-mig" {
}
}
stateful_disks = {
repd-1 = null
repd-1 = false
}
}
# tftest modules=2 resources=3
@@ -393,8 +393,8 @@ module "nginx-mig" {
stateful_config = {
# name needs to match a MIG instance name
instance-1 = {
minimal_action = "NONE",
most_disruptive_allowed_action = "REPLACE"
minimal_action = "NONE",
most_disruptive_allowed_action = "REPLACE"
preserved_state = {
disks = {
persistent-disk-1 = {
@@ -417,10 +417,10 @@ module "nginx-mig" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [instance_template](variables.tf#L174) | Instance template for the default version. | <code>string</code> | ✓ | |
| [location](variables.tf#L179) | Compute zone or region. | <code>string</code> | ✓ | |
| [name](variables.tf#L184) | Managed group name. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L195) | Project id. | <code>string</code> | ✓ | |
| [instance_template](variables.tf#L177) | Instance template for the default version. | <code>string</code> | ✓ | |
| [location](variables.tf#L182) | Compute zone or region. | <code>string</code> | ✓ | |
| [name](variables.tf#L187) | Managed group name. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L198) | Project id. | <code>string</code> | ✓ | |
| [all_instances_config](variables.tf#L17) | Metadata and labels set to all instances in the group. | <code title="object&#40;&#123;&#10; labels &#61; optional&#40;map&#40;string&#41;&#41;&#10; metadata &#61; optional&#40;map&#40;string&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [auto_healing_policies](variables.tf#L26) | Auto-healing policies for this group. | <code title="object&#40;&#123;&#10; health_check &#61; optional&#40;string&#41;&#10; initial_delay_sec &#61; number&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [autoscaler_config](variables.tf#L35) | Optional autoscaler configuration. | <code title="object&#40;&#123;&#10; max_replicas &#61; number&#10; min_replicas &#61; number&#10; cooldown_period &#61; optional&#40;number&#41;&#10; mode &#61; optional&#40;string&#41; &#35; OFF, ONLY_UP, ON&#10; scaling_control &#61; optional&#40;object&#40;&#123;&#10; down &#61; optional&#40;object&#40;&#123;&#10; max_replicas_fixed &#61; optional&#40;number&#41;&#10; max_replicas_percent &#61; optional&#40;number&#41;&#10; time_window_sec &#61; optional&#40;number&#41;&#10; &#125;&#41;&#41;&#10; in &#61; optional&#40;object&#40;&#123;&#10; max_replicas_fixed &#61; optional&#40;number&#41;&#10; max_replicas_percent &#61; optional&#40;number&#41;&#10; time_window_sec &#61; optional&#40;number&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10; scaling_signals &#61; optional&#40;object&#40;&#123;&#10; cpu_utilization &#61; optional&#40;object&#40;&#123;&#10; target &#61; number&#10; optimize_availability &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#10; load_balancing_utilization &#61; optional&#40;object&#40;&#123;&#10; target &#61; number&#10; &#125;&#41;&#41;&#10; metrics &#61; optional&#40;list&#40;object&#40;&#123;&#10; name &#61; string&#10; type &#61; string &#35; GAUGE, DELTA_PER_SECOND, DELTA_PER_MINUTE&#10; target_value &#61; number&#10; single_instance_assignment &#61; optional&#40;number&#41;&#10; time_series_filter &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#41;&#10; schedules &#61; optional&#40;list&#40;object&#40;&#123;&#10; duration_sec &#61; number&#10; name &#61; string&#10; min_required_replicas &#61; number&#10; cron_schedule &#61; string&#10; description &#61; optional&#40;bool&#41;&#10; timezone &#61; optional&#40;string&#41;&#10; disabled &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
@@ -428,14 +428,14 @@ module "nginx-mig" {
| [description](variables.tf#L89) | Optional description used for all resources managed by this module. | <code>string</code> | | <code>&#34;Terraform managed.&#34;</code> |
| [distribution_policy](variables.tf#L95) | DIstribution policy for regional MIG. | <code title="object&#40;&#123;&#10; target_shape &#61; optional&#40;string&#41;&#10; zones &#61; optional&#40;list&#40;string&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [health_check_config](variables.tf#L104) | Optional auto-created health check configuration, use the output self-link to set it in the auto healing policy. Refer to examples for usage. | <code title="object&#40;&#123;&#10; check_interval_sec &#61; optional&#40;number&#41;&#10; description &#61; optional&#40;string, &#34;Terraform managed.&#34;&#41;&#10; enable_logging &#61; optional&#40;bool, false&#41;&#10; healthy_threshold &#61; optional&#40;number&#41;&#10; timeout_sec &#61; optional&#40;number&#41;&#10; unhealthy_threshold &#61; optional&#40;number&#41;&#10; grpc &#61; optional&#40;object&#40;&#123;&#10; port &#61; optional&#40;number&#41;&#10; port_name &#61; optional&#40;string&#41;&#10; port_specification &#61; optional&#40;string&#41; &#35; USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT&#10; service_name &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; http &#61; optional&#40;object&#40;&#123;&#10; host &#61; optional&#40;string&#41;&#10; port &#61; optional&#40;number&#41;&#10; port_name &#61; optional&#40;string&#41;&#10; port_specification &#61; optional&#40;string&#41; &#35; USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT&#10; proxy_header &#61; optional&#40;string&#41;&#10; request_path &#61; optional&#40;string&#41;&#10; response &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; http2 &#61; optional&#40;object&#40;&#123;&#10; host &#61; optional&#40;string&#41;&#10; port &#61; optional&#40;number&#41;&#10; port_name &#61; optional&#40;string&#41;&#10; port_specification &#61; optional&#40;string&#41; &#35; USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT&#10; proxy_header &#61; optional&#40;string&#41;&#10; request_path &#61; optional&#40;string&#41;&#10; response &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; https &#61; optional&#40;object&#40;&#123;&#10; host &#61; optional&#40;string&#41;&#10; port &#61; optional&#40;number&#41;&#10; port_name &#61; optional&#40;string&#41;&#10; port_specification &#61; optional&#40;string&#41; &#35; USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT&#10; proxy_header &#61; optional&#40;string&#41;&#10; request_path &#61; optional&#40;string&#41;&#10; response &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; tcp &#61; optional&#40;object&#40;&#123;&#10; port &#61; optional&#40;number&#41;&#10; port_name &#61; optional&#40;string&#41;&#10; port_specification &#61; optional&#40;string&#41; &#35; USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT&#10; proxy_header &#61; optional&#40;string&#41;&#10; request &#61; optional&#40;string&#41;&#10; response &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; ssl &#61; optional&#40;object&#40;&#123;&#10; port &#61; optional&#40;number&#41;&#10; port_name &#61; optional&#40;string&#41;&#10; port_specification &#61; optional&#40;string&#41; &#35; USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT&#10; proxy_header &#61; optional&#40;string&#41;&#10; request &#61; optional&#40;string&#41;&#10; response &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [named_ports](variables.tf#L189) | Named ports. | <code>map&#40;number&#41;</code> | | <code>null</code> |
| [stateful_config](variables.tf#L200) | Stateful configuration for individual instances. | <code title="map&#40;object&#40;&#123;&#10; minimal_action &#61; optional&#40;string&#41;&#10; most_disruptive_action &#61; optional&#40;string&#41;&#10; remove_state_on_destroy &#61; optional&#40;bool&#41;&#10; preserved_state &#61; optional&#40;object&#40;&#123;&#10; disks &#61; optional&#40;map&#40;object&#40;&#123;&#10; source &#61; string&#10; delete_on_instance_deletion &#61; optional&#40;bool&#41;&#10; read_only &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#41;&#10; metadata &#61; optional&#40;map&#40;string&#41;&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [stateful_disks](variables.tf#L219) | Stateful disk configuration applied at the MIG level to all instances, in device name => on permanent instance delete rule as boolean. | <code>map&#40;bool&#41;</code> | | <code>&#123;&#125;</code> |
| [target_pools](variables.tf#L226) | Optional list of URLs for target pools to which new instances in the group are added. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [target_size](variables.tf#L232) | Group target size, leave null when using an autoscaler. | <code>number</code> | | <code>null</code> |
| [update_policy](variables.tf#L238) | Update policy. Minimal action and type are required. | <code title="object&#40;&#123;&#10; minimal_action &#61; string&#10; type &#61; string&#10; max_surge &#61; optional&#40;object&#40;&#123;&#10; fixed &#61; optional&#40;number&#41;&#10; percent &#61; optional&#40;number&#41;&#10; &#125;&#41;&#41;&#10; max_unavailable &#61; optional&#40;object&#40;&#123;&#10; fixed &#61; optional&#40;number&#41;&#10; percent &#61; optional&#40;number&#41;&#10; &#125;&#41;&#41;&#10; min_ready_sec &#61; optional&#40;number&#41;&#10; most_disruptive_action &#61; optional&#40;string&#41;&#10; regional_redistribution_type &#61; optional&#40;string&#41;&#10; replacement_method &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [versions](variables.tf#L259) | Additional application versions, target_size is optional. | <code title="map&#40;object&#40;&#123;&#10; instance_template &#61; string&#10; target_size &#61; optional&#40;object&#40;&#123;&#10; fixed &#61; optional&#40;number&#41;&#10; percent &#61; optional&#40;number&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [wait_for_instances](variables.tf#L272) | Wait for all instances to be created/updated before returning. | <code title="object&#40;&#123;&#10; enabled &#61; bool&#10; status &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [named_ports](variables.tf#L192) | Named ports. | <code>map&#40;number&#41;</code> | | <code>null</code> |
| [stateful_config](variables.tf#L203) | Stateful configuration for individual instances. | <code title="map&#40;object&#40;&#123;&#10; minimal_action &#61; optional&#40;string&#41;&#10; most_disruptive_action &#61; optional&#40;string&#41;&#10; remove_state_on_destroy &#61; optional&#40;bool&#41;&#10; preserved_state &#61; optional&#40;object&#40;&#123;&#10; disks &#61; optional&#40;map&#40;object&#40;&#123;&#10; source &#61; string&#10; delete_on_instance_deletion &#61; optional&#40;bool&#41;&#10; read_only &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#41;&#10; metadata &#61; optional&#40;map&#40;string&#41;&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [stateful_disks](variables.tf#L222) | Stateful disk configuration applied at the MIG level to all instances, in device name => on permanent instance delete rule as boolean. | <code>map&#40;bool&#41;</code> | | <code>&#123;&#125;</code> |
| [target_pools](variables.tf#L229) | Optional list of URLs for target pools to which new instances in the group are added. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [target_size](variables.tf#L235) | Group target size, leave null when using an autoscaler. | <code>number</code> | | <code>null</code> |
| [update_policy](variables.tf#L241) | Update policy. Minimal action and type are required. | <code title="object&#40;&#123;&#10; minimal_action &#61; string&#10; type &#61; string&#10; max_surge &#61; optional&#40;object&#40;&#123;&#10; fixed &#61; optional&#40;number&#41;&#10; percent &#61; optional&#40;number&#41;&#10; &#125;&#41;&#41;&#10; max_unavailable &#61; optional&#40;object&#40;&#123;&#10; fixed &#61; optional&#40;number&#41;&#10; percent &#61; optional&#40;number&#41;&#10; &#125;&#41;&#41;&#10; min_ready_sec &#61; optional&#40;number&#41;&#10; most_disruptive_action &#61; optional&#40;string&#41;&#10; regional_redistribution_type &#61; optional&#40;string&#41;&#10; replacement_method &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [versions](variables.tf#L262) | Additional application versions, target_size is optional. | <code title="map&#40;object&#40;&#123;&#10; instance_template &#61; string&#10; target_size &#61; optional&#40;object&#40;&#123;&#10; fixed &#61; optional&#40;number&#41;&#10; percent &#61; optional&#40;number&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [wait_for_instances](variables.tf#L275) | Wait for all instances to be created/updated before returning. | <code title="object&#40;&#123;&#10; enabled &#61; bool&#10; status &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
## Outputs

View File

@@ -71,7 +71,7 @@ resource "google_compute_instance_group_manager" "default" {
for_each = var.stateful_disks
content {
device_name = stateful_disk.key
delete_rule = stateful_disk.value
delete_rule = stateful_disk.value ? "ON_PERMANENT_INSTANCE_DELETION" : "NEVER"
}
}
@@ -161,7 +161,7 @@ resource "google_compute_region_instance_group_manager" "default" {
for_each = var.stateful_disks
content {
device_name = stateful_disk.key
delete_rule = stateful_disk.value
delete_rule = stateful_disk.value ? "ON_PERMANENT_INSTANCE_DELETION" : "NEVER"
}
}

View File

@@ -165,7 +165,10 @@ variable "health_check_config" {
condition = (
(try(var.health_check_config.grpc, null) == null ? 0 : 1) +
(try(var.health_check_config.http, null) == null ? 0 : 1) +
(try(var.health_check_config.tcp, null) == null ? 0 : 1) <= 1
(try(var.health_check_config.http2, null) == null ? 0 : 1) +
(try(var.health_check_config.https, null) == null ? 0 : 1) +
(try(var.health_check_config.tcp, null) == null ? 0 : 1) +
(try(var.health_check_config.ssl, null) == null ? 0 : 1) <= 1
)
error_message = "Only one health check type can be configured at a time."
}

Some files were not shown because too many files have changed in this diff Show More