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

feat: Edit object type #28

Open
ryanmills opened this issue May 20, 2021 · 6 comments
Open

feat: Edit object type #28

ryanmills opened this issue May 20, 2021 · 6 comments

Comments

@ryanmills
Copy link

ryanmills commented May 20, 2021

I have the following HCL file:

locals {
  workload_1 = {
    vpc0 = {
      cidr_block     = "192.168.1.0/24"
      extended_cidrs = {}
      name_prefix    = "workload"
    }
  }
}

And receive the following outputs:

$ cat test.hcl | hcledit block get locals
locals {
  workload_1 = {
    vpc0 = {
      cidr_block     = "192.168.1.0/24"
      extended_cidrs = {}
      name_prefix    = "workload"
    }
  }
}
$ cat test.hcl | hcledit block get locals.workload_1
$ cat test.hcl | hcledit block get locals.workload_1.vpc0
$ 

No results are returned for locals.workload_1. Not sure why. Thanks!

@ryanmills ryanmills changed the title Nested Nested objects May 20, 2021
@minamijoyo
Copy link
Owner

The locals.workload_1 is an attribute, not a block. We can get it with hcledit attribute get locals.workload_1

$ cat test.hcl | hcledit attribute get locals.workload_1
{
    vpc0 = {
      cidr_block     = "192.168.1.0/24"
      extended_cidrs = {}
      name_prefix    = "workload"
    }
  }

However, The type of workload_1 is an object and the vpc0 is a key of the object, so it would be great if we can get it with hcledit attribute get 'locals.workload_1["vpc0"]', but it's not supported yet.

@ryanmills
Copy link
Author

ryanmills commented May 20, 2021

Thanks. For completeness, my use case is:

locals {
  prod_1 = {
    vpc0 = {
      cidr_block     = "1.2.3.4/19"
      extended_cidrs = {}
      name_prefix    = "workload"
      tgw_subnets = {
        a0 = {
          cidr_block        = "1.2.3.4/28"
          name_prefix       = "tgw"
        }
        b0 = {
          cidr_block        = "1.2.3.4/28"
          name_prefix       = "tgw"
        }
        c0 = {
          cidr_block        = "1.2.3.4/28"
          name_prefix       = "tgw"
        }
      }
      ram_subnets = {
        a0 = {
          cidr_block        = "1.2.3.4/28"
          name_prefix       = "ram"
        }
      }
      private_subnets = {
        endpoints_a0 = {
          cidr_block        = "1.2.3.4/26"
          name_prefix       = "endpoints"
        }
        endpoints_b0 = {
          cidr_block        = "1.2.3.4/26"
          name_prefix       = "endpoints"
        }
        endpoints_c0 = {
          cidr_block        = "1.2.3.4/26"
          name_prefix       = "endpoints"
        }
      }
      shared_subnets = {
        data_a0 = {
          cidr_block        = "1.2.3.4/26"
          name_prefix       = "shared"
          app_name          = "shared"
        }
        data_b0 = {
          cidr_block        = "1.2.3.4/26"
          name_prefix       = "shared"
          app_name          = "shared"
        }
        data_c0 = {
          cidr_block        = "1.2.3.4/26"
          name_prefix       = "shared"
          app_name          = "shared"
        }
        compute_a0 = {
          cidr_block        = "1.2.3.4/26"
          name_prefix       = "shared"
          app_name          = "shared"
        }
        compute_b0 = {
          cidr_block        = "1.2.3.4/26"
          name_prefix       = "shared"
          app_name          = "shared"
        }
        compute_c0 = {
          cidr_block        = "1.2.3.4/26"
          name_prefix       = "shared"
          app_name          = "shared"
        }
      }
    }
  }
}

Trying to extract (and set) the value of locals.prod_1.vpc0.ram_subnets.a0.cidr_block

@minamijoyo
Copy link
Owner

minamijoyo commented May 21, 2021

The hcledit depends on the hclwrite parser in the hcl library which is used by the terraform fmt command and is specialized for the token-based edit to preserve comments. However, at time of this writing, it has very limited capabilities and doesn't have enough AST representations for such a complex object type. So I think it's not possible to support it without extending the hclwrite.

If your concern is only query (not edit), the best way to do this for now is convert it to json with hcl2json and query the json string with jq.

https://github.com/tmccombs/hcl2json

$ cat test.hcl | hcl2json | jq '.locals[0].workload_1.vpc0'
{
  "cidr_block": "192.168.1.0/24",
  "extended_cidrs": {},
  "name_prefix": "workload"
}

@buggtb
Copy link

buggtb commented May 3, 2022

So if I read this correctly, we couldn't add, for example, a tags block into an AWS resource:

  tags = {
    hello = "world"
  }

although actually:

➜  ~ cat ./elastic.tf | ./hcledit attribute get resource.aws_elasticsearch_domain.sample.tags
{
    hello = "world"
    someothertag = "yes"
  }

seems to return the string. And I can set it with

➜  ~ cat ./elastic.tf | ./hcledit attribute set resource.aws_elasticsearch_domain.sample.tags '{ hello="world", somenewtag = "no"}'

so as long as you don't mind replacing the whole block you can do so?

@minamijoyo
Copy link
Owner

Thank you for pointing out it.

The hcledit uses a token based parser and actually doesn't know what type is correct in application schema, so you can set an object literal as a string.

@wondersd
Copy link
Contributor

wondersd commented Aug 27, 2024

One way to work around this for now is to recursively feed attribute blocks back into hcledit as intermediate locals blocks

main.tf

locals {
  map = {
     key = "foo"
  }
}

Normally locals.map is returned as

$ hcledit -f main.tf attribute get locals.map
{
     key = "foo"
  }

Can get the above output to look like a locals block of a new intermediate tf file and to then select the next nested key

$ hcledit -f <(echo "locals $(hcledit -f main.tf attribute get locals.map)") attribute get locals.key
"foo"

This can be implemented recursively to get (and even set) deeply nested attributes of locals, resources, modules, etc

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

No branches or pull requests

4 participants