Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented specialized conversion for helm_release resources. #198

Closed
wants to merge 7 commits into from

Conversation

Zaid-Ajaj
Copy link
Contributor

Description

This PR implements custom conversion handling for helm_release resources and maps them to resources of type kubernetes:helm.sh/v3:Release.

Addresses #58
Fixes pulumi/pulumi-kubernetes#2744 because the type mapping is also handled for state conversions.

Implemented using a specialized version of convertBody called convertHelmReleaseResource which handles converting the supported fields, their required renames, nesting and rewrites (see examples below or full example added to the tests)

It doesn't handle the helm provider blocks, haven't looked into these for this implementation, only the helm_release itself.

Basic example

resource "helm_release" "example" {
  name  = "redis"
  chart = "redis"
}

becomes:

resource "example" "kubernetes:helm.sh/v3:Release" {
  name = "redis"
  chart = "redis"
}

Example with repository options

Repository options in the tf schema are top-level fields but in pulumi-kubernetes, these are subfields of an options object repositoryOpts:

resource "helm_release" "example" {
  name  = "redis"
  chart  = "redis"
  repository = "https://charts.bitnami.com/bitnami"
  repository_ca_file = "./ca.pem"
  repository_cert_file = "./cert.pem"
  repository_key_file = "./key.pem"
  repository_password = "password"
  repository_username = "username"
}

becomes:

resource "example" "kubernetes:helm.sh/v3:Release" {
  name = "redis"
  chart = "redis"
  repositoryOpts = {
    repo     = "https://charts.bitnami.com/bitnami"
    caFile   = "./ca.pem"
    certFile = "./cert.pem"
    keyFile  = "./key.pem"
    password = "password"
    username = "username"
  }
}

Example with custom chart values

In tf, the helm_release resources uses blocks set_value, set_list and set_sensitive that have attributes name and value. With this implementation, these blocks are converted to a single values map as follows:

resource "helm_release" "example" {
  name  = "redis"
  chart = "redis"
  set {
    name  = "set_1"
    value = "value1"
  }
  set_list {
    name  = "set_list_1"
    value = "value1"
  }
  set_sensitive {
    name  = "set_sensitive_1"
    value = "value1"
    type = "string"
  }
}

becomes:

resource "example" "kubernetes:helm.sh/v3:Release" {
  name = "redis"
  chart = "redis"
  values = {
    "set_1"           = "value1"
    "set_list_1"      = "value1"
    "set_sensitive_1" = secret("value1")
  }
}

TODOs for other fields:

The block postrender { binaryPath = "bin", args = ["args"] } and field values = ["key:value"] are not converted yet. I need to think a bit more about these two because postrender block should be combined into a single string postrender = "bin arg"

the values field need to map to valueYamlFiles where each element of the list should be wrapped in stringAsset:

# tf
values = ["key:value"]
# pulumi
valueYamlFiles = [stringAsset("key:value")]

@stooj
Copy link

stooj commented Oct 7, 2024

There is a useful collection of aws-specific helm terraform projects that might be useful for testing.

https://github.com/awslabs/data-on-eks

Copy link

@EronWright EronWright left a comment

Choose a reason for hiding this comment

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

I would advocate for a different approach that would encapsulate the translation logic into the resource provider. Imagine that the converter used an alternative Args class and that the Helm resource constructor were polymorphic. The Check method could normalize the args at will.

This code looks fine though.

blockPath = appendPathArray(blockPath)
}

if block.Type == "dynamic" {

Choose a reason for hiding this comment

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

This all seems like generic parsing logic, is it really resource-specific?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is not resource specific, dynamic blocks are used to create list comprehensions for resource fields. That said, for this resource, I don't see this being used for the available fields. I can simplify and remove this logic from here.

Copy link

@EronWright EronWright left a comment

Choose a reason for hiding this comment

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

This approach strikes me as quite undesirable, it is simply too specialized.

I would advocate for a different design, where the converter produce a generic "TF args" to convey the inputs (without transformation) to the resource. The Check operation could then handle conversion from TF input to checked state.

@Zaid-Ajaj Zaid-Ajaj closed this Dec 10, 2024
@Zaid-Ajaj Zaid-Ajaj deleted the zaid/specialized-helm-release-conversion branch December 11, 2024 09:19
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.

TF Converter for Helm Release
3 participants