Skip to content

fix: keda_additional_scaling_targets variable#203

Merged
Uchinda Padmaperuma (uchinda-sph) merged 14 commits into
mainfrom
fix/keda-scaling-variable
May 8, 2026
Merged

fix: keda_additional_scaling_targets variable#203
Uchinda Padmaperuma (uchinda-sph) merged 14 commits into
mainfrom
fix/keda-scaling-variable

Conversation

@uchinda-sph

Copy link
Copy Markdown
Contributor

No description provided.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current implementation of keda_additional_scaling_targets in scaling.tf uses lookup(t, "attribute", default) to access optional fields. While this works for map types, it fails on object types (like the one defined in this PR) if the attribute is missing from the specific instance, even if it's marked as optional in the variable definition.

To make the module truly flexible and resolve the "Unsupported attribute" errors, we should:

  1. Replace lookup(t, ...) with try(t.attribute, ...) in scaling.tf.
  2. Ensure the variables.tf definition matches the one in this PR to provide the expected schema.

I recommend updating modules/essentials/scaling.tf as well in this PR.

@uchinda-sph

Copy link
Copy Markdown
Contributor Author

The current implementation of keda_additional_scaling_targets in scaling.tf uses lookup(t, "attribute", default) to access optional fields. While this works for map types, it fails on object types (like the one defined in this PR) if the attribute is missing from the specific instance, even if it's marked as optional in the variable definition.

To make the module truly flexible and resolve the "Unsupported attribute" errors, I recommend updating modules/essentials/scaling.tf to use try() instead:

  # Combine system targets with additional targets
  all_scaling_targets = concat(
    [for t in local.system_scaling_targets : {
      name      = t.name
      namespace = t.namespace
      kind      = t.kind
      replicas  = t.replicas
      enabled   = t.enabled
      triggers = try(t.triggers, [
        {
          type = "cron"
          metadata = {
            timezone        = var.keda_scaling_timezone
            start           = try(t.start, "0 8 * * 1-5")
            end             = try(t.end, "0 20 * * 1-5")
            desiredReplicas = tostring(try(t.replicas, 1))
          }
        }
      ])
    } if t.enabled],
    [for t in var.keda_additional_scaling_targets : {
      name      = t.name
      namespace = t.namespace
      kind      = t.kind
      replicas  = t.replicas
      enabled   = true
      triggers = try(t.triggers, [
        {
          type = "cron"
          metadata = {
            timezone        = var.keda_scaling_timezone
            start           = try(t.start, "0 8 * * 1-5")
            end             = try(t.end, "0 20 * * 1-5")
            desiredReplicas = tostring(try(t.replicas, 1))
          }
        }
      ])
    }]
  )

Note: This change is required because lookup() on an object type strictly requires the attribute to exist in the object's schema. Using try(t.attribute, ...) allows for safe navigation of optional fields and prevents the "Unsupported attribute" errors when users provide inconsistent object structures in the input list.

`lookup()` on an object type strictly requires the attribute to exist in the schema. Switching to `try()` allows for safe navigation of optional attributes (start, end, triggers) when users provide inconsistent object structures in the input list.
Added optional fields (min_replicas, max_replicas, scaled_object, authentication) to support both legacy and advanced KEDA configurations in the same list.
Updated `scaling.tf` to support the expanded schema while maintaining backwards compatibility:
- Use `try()` to safely access optional object attributes.
- Support `min_replicas`, `max_replicas`, and `scaled_object` with fallback to `replicas` and `kind`.
- Support `authentication` parameter for `ScaledObject`.
- Ensure type consistency across both system and additional scaling targets.
Switching 'triggers' from 'list(any)' to 'any' provides maximum flexibility for nested object reconciliation, resolving stubborn type inference issues when mixing legacy and advanced scaling formats.
Changing the entire variable type to 'any' is the only definitive way to support truly polymorphic lists of objects in Terraform. This bypasses the source-level literal conversion issues and allows the module's robust internal 'try()' logic to handle various scaling configurations seamlessly.
Replaced the invalid `dynamic "manifest"` block with a `merge()` function on the `spec` map. Attributes in `kubernetes_manifest` cannot be defined using dynamic blocks.
Prevents plan failures when var.cluster_name is derived from a sensitive source, as the name is used to calculate the 'create' boolean for for_each loops in the irsa_role module.
Prevents plan failures when role names are derived from sensitive variables.
Prevents plan failures when names are derived from sensitive variables.
Ensures that if namespace or name are derived from sensitive cluster variables, the for_each loop keys are treated as non-sensitive to prevent plan failures.
@uchinda-sph Uchinda Padmaperuma (uchinda-sph) merged commit 6cd9006 into main May 8, 2026
9 checks passed
@uchinda-sph Uchinda Padmaperuma (uchinda-sph) deleted the fix/keda-scaling-variable branch May 8, 2026 02:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants