Merge branch 'master' into projects-ds-new-version
This commit is contained in:
@@ -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 -->
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 -->
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(object({ region = string service_attachment = string }))">map(object({…}))</code> | | <code>null</code> |
|
||||
| [envgroups](variables.tf#L26) | Environment groups (NAME => [HOSTNAMES]). | <code>map(list(string))</code> | | <code>null</code> |
|
||||
| [environments](variables.tf#L32) | Environments. | <code title="map(object({ display_name = optional(string) description = optional(string, "Terraform-managed") node_config = optional(object({ min_node_count = optional(number) max_node_count = optional(number) })) iam = optional(map(list(string))) envgroups = list(string) }))">map(object({…}))</code> | | <code>null</code> |
|
||||
| [instances](variables.tf#L47) | Instances. | <code title="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)) }))">map(object({…}))</code> | | <code>null</code> |
|
||||
| [organization](variables.tf#L61) | Apigee organization. If set to null the organization must already exist. | <code title="object({ display_name = optional(string) description = optional(string, "Terraform-managed") authorized_network = optional(string) runtime_type = optional(string, "CLOUD") billing_type = optional(string) database_encryption_key = optional(string) analytics_region = optional(string, "europe-west1") })">object({…})</code> | | <code>null</code> |
|
||||
| [environments](variables.tf#L32) | Environments. | <code title="map(object({ 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) })) iam = optional(map(list(string))) envgroups = list(string) }))">map(object({…}))</code> | | <code>null</code> |
|
||||
| [instances](variables.tf#L49) | Instances. | <code title="map(object({ 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)) }))">map(object({…}))</code> | | <code>null</code> |
|
||||
| [organization](variables.tf#L64) | Apigee organization. If set to null the organization must already exist. | <code title="object({ display_name = optional(string) description = optional(string, "Terraform-managed") authorized_network = optional(string) runtime_type = optional(string, "CLOUD") billing_type = optional(string) database_encryption_key = optional(string) analytics_region = optional(string, "europe-west1") })">object({…})</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 -->
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(object({ role = string type = string }))">map(object({…}))</code> | | <code>{}</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(string)</code> | | <code>{}</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(list(string))</code> | | <code>{}</code> |
|
||||
| [labels](variables.tf#L74) | Dataset labels. | <code>map(string)</code> | | <code>{}</code> |
|
||||
| [location](variables.tf#L80) | Dataset location. | <code>string</code> | | <code>"EU"</code> |
|
||||
| [options](variables.tf#L86) | Dataset options. | <code title="object({ default_table_expiration_ms = number default_partition_expiration_ms = number delete_contents_on_destroy = bool })">object({…})</code> | | <code title="{ default_table_expiration_ms = null default_partition_expiration_ms = null delete_contents_on_destroy = false }">{…}</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(object({ friendly_name = string labels = map(string) options = object({ clustering = list(string) encryption_key = string expiration_time = number }) partitioning = object({ field = string range = object({ end = number interval = number start = number }) time = object({ expiration_ms = number type = string }) }) schema = string deletion_protection = bool }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [views](variables.tf#L133) | View definitions. | <code title="map(object({ friendly_name = string labels = map(string) query = string use_legacy_sql = bool deletion_protection = bool }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [options](variables.tf#L86) | Dataset options. | <code title="object({ 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) })">object({…})</code> | | <code>{}</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(object({ friendly_name = string labels = map(string) options = object({ clustering = list(string) encryption_key = string expiration_time = number }) partitioning = object({ field = string range = object({ end = number interval = number start = number }) time = object({ expiration_ms = number type = string }) }) schema = string deletion_protection = bool }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [views](variables.tf#L130) | View definitions. | <code title="map(object({ friendly_name = string labels = map(string) query = string use_legacy_sql = bool deletion_protection = bool }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
|
||||
## Outputs
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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" {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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({ min_nodes = number max_nodes = number cpu_target = number, storage_target = optional(number, null) })">object({…})</code> | | <code>null</code> |
|
||||
| [cluster_id](variables.tf#L28) | The ID of the Cloud Bigtable cluster. | <code>string</code> | | <code>"europe-west1"</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(list(string))</code> | | <code>{}</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>"SSD"</code> |
|
||||
| [table_options_defaults](variables.tf#L78) | Default option of tables created in the BigTable instance. | <code title="object({ split_keys = list(string) column_family = string })">object({…})</code> | | <code title="{ split_keys = [] column_family = null }">{…}</code> |
|
||||
| [tables](variables.tf#L90) | Tables to be created in the BigTable instance, options can be null. | <code title="map(object({ split_keys = list(string) column_family = string }))">map(object({…}))</code> | | <code>{}</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(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) })) }))">map(object({…}))</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({ min_nodes = number max_nodes = number cpu_target = number storage_target = optional(number) })">object({…})</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({ deletion_policy = optional(string) gc_rules = optional(string) mode = optional(string) max_age = optional(string) max_version = optional(string) })">object({…})</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(list(string))</code> | | <code>{}</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(object({ 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) })), {}) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
|
||||
## Outputs
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Instance Configuration via `cloud-config`
|
||||
|
||||
This set of modules creates specialized [cloud-config](https://cloud.google.com/container-optimized-os/docs/how-to/run-container-instance#starting_a_docker_container_via_cloud-config) configurations, which are designed for use with [Container Optimized OS](https://cloud.google.com/container-optimized-os/docs) (the [onprem module](./onprem/) is the only exception) but can also be used as a basis for other image types or cloud providers.
|
||||
This set of modules creates specialized [cloud-config](https://cloud.google.com/container-optimized-os/docs/how-to/run-container-instance#starting_a_docker_container_via_cloud-config) configurations, which are designed for use with [Container Optimized OS](https://cloud.google.com/container-optimized-os/docs) (the onprem module is the only exception) but can also be used as a basis for other image types or cloud providers.
|
||||
|
||||
These modules are designed for several use cases:
|
||||
|
||||
@@ -14,8 +14,8 @@ These modules are designed for several use cases:
|
||||
- [CoreDNS](./coredns)
|
||||
- [MySQL](./mysql)
|
||||
- [Nginx](./nginx)
|
||||
- [On-prem in Docker](./onprem)
|
||||
- [Squid forward proxy](./squid)
|
||||
- On-prem in Docker (*needs fixing*)
|
||||
|
||||
## Using the modules
|
||||
|
||||
@@ -23,8 +23,6 @@ All modules are designed to be as lightweight as possible, so that specialized m
|
||||
|
||||
To use the modules with instances or instance templates, simply set use their `cloud_config` output for the `user-data` metadata. When updating the metadata after a variable change remember to manually restart the instances that use a module's output, or the changes won't effect the running system.
|
||||
|
||||
For convenience when developing or prototyping infrastructure, an optional test instance is included in all modules. If it's not needed, the linked `*instance.tf` files can be removed from the modules without harm.
|
||||
|
||||
## TODO
|
||||
|
||||
- [ ] convert all `xxx_config` variables to use file content instead of path
|
||||
|
||||
@@ -10,18 +10,14 @@ The emulated on-premises infrastructure is composed of:
|
||||
- an Nginx container serving a simple static web page
|
||||
- a [generic Linux container](./docker-images/toolbox) used as a jump host inside the on-premises network
|
||||
|
||||
A [complete scenario using this module](../../../blueprints/networking/onprem-google-access-dns) is available in the networking blueprints.
|
||||
A complete scenario using this module is available in the networking blueprints.
|
||||
|
||||
The module renders the generated cloud config in the `cloud_config` output, to be used in instances or instance templates via the `user-data` metadata.
|
||||
|
||||
For convenience during development or for simple use cases, the module can optionally manage a single instance via the `test_instance` variable. If the instance is not needed the `instance*tf` files can be safely removed. Refer to the [top-level README](../README.md) for more details on the included instance.
|
||||
|
||||
## Examples
|
||||
|
||||
### Static VPN
|
||||
|
||||
The test instance is optional, as described above.
|
||||
|
||||
```hcl
|
||||
module "cloud-vpn" {
|
||||
source = "./fabric/modules/net-vpn-static"
|
||||
@@ -32,29 +28,43 @@ module "cloud-vpn" {
|
||||
remote_ranges = ["192.168.192.0/24"]
|
||||
tunnels = {
|
||||
remote-0 = {
|
||||
peer_ip = module.on-prem.external_address
|
||||
peer_ip = module.vm.external_ip
|
||||
traffic_selectors = { local = ["0.0.0.0/0"], remote = null }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module "on-prem" {
|
||||
source = "./fabric/modules/cos-container/on-prem"
|
||||
name = "onprem"
|
||||
source = "./fabric/modules/cloud-config-container/onprem"
|
||||
vpn_config = {
|
||||
type = "static"
|
||||
peer_ip = module.cloud-vpn.address
|
||||
shared_secret = module.cloud-vpn.random_secret
|
||||
}
|
||||
test_instance = {
|
||||
project_id = "my-project"
|
||||
zone = "europe-west1-b"
|
||||
name = "cos-coredns"
|
||||
type = "f1-micro"
|
||||
network = "default"
|
||||
subnetwork = "https://www.googleapis.com/compute/v1/projects/my-project/regions/europe-west1/subnetworks/my-subnet"
|
||||
}
|
||||
}
|
||||
|
||||
module "vm" {
|
||||
source = "./fabric/modules/compute-vm"
|
||||
project_id = "my-project"
|
||||
zone = "europe-west8-b"
|
||||
name = "cos-nginx-tls"
|
||||
network_interfaces = [{
|
||||
nat = true
|
||||
network = "default"
|
||||
subnetwork = "gce"
|
||||
}]
|
||||
metadata = {
|
||||
user-data = module.on-prem.cloud_config
|
||||
google-logging-enabled = true
|
||||
}
|
||||
boot_disk = {
|
||||
image = "projects/cos-cloud/global/images/family/cos-stable"
|
||||
type = "pd-ssd"
|
||||
size = 10
|
||||
}
|
||||
tags = ["ssh"]
|
||||
}
|
||||
# tftest skip
|
||||
```
|
||||
<!-- BEGIN TFDOC -->
|
||||
|
||||
@@ -62,12 +72,10 @@ module "on-prem" {
|
||||
|
||||
| name | description | type | required | default |
|
||||
|---|---|:---:|:---:|:---:|
|
||||
| [vpn_config](variables.tf#L35) | VPN configuration, type must be one of 'dynamic' or 'static'. | <code title="object({ peer_ip = string shared_secret = string type = string peer_ip2 = string shared_secret2 = string })">object({…})</code> | ✓ | |
|
||||
| [vpn_config](variables.tf#L35) | VPN configuration, type must be one of 'dynamic' or 'static'. | <code title="object({ peer_ip = string shared_secret = string type = optional(string, "static") peer_ip2 = optional(string) shared_secret2 = optional(string) })">object({…})</code> | ✓ | |
|
||||
| [config_variables](variables.tf#L17) | Additional variables used to render the cloud-config and CoreDNS templates. | <code>map(any)</code> | | <code>{}</code> |
|
||||
| [coredns_config](variables.tf#L23) | CoreDNS configuration path, if null default will be used. | <code>string</code> | | <code>null</code> |
|
||||
| [local_ip_cidr_range](variables.tf#L29) | IP CIDR range used for the Docker onprem network. | <code>string</code> | | <code>"192.168.192.0/24"</code> |
|
||||
| [test_instance](variables-instance.tf#L17) | Test/development instance attributes, leave null to skip creation. | <code title="object({ project_id = string zone = string name = string type = string network = string subnetwork = string })">object({…})</code> | | <code>null</code> |
|
||||
| [test_instance_defaults](variables-instance.tf#L30) | Test/development instance defaults used for optional configuration. If image is null, COS stable will be used. | <code title="object({ disks = map(object({ read_only = bool size = number })) image = string metadata = map(string) nat = bool service_account_roles = list(string) tags = list(string) })">object({…})</code> | | <code title="{ disks = {} image = null metadata = {} nat = false service_account_roles = [ "roles/logging.logWriter", "roles/monitoring.metricWriter" ] tags = ["ssh"] }">{…}</code> |
|
||||
| [vpn_dynamic_config](variables.tf#L46) | BGP configuration for dynamic VPN, ignored if VPN type is 'static'. | <code title="object({ local_bgp_asn = number local_bgp_address = string peer_bgp_asn = number peer_bgp_address = string local_bgp_asn2 = number local_bgp_address2 = string peer_bgp_asn2 = number peer_bgp_address2 = string })">object({…})</code> | | <code title="{ local_bgp_asn = 64514 local_bgp_address = "169.254.1.2" peer_bgp_asn = 64513 peer_bgp_address = "169.254.1.1" local_bgp_asn2 = 64514 local_bgp_address2 = "169.254.2.2" peer_bgp_asn2 = 64520 peer_bgp_address2 = "169.254.2.1" }">{…}</code> |
|
||||
| [vpn_static_ranges](variables.tf#L70) | Remote CIDR ranges for static VPN, ignored if VPN type is 'dynamic'. | <code>list(string)</code> | | <code>["10.0.0.0/8"]</code> |
|
||||
|
||||
@@ -76,7 +84,5 @@ module "on-prem" {
|
||||
| name | description | sensitive |
|
||||
|---|---|:---:|
|
||||
| [cloud_config](outputs.tf#L17) | Rendered cloud-config file to be passed as user-data instance metadata. | |
|
||||
| [test_instance](outputs-instance.tf#L17) | Optional test instance name and address. | |
|
||||
|
||||
<!-- END TFDOC -->
|
||||
|
||||
@@ -37,9 +37,9 @@ variable "vpn_config" {
|
||||
type = object({
|
||||
peer_ip = string
|
||||
shared_secret = string
|
||||
type = string
|
||||
peer_ip2 = string
|
||||
shared_secret2 = string
|
||||
type = optional(string, "static")
|
||||
peer_ip2 = optional(string)
|
||||
shared_secret2 = optional(string)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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({ owner = string permissions = string })">object({…})</code> | | <code title="{ owner = "root" permissions = "0644" }">{…}</code> |
|
||||
| [files](variables.tf#L47) | Map of extra files to create on the instance, path as key. Owner and permissions will use defaults if null. | <code title="map(object({ content = string owner = string permissions = string }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [test_instance](variables-instance.tf#L17) | Test/development instance attributes, leave null to skip creation. | <code title="object({ project_id = string zone = string name = string type = string network = string subnetwork = string })">object({…})</code> | | <code>null</code> |
|
||||
| [test_instance_defaults](variables-instance.tf#L30) | Test/development instance defaults used for optional configuration. If image is null, COS stable will be used. | <code title="object({ disks = map(object({ read_only = bool size = number })) image = string metadata = map(string) nat = bool service_account_roles = list(string) tags = list(string) })">object({…})</code> | | <code title="{ disks = {} image = null metadata = {} nat = false service_account_roles = [ "roles/logging.logWriter", "roles/monitoring.metricWriter" ] tags = ["ssh"] }">{…}</code> |
|
||||
|
||||
## Outputs
|
||||
|
||||
| name | description | sensitive |
|
||||
|---|---|:---:|
|
||||
| [cloud_config](outputs.tf#L17) | Rendered cloud-config file to be passed as user-data instance metadata. | |
|
||||
| [test_instance](outputs-instance.tf#L17) | Optional test instance name and address. | |
|
||||
|
||||
<!-- END TFDOC -->
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
../instance.tf
|
||||
@@ -1 +0,0 @@
|
||||
../outputs-instance.tf
|
||||
@@ -1 +0,0 @@
|
||||
../variables-instance.tf
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 -->
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 -->
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
/**
|
||||
* Copyright 2022 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
resource "google_service_account" "default" {
|
||||
count = var.test_instance == null ? 0 : 1
|
||||
project = var.test_instance.project_id
|
||||
account_id = "fabric-container-${var.test_instance.name}"
|
||||
display_name = "Managed by the cos Terraform module."
|
||||
}
|
||||
|
||||
resource "google_project_iam_member" "default" {
|
||||
for_each = (
|
||||
var.test_instance == null
|
||||
? toset([])
|
||||
: toset(var.test_instance_defaults.service_account_roles)
|
||||
)
|
||||
project = var.test_instance.project_id
|
||||
role = each.value
|
||||
member = "serviceAccount:${google_service_account.default[0].email}"
|
||||
}
|
||||
|
||||
resource "google_compute_disk" "disks" {
|
||||
for_each = (
|
||||
var.test_instance == null
|
||||
? {}
|
||||
: var.test_instance_defaults.disks
|
||||
)
|
||||
project = var.test_instance.project_id
|
||||
zone = var.test_instance.zone
|
||||
name = each.key
|
||||
type = "pd-ssd"
|
||||
size = each.value.size
|
||||
}
|
||||
|
||||
resource "google_compute_instance" "default" {
|
||||
count = var.test_instance == null ? 0 : 1
|
||||
project = var.test_instance.project_id
|
||||
zone = var.test_instance.zone
|
||||
name = var.test_instance.name
|
||||
description = "Managed by the cos Terraform module."
|
||||
tags = var.test_instance_defaults.tags
|
||||
machine_type = (
|
||||
var.test_instance.type == null ? "f1-micro" : var.test_instance.type
|
||||
)
|
||||
metadata = merge(var.test_instance_defaults.metadata, {
|
||||
user-data = local.cloud_config
|
||||
})
|
||||
|
||||
dynamic "attached_disk" {
|
||||
for_each = var.test_instance_defaults.disks
|
||||
iterator = disk
|
||||
content {
|
||||
device_name = disk.key
|
||||
mode = disk.value.read_only ? "READ_ONLY" : "READ_WRITE"
|
||||
source = google_compute_disk.disks[disk.key].name
|
||||
}
|
||||
}
|
||||
|
||||
boot_disk {
|
||||
initialize_params {
|
||||
type = "pd-ssd"
|
||||
image = (
|
||||
var.test_instance_defaults.image == null
|
||||
? "projects/cos-cloud/global/images/family/cos-stable"
|
||||
: var.test_instance_defaults.image
|
||||
)
|
||||
size = 10
|
||||
}
|
||||
}
|
||||
|
||||
network_interface {
|
||||
network = var.test_instance.network
|
||||
subnetwork = var.test_instance.subnetwork
|
||||
dynamic "access_config" {
|
||||
for_each = var.test_instance_defaults.nat ? [""] : []
|
||||
iterator = config
|
||||
content {
|
||||
nat_ip = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
service_account {
|
||||
email = google_service_account.default[0].email
|
||||
scopes = ["https://www.googleapis.com/auth/cloud-platform"]
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,18 +26,31 @@ This example will create a `cloud-config` that uses the container's default conf
|
||||
|
||||
```hcl
|
||||
module "cos-mysql" {
|
||||
source = "./fabric/modules/cos-container/mysql"
|
||||
source = "./fabric/modules/cloud-config-container/mysql"
|
||||
mysql_password = "foo"
|
||||
}
|
||||
|
||||
# use it as metadata in a compute instance or template
|
||||
module "vm-mysql" {
|
||||
source = "./fabric/modules/compute-vm"
|
||||
module "vm" {
|
||||
source = "./fabric/modules/compute-vm"
|
||||
project_id = "my-project"
|
||||
zone = "europe-west8-b"
|
||||
name = "cos-mysql"
|
||||
network_interfaces = [{
|
||||
network = "default"
|
||||
subnetwork = "gce"
|
||||
}]
|
||||
metadata = {
|
||||
user-data = module.cos-mysql.cloud_config
|
||||
google-logging-enabled = true
|
||||
}
|
||||
boot_disk = {
|
||||
image = "projects/cos-cloud/global/images/family/cos-stable"
|
||||
type = "pd-ssd"
|
||||
size = 10
|
||||
}
|
||||
tags = ["mysql", "ssh"]
|
||||
}
|
||||
# tftest modules=1 resources=1
|
||||
```
|
||||
|
||||
### Custom MySQL configuration and KMS encrypted password
|
||||
@@ -46,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({ project_id = string keyring = string location = string key = string })">object({…})</code> | | <code>null</code> |
|
||||
| [mysql_config](variables.tf#L46) | MySQL configuration file content, if null container default will be used. | <code>string</code> | | <code>null</code> |
|
||||
| [mysql_data_disk](variables.tf#L52) | MySQL data disk name in /dev/disk/by-id/ including the google- prefix. If null the boot disk will be used for data. | <code>string</code> | | <code>null</code> |
|
||||
| [test_instance](variables-instance.tf#L17) | Test/development instance attributes, leave null to skip creation. | <code title="object({ project_id = string zone = string name = string type = string network = string subnetwork = string })">object({…})</code> | | <code>null</code> |
|
||||
| [test_instance_defaults](variables-instance.tf#L30) | Test/development instance defaults used for optional configuration. If image is null, COS stable will be used. | <code title="object({ disks = map(object({ read_only = bool size = number })) image = string metadata = map(string) nat = bool service_account_roles = list(string) tags = list(string) })">object({…})</code> | | <code title="{ disks = {} image = null metadata = {} nat = false service_account_roles = [ "roles/logging.logWriter", "roles/monitoring.metricWriter" ] tags = ["ssh"] }">{…}</code> |
|
||||
|
||||
## Outputs
|
||||
|
||||
| name | description | sensitive |
|
||||
|---|---|:---:|
|
||||
| [cloud_config](outputs.tf#L17) | Rendered cloud-config file to be passed as user-data instance metadata. | |
|
||||
| [test_instance](outputs-instance.tf#L17) | Optional test instance name and address. | |
|
||||
|
||||
<!-- END TFDOC -->
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
../instance.tf
|
||||
@@ -1 +0,0 @@
|
||||
../outputs-instance.tf
|
||||
@@ -1 +0,0 @@
|
||||
../variables-instance.tf
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,48 +1,37 @@
|
||||
# Containerized Nginx with self-signed TLS on Container Optimized OS
|
||||
|
||||
This module manages a `cloud-config` configuration that starts a containerized Nginx with a self-signed TLS cert on Container Optimized OS.
|
||||
This can be useful if you need quickly a VM or instance group answering HTTPS for prototyping.
|
||||
This module manages a `cloud-config` configuration that starts a containerized Nginx with a self-signed TLS cert on Container Optimized OS. This can be useful if you need quickly a VM or instance group answering HTTPS for prototyping.
|
||||
|
||||
The generated cloud config is rendered in the `cloud_config` output, and is meant to be used in instances or instance templates via the `user-data` metadata.
|
||||
|
||||
This module depends on the [`cos-generic-metadata` module](../cos-generic-metadata) being in the parent folder. If you change its location be sure to adjust the `source` attribute in `main.tf`.
|
||||
|
||||
## Examples
|
||||
|
||||
### Default configuration
|
||||
## Example
|
||||
|
||||
```hcl
|
||||
# Nginx with self-signed TLS config
|
||||
module "cos-nginx-tls" {
|
||||
source = "./fabric/modules/cloud-config-container/nginx-tls"
|
||||
}
|
||||
|
||||
# COS VM
|
||||
module "vm-nginx-tls" {
|
||||
source = "./fabric/modules/compute-vm"
|
||||
project_id = local.project_id
|
||||
zone = local.zone
|
||||
project_id = "my-project"
|
||||
zone = "europe-west8-b"
|
||||
name = "cos-nginx-tls"
|
||||
network_interfaces = [{
|
||||
network = local.vpc.self_link,
|
||||
subnetwork = local.vpc.subnet_self_link,
|
||||
nat = false,
|
||||
addresses = null
|
||||
network = "default"
|
||||
subnetwork = "gce"
|
||||
}]
|
||||
|
||||
metadata = {
|
||||
user-data = module.cos-nginx-tls.cloud_config
|
||||
google-logging-enabled = true
|
||||
}
|
||||
|
||||
boot_disk = {
|
||||
image = "projects/cos-cloud/global/images/family/cos-stable"
|
||||
type = "pd-ssd"
|
||||
size = 10
|
||||
}
|
||||
|
||||
service_account_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
|
||||
tags = ["http-server", "https-server", "ssh"]
|
||||
}
|
||||
# tftest modules=1 resources=1
|
||||
```
|
||||
<!-- BEGIN TFDOC -->
|
||||
|
||||
@@ -50,11 +39,9 @@ module "vm-nginx-tls" {
|
||||
|
||||
| name | description | type | required | default |
|
||||
|---|---|:---:|:---:|:---:|
|
||||
| [files](variables.tf#L17) | Map of extra files to create on the instance, path as key. Owner and permissions will use defaults if null. | <code title="map(object({ content = string owner = string permissions = string }))">map(object({…}))</code> | | <code>null</code> |
|
||||
| [nginx_image](variables.tf#L27) | Nginx container image to use. | <code>string</code> | | <code>"nginx:1.23.1"</code> |
|
||||
| [runcmd_post](variables.tf#L33) | Extra commands to run after starting nginx. | <code>list(string)</code> | | <code>[]</code> |
|
||||
| [runcmd_pre](variables.tf#L39) | Extra commands to run before starting nginx. | <code>list(string)</code> | | <code>[]</code> |
|
||||
| [users](variables.tf#L45) | Additional list of usernames to be created. | <code title="list(object({ username = string, uid = number, }))">list(object({…}))</code> | | <code title="[ ]">[…]</code> |
|
||||
| [files](variables.tf#L17) | Map of extra files to create on the instance, path as key. Owner and permissions will use defaults if null. | <code title="map(object({ content = string owner = optional(string, "root") permissions = optional(string, "0644") }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [hello](variables.tf#L28) | Behave like the nginx hello image by returning plain text informative responses. | <code>bool</code> | | <code>true</code> |
|
||||
| [image](variables.tf#L35) | Nginx container image to use. | <code>string</code> | | <code>"nginx:1.23.1"</code> |
|
||||
|
||||
## Outputs
|
||||
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
#cloud-config
|
||||
|
||||
# Copyright 2022 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
users:
|
||||
- name: nginx
|
||||
uid: 2000
|
||||
|
||||
write_files:
|
||||
- path: /var/lib/docker/daemon.json
|
||||
permissions: "0644"
|
||||
owner: root
|
||||
content: |
|
||||
{
|
||||
"live-restore": true,
|
||||
"storage-driver": "overlay2",
|
||||
"log-opts": {
|
||||
"max-size": "1024m"
|
||||
}
|
||||
}
|
||||
# nginx container service
|
||||
- path: /etc/systemd/system/nginx.service
|
||||
permissions: "0644"
|
||||
owner: root
|
||||
content: |
|
||||
[Unit]
|
||||
Description=Start nginx container
|
||||
After=gcr-online.target docker.socket
|
||||
Wants=gcr-online.target docker.socket docker-events-collector.service
|
||||
[Service]
|
||||
Environment="HOME=/home/nginx"
|
||||
ExecStart=/usr/bin/docker run --rm --name=nginx \
|
||||
--network host --pid host \
|
||||
-v /etc/nginx/conf.d:/etc/nginx/conf.d \
|
||||
-v /etc/ssl:/etc/ssl \
|
||||
${image}
|
||||
ExecStop=/usr/bin/docker stop nginx
|
||||
%{ for k, v in files ~}
|
||||
- path: ${k}
|
||||
owner: ${v.owner}
|
||||
permissions: "${v.permissions}"
|
||||
content: |
|
||||
${indent(6, v.content)}
|
||||
%{ endfor ~}
|
||||
|
||||
runcmd:
|
||||
- iptables -I INPUT 1 -p tcp -m tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
|
||||
- iptables -I INPUT 1 -p tcp -m tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT
|
||||
- /var/run/nginx/customize.sh
|
||||
- systemctl daemon-reload
|
||||
- systemctl start nginx
|
||||
@@ -13,8 +13,12 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
FQDN=$(curl -s -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/hostname)
|
||||
FQDN=$(\
|
||||
curl -s -H "Metadata-Flavor: Google" \
|
||||
http://metadata/computeMetadata/v1/instance/hostname)
|
||||
HOSTNAME=$(echo $FQDN | cut -d"." -f1)
|
||||
openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 -subj /CN=$HOSTNAME/ -addext "subjectAltName = DNS:$FQDN" -keyout /etc/ssl/self-signed.key -out /etc/ssl/self-signed.crt
|
||||
openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 \
|
||||
-subj /CN=$HOSTNAME/ -addext "subjectAltName = DNS:$FQDN" \
|
||||
-keyout /etc/ssl/self-signed.key -out /etc/ssl/self-signed.crt
|
||||
chgrp nginx /etc/ssl/self-signed.key -out /etc/ssl/self-signed.crt
|
||||
sed -i "s/HOSTNAME/${HOSTNAME}/" /etc/nginx/conf.d/default.conf
|
||||
24
modules/cloud-config-container/nginx-tls/assets/default.conf
Normal file
24
modules/cloud-config-container/nginx-tls/assets/default.conf
Normal file
@@ -0,0 +1,24 @@
|
||||
server {
|
||||
listen 80;
|
||||
listen 443 ssl;
|
||||
server_name HOSTNAME;
|
||||
ssl_certificate /etc/ssl/self-signed.crt;
|
||||
ssl_certificate_key /etc/ssl/self-signed.key;
|
||||
|
||||
location / {
|
||||
{% if hello %}
|
||||
default_type text/plain;
|
||||
expires -1;
|
||||
return 200 'Server address: $server_addr:$server_port\nServer name: $hostname\nDate: $time_local\nURI: $request_uri\nRequest ID: $request_id\n';
|
||||
{% else %}
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
{% endif %}
|
||||
}
|
||||
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
|
||||
location = /50x.html {
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
server {
|
||||
listen 80;
|
||||
listen 443 ssl;
|
||||
server_name HOSTNAME;
|
||||
ssl_certificate /etc/ssl/self-signed.crt;
|
||||
ssl_certificate_key /etc/ssl/self-signed.key;
|
||||
|
||||
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
}
|
||||
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
|
||||
location = /50x.html {
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/**
|
||||
* Copyright 2022 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
locals {
|
||||
default_files = {
|
||||
"/var/run/nginx/customize.sh" = {
|
||||
content = file("${path.module}/files/customize.sh")
|
||||
owner = "root"
|
||||
permissions = "0744"
|
||||
}
|
||||
"/etc/nginx/conf.d/default.conf" = {
|
||||
content = file("${path.module}/files/default.conf")
|
||||
owner = "root"
|
||||
permissions = "0644"
|
||||
}
|
||||
}
|
||||
files = var.files != null ? merge(local.default_files, var.files) : local.default_files
|
||||
}
|
||||
|
||||
module "cos-envoy-td" {
|
||||
source = "../cos-generic-metadata"
|
||||
|
||||
authenticate_gcr = true
|
||||
users = concat([
|
||||
{
|
||||
username = "nginx"
|
||||
uid = 2000
|
||||
}
|
||||
], var.users)
|
||||
run_as_first_user = false
|
||||
|
||||
boot_commands = [
|
||||
"systemctl start node-problem-detector",
|
||||
]
|
||||
|
||||
container_image = var.nginx_image
|
||||
container_name = "nginx"
|
||||
container_args = ""
|
||||
|
||||
container_volumes = [
|
||||
{ host = "/etc/nginx/conf.d", container = "/etc/nginx/conf.d" },
|
||||
{ host = "/etc/ssl", container = "/etc/ssl" },
|
||||
]
|
||||
|
||||
docker_args = "--network host --pid host"
|
||||
|
||||
files = local.files
|
||||
|
||||
run_commands = concat(var.runcmd_pre, [
|
||||
"iptables -I INPUT 1 -p tcp -m tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT",
|
||||
"iptables -I INPUT 1 -p tcp -m tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT",
|
||||
"/var/run/nginx/customize.sh",
|
||||
"systemctl daemon-reload",
|
||||
"systemctl start nginx",
|
||||
], var.runcmd_post)
|
||||
|
||||
}
|
||||
@@ -16,5 +16,23 @@
|
||||
|
||||
output "cloud_config" {
|
||||
description = "Rendered cloud-config file to be passed as user-data instance metadata."
|
||||
value = module.cos-envoy-td.cloud_config
|
||||
value = templatefile("${path.module}/assets/cloud-config.yaml", {
|
||||
files = merge(
|
||||
{
|
||||
"/var/run/nginx/customize.sh" = {
|
||||
content = file("${path.module}/assets/customize.sh")
|
||||
owner = "root"
|
||||
permissions = "0744"
|
||||
}
|
||||
"/etc/nginx/conf.d/default.conf" = {
|
||||
content = templatefile(
|
||||
"${path.module}/assets/default.conf", { hello = var.hello }
|
||||
)
|
||||
owner = "root"
|
||||
permissions = "0644"
|
||||
}
|
||||
}, var.files
|
||||
)
|
||||
image = var.image
|
||||
})
|
||||
}
|
||||
|
||||
@@ -18,38 +18,22 @@ variable "files" {
|
||||
description = "Map of extra files to create on the instance, path as key. Owner and permissions will use defaults if null."
|
||||
type = map(object({
|
||||
content = string
|
||||
owner = string
|
||||
permissions = string
|
||||
owner = optional(string, "root")
|
||||
permissions = optional(string, "0644")
|
||||
}))
|
||||
default = null
|
||||
default = {}
|
||||
nullable = false
|
||||
}
|
||||
|
||||
variable "nginx_image" {
|
||||
variable "hello" {
|
||||
description = "Behave like the nginx hello image by returning plain text informative responses."
|
||||
type = bool
|
||||
default = true
|
||||
nullable = false
|
||||
}
|
||||
|
||||
variable "image" {
|
||||
description = "Nginx container image to use."
|
||||
type = string
|
||||
default = "nginx:1.23.1"
|
||||
}
|
||||
|
||||
variable "runcmd_post" {
|
||||
description = "Extra commands to run after starting nginx."
|
||||
type = list(string)
|
||||
default = []
|
||||
}
|
||||
|
||||
variable "runcmd_pre" {
|
||||
description = "Extra commands to run before starting nginx."
|
||||
type = list(string)
|
||||
default = []
|
||||
}
|
||||
|
||||
variable "users" {
|
||||
description = "Additional list of usernames to be created."
|
||||
type = list(object({
|
||||
username = string,
|
||||
uid = number,
|
||||
}))
|
||||
default = [
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(string)</code> | | <code>[]</code> |
|
||||
| [runcmd_pre](variables.tf#L69) | Extra commands to run before starting nginx. | <code>list(string)</code> | | <code>[]</code> |
|
||||
| [test_instance](variables-instance.tf#L17) | Test/development instance attributes, leave null to skip creation. | <code title="object({ project_id = string zone = string name = string type = string network = string subnetwork = string })">object({…})</code> | | <code>null</code> |
|
||||
| [test_instance_defaults](variables-instance.tf#L30) | Test/development instance defaults used for optional configuration. If image is null, COS stable will be used. | <code title="object({ disks = map(object({ read_only = bool size = number })) image = string metadata = map(string) nat = bool service_account_roles = list(string) tags = list(string) })">object({…})</code> | | <code title="{ disks = {} image = null metadata = {} nat = false service_account_roles = [ "roles/logging.logWriter", "roles/monitoring.metricWriter" ] tags = ["ssh"] }">{…}</code> |
|
||||
| [users](variables.tf#L75) | List of additional usernames to be created. | <code title="list(object({ username = string, uid = number, }))">list(object({…}))</code> | | <code title="[ ]">[…]</code> |
|
||||
|
||||
## Outputs
|
||||
@@ -77,6 +70,5 @@ module "cos-nginx" {
|
||||
| name | description | sensitive |
|
||||
|---|---|:---:|
|
||||
| [cloud_config](outputs.tf#L17) | Rendered cloud-config file to be passed as user-data instance metadata. | |
|
||||
| [test_instance](outputs-instance.tf#L17) | Optional test instance name and address. | |
|
||||
|
||||
<!-- END TFDOC -->
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
../instance.tf
|
||||
@@ -1 +0,0 @@
|
||||
../outputs-instance.tf
|
||||
@@ -1 +0,0 @@
|
||||
../variables-instance.tf
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
../instance.tf
|
||||
@@ -1 +0,0 @@
|
||||
../outputs-instance.tf
|
||||
@@ -1 +0,0 @@
|
||||
../variables-instance.tf
|
||||
@@ -1,28 +0,0 @@
|
||||
/**
|
||||
* Copyright 2022 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
output "test_instance" {
|
||||
description = "Optional test instance name and address."
|
||||
value = (var.test_instance == null ? {} : {
|
||||
address = google_compute_instance.default[0].network_interface.0.network_ip
|
||||
name = google_compute_instance.default[0].name
|
||||
nat_address = try(
|
||||
google_compute_instance.default[0].network_interface.0.access_config.0.nat_ip,
|
||||
null
|
||||
)
|
||||
service_account = google_service_account.default[0].email
|
||||
})
|
||||
}
|
||||
@@ -9,7 +9,6 @@ This NVA can be used to interconnect up to 8 VPCs.
|
||||
### Simple example
|
||||
|
||||
```hcl
|
||||
# Interfaces configuration
|
||||
locals {
|
||||
network_interfaces = [
|
||||
{
|
||||
@@ -28,41 +27,40 @@ locals {
|
||||
routes = ["10.0.0.0/9"]
|
||||
subnetwork = "prod_vpc_nva_subnet_self_link"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
# NVA config
|
||||
module "nva-cloud-config" {
|
||||
source = "../../../cloud-foundation-fabric/modules/cloud-config-container/simple-nva"
|
||||
module "cos-nva" {
|
||||
source = "./fabric/modules/cloud-config-container/simple-nva"
|
||||
enable_health_checks = true
|
||||
network_interfaces = local.network_interfaces
|
||||
files = {
|
||||
"/var/lib/cloud/scripts/per-boot/firewall-rules.sh" = {
|
||||
content = file("./your_path/to/firewall-rules.sh")
|
||||
owner = "root"
|
||||
permissions = 0700
|
||||
}
|
||||
}
|
||||
# files = {
|
||||
# "/var/lib/cloud/scripts/per-boot/firewall-rules.sh" = {
|
||||
# content = file("./your_path/to/firewall-rules.sh")
|
||||
# owner = "root"
|
||||
# permissions = 0700
|
||||
# }
|
||||
# }
|
||||
}
|
||||
|
||||
# COS VM
|
||||
module "nva" {
|
||||
source = "../../modules/compute-vm"
|
||||
project_id = "myproject"
|
||||
instance_type = "e2-standard-2"
|
||||
name = "nva"
|
||||
can_ip_forward = true
|
||||
zone = "europe-west8-a"
|
||||
tags = ["nva"]
|
||||
module "vm" {
|
||||
source = "./fabric/modules/compute-vm"
|
||||
project_id = "my-project"
|
||||
zone = "europe-west8-b"
|
||||
name = "cos-nva"
|
||||
network_interfaces = local.network_interfaces
|
||||
metadata = {
|
||||
user-data = module.cos-nva.cloud_config
|
||||
google-logging-enabled = true
|
||||
}
|
||||
boot_disk = {
|
||||
image = "projects/cos-cloud/global/images/family/cos-stable"
|
||||
type = "pd-ssd"
|
||||
size = 10
|
||||
type = "pd-balanced"
|
||||
}
|
||||
metadata = {
|
||||
user-data = module.nva-cloud-config.cloud_config
|
||||
}
|
||||
tags = ["nva", "ssh"]
|
||||
}
|
||||
# tftest modules=1 resources=1
|
||||
```
|
||||
<!-- BEGIN TFDOC -->
|
||||
|
||||
@@ -74,14 +72,11 @@ module "nva" {
|
||||
| [cloud_config](variables.tf#L17) | Cloud config template path. If null default will be used. | <code>string</code> | | <code>null</code> |
|
||||
| [enable_health_checks](variables.tf#L23) | Configures routing to enable responses to health check probes. | <code>bool</code> | | <code>false</code> |
|
||||
| [files](variables.tf#L29) | Map of extra files to create on the instance, path as key. Owner and permissions will use defaults if null. | <code title="map(object({ content = string owner = string permissions = string }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [test_instance](variables-instance.tf#L17) | Test/development instance attributes, leave null to skip creation. | <code title="object({ project_id = string zone = string name = string type = string network = string subnetwork = string })">object({…})</code> | | <code>null</code> |
|
||||
| [test_instance_defaults](variables-instance.tf#L30) | Test/development instance defaults used for optional configuration. If image is null, COS stable will be used. | <code title="object({ disks = map(object({ read_only = bool size = number })) image = string metadata = map(string) nat = bool service_account_roles = list(string) tags = list(string) })">object({…})</code> | | <code title="{ disks = {} image = null metadata = {} nat = false service_account_roles = [ "roles/logging.logWriter", "roles/monitoring.metricWriter" ] tags = ["ssh"] }">{…}</code> |
|
||||
|
||||
## Outputs
|
||||
|
||||
| name | description | sensitive |
|
||||
|---|---|:---:|
|
||||
| [cloud_config](outputs.tf#L17) | Rendered cloud-config file to be passed as user-data instance metadata. | |
|
||||
| [test_instance](outputs-instance.tf#L17) | Optional test instance name and address. | |
|
||||
|
||||
<!-- END TFDOC -->
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
../instance.tf
|
||||
@@ -1 +0,0 @@
|
||||
../outputs-instance.tf
|
||||
@@ -1 +0,0 @@
|
||||
../variables-instance.tf
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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({ owner = string permissions = string })">object({…})</code> | | <code title="{ owner = "root" permissions = "0644" }">{…}</code> |
|
||||
| [files](variables.tf#L70) | Map of extra files to create on the instance, path as key. Owner and permissions will use defaults if null. | <code title="map(object({ content = string owner = string permissions = string }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [squid_config](variables.tf#L80) | Squid configuration path, if null default will be used. | <code>string</code> | | <code>null</code> |
|
||||
| [test_instance](variables-instance.tf#L17) | Test/development instance attributes, leave null to skip creation. | <code title="object({ project_id = string zone = string name = string type = string network = string subnetwork = string })">object({…})</code> | | <code>null</code> |
|
||||
| [test_instance_defaults](variables-instance.tf#L30) | Test/development instance defaults used for optional configuration. If image is null, COS stable will be used. | <code title="object({ disks = map(object({ read_only = bool size = number })) image = string metadata = map(string) nat = bool service_account_roles = list(string) tags = list(string) })">object({…})</code> | | <code title="{ disks = {} image = null metadata = {} nat = false service_account_roles = [ "roles/logging.logWriter", "roles/monitoring.metricWriter" ] tags = ["ssh"] }">{…}</code> |
|
||||
|
||||
## Outputs
|
||||
|
||||
| name | description | sensitive |
|
||||
|---|---|:---:|
|
||||
| [cloud_config](outputs.tf#L17) | Rendered cloud-config file to be passed as user-data instance metadata. | |
|
||||
| [test_instance](outputs-instance.tf#L17) | Optional test instance name and address. | |
|
||||
|
||||
<!-- END TFDOC -->
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
../instance.tf
|
||||
@@ -1 +0,0 @@
|
||||
../outputs-instance.tf
|
||||
@@ -1 +0,0 @@
|
||||
../variables-instance.tf
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"]
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ module "group" {
|
||||
]
|
||||
managers = [
|
||||
"user3@example.com"
|
||||
]
|
||||
]
|
||||
}
|
||||
# tftest modules=1 resources=5
|
||||
```
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(string)</code> | | <code>null</code> |
|
||||
| [availability_type](variables.tf#L23) | Availability type for the primary replica. Either `ZONAL` or `REGIONAL`. | <code>string</code> | | <code>"ZONAL"</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({ enabled = bool binary_log_enabled = bool start_time = string location = string log_retention_days = number retention_count = number })">object({…})</code> | | <code title="{ enabled = false binary_log_enabled = false start_time = "23:00" location = null log_retention_days = 7 retention_count = 7 }">{…}</code> |
|
||||
| [databases](variables.tf#L54) | Databases to create once the primary instance is created. | <code>list(string)</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>"PD_SSD"</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(string)</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(string)</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(object({ region = string encryption_key_name = string }))">map(object({…}))</code> | | <code>{}</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(string)</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({ primary = optional(string) replica = optional(string) })">object({…})</code> | | <code>{}</code> |
|
||||
| [authorized_networks](variables.tf#L26) | Map of NAME=>CIDR_RANGE to allow to connect to the database(s). | <code>map(string)</code> | | <code>null</code> |
|
||||
| [availability_type](variables.tf#L32) | Availability type for the primary replica. Either `ZONAL` or `REGIONAL`. | <code>string</code> | | <code>"ZONAL"</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({ 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) })">object({…})</code> | | <code title="{ 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 }">{…}</code> |
|
||||
| [databases](variables.tf#L66) | Databases to create once the primary instance is created. | <code>list(string)</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>"PD_SSD"</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(string)</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(string)</code> | | <code>null</code> |
|
||||
| [postgres_client_certificates](variables.tf#L124) | Map of cert keys connect to the application(s) using public IP. | <code>list(string)</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(object({ region = string encryption_key_name = string }))">map(object({…}))</code> | | <code>{}</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(string)</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 -->
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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({ labels = optional(map(string)) metadata = optional(map(string)) })">object({…})</code> | | <code>null</code> |
|
||||
| [auto_healing_policies](variables.tf#L26) | Auto-healing policies for this group. | <code title="object({ health_check = optional(string) initial_delay_sec = number })">object({…})</code> | | <code>null</code> |
|
||||
| [autoscaler_config](variables.tf#L35) | Optional autoscaler configuration. | <code title="object({ max_replicas = number min_replicas = number cooldown_period = optional(number) mode = optional(string) # OFF, ONLY_UP, ON scaling_control = optional(object({ down = optional(object({ max_replicas_fixed = optional(number) max_replicas_percent = optional(number) time_window_sec = optional(number) })) in = optional(object({ max_replicas_fixed = optional(number) max_replicas_percent = optional(number) time_window_sec = optional(number) })) }), {}) scaling_signals = optional(object({ cpu_utilization = optional(object({ target = number optimize_availability = optional(bool) })) load_balancing_utilization = optional(object({ target = number })) metrics = optional(list(object({ name = string type = string # GAUGE, DELTA_PER_SECOND, DELTA_PER_MINUTE target_value = number single_instance_assignment = optional(number) time_series_filter = optional(string) }))) schedules = optional(list(object({ duration_sec = number name = string min_required_replicas = number cron_schedule = string description = optional(bool) timezone = optional(string) disabled = optional(bool) }))) }), {}) })">object({…})</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>"Terraform managed."</code> |
|
||||
| [distribution_policy](variables.tf#L95) | DIstribution policy for regional MIG. | <code title="object({ target_shape = optional(string) zones = optional(list(string)) })">object({…})</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({ check_interval_sec = optional(number) description = optional(string, "Terraform managed.") enable_logging = optional(bool, false) healthy_threshold = optional(number) timeout_sec = optional(number) unhealthy_threshold = optional(number) grpc = optional(object({ port = optional(number) port_name = optional(string) port_specification = optional(string) # USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT service_name = optional(string) })) http = optional(object({ host = optional(string) port = optional(number) port_name = optional(string) port_specification = optional(string) # USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT proxy_header = optional(string) request_path = optional(string) response = optional(string) })) http2 = optional(object({ host = optional(string) port = optional(number) port_name = optional(string) port_specification = optional(string) # USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT proxy_header = optional(string) request_path = optional(string) response = optional(string) })) https = optional(object({ host = optional(string) port = optional(number) port_name = optional(string) port_specification = optional(string) # USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT proxy_header = optional(string) request_path = optional(string) response = optional(string) })) tcp = optional(object({ port = optional(number) port_name = optional(string) port_specification = optional(string) # USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT proxy_header = optional(string) request = optional(string) response = optional(string) })) ssl = optional(object({ port = optional(number) port_name = optional(string) port_specification = optional(string) # USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT proxy_header = optional(string) request = optional(string) response = optional(string) })) })">object({…})</code> | | <code>null</code> |
|
||||
| [named_ports](variables.tf#L189) | Named ports. | <code>map(number)</code> | | <code>null</code> |
|
||||
| [stateful_config](variables.tf#L200) | Stateful configuration for individual instances. | <code title="map(object({ minimal_action = optional(string) most_disruptive_action = optional(string) remove_state_on_destroy = optional(bool) preserved_state = optional(object({ disks = optional(map(object({ source = string delete_on_instance_deletion = optional(bool) read_only = optional(bool) }))) metadata = optional(map(string)) })) }))">map(object({…}))</code> | | <code>{}</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(bool)</code> | | <code>{}</code> |
|
||||
| [target_pools](variables.tf#L226) | Optional list of URLs for target pools to which new instances in the group are added. | <code>list(string)</code> | | <code>[]</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({ minimal_action = string type = string max_surge = optional(object({ fixed = optional(number) percent = optional(number) })) max_unavailable = optional(object({ fixed = optional(number) percent = optional(number) })) min_ready_sec = optional(number) most_disruptive_action = optional(string) regional_redistribution_type = optional(string) replacement_method = optional(string) })">object({…})</code> | | <code>null</code> |
|
||||
| [versions](variables.tf#L259) | Additional application versions, target_size is optional. | <code title="map(object({ instance_template = string target_size = optional(object({ fixed = optional(number) percent = optional(number) })) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [wait_for_instances](variables.tf#L272) | Wait for all instances to be created/updated before returning. | <code title="object({ enabled = bool status = optional(string) })">object({…})</code> | | <code>null</code> |
|
||||
| [named_ports](variables.tf#L192) | Named ports. | <code>map(number)</code> | | <code>null</code> |
|
||||
| [stateful_config](variables.tf#L203) | Stateful configuration for individual instances. | <code title="map(object({ minimal_action = optional(string) most_disruptive_action = optional(string) remove_state_on_destroy = optional(bool) preserved_state = optional(object({ disks = optional(map(object({ source = string delete_on_instance_deletion = optional(bool) read_only = optional(bool) }))) metadata = optional(map(string)) })) }))">map(object({…}))</code> | | <code>{}</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(bool)</code> | | <code>{}</code> |
|
||||
| [target_pools](variables.tf#L229) | Optional list of URLs for target pools to which new instances in the group are added. | <code>list(string)</code> | | <code>[]</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({ minimal_action = string type = string max_surge = optional(object({ fixed = optional(number) percent = optional(number) })) max_unavailable = optional(object({ fixed = optional(number) percent = optional(number) })) min_ready_sec = optional(number) most_disruptive_action = optional(string) regional_redistribution_type = optional(string) replacement_method = optional(string) })">object({…})</code> | | <code>null</code> |
|
||||
| [versions](variables.tf#L262) | Additional application versions, target_size is optional. | <code title="map(object({ instance_template = string target_size = optional(object({ fixed = optional(number) percent = optional(number) })) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [wait_for_instances](variables.tf#L275) | Wait for all instances to be created/updated before returning. | <code title="object({ enabled = bool status = optional(string) })">object({…})</code> | | <code>null</code> |
|
||||
|
||||
## Outputs
|
||||
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user