466 lines
14 KiB
HCL
466 lines
14 KiB
HCL
/**
|
|
* Copyright 2024 Google LLC
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
locals {
|
|
_region = join("-", slice(split("-", local.zone), 0, 2))
|
|
advanced_mf = var.options.advanced_machine_features
|
|
attached_disks = {
|
|
for i, disk in var.attached_disks :
|
|
coalesce(disk.name, disk.device_name, "disk-${i}") => merge(disk, {
|
|
options = disk.options == null ? var.attached_disk_defaults : disk.options
|
|
})
|
|
}
|
|
attached_disks_regional = {
|
|
for k, v in local.attached_disks :
|
|
k => v if try(v.options.replica_zone, null) != null
|
|
}
|
|
attached_disks_zonal = {
|
|
for k, v in local.attached_disks :
|
|
k => v if try(v.options.replica_zone, null) == null
|
|
}
|
|
ctx = {
|
|
for k, v in var.context : k => {
|
|
for kk, vv in v : "${local.ctx_p}${k}:${kk}" => vv
|
|
}
|
|
}
|
|
ctx_p = "$"
|
|
gpu = var.gpu != null
|
|
on_host_maintenance = (
|
|
var.options.spot || var.confidential_compute || local.gpu
|
|
? "TERMINATE"
|
|
: "MIGRATE"
|
|
)
|
|
project_id = lookup(local.ctx.project_ids, var.project_id, var.project_id)
|
|
region = lookup(local.ctx.locations, local._region, local._region)
|
|
service_account = var.service_account == null ? null : {
|
|
email = (var.service_account.auto_create
|
|
? google_service_account.service_account[0].email
|
|
: try(
|
|
local.ctx.iam_principals[var.service_account.email],
|
|
var.service_account.email
|
|
)
|
|
)
|
|
scopes = (
|
|
var.service_account.scopes != null ? var.service_account.scopes : (
|
|
var.service_account.email == null && !var.service_account.auto_create
|
|
# default scopes for Compute default SA
|
|
? [
|
|
"https://www.googleapis.com/auth/devstorage.read_only",
|
|
"https://www.googleapis.com/auth/logging.write",
|
|
"https://www.googleapis.com/auth/monitoring.write"
|
|
]
|
|
# default scopes for own SA
|
|
: [
|
|
"https://www.googleapis.com/auth/cloud-platform",
|
|
"https://www.googleapis.com/auth/userinfo.email"
|
|
]
|
|
)
|
|
)
|
|
}
|
|
termination_action = (
|
|
var.options.spot || var.options.max_run_duration != null ? coalesce(var.options.termination_action, "STOP") : null
|
|
)
|
|
zone = lookup(local.ctx.locations, var.zone, var.zone)
|
|
}
|
|
|
|
resource "google_compute_disk" "boot" {
|
|
count = !local.template_create && var.boot_disk.use_independent_disk ? 1 : 0
|
|
project = local.project_id
|
|
zone = local.zone
|
|
# by default, GCP creates boot disks with the same name as instance, the deviation here is kept for backwards
|
|
# compatibility
|
|
name = "${var.name}-boot"
|
|
type = var.boot_disk.initialize_params.type
|
|
size = var.boot_disk.initialize_params.size
|
|
image = var.boot_disk.initialize_params.image
|
|
labels = merge(var.labels, {
|
|
disk_name = "boot"
|
|
disk_type = var.boot_disk.initialize_params.type
|
|
})
|
|
dynamic "disk_encryption_key" {
|
|
for_each = var.encryption != null ? [""] : []
|
|
content {
|
|
raw_key = var.encryption.disk_encryption_key_raw
|
|
kms_key_self_link = lookup(
|
|
local.ctx.kms_keys,
|
|
var.encryption.kms_key_self_link,
|
|
var.encryption.kms_key_self_link
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
resource "google_compute_disk" "disks" {
|
|
for_each = local.template_create ? {} : {
|
|
for k, v in local.attached_disks_zonal :
|
|
k => v if v.source_type != "attach"
|
|
}
|
|
project = local.project_id
|
|
zone = local.zone
|
|
name = "${var.name}-${each.key}"
|
|
type = each.value.options.type
|
|
size = each.value.size
|
|
image = each.value.source_type == "image" ? each.value.source : null
|
|
snapshot = each.value.source_type == "snapshot" ? each.value.source : null
|
|
labels = merge(var.labels, {
|
|
disk_name = each.value.name
|
|
disk_type = each.value.options.type
|
|
})
|
|
dynamic "disk_encryption_key" {
|
|
for_each = var.encryption != null ? [""] : []
|
|
content {
|
|
raw_key = var.encryption.disk_encryption_key_raw
|
|
kms_key_self_link = lookup(
|
|
local.ctx.kms_keys,
|
|
var.encryption.kms_key_self_link,
|
|
var.encryption.kms_key_self_link
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
resource "google_compute_region_disk" "disks" {
|
|
provider = google-beta
|
|
for_each = local.template_create ? {} : {
|
|
for k, v in local.attached_disks_regional :
|
|
k => v if v.source_type != "attach"
|
|
}
|
|
project = local.project_id
|
|
region = local.region
|
|
replica_zones = [local.zone, each.value.options.replica_zone]
|
|
name = "${var.name}-${each.key}"
|
|
type = each.value.options.type
|
|
size = each.value.size
|
|
# image = each.value.source_type == "image" ? each.value.source : null
|
|
snapshot = each.value.source_type == "snapshot" ? each.value.source : null
|
|
labels = merge(var.labels, {
|
|
disk_name = each.value.name
|
|
disk_type = each.value.options.type
|
|
})
|
|
dynamic "disk_encryption_key" {
|
|
for_each = var.encryption != null ? [""] : []
|
|
content {
|
|
raw_key = var.encryption.disk_encryption_key_raw
|
|
# TODO: check if self link works here
|
|
kms_key_name = lookup(
|
|
local.ctx.kms_keys,
|
|
var.encryption.kms_key_self_link,
|
|
var.encryption.kms_key_self_link
|
|
)
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
resource "google_compute_instance" "default" {
|
|
provider = google-beta
|
|
count = local.template_create ? 0 : 1
|
|
project = local.project_id
|
|
zone = local.zone
|
|
name = var.name
|
|
hostname = var.hostname
|
|
description = var.description
|
|
tags = var.tags
|
|
machine_type = var.instance_type
|
|
min_cpu_platform = var.min_cpu_platform
|
|
can_ip_forward = var.can_ip_forward
|
|
allow_stopping_for_update = var.options.allow_stopping_for_update
|
|
deletion_protection = var.options.deletion_protection
|
|
enable_display = var.enable_display
|
|
labels = var.labels
|
|
metadata = var.metadata
|
|
metadata_startup_script = var.metadata_startup_script
|
|
resource_policies = (
|
|
var.resource_policies == null && var.instance_schedule == null
|
|
? null
|
|
: concat(
|
|
coalesce(var.resource_policies, []),
|
|
coalesce(local.ischedule, [])
|
|
)
|
|
)
|
|
|
|
dynamic "advanced_machine_features" {
|
|
for_each = local.advanced_mf != null ? [""] : []
|
|
content {
|
|
enable_nested_virtualization = local.advanced_mf.enable_nested_virtualization
|
|
enable_uefi_networking = local.advanced_mf.enable_uefi_networking
|
|
performance_monitoring_unit = local.advanced_mf.performance_monitoring_unit
|
|
threads_per_core = local.advanced_mf.threads_per_core
|
|
turbo_mode = (
|
|
local.advanced_mf.enable_turbo_mode ? "ALL_CORE_MAX" : null
|
|
)
|
|
visible_core_count = local.advanced_mf.visible_core_count
|
|
}
|
|
}
|
|
|
|
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
|
|
source = (
|
|
config.value.source_type == "attach"
|
|
? config.value.source
|
|
: google_compute_disk.disks[config.key].name
|
|
)
|
|
}
|
|
}
|
|
|
|
dynamic "attached_disk" {
|
|
for_each = local.attached_disks_regional
|
|
iterator = config
|
|
content {
|
|
device_name = coalesce(
|
|
config.value.device_name, config.value.name, config.key
|
|
)
|
|
mode = config.value.options.mode
|
|
source = (
|
|
config.value.source_type == "attach"
|
|
? config.value.source
|
|
: google_compute_region_disk.disks[config.key].id
|
|
)
|
|
}
|
|
}
|
|
|
|
boot_disk {
|
|
auto_delete = (
|
|
var.boot_disk.use_independent_disk
|
|
? false
|
|
: var.boot_disk.auto_delete
|
|
)
|
|
source = (
|
|
var.boot_disk.use_independent_disk
|
|
? google_compute_disk.boot[0].id
|
|
: var.boot_disk.source
|
|
)
|
|
disk_encryption_key_raw = (
|
|
var.encryption != null ?
|
|
try(
|
|
local.ctx.kms_keys[var.encryption.disk_encryption_key_raw],
|
|
var.encryption.disk_encryption_key_raw
|
|
)
|
|
: null
|
|
)
|
|
kms_key_self_link = (
|
|
var.encryption != null
|
|
? try(
|
|
local.ctx.kms_keys[var.encryption.kms_key_self_link],
|
|
var.encryption.kms_key_self_link
|
|
)
|
|
: null
|
|
)
|
|
dynamic "initialize_params" {
|
|
for_each = (
|
|
var.boot_disk.initialize_params == null
|
|
||
|
|
var.boot_disk.use_independent_disk
|
|
||
|
|
var.boot_disk.source != null
|
|
? []
|
|
: [""]
|
|
)
|
|
content {
|
|
image = var.boot_disk.initialize_params.image
|
|
size = var.boot_disk.initialize_params.size
|
|
type = var.boot_disk.initialize_params.type
|
|
resource_manager_tags = var.tag_bindings_immutable
|
|
}
|
|
}
|
|
}
|
|
|
|
dynamic "confidential_instance_config" {
|
|
for_each = var.confidential_compute ? [""] : []
|
|
content {
|
|
enable_confidential_compute = true
|
|
}
|
|
}
|
|
|
|
dynamic "network_interface" {
|
|
for_each = var.network_interfaces
|
|
iterator = config
|
|
content {
|
|
network = lookup(
|
|
local.ctx.networks, config.value.network, config.value.network
|
|
)
|
|
subnetwork = lookup(
|
|
local.ctx.subnets, config.value.subnetwork, config.value.subnetwork
|
|
)
|
|
network_ip = try(
|
|
local.ctx.addresses[config.value.addresses.internal],
|
|
config.value.addresses.internal,
|
|
null
|
|
)
|
|
nic_type = config.value.nic_type
|
|
stack_type = config.value.stack_type
|
|
dynamic "access_config" {
|
|
for_each = config.value.nat || config.value.network_tier != null ? [""] : []
|
|
content {
|
|
nat_ip = try(
|
|
local.ctx.addresses[config.value.addresses.external],
|
|
config.value.addresses.external,
|
|
null
|
|
)
|
|
network_tier = try(config.value.network_tier, null)
|
|
}
|
|
}
|
|
dynamic "alias_ip_range" {
|
|
for_each = config.value.alias_ips
|
|
iterator = config_alias
|
|
content {
|
|
subnetwork_range_name = config_alias.key
|
|
ip_cidr_range = config_alias.value
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
dynamic "network_interface" {
|
|
for_each = var.network_attached_interfaces
|
|
content {
|
|
network_attachment = network_interface.value
|
|
}
|
|
}
|
|
|
|
scheduling {
|
|
automatic_restart = !var.options.spot
|
|
instance_termination_action = local.termination_action
|
|
on_host_maintenance = local.on_host_maintenance
|
|
preemptible = var.options.spot
|
|
provisioning_model = var.options.spot ? "SPOT" : "STANDARD"
|
|
dynamic "max_run_duration" {
|
|
for_each = var.options.max_run_duration == null ? [] : [""]
|
|
content {
|
|
nanos = var.options.max_run_duration.nanos
|
|
seconds = var.options.max_run_duration.seconds
|
|
}
|
|
}
|
|
|
|
dynamic "node_affinities" {
|
|
for_each = var.options.node_affinities
|
|
iterator = affinity
|
|
content {
|
|
key = affinity.key
|
|
operator = affinity.value.in ? "IN" : "NOT_IN"
|
|
values = affinity.value.values
|
|
}
|
|
}
|
|
|
|
dynamic "graceful_shutdown" {
|
|
for_each = var.options.graceful_shutdown != null ? [""] : []
|
|
content {
|
|
enabled = var.options.graceful_shutdown.enabled
|
|
dynamic "max_duration" {
|
|
for_each = var.options.graceful_shutdown.enabled == true && var.options.graceful_shutdown.max_duration_secs != null ? [""] : []
|
|
content {
|
|
seconds = var.options.graceful_shutdown.max_duration_secs
|
|
nanos = 0
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
dynamic "scratch_disk" {
|
|
for_each = [
|
|
for i in range(0, var.scratch_disks.count) : var.scratch_disks.interface
|
|
]
|
|
iterator = config
|
|
content {
|
|
interface = config.value
|
|
}
|
|
}
|
|
|
|
dynamic "service_account" {
|
|
for_each = var.service_account == null ? [] : [""]
|
|
content {
|
|
email = local.service_account.email
|
|
scopes = local.service_account.scopes
|
|
}
|
|
}
|
|
|
|
dynamic "shielded_instance_config" {
|
|
for_each = var.shielded_config != null ? [var.shielded_config] : []
|
|
iterator = config
|
|
content {
|
|
enable_secure_boot = config.value.enable_secure_boot
|
|
enable_vtpm = config.value.enable_vtpm
|
|
enable_integrity_monitoring = config.value.enable_integrity_monitoring
|
|
}
|
|
}
|
|
|
|
dynamic "params" {
|
|
for_each = var.tag_bindings_immutable == null ? [] : [""]
|
|
content {
|
|
resource_manager_tags = var.tag_bindings_immutable
|
|
}
|
|
}
|
|
|
|
dynamic "guest_accelerator" {
|
|
for_each = local.gpu ? [var.gpu] : []
|
|
content {
|
|
type = guest_accelerator.value.type
|
|
count = guest_accelerator.value.count
|
|
}
|
|
}
|
|
}
|
|
|
|
resource "google_compute_instance_iam_binding" "default" {
|
|
project = local.project_id
|
|
for_each = var.iam
|
|
zone = local.zone
|
|
instance_name = var.name
|
|
role = lookup(local.ctx.custom_roles, each.key, each.key)
|
|
members = [
|
|
for m in each.value : lookup(local.ctx.iam_principals, m, m)
|
|
]
|
|
depends_on = [google_compute_instance.default]
|
|
}
|
|
|
|
resource "google_compute_instance_group" "unmanaged" {
|
|
count = var.group != null && !local.template_create ? 1 : 0
|
|
project = local.project_id
|
|
network = (
|
|
length(var.network_interfaces) > 0
|
|
? var.network_interfaces[0].network
|
|
: ""
|
|
)
|
|
zone = local.zone
|
|
name = var.name
|
|
description = var.description
|
|
instances = [google_compute_instance.default[0].self_link]
|
|
dynamic "named_port" {
|
|
for_each = var.group.named_ports != null ? var.group.named_ports : {}
|
|
iterator = config
|
|
content {
|
|
name = config.key
|
|
port = config.value
|
|
}
|
|
}
|
|
}
|
|
|
|
resource "google_service_account" "service_account" {
|
|
count = try(var.service_account.auto_create, null) == true ? 1 : 0
|
|
project = local.project_id
|
|
account_id = "tf-vm-${var.name}"
|
|
display_name = "Terraform VM ${var.name}."
|
|
}
|