Refactor compute-vm to remove multiple instance support (#314)

* first iteration, largely untested

* basic tests pass

* basic tests pass

* nic test

* disk tests, refactor

* fix tests

* update README

* update gcs to bq example

* fix README examples, do not create disks for template

* fix data solutions examples

* update cloud operations examples

* update networking examples, mig and ilb modules examples

* update default image to debian 11

* update README table
This commit is contained in:
Ludovico Magnocavallo 2021-10-04 10:46:44 +02:00 committed by GitHub
parent 0bceb328d4
commit 262f823464
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 500 additions and 618 deletions

View File

@ -102,7 +102,7 @@ module "cf" {
module "simple-vm-example" { module "simple-vm-example" {
source = "../../modules/compute-vm" source = "../../modules/compute-vm"
project_id = module.project.project_id project_id = module.project.project_id
region = var.region zone = "${var.region}-b"
name = var.name name = var.name
network_interfaces = [{ network_interfaces = [{
network = module.vpc.self_link network = module.vpc.self_link
@ -112,7 +112,6 @@ module "simple-vm-example" {
alias_ips = null alias_ips = null
}] }]
tags = ["${var.project_id}-test-feed", "shared-test-feed"] tags = ["${var.project_id}-test-feed", "shared-test-feed"]
instance_count = 1
} }
resource "random_pet" "random" { resource "random_pet" "random" {

View File

@ -104,7 +104,7 @@ module "service-directory" {
module "vm-ns-editor" { module "vm-ns-editor" {
source = "../../modules/compute-vm" source = "../../modules/compute-vm"
project_id = module.project.project_id project_id = module.project.project_id
region = var.region zone = "${var.region}-b"
name = "${var.name}-ns" name = "${var.name}-ns"
network_interfaces = [{ network_interfaces = [{
network = module.vpc.self_link network = module.vpc.self_link
@ -116,13 +116,12 @@ module "vm-ns-editor" {
metadata = { startup-script = local.startup-script } metadata = { startup-script = local.startup-script }
service_account_create = true service_account_create = true
tags = ["ssh"] tags = ["ssh"]
instance_count = 1
} }
module "vm-svc-editor" { module "vm-svc-editor" {
source = "../../modules/compute-vm" source = "../../modules/compute-vm"
project_id = module.project.project_id project_id = module.project.project_id
region = var.region zone = "${var.region}-b"
name = "${var.name}-svc" name = "${var.name}-svc"
network_interfaces = [{ network_interfaces = [{
network = module.vpc.self_link network = module.vpc.self_link
@ -134,5 +133,4 @@ module "vm-svc-editor" {
metadata = { startup-script = local.startup-script } metadata = { startup-script = local.startup-script }
service_account_create = true service_account_create = true
tags = ["ssh"] tags = ["ssh"]
instance_count = 1
} }

View File

@ -17,15 +17,15 @@
output "vms" { output "vms" {
description = "VM names." description = "VM names."
value = { value = {
ns-editor = module.vm-ns-editor.names.0 ns-editor = module.vm-ns-editor.instance.name
svc-editor = module.vm-svc-editor.names.0 svc-editor = module.vm-svc-editor.instance.name
} }
} }
output "gcloud_commands" { output "gcloud_commands" {
description = "Commands used to SSH to the VMs." description = "Commands used to SSH to the VMs."
value = { value = {
ns-editor = "gcloud compute ssh ${module.vm-ns-editor.names.0} --zone ${var.region}-b --tunnel-through-iap" ns-editor = "gcloud compute ssh ${module.vm-ns-editor.instance.name} --zone ${var.region}-b --tunnel-through-iap"
svc-editor = "gcloud compute ssh ${module.vm-svc-editor.names.0} --zone ${var.region}-b --tunnel-through-iap" svc-editor = "gcloud compute ssh ${module.vm-svc-editor.instance.name} --zone ${var.region}-b --tunnel-through-iap"
} }
} }

View File

@ -52,6 +52,6 @@ This sample creates several distinct groups of resources:
| bucket | GCS Bucket URL. | | | bucket | GCS Bucket URL. | |
| bucket_keys | GCS Bucket Cloud KMS crypto keys. | | | bucket_keys | GCS Bucket Cloud KMS crypto keys. | |
| projects | Project ids. | | | projects | Project ids. | |
| vm | GCE VMs. | | | vm | GCE VM. | |
| vm_keys | GCE VM Cloud KMS crypto keys. | | | vm_keys | GCE VM Cloud KMS crypto keys. | |
<!-- END TFDOC --> <!-- END TFDOC -->

View File

@ -97,10 +97,10 @@ module "kms" {
# GCE # # GCE #
############################################################################### ###############################################################################
module "kms_vm_example" { module "vm_example" {
source = "../../modules/compute-vm" source = "../../modules/compute-vm"
project_id = module.project-service.project_id project_id = module.project-service.project_id
region = var.region zone = "${var.region}-b"
name = "kms-vm" name = "kms-vm"
network_interfaces = [{ network_interfaces = [{
network = module.vpc.self_link, network = module.vpc.self_link,
@ -111,14 +111,13 @@ module "kms_vm_example" {
}] }]
attached_disks = [ attached_disks = [
{ {
name = "attacheddisk" name = "data"
size = 10 size = 10
source = null source = null
source_type = null source_type = null
options = null options = null
} }
] ]
instance_count = 1
boot_disk = { boot_disk = {
image = "projects/debian-cloud/global/images/family/debian-10" image = "projects/debian-cloud/global/images/family/debian-10"
type = "pd-ssd" type = "pd-ssd"

View File

@ -31,17 +31,17 @@ output "projects" {
} }
output "vm" { output "vm" {
description = "GCE VMs." description = "GCE VM."
value = { value = {
for instance in module.kms_vm_example.instances : name = module.vm_example.instance.name
instance.name => instance.network_interface.0.network_ip address = module.vm_example.internal_ip
} }
} }
output "vm_keys" { output "vm_keys" {
description = "GCE VM Cloud KMS crypto keys." description = "GCE VM Cloud KMS crypto keys."
value = { value = {
for instance in module.kms_vm_example.instances : name = module.vm_example.instance.name
instance.name => instance.boot_disk.0.kms_key_self_link key = module.vm_example.instance.boot_disk.0.kms_key_self_link
} }
} }

View File

@ -46,7 +46,7 @@ This sample creates several distinct groups of resources:
You can now connect to the GCE instance with the following command: You can now connect to the GCE instance with the following command:
```hcl ```hcl
gcloud compute ssh vm-example-1 gcloud compute ssh vm-example
``` ```
You can run now the simple pipeline you can find [here](./script/data_ingestion/). Once you have installed required packages and copied a file into the GCS bucket, you can trigger the pipeline using internal ips with a command simila to: You can run now the simple pipeline you can find [here](./script/data_ingestion/). Once you have installed required packages and copied a file into the GCS bucket, you can trigger the pipeline using internal ips with a command simila to:
@ -95,7 +95,7 @@ You can check data imported into Google BigQuery from the Google Cloud Console U
You can now connect to the GCE instance with the following command: You can now connect to the GCE instance with the following command:
```hcl ```hcl
gcloud compute ssh vm-example-1 gcloud compute ssh vm-example
``` ```
You can run now a simple 'bq load' command to import data into Bigquery. Below an example command: You can run now a simple 'bq load' command to import data into Bigquery. Below an example command:
@ -133,5 +133,5 @@ You can check data imported into Google BigQuery from the Google Cloud Console U
| bq_tables | Bigquery Tables. | | | bq_tables | Bigquery Tables. | |
| buckets | GCS Bucket Cloud KMS crypto keys. | | | buckets | GCS Bucket Cloud KMS crypto keys. | |
| projects | Project ids. | | | projects | Project ids. | |
| vm | GCE VMs. | | | vm | GCE VM. | |
<!-- END TFDOC --> <!-- END TFDOC -->

View File

@ -200,7 +200,7 @@ module "nat" {
module "vm_example" { module "vm_example" {
source = "../../modules/compute-vm" source = "../../modules/compute-vm"
project_id = module.project-service.project_id project_id = module.project-service.project_id
region = var.region zone = "${var.region}-b"
name = "vm-example" name = "vm-example"
network_interfaces = [{ network_interfaces = [{
network = module.vpc.self_link, network = module.vpc.self_link,
@ -211,14 +211,13 @@ module "vm_example" {
}] }]
attached_disks = [ attached_disks = [
{ {
name = "attacheddisk" name = "data"
size = 10 size = 10
source = null source = null
source_type = null source_type = null
options = null options = null
} }
] ]
instance_count = 2
boot_disk = { boot_disk = {
image = "projects/debian-cloud/global/images/family/debian-10" image = "projects/debian-cloud/global/images/family/debian-10"
type = "pd-ssd" type = "pd-ssd"
@ -230,7 +229,9 @@ module "vm_example" {
disk_encryption_key_raw = null disk_encryption_key_raw = null
kms_key_self_link = module.kms.key_self_links.key-gce kms_key_self_link = module.kms.key_self_links.key-gce
} }
metadata = { startup-script = local.vm-startup-script } metadata = {
startup-script = local.vm-startup-script
}
service_account = module.service-account-gce.email service_account = module.service-account-gce.email
service_account_scopes = ["https://www.googleapis.com/auth/cloud-platform"] service_account_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
tags = ["ssh"] tags = ["ssh"]

View File

@ -34,9 +34,9 @@ output "projects" {
} }
output "vm" { output "vm" {
description = "GCE VMs." description = "GCE VM."
value = { value = {
for instance in module.vm_example.instances : name = module.vm_example.instance.name
instance.name => instance.network_interface.0.network_ip address = module.vm_example.internal_ip
} }
} }

View File

@ -17,8 +17,7 @@ module "nginx-template" {
source = "./modules/compute-vm" source = "./modules/compute-vm"
project_id = var.project_id project_id = var.project_id
name = "nginx-template" name = "nginx-template"
region = "europe-west1" zone = "europe-west1-b"
zones = ["europe-west1-b", "europe-west1-d"]
tags = ["http-server", "ssh"] tags = ["http-server", "ssh"]
network_interfaces = [{ network_interfaces = [{
network = var.vpc.self_link network = var.vpc.self_link
@ -32,7 +31,7 @@ module "nginx-template" {
type = "pd-ssd" type = "pd-ssd"
size = 10 size = 10
} }
use_instance_template = true create_template = true
metadata = { metadata = {
user-data = module.cos-nginx.cloud_config user-data = module.cos-nginx.cloud_config
} }
@ -65,8 +64,7 @@ module "nginx-template" {
source = "./modules/compute-vm" source = "./modules/compute-vm"
project_id = var.project_id project_id = var.project_id
name = "nginx-template" name = "nginx-template"
region = "europe-west1" zone = "europe-west1-b"
zones = ["europe-west1-b", "europe-west1-d"]
tags = ["http-server", "ssh"] tags = ["http-server", "ssh"]
network_interfaces = [{ network_interfaces = [{
network = var.vpc.self_link network = var.vpc.self_link
@ -80,7 +78,7 @@ module "nginx-template" {
type = "pd-ssd" type = "pd-ssd"
size = 10 size = 10
} }
use_instance_template = true create_template = true
metadata = { metadata = {
user-data = module.cos-nginx.cloud_config user-data = module.cos-nginx.cloud_config
} }
@ -120,8 +118,7 @@ module "nginx-template" {
source = "./modules/compute-vm" source = "./modules/compute-vm"
project_id = var.project_id project_id = var.project_id
name = "nginx-template" name = "nginx-template"
region = "europe-west1" zone = "europe-west1-b"
zones = ["europe-west1-b", "europe-west1-d"]
tags = ["http-server", "ssh"] tags = ["http-server", "ssh"]
network_interfaces = [{ network_interfaces = [{
network = var.vpc.self_link, network = var.vpc.self_link,
@ -135,7 +132,7 @@ module "nginx-template" {
type = "pd-ssd" type = "pd-ssd"
size = 10 size = 10
} }
use_instance_template = true create_template = true
metadata = { metadata = {
user-data = module.cos-nginx.cloud_config user-data = module.cos-nginx.cloud_config
} }
@ -178,8 +175,7 @@ module "nginx-template" {
source = "./modules/compute-vm" source = "./modules/compute-vm"
project_id = var.project_id project_id = var.project_id
name = "nginx-template" name = "nginx-template"
region = "europe-west1" zone = "europe-west1-b"
zones = ["europe-west1-b", "europe-west1-d"]
tags = ["http-server", "ssh"] tags = ["http-server", "ssh"]
network_interfaces = [{ network_interfaces = [{
network = var.vpc.self_link network = var.vpc.self_link
@ -193,7 +189,7 @@ module "nginx-template" {
type = "pd-ssd" type = "pd-ssd"
size = 10 size = 10
} }
use_instance_template = true create_template = true
metadata = { metadata = {
user-data = module.cos-nginx.cloud_config user-data = module.cos-nginx.cloud_config
} }
@ -232,8 +228,7 @@ module "nginx-template" {
source = "./modules/compute-vm" source = "./modules/compute-vm"
project_id = var.project_id project_id = var.project_id
name = "nginx-template" name = "nginx-template"
region = "europe-west1" zone = "europe-west1-b"
zones = ["europe-west1-b", "europe-west1-d"]
tags = ["http-server", "ssh"] tags = ["http-server", "ssh"]
network_interfaces = [{ network_interfaces = [{
network = var.vpc.self_link network = var.vpc.self_link
@ -247,7 +242,7 @@ module "nginx-template" {
type = "pd-ssd" type = "pd-ssd"
size = 10 size = 10
} }
use_instance_template = true create_template = true
metadata = { metadata = {
user-data = module.cos-nginx.cloud_config user-data = module.cos-nginx.cloud_config
} }

View File

@ -17,7 +17,7 @@ The simplest example leverages defaults for the boot disk image and size, and us
module "simple-vm-example" { module "simple-vm-example" {
source = "./modules/compute-vm" source = "./modules/compute-vm"
project_id = var.project_id project_id = var.project_id
region = var.region zone = "europe-west1-b"
name = "test" name = "test"
network_interfaces = [{ network_interfaces = [{
network = var.vpc.self_link network = var.vpc.self_link
@ -27,7 +27,6 @@ module "simple-vm-example" {
alias_ips = null alias_ips = null
}] }]
service_account_create = true service_account_create = true
instance_count = 1
} }
# tftest:modules=1:resources=2 # tftest:modules=1:resources=2
@ -48,7 +47,7 @@ This is an example of attaching a pre-existing regional PD to a new instance:
module "simple-vm-example" { module "simple-vm-example" {
source = "./modules/compute-vm" source = "./modules/compute-vm"
project_id = var.project_id project_id = var.project_id
region = var.region zone = "${var.region}-b"
name = "test" name = "test"
network_interfaces = [{ network_interfaces = [{
network = var.vpc.self_link network = var.vpc.self_link
@ -63,9 +62,8 @@ module "simple-vm-example" {
source_type = "attach" source_type = "attach"
source = "regions/${var.region}/disks/repd-test-1" source = "regions/${var.region}/disks/repd-test-1"
options = { options = {
auto_delete = false
mode = null mode = null
regional = true replica_zone = "${var.region}-c"
type = null type = null
} }
}] }]
@ -80,7 +78,7 @@ And the same example for an instance template (where not using the full self lin
module "simple-vm-example" { module "simple-vm-example" {
source = "./modules/compute-vm" source = "./modules/compute-vm"
project_id = var.project_id project_id = var.project_id
region = var.region zone = "${var.region}-b"
name = "test" name = "test"
network_interfaces = [{ network_interfaces = [{
network = var.vpc.self_link network = var.vpc.self_link
@ -95,14 +93,13 @@ module "simple-vm-example" {
source_type = "attach" source_type = "attach"
source = "https://www.googleapis.com/compute/v1/projects/${var.project_id}/regions/${var.region}/disks/repd-test-1" source = "https://www.googleapis.com/compute/v1/projects/${var.project_id}/regions/${var.region}/disks/repd-test-1"
options = { options = {
auto_delete = false
mode = null mode = null
regional = true replica_zone = "${var.region}-c"
type = null type = null
} }
}] }]
service_account_create = true service_account_create = true
use_instance_template = true create_template = true
} }
# tftest:modules=1:resources=2 # tftest:modules=1:resources=2
``` ```
@ -115,7 +112,7 @@ This example shows how to control disk encryption via the the `encryption` varia
module "kms-vm-example" { module "kms-vm-example" {
source = "./modules/compute-vm" source = "./modules/compute-vm"
project_id = var.project_id project_id = var.project_id
region = var.region zone = "europe-west1-b"
name = "kms-test" name = "kms-test"
network_interfaces = [{ network_interfaces = [{
network = var.vpc.self_link network = var.vpc.self_link
@ -134,7 +131,6 @@ module "kms-vm-example" {
} }
] ]
service_account_create = true service_account_create = true
instance_count = 1
boot_disk = { boot_disk = {
image = "projects/debian-cloud/global/images/family/debian-10" image = "projects/debian-cloud/global/images/family/debian-10"
type = "pd-ssd" type = "pd-ssd"
@ -157,7 +153,7 @@ This example shows how add additional [Alias IPs](https://cloud.google.com/vpc/d
module "vm-with-alias-ips" { module "vm-with-alias-ips" {
source = "./modules/compute-vm" source = "./modules/compute-vm"
project_id = "my-project" project_id = "my-project"
region = "europe-west1" zone = "europe-west1-b"
name = "test" name = "test"
network_interfaces = [{ network_interfaces = [{
network = var.vpc.self_link network = var.vpc.self_link
@ -165,17 +161,12 @@ module "vm-with-alias-ips" {
nat = false nat = false
addresses = null addresses = null
alias_ips = { alias_ips = {
alias1 = [ alias1 = "10.16.0.10/32"
"10.16.0.10/32", # alias1 IP for first instance
"10.16.0.11/32", # alias1 IP for second instance
"10.16.0.12/32", # alias1 IP for third instance
]
} }
}] }]
service_account_create = true service_account_create = true
instance_count = 3
} }
# tftest:modules=1:resources=4 # tftest:modules=1:resources=2
``` ```
### Instance template ### Instance template
@ -186,7 +177,7 @@ This example shows how to use the module to manage an instance template that def
module "cos-test" { module "cos-test" {
source = "./modules/compute-vm" source = "./modules/compute-vm"
project_id = "my-project" project_id = "my-project"
region = "europe-west1" zone = "europe-west1-b"
name = "test" name = "test"
network_interfaces = [{ network_interfaces = [{
network = var.vpc.self_link network = var.vpc.self_link
@ -195,7 +186,6 @@ module "cos-test" {
addresses = null addresses = null
alias_ips = null alias_ips = null
}] }]
instance_count = 1
boot_disk = { boot_disk = {
image = "projects/cos-cloud/global/images/family/cos-stable" image = "projects/cos-cloud/global/images/family/cos-stable"
type = "pd-ssd" type = "pd-ssd"
@ -211,7 +201,7 @@ module "cos-test" {
} }
] ]
service_account = "vm-default@my-project.iam.gserviceaccount.com" service_account = "vm-default@my-project.iam.gserviceaccount.com"
use_instance_template = true create_template = true
} }
# tftest:modules=1:resources=1 # tftest:modules=1:resources=1
``` ```
@ -228,7 +218,7 @@ locals {
module "instance-group" { module "instance-group" {
source = "./modules/compute-vm" source = "./modules/compute-vm"
project_id = "my-project" project_id = "my-project"
region = "europe-west1" zone = "europe-west1-b"
name = "ilb-test" name = "ilb-test"
network_interfaces = [{ network_interfaces = [{
network = var.vpc.self_link network = var.vpc.self_link
@ -257,25 +247,25 @@ module "instance-group" {
| name | description | type | required | default | | name | description | type | required | default |
|---|---|:---: |:---:|:---:| |---|---|:---: |:---:|:---:|
| name | Instances base name. | <code title="">string</code> | ✓ | | | name | Instance name. | <code title="">string</code> | ✓ | |
| network_interfaces | Network interfaces configuration. Use self links for Shared VPC, set addresses and alias_ips to null if not needed. | <code title="list&#40;object&#40;&#123;&#10;nat &#61; bool&#10;network &#61; string&#10;subnetwork &#61; string&#10;addresses &#61; object&#40;&#123;&#10;internal &#61; list&#40;string&#41;&#10;external &#61; list&#40;string&#41;&#10;&#125;&#41;&#10;alias_ips &#61; map&#40;list&#40;string&#41;&#41;&#10;&#125;&#41;&#41;">list(object({...}))</code> | ✓ | | | network_interfaces | Network interfaces configuration. Use self links for Shared VPC, set addresses and alias_ips to null if not needed. | <code title="list&#40;object&#40;&#123;&#10;nat &#61; bool&#10;network &#61; string&#10;subnetwork &#61; string&#10;addresses &#61; object&#40;&#123;&#10;internal &#61; string&#10;external &#61; string&#10;&#125;&#41;&#10;alias_ips &#61; map&#40;string&#41;&#10;&#125;&#41;&#41;">list(object({...}))</code> | ✓ | |
| project_id | Project id. | <code title="">string</code> | ✓ | | | project_id | Project id. | <code title="">string</code> | ✓ | |
| region | Compute region. | <code title="">string</code> | ✓ | | | zone | Compute zone. | <code title="">string</code> | ✓ | |
| *attached_disk_defaults* | Defaults for attached disks options. | <code title="object&#40;&#123;&#10;auto_delete &#61; bool&#10;mode &#61; string&#10;regional &#61; bool&#10;type &#61; string&#10;&#125;&#41;">object({...})</code> | | <code title="&#123;&#10;auto_delete &#61; true&#10;mode &#61; &#34;READ_WRITE&#34;&#10;regional &#61; false&#10;type &#61; &#34;pd-ssd&#34;&#10;&#125;">...</code> | | *attached_disk_defaults* | Defaults for attached disks options. | <code title="object&#40;&#123;&#10;mode &#61; string&#10;replica_zone &#61; string&#10;type &#61; string&#10;&#125;&#41;">object({...})</code> | | <code title="&#123;&#10;auto_delete &#61; true&#10;mode &#61; &#34;READ_WRITE&#34;&#10;replica_zone &#61; null&#10;type &#61; &#34;pd-balanced&#34;&#10;&#125;">...</code> |
| *attached_disks* | Additional disks, if options is null defaults will be used in its place. Source type is one of 'image' (zonal disks in vms and template), 'snapshot' (vm), 'existing', and null. | <code title="list&#40;object&#40;&#123;&#10;name &#61; string&#10;size &#61; string&#10;source &#61; string&#10;source_type &#61; string&#10;options &#61; object&#40;&#123;&#10;auto_delete &#61; bool&#10;mode &#61; string&#10;regional &#61; bool&#10;type &#61; string&#10;&#125;&#41;&#10;&#125;&#41;&#41;">list(object({...}))</code> | | <code title="&#91;&#93;&#10;validation &#123;&#10;condition &#61; length&#40;&#91;&#10;for d in var.attached_disks : d if&#40;&#10;d.source_type &#61;&#61; null&#10;&#124;&#124;&#10;contains&#40;&#91;&#34;image&#34;, &#34;snapshot&#34;, &#34;attach&#34;&#93;, coalesce&#40;d.source_type, &#34;1&#34;&#41;&#41;&#10;&#41;&#10;&#93;&#41; &#61;&#61; length&#40;var.attached_disks&#41;&#10;error_message &#61; &#34;Source type must be one of &#39;image&#39;, &#39;snapshot&#39;, &#39;attach&#39;, null.&#34;&#10;&#125;">...</code> | | *attached_disks* | Additional disks, if options is null defaults will be used in its place. Source type is one of 'image' (zonal disks in vms and template), 'snapshot' (vm), 'existing', and null. | <code title="list&#40;object&#40;&#123;&#10;name &#61; string&#10;size &#61; string&#10;source &#61; string&#10;source_type &#61; string&#10;options &#61; object&#40;&#123;&#10;mode &#61; string&#10;replica_zone &#61; string&#10;type &#61; string&#10;&#125;&#41;&#10;&#125;&#41;&#41;">list(object({...}))</code> | | <code title="&#91;&#93;&#10;validation &#123;&#10;condition &#61; length&#40;&#91;&#10;for d in var.attached_disks : d if&#40;&#10;d.source_type &#61;&#61; null&#10;&#124;&#124;&#10;contains&#40;&#91;&#34;image&#34;, &#34;snapshot&#34;, &#34;attach&#34;&#93;, coalesce&#40;d.source_type, &#34;1&#34;&#41;&#41;&#10;&#41;&#10;&#93;&#41; &#61;&#61; length&#40;var.attached_disks&#41;&#10;error_message &#61; &#34;Source type must be one of &#39;image&#39;, &#39;snapshot&#39;, &#39;attach&#39;, null.&#34;&#10;&#125;">...</code> |
| *boot_disk* | Boot disk properties. | <code title="object&#40;&#123;&#10;image &#61; string&#10;size &#61; number&#10;type &#61; string&#10;&#125;&#41;">object({...})</code> | | <code title="&#123;&#10;image &#61; &#34;projects&#47;debian-cloud&#47;global&#47;images&#47;family&#47;debian-10&#34;&#10;type &#61; &#34;pd-ssd&#34;&#10;size &#61; 10&#10;&#125;">...</code> | | *boot_disk* | Boot disk properties. | <code title="object&#40;&#123;&#10;image &#61; string&#10;size &#61; number&#10;type &#61; string&#10;&#125;&#41;">object({...})</code> | | <code title="&#123;&#10;image &#61; &#34;projects&#47;debian-cloud&#47;global&#47;images&#47;family&#47;debian-11&#34;&#10;type &#61; &#34;pd-balanced&#34;&#10;size &#61; 10&#10;&#125;">...</code> |
| *boot_disk_delete* | Auto delete boot disk. | <code title="">bool</code> | | <code title="">true</code> |
| *can_ip_forward* | Enable IP forwarding. | <code title="">bool</code> | | <code title="">false</code> | | *can_ip_forward* | Enable IP forwarding. | <code title="">bool</code> | | <code title="">false</code> |
| *confidential_compute* | Enable Confidential Compute for these instances. | <code title="">bool</code> | | <code title="">false</code> | | *confidential_compute* | Enable Confidential Compute for these instances. | <code title="">bool</code> | | <code title="">false</code> |
| *create_template* | Create instance template instead of instances. | <code title="">bool</code> | | <code title="">false</code> |
| *enable_display* | Enable virtual display on the instances | <code title="">bool</code> | | <code title="">false</code> | | *enable_display* | Enable virtual display on the instances | <code title="">bool</code> | | <code title="">false</code> |
| *encryption* | Encryption options. Only one of kms_key_self_link and disk_encryption_key_raw may be set. If needed, you can specify to encrypt or not the boot disk. | <code title="object&#40;&#123;&#10;encrypt_boot &#61; bool&#10;disk_encryption_key_raw &#61; string&#10;kms_key_self_link &#61; string&#10;&#125;&#41;">object({...})</code> | | <code title="">null</code> | | *encryption* | Encryption options. Only one of kms_key_self_link and disk_encryption_key_raw may be set. If needed, you can specify to encrypt or not the boot disk. | <code title="object&#40;&#123;&#10;encrypt_boot &#61; bool&#10;disk_encryption_key_raw &#61; string&#10;kms_key_self_link &#61; string&#10;&#125;&#41;">object({...})</code> | | <code title="">null</code> |
| *group* | Define this variable to create an instance group for instances. Disabled for template use. | <code title="object&#40;&#123;&#10;named_ports &#61; map&#40;number&#41;&#10;&#125;&#41;">object({...})</code> | | <code title="">null</code> | | *group* | Define this variable to create an instance group for instances. Disabled for template use. | <code title="object&#40;&#123;&#10;named_ports &#61; map&#40;number&#41;&#10;&#125;&#41;">object({...})</code> | | <code title="">null</code> |
| *hostname* | Instance FQDN name. | <code title="">string</code> | | <code title="">null</code> | | *hostname* | Instance FQDN name. | <code title="">string</code> | | <code title="">null</code> |
| *iam* | IAM bindings in {ROLE => [MEMBERS]} format. | <code title="map&#40;list&#40;string&#41;&#41;">map(list(string))</code> | | <code title="">{}</code> | | *iam* | IAM bindings in {ROLE => [MEMBERS]} format. | <code title="map&#40;list&#40;string&#41;&#41;">map(list(string))</code> | | <code title="">{}</code> |
| *instance_count* | Number of instances to create (only for non-template usage). | <code title="">number</code> | | <code title="">1</code> |
| *instance_type* | Instance type. | <code title="">string</code> | | <code title="">f1-micro</code> | | *instance_type* | Instance type. | <code title="">string</code> | | <code title="">f1-micro</code> |
| *labels* | Instance labels. | <code title="map&#40;string&#41;">map(string)</code> | | <code title="">{}</code> | | *labels* | Instance labels. | <code title="map&#40;string&#41;">map(string)</code> | | <code title="">{}</code> |
| *metadata* | Instance metadata. | <code title="map&#40;string&#41;">map(string)</code> | | <code title="">{}</code> | | *metadata* | Instance metadata. | <code title="map&#40;string&#41;">map(string)</code> | | <code title="">{}</code> |
| *metadata_list* | List of instance metadata that will be cycled through. Ignored for template use. | <code title="list&#40;map&#40;string&#41;&#41;">list(map(string))</code> | | <code title="">[]</code> |
| *min_cpu_platform* | Minimum CPU platform. | <code title="">string</code> | | <code title="">null</code> | | *min_cpu_platform* | Minimum CPU platform. | <code title="">string</code> | | <code title="">null</code> |
| *options* | Instance options. | <code title="object&#40;&#123;&#10;allow_stopping_for_update &#61; bool&#10;deletion_protection &#61; bool&#10;preemptible &#61; bool&#10;&#125;&#41;">object({...})</code> | | <code title="&#123;&#10;allow_stopping_for_update &#61; true&#10;deletion_protection &#61; false&#10;preemptible &#61; false&#10;&#125;">...</code> | | *options* | Instance options. | <code title="object&#40;&#123;&#10;allow_stopping_for_update &#61; bool&#10;deletion_protection &#61; bool&#10;preemptible &#61; bool&#10;&#125;&#41;">object({...})</code> | | <code title="&#123;&#10;allow_stopping_for_update &#61; true&#10;deletion_protection &#61; false&#10;preemptible &#61; false&#10;&#125;">...</code> |
| *scratch_disks* | Scratch disks configuration. | <code title="object&#40;&#123;&#10;count &#61; number&#10;interface &#61; string&#10;&#125;&#41;">object({...})</code> | | <code title="&#123;&#10;count &#61; 0&#10;interface &#61; &#34;NVME&#34;&#10;&#125;">...</code> | | *scratch_disks* | Scratch disks configuration. | <code title="object&#40;&#123;&#10;count &#61; number&#10;interface &#61; string&#10;&#125;&#41;">object({...})</code> | | <code title="&#123;&#10;count &#61; 0&#10;interface &#61; &#34;NVME&#34;&#10;&#125;">...</code> |
@ -283,21 +273,17 @@ module "instance-group" {
| *service_account_create* | Auto-create service account. | <code title="">bool</code> | | <code title="">false</code> | | *service_account_create* | Auto-create service account. | <code title="">bool</code> | | <code title="">false</code> |
| *service_account_scopes* | Scopes applied to service account. | <code title="list&#40;string&#41;">list(string)</code> | | <code title="">[]</code> | | *service_account_scopes* | Scopes applied to service account. | <code title="list&#40;string&#41;">list(string)</code> | | <code title="">[]</code> |
| *shielded_config* | Shielded VM configuration of the instances. | <code title="object&#40;&#123;&#10;enable_secure_boot &#61; bool&#10;enable_vtpm &#61; bool&#10;enable_integrity_monitoring &#61; bool&#10;&#125;&#41;">object({...})</code> | | <code title="">null</code> | | *shielded_config* | Shielded VM configuration of the instances. | <code title="object&#40;&#123;&#10;enable_secure_boot &#61; bool&#10;enable_vtpm &#61; bool&#10;enable_integrity_monitoring &#61; bool&#10;&#125;&#41;">object({...})</code> | | <code title="">null</code> |
| *single_name* | Do not append progressive count to instance name. | <code title="">bool</code> | | <code title="">false</code> |
| *tags* | Instance tags. | <code title="list&#40;string&#41;">list(string)</code> | | <code title="">[]</code> | | *tags* | Instance tags. | <code title="list&#40;string&#41;">list(string)</code> | | <code title="">[]</code> |
| *use_instance_template* | Create instance template instead of instances. | <code title="">bool</code> | | <code title="">false</code> |
| *zones* | Compute zone, instance will cycle through the list, defaults to the 'b' zone in the region. | <code title="list&#40;string&#41;">list(string)</code> | | <code title="">[]</code> |
## Outputs ## Outputs
| name | description | sensitive | | name | description | sensitive |
|---|---|:---:| |---|---|:---:|
| external_ips | Instance main interface external IP addresses. | | | external_ip | Instance main interface external IP addresses. | |
| groups | Instance group resources. | | | group | Instance group resource. | |
| instances | Instance resources. | | | instance | Instance resource. | |
| internal_ips | Instance main interface internal IP addresses. | | | internal_ip | Instance main interface internal IP address. | |
| names | Instance names. | | | self_link | Instance self links. | |
| self_links | Instance self links. | |
| service_account | Service account resource. | | | service_account | Service account resource. | |
| service_account_email | Service account email. | | | service_account_email | Service account email. | |
| service_account_iam_email | Service account email. | | | service_account_iam_email | Service account email. | |

View File

@ -21,36 +21,20 @@ locals {
options = disk.options == null ? var.attached_disk_defaults : disk.options options = disk.options == null ? var.attached_disk_defaults : disk.options
}) })
} }
attached_disks_pairs = { attached_disks_regional = {
for pair in setproduct(keys(local.names), keys(local.attached_disks)) : for k, v in local.attached_disks :
"${pair[0]}-${pair[1]}" => { disk_name = pair[1], name = pair[0] } k => v if try(v.options.replica_zone, null) != null
} }
attached_region_disks_pairs = { attached_disks_zonal = {
for k, v in local.attached_disks_pairs : for k, v in local.attached_disks :
k => v if local.attached_disks[v.disk_name].options.regional k => v if try(v.options.replica_zone, null) == null
}
attached_zone_disks_pairs = {
for k, v in local.attached_disks_pairs :
k => v if !local.attached_disks[v.disk_name].options.regional
} }
on_host_maintenance = ( on_host_maintenance = (
var.options.preemptible || var.confidential_compute var.options.preemptible || var.confidential_compute
? "TERMINATE" ? "TERMINATE"
: "MIGRATE" : "MIGRATE"
) )
iam_members = var.use_instance_template ? {} : { region = join("-", slice(split("-", var.zone), 0, 2))
for pair in setproduct(keys(var.iam), keys(local.names)) :
"${pair.0}/${pair.1}" => { role = pair.0, name = pair.1, members = var.iam[pair.0] }
}
names = (
var.use_instance_template
? { (var.name) = 0 }
: (
var.single_name && var.instance_count == 1
? { (var.name) = 0 }
: { for i in range(0, var.instance_count) : "${var.name}-${i + 1}" => i }
)
)
service_account_email = ( service_account_email = (
var.service_account_create var.service_account_create
? ( ? (
@ -76,38 +60,23 @@ locals {
] ]
) )
) )
zones_list = length(var.zones) == 0 ? ["${var.region}-b"] : var.zones
zones = {
for name, i in local.names : name => element(local.zones_list, i)
}
} }
resource "google_compute_disk" "disks" { resource "google_compute_disk" "disks" {
for_each = var.use_instance_template ? {} : { for_each = var.create_template ? {} : {
for k, v in local.attached_zone_disks_pairs : for k, v in local.attached_disks_zonal :
k => v if local.attached_disks[v.disk_name].source_type != "attach" k => v if v.source_type != "attach"
} }
project = var.project_id project = var.project_id
zone = local.zones[each.value.name] zone = var.zone
name = each.key name = "${var.name}-${each.key}"
type = local.attached_disks[each.value.disk_name].options.type type = each.value.options.type
size = local.attached_disks[each.value.disk_name].size size = each.value.size
image = ( image = each.value.source_type == "image" ? each.value.source : null
local.attached_disks[each.value.disk_name].source_type == "image" snapshot = each.value.source_type == "snapshot" ? each.value.source : null
? local.attached_disks[each.value.disk_name].source
: null
)
snapshot = (
local.attached_disks[each.value.disk_name].source_type == "snapshot"
? local.attached_disks[each.value.disk_name].source
: null
)
labels = merge(var.labels, { labels = merge(var.labels, {
disk_name = local.attached_disks[each.value.disk_name].name disk_name = each.value.name
disk_type = local.attached_disks[each.value.disk_name].options.type disk_type = each.value.options.type
# Disk images usually have slashes, which is against label
# restrictions
# image = local.attached_disks[each.value.disk_name].image
}) })
dynamic "disk_encryption_key" { dynamic "disk_encryption_key" {
for_each = var.encryption != null ? [""] : [] for_each = var.encryption != null ? [""] : []
@ -120,29 +89,27 @@ resource "google_compute_disk" "disks" {
resource "google_compute_region_disk" "disks" { resource "google_compute_region_disk" "disks" {
provider = google-beta provider = google-beta
for_each = var.use_instance_template ? {} : { for_each = var.create_template ? {} : {
for k, v in local.attached_region_disks_pairs : for k, v in local.attached_disks_regional :
k => v if local.attached_disks[v.disk_name].source_type != "attach" k => v if v.source_type != "attach"
} }
project = var.project_id project = var.project_id
region = var.region region = local.region
replica_zones = var.zones replica_zones = [var.zone, each.value.options.replica_zone]
name = each.key name = "${var.name}-${each.key}"
type = local.attached_disks[each.value.disk_name].options.type type = each.value.options.type
size = local.attached_disks[each.value.disk_name].size size = each.value.size
snapshot = ( # image = each.value.source_type == "image" ? each.value.source : null
local.attached_disks[each.value.disk_name].source_type == "snapshot" snapshot = each.value.source_type == "snapshot" ? each.value.source : null
? local.attached_disks[each.value.disk_name].source
: null
)
labels = merge(var.labels, { labels = merge(var.labels, {
disk_name = local.attached_disks[each.value.disk_name].name disk_name = each.value.name
disk_type = local.attached_disks[each.value.disk_name].options.type disk_type = each.value.options.type
}) })
dynamic "disk_encryption_key" { dynamic "disk_encryption_key" {
for_each = var.encryption != null ? [""] : [] for_each = var.encryption != null ? [""] : []
content { content {
raw_key = var.encryption.disk_encryption_key_raw raw_key = var.encryption.disk_encryption_key_raw
# TODO: check if self link works here
kms_key_name = var.encryption.kms_key_self_link kms_key_name = var.encryption.kms_key_self_link
} }
} }
@ -150,10 +117,10 @@ resource "google_compute_region_disk" "disks" {
resource "google_compute_instance" "default" { resource "google_compute_instance" "default" {
provider = google-beta provider = google-beta
for_each = var.use_instance_template ? {} : local.names count = var.create_template ? 0 : 1
project = var.project_id project = var.project_id
zone = local.zones[each.key] zone = var.zone
name = each.key name = var.name
hostname = var.hostname hostname = var.hostname
description = "Managed by the compute-vm Terraform module." description = "Managed by the compute-vm Terraform module."
tags = var.tags tags = var.tags
@ -164,16 +131,10 @@ resource "google_compute_instance" "default" {
deletion_protection = var.options.deletion_protection deletion_protection = var.options.deletion_protection
enable_display = var.enable_display enable_display = var.enable_display
labels = var.labels labels = var.labels
metadata = merge( metadata = var.metadata
var.metadata, try(element(var.metadata_list, each.value), {})
)
dynamic "attached_disk" { dynamic "attached_disk" {
for_each = { for_each = local.attached_disks_zonal
for resource_name, pair in local.attached_disks_pairs :
resource_name => local.attached_disks[pair.disk_name]
if pair.name == each.key
}
iterator = config iterator = config
content { content {
device_name = config.value.name device_name = config.value.name
@ -181,16 +142,27 @@ resource "google_compute_instance" "default" {
source = ( source = (
config.value.source_type == "attach" config.value.source_type == "attach"
? config.value.source ? config.value.source
: (
config.value.options.regional
? google_compute_region_disk.disks[config.key].id
: google_compute_disk.disks[config.key].name : google_compute_disk.disks[config.key].name
) )
}
}
dynamic "attached_disk" {
for_each = local.attached_disks_regional
iterator = config
content {
device_name = config.value.name
mode = config.value.options.mode
source = (
config.value.source_type == "attach"
? config.value.source
: google_compute_region_disk.disks[config.key].name
) )
} }
} }
boot_disk { boot_disk {
auto_delete = var.boot_disk_delete
initialize_params { initialize_params {
type = var.boot_disk.type type = var.boot_disk.type
image = var.boot_disk.image image = var.boot_disk.image
@ -213,26 +185,19 @@ resource "google_compute_instance" "default" {
content { content {
network = config.value.network network = config.value.network
subnetwork = config.value.subnetwork subnetwork = config.value.subnetwork
network_ip = config.value.addresses == null ? null : ( network_ip = try(config.value.addresses.internal, null)
length(config.value.addresses.internal) == 0
? null
: config.value.addresses.internal[each.value]
)
dynamic "access_config" { dynamic "access_config" {
for_each = config.value.nat ? [config.value.addresses] : [] for_each = config.value.nat ? [""] : []
iterator = addresses
content { content {
nat_ip = addresses.value == null ? null : ( nat_ip = try(config.value.addresses.external, null)
length(addresses.value.external) == 0 ? null : addresses.value.external[each.value]
)
} }
} }
dynamic "alias_ip_range" { dynamic "alias_ip_range" {
for_each = config.value.alias_ips != null ? config.value.alias_ips : {} for_each = config.value.alias_ips != null ? config.value.alias_ips : {}
iterator = alias_ips iterator = config_alias
content { content {
subnetwork_range_name = alias_ips.key subnetwork_range_name = config_alias.key
ip_cidr_range = alias_ips.value[each.value] ip_cidr_range = config_alias.value
} }
} }
} }
@ -273,20 +238,20 @@ resource "google_compute_instance" "default" {
} }
resource "google_compute_instance_iam_binding" "default" { resource "google_compute_instance_iam_binding" "default" {
for_each = local.iam_members
project = var.project_id project = var.project_id
zone = local.zones[each.value.name] for_each = var.iam
instance_name = each.value.name zone = var.zone
role = each.value.role instance_name = var.name
members = each.value.members role = each.key
members = each.value
depends_on = [google_compute_instance.default] depends_on = [google_compute_instance.default]
} }
resource "google_compute_instance_template" "default" { resource "google_compute_instance_template" "default" {
provider = google-beta provider = google-beta
count = var.use_instance_template ? 1 : 0 count = var.create_template ? 1 : 0
project = var.project_id project = var.project_id
region = var.region region = local.region
name_prefix = "${var.name}-" name_prefix = "${var.name}-"
description = "Managed by the compute-vm Terraform module." description = "Managed by the compute-vm Terraform module."
tags = var.tags tags = var.tags
@ -297,10 +262,11 @@ resource "google_compute_instance_template" "default" {
labels = var.labels labels = var.labels
disk { disk {
source_image = var.boot_disk.image auto_delete = var.boot_disk_delete
disk_type = var.boot_disk.type
disk_size_gb = var.boot_disk.size
boot = true boot = true
disk_size_gb = var.boot_disk.size
disk_type = var.boot_disk.type
source_image = var.boot_disk.image
} }
dynamic "confidential_instance_config" { dynamic "confidential_instance_config" {
@ -314,7 +280,7 @@ resource "google_compute_instance_template" "default" {
for_each = local.attached_disks for_each = local.attached_disks
iterator = config iterator = config
content { content {
auto_delete = config.value.options.auto_delete # auto_delete = config.value.options.auto_delete
device_name = config.value.name device_name = config.value.name
# Cannot use `source` with any of the fields in # Cannot use `source` with any of the fields in
# [disk_size_gb disk_name disk_type source_image labels] # [disk_size_gb disk_name disk_type source_image labels]
@ -344,9 +310,20 @@ resource "google_compute_instance_template" "default" {
content { content {
network = config.value.network network = config.value.network
subnetwork = config.value.subnetwork subnetwork = config.value.subnetwork
network_ip = try(config.value.addresses.internal, null)
dynamic "access_config" { dynamic "access_config" {
for_each = config.value.nat ? [""] : [] for_each = config.value.nat ? [""] : []
content {} content {
nat_ip = try(config.value.addresses.external, null)
}
}
dynamic "alias_ip_range" {
for_each = config.value.alias_ips != null ? config.value.alias_ips : {}
iterator = config_alias
content {
subnetwork_range_name = config_alias.key
ip_cidr_range = config_alias.value
}
} }
} }
} }
@ -368,24 +345,17 @@ resource "google_compute_instance_template" "default" {
} }
resource "google_compute_instance_group" "unmanaged" { resource "google_compute_instance_group" "unmanaged" {
for_each = toset( count = var.group != null && !var.create_template ? 1 : 0
var.group != null && !var.use_instance_template
? local.zones_list
: []
)
project = var.project_id project = var.project_id
network = ( network = (
length(var.network_interfaces) > 0 length(var.network_interfaces) > 0
? var.network_interfaces.0.network ? var.network_interfaces.0.network
: "" : ""
) )
zone = each.key zone = var.zone
name = "${var.name}-${each.key}" name = var.name
description = "Terraform-managed." description = "Terraform-managed."
instances = [ instances = [google_compute_instance.default.0.self_link]
for name, instance in google_compute_instance.default :
instance.self_link if instance.zone == each.key
]
dynamic "named_port" { dynamic "named_port" {
for_each = var.group.named_ports != null ? var.group.named_ports : {} for_each = var.group.named_ports != null ? var.group.named_ports : {}
iterator = config iterator = config

View File

@ -14,50 +14,42 @@
* limitations under the License. * limitations under the License.
*/ */
output "external_ips" { output "external_ip" {
description = "Instance main interface external IP addresses." description = "Instance main interface external IP addresses."
value = ( value = (
var.network_interfaces[0].nat var.network_interfaces[0].nat
? [ ? try(google_compute_instance.default.0.network_interface.0.access_config.0.nat_ip, null)
for name, instance in google_compute_instance.default : : null
try(instance.network_interface.0.access_config.0.nat_ip, null)
]
: []
) )
} }
output "groups" { output "group" {
description = "Instance group resources." description = "Instance group resource."
value = google_compute_instance_group.unmanaged value = try(google_compute_instance_group.unmanaged.0, null)
} }
output "instances" { output "instance" {
description = "Instance resources." description = "Instance resource."
value = [for name, instance in google_compute_instance.default : instance] value = try(google_compute_instance.default.0, null)
} }
output "internal_ips" { output "internal_ip" {
description = "Instance main interface internal IP addresses." description = "Instance main interface internal IP address."
value = [ value = try(
for name, instance in google_compute_instance.default : google_compute_instance.default.0.network_interface.0.network_ip,
instance.network_interface.0.network_ip null
] )
} }
output "names" { output "self_link" {
description = "Instance names."
value = [for name, instance in google_compute_instance.default : instance.name]
}
output "self_links" {
description = "Instance self links." description = "Instance self links."
value = [for name, instance in google_compute_instance.default : instance.self_link] value = try(google_compute_instance.default.0.self_link, null)
} }
output "service_account" { output "service_account" {
description = "Service account resource." description = "Service account resource."
value = ( value = (
var.service_account_create ? google_service_account.service_account[0] : null var.service_account_create ? google_service_account.service_account.0 : null
) )
} }
@ -76,18 +68,10 @@ output "service_account_iam_email" {
output "template" { output "template" {
description = "Template resource." description = "Template resource."
value = ( value = try(google_compute_instance_template.default.0, null)
length(google_compute_instance_template.default) > 0
? google_compute_instance_template.default[0]
: null
)
} }
output "template_name" { output "template_name" {
description = "Template name." description = "Template name."
value = ( value = try(google_compute_instance_template.default.0.name, null)
length(google_compute_instance_template.default) > 0
? google_compute_instance_template.default[0].name
: null
)
} }

View File

@ -22,9 +22,8 @@ variable "attached_disks" {
source = string source = string
source_type = string source_type = string
options = object({ options = object({
auto_delete = bool
mode = string mode = string
regional = bool replica_zone = string
type = string type = string
}) })
})) }))
@ -44,16 +43,15 @@ variable "attached_disks" {
variable "attached_disk_defaults" { variable "attached_disk_defaults" {
description = "Defaults for attached disks options." description = "Defaults for attached disks options."
type = object({ type = object({
auto_delete = bool
mode = string mode = string
regional = bool replica_zone = string
type = string type = string
}) })
default = { default = {
auto_delete = true auto_delete = true
mode = "READ_WRITE" mode = "READ_WRITE"
regional = false replica_zone = null
type = "pd-ssd" type = "pd-balanced"
} }
} }
@ -65,12 +63,18 @@ variable "boot_disk" {
type = string type = string
}) })
default = { default = {
image = "projects/debian-cloud/global/images/family/debian-10" image = "projects/debian-cloud/global/images/family/debian-11"
type = "pd-ssd" type = "pd-balanced"
size = 10 size = 10
} }
} }
variable "boot_disk_delete" {
description = "Auto delete boot disk."
type = bool
default = true
}
variable "can_ip_forward" { variable "can_ip_forward" {
description = "Enable IP forwarding." description = "Enable IP forwarding."
type = bool type = bool
@ -83,6 +87,12 @@ variable "confidential_compute" {
default = false default = false
} }
variable "create_template" {
description = "Create instance template instead of instances."
type = bool
default = false
}
variable "enable_display" { variable "enable_display" {
description = "Enable virtual display on the instances" description = "Enable virtual display on the instances"
type = bool type = bool
@ -119,12 +129,6 @@ variable "iam" {
default = {} default = {}
} }
variable "instance_count" {
description = "Number of instances to create (only for non-template usage)."
type = number
default = 1
}
variable "instance_type" { variable "instance_type" {
description = "Instance type." description = "Instance type."
type = string type = string
@ -143,12 +147,6 @@ variable "metadata" {
default = {} default = {}
} }
variable "metadata_list" {
description = "List of instance metadata that will be cycled through. Ignored for template use."
type = list(map(string))
default = []
}
variable "min_cpu_platform" { variable "min_cpu_platform" {
description = "Minimum CPU platform." description = "Minimum CPU platform."
type = string type = string
@ -156,7 +154,7 @@ variable "min_cpu_platform" {
} }
variable "name" { variable "name" {
description = "Instances base name." description = "Instance name."
type = string type = string
} }
@ -167,10 +165,10 @@ variable "network_interfaces" {
network = string network = string
subnetwork = string subnetwork = string
addresses = object({ addresses = object({
internal = list(string) internal = string
external = list(string) external = string
}) })
alias_ips = map(list(string)) alias_ips = map(string)
})) }))
} }
@ -193,11 +191,6 @@ variable "project_id" {
type = string type = string
} }
variable "region" {
description = "Compute region."
type = string
}
variable "scratch_disks" { variable "scratch_disks" {
description = "Scratch disks configuration." description = "Scratch disks configuration."
type = object({ type = object({
@ -230,30 +223,6 @@ variable "service_account_scopes" {
default = [] default = []
} }
variable "single_name" {
description = "Do not append progressive count to instance name."
type = bool
default = false
}
variable "tags" {
description = "Instance tags."
type = list(string)
default = []
}
variable "use_instance_template" {
description = "Create instance template instead of instances."
type = bool
default = false
}
variable "zones" {
description = "Compute zone, instance will cycle through the list, defaults to the 'b' zone in the region."
type = list(string)
default = []
}
variable "shielded_config" { variable "shielded_config" {
description = "Shielded VM configuration of the instances." description = "Shielded VM configuration of the instances."
type = object({ type = object({
@ -263,3 +232,14 @@ variable "shielded_config" {
}) })
default = null default = null
} }
variable "tags" {
description = "Instance tags."
type = list(string)
default = []
}
variable "zone" {
description = "Compute zone."
type = string
}

View File

@ -67,10 +67,10 @@ module "cos-nginx" {
module "instance-group" { module "instance-group" {
source = "./modules/compute-vm" source = "./modules/compute-vm"
for_each = toset(["b", "c"])
project_id = var.project_id project_id = var.project_id
region = "europe-west1" zone = "europe-west1-${each.key}"
zones = ["europe-west1-b", "europe-west1-c"] name = "ilb-test-${each.key}"
name = "ilb-test"
network_interfaces = [{ network_interfaces = [{
network = var.vpc.self_link network = var.vpc.self_link
subnetwork = var.subnet.self_link subnetwork = var.subnet.self_link
@ -100,9 +100,9 @@ module "ilb" {
subnetwork = var.subnet.self_link subnetwork = var.subnet.self_link
ports = [80] ports = [80]
backends = [ backends = [
for name, group in module.instance-group.groups : { for z, mod in module.instance-group : {
failover = false failover = false
group = group.self_link group = mod.group.self_link
balancing_mode = "CONNECTION" balancing_mode = "CONNECTION"
} }
] ]
@ -110,7 +110,7 @@ module "ilb" {
type = "http", check = { port = 80 }, config = {}, logging = true type = "http", check = { port = 80 }, config = {}, logging = true
} }
} }
# tftest:modules=2:resources=6 # tftest:modules=3:resources=7
``` ```
<!-- BEGIN TFDOC --> <!-- BEGIN TFDOC -->

View File

@ -18,7 +18,7 @@ locals {
squid_address = ( squid_address = (
var.mig var.mig
? module.squid-ilb.0.forwarding_rule_address ? module.squid-ilb.0.forwarding_rule_address
: module.squid-vm.internal_ips.0 : module.squid-vm.internal_ip
) )
} }
@ -149,9 +149,10 @@ module "cos-squid" {
module "squid-vm" { module "squid-vm" {
source = "../../modules/compute-vm" source = "../../modules/compute-vm"
project_id = module.project-host.project_id project_id = module.project-host.project_id
region = var.region zone = "${var.region}-b"
name = "squid-vm" name = "squid-vm"
instance_type = "e2-medium" instance_type = "e2-medium"
create_template = var.mig
network_interfaces = [{ network_interfaces = [{
network = module.vpc.self_link network = module.vpc.self_link
subnetwork = module.vpc.subnet_self_links["${var.region}/proxy"] subnetwork = module.vpc.subnet_self_links["${var.region}/proxy"]
@ -166,7 +167,6 @@ module "squid-vm" {
} }
service_account = module.service-account-squid.email service_account = module.service-account-squid.email
service_account_scopes = ["https://www.googleapis.com/auth/cloud-platform"] service_account_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
use_instance_template = var.mig
metadata = { metadata = {
user-data = module.cos-squid.cloud_config user-data = module.cos-squid.cloud_config
} }
@ -261,7 +261,7 @@ module "project-app" {
module "test-vm" { module "test-vm" {
source = "../../modules/compute-vm" source = "../../modules/compute-vm"
project_id = module.project-app.project_id project_id = module.project-app.project_id
region = var.region zone = "${var.region}-b"
name = "test-vm" name = "test-vm"
instance_type = "e2-micro" instance_type = "e2-micro"
tags = ["ssh"] tags = ["ssh"]

View File

@ -14,11 +14,11 @@
locals { locals {
prefix = var.prefix != null && var.prefix != "" ? "${var.prefix}-" : "" prefix = var.prefix != null && var.prefix != "" ? "${var.prefix}-" : ""
vm-instances = concat( vm-instances = [
module.vm-hub.instances, module.vm-hub.instance,
module.vm-spoke-1.instances, module.vm-spoke-1.instance,
module.vm-spoke-2.instances module.vm-spoke-2.instance
) ]
vm-startup-script = join("\n", [ vm-startup-script = join("\n", [
"#! /bin/bash", "#! /bin/bash",
"apt-get update && apt-get install -y bash-completion dnsutils kubectl" "apt-get update && apt-get install -y bash-completion dnsutils kubectl"
@ -178,7 +178,7 @@ module "hub-to-spoke-2-peering" {
module "vm-hub" { module "vm-hub" {
source = "../../modules/compute-vm" source = "../../modules/compute-vm"
project_id = module.project.project_id project_id = module.project.project_id
region = var.region zone = "${var.region}-b"
name = "${local.prefix}hub" name = "${local.prefix}hub"
network_interfaces = [{ network_interfaces = [{
network = module.vpc-hub.self_link network = module.vpc-hub.self_link
@ -196,7 +196,7 @@ module "vm-hub" {
module "vm-spoke-1" { module "vm-spoke-1" {
source = "../../modules/compute-vm" source = "../../modules/compute-vm"
project_id = module.project.project_id project_id = module.project.project_id
region = var.region zone = "${var.region}-b"
name = "${local.prefix}spoke-1" name = "${local.prefix}spoke-1"
network_interfaces = [{ network_interfaces = [{
network = module.vpc-spoke-1.self_link network = module.vpc-spoke-1.self_link
@ -214,7 +214,7 @@ module "vm-spoke-1" {
module "vm-spoke-2" { module "vm-spoke-2" {
source = "../../modules/compute-vm" source = "../../modules/compute-vm"
project_id = module.project.project_id project_id = module.project.project_id
region = var.region zone = "${var.region}-b"
name = "${local.prefix}spoke-2" name = "${local.prefix}spoke-2"
network_interfaces = [{ network_interfaces = [{
network = module.vpc-spoke-2.self_link network = module.vpc-spoke-2.self_link

View File

@ -13,10 +13,10 @@
# limitations under the License. # limitations under the License.
locals { locals {
vm-instances = concat( vm-instances = [
module.vm-spoke-1.instances, module.vm-spoke-1.instance,
module.vm-spoke-2.instances module.vm-spoke-2.instance
) ]
vm-startup-script = join("\n", [ vm-startup-script = join("\n", [
"#! /bin/bash", "#! /bin/bash",
"apt-get update && apt-get install -y dnsutils" "apt-get update && apt-get install -y dnsutils"
@ -250,7 +250,7 @@ module "nat-spoke-2" {
module "vm-spoke-1" { module "vm-spoke-1" {
source = "../../modules/compute-vm" source = "../../modules/compute-vm"
project_id = var.project_id project_id = var.project_id
region = var.regions.b zone = "${var.regions.b}-b"
name = "spoke-1-test" name = "spoke-1-test"
network_interfaces = [{ network_interfaces = [{
network = module.vpc-spoke-1.self_link network = module.vpc-spoke-1.self_link
@ -266,7 +266,7 @@ module "vm-spoke-1" {
module "vm-spoke-2" { module "vm-spoke-2" {
source = "../../modules/compute-vm" source = "../../modules/compute-vm"
project_id = var.project_id project_id = var.project_id
region = var.regions.b zone = "${var.regions.b}-b"
name = "spoke-2-test" name = "spoke-2-test"
network_interfaces = [{ network_interfaces = [{
network = module.vpc-spoke-2.self_link network = module.vpc-spoke-2.self_link
@ -290,11 +290,13 @@ module "dns-host" {
name = "example" name = "example"
domain = "example.com." domain = "example.com."
client_networks = [module.vpc-hub.self_link] client_networks = [module.vpc-hub.self_link]
# setting instance IPs at first apply fails due to dynamic values
recordsets = [ recordsets = [
for instance in local.vm-instances : { { name = "localhost", type = "A", ttl = 300, records = ["127.0.0.1"] }
name = instance.name, type = "A", ttl = 300, # for instance in local.vm-instances : {
records = [instance.network_interface.0.network_ip] # name = instance.name, type = "A", ttl = 300,
} # records = [instance.network_interface.0.network_ip]
# }
] ]
} }

View File

@ -16,10 +16,10 @@
module "gw" { module "gw" {
source = "../../modules/compute-vm" source = "../../modules/compute-vm"
for_each = local.zones
project_id = module.project.project_id project_id = module.project.project_id
region = var.region zone = each.value
zones = local.zones name = "${local.prefix}gw-${each.key}"
name = "${local.prefix}gw"
instance_type = "f1-micro" instance_type = "f1-micro"
boot_disk = { boot_disk = {
@ -56,7 +56,6 @@ module "gw" {
module.service-accounts.emails["${local.prefix}gce-vm"], null module.service-accounts.emails["${local.prefix}gce-vm"], null
) )
service_account_scopes = ["https://www.googleapis.com/auth/cloud-platform"] service_account_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
instance_count = 2
group = { named_ports = null } group = { named_ports = null }
} }
@ -74,9 +73,9 @@ module "ilb-left" {
timeout_sec = null timeout_sec = null
connection_draining_timeout_sec = null connection_draining_timeout_sec = null
} }
backends = [for zone, group in module.gw.groups : { backends = [for z, mod in module.gw : {
failover = false failover = false
group = group.self_link group = mod.group.self_link
balancing_mode = "CONNECTION" balancing_mode = "CONNECTION"
}] }]
health_check_config = { health_check_config = {
@ -98,9 +97,9 @@ module "ilb-right" {
timeout_sec = null timeout_sec = null
connection_draining_timeout_sec = null connection_draining_timeout_sec = null
} }
backends = [for zone, group in module.gw.groups : { backends = [for z, mod in module.gw : {
failover = false failover = false
group = group.self_link group = mod.group.self_link
balancing_mode = "CONNECTION" balancing_mode = "CONNECTION"
}] }]
health_check_config = { health_check_config = {

View File

@ -20,7 +20,7 @@ locals {
trimprefix(k, local.prefix) => v.address trimprefix(k, local.prefix) => v.address
} }
prefix = var.prefix == null || var.prefix == "" ? "" : "${var.prefix}-" prefix = var.prefix == null || var.prefix == "" ? "" : "${var.prefix}-"
zones = [for z in var.zones : "${var.region}-${z}"] zones = { for z in var.zones : z => "${var.region}-${z}" }
} }
module "project" { module "project" {

View File

@ -17,11 +17,11 @@
output "addresses" { output "addresses" {
description = "IP addresses." description = "IP addresses."
value = { value = {
gw = module.gw.internal_ips gw = [for z, mod in module.gw : mod.internal_ip]
ilb-left = module.ilb-left.forwarding_rule_address ilb-left = module.ilb-left.forwarding_rule_address
ilb-right = module.ilb-right.forwarding_rule_address ilb-right = module.ilb-right.forwarding_rule_address
vm-left = module.vm-left.internal_ips vm-left = [for z, mod in module.vm-left : mod.internal_ip]
vm-right = module.vm-right.internal_ips vm-right = [for z, mod in module.vm-right : mod.internal_ip]
} }
} }
@ -48,23 +48,23 @@ output "backend_health_right" {
output "ssh_gw" { output "ssh_gw" {
description = "Command-line login to gateway VMs." description = "Command-line login to gateway VMs."
value = [ value = [
for name, instance in module.gw.instances : for z, mod in module.gw :
"gcloud compute ssh ${instance.name} --project ${var.project_id} --zone ${instance.zone}" "gcloud compute ssh ${mod.instance.name} --project ${var.project_id} --zone ${mod.instance.zone}"
] ]
} }
output "ssh_vm_left" { output "ssh_vm_left" {
description = "Command-line login to left VMs." description = "Command-line login to left VMs."
value = [ value = [
for name, instance in module.vm-left.instances : for z, mod in module.vm-left :
"gcloud compute ssh ${instance.name} --project ${var.project_id} --zone ${instance.zone}" "gcloud compute ssh ${mod.instance.name} --project ${var.project_id} --zone ${mod.instance.zone}"
] ]
} }
output "ssh_vm_right" { output "ssh_vm_right" {
description = "Command-line login to right VMs." description = "Command-line login to right VMs."
value = [ value = [
for name, instance in module.vm-right.instances : for z, mod in module.vm-right :
"gcloud compute ssh ${instance.name} --project ${var.project_id} --zone ${instance.zone}" "gcloud compute ssh ${mod.instance.name} --project ${var.project_id} --zone ${mod.instance.zone}"
] ]
} }

View File

@ -24,10 +24,10 @@ END
module "vm-left" { module "vm-left" {
source = "../../modules/compute-vm" source = "../../modules/compute-vm"
for_each = local.zones
project_id = module.project.project_id project_id = module.project.project_id
region = var.region zone = each.value
zones = local.zones name = "${local.prefix}vm-left-${each.key}"
name = "${local.prefix}vm-left"
instance_type = "f1-micro" instance_type = "f1-micro"
network_interfaces = [ network_interfaces = [
{ {
@ -46,15 +46,14 @@ module "vm-left" {
module.service-accounts.email, null module.service-accounts.email, null
) )
service_account_scopes = ["https://www.googleapis.com/auth/cloud-platform"] service_account_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
instance_count = 2
} }
module "vm-right" { module "vm-right" {
source = "../../modules/compute-vm" source = "../../modules/compute-vm"
for_each = local.zones
project_id = module.project.project_id project_id = module.project.project_id
region = var.region zone = each.value
name = "${local.prefix}vm-right" name = "${local.prefix}vm-right-${each.key}"
zones = local.zones
instance_type = "f1-micro" instance_type = "f1-micro"
network_interfaces = [ network_interfaces = [
{ {
@ -73,5 +72,4 @@ module "vm-right" {
module.service-accounts.email, null module.service-accounts.email, null
) )
service_account_scopes = ["https://www.googleapis.com/auth/cloud-platform"] service_account_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
instance_count = 2
} }

View File

@ -39,14 +39,14 @@ module "vpc-right" {
priority = null priority = null
tags = null tags = null
next_hop_type = "instance" next_hop_type = "instance"
next_hop = module.gw.instances.0.self_link next_hop = module.gw[var.zones[0]].self_link
} }
to-left-gw-2 = { to-left-gw-2 = {
dest_range = var.ip_ranges.left dest_range = var.ip_ranges.left
priority = null priority = null
tags = null tags = null
next_hop_type = "instance" next_hop_type = "instance"
next_hop = module.gw.instances.1.self_link next_hop = module.gw[var.zones[1]].self_link
} }
} }
} }

View File

@ -104,7 +104,7 @@ module "vpn1" {
} }
bgp_session_range = "${local.bgp_interface_gcp1}/30" bgp_session_range = "${local.bgp_interface_gcp1}/30"
ike_version = 2 ike_version = 2
peer_ip = module.vm-onprem.external_ips.0 peer_ip = module.vm-onprem.external_ip
router = null router = null
shared_secret = "" shared_secret = ""
} }
@ -136,7 +136,7 @@ module "vpn2" {
} }
bgp_session_range = "${local.bgp_interface_gcp2}/30" bgp_session_range = "${local.bgp_interface_gcp2}/30"
ike_version = 2 ike_version = 2
peer_ip = module.vm-onprem.external_ips.0 peer_ip = module.vm-onprem.external_ip
router = null router = null
shared_secret = "" shared_secret = ""
} }
@ -173,14 +173,17 @@ module "dns-gcp" {
client_networks = [module.vpc.self_link] client_networks = [module.vpc.self_link]
recordsets = concat( recordsets = concat(
[{ name = "localhost", type = "A", ttl = 300, records = ["127.0.0.1"] }], [{ name = "localhost", type = "A", ttl = 300, records = ["127.0.0.1"] }],
[ # setting addresses during first apply triggers a dynamic value error
for name, ip in zipmap(module.vm-test1.names, module.vm-test1.internal_ips) : # [
{ name = name, type = "A", ttl = 300, records = [ip] } # {
], # name = module.vm-test1.instance.name, type = "A", ttl = 300,
[ # records = [module.vm-test1.internal_ip]
for name, ip in zipmap(module.vm-test2.names, module.vm-test2.internal_ips) : # },
{ name = name, type = "A", ttl = 300, records = [ip] } # {
] # name = module.vm-test2.instance.name, type = "A", ttl = 300,
# records = [module.vm-test2.internal_ip]
# }
# ]
) )
} }
@ -239,7 +242,7 @@ module "service-account-gce" {
module "vm-test1" { module "vm-test1" {
source = "../../modules/compute-vm" source = "../../modules/compute-vm"
project_id = var.project_id project_id = var.project_id
region = var.region.gcp1 zone = "${var.region.gcp1}-b"
name = "test-1" name = "test-1"
network_interfaces = [{ network_interfaces = [{
network = module.vpc.self_link network = module.vpc.self_link
@ -257,7 +260,7 @@ module "vm-test1" {
module "vm-test2" { module "vm-test2" {
source = "../../modules/compute-vm" source = "../../modules/compute-vm"
project_id = var.project_id project_id = var.project_id
region = var.region.gcp2 zone = "${var.region.gcp2}-b"
name = "test-2" name = "test-2"
network_interfaces = [{ network_interfaces = [{
network = module.vpc.self_link network = module.vpc.self_link
@ -316,7 +319,7 @@ module "service-account-onprem" {
module "vm-onprem" { module "vm-onprem" {
source = "../../modules/compute-vm" source = "../../modules/compute-vm"
project_id = var.project_id project_id = var.project_id
region = var.region.gcp1 zone = "${var.region.gcp1}-b"
instance_type = "f1-micro" instance_type = "f1-micro"
name = "onprem" name = "onprem"
boot_disk = { boot_disk = {

View File

@ -17,23 +17,23 @@
output "onprem-instance" { output "onprem-instance" {
description = "Onprem instance details." description = "Onprem instance details."
value = { value = {
external_ip = module.vm-onprem.external_ips.0 external_ip = module.vm-onprem.external_ip
internal_ip = module.vm-onprem.internal_ips.0 internal_ip = module.vm-onprem.internal_ip
name = module.vm-onprem.names.0 name = module.vm-onprem.instance.name
} }
} }
output "test-instance1" { output "test-instance1" {
description = "Test instance details." description = "Test instance details."
value = join(" ", [ value = join(" ", [
module.vm-test1.names[0], module.vm-test1.instance.name,
module.vm-test1.internal_ips[0] module.vm-test1.internal_ip
]) ])
} }
output "test-instance2" { output "test-instance2" {
description = "Test instance details." description = "Test instance details."
value = join(" ", [ value = join(" ", [
module.vm-test2.names[0], module.vm-test2.instance.name,
module.vm-test2.internal_ips[0] module.vm-test2.internal_ip
]) ])
} }

View File

@ -177,7 +177,7 @@ module "vpn-hub" {
module "test-vm" { module "test-vm" {
source = "../../modules/compute-vm" source = "../../modules/compute-vm"
project_id = module.project.project_id project_id = module.project.project_id
region = var.region zone = "${var.region}-b"
name = "${var.name}-test" name = "${var.name}-test"
instance_type = "e2-micro" instance_type = "e2-micro"
boot_disk = { boot_disk = {
@ -192,7 +192,6 @@ module "test-vm" {
network = module.vpc-onprem.self_link network = module.vpc-onprem.self_link
subnetwork = module.vpc-onprem.subnet_self_links["${var.region}/${var.name}-onprem"] subnetwork = module.vpc-onprem.subnet_self_links["${var.region}/${var.name}-onprem"]
}] }]
single_name = true
tags = ["ssh"] tags = ["ssh"]
} }

View File

@ -159,7 +159,7 @@ module "host-dns" {
client_networks = [module.vpc-shared.self_link] client_networks = [module.vpc-shared.self_link]
recordsets = [ recordsets = [
{ name = "localhost", type = "A", ttl = 300, records = ["127.0.0.1"] }, { name = "localhost", type = "A", ttl = 300, records = ["127.0.0.1"] },
{ name = "bastion", type = "A", ttl = 300, records = module.vm-bastion.internal_ips }, # { name = "bastion", type = "A", ttl = 300, records = [module.vm-bastion.internal_ip] },
] ]
} }
@ -170,7 +170,7 @@ module "host-dns" {
module "vm-bastion" { module "vm-bastion" {
source = "../../modules/compute-vm" source = "../../modules/compute-vm"
project_id = module.project-svc-gce.project_id project_id = module.project-svc-gce.project_id
region = var.region zone = "${var.region}-b"
name = "bastion" name = "bastion"
network_interfaces = [{ network_interfaces = [{
network = module.vpc-shared.self_link network = module.vpc-shared.self_link
@ -179,7 +179,6 @@ module "vm-bastion" {
addresses = null addresses = null
alias_ips = null alias_ips = null
}] }]
instance_count = 1
tags = ["ssh"] tags = ["ssh"]
metadata = { metadata = {
startup-script = join("\n", [ startup-script = join("\n", [

View File

@ -41,8 +41,7 @@ output "vpc" {
output "vms" { output "vms" {
description = "GCE VMs." description = "GCE VMs."
value = { value = {
for instance in concat(module.vm-bastion.instances) : (module.vm-bastion.instance.name) = module.vm-bastion.internal_ip
instance.name => instance.network_interface.0.network_ip
} }
} }

View File

@ -24,4 +24,4 @@ def test_resources(e2e_plan_runner):
"Test that plan works and the numbers of resources is as expected." "Test that plan works and the numbers of resources is as expected."
modules, resources = e2e_plan_runner(FIXTURES_DIR) modules, resources = e2e_plan_runner(FIXTURES_DIR)
assert len(modules) == 14 assert len(modules) == 14
assert len(resources) == 62 assert len(resources) == 60

View File

@ -17,17 +17,15 @@
module "test" { module "test" {
source = "../../../../modules/compute-vm" source = "../../../../modules/compute-vm"
project_id = "my-project" project_id = "my-project"
region = "europe-west1" zone = "europe-west1-b"
zones = var.zones
name = "test" name = "test"
network_interfaces = var.network_interfaces attached_disks = var.attached_disks
service_account_create = var.service_account_create attached_disk_defaults = var.attached_disk_defaults
instance_count = var.instance_count create_template = var.create_template
use_instance_template = var.use_instance_template
confidential_compute = var.confidential_compute confidential_compute = var.confidential_compute
group = var.group group = var.group
iam = var.iam iam = var.iam
metadata = var.metadata metadata = var.metadata
metadata_list = var.metadata_list network_interfaces = var.network_interfaces
single_name = var.single_name service_account_create = var.service_account_create
} }

View File

@ -14,11 +14,46 @@
* limitations under the License. * limitations under the License.
*/ */
variable "attached_disks" {
description = "Additional disks, if options is null defaults will be used in its place. Source type is one of 'image' (zonal disks in vms and template), 'snapshot' (vm), 'existing', and null."
type = list(object({
name = string
size = string
source = string
source_type = string
options = object({
mode = string
replica_zone = string
type = string
})
}))
default = []
}
variable "attached_disk_defaults" {
description = "Defaults for attached disks options."
type = object({
mode = string
replica_zone = string
type = string
})
default = {
mode = "READ_WRITE"
replica_zone = null
type = "pd-balanced"
}
}
variable "confidential_compute" { variable "confidential_compute" {
type = bool type = bool
default = false default = false
} }
variable "create_template" {
type = bool
default = false
}
variable "group" { variable "group" {
type = any type = any
default = null default = null
@ -29,31 +64,21 @@ variable "iam" {
default = {} default = {}
} }
variable "instance_count" {
type = number
default = 1
}
variable "metadata" { variable "metadata" {
type = map(string) type = map(string)
default = {} default = {}
} }
variable "metadata_list" {
type = list(map(string))
default = []
}
variable "network_interfaces" { variable "network_interfaces" {
type = list(object({ type = list(object({
nat = bool nat = bool
network = string network = string
subnetwork = string subnetwork = string
addresses = object({ addresses = object({
internal = list(string) internal = string
external = list(string) external = string
}) })
alias_ips = map(list(string)) alias_ips = map(string)
})) }))
default = [{ default = [{
network = "https://www.googleapis.com/compute/v1/projects/my-project/global/networks/default", network = "https://www.googleapis.com/compute/v1/projects/my-project/global/networks/default",
@ -68,18 +93,3 @@ variable "service_account_create" {
type = bool type = bool
default = false default = false
} }
variable "single_name" {
type = bool
default = false
}
variable "use_instance_template" {
type = bool
default = false
}
variable "zones" {
type = list(string)
default = []
}

View File

@ -20,53 +20,30 @@ import pytest
FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'fixture') FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'fixture')
def test_single_instance(plan_runner): def test_defaults(plan_runner):
_, resources = plan_runner(FIXTURES_DIR) _, resources = plan_runner(FIXTURES_DIR)
assert len(resources) == 1 assert len(resources) == 1
assert resources[0]['type'] == 'google_compute_instance' assert resources[0]['type'] == 'google_compute_instance'
def test_single_instance_single_name(plan_runner):
_, resources = plan_runner(FIXTURES_DIR, single_name=1)
assert len(resources) == 1
assert resources[0]['type'] == 'google_compute_instance'
assert resources[0]['values']['name'] == 'test'
def test_multiple_instances(plan_runner):
_, resources = plan_runner(FIXTURES_DIR, instance_count=2)
assert len(resources) == 2
assert set(r['type'] for r in resources) == set(['google_compute_instance'])
def test_service_account(plan_runner): def test_service_account(plan_runner):
_, resources = plan_runner(FIXTURES_DIR, instance_count=2, _, resources = plan_runner(FIXTURES_DIR, service_account_create='true')
service_account_create='true') assert len(resources) == 2
assert len(resources) == 3 assert set(r['type'] for r in resources) == set([
assert 'google_service_account' in [r['type'] for r in resources] 'google_compute_instance', 'google_service_account'
])
def test_template(plan_runner): def test_template(plan_runner):
_, resources = plan_runner(FIXTURES_DIR, use_instance_template='true') _, resources = plan_runner(FIXTURES_DIR, create_template='true')
assert len(resources) == 1 assert len(resources) == 1
assert resources[0]['type'] == 'google_compute_instance_template' assert resources[0]['type'] == 'google_compute_instance_template'
assert resources[0]['values']['name_prefix'] == 'test-' assert resources[0]['values']['name_prefix'] == 'test-'
def test_group(plan_runner): def test_group(plan_runner):
_, resources = plan_runner(FIXTURES_DIR, instance_count=2, _, resources = plan_runner(FIXTURES_DIR, group='{named_ports={}}')
group='{named_ports={}}') assert len(resources) == 2
assert len(resources) == 3
assert set(r['type'] for r in resources) == set([
'google_compute_instance_group', 'google_compute_instance'
])
def test_group_zones(plan_runner):
_, resources = plan_runner(FIXTURES_DIR, instance_count=2,
group='{named_ports={}}',
zones='["europe-west1-b", "europe-west1-c"]')
assert len(resources) == 4
assert set(r['type'] for r in resources) == set([ assert set(r['type'] for r in resources) == set([
'google_compute_instance_group', 'google_compute_instance' 'google_compute_instance_group', 'google_compute_instance'
]) ])
@ -77,9 +54,8 @@ def test_iam(plan_runner):
'{"roles/compute.instanceAdmin" = ["user:a@a.com", "user:b@a.com"],' '{"roles/compute.instanceAdmin" = ["user:a@a.com", "user:b@a.com"],'
'"roles/iam.serviceAccountUser" = ["user:a@a.com"]}' '"roles/iam.serviceAccountUser" = ["user:a@a.com"]}'
) )
_, resources = plan_runner( _, resources = plan_runner(FIXTURES_DIR, iam=iam)
FIXTURES_DIR, instance_count=2, iam=iam) assert len(resources) == 3
assert len(resources) == 6
assert set(r['type'] for r in resources) == set([ assert set(r['type'] for r in resources) == set([
'google_compute_instance', 'google_compute_instance_iam_binding']) 'google_compute_instance', 'google_compute_instance_iam_binding'])
iam_bindings = dict( iam_bindings = dict(
@ -87,16 +63,13 @@ def test_iam(plan_runner):
== 'google_compute_instance_iam_binding' == 'google_compute_instance_iam_binding'
) )
assert iam_bindings == { assert iam_bindings == {
'roles/compute.instanceAdmin/test-1': ['user:a@a.com', 'user:b@a.com'], 'roles/compute.instanceAdmin': ['user:a@a.com', 'user:b@a.com'],
'roles/compute.instanceAdmin/test-2': ['user:a@a.com', 'user:b@a.com'], 'roles/iam.serviceAccountUser': ['user:a@a.com'],
'roles/iam.serviceAccountUser/test-1': ['user:a@a.com'],
'roles/iam.serviceAccountUser/test-2': ['user:a@a.com'],
} }
def test_confidential_compute(plan_runner): def test_confidential_compute(plan_runner):
_, resources = plan_runner(FIXTURES_DIR, instance_count=1, _, resources = plan_runner(FIXTURES_DIR, confidential_compute='true')
confidential_compute='true')
assert len(resources) == 1 assert len(resources) == 1
assert resources[0]['values']['confidential_instance_config'] == [ assert resources[0]['values']['confidential_instance_config'] == [
{'enable_confidential_compute': True}] {'enable_confidential_compute': True}]
@ -104,9 +77,8 @@ def test_confidential_compute(plan_runner):
def test_confidential_compute_template(plan_runner): def test_confidential_compute_template(plan_runner):
_, resources = plan_runner(FIXTURES_DIR, instance_count=1, _, resources = plan_runner(FIXTURES_DIR, confidential_compute='true',
confidential_compute='true', create_template='true')
use_instance_template='true')
assert len(resources) == 1 assert len(resources) == 1
assert resources[0]['values']['confidential_instance_config'] == [ assert resources[0]['values']['confidential_instance_config'] == [
{'enable_confidential_compute': True}] {'enable_confidential_compute': True}]

View File

@ -0,0 +1,118 @@
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import pytest
FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'fixture')
def test_types(plan_runner):
_disks = '''[{
name = "data1"
size = "10"
source_type = "image"
source = "image-1"
options = null
}, {
name = "data2"
size = "20"
source_type = "snapshot"
source = "snapshot-2"
options = null
}, {
name = "data3"
size = null
source_type = "attach"
source = "disk-3"
options = null
}]
'''
_, resources = plan_runner(FIXTURES_DIR, attached_disks=_disks)
assert len(resources) == 3
disks = {r['values']['name']: r['values']
for r in resources if r['type'] == 'google_compute_disk'}
assert disks['test-data1']['size'] == 10
assert disks['test-data2']['size'] == 20
assert disks['test-data1']['image'] == 'image-1'
assert disks['test-data1']['snapshot'] is None
assert disks['test-data2']['snapshot'] == 'snapshot-2'
assert disks['test-data2']['image'] is None
instance = [r['values']
for r in resources if r['type'] == 'google_compute_instance'][0]
instance_disks = {d['source']: d['device_name']
for d in instance['attached_disk']}
assert instance_disks == {'test-data1': 'data1',
'test-data2': 'data2', 'disk-3': 'data3'}
def test_options(plan_runner):
_disks = '''[{
name = "data1"
size = "10"
source_type = "image"
source = "image-1"
options = {
mode = null, replica_zone = null, type = "pd-standard"
}
}, {
name = "data2"
size = "20"
source_type = null
source = null
options = {
mode = null, replica_zone = "europe-west1-c", type = "pd-ssd"
}
}]
'''
_, resources = plan_runner(FIXTURES_DIR, attached_disks=_disks)
assert len(resources) == 3
disks_z = [r['values']
for r in resources if r['type'] == 'google_compute_disk']
disks_r = [r['values']
for r in resources if r['type'] == 'google_compute_region_disk']
assert len(disks_z) == len(disks_r) == 1
instance = [r['values']
for r in resources if r['type'] == 'google_compute_instance'][0]
instance_disks = [d['device_name'] for d in instance['attached_disk']]
assert instance_disks == ['data1', 'data2']
def test_template(plan_runner):
_disks = '''[{
name = "data1"
size = "10"
source_type = "image"
source = "image-1"
options = {
mode = null, replica_zone = null, type = "pd-standard"
}
}, {
name = "data2"
size = "20"
source_type = null
source = null
options = {
mode = null, replica_zone = "europe-west1-c", type = "pd-ssd"
}
}]
'''
_, resources = plan_runner(
FIXTURES_DIR, attached_disks=_disks, create_template="true")
assert len(resources) == 1
template = [r['values'] for r in resources if r['type']
== 'google_compute_instance_template'][0]
assert len(template['disk']) == 3

View File

@ -20,60 +20,33 @@ import pytest
FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'fixture') FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'fixture')
def test_no_addresses(plan_runner): def test_address(plan_runner):
network_interfaces = '''[{ nics = '''[{
network = "https://www.googleapis.com/compute/v1/projects/my-project/global/networks/default", network = "https://www.googleapis.com/compute/v1/projects/my-project/global/networks/default",
subnetwork = "https://www.googleapis.com/compute/v1/projects/my-project/regions/europe-west1/subnetworks/default-default", subnetwork = "https://www.googleapis.com/compute/v1/projects/my-project/regions/europe-west1/subnetworks/default-default",
nat = false, nat = false,
addresses = {external=[], internal=[]} addresses = {external=null, internal="10.0.0.2"}
alias_ips = null alias_ips = null
}] }]
''' '''
_, resources = plan_runner( _, resources = plan_runner(FIXTURES_DIR, network_interfaces=nics)
FIXTURES_DIR, instance_count=2, network_interfaces=network_interfaces) assert len(resources) == 1
assert len(resources) == 2 n = resources[0]['values']['network_interface'][0]
assert n['network_ip'] == "10.0.0.2"
assert n['access_config'] == []
def test_internal_addresses(plan_runner): def test_nat_address(plan_runner):
network_interfaces = '''[{ nics = '''[{
network = "https://www.googleapis.com/compute/v1/projects/my-project/global/networks/default",
subnetwork = "https://www.googleapis.com/compute/v1/projects/my-project/regions/europe-west1/subnetworks/default-default",
nat = false,
addresses = {external=[], internal=["1.1.1.2", "1.1.1.3"]}
alias_ips = null
}]
'''
_, resources = plan_runner(
FIXTURES_DIR, instance_count=2, network_interfaces=network_interfaces)
assert [r['values']['network_interface'][0]['network_ip']
for r in resources] == ["1.1.1.2", "1.1.1.3"]
def test_internal_addresses_nat(plan_runner):
network_interfaces = '''[{
network = "https://www.googleapis.com/compute/v1/projects/my-project/global/networks/default", network = "https://www.googleapis.com/compute/v1/projects/my-project/global/networks/default",
subnetwork = "https://www.googleapis.com/compute/v1/projects/my-project/regions/europe-west1/subnetworks/default-default", subnetwork = "https://www.googleapis.com/compute/v1/projects/my-project/regions/europe-west1/subnetworks/default-default",
nat = true, nat = true,
addresses = {external=[], internal=["1.1.1.2", "1.1.1.3"]} addresses = {external="8.8.8.8", internal=null}
alias_ips = null alias_ips = null
}] }]
''' '''
_, resources = plan_runner( _, resources = plan_runner(FIXTURES_DIR, network_interfaces=nics)
FIXTURES_DIR, instance_count=2, network_interfaces=network_interfaces) assert len(resources) == 1
assert [r['values']['network_interface'][0]['network_ip'] n = resources[0]['values']['network_interface'][0]
for r in resources] == ["1.1.1.2", "1.1.1.3"] assert 'network_ip' not in n
assert n['access_config'][0]['nat_ip'] == '8.8.8.8'
def test_all_addresses(plan_runner):
network_interfaces = '''[{
network = "https://www.googleapis.com/compute/v1/projects/my-project/global/networks/default",
subnetwork = "https://www.googleapis.com/compute/v1/projects/my-project/regions/europe-west1/subnetworks/default-default",
nat = true,
addresses = {external=["2.2.2.2", "2.2.2.3"], internal=["1.1.1.2", "1.1.1.3"]}
alias_ips = null
}]
'''
_, resources = plan_runner(
FIXTURES_DIR, instance_count=2, network_interfaces=network_interfaces)
assert [r['values']['network_interface'][0]['access_config'][0]['nat_ip']
for r in resources] == ["2.2.2.2", "2.2.2.3"]

View File

@ -1,34 +0,0 @@
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import pytest
FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'fixture')
def test_default(plan_runner):
_, resources = plan_runner(FIXTURES_DIR, metadata='{a=1, b=2}')
assert resources[0]['values']['metadata'] == {'a': '1', 'b': '2'}
def test_multi(plan_runner):
_, resources = plan_runner(FIXTURES_DIR, instance_count=3,
metadata='{a=1, b=2}',
metadata_list='[{c=3}, {c=4}]')
assert resources[0]['values']['metadata'] == {'a': '1', 'b': '2', 'c': '3'}
assert resources[1]['values']['metadata'] == {'a': '1', 'b': '2', 'c': '4'}
assert resources[2]['values']['metadata'] == {'a': '1', 'b': '2', 'c': '3'}

View File

@ -1,66 +0,0 @@
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import pytest
FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'fixture')
def test_default(plan_runner):
_, resources = plan_runner(FIXTURES_DIR)
assert resources[0]['values']['zone'] == 'europe-west1-b'
def test_multiple_default(plan_runner):
_, resources = plan_runner(FIXTURES_DIR, instance_count=2)
assert set(r['values']['zone'] for r in resources) == set(['europe-west1-b'])
def test_custom(plan_runner):
_, resources = plan_runner(FIXTURES_DIR, zones='["a", "b"]')
assert resources[0]['values']['zone'] == 'a'
def test_custom_default(plan_runner):
_, resources = plan_runner(
FIXTURES_DIR, instance_count=3, zones='["a", "b"]')
assert [r['values']['zone'] for r in resources] == ['a', 'b', 'a']
def test_group(plan_runner):
_, resources = plan_runner(FIXTURES_DIR, instance_count=2,
group='{named_ports={}}', zones='["a", "b"]')
assert resources[2]['type'] == 'google_compute_instance_group'
assert resources[2]['values']['zone'] == 'a'
def test_iam(plan_runner):
iam = '{"roles/a" = ["user:a@a.com"], "roles/b" = ["user:a@a.com"]}'
_, resources = plan_runner(FIXTURES_DIR, instance_count=3,
iam=iam, zones='["a", "b"]')
iam_bindings = dict(
(r['index'], r['values']['zone']) for r in resources if r['type']
== 'google_compute_instance_iam_binding'
)
assert iam_bindings == {
'roles/a/test-1': 'a',
'roles/a/test-2': 'b',
'roles/a/test-3': 'a',
'roles/b/test-1': 'a',
'roles/b/test-2': 'b',
'roles/b/test-3': 'a',
}

View File

@ -24,4 +24,4 @@ def test_resources(e2e_plan_runner):
"Test that plan works and the numbers of resources is as expected." "Test that plan works and the numbers of resources is as expected."
modules, resources = e2e_plan_runner(FIXTURES_DIR) modules, resources = e2e_plan_runner(FIXTURES_DIR)
assert len(modules) == 17 assert len(modules) == 17
assert len(resources) == 70 assert len(resources) == 69

View File

@ -23,5 +23,5 @@ FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'fixture')
def test_resources(e2e_plan_runner): def test_resources(e2e_plan_runner):
"Test that plan works and the numbers of resources is as expected." "Test that plan works and the numbers of resources is as expected."
modules, resources = e2e_plan_runner(FIXTURES_DIR) modules, resources = e2e_plan_runner(FIXTURES_DIR)
assert len(modules) == 14 assert len(modules) == 17
assert len(resources) == 42 assert len(resources) == 42

View File

@ -24,4 +24,4 @@ def test_resources(e2e_plan_runner):
"Test that plan works and the numbers of resources is as expected." "Test that plan works and the numbers of resources is as expected."
modules, resources = e2e_plan_runner(FIXTURES_DIR) modules, resources = e2e_plan_runner(FIXTURES_DIR)
assert len(modules) == 14 assert len(modules) == 14
assert len(resources) == 48 assert len(resources) == 46

View File

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