Kargo Projects Created via Terraform Not Visible in UI or CLI
Understanding and Resolving Issues with kargo_instance Terraform Resource and local.projects Variable Configuration
When using the kargo_instance Terraform resource to manage project creation, it’s possible for Terraform to report successful application of resources while the corresponding projects do not appear in the Kargo UI or CLI.
This issue commonly stems from how the local.projects variable is constructed, particularly when using yamldecode and jsonencode to generate Kargo project manifests dynamically.
Observed Behavior
-
Terraform plan and apply complete successfully with no reported errors.
-
Kargo projects are not visible via:
-
Kargo UI
-
kargo get projectsCLI command
-
-
The Terraform state file (
terraform.tfstate) reflects the resources as applied.
Root Cause
The problem is typically due to how the local.projects block generates keys and values when using Terraform locals.
Here’s the problematic configuration snippet:
locals { kargo_resource_objects = [ for p in var.projects : yamldecode(<<-EOT apiVersion: kargo.akuity.io/v1alpha1 kind: Project metadata: name: ${p} EOT ) ] projects = { for obj in local.kargo_resource_objects : "${obj.apiVersion}/${obj.kind}/${try(obj.metadata.namespace, "")}/${obj.metadata.name}" => jsonencode(obj) }}The issue lies in the namespace resolution (try(obj.metadata.namespace, "")) — the empty namespace ("") in the key generation can lead to misalignment with what the Kargo provider expects. As a result, the resources are "applied" in Terraform but never reach the actual API server.
In other words, Terraform sees the locals as valid inputs, but the Kargo provider doesn't submit a valid resource definition to the control plane due to malformed or incomplete keys.
Resolution Steps
-
Update the locals block to correctly handle namespaces and serialization:
locals {
kargo_resource_objects = [
for p in var.projects :
yamldecode(<<-EOT
apiVersion: kargo.akuity.io/v1alpha1
kind: Project
metadata:
name: ${p}
namespace: kargo-system
EOT
)
]
projects = {
for obj in local.kargo_resource_objects :
"${obj.apiVersion}/${obj.kind}/${obj.metadata.namespace}/${obj.metadata.name}" => jsonencode(obj)
}
}✅ Key changes:
-
Explicitly set a namespace (e.g.,
kargo-system). -
Removed the
try()wrapper to ensure valid key formation. -
Guaranteed that every resource includes both
apiVersion,kind, andnamespacekeys for correct API mapping.
-
-
Re-run Terraform Apply
terraform plan
terraform apply -
Verify the Project Exists
-
Via CLI:
kargo get projects -
Via UI:
Navigate to the Projects tab in the Kargo UI — the newly created projects should now appear.
-
-
Optional Validation
Confirm that the Kargo controller has received the resource definitions:kubectl get projects.kargo.akuity.io -A
Additional Notes
-
Terraform may not report validation issues when locals or dynamic resources generate invalid or incomplete manifests — it only verifies syntax and HCL structure, not the correctness of the YAML for the API.
-
Always ensure that:
-
apiVersionandkindare correct. -
metadata.namespaceis explicitly defined. -
The resulting
jsonencode()output matches the schema expected by the Kargo API.
-