HCL
HCL, the language of Terraform, Nomad and Packer files: read as values, expressions worked out from your variables, and written back.
Version 1.0.0 · 4 functions · 1 crate
Functions
What use hcl.qwer gives a program, with the types Quillo sees. To take only some, or under other names: use hcl_parse, hcl_read_file from hcl (Quillo 0.6).
hcl_parse(text: str) → anyor an errorHCL text as a map: attributes as keys, blocks as nested maps by their labels (resource "aws_instance" "web" { ... } is resource.aws_instance.web), a block type used several times as a list. Expressions that need evaluating (var.region, "${local.name}-web", function calls) stay as their text in ${...}.
hcl_read_file(path: str) → anyor an errorAn HCL file read as hcl_parse reads text.
hcl_eval(text: str, variables: any, locals: any) → anyor an errorHCL text with its expressions worked out where they can be: var.<name> from variables (a map), local.<name> from locals, arithmetic, conditions, for expressions and template strings. What cannot be (a name not given, a type such as string, Terraform's functions) stays as its text in ${...}, as hcl_parse leaves it.
hcl_write(value: any) → stror an errorA map written as HCL text: keys holding text, numbers, booleans and lists as attributes (name = "web"), maps as maps.
Get it
$ quillo install hcl # hcl.qwer into this folder$ quillo install hcl --example # and its example, hcl.qweOr with curl:
$ curl -O https://quillolang.org/plugins/files/hcl.qwer$ curl -O https://quillolang.org/plugins/files/hcl.qwe$ curl -O https://quillolang.org/plugins/files/hcl_sample.tfThen, in your program, all of it or only what you call:
use hcl.qweruse hcl_parse, hcl_read_file from hcl // Quillo 0.6: only theseIt uses this crate, which cargo fetches the first time the plugin is built:
hcl-rs = "0.18"Example
// What a Terraform file deploys, read for an internal dashboard.//// quillo run hcl.qwe then open http://localhost:8080/resourcesuse "hcl.qwer"route GET /resources { let tf = hcl_read_file("hcl_sample.tf")? { region_default: tf.variable.region.default, instance_type: tf.resource.aws_instance.web.instance_type, kinds: keys(tf.resource), }}route GET /evaluated { let tf = hcl_eval(read_file("hcl_sample.tf")?, { region: "eu-central-1", size: "big" }, { name: "quillo-shop" })? { region: tf.provider.aws.region, type: tf.resource.aws_instance.web.instance_type, name: tf.resource.aws_instance.web.tags.Name, count: tf.resource.aws_instance.web.count }}route GET /write = respond(200, hcl_write({ job: { web: { datacenters: ["ams1"], count: 3, image: "quillo/shop:1.4" } } })?, { "content-type": "text/plain" })$ quillo run hcl.qwe$ curl 'localhost:8080/resources'$ curl 'localhost:8080/evaluated'Source
//! HCL, the language of Terraform, Nomad, Packer and Vault files: read as values (with `var.x` left as `${var.x}`, or worked out from your variables), and values written back as HCL.//! version: 1.0.0//!//! [dependencies]//! hcl-rs = "0.18"use serde_json::Value;/// Files up to 10 MB are read.const MAX: usize = 10 * 1024 * 1024;fn size(text: &str) -> Result<(), String> { if text.len() > MAX { return Err("HCL files up to 10 MB".into()); } if too_deep(text, 128) { return Err("nested more than 128 deep".into()); } Ok(())}/// The deepest nesting of brackets outside strings: the parser recurses, and text nested thousands deep would overflow/// the server's stack, so it is refused first.fn too_deep(text: &str, max: usize) -> bool { let (mut depth, mut quote, mut esc) = (0usize, None::<char>, false); for c in text.chars() { if let Some(q) = quote { if esc { esc = false } else if c == '\\' { esc = true } else if c == q { quote = None } continue; } match c { '"' => quote = Some(c), '[' | '{' | '(' => { depth += 1; if depth > max { return true; } } ']' | '}' | ')' => depth = depth.saturating_sub(1), _ => {} } } false}/// HCL text as a map: attributes as keys, blocks as nested maps by their labels (`resource "aws_instance" "web" { ... }` is/// `resource.aws_instance.web`), a block type used several times as a list. Expressions that need evaluating (`var.region`,/// `"${local.name}-web"`, function calls) stay as their text in `${...}`.pub fn hcl_parse(text: &str) -> Result<Value, String> { size(text)?; hcl::from_str::<Value>(text).map_err(|e| format!("not HCL: {}", e))}/// An HCL file read as hcl_parse reads text.pub fn hcl_read_file(path: &str) -> Result<Value, String> { let t = std::fs::read_to_string(path).map_err(|e| format!("{}: {}", path, e))?; hcl_parse(&t)}/// HCL text with its expressions worked out where they can be: `var.<name>` from `variables` (a map), `local.<name>` from/// `locals`, arithmetic, conditions, `for` expressions and template strings. What cannot be (a name not given, a type such as/// `string`, Terraform's functions) stays as its text in `${...}`, as hcl_parse leaves it.pub fn hcl_eval(text: &str, variables: serde_json::Value, locals: serde_json::Value) -> Result<Value, String> { use hcl::eval::Evaluate; size(text)?; let mut ctx = hcl::eval::Context::new(); ctx.declare_var("var", hcl::to_value(&variables).map_err(|e| e.to_string())?); ctx.declare_var("local", hcl::to_value(&locals).map_err(|e| e.to_string())?); let mut body = hcl::parse(text).map_err(|e| format!("not HCL: {}", e))?; // Every expression that can be worked out is; the errors of the others are left aside. let _ = body.evaluate_in_place(&ctx); hcl::from_body::<Value>(body).map_err(|e| e.to_string())}/// A map written as HCL text: keys holding text, numbers, booleans and lists as attributes (`name = "web"`), maps as maps.pub fn hcl_write(value: serde_json::Value) -> Result<String, String> { if !value.is_object() { return Err("HCL is written from a map".into()); } hcl::to_string(&hcl::to_value(&value).map_err(|e| e.to_string())?).map_err(|e| e.to_string())}Related
dotenv.qwer · 1.0.0.env files read with their quoting rules and ${VAR} expansion, linted and compared with .env.example, and written or changed one key at a time with comments kept.8 views · 9 downloadsINI ini.qwer · 1.0.0INI files read and written, sections and keys: php.ini, setup.cfg, .gitconfig and the settings of older software.8 views · 7 downloadsJava properties java_properties.qwer · 1.0.0Java .properties files read and written: Spring settings and translation bundles, with continued lines and \u escapes.6 views · 8 downloadsJSON5 json5.qwer · 1.0.0JSON5 and JSON with comments read as values: tsconfig.json and editor settings, with comments, trailing commas and unquoted keys.7 views · 8 downloadsProperty lists plist.qwer · 1.0.0Apple property lists, XML and binary: Info.plist, profiles and preferences read as values, and values written back as either.6 views · 9 downloadsAvro avro.qwer · 1.0.0Apache Avro data files: rows written with a schema, as Kafka, Hadoop and BigQuery use, and read back with the schema they carry.9 views · 6 downloadsThread 0 posts
On HCL: questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.