hashicorp / terraform-provider-helm

Terraform Helm provider
https://www.terraform.io/docs/providers/helm/
Mozilla Public License 2.0
999 stars 370 forks source link

error unmarshaling JSON: while decoding JSON: json: cannot unmarshal string into Go value of type #838

Closed gothrek22 closed 1 year ago

gothrek22 commented 2 years ago

Terraform, Provider, Kubernetes and Helm Versions

Terraform version: 1.1.7
Provider version: 2.4.1
Kubernetes version: 1.20

Affected Resource(s)

Terraform Configuration Files

resource "kubernetes_namespace" "cluster-autoscaler" {
  count = var.ca_arn == null ? 0 : 1
  metadata {
    name = "cluster-autoscaler"
  }
}

resource "helm_release" "cluster-autoscaler" {
  count     = var.ca_arn == null ? 0 : 1
  name      = "cluster-autoscaler"
  namespace = "cluster-autoscaler"

  repository = "https://kubernetes.github.io/autoscaler"
  chart      = "cluster-autoscaler"

  values = ["ca-values.yml"]

  set {
    name  = "autoDiscovery.clusterName"
    value = var.cluster_name
  }
  set {
    #escapes required to break interpolation of fields for domain style annotations
    name  = "rbac.serviceAccount.annotations.eks\\.amazonaws\\.com/role-arn"
    value = var.ca_arn
  }
  set {
    name  = "awsRegion"
    value = var.region
  }
}

ca-values.yaml:

extraArgs:
  logtostderr: true
  stderrthreshold: info
  v: 4
  skip-nodes-with-local-storage: false
  expander: least-waste
  balance-similar-node-groups: true  
  skip-nodes-with-system-pods: false 
rbac:
  create: true
  pspEnabled: false
  serviceAccount:
    create: true
    name: cluster-autoscaler
replicaCount: 1
resources: 
  limits:
    cpu: 100m
    memory: 600Mi
  requests:
    cpu: 100m
    memory: 600Mi
securityContext:
  runAsNonRoot: true
  runAsUser: 65534
  fsGroup: 65534

tfvars

Debug Output

Nothing related could be found in the log.

Panic Output

No panic was found

Steps to Reproduce

  1. terraform apply

set:

ca_arn: to any string region: set it to any valid aws region or probably anything at all cluster-name: set it to anything

Expected Behavior

cluster-autoscaler should be deployed

Actual Behavior

 ---> error unmarshaling JSON: while decoding JSON: json: cannot unmarshal string into Go value of type map[string]interface {} ca-values.yml
│
│   helm_release.cluster-autoscaler[0],

Important Factoids

AWS EKS is used here.

If I disable values attribute and run an apply, it works, enabling values attribute then and re-running also works. It only fails when running against a vanilla setup

References

Community Note

gothrek22 commented 2 years ago

Regarding debug logs, I've went through them, but it seems to me that there is nothing relevant there, as there is no lines relating to the yaml itself.

I'll also add that the same yaml with all the values works, when used by helm directly. Seems to be an issue with casting stuff in the yaml to string. But I'm trying to confirm that right now.

gothrek22 commented 2 years ago

Second run was also not fixing the issue, because it was not replacing the config, due to missing force_update=true. So it seems that the issue is just there.

gothrek22 commented 2 years ago

Ok, found the issue.

That cryptic error about unmarshalling string to a map of string means that the module was unable to resolve the content of values parameter to the contents of the actual file. Which caused the issue.

I've used an example from the net to use this module, whereas the proper call is in the docs. Although the error could use refinement. So I'm not sure if I should close this issue or not.

blue928 commented 2 years ago

@gothrek22 Could you please paste your solution? I'm also getting this error and consider it a bug. No matter what I do, I cannot get annotations to work.

I'm using the Bitnami Drupal helm chart, and per the helm chart documentation for Drupal, the default value for ingress.annotations is {}

set {
    name = "ingress.annotations"
    value = "cert-manager.io/cluster-issuer: letsencrypt-prod"
  }

or

set {
    name = "ingress.annotations.cert-manager.io/cluster-issuer"
    value = "letsencrypt-prod"
  }

The above does not work. I get this error: (note, I've tried every way to escape it that I know as well)

Error: YAML parse error on drupal/templates/ingress.yaml: error unmarshaling JSON: while decoding JSON: json: cannot unmarshal array into Go struct field .metadata.annotations of type map[string]string

The bitnami default values.yaml file has the correct annotations syntax for let's encrypt, so when I try to use the values block I still get errors:

  values = [
    "${path.module}/values.yaml"
  ]

#### bitnami default yaml section
ingress:
...
   annotations:
     kubernetes.io/ingress.class: nginx
     cert-manager.io/cluster-issuer: cluster-issuer-name

That throws this error:

Error: ---> error unmarshaling JSON: while decoding JSON: json: cannot unmarshal string into Go value of type map[string]interface {} .terraform/modules/helm-app-module/values.yaml

If the default values in a bitnami chart throw an error, and that's not a bug, what are the correct ways to set these types of values via the set{} block in helm_release or via values.yaml?

dza89 commented 2 years ago

This can be fixed by setting: tostring(var.ca_arn)

ghost commented 2 years ago

I was having the same issue. But set the annotations values like this and it worked.

  set {
      name = "serviceAccount.annotations.eks\\.amazonaws\\.com/role-arn"
      value = "${aws_iam_role.this.arn}"
      type = "string"
  }
ashishjullia commented 2 years ago

Hey guys, same issue here, been struggling with this for the past 3-4 days.

I'm using the following:

  set {
    name = "serviceAccount.annotations.eks\\.amazonaws\\.com/role-arn"
    value = module.load_balancer_controller_irsa_role.iam_role_arn
    type  = "string"
  }

  set {
    name = "serviceAccount.annotations.eks.\\amazonaws\\.com/sts-regional-endpoints"
    value = "true"
    type  = "string"
  }

But still getting the following error: Error: YAML parse error on aws-load-balancer-controller/templates/serviceaccount.yaml: error unmarshaling JSON: while decoding JSON: json: cannot unmarshal object into Go struct field .metadata.annotations of type string

Also, FYI this is the link to exact line of code in the chart.

If there's anything to point out here, please help me out.

tyu0912 commented 2 years ago

I was having the same issue. But set the annotations values like this and it worked.

  set {
      name = "serviceAccount.annotations.eks\\.amazonaws\\.com/role-arn"
      value = "${aws_iam_role.this.arn}"
      type = "string"
  }

Thanks @git4suvendu . Was looking everywhere for this. Knew it was something easy.

ashishjullia commented 2 years ago

@tyu0912 There was a typo on my side which was hard to figure out but I can understand the following thing, maybe it will help you or others in future on this:

-> When using a module and accessing things like "arn" and other related things to that module, there is no need to use "${ }". it can be done without it, i.e. the value can be accessed without that as a string.

gothrek22 commented 2 years ago

@blue928 I have notifications turned off here, but the solution was to do it like this:

values = [
    file("${path.module}/ca-values.yml")
  ]
kalamba commented 2 years ago

It's working for me too

  set {
    name  = "controller.serviceAccount.annotations.eks\\.amazonaws\\.com/role-arn"
    value = "${module.ebs_csi_irsa_role.iam_role_arn}"
    type = "string"
  }
manshshriva commented 1 year ago

it's not working for me Terraform v1.0.2 on darwin_amd64

ashishjullia commented 1 year ago

it's not working for me Terraform v1.0.2 on darwin_amd64

  • provider registry.terraform.io/cloudposse/utils v1.5.0
  • provider registry.terraform.io/hashicorp/aws v4.38.0
  • provider registry.terraform.io/hashicorp/helm v2.7.1
  • provider registry.terraform.io/hashicorp/kubernetes v1.13.4
  • provider registry.terraform.io/hashicorp/null v3.2.0 set { name = "certificate_arn" value = "${var.certificate_arn}" type = "string" }

Try the 'value' part without "${}".

manshshriva commented 1 year ago

no, it did not work. this is what I am trying to do in service.yaml

apiVersion: v1 kind: Service metadata: name: api-service annotations: service.beta.kubernetes.io/aws-load-balancer-ssl-cert: {{.Values.certificate_arn}}

And I am trying to set the variable value in terraform set { name = "certificate_arn" value = "${var.certificate_arn}" type = "string" }

pallasathena92 commented 1 year ago

I was having the same issue. But set the annotations values like this and it worked.

  set {
      name = "serviceAccount.annotations.eks\\.amazonaws\\.com/role-arn"
      value = "${aws_iam_role.this.arn}"
      type = "string"
  }

For this name = "serviceAccount.annotations.eks\\.amazonaws\\.com/role-arn" why only add \ before .amazonaws and .com. Is there any reason?

Updated: I finger it out, eks.amazonaws.com/role-arn is the key for this annotation

suman7718 commented 1 year ago

json: cannot unmarshal array into Go struct field Prediction.input of type map[string]interface ()

smyja commented 1 year ago

still getting the same error