diff --git a/nullplatform/scope_definition/data.tf b/nullplatform/scope_definition/data.tf index d2586e5bb..d72d4fee0 100644 --- a/nullplatform/scope_definition/data.tf +++ b/nullplatform/scope_definition/data.tf @@ -10,7 +10,7 @@ data "http" "scope_type_template" { } data "http" "action_templates" { - for_each = toset(var.action_spec_names) + for_each = local.static_action_specs url = "${var.repository_action_templates}/${var.repository_action_templates_branch}/${var.service_path}/specs/actions/${each.key}.json.tpl" } @@ -63,7 +63,7 @@ data "external" "scope_type" { # it forces a phantom destroy+recreate of EVERY action_specification # instance at once (their `type` is ForceNew). data "external" "action_specs" { - for_each = toset(var.action_spec_names) + for_each = local.static_action_specs depends_on = [ data.http.action_templates ] diff --git a/nullplatform/scope_definition/locals.tf b/nullplatform/scope_definition/locals.tf index fd3292bf5..468c71374 100644 --- a/nullplatform/scope_definition/locals.tf +++ b/nullplatform/scope_definition/locals.tf @@ -15,7 +15,9 @@ locals { scope_type_def = jsondecode(data.external.scope_type.result.json) - static_action_specs = toset(var.action_spec_names) + static_action_specs = toset( + var.action_spec_names != null ? var.action_spec_names : try(local.service_spec_parsed.available_actions, []) + ) scope_configuration_rendered = var.create_scope_configuration ? replace( data.http.scope_configuration_template[0].response_body, diff --git a/nullplatform/scope_definition/main.tf b/nullplatform/scope_definition/main.tf index 2c41801d6..078724b72 100644 --- a/nullplatform/scope_definition/main.tf +++ b/nullplatform/scope_definition/main.tf @@ -22,6 +22,29 @@ resource "nullplatform_service_specification" "from_template" { provider = local.service_spec_parsed.selectors.provider sub_category = local.service_spec_parsed.selectors.sub_category } + + # Resolving to no actions means the caller relied on the default this variable + # no longer has, and its spec predates `available_actions`. Left alone that is + # an empty for_each below, which destroys every action specification the scope + # has registered — silently, since an empty list is not an error. + # + # The check lives here and not on the action_specification resource: with an + # empty for_each that resource has no instances, so its preconditions never run. + lifecycle { + precondition { + condition = length(local.static_action_specs) > 0 + error_message = <<-EOT + No actions resolved for scope "${var.service_spec_name}". + + Declare `available_actions` in ${var.service_path}/specs/service-spec.json.tpl, + or pass `action_spec_names` explicitly. + + Proceeding would destroy every action specification registered for this + scope: creating and deleting scopes, deploying, blue/green, rollback and + diagnostics all stop being available from the UI. + EOT + } + } } ################################################################################ diff --git a/nullplatform/scope_definition/variables.tf b/nullplatform/scope_definition/variables.tf index 4d2ec94f9..3ce1eaff7 100644 --- a/nullplatform/scope_definition/variables.tf +++ b/nullplatform/scope_definition/variables.tf @@ -58,25 +58,15 @@ variable "repo_path" { } variable "action_spec_names" { - description = "List of action specification template names to fetch and create for scope operations" + description = <<-EOT + List of action specification template names to fetch and create for scope + operations. Default `null` -> use the `available_actions` array from the + scope's `service-spec.json.tpl` (fetched via `repository_service_spec` / + `service_path`). Set this explicitly only when the spec's list is wrong + for your case or the spec predates the `available_actions` field. + EOT type = list(string) - default = [ - "create-scope", - "delete-scope", - "start-initial", - "start-blue-green", - "finalize-blue-green", - "rollback-deployment", - "delete-deployment", - "switch-traffic", - "set-desired-instance-count", - "pause-autoscaling", - "resume-autoscaling", - "restart-pods", - "kill-instances", - "diagnose-deployment", - "diagnose-scope" - ] + default = null } ################################################################################