Add support for resource policies to compute vm module (#1467)

* instance schedule

* snapshot resource policy variable and resource

* tfdoc

* snapshot schedules
This commit is contained in:
Ludovico Magnocavallo 2023-06-26 08:49:05 +02:00 committed by GitHub
parent 32b347b104
commit ce647647cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 469 additions and 39 deletions

View File

@ -25,6 +25,8 @@ In both modes, an optional service account can be created and assigned to either
- [Disk encryption with Cloud KMS](#disk-encryption-with-cloud-kms)
- [Instance template](#instance-template)
- [Instance group](#instance-group)
- [Instance Schedule](#instance-schedule)
- [Snapshot Schedules](#snapshot-schedules)
### Instance using defaults
@ -500,40 +502,132 @@ module "instance-group" {
}
# tftest modules=1 resources=2 inventory=group.yaml
```
### Instance Schedule
Instance start and stop schedules can be defined via an existing or auto-created resource policy.
To use an existing policy pass its id to the `instance_schedule` variable:
```hcl
module "instance" {
source = "./fabric/modules/compute-vm"
project_id = "my-project"
zone = "europe-west1-b"
name = "schedule-test"
network_interfaces = [{
network = var.vpc.self_link
subnetwork = var.subnet.self_link
}]
boot_disk = {
image = "projects/cos-cloud/global/images/family/cos-stable"
}
instance_schedule = {
resource_policy_id = "projects/my-project/regions/europe-west1/resourcePolicies/test"
}
}
# tftest modules=1 resources=1 inventory=instance-schedule-id.yaml
```
To create a new policy set its configuration in the `instance_schedule` variable. When removing the policy follow a two-step process by first setting `active = false` in the schedule configuration, which will unattach the policy, then removing the variable so the policy is destroyed.
```hcl
module "instance" {
source = "./fabric/modules/compute-vm"
project_id = "my-project"
zone = "europe-west1-b"
name = "schedule-test"
network_interfaces = [{
network = var.vpc.self_link
subnetwork = var.subnet.self_link
}]
boot_disk = {
image = "projects/cos-cloud/global/images/family/cos-stable"
}
instance_schedule = {
create_config = {
vm_start = "0 8 * * *"
vm_stop = "0 17 * * *"
}
}
}
# tftest modules=1 resources=2 inventory=instance-schedule-create.yaml
```
### Snapshot Schedules
Snapshot policies can be attached to disks with optional creation managed by the module.
```hcl
module "instance" {
source = "./fabric/modules/compute-vm"
project_id = "my-project"
zone = "europe-west1-b"
name = "schedule-test"
network_interfaces = [{
network = var.vpc.self_link
subnetwork = var.subnet.self_link
}]
boot_disk = {
image = "projects/cos-cloud/global/images/family/cos-stable"
snapshot_schedule = "boot"
}
attached_disks = [
{
name = "disk-1"
size = 10
snapshot_schedule = "generic-vm"
}
]
snapshot_schedules = {
boot = {
schedule = {
daily = {
days_in_cycle = 1
start_time = "03:00"
}
}
}
}
}
# tftest modules=1 resources=5 inventory=snapshot-schedule-create.yaml
```
<!-- BEGIN TFDOC -->
## Variables
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [name](variables.tf#L182) | Instance name. | <code>string</code> | ✓ | |
| [network_interfaces](variables.tf#L187) | Network interfaces configuration. Use self links for Shared VPC, set addresses to null if not needed. | <code title="list&#40;object&#40;&#123;&#10; nat &#61; optional&#40;bool, false&#41;&#10; network &#61; string&#10; subnetwork &#61; string&#10; addresses &#61; optional&#40;object&#40;&#123;&#10; internal &#61; optional&#40;string&#41;&#10; external &#61; optional&#40;string&#41;&#10; &#125;&#41;, null&#41;&#10; alias_ips &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; nic_type &#61; optional&#40;string&#41;&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | ✓ | |
| [project_id](variables.tf#L224) | Project id. | <code>string</code> | ✓ | |
| [zone](variables.tf#L283) | Compute zone. | <code>string</code> | ✓ | |
| [name](variables.tf#L219) | Instance name. | <code>string</code> | ✓ | |
| [network_interfaces](variables.tf#L224) | Network interfaces configuration. Use self links for Shared VPC, set addresses to null if not needed. | <code title="list&#40;object&#40;&#123;&#10; nat &#61; optional&#40;bool, false&#41;&#10; network &#61; string&#10; subnetwork &#61; string&#10; addresses &#61; optional&#40;object&#40;&#123;&#10; internal &#61; optional&#40;string&#41;&#10; external &#61; optional&#40;string&#41;&#10; &#125;&#41;, null&#41;&#10; alias_ips &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; nic_type &#61; optional&#40;string&#41;&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | ✓ | |
| [project_id](variables.tf#L261) | Project id. | <code>string</code> | ✓ | |
| [zone](variables.tf#L363) | Compute zone. | <code>string</code> | ✓ | |
| [attached_disk_defaults](variables.tf#L17) | Defaults for attached disks options. | <code title="object&#40;&#123;&#10; auto_delete &#61; optional&#40;bool, false&#41;&#10; mode &#61; string&#10; replica_zone &#61; string&#10; type &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</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;">&#123;&#8230;&#125;</code> |
| [attached_disks](variables.tf#L38) | 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; device_name &#61; optional&#40;string&#41;&#10; size &#61; string&#10; source &#61; optional&#40;string&#41;&#10; source_type &#61; optional&#40;string&#41;&#10; options &#61; optional&#40;&#10; object&#40;&#123;&#10; auto_delete &#61; optional&#40;bool, false&#41;&#10; mode &#61; optional&#40;string, &#34;READ_WRITE&#34;&#41;&#10; replica_zone &#61; optional&#40;string&#41;&#10; type &#61; optional&#40;string, &#34;pd-balanced&#34;&#41;&#10; &#125;&#41;,&#10; &#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;&#10; &#41;&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [boot_disk](variables.tf#L82) | Boot disk properties. | <code title="object&#40;&#123;&#10; auto_delete &#61; optional&#40;bool, true&#41;&#10; source &#61; optional&#40;string&#41;&#10; initialize_params &#61; optional&#40;object&#40;&#123;&#10; image &#61; optional&#40;string, &#34;projects&#47;debian-cloud&#47;global&#47;images&#47;family&#47;debian-11&#34;&#41;&#10; size &#61; optional&#40;number, 10&#41;&#10; type &#61; optional&#40;string, &#34;pd-balanced&#34;&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; initialize_params &#61; &#123;&#125;&#10;&#125;">&#123;&#8230;&#125;</code> |
| [can_ip_forward](variables.tf#L99) | Enable IP forwarding. | <code>bool</code> | | <code>false</code> |
| [confidential_compute](variables.tf#L105) | Enable Confidential Compute for these instances. | <code>bool</code> | | <code>false</code> |
| [create_template](variables.tf#L111) | Create instance template instead of instances. | <code>bool</code> | | <code>false</code> |
| [description](variables.tf#L116) | Description of a Compute Instance. | <code>string</code> | | <code>&#34;Managed by the compute-vm Terraform module.&#34;</code> |
| [enable_display](variables.tf#L122) | Enable virtual display on the instances. | <code>bool</code> | | <code>false</code> |
| [encryption](variables.tf#L128) | 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; optional&#40;bool, false&#41;&#10; disk_encryption_key_raw &#61; optional&#40;string&#41;&#10; kms_key_self_link &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [group](variables.tf#L138) | 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&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [hostname](variables.tf#L146) | Instance FQDN name. | <code>string</code> | | <code>null</code> |
| [iam](variables.tf#L152) | IAM bindings in {ROLE => [MEMBERS]} format. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [instance_type](variables.tf#L158) | Instance type. | <code>string</code> | | <code>&#34;f1-micro&#34;</code> |
| [labels](variables.tf#L164) | Instance labels. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [metadata](variables.tf#L170) | Instance metadata. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [min_cpu_platform](variables.tf#L176) | Minimum CPU platform. | <code>string</code> | | <code>null</code> |
| [options](variables.tf#L202) | Instance options. | <code title="object&#40;&#123;&#10; allow_stopping_for_update &#61; optional&#40;bool, true&#41;&#10; deletion_protection &#61; optional&#40;bool, false&#41;&#10; spot &#61; optional&#40;bool, false&#41;&#10; termination_action &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; allow_stopping_for_update &#61; true&#10; deletion_protection &#61; false&#10; spot &#61; false&#10; termination_action &#61; null&#10;&#125;">&#123;&#8230;&#125;</code> |
| [scratch_disks](variables.tf#L229) | Scratch disks configuration. | <code title="object&#40;&#123;&#10; count &#61; number&#10; interface &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; count &#61; 0&#10; interface &#61; &#34;NVME&#34;&#10;&#125;">&#123;&#8230;&#125;</code> |
| [service_account](variables.tf#L241) | Service account email. Unused if service account is auto-created. | <code>string</code> | | <code>null</code> |
| [service_account_create](variables.tf#L247) | Auto-create service account. | <code>bool</code> | | <code>false</code> |
| [service_account_scopes](variables.tf#L255) | Scopes applied to service account. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [shielded_config](variables.tf#L261) | 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&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [tag_bindings](variables.tf#L271) | Tag bindings for this instance, in key => tag value id format. | <code>map&#40;string&#41;</code> | | <code>null</code> |
| [tags](variables.tf#L277) | Instance network tags for firewall rule targets. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [attached_disks](variables.tf#L38) | 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; device_name &#61; optional&#40;string&#41;&#10; size &#61; string&#10; snapshot_schedule &#61; optional&#40;string&#41;&#10; source &#61; optional&#40;string&#41;&#10; source_type &#61; optional&#40;string&#41;&#10; options &#61; optional&#40;&#10; object&#40;&#123;&#10; auto_delete &#61; optional&#40;bool, false&#41;&#10; mode &#61; optional&#40;string, &#34;READ_WRITE&#34;&#41;&#10; replica_zone &#61; optional&#40;string&#41;&#10; type &#61; optional&#40;string, &#34;pd-balanced&#34;&#41;&#10; &#125;&#41;,&#10; &#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;&#10; &#41;&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [boot_disk](variables.tf#L83) | Boot disk properties. | <code title="object&#40;&#123;&#10; auto_delete &#61; optional&#40;bool, true&#41;&#10; snapshot_schedule &#61; optional&#40;string&#41;&#10; source &#61; optional&#40;string&#41;&#10; initialize_params &#61; optional&#40;object&#40;&#123;&#10; image &#61; optional&#40;string, &#34;projects&#47;debian-cloud&#47;global&#47;images&#47;family&#47;debian-11&#34;&#41;&#10; size &#61; optional&#40;number, 10&#41;&#10; type &#61; optional&#40;string, &#34;pd-balanced&#34;&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; initialize_params &#61; &#123;&#125;&#10;&#125;">&#123;&#8230;&#125;</code> |
| [can_ip_forward](variables.tf#L101) | Enable IP forwarding. | <code>bool</code> | | <code>false</code> |
| [confidential_compute](variables.tf#L107) | Enable Confidential Compute for these instances. | <code>bool</code> | | <code>false</code> |
| [create_template](variables.tf#L113) | Create instance template instead of instances. | <code>bool</code> | | <code>false</code> |
| [description](variables.tf#L118) | Description of a Compute Instance. | <code>string</code> | | <code>&#34;Managed by the compute-vm Terraform module.&#34;</code> |
| [enable_display](variables.tf#L124) | Enable virtual display on the instances. | <code>bool</code> | | <code>false</code> |
| [encryption](variables.tf#L130) | 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; optional&#40;bool, false&#41;&#10; disk_encryption_key_raw &#61; optional&#40;string&#41;&#10; kms_key_self_link &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [group](variables.tf#L140) | 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&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [hostname](variables.tf#L148) | Instance FQDN name. | <code>string</code> | | <code>null</code> |
| [iam](variables.tf#L154) | IAM bindings in {ROLE => [MEMBERS]} format. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [instance_schedule](variables.tf#L160) | Assign or create and assign an instance schedule policy. Either resource policy id or create_config must be specified if not null. Set active to null to dtach a policy from vm before destroying. | <code title="object&#40;&#123;&#10; resource_policy_id &#61; optional&#40;string&#41;&#10; create_config &#61; optional&#40;object&#40;&#123;&#10; active &#61; optional&#40;bool, true&#41;&#10; description &#61; optional&#40;string&#41;&#10; expiration_time &#61; optional&#40;string&#41;&#10; start_time &#61; optional&#40;string&#41;&#10; timezone &#61; optional&#40;string, &#34;UTC&#34;&#41;&#10; vm_start &#61; optional&#40;string&#41;&#10; vm_stop &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [instance_type](variables.tf#L195) | Instance type. | <code>string</code> | | <code>&#34;f1-micro&#34;</code> |
| [labels](variables.tf#L201) | Instance labels. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [metadata](variables.tf#L207) | Instance metadata. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [min_cpu_platform](variables.tf#L213) | Minimum CPU platform. | <code>string</code> | | <code>null</code> |
| [options](variables.tf#L239) | Instance options. | <code title="object&#40;&#123;&#10; allow_stopping_for_update &#61; optional&#40;bool, true&#41;&#10; deletion_protection &#61; optional&#40;bool, false&#41;&#10; spot &#61; optional&#40;bool, false&#41;&#10; termination_action &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; allow_stopping_for_update &#61; true&#10; deletion_protection &#61; false&#10; spot &#61; false&#10; termination_action &#61; null&#10;&#125;">&#123;&#8230;&#125;</code> |
| [scratch_disks](variables.tf#L266) | Scratch disks configuration. | <code title="object&#40;&#123;&#10; count &#61; number&#10; interface &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; count &#61; 0&#10; interface &#61; &#34;NVME&#34;&#10;&#125;">&#123;&#8230;&#125;</code> |
| [service_account](variables.tf#L278) | Service account email. Unused if service account is auto-created. | <code>string</code> | | <code>null</code> |
| [service_account_create](variables.tf#L284) | Auto-create service account. | <code>bool</code> | | <code>false</code> |
| [service_account_scopes](variables.tf#L292) | Scopes applied to service account. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [shielded_config](variables.tf#L298) | 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&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [snapshot_schedules](variables.tf#L308) | Snapshot schedule resource policies that can be attached to disks. | <code title="map&#40;object&#40;&#123;&#10; schedule &#61; object&#40;&#123;&#10; daily &#61; optional&#40;object&#40;&#123;&#10; days_in_cycle &#61; number&#10; start_time &#61; string&#10; &#125;&#41;&#41;&#10; hourly &#61; optional&#40;object&#40;&#123;&#10; hours_in_cycle &#61; number&#10; start_time &#61; string&#10; &#125;&#41;&#41;&#10; weekly &#61; optional&#40;list&#40;object&#40;&#123;&#10; day &#61; string&#10; start_time &#61; string&#10; &#125;&#41;&#41;&#41;&#10; &#125;&#41;&#10; description &#61; optional&#40;string&#41;&#10; retention_policy &#61; optional&#40;object&#40;&#123;&#10; max_retention_days &#61; number&#10; on_source_disk_delete_keep &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#10; snapshot_properties &#61; optional&#40;object&#40;&#123;&#10; chain_name &#61; optional&#40;string&#41;&#10; guest_flush &#61; optional&#40;bool&#41;&#10; labels &#61; optional&#40;map&#40;string&#41;&#41;&#10; storage_locations &#61; optional&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [tag_bindings](variables.tf#L351) | Tag bindings for this instance, in key => tag value id format. | <code>map&#40;string&#41;</code> | | <code>null</code> |
| [tags](variables.tf#L357) | Instance network tags for firewall rule targets. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
## Outputs

View File

@ -1,5 +1,5 @@
/**
* Copyright 2022 Google LLC
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -133,13 +133,18 @@ resource "google_compute_instance" "default" {
enable_display = var.enable_display
labels = var.labels
metadata = var.metadata
resource_policies = local.ischedule_attach
dynamic "attached_disk" {
for_each = local.attached_disks_zonal
iterator = config
content {
device_name = config.value.device_name != null ? config.value.device_name : config.value.name
mode = config.value.options.mode
device_name = (
config.value.device_name != null
? config.value.device_name
: config.value.name
)
mode = config.value.options.mode
source = (
config.value.source_type == "attach"
? config.value.source
@ -152,8 +157,12 @@ resource "google_compute_instance" "default" {
for_each = local.attached_disks_regional
iterator = config
content {
device_name = config.value.device_name != null ? config.value.device_name : config.value.name
mode = config.value.options.mode
device_name = (
config.value.device_name != null
? config.value.device_name
: config.value.name
)
mode = config.value.options.mode
source = (
config.value.source_type == "attach"
? config.value.source

View File

@ -0,0 +1,174 @@
/**
* Copyright 2023 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.
*/
# tfdoc:file:description Resource policies.
locals {
ischedule = try(var.instance_schedule.create_config, null)
ischedule_attach = var.instance_schedule == null ? null : (
var.instance_schedule.create_config != null
# created policy with optional attach to allow policy destroy
? (
var.instance_schedule.create_config.active
? [google_compute_resource_policy.schedule.0.id]
: null
)
# externally managed policy
: [var.instance_schedule.resource_policy_id]
)
}
resource "google_compute_resource_policy" "schedule" {
count = local.ischedule != null ? 1 : 0
project = var.project_id
region = substr(var.zone, 0, length(var.zone) - 2)
name = var.name
description = coalesce(
local.ischedule.description, "Schedule policy for ${var.name}."
)
instance_schedule_policy {
expiration_time = local.ischedule.expiration_time
start_time = local.ischedule.start_time
time_zone = local.ischedule.timezone
dynamic "vm_start_schedule" {
for_each = local.ischedule.vm_start != null ? [""] : []
content {
schedule = local.ischedule.vm_start
}
}
dynamic "vm_stop_schedule" {
for_each = local.ischedule.vm_stop != null ? [""] : []
content {
schedule = local.ischedule.vm_stop
}
}
}
}
resource "google_compute_resource_policy" "snapshot" {
for_each = var.snapshot_schedules
project = var.project_id
region = substr(var.zone, 0, length(var.zone) - 2)
name = "${var.name}-${each.key}"
description = coalesce(
each.value.description, "Schedule policy ${each.key} for ${var.name}."
)
snapshot_schedule_policy {
schedule {
dynamic "daily_schedule" {
for_each = each.value.schedule.daily != null ? [""] : []
content {
days_in_cycle = each.value.schedule.daily.days_in_cycle
start_time = each.value.schedule.daily.start_time
}
}
dynamic "hourly_schedule" {
for_each = each.value.schedule.hourly != null ? [""] : []
content {
hours_in_cycle = each.value.schedule.hourly.hours_in_cycle
start_time = each.value.schedule.hourly.start_time
}
}
dynamic "weekly_schedule" {
for_each = each.value.schedule.weekly != null ? [""] : []
content {
dynamic "day_of_weeks" {
for_each = each.value.schedule.weekly
content {
day = day_of_weeks.value.day
start_time = day_of_weeks.value.start_time
}
}
}
}
}
dynamic "retention_policy" {
for_each = each.value.retention_policy != null ? [""] : []
content {
max_retention_days = each.value.retention_policy.max_retention_days
on_source_disk_delete = (
each.value.retention_policy.on_source_disk_delete_keep == false
? "APPLY_RETENTION_POLICY"
: "KEEP_AUTO_SNAPSHOTS"
)
}
}
dynamic "snapshot_properties" {
for_each = each.value.snapshot_properties != null ? [""] : []
content {
labels = each.value.snapshot_properties.labels
storage_locations = each.value.snapshot_properties.storage_locations
guest_flush = each.value.snapshot_properties.guest_flush
}
}
}
}
resource "google_compute_disk_resource_policy_attachment" "boot" {
count = var.boot_disk.snapshot_schedule != null ? 1 : 0
project = var.project_id
zone = var.zone
name = try(
google_compute_resource_policy.snapshot[var.boot_disk.snapshot_schedule].name,
var.boot_disk.snapshot_schedule
)
disk = var.name
depends_on = [google_compute_instance.default]
}
resource "google_compute_disk_resource_policy_attachment" "attached" {
for_each = {
for k, v in local.attached_disks_zonal :
k => v if v.snapshot_schedule != null
}
project = var.project_id
zone = var.zone
name = try(
google_compute_resource_policy.snapshot[each.value.snapshot_schedule].name,
each.value.snapshot_schedule
)
disk = (
each.value.source_type == "attach"
? each.value.source
: google_compute_disk.disks[each.key].name
)
depends_on = [
google_compute_instance.default,
google_compute_disk.disks
]
}
resource "google_compute_region_disk_resource_policy_attachment" "attached" {
for_each = {
for k, v in local.attached_disks_regional :
k => v if v.snapshot_schedule != null
}
project = var.project_id
region = substr(var.zone, 0, length(var.zone) - 2)
name = try(
google_compute_resource_policy.snapshot[each.value.snapshot_schedule].name,
each.value.snapshot_schedule
)
disk = (
each.value.source_type == "attach"
? each.value.source
: google_compute_region_disk.disks[each.key].name
)
depends_on = [
google_compute_instance.default,
google_compute_region_disk.disks
]
}

View File

@ -14,6 +14,8 @@
* limitations under the License.
*/
# tfdoc:file:description Tag bindings.
resource "google_tags_tag_binding" "binding" {
for_each = var.create_template ? {} : coalesce(var.tag_bindings, {})
parent = "//compute.googleapis.com/${google_compute_instance.default.0.id}"

View File

@ -38,11 +38,12 @@ variable "attached_disk_defaults" {
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
device_name = optional(string)
size = string
source = optional(string)
source_type = optional(string)
name = string
device_name = optional(string)
size = string
snapshot_schedule = optional(string)
source = optional(string)
source_type = optional(string)
options = optional(
object({
auto_delete = optional(bool, false)
@ -82,8 +83,9 @@ variable "attached_disks" {
variable "boot_disk" {
description = "Boot disk properties."
type = object({
auto_delete = optional(bool, true)
source = optional(string)
auto_delete = optional(bool, true)
snapshot_schedule = optional(string)
source = optional(string)
initialize_params = optional(object({
image = optional(string, "projects/debian-cloud/global/images/family/debian-11")
size = optional(number, 10)
@ -155,6 +157,41 @@ variable "iam" {
default = {}
}
variable "instance_schedule" {
description = "Assign or create and assign an instance schedule policy. Either resource policy id or create_config must be specified if not null. Set active to null to dtach a policy from vm before destroying."
type = object({
resource_policy_id = optional(string)
create_config = optional(object({
active = optional(bool, true)
description = optional(string)
expiration_time = optional(string)
start_time = optional(string)
timezone = optional(string, "UTC")
vm_start = optional(string)
vm_stop = optional(string)
}))
})
default = null
validation {
condition = (
var.instance_schedule == null ||
try(var.instance_schedule.resource_policy_id, null) != null ||
try(var.instance_schedule.create_config, null) != null
)
error_message = "A resource policy name or configuration must be specified when not null."
}
validation {
condition = (
try(var.instance_schedule.create_config, null) == null ||
length(compact([
try(var.instance_schedule.create_config.vm_start, null),
try(var.instance_schedule.create_config.vm_stop, null)
])) > 0
)
error_message = "A resource policy configuration must contain at least one schedule."
}
}
variable "instance_type" {
description = "Instance type."
type = string
@ -268,6 +305,49 @@ variable "shielded_config" {
default = null
}
variable "snapshot_schedules" {
description = "Snapshot schedule resource policies that can be attached to disks."
type = map(object({
schedule = object({
daily = optional(object({
days_in_cycle = number
start_time = string
}))
hourly = optional(object({
hours_in_cycle = number
start_time = string
}))
weekly = optional(list(object({
day = string
start_time = string
})))
})
description = optional(string)
retention_policy = optional(object({
max_retention_days = number
on_source_disk_delete_keep = optional(bool)
}))
snapshot_properties = optional(object({
chain_name = optional(string)
guest_flush = optional(bool)
labels = optional(map(string))
storage_locations = optional(list(string))
}))
}))
nullable = false
default = {}
validation {
condition = alltrue([
for k, v in var.snapshot_schedules : (
(v.schedule.daily != null ? 1 : 0) +
(v.schedule.hourly != null ? 1 : 0) +
(v.schedule.weekly != null ? 1 : 0)
) == 1
])
error_message = "Schedule must contain exactly one of daily, hourly, or weekly schedule."
}
}
variable "tag_bindings" {
description = "Tag bindings for this instance, in key => tag value id format."
type = map(string)

View File

@ -0,0 +1,31 @@
# Copyright 2023 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.
values:
module.instance.google_compute_resource_policy.schedule[0]:
description: Schedule policy for schedule-test.
instance_schedule_policy:
- expiration_time: null
start_time: null
time_zone: UTC
vm_start_schedule:
- schedule: 0 8 * * *
vm_stop_schedule:
- schedule: 0 17 * * *
name: schedule-test
region: europe-west1
counts:
google_compute_instance: 1
google_compute_resource_policy: 1

View File

@ -0,0 +1,21 @@
# Copyright 2023 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.
values:
module.instance.google_compute_instance.default[0]:
resource_policies:
- projects/my-project/regions/europe-west1/resourcePolicies/test
counts:
google_compute_instance: 1

View File

@ -0,0 +1,19 @@
# Copyright 2023 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.
counts:
google_compute_disk: 1
google_compute_disk_resource_policy_attachment: 2
google_compute_instance: 1
google_compute_resource_policy: 1