appvia / terranetes-controller

The terraform controller manages the life cycles of a terraform resource, allowing developers to self-serve dependencies in a controlled manner.
https://terranetes.appvia.io
GNU General Public License v2.0
152 stars 12 forks source link

AWS Provider - default tags #1483

Closed taktakpeops closed 3 hours ago

taktakpeops commented 1 month ago

Describe the bug

Hello,

When using the AWS provider, the configuration property doesn't allow setting up a map as value for defining the default_tags.tags.

To Reproduce

Steps to reproduce the behavior:

  1. Apply the following provider definition:
    apiVersion: terraform.appvia.io/v1alpha1
    kind: Provider
    metadata:
    name: aws
    spec:
    configuration:
    assume_role:
      role_arn: "arn:aws:iam::${some_account_id}:role/${some_role}"
    default_tags:
      tags:
        Environment: "dev"
        Name: "${some_name}"
        Region: "${some_region}"
        CostCenter: "${some_cost_center}"
        Terraform: true
  2. Deploy a CloudResource using the provider above, here is the provider.tf produced with the controller inside of the secret with all the config:

    
    provider "aws" {
    
    assume_role {
    role_arn = "arn:aws:iam::${some_account_id}:role/${some_role}"
    }
    
    default_tags {
    tags {
      CostCenter  = "${some_cost_center}"
      Environment = "dev"
      Name        = "${some_name}"
      Region      = "${some_region}"
      Terraform   = true
    }
    }

}

3. When the plan runs, it generates the following error:

Error: Unsupported block type

on provider.tf line 8, in provider "aws": 8: tags {

Blocks of type "tags" are not expected here. Did you mean to define argument "tags"? If so, use the equals sign to assign it a value.


**Expected behavior**

When the parsing happens, `default_tags.tags` should be seen an argument, rather than a block. I think the logic for dealing with it  should be implemented in here: https://github.com/appvia/terranetes-controller/blob/master/pkg/utils/terraform/utils.go#L136

I would expect such output for the `provider.tf`:
```yaml
provider "aws" {

  assume_role {
    role_arn = "arn:aws:iam::${some_account_id}:role/${some_role}"
  }

  default_tags {
    tags = {
      CostCenter  = "${some_cost_center}"
      Environment = "dev"
      Name        = "${some_name}"
      Region      = "${some_region}"
      Terraform   = true
    }
  }

}
gambol99 commented 1 week ago

hi @taktakpeops … thanks for raising the issue. That’s gonna be an interesting one to fix, as it’s related to the complexity of HCL, unlike JSON, having an actual schema - i.e. informing it that tags should be argument not a map https://github.com/hashicorp/terraform-provider-aws/blob/main/internal/provider/provider.go#L66-L76 ..

taktakpeops commented 1 week ago

Hello @gambol99 , thanks for your answer.

After looking around, I was wondering if the parser used in the controller to convert YAML to HCL couldn't be changed to handle this use case of map as a resource. If so, what would be the process to change it?

gambol99 commented 1 week ago

If so, what would be the process to change it?

We could definitely do a one-off i.e if default_tags or x - define as an argument rather than a hcl map, but I was hoping to fix it for all providers in one go. One “potential” solution mentioned was passing the provider.tf as json rather than trying to convert it ourselves i.e. provider.json.tf - As the provider binary (whom knows the schema) will be able to handle the conversion for us. I just need to validate the fix works

gambol99 commented 1 week ago

This appears to work, having tested it locally … I used the provider.tf.json

{
  "provider": {
    "aws": {
      "region": "eu-west-2",
      "profile": "appvia-io-network",
      "default_tags": {
        "tags": {
          "Environment": "dev",
          "Name": "test",
          "Region": "region",
          "CostCenter": "cost_center",
          "Terraform": true
        }
      }
    }
  }
}

And copied the main.tf from https://github.com/hashicorp/learn-terraform-aws-default-tags/blob/main/main.tf … Out plan show

  # aws_launch_template.example will be created
  + resource "aws_launch_template" "example" {
      + arn             = (known after apply)
      + default_version = (known after apply)
      + id              = (known after apply)
      + image_id        = "ami-0f83016656f175553"
      + instance_type   = "t2.micro"
      + latest_version  = (known after apply)
      + name            = (known after apply)
      + name_prefix     = "learn-terraform-aws-default-tags-"
      + tags_all        = {
          + "CostCenter"  = "cost_center"
          + "Environment" = "dev"
          + "Name"        = "test"
          + "Region"      = "region"
          + "Terraform"   = "true"
        }

      + metadata_options (known after apply)
    }

So we could just update the controller to render the provider in pure json and it should work for all providers.

gambol99 commented 6 days ago

Hi @taktakpeops … this has been merged into the develop branch and will be available in the next release - If you have time, we’d definitely appreciate a validation of the fix :-) .. Develop branch pushes ghcr.io/appvia/terranetes-controller:develop on every commit, so if you change the values in the helm chart or —set controller.images.controller ghcr.io/appvia/terranetes-controller:develop and so on … you’ll get the latest

gambol99 commented 3 hours ago

Closing as fixed for now - as the feature was shipped in the v0.4.14 release