Why not use protobuf, or similar interface definition languages? Then let users specify the config in whatever language they are comfortable with.
Why not use protobuf, or similar interface definition languages? Then let users specify the config in whatever language they are comfortable with.
I see some value instead. Lately I've been working on Terraform code to bring up a whole platform in half a day (aws sub-account, eks cluster, a managed nodegroup for karpenter, karpenter deployment, ingress controllers, LGTM stack, public/private dns zones, cert-manager and a lot more) and I did everything in Terraform, including Kubernetes resources.
What I appreciated about creating Kubernetes resources (and helm deployments) in HCL is that it's typed and has a schema, so any ide capable of talking to an LSP (language server protocol - I'm using GNU Emacs with terraform-ls) can provide meaningful auto-completion as well proper syntax checking (I don't need to apply something to see it fail, emacs (via the language server) can already tell me what I'm writing is wrong).
I really don't miss having to switch between my ide and the Kubernetes API reference to make sure I'm filling each field correctly.
Not really. There are optional ways to add schema but nothing that's established enough to rely on.
Edit: apparently it just has popular ones built in: https://raw.githubusercontent.com/SchemaStore/schemastore/ma...
As much as Helm is prone to some type of errors, it will validate the schema before doing an install or upgrade so `version: 1.30` won't apply but `version: "1.30"` will.
In the age of AI arguments about a configuration language are moot. Nobody is going to hand craft those deployment configs anymore. The AIs can generate whatever weird syntax the underlying K8s machinery needs and do it more reliably than any human. If not today then probably in 3 months or something.
If you want to dream big for K8s 2.0 let AI parse human intent to generate the deployments and the cluster admin. Call it vibe-config or something. Describe what you want in plain language. A good model will think about the edge cases and ask you some questions to clarify, then generate a config for your review. Or apply it automatically if you're an edgelord ops operator.
Let's face it, modern code generation is already heading mostly in that direction. You're interacting with an AI to create whatever application you have in your imagination. You still have to guide it to not make stupid choices, but you're not going to hand craft every function. Tell the AI "I want 4 pods with anti-affinity, rolling deployment, connected to the existing Postgres pod and autoscaling based on CPU usage. Think hard about any edge cases I missed." and get on with your life. That's where we're heading.
I'm emotionally prepared for the roasting this comment will elicit so go for it. I genuinely want to hear pro and con arguments on this.
The idea that someone who works with JavaScript all day might find HCL confusing seems hard to imagine to me.
To be clear, I am talking about the syntax and data types in HCL, not necessarily the way Terraform processes it, which I admit can be confusing/frustrating. But Kubernetes wouldn’t have those pitfalls.
outer {
example {
foo = "bar"
}
example {
foo = "baz"
}
}
it reminds me of the insanity of toml [lol]
[[whut]]
foo = "bar"
[[whut]]
foo = "baz"
only at least with toml I can $(python3.13 -c 'import tomllib, sys; print(tomllib.loads(sys.stdin.read()))') to find out, but with hcl too badPeople complain about YAML then go and use TOML.
server {
location / {
return 200 "OK";
}
location /error {
return 404 "Error";
}
}
server {
location / {
return 200 "OK";
}
location /error {
return 404 "Error";
}
}
But because we know that nginx is a configuration language for a server where we define the behavior we want through creating a set of resources (servers in this example, but "example"s or "whut"s in yours) {
"servers": [
{
"locations": [
{
"key": "/",
"return": {
"status": 200,
"content": "OK"
}
},
{
"key": "/error",
"return": {
"status": 404,
"content": "error"
}
}
]
},
{
"locations": [
{
"key": "/",
"return": {
"status": 200,
"content": "OK"
}
},
{
"key": "/error",
"return": {
"status": 404,
"content": "error"
}
}
]
}
]
}I did see the "inspired by nginx" on hcl's readme, but that must be why you and Mitchell like hcl so much because I loathe nginx's config with all my heart
At the end of the day HCL isn't that much more complex than something like yaml. Saying "You don't want your developers learning yaml" is like saying "You don't want your developers learning Yaml. They send an email to the SRE guys, and the SRE guys are the Yaml experts"
$ hcl2json <<FOO | jq -r '"has \(length) keys"'
outer {
example {
foo = "bar"
}
example {
foo = "baz"
}
}
FOO
has 1 keysTerraform converts HCL to JSON in a different way that makes a lot more sense, and hcldec provided by Hashicorp lets you define your own specification for how you want to use it.
I would like to point out that perfect compatibility with JSON is not a goal nor a requirement of a decent configuration language.
As for why I linked to "some random guy," that's because the Hashicorp people in their infinite wisdom didn't ship any rendering binary so some kind soul had to glue one to the official sdk https://github.com/tmccombs/hcl2json/blob/v0.6.7/go.mod#L8
I hear you about JSON might not be a goal, but I can tell you that Terraform accepts .json files just as much as it accepts .hcl files so that sane people can generate them, because sane people cannot generate HCL https://developer.hashicorp.com/terraform/language/syntax/js...
https://www.npmjs.com/package/@cdktf/hcl2json
https://github.com/hashicorp/terraform-cdk/tree/main/package...
I use the package to implement module dependency graph tracking across our terraform monorepo for things like code reviews and CI triggering.
I've found HCL perfectly adequate for vanilla Terraform, furthermore I've found no real reason to leverage CDK.
To be clear I am not saying HCL is amazing, merely that it's adequate and better than YAML, and that I'm not sure how it could be considered confusing. I personally think HashiCorp has jumped the shark since the IBM acquisition and that CDK will never gain mass adoption in a significant way.
Absolutely loathsome syntax IMO
variable "my_list" { default = ["a", "b"] }
resource whatever something {
for_each = var.my_list
}
The given "for_each" argument value is unsuitable: the "for_each" argument must be a map, or set of strings, and you have provided a value of type tuple.Ansible's with_items: and loop: do the exact same thing with YAML.
HCL's looping and conditionals are a mess but they're wonderful in comparison to its facilities for defining and calling functions.
Good functional languages like Clojure make something like this awkward and painful to do, because it doesn't really make sense in a functional context.
It is claiming the provided thing is not a set of strings it's a tuple
The fix is
for_each = toset(var.my_list)
but who in their right mind would say "oh, I see you have a list of things, but I only accept unordered things" zipmap(range(length(var.my_list)), var.my_list)
where you get {0 => item, 1=>item} and your resources will be named .0, .1, .2. I get the annoyance about the type naming but in HCL lists and tuples are the same thing.Ok, so which one of ["a", "b"] in my example isn't unique?
And I definitely, unquestionably, never want resources named foo.0 and foo.1 when the input was foo.alpha and foo.beta
If you don't want .0, .1 then you agree with Terraform's design because that's the only way you could for_each over an arbitrary list that might contain duplicate values. Terraform making you turn your lists into sets gets you what you want.
This sounds a lot more like “I resented learning something new” than anything about HCL, or possibly confusing learning HCL simultaneously with something complex as a problem with the config language rather than the problem domain being configured.
The ideal solution would be to have an abstraction that is easy to use and does not require learning a whole new concept (especially an ugly one as hcl). Also learning hcl is simply just the tip of the iceberg, with sinking into the dependencies between components and outputs read from a bunch of workspaces etc. It is simply wasted time to have the devs keeping up with all the terraform heap that SREs manage and keep evolving under the hood. The same dev time better spent creating features.
If your argument is instead that they shouldn’t learn infrastructure, then the point is moot because that applies equally to every choice (knowing how to indent YAML doesn’t mean they know what to write). That’s also wrong as an absolute position but for different reasons.
I have no objections to protobufs, but I think that once you’re past a basic level of improvements over YAML (real typing, no magic, good validation and non-corrupting formatters) this matters less than managing the domain complexity. YAML is a bad choice for anything but text documents read by humans because it requires you to know how its magic works to avoid correct inputs producing unexpected outputs (Norway, string/float confusion, punctuation in string values, etc.) and every tool has to invent conventions for templating, flow control, etc. I think HCL is better across the board but am not dogmatic about it - I just want to avoid spending more time out of people’s lives where they realize that they just spent two hours chasing an extra space or not quoting the one value in a list which absolutely must be quoted to avoid misinterpretation.
Given that its main purpose is to describe objects of various types, its facilities for describing types are pretty weak and its facilities for describing data are oddly inconsistent. Its features for loops and conditionals are weak and ad-hoc compared with a regular programming language. Identifier scope / imports are a disaster and defining a function is woeful.
Some of this is influenced by Terraform's problem domain but most of it isn't required by that (if it was required, people wouldn't have such an easy time doing their Terraform in python/go/rust).
Despite this, Terraform is overall good. But there's a reason there's a small industry of alternatives to HCL.
The actual format is binary and I'm not expecting people to pass around binary blobs that describe their deployment configuration.
to serialize it, you're writing code in some language... then what? you just want deployment as code? because that seems like a separate paradigm.
I don't think I can take a JSON or YAML document and export it to an HCL that contains logic like that, but at the same time we shouldn't be doing that either IMHO. I very much do not want my configuration files to have side effects or behave differently based on the environment. "Where did this random string come from?" "It was created dynamically by the config file because this environment variable wasn't set" sounds like a nightmare to debug.
YAML is bad for a great many reasons and I agree with the author that we should get rid of it, but HCL is bad for this use case for the same reasons - it does too much. Unfortunately, I'm not sure if there's another configuration language that makes real honest sense in this use case that isn't full of nightmarish cruft also.
What would you expect to be hearing different if HCL really was just an objectively bad language design?
Could you elaborate on your setup? Do you just convert them to JSON/YAML before passing them to kube/helm or…? (Are you able to type-constrain your values.dhall?)