terraform-linters / tflint

A Pluggable Terraform Linter
Mozilla Public License 2.0
4.86k stars 353 forks source link

Panic: cannot refine an unknown value of an unknown type #1831

Closed ahmad-hamade closed 1 year ago

ahmad-hamade commented 1 year ago

Summary

TFLint started crashing after we upgraded from 0.46.1 to 0.47.0

Command

tflint --config=/infra/.tflint.hcl -f compact

Terraform Configuration

module "eks_common_01" {
  source  = "terraform-aws-modules/eks/aws"
  version = "~> 19.15"

  cluster_name                    = "${var.prefix}-${var.environment_name}-${var.aws_region}-common-01-eks"
  iam_role_name                   = "${var.environment_name}-common-01"
  cluster_version                 = "1.26"
  cluster_endpoint_private_access = true
  cluster_endpoint_public_access  = true

  cluster_addons = {
    coredns = {
      resolve_conflicts = "OVERWRITE"
    }
    kube-proxy = {
      resolve_conflicts = "OVERWRITE"
    }
    vpc-cni = {
      resolve_conflicts = "OVERWRITE"
    }
  }

  create_kms_key                = true
  kms_key_administrators        = data.aws_iam_roles.admin_roles.arns
  kms_key_enable_default_policy = true

  cloudwatch_log_group_retention_in_days = var.cloudwatch_log_retention_days

  cluster_encryption_config = {
    resources = ["secrets"]
  }

  vpc_id     = module.vpc.vpc_id
  subnet_ids = module.vpc.private_subnets

  eks_managed_node_group_defaults = {
    ami_type       = "AL2_x86_64"
    disk_size      = 50
    instance_types = var.eks_common_01_config.instance_types
  }

  # Create nodegroup for each az
  eks_managed_node_groups = {
    for index, subnet_id in module.vpc.private_subnets :
    "${var.environment_name}-common-01-node-${index}" => {
      min_size     = var.eks_common_01_config.worker_min_size_per_az
      max_size     = var.eks_common_01_config.worker_max_size_per_az
      desired_size = var.eks_common_01_config.worker_min_size_per_az

      instance_types = var.eks_common_01_config.instance_types
      capacity_type  = var.eks_common_01_config.capacity_type
      tags           = var.tags
      subnet_ids     = [subnet_id]
    }
  }

  manage_aws_auth_configmap = false

  tags = var.tags
}

TFLint Configuration

config {
    module = true
    force = false
    disabled_by_default = false
}

plugin "terraform" {
    enabled = true
    preset = "all"
    version = "0.4.0"
    source = "github.com/terraform-linters/tflint-ruleset-terraform"
}

plugin "aws" {
    enabled = true
    version = "0.26.0"
    source = "github.com/terraform-linters/tflint-ruleset-aws"
}

Output

Panic: cannot refine an unknown value of an unknown type
 -> 0: main.main.func1: /main.go(25)
 -> 1: runtime.gopanic: /panic.go(884)
 -> 2: github.com/zclconf/go-cty/cty.Value.Refine: /unknown_refinement.go(47)
 -> 3: github.com/zclconf/go-cty/cty.Value.RefineNotNull: /unknown_refinement.go(123)
 -> 4: github.com/hashicorp/hcl/v2/ext/typeexpr.(*Defaults).apply: /defaults.go(99)
 -> 5: github.com/hashicorp/hcl/v2/ext/typeexpr.(*Defaults).Apply: /defaults.go(45)
 -> 6: github.com/terraform-linters/tflint/terraform.(*evaluationData).GetInputVariable: /evaluator.go(204)
 -> 7: github.com/terraform-linters/tflint/terraform/lang.(*Scope).evalContext: /eval.go(141)
 -> 8: github.com/terraform-linters/tflint/terraform/lang.(*Scope).EvalContext: /eval.go(81)
 -> 9: github.com/terraform-linters/tflint/terraform/lang.(*Scope).ExpandBlock: /eval.go(25)
 -> 10: github.com/terraform-linters/tflint/terraform.(*Evaluator).ExpandBlock: /evaluator.go(101)
 -> 11: github.com/terraform-linters/tflint/terraform.(*Module).PartialContent: /module.go(132)
 -> 12: github.com/terraform-linters/tflint/tflint.NewModuleRunners: /runner.go(110)
 -> 13: github.com/terraform-linters/tflint/tflint.NewModuleRunners: /runner.go(163)
 -> 14: github.com/terraform-linters/tflint/cmd.(*CLI).setupRunners: /inspect.go(251)
 -> 15: github.com/terraform-linters/tflint/cmd.(*CLI).inspectModule: /inspect.go(127)
 -> 16: github.com/terraform-linters/tflint/cmd.(*CLI).inspect.func1: /inspect.go(54)
 -> 17: github.com/terraform-linters/tflint/cmd.(*CLI).withinChangedDir: /cli.go(190)
 -> 18: github.com/terraform-linters/tflint/cmd.(*CLI).inspect: /inspect.go(35)
 -> 19: github.com/terraform-linters/tflint/cmd.(*CLI).Run: /cli.go(106)
 -> 20: main.main: /main.go(38)
 -> 21: runtime.main: /proc.go(250)
 -> 22: runtime.goexit: /asm_amd64.s(1598)

TFLint crashed... :(
Please attach an output log, describe the situation and version that occurred and post an issue to https://github.com/terraform-linters/tflint/issues
Error: Process completed with exit code 1.

TFLint Version

0.47.0

Terraform Version

1.5.2

Operating System

ahmad-hamade commented 1 year ago

Please note, the issue is reported only when I use a custom terraform module that has the following values:

  external_dns = {
    enabled          = true
    domain_names     = keys(module.base_dns_zone.route53_zone_name)
    domain_name_arns = values(module.base_dns_zone.route53_zone_zone_arn)  # <---- this line is what causing the problem
  }

If I omit the value for domain_name_arns property then tflint works just fine.

Below is the external_dns variable definition:

variable "external_dns" {
  type = object({
    enabled          = bool
    domain_names     = list(string)
    domain_name_arns = optional(list(string), [])
    helm_version     = optional(string, "1.13.0")
  })
  description = "External DNS configuration"
  default     = null
}
wata727 commented 1 year ago

Thank you for reporting this. This seems like a bug.

In TFLint an expression like module.base_dns_zone.route53_zone_zone_arn always resolves to an unknown value of an unknown type. https://github.com/terraform-linters/tflint/blob/dcc49cefef705925dbf7003d41889059421277e8/terraform/lang/eval.go#L189

Next, HCL v2.17, which is used in TFLint v0.47, introduces the concept of refinements. This seems to apply implicit refinements when default values such as optional(list(string), []) are applied.

Unfortunately refinements for unknown values of unknown types don't seem to be supported. https://github.com/zclconf/go-cty/blob/v1.13.3/cty/unknown_refinement.go#L46-L47

I'm not sure how to fix this, but it might be a good idea to fix the HCL to not apply the refinement in case of unknown values of unknown types.

The current workaround is to downgrade to TFLint v0.46.1.

wata727 commented 1 year ago

The upstream bug is fixed in https://github.com/hashicorp/hcl/pull/625 This issue is expected to be resolved by updating to the latest HCL version (unreleased).

ahmad-hamade commented 1 year ago

Thank you @wata727 for the fix. I can confirm the issue is resolved in tflint v0.48.0.