modules/compute/gke-node-pool/reservation_definitions.tf (65 lines of code) (raw):

/** * Copyright 2025 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. */ # Split the input into three different lists where the details of a given reservation are at the same index across these lists. locals { # Specific block of an extended reservation can be targeted with exr-one/reservationBlocks/exr-one-block-1 # Data source needs to be queried with the reservation name only. So, we extract the reservation name input_reservation_names = [for r in try(var.reservation_affinity.specific_reservations, []) : split("/", r.name)[0]] input_reservation_projects = [for r in try(var.reservation_affinity.specific_reservations, []) : coalesce(r.project, var.project_id)] # We, also, remember the suffix "/reservationBlocks/exr-one-block-1" for use elsewhere afterwards input_reservation_suffixes = [for r in try(var.reservation_affinity.specific_reservations, []) : substr(r.name, length(split("/", r.name)[0]), -1)] } data "google_compute_reservation" "specific_reservations" { for_each = ( local.input_specific_reservations_count == 0 ? {} : { for pair in flatten([ for zone in try(var.zones, []) : [ for i, reservation_name in try(local.input_reservation_names, []) : { key : "${local.input_reservation_projects[i]}/${zone}/${reservation_name}" zone : zone reservation_name : reservation_name project : local.input_reservation_projects[i] } ] ]) : pair.key => pair } ) name = each.value.reservation_name zone = each.value.zone project = each.value.project } locals { generated_guest_accelerator = module.gpu.machine_type_guest_accelerator reservation_resource_api_label = "compute.googleapis.com/reservation-name" input_specific_reservations_count = try(length(var.reservation_affinity.specific_reservations), 0) # Filter specific reservations verified_specific_reservations = [for k, v in data.google_compute_reservation.specific_reservations : v if(v.specific_reservation != null && v.specific_reservation_required == true)] # Build two maps to be used to compare the VM properties between reservations and the node pool # Skip this for TPUs reservation_vm_properties = local.has_gpu ? ([for reservation in local.verified_specific_reservations : { "machine_type" : try(reservation.specific_reservation[0].instance_properties[0].machine_type, "") "guest_accelerators" : { for acc in try(reservation.specific_reservation[0].instance_properties[0].guest_accelerators, []) : acc.accelerator_type => acc.accelerator_count } }]) : [] nodepool_vm_properties = { "machine_type" : var.machine_type "guest_accelerators" : { for acc in try(local.guest_accelerator, []) : coalesce(acc.type, try(local.generated_guest_accelerator[0].type, "")) => coalesce(acc.count, try(local.generated_guest_accelerator[0].count, 0)) } } # Compare two maps by counting the keys that mismatch. # Know that in map comparison the order of keys does not matter. That is {NVME: x, SCSI: y} and {SCSI: y, NVME: x} are equal # As of this writing, there is only one reservation supported by the Node Pool API. So, directly accessing it from the list specific_reservation_requirement_violations = length(local.reservation_vm_properties) == 0 ? [] : [for k, v in local.nodepool_vm_properties : k if v != local.reservation_vm_properties[0][k]] specific_reservation_requirement_violation_messages = { "machine_type" : <<-EOT The reservation has "${try(local.reservation_vm_properties[0].machine_type, "")}" machine type and the node pool has "${local.nodepool_vm_properties.machine_type}". Check the relevant node pool setting: "machine_type" EOT "guest_accelerators" : <<-EOT The reservation has ${jsonencode(try(local.reservation_vm_properties[0].guest_accelerators, {}))} accelerators and the node pool has ${jsonencode(try(local.nodepool_vm_properties.guest_accelerators, {}))}. Check the relevant node pool setting: "guest_accelerator". When unspecified, for the machine_type=${var.machine_type}, the default is guest_accelerator=${jsonencode(try(local.generated_guest_accelerator, [{}]))}. EOT } }