Closed samgaw closed 3 years ago
There's nothing in HCL about modules, so I think you are correct that it's a Terraform specific behaviour.
It does however touch on something I'd like to include which is custom evaluation of the AST. Right now there isn't a way to hook into the evaluation, since it runs directly after the parse in decode/2
So define a behaviour and accept other evaluators modules as options to decode. Unfortunately the functions that actually does the evaluation are private in HXL.Eval
, so you can't do anything about it right now. But I'll move it to a HXL.Eval.Base
so in your case you'd implement eval/2
for Blocks matching modules something like:
Given the following ast:
hcl = """
module "foo" {
source = "./mod"
}
"""
HXL.decode_as_ast(hcl)
{:ok,
%HXL.Ast.Body{
statements: [
%HXL.Ast.Block{
body: %HXL.Ast.Body{
statements: [
%HXL.Ast.Attr{
expr: %HXL.Ast.TemplateExpr{delimiter: nil, lines: ["./mod"]},
name: "source"
}
]
},
labels: ["foo"],
type: "module"
}
]
}}
The evaluator have to handle the Block
and Body
and the Attr
so it'd look something like:
defmodule Terraform.Eval do
alias HXL.Ast.{Block, Body, Attr}
@behaviour HXL.Eval
@impl true
@spec eval(HXL.Ast.t(), HXL.Eval.t()) :: {term(), HXL.Eval.t()}
def eval(%Block{body: body, type: "module", labels: labels}, ctx) do
# Handle module body and return a value
# or put something into the context
_value = handle_module_body(body, ctx)
{:ignore, ctx}
end
def eval(ast, ctx) do
HXL.Eval.Base.eval(ast, ctx)
end
def handle_module_body(%Body{statements: [%Attr{name: "source", expr: expr}]}, ctx) do
# Expr is template expr containing the source path
# Do something and return a value
end
Handle the parts that you require and delegate to the base eval mod. I'll create an issue and track it :)
What do you think?
That would be perfect! It solves my immediate need to handle Terraform modules. But also gives me an option of expanding it to handle Sentinel configs as well, which are another flavour of HCL.
@samgaw I just released v0.2.0 with support for custom evaluators. I added an example with Terraform modules evaluator
Let me know how it works out for you 😄 !
I did a little dance when I read this 😂
I’ll spend some time building with this at the end of week and let you know. Awesome work!! I’m really excited!
Remembering my own naive attempt at this a few years ago using
leex
&yaac
I very much appreciate your efforts!I've had a hard time try to find any reference to this in the HCL spec so I'm starting to think the concept of modules are a Terraform specific behaviour?
A basic example would be:
The workaround is to wrap the path reference in a
file()
function call. Although that obviously requires a bit of cleanup afterwards :)Are modules within the eventual scope of the library? Or would you have any pointers on working with includes as-is?
Thanks!