Closed tobimai closed 1 year ago
Hi there!
Reading your description I'm still not entirely sure what your use case is.
Let's take a simple example as a starting point. Given the following HCL:
resource "aws_sqs_queue" "queue" {
name = "my-queue"
redrive_policy = jsonencode({
deadLetterTargetArn = aws_sqs_queue.dead_letter_queue.arn
maxReceiveCount = 5
})
}
jsonencode
function so that redrive_policy
becomes a JSON encoded string?jsonencode
, like in the block above?The first two cases are supported by hcl-rs
and I can provide examples for them.
Can you further elaborate? Maybe an example of what you're trying to achieve in pseudo code could help.
Sorry I was not clear.
It's the second one, I want to output data I have in a struct in rust as HCL.
Example:
I have this:
struct Demo {
foo: String
}
Demo{foo: "bar".into()}
And want to get this:
resource "demo" "demo" {
model = jsonencode({
foo = "bar"
})
}
This is certainly possible. Here's one way to achieve this (I added comments to the most relevant bits):
use hcl::expr::FuncCall;
use hcl::structure::{Attribute, Block, Body};
#[derive(serde::Serialize)]
struct Demo {
foo: String,
}
let demo = Demo { foo: "bar".into() };
// Convert the custom struct to an `hcl::expr::Expression`.
let expr = hcl::to_expression(&demo).unwrap();
let body = Body::builder()
.add_block(
Block::builder("resource")
.add_labels(["demo", "demo"])
.add_attribute(Attribute::new(
"model",
// Construct the `jsonencode` function call.
FuncCall::builder("jsonencode").arg(expr).build(),
))
.build(),
)
.build();
assert_eq!(
hcl::to_string(&body).unwrap(),
indoc! {r#"
resource "demo" "demo" {
model = jsonencode({ "foo" = "bar" })
}
"#}
);
Please note that the final formatting is a little bit different than in your example:
foo
key is quoted. This behaviour can be configured via a custom formatter instance to make ident-like keys render unqoted:use hcl::format::{Format, Formatter};
let mut fmt = Formatter::builder().prefer_ident_keys(true).build_vec();
let formatted = body.format_string(&mut fmt).unwrap();
assert_eq!(
formatted,
indoc! {r#"
resource "demo" "demo" {
model = jsonencode({ foo = "bar" })
}
"#}
);
I hope this more or less covers your use case. Let me know if something is missing.
Thanks, thats exactly what I needed. (well, multiline would be nicer but doesn't really change anything, the code will be auto-generated and not touched 99% of the time)
One short thing, I noticed that when you have an empty list in a struct you serialze using to_expression it will not generate a comma after it. Is that a know error/Intended? If not I would create a proper bug report once I have time.
Could you provide an example of the actual output and how it should look like in your opinion? In general the formatter avoids to emit commas that are not significant.
I am currently trying to write something which relies on using terraforms jsonencode.
From what I can tell this is currently not supported/possible, is this correct?
So what I was trying to do was basically wrapping a block into a jsonecode block and therefore be able to write everything in rust/hcl-rs without having to resort to raw string inputs in attributes (which also mess up escaping and intendation)