In Defense of YAML
blog.atomist.com
blog.atomist.com
I find myself expressing this same opinion to people on a frequent basis. See ansible for another big example. Ansible has a try/catch equivalent in yaml [0]!
Unfortunately, YAML is more or less a lowest common denominator for these sorts of interactions - being usable from any language is a really big boon. Would love to see the world adopt a trivial lisp or similar for this sort of thing, but that feels a ways off.
Helm 3 introducing lua, for example, is a big step forward. Pretty much exactly what I've been envisioning for making k8s deployments less crummy, so I hope they end up with a good product. [1] Helm 2 is using Go-templated YAML, and it's terribly unergonomic and not particularly maintainable. Until you run templating, it's not even valid yaml, so text editors are terribly useless in aiding you with linting.
[0]: https://docs.ansible.com/ansible/latest/user_guide/playbooks...
It does this by creating something not quite as powerful as a real programming language (sometimes a feature; probably not here though) while still complicated enough to effectively be unreadable to an average Joe.
Imagine being able to go from a foo.app like this:
{application,otpcl,
[{description,"Open Telecom Platform Command Language"},
{vsn,"0.1.0"},
{modules,[otpcl,otpcl_env,otpcl_eval,otpcl_init,otpcl_parse,
otpcl_shell,otpcl_stdlib,otpcl_stdmeta]},
{registered,[]},
{applications,[kernel,stdlib]},
{licenses,["ISC"]},
{links,[{"Bitbucket","https://bitbucket.org/YellowApple/otpcl"},
{"GitHub","https://github.com/YellowApple/otpcl"}]}]}.
to something more like a foo.app.otpcl: application otpcl {
description "Open Telecom Platform Command Language"
vsn 0.1.0
modules otpcl otpcl_env otpcl_eval otpcl_init otpcl_parse \
otpcl_shell otpcl_stdlib otpcl_stdmeta
registered
applications kernel stdlib
licenses ISC
links {
Bitbucket "https://bitbucket.org/YellowApple/otpcl"
GitHub "https://github.com/YellowApple/otpcl"
}
}
I dunno about you, but I like the latter a lot better :) It ain't a 1:1 representation, but it'd be straightforward to define each of those parameters as commands that emit the corresponding Erlang forms that make up an actual app spec.While OTPCL's by no means ready for primetime yet, I'm hoping it'll eventually be good enough to fill that niche in the Erlang/OTP ecosystem the same way Tcl was meant to fill that niche for software in general.
[1]: https://otpcl.github.io / https://github.com/otpcl/otpcl
Dhall supports functions from URLs and it's good to pin them using SHA hashes of their internal representation.
Both of them are basically BCL/GCL but with some semantic/scoping horrors removed.
Which to me seemed more intuitive.
But I'm also pretty excited about the UI-as-code features happening in Dart: https://medium.com/dartlang/making-dart-a-better-language-fo...
Mostly I prefer YAML w. json-e because it's declarative and expressive enough for those few cases where you needed fancy stuff..
But the new Dart features coming up, makes me think I could write config as code -- we'll see :)
(Disclaimer: I work at Google)
I don't find that Chef cookbooks are all that onerous to debug at all. Cleanly-written Ruby (and you can write Chef cookbooks in very clean Ruby, it really isn't that big of an ask) isn't hard to trace and in the extreme case--and this has happened twice in my career--I just install Pry and drop a breakpoint into the Chef cookbook, then proceed to poke around, isolate the problem, and move on with my day.
This, contrasted with Ansible's flinging around of Jinja templates and trying to turn YAML into a bad programming language, is a relief, and when I was a consultant I charged a premium for Ansible first because it frustrated me but second because it was generally harder for me to find out what was actually going on due to the verbosity, the commonplace copy-pasting, the relatively poor method of inventorying, and the "strap in, it's gonna get bad" anytime somebody decided to break out of the YAML mines and go write their own module.
There remains a very awkward sysadmin/developer divide in the devops world, and I think that criticisms like the one you describe generally tend to hail from the former. As a developer whose output on occasion happens to be configured systems (when it isn't web pages, etc.), I'd rather a predictable programming environment over a "configuration language" every day (and it's one of the reasons I really wish that Noah's attempt to turn cookbooks into gems paid off; having them be a completely separate artifact from a Ruby gem is just silly).
you can, but in reality, this doesn't happen. especially for people who just want config management, and not to learn Ruby, or exactlty the "sysadmin/developer divide" as you've so aptly put it. all I got from Chef was loathing Ruby and all it's magic.
anyhow, the point was to illuminate how/why Ansible came about. i don't really like or use Ansible much anymore.
I get that not everybody is a Ruby person. "Chef but in Python" probably would have done pretty well. But it is genuinely not that difficult and probably more widespread than people give it credit for being.
Bash/Make => ? => Ansible => Chef/Puppet/Salt => CFEngine
There's a big jump in complexity from Bash/Make to Ansible. This is a place where Python or Ruby would make a lot of sense but without all the dsl/yaml/declarative nonsense. A small library of reusable functions would fit in well here, written in a language that isn't fundamentally broken (bash).
https://github.com/lightbend/config
It adds includes/inheritance, substitutions, unit of measure parity , comments , and few other things -- on top of JSON.
does not have if-logic, loops, or arbitrary functions, however.
On plus side, the library is available in a number of languages, easily embeddable. And there is an IntelliJ plugin for it, to color the syntax of the config files.
Personally, I'm not particularly happy with the idea that I would use something inferior (like YAML) because various mainstream languages are bad and don't make more sophisticated languages possible.
On a slight side-note this is something that's been bothering me with markdown and other markup languages.
They're very good for short comments but when you're writing a blog post, or god forbid an article series or a book, sometimes having access to a programming language is fantastic.
It's why I like a markup like Pollen use. Also X-expressions fits very well to model a document.
Oh, this is cool! I've actually been thinking for a while that things like Helm or CloudFormation templates or other infra-as-code things would be better served by something like Starlark, but Lua probably suits as well.
I mean, sure, you can convert one into the other syntax-wise, both form trees, but what do you gain?
It's easy for someone who never {wanted to, learned to} program to accept yet another configuration format (with all options specified up front) and then accidentally learn (bastardized) programming concepts. It'd take much more effort to turn them into a 'real' programmer, learning a language from scratch, practicing that, and only then introducing some tool in the form of a library.
-Define the desired state of your system in a declarative way. This requires a DSL, and some tools such as Ansible and Kubernets use YAML as that DSL.
-The configuration engine (Kubernetes, Ansible, Chef, Salt) will converge the system to the desired state in an idempotent way using the DSL.
-Many systems have mostly the same config and many systems also run in environments that are mostly similar but with some differences. It doesn't follow the DRY principle to create separate but mostly identical desired state configurations for every system/environment, so we need programming primitives and templating tools to accomplish it. It's no less valid than a web app templating HTML for instance.
It's easy to conflate "mixing programming with configuration" with "using programming to solve configuration generation."
Meanwhile, YAML is not a good DSL framework, it's not even a programming language, it's a markup language. Any logic defined in it will be inherently bolted on and likely based on text templating and full of stringly-typed confusion. A classic CM tool that does get this right is Chef, where normal Ruby code is used to build the declarative intended state. You can extremely easily implement any logic you want to create an intended state (even retrieve it from other components) and then emit a desired, declarative resource state (and --why-run will then show what steps will be taken to converge tit). You can do these things right, just don't try to turn a markup language into a turing-complete DSL.
You compare this to templating HTML - but nobody would ever seriously consider declaring such templating logic within HTML itself with some sort of Jinja2 templating engine duct-taped to the side. Instead, we use whatever is in control of serving HTML to render the final markup, with the bulk of the logic implemented in a normal programming language, while a templating engine takes care of rendering variables and loops.
Comparing Ansible's YAML and Kubernetes' YAML is also wrong. A better comparison would be comparing Ansible to Helm, since they both take the templated-YAML approach. Kubernetes by itself doesn't even let you just use YAML files as intent and idempotently apply them (some objects can be created from YAML using apply, but then not updated, and instead have to be recreated, and that's the logic that's pushed onto external tools like Helm, Kubecfg, ...).
And even instead of using a real DSL that's built into a particular tool, there's the second approach that I currently follow and recommend: use whatever programming language you're comfortable with to emit a desired state in whatever interchange format your management tools needs, and let those tools handle the domain-specific task of converging the state.
If you're saying that, you should clarify for anyone not familiar with various config mgmt tools that in order to provide you with ruby, it compiles ruby in 1 pass, then evaluates the result in ruby again after enriching its environment with the results of the first pass.
This creates surprises when code apparently disappears (because it's been evaluated). In addition, to accomplish some of its other goals, chef performs an up-to 18-layer collapsing of various variables to make them available via the node object, which means that depending on which evaluation phase has completed and what else may have enriched the various layers, the state of the node object can be very hard to understand.
I say this as a big fan of chef - it's quite a lovely product. But on the other side, salt and ansible work to provide fewer footguns in the default case where the goal is to provide structured data to a function that will act on it. It allows you to footgun yourself differently, but your excitement about yaml vs. a programming language is understandable, but impractical since putting programming languages into the position of managing the messy reality of running a program on an operating system requires a lot of any programming language - it's where the rubber meets the road and the road is neither smooth nor straight.
And back in the day sysadmins wrote programs like tcp_wrappers, postfix, sendmail, etc. It was definitely common and encouraged if not expected.
The idea that system admins should be able to get away with never professionally stepping up to doing programming is a late-90s/early-00s aberration that was generated by the need to scale up during the dot com boom before good automation practices existed. And it is not a good thing and it stunts intellectual growth. Devops is in some sense back-to-the-future by tearing down an artificial wall that never should have been made in the first place.
Sure, lots of systems people program and love programming, but the job isn't to write write tcp_wrappers, postfix, sendmail etc. it's to do what's needed to make sure that such things run, which is a different kind of programming.
My take is:
The complex admin work will be going to the cloud providers.
The rest (besides some niche stuff) will get so simple a programmer can do it on the side.
Admins that don't learn to program are left behind. Only those who have some cushy full time employment, were they can't be let go, will remain.
While I personally am a Software Engineer + Systems Engineer combination perfect for modern Devops... I do not agree with you one bit.
There will always be a place for non-programming systems administrators -- especially as we get more and more systems over time.
Will those administrators be able to /scale/ to managing 100s or 1000s of system without learning some sort of programming language or configuration management system? Probably not.
However, there are plenty of businesses out there that only have a handful of servers and services which can totally (and more cheaply) be managed manually.
Automation has an up-front cost that doesn't always make sense for the business to spend.
I wish we started analyzing this as the hard problem it is rather than getting angry that people didn't always make the right decision by correctly anticipating how their software would end up being used.
Why couldn't they use a regular programming language to create the markup? I mean this is done with HTML and JS all the time.
jinja is in wide use in the python community.
Sure, you can probably build your own concept of functions on top of Jinja, either by embedding them or building your own paradigm on top of Jinja's template inheritance, but it's a hack either way.
In the case of thread OP, that template is pretty messy, yes. In ansible, I would just create a custom module or action plugin in python to spit out whatever it is I need. I don't know how flexible salt is in this regard, but ansible is quite flexible.
For simple cases, jinja works great if you're just doing a find/replace type operation in yaml.
Please don't give markup a bad name because of YAML, or the clusterfuck linked by GP.
I just don't understand why someone would create such a "clusterfuck linked by my GP"
If you re-invent a programming language in markup, you basically get a new custom programming language that "probably" can do the same as another non-custom programming language, but without the benefit of many people already know them.
Why not integrate something like Lua or Dyon instead of YAML or XML?
And if I'm writing code, it should look like code you'd actually want to read and edit. Not something with hacked-on delimiters {%- all over the place %}.
My company's scripts have lots of "if fail, try two more times, and hope it succeeds" logic as a result. -_-
> Three dots ( “...”) indicate the end of a document without starting a new one, for use in communication channels
If the user sends;
---
time: 20:03:20
player: Sammy Sosa
action: strike (miss)
...
.. you can't know if they actually meant to send .. ---
time: 20:03:20
player: Sammy Sosa
action: strike (miss)
...
---
time: 20:03:47
player: Sammy Sosa
action: grand slam
...
Also, in my experience, which is mostly limited to Ansible config because I prefer JSON, I've never seen three dots in the wild. I don't think devops people like them. ---
But depending on the exact setup and used YAML parser, this may be hard to enforce.One really really nice aspect of YAML is how incredibly terse it is. That's a massive and very underrated boon for readability but the lack of syntactic cruft also means that it's much more susceptible to various type errors if it's parsed without a schema.
Sure, the text format is quirky, but so far it works quite well for me and protobuffers (v3) can be easily rendered as JSON.
Had not heard of protobuffers before though, and it does look pretty neat.
I do agree that your approach seems good. Alternatives such as jsonschema seem to have much worse syntax, tooling and language support. And we don't discuss XML schemas in polite company.
Sure, you should wrap up all the shell commands you plan to use into code fragments that you can reference. It's neater that way. Suddenly, you have 50 beautifully unit tested objects in your code, each encapsulating a different way you planned on using 'grep'.
And then you open-source your tool, and hundreds of people descend on it and yearn to use it in ways unimaginable to you. You then have to decide whether you're going to a) create a plugin system that allows nicely tested modules in whatever language the user is most familiar with, b) you wrap all the functions yourself (good luck!), c) Say "Sorry, my beautiful tool - with is 99% exactly what you need - is totally not for this. Fork it and be gone" - or d) let people embed scripting statements or shell commands in some way.
If you have the time for (a) and (b), and this is the issue on which you wish to sacrifice yourself, more power to you. If (c) makes more sense to you, then thank you for your input, sorry your project didn't quite take off like you planned.
But please, don't get upset if people choose (d) and get on with their lives. Yes, it _might_ cause pain further down the road, but it's their road to travel.
It's not a programming language, but rather a specification for calculable parts of the law. A JS programm then generates Typeform-like simulators, a node library, and an online interactive documentation (it is now compulsory for french administrations to explain their algorithms).
I'm not sure YAML is the good long-term design choice, but as we can't afford to write our own language, it's bootstrapped the project successfully.
Here is the main file : https://github.com/betagouv/syso/blob/master/source/règles/b... Don't be afraid by the number of lines, it's just a collection of variables.
Bugs arise when you're forced to integrate rules that change over time.
http://github.com/crdoconnor/strictyaml
It also does away with a few other anti-features (e.g. the object parsing that led to the epic RoR security hole) and there's a long justification for each.
I would like somehow to create a new spec out of this and see it implemented in programming languages other than python.
"y|Y|yes|Yes|YES|n|N|no|No|NO |true|True|TRUE|false|False|FALSE |on|On|ON|off|Off|OFF"
- languages:
- en # english
- is # icelandic
- no # norwegian
- ja # japanese
- fr # french
[{"languages": ["en", "is", false, "ja", "fr"]}]I don't want to hand-craft a file like a 14th century woodworker carving out letters on blocks. I want a program to just make the config or do the appropriate action for me, based on questions it asks me. I shouldn't have to write code to do that, or treat a file as code, or use a "language" to get work done, whenever it is possible (i.e. most of the time).
The only times I ever want a "language" is when I need to do something complex and iterative, like crafting a search query, or constructing a simple one-line pipeline of pre-defined functions. Aside from that, crafting configuration and performing operations should have a real user interface.
All of that applies to config, or to any other solution to the problem, because the complexity is (usually) inherent to the business problem you're solving. The difference is that in config, none of that tooling is available. If I put some complex logic in config I still want to version control it and debug it and test it - but I can't. Give me a real programming language where at least I have standard tools available for managing complexity.
> Aside from that, crafting configuration and performing operations should have a real user interface.
Code is the best user interface anyone has ever come up with for specifying complex logic, precisely. Mathematicians use something very similar, not because maths is done on computers but because they have the same need to communicate precisely. Lawyers use a "plain english" language that ends up being more verbose and less readable. Any "visual" format, including every configuration UI I've seen in practice, is even worse.
While I haven't run menuconfig since the 90's I find myself setting up CPAN on just about every server I manage. Although a bit dated like I said above it's still very easy to use and provides clear instructions on why you should or should not choose certain options based on the environment you are setting up.
Just wondering if these are good examples or not. If not, do you have any other examples of good config programs you can point to?
I have to admit that I used to spend time reading and painstakingly setting each and every option in CPAN, some of the time not even understanding why or what I was setting, but these days I just say yes to “do you want me to try and configure as much as possible automatically?”. It hasn’t failed me yet! :-)
Any tool that can do the heavy lifting by poking the environment a bit like that seemed to fit what you were talking about so that’s why I mentioned it.
Binary computers are precise in their operation; that's why we use programming languages: to make it easier to create the underlying instructions to perform calculations. You are assuming that human answers to human questions in imprecise human language can even be converted to binary instructions. If it were that easy, general AI would've already been invented and self-driving cars would already exist.
$ awscli s3 ls
Unable to locate credentials. You can configure credentials by running "aws configure".
That is stupid. Let's fix it. #!/bin/bash
[ -r .awssettings ] && . .awssettings
[ -n "$USERN" ] || read -p "What is your username? " USERN
if [ ! -n "$PASS" ] ; then
read -s -p "Enter your password: " PASS ; echo ""
fi
[ -n "$REGION" ] || read -p "What region should I run this in? " REGION
echo awscli --region $REGION --user $USER --pass $PASS "$@" \
&& echo -en "USER=$USER\nREGION=$REGION\n" > .awssettings
$ ./foo.sh s3 ls
What is your username? peter
Enter your password:
What region should I run this in? us-east-1
awscli --region us-east-1 --user peter --pass blahblah s3 ls
This is a contrived example, because of course AWS wants obscure tokens and secrets to log in, but the point is that it was trivial to write an interface that helped the user out. The fact that this isn't the default is stupid. (The argument that it fails by default to "help programs out" is dumb, because a simple argument like --no-questions which becomes default without a tty is easy)Having simple, predictable, consistent behavior from our tools is far better than trying to guess what the user wanted.
In my universe people have been pushing "visual programming environments" for something close to 60 years, and they're still awful and haven't caught on. Over the last 10-20 years programs have taken a step away from "wizard" style interactions like you describe, as it turns out that a simple, automatable config format is more useful than a step-by-step interaction. API design has started to realise the importance of understandability over magic, e.g. the new generation of 3D graphics APIs are much less "do what I mean" than the previous generation.
Even the simplest things, like passing some data (e.g. a link) from one job to another requires quite an overhead (either using artifacts, storing it somewhere in KV or even something worse).
Moreover, .gitlab-ci.yml is one and only entry-point for the CI configuration, so everything goes into it. Yes, it does have concept of includes, but even that is quite limited and not sufficient for any reasonable workflow.
I agree that a lot of complex pipelines can be tough to express in YAML. One of our key focuses this year is to make advanced use cases for GitLab CI/CD more lovable. Specifically, you can see the overall direction here: https://about.gitlab.com/direction/verify/. Some specific issues I'd love feedback from the community on that I'm thinking about are:
* Directed acyclic graphs (DAG) for pipelines: https://gitlab.com/gitlab-org/gitlab-ce/issues/47063
* Make it possible to use any language to generate `.gitlab-ci.yml` and pipelines: https://gitlab.com/gitlab-org/gitlab-ce/issues/45828
* First class support for multiple pipelines: https://gitlab.com/gitlab-org/gitlab-ce/issues/28592
* Self-modifying pipelines: https://gitlab.com/gitlab-org/gitlab-ce/issues/44199
(edited for readability)
Yes, a lot of YAML abuse consists of trying to pretend code is config, and that problem exists for any config format. However YAML specifically is also a uniquely bad config format, even when used for plain config; too many obscure corner cases (e.g. the abbreviation for Norway turning into false, port mappings turning into times when the ends in a number...)
Code is Data! Lisp-it or Quit!
I mean, maybe there is something about your format that makes these specific approachs inconvenient. But once you give a Lisper a bunch of S-expressions, you just opened the door for them to unleash the full power of Lisp upon it.
So I think your plan to frustrate Lispers by making an S-expression based format popular, will just give them even more power.
The IMAP4 mail protocol uses S-expressions also.
I saw the comment that Helm is going to include Lua, but not getting the advantage that Helm brings over base Lua.
Right, which is essentially what Dhall is. There aren't any established "real" programming languages that are restricted enough (non-Turing complete, etc.) to use for this kind of case.
> (I (can't (think (of any though))))
S-expressions are never going to succeed; there are too many subtly incompatible variations going around already, and their fans are unwilling to compromise and agree on a common standard.
* https://github.com/edn-format/edn * https://learnxinyminutes.com/docs/edn/ * https://www.compoundtheory.com/clojure-edn-walkthrough/
(gitlab:assets:compile
#%dedicate-no-docs-pull-cache-job
(image "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.5.3-git-2.18-chrome-71.0-node-8.x-yarn-1.12-graphicsmagick-1.3.29-docker-18.06.1")
(dependencies
setup-test-env)
(services
(docker stable-dind))
(variables
(NODE_ENV production)
(RAILS_ENV production)
(SETUP_DB false)
(SKIP_STORAGE_VALIDATION true)
(WEBPACK_REPORT true)
;; we override the max_old_space_size to prevent OOM errors
(NODE_OPTIONS "--max_old_space_size=3584")
(DOCKER_DRIVER overlay2)
(DOCKER_HOST "tcp://docker:2375"))
(script
"node --version"
"yarn install --frozen-lockfile --production --cache-folder .yarn-cache"
"free -m"
"bundle exec rake gitlab:assets:compile"
"time scripts/build_assets_image"
"scripts/clean-old-cached-assets")
(artifacts
(webpack-report
(expire-in 31d)
(paths
"webpack-report"
"public/assets/"))))
And that’s just a first cut; it could be made much nicer.This is exactly the problem with S-expressions. No-one is willing to define what "good enough" looks like and create a fixed, reusable standard for how you represent these things. Instead everyone hand-rolls their own, subtly incompatible variant.
Which is completely useless, because it means everyone will do it differently.
> Beyond that, give your users the power to do it their way. Or they will find a way to get it themselves.
Users put value on having a standard set of scaffolding. That's why these standardised config formats have succeeded.
Then there is the slow creep of Turing into config for the sake of dynamic config. Starts as a simple condition flag. Then add if/then logic. It is an amusing tread.
So, yes. You can get a lot of variety in how configs look. But at the end if the day, they should all work. Usually in much more explainable terms. Just look at most people's emacs config. There are good options to make those readable today. It is still not that hard to see how most people's have worked for a long time.
Reading people's CloudFormation and related templates? Especially if they are done using jinja or some other yaml generation trick? Near impossible.
To directly answer your question, though. No, it does not appear that anyone agrees on how to generate config for things. Which is why every team I join seems to have invented a new way for doing it, all in the name of "maintainability." I often get dirty looks for suggesting that people not build automation on top of the config before they have proven it is truly needed with experience. (That is, if this is your first config to create, do it by hand for the reviewability, if for no other reason.)
For example: I used to use YAML to define field mappings between external data and internal models in a Rails application.
like:
- src: fieldA
dest: field_a
filter: name_of_some_filter_function
Is this programming? Data? Really it's configuration for an import library, but I find the line blurry.In your case, it can be defended as documentation for data mapping, but executable scripts are rarely so.
The TypeScript SDK is extremely thorough and type driven, enabling non-devops engineers to catch more errors before it's run, and it extensively uses asynchrony to build up a graph of resources needed, even if those are across platforms. e.g.: We create a project in Google Cloud, then create a service account, then we create a GKE cluster, then a namespace in the cluster when that's available, then we create roles, ... all of this falls out of simply using their SDK, the resolution of the DAG and awaiting of results is done automatically with some nifty types (almost all inputs can take a promise-like value instead of a POD data type.)
from multiprocessing import cpu_count
def max_workers():
return cpu_count() * 2 + 1
workers = max_workers()
errorlog = "/var/www/lcfs/logs/error_logs.log"
accesslog = "/var/www/lcfs/logs/access_logs.log"My point being that just having some code to configure your thing is not exactly novel. Just not commonly done. Outside of lisp communities.
I've been playing with ways of entering test data for years. At Triggerz where I have worked, we use Excel heavily. That works really well but I have to open Excel or LibreCalc to edit the files, which feels really slow and annoying compared to all other files that I can keep in my editor. There is a read-only plugin for VSCode but not yet one that lets me edit.
Markdown tables are quite easy to write when the editor supports them (i.e. auto-formatting), and work pretty well for me.
When you have sevral configuration files where you have to change/tweak data I always end up pulling my hairs why stuff isn't working because of an extra space lying anywhere in the file.
Please don't use YAML for anything that has to be edited by a human
INI, XML, JSON are all formats that are more forgivable regarding that (oh and always trim anything you parse. The more you do to help against accidental input, the less admins you'll have ;)
I have actually seen something similar to this happen:
1. We just need a few configuration options. Let's add an XML configuration file.
2. Keeping all the configuration files in sync for different environments is a lot of work and really error-prone. Let's generate all the configuration files. What about an XML meta-configuration file?
3. Some things are different between environments. We need conditionals in our XML meta-configuration language.
4. There is a lot of repetitive configuration. It would be more maintainable if we had loops, variables, integers, string interpolation, functions, ... in our XML meta-configuration language.
Great, now we invented our own awful programming language that lacks any tooling, documentation or libraries and isn't compatible with anything else.
What are you talking about? YAML, XML (particularly HTML) and JSON were always intended to be written by and understood by human beings, no less so than any "programming language." All of these were designed to be "used by people" and machines.
>Actual programming languages - designed for use by people - are rarely considered for high level configuration.
And the rest of your comment illustrates why. What you have when you use a programming language for "high level configuration" isn't configuration. Configuration should describe constant state, not operate on or transform mutable state. What you have, then, is just more application layer, on top of your application.
Which you don't have with JSON. Or INI. And you do still kind of have with YAML, and definitely can with XML, but that's why a lot of people don't like YAML or XML when it gets too complex.
What it looks like your example shows is dumping unnecessary complexity into configuration in order to maintain "simplicity" in the application. You would have the exact same problem using a high level programming language, it would just be potentially infinitely worse with the explosion of complexity and feature creep that comes with it.
I'd like to propose that there is no fundamental distinction between code and configuration languages. The distinction is actually between total and non-total (Turing-complete) languages. Configuration languages are just programming languages of varying complexity. Some of them are total (i.e. non-Turing-complete) and that's a good thing.
Can be broken to file parts, support comment, variable, functions or scripts. And with additional extension can import packages. Though the downside may be JSON format that's noticably bigger than yaml.
Over fifteen years ago I was in programming as configuration hell with Interface21, and later Spring-based enterprise Java stuff...
Code is data is code.
All with any form of inheritance or programmatically derived settings I see fit.
ROS2 is going the same way too.
> Djikstra
Dijkstra. Please!