Skip to content

Conversation

@rauneetverma
Copy link
Contributor

@rauneetverma rauneetverma commented Aug 21, 2025

Description

Related issues

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

Checklist

  • I have created feat/bugfix branch out of develop branch
  • Code passes linting/formatting checks
  • Changes to resources have been tested in our dev environments
  • I have made corresponding changes to the documentation

Testing

Reviewer instructions

Summary by CodeRabbit

  • New Features
    • Introduced a Helm deployment module for Kubernetes (k8s v0.2) enabling installation of external Helm charts with configurable chart, repository, version, namespace, wait behavior, and optional repository credentials.
    • Supports values as YAML with an inline editor and sensible defaults (namespace, timeout, create-namespace, cleanup on failure).
    • Integrates with common clouds and Kubernetes providers.
    • Exposes release metadata and status for visibility and automation.
    • Includes sample configuration to get started quickly.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 21, 2025

Walkthrough

Introduces a new Helm module for Kubernetes (k8s flavor v0.2) with a facet definition, Terraform providers, variables, Helm release deployment logic, and outputs exposing Helm release metadata and status.

Changes

Cohort / File(s) Summary of changes
Facet definition (k8s Helm v0.2)
modules/helm/k8s/0.2/facets.yaml
Adds a public facet manifest for Helm intent (k8s, v0.2), declaring clouds, IAC validation, required inputs, a Helm chart schema (chart/repository/version/namespace/credentials/wait), required values, and a sample spec.
Terraform module scaffolding
modules/helm/k8s/0.2/variables.tf, modules/helm/k8s/0.2/versions.tf
Declares module variables (instance, instance_name, environment, inputs) and required providers (helm3, kubernetes) with Terraform version constraint.
Helm release deployment
modules/helm/k8s/0.2/main.tf
Implements locals for env variable resolution and a helm_release resource configuring chart/name/namespace, repo/version/credentials, wait/timeout, namespace creation, cleanup on fail, and optional YAML-encoded values.
Module outputs
modules/helm/k8s/0.2/outputs.tf
Exposes Helm release metadata and status; defines locals for output attributes/interfaces.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Facet as Facet (facets.yaml)
  participant TF as Terraform Module
  participant Helm as Provider: helm3
  participant K8s as Provider: kubernetes
  Note over Facet: Defines spec schema (helm + values) and inputs
  User->>Facet: Provide spec (chart/repo/version/namespace/values)
  Facet->>TF: Pass instance, environment, inputs
  TF->>TF: Build locals (static/secret env, values)
  TF->>Helm: helm_release(external_helm_charts)
  Helm->>K8s: Create namespace (if needed)
  Helm->>K8s: Install/upgrade Helm chart
  K8s-->>Helm: Status/metadata
  Helm-->>TF: Release metadata/status
  TF-->>User: Outputs: metadata, status
  Note over TF: cleanup_on_fail, wait, timeout handling
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

migration

Suggested reviewers

  • rr0hit
  • anshulsao
  • vishnukv-facets
  • pramodh-ayyappan
  • ishaankalra
  • unni-facets

Poem

In charts I hop, in namespaces I play,
A helm-toting bunny deploying away.
Repos and values tucked under my ear,
I wait (or don’t) with zero fear.
Metadata glitter, statuses glow—
Carrots secured, to prod we go! 🥕⛵️

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch helm3-provider

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🧹 Nitpick comments (8)
modules/helm/k8s/0.2/versions.tf (1)

10-11: Consider tightening the Terraform version constraint.

>= 0.13 is extremely broad and allows pre-1.0 releases with different behaviors. Consider pinning to the tested major/minor range (for example, >= 1.3, < 2.0) to avoid unexpected init/plan differences across environments. If you already validated with a specific 1.x series, lock that in.

Would you like me to propose exact version constraints for both Terraform and the Helm/Kubernetes providers based on your currently tested versions?

modules/helm/k8s/0.2/variables.tf (3)

6-9: Avoid defaulting instance_name to a placeholder.

A default like "test_instance" can cause accidental cross-env name collisions. Prefer making it required (no default) or generate it upstream.


18-21: inputs appears unused in this module.

If not used, drop it to reduce surface area; if it is planned, reference it in main.tf.


1-4: Enforce a strict schema for var.instance instead of using any and guard direct indexing

The untyped variable "instance" in modules/helm/k8s/0.2/variables.tf (lines 1–4) allows arbitrary values, but we have unguarded reads like:

  • chart = var.instance.spec["helm"]["chart"] in modules/helm/k8s/0.2/main.tf:20
  • variables = lookup(var.instance.spec, "env", []) (guarded here, but others are not)

To catch missing or misspelled attributes at plan time and avoid runtime errors, replace the any type with a minimal object schema that mirrors the expected shape, and then you can safely use direct indexing on required fields (or continue to use lookup() for optional ones).

Locations to update:

  • modules/helm/k8s/0.2/variables.tf (lines 1–4)
  • modules/helm/k8s/0.2/main.tf (lines 19–23)

Proposed diff for variables.tf:

 variable "instance" {
-  type    = any
-  default = {}
+  type = object({
+    spec = object({
+      helm = object({
+        chart                = string
+        namespace            = optional(string, var.environment.namespace)
+        timeout              = optional(number, 300)
+        wait                 = optional(bool, true)
+        repository           = optional(string, "")
+        version              = optional(string, "")
+        recreate_pods        = optional(bool, false)
+        repository_username  = optional(string, null)
+        repository_password  = optional(string, null)
+      })
+      env    = optional(list(object({ key = string, value = string, type = string })), [])
+      values = optional(map(any), {})
+    })
+  })
 }

And for main.tf, either:

• Rely on direct indexing for required fields now enforced by the type:

  chart               = var.instance.spec.helm.chart
  namespace           = var.instance.spec.helm.namespace

• Or wrap all reads in lookup()/try() if you’d rather keep any and handle missing keys at runtime:

- chart               = var.instance.spec["helm"]["chart"]
+ chart               = lookup(var.instance.spec["helm"], "chart", "")

Let me know if you’d like a full typed-schema proposal for other modules’ instance variables or any adjustments here.

modules/helm/k8s/0.2/facets.yaml (3)

45-47: Typo in error message: “hypens” → “hyphens”; also consider restricting to lowercase for chart names.

Helm chart names conventionally use lowercase alphanumeric and hyphens. Fix the typo and optionally update the regex to enforce lowercase to match common constraints.

-          pattern: ^[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*[a-zA-Z0-9]$
-          x-ui-error-message: Invalid format. Only alphabets, numbers and hypens are
-            allowed
+          pattern: '^[a-z0-9]([-a-z0-9]*[a-z0-9])?$'
+          x-ui-error-message: Invalid format. Only lowercase letters, numbers, and hyphens are allowed.

26-29: Provider naming inconsistency across layers.

The facet lists provider names kubernetes, helm, kubernetes-alpha, but versions.tf uses a provider named helm3. Align the naming to avoid confusion in orchestration and provider wiring docs.


10-12: Validate more than variables.tf in IAC gates.

Given the logic concentrated in main.tf and schema in this file, include them in validation to catch drifts early.

 iac:
   validated_files:
-  - variables.tf
+  - variables.tf
+  - main.tf
+  - facets.yaml
modules/helm/k8s/0.2/outputs.tf (1)

1-6: output_interfaces is declared but unused.

If this is a convention for consumers, keep it; otherwise, drop it to reduce noise.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a6eb702 and 1898907.

📒 Files selected for processing (5)
  • modules/helm/k8s/0.2/facets.yaml (1 hunks)
  • modules/helm/k8s/0.2/main.tf (1 hunks)
  • modules/helm/k8s/0.2/outputs.tf (1 hunks)
  • modules/helm/k8s/0.2/variables.tf (1 hunks)
  • modules/helm/k8s/0.2/versions.tf (1 hunks)

Comment on lines +66 to +69
pattern: ^[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*$
x-ui-error-message: Invalid namespace format. The namespace must be DNS-compliant,
containing only letters, numbers, and hyphens, and must not start or end
with a hyphen
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Namespace regex allows uppercase and violates k8s DNS-1123 label rules.

Kubernetes namespaces must be lowercase alphanumeric plus hyphen, start/end with alphanumeric, max 63 chars. Update the pattern accordingly.

-          pattern: ^[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*$
-          x-ui-error-message: Invalid namespace format. The namespace must be DNS-compliant,
-            containing only letters, numbers, and hyphens, and must not start or end
-            with a hyphen
+          pattern: '^[a-z0-9]([-a-z0-9]*[a-z0-9])?$'
+          x-ui-error-message: Invalid namespace format. Must be DNS-1123 compliant: lowercase letters,
+            numbers, and hyphens; must start and end with an alphanumeric character.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In modules/helm/k8s/0.2/facets.yaml around lines 66 to 69, the current regex
allows uppercase letters and doesn't enforce Kubernetes DNS-1123 label rules;
replace the pattern with one that enforces lowercase letters, numbers and
hyphens only, ensures the name starts and ends with an alphanumeric character,
and limits length to 1–63 characters (e.g. use a pattern like
^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$), and adjust the x-ui-error-message to
mention lowercase and the 63-character limit.

Comment on lines +101 to +117
required:
- helm
- values
sample:
$schema: https://facets-cloud.github.io/facets-schemas/schemas/helm/helm.schema.json
kind: helm
flavor: k8s
disabled: true
metadata: {}
version: '0.2'
spec:
helm:
repository: https://helm.datadoghq.com
chart: datadog
namespace: default
wait: false
values: null
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Schema requires values but sample sets it to null; this will fail validation.

You mark values as required and typed object, yet the sample has values: null and main.tf explicitly supports null. Relax the schema or drop values from required.

Option A (allow nulls):

-    values:
-      type: object
+    values:
+      type:
+      - object
+      - 'null'
@@
-  required:
-  - helm
-  - values
+  required:
+  - helm

Option B (if you want to require non-null values): update sample and main.tf to align.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
required:
- helm
- values
sample:
$schema: https://facets-cloud.github.io/facets-schemas/schemas/helm/helm.schema.json
kind: helm
flavor: k8s
disabled: true
metadata: {}
version: '0.2'
spec:
helm:
repository: https://helm.datadoghq.com
chart: datadog
namespace: default
wait: false
values: null
# In your JSON Schema definitions (e.g. under `properties:`)
values:
type:
- object
- 'null'
# In the same file, replace the `required` block:
required:
- helm
# (The rest of the sample stays unchanged:)
sample:
$schema: https://facets-cloud.github.io/facets-schemas/schemas/helm/helm.schema.json
kind: helm
flavor: k8s
disabled: true
metadata: {}
version: '0.2'
spec:
helm:
repository: https://helm.datadoghq.com
chart: datadog
namespace: default
wait: false
values: null
🤖 Prompt for AI Agents
In modules/helm/k8s/0.2/facets.yaml around lines 101 to 117, the schema marks
`values` as required and object-typed but the sample sets `values: null`,
causing validation failure; fix by either A) allowing nulls in the schema (make
the `values` type accept null, e.g., object OR null) or remove `values` from the
required list so null is permitted, or B) if `values` must be non-null, update
the sample to provide a valid object for `values` and adjust main.tf to disallow
nulls consistently.

Comment on lines +3 to +15
variables = lookup(var.instance.spec, "env", [])
# filter out static variables
static_variables = toset([for x in local.variables : x if x["type"] == "static"])
# filter out static variables
dynamic_variables_raw = toset([for x in local.variables : x if x["type"] == "secret"])
# replace the value
dynamic_variables = toset([
for x in local.dynamic_variables_raw : {
name = x["name"],
default = lookup(var.environment.secrets, x["attribute"], "Invalid Secret Reference")
}
])
all_variables = setunion(local.static_variables, local.dynamic_variables)
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Guard nested attribute access and avoid set unions across heterogeneous object shapes.

Directly accessing var.instance.spec and var.environment.secrets will error when absent. Also, setunion across objects with different shapes (static vs. dynamic) can fail type unification. Use try()/lookup() and keep lists unless you specifically need sets.

Apply this refactor to harden locals:

 locals {
-
-  variables = lookup(var.instance.spec, "env", [])
-  # filter out static variables
-  static_variables = toset([for x in local.variables : x if x["type"] == "static"])
-  # filter out static variables
-  dynamic_variables_raw = toset([for x in local.variables : x if x["type"] == "secret"])
-  # replace the value
-  dynamic_variables = toset([
-    for x in local.dynamic_variables_raw : {
-      name    = x["name"],
-      default = lookup(var.environment.secrets, x["attribute"], "Invalid Secret Reference")
-    }
-  ])
-  all_variables = setunion(local.static_variables, local.dynamic_variables)
+  spec      = try(var.instance.spec, {})
+  helm_spec = try(local.spec.helm, {})
+  variables = try(local.spec.env, [])
+
+  # Filter static variables
+  static_variables = [for x in local.variables : x if try(x.type, null) == "static"]
+
+  # Filter secret-backed variables
+  dynamic_variables_raw = [for x in local.variables : x if try(x.type, null) == "secret"]
+
+  # Resolve secret defaults safely (environment.secrets may be absent)
+  dynamic_variables = [
+    for x in local.dynamic_variables_raw : {
+      name    = x.name
+      default = lookup(lookup(var.environment, "secrets", {}), x.attribute, "Invalid Secret Reference")
+    }
+  ]
+
+  # Combine without forcing a set of mixed object shapes
+  all_variables = concat(local.static_variables, local.dynamic_variables)
 }

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In modules/helm/k8s/0.2/main.tf around lines 3 to 15, the code directly indexes
nested attributes and performs setunion across objects with different shapes
which will break when var.instance.spec or var.environment.secrets are absent
and when static and dynamic objects differ; change to use lookup()/try() to
safely access var.instance.spec and var.environment.secrets with sensible
defaults, keep variables as lists (not sets) while you build/transform them to
maintain consistent object shapes, ensure both static and dynamic entries share
the same key set (e.g., name and value/default) or normalize them into a common
object shape, then concatenate lists (concat()) instead of setunion() or convert
to sets only after normalization if deduping is required, and provide default
fallback strings for missing secret lookups via lookup(var.environment.secrets,
attr, "<missing>").

Comment on lines +19 to +33
provider = "helm3"
chart = var.instance.spec["helm"]["chart"]
name = var.instance_name
namespace = lookup(var.instance.spec["helm"], "namespace", var.environment.namespace)
timeout = lookup(var.instance.spec["helm"], "timeout", 300)
create_namespace = true
wait = lookup(var.instance.spec["helm"], "wait", true)
repository = lookup(var.instance.spec["helm"], "repository", "")
version = lookup(var.instance.spec["helm"], "version", "")
recreate_pods = lookup(var.instance.spec["helm"], "recreate_pods", false)
repository_username = lookup(var.instance.spec["helm"], "repository_username", null)
repository_password = lookup(var.instance.spec["helm"], "repository_password", null)
values = lookup(var.instance.spec, "values", null) != null ? [yamlencode(lookup(var.instance.spec, "values", {}))] : null
cleanup_on_fail = true
}
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Fix provider reference and make Helm spec access safe.

  • The provider meta-arg must reference a configured provider block (e.g., helm or helm.alias), not a string. Remove it here and let the root module pass the provider mapping, or switch to provider = helm.some_alias if you declare it.
  • Use the guarded locals to read Helm settings without crashing when keys are absent.
  • Optional: align default wait with the facet sample (false) to avoid surprises.
 resource "helm_release" "external_helm_charts" {
-  provider            = "helm3"
-  chart               = var.instance.spec["helm"]["chart"]
-  name                = var.instance_name
-  namespace           = lookup(var.instance.spec["helm"], "namespace", var.environment.namespace)
-  timeout             = lookup(var.instance.spec["helm"], "timeout", 300)
-  create_namespace    = true
-  wait                = lookup(var.instance.spec["helm"], "wait", true)
-  repository          = lookup(var.instance.spec["helm"], "repository", "")
-  version             = lookup(var.instance.spec["helm"], "version", "")
-  recreate_pods       = lookup(var.instance.spec["helm"], "recreate_pods", false)
-  repository_username = lookup(var.instance.spec["helm"], "repository_username", null)
-  repository_password = lookup(var.instance.spec["helm"], "repository_password", null)
-  values              = lookup(var.instance.spec, "values", null) != null ? [yamlencode(lookup(var.instance.spec, "values", {}))] : null
-  cleanup_on_fail     = true
+  # provider = helm           # (optional) let root module pass provider; uncomment and set alias if needed
+  chart               = local.helm_spec.chart
+  name                = var.instance_name
+  namespace           = lookup(local.helm_spec, "namespace", lookup(var.environment, "namespace", "default"))
+  timeout             = lookup(local.helm_spec, "timeout", 300)
+  create_namespace    = true
+  wait                = lookup(local.helm_spec, "wait", true)
+  repository          = lookup(local.helm_spec, "repository", "")
+  version             = lookup(local.helm_spec, "version", "")
+  recreate_pods       = lookup(local.helm_spec, "recreate_pods", false)
+  repository_username = lookup(local.helm_spec, "repository_username", null)
+  repository_password = lookup(local.helm_spec, "repository_password", null)
+  values              = try(local.spec.values, null) != null ? [yamlencode(local.spec.values)] : null
+  cleanup_on_fail     = true
 }
  • If you intend to keep an aliased provider (e.g., helm3), add provider "helm" { alias = "v3" } in the root and use provider = helm.v3 here, and adjust required_providers to helm = { source = "hashicorp/helm" } in versions.tf.
  • Confirm whether wait default should be false to match the facet sample (values.wait: false).

🏁 Script executed:

#!/bin/bash
set -e

# Inspect for locals block within the helm module
echo ">>> Checking for locals blocks in modules/helm/k8s/0.2/main.tf"
rg -n 'locals' -C3 modules/helm/k8s/0.2/main.tf || echo "No locals block found in this file"

# Search for any references to helm_spec throughout the repo
echo ">>> Searching for 'helm_spec' references across the repository"
rg -n 'helm_spec' -C3 . || echo "No occurrences of 'helm_spec' found"

Length of output: 544


Fix missing local.helm_spec definition and correct provider usage

The suggested diff references local.helm_spec, but no such local is defined in modules/helm/k8s/0.2/main.tf. To implement these changes safely:

• Add a locals block at the top of modules/helm/k8s/0.2/main.tf:

locals {
  # pull the Helm-specific settings, or use an empty object if absent
  helm_spec   = lookup(var.instance.spec, "helm", {})
  # pull any top-level values, or default to empty map
  spec_values = lookup(var.instance.spec, "values", {})
}

• In the helm_release.external_helm_charts resource (lines 19–33), replace all lookup(var.instance.spec["helm"], …) calls with lookup(local.helm_spec, …) and change the values argument to:

values = length(local.spec_values) > 0 ? [yamlencode(local.spec_values)] : null

• Remove the hard-coded provider = "helm3" meta-arg. Either:

  1. Omit the provider setting so the root module’s provider mapping applies, or
  2. Declare an aliased provider in the root (e.g. provider "helm" { alias = "v3" } and required_providers { helm = { source = "hashicorp/helm" } }) and reference it here as provider = helm.v3.
    • Decide on a wait default (true vs. false) to match your facet sample (values.wait = false vs. current default true).

Revised snippet for the resource:

 resource "helm_release" "external_helm_charts" {
-  provider            = "helm3"
-  chart               = var.instance.spec["helm"]["chart"]
+  # provider = helm.v3      # uncomment if using an aliased provider
+  chart               = local.helm_spec.chart
   name                = var.instance_name
   namespace           = lookup(local.helm_spec, "namespace", lookup(var.environment, "namespace", "default"))
   timeout             = lookup(local.helm_spec, "timeout", 300)
   create_namespace    = true
   wait                = lookup(local.helm_spec, "wait", true)
   repository          = lookup(local.helm_spec, "repository", "")
   version             = lookup(local.helm_spec, "version", "")
   recreate_pods       = lookup(local.helm_spec, "recreate_pods", false)
   repository_username = lookup(local.helm_spec, "repository_username", null)
   repository_password = lookup(local.helm_spec, "repository_password", null)
-  values              = lookup(var.instance.spec, "values", null) != null ? [yamlencode(lookup(var.instance.spec, "values", {}))] : null
+  values              = length(local.spec_values) > 0 ? [yamlencode(local.spec_values)] : null
   cleanup_on_fail     = true
 }
🤖 Prompt for AI Agents
In modules/helm/k8s/0.2/main.tf around lines 19 to 33, the code references
local.helm_spec which is not defined and hard-codes provider = "helm3"; fix by
adding a locals block at the top that defines helm_spec =
lookup(var.instance.spec, "helm", {}) and spec_values =
lookup(var.instance.spec, "values", {}), replace all
lookup(var.instance.spec["helm"], ...) calls in the
helm_release.external_helm_charts resource with lookup(local.helm_spec, ...),
change the values argument to use local.spec_values (e.g. values =
length(local.spec_values) > 0 ? [yamlencode(local.spec_values)] : null), and
remove the hard-coded provider meta-arg (or instead reference an aliased
provider declared in the root module such as provider = helm.v3) and ensure the
wait default is set consistently with your facet (choose true or false).

Comment on lines +8 to +10
output "metadata" {
value = helm_release.external_helm_charts.metadata
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

helm_release doesn’t expose a metadata attribute; construct a metadata map instead.

The Helm provider’s helm_release resource exports fields like name, namespace, chart, version, status, etc., but not a single metadata map. Building your own avoids plan/apply failures.

-output "metadata" {
-  value = helm_release.external_helm_charts.metadata
-}
+output "metadata" {
+  value = {
+    name      = helm_release.external_helm_charts.name
+    namespace = helm_release.external_helm_charts.namespace
+    chart     = helm_release.external_helm_charts.chart
+    version   = helm_release.external_helm_charts.version
+  }
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
output "metadata" {
value = helm_release.external_helm_charts.metadata
}
output "metadata" {
value = {
name = helm_release.external_helm_charts.name
namespace = helm_release.external_helm_charts.namespace
chart = helm_release.external_helm_charts.chart
version = helm_release.external_helm_charts.version
}
}
🤖 Prompt for AI Agents
In modules/helm/k8s/0.2/outputs.tf around lines 8 to 10, the output references a
non-existent helm_release.external_helm_charts.metadata attribute; replace it by
constructing and returning a map of metadata using existing attributes (for
example name, namespace, chart, version, status, and any other exported fields
you need) — e.g., build a map literal that pulls
helm_release.external_helm_charts.name, .namespace, .chart, .version, .status,
etc., and output that instead so Terraform plan/apply won’t fail.

Comment on lines +11 to +16
variable "environment" {
type = any
default = {
namespace = "default"
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Default environment lacks secrets; downstream attribute access will crash.

main.tf reads var.environment.secrets. With the current default, var.environment.secrets is undefined and will trigger an evaluation error. Add a default empty map for secrets.

 variable "environment" {
   type = any
   default = {
     namespace = "default"
+    secrets   = {}
   }
 }
🤖 Prompt for AI Agents
In modules/helm/k8s/0.2/variables.tf around lines 11 to 16, the variable
"environment" default lacks a "secrets" key which causes var.environment.secrets
to be undefined downstream; update the default value to include a secrets
attribute (empty map) so the structure matches expectations (e.g., add secrets =
{} inside the default map) and ensure the variable type still accepts that
shape.

Comment on lines +3 to +5
helm3 = {
source = "hashicorp/helm3"
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Use the official Helm provider source and local name; hashicorp/helm3 is invalid.

Terraform’s official Helm provider is hashicorp/helm, and the local name should match how you reference the provider elsewhere. Using helm3 here plus a string literal provider reference in resources will fail provider wiring at plan time.

Apply this diff to align with the official provider:

   required_providers {
-    helm3 = {
-      source  = "hashicorp/helm3"
-    }
+    helm = {
+      source  = "hashicorp/helm"
+    }
     kubernetes = {
       source = "hashicorp/kubernetes"
     }
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
helm3 = {
source = "hashicorp/helm3"
}
required_providers {
helm = {
source = "hashicorp/helm"
}
kubernetes = {
source = "hashicorp/kubernetes"
}
}
🤖 Prompt for AI Agents
In modules/helm/k8s/0.2/versions.tf around lines 3 to 5, the provider source and
local name are incorrect: replace the invalid "hashicorp/helm3" and local name
"helm3" with the official provider source "hashicorp/helm" and a local name that
matches how the provider is referenced elsewhere in the module (e.g., "helm" if
resources refer to provider.helm); update any provider aliases/references in the
module to match the new local name so Terraform can wire the provider correctly
at plan time.

@rauneetverma
Copy link
Contributor Author

deployed keycloak latest version using the new helm 0.2 module:
Screenshot 2025-08-22 at 12 03 13 PM

@@ -0,0 +1,33 @@
locals {

variables = lookup(var.instance.spec, "env", [])
Copy link
Collaborator

Choose a reason for hiding this comment

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

dont have this, variables, static_variables, dynamic_variables_raw etc

default = {}
}

variable "instance_name" {
Copy link
Collaborator

Choose a reason for hiding this comment

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

ask mcp to validate the variables.tf file

@ishaankalra
Copy link
Collaborator

Pending for iac release

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.

3 participants