I tried using Ansible once and could never escape the fact that anything complex like installing files or raising docker containers requires the use of external modules with actual code and templated YAML. Every time something "templated" shows up in a supposedly "declarative" language it feels like the designers had to add on features from an actual programming language to do what they wanted, because the DSL was too declarative and static to accomplish anything useful.

For example, look at this Azure deployment template:

https://github.com/Azure/azure-quickstart-templates/blob/65d...

Notice all the inline function calls. They basically modified JSON with their own domain-specific "functions" like "concat" and have an entire section dedicated to "variables" because in standard JSON this is not possible to express. Already this sounds like a scripting language, except terribly watered down and specific only to Azure services.

As a personal anecdote, I once made the dumb mistake of choosing a static config file instead of a dynamic one when I was developing a mod system for a game. The problem became that there were things like function callbacks that I wanted to add in, so that meant I ended up writing inline "pointers" to a place where a Lua callback existed as an identifier, instead of inlining it as Lua code, then it went through an unnecessary transpilation step to Lua data structures. My mistake was assuming that the DSL was expressive enough for my needs, which included loops, inline function callbacks and code generation, when clearly it was not.

Sometimes the effort people expend to make declarative configs work out are significant. The OpenAge project (an engine rewrite of Age of Empires II) uses a declarative language called nyan[1] which describes the changes of things like unit health or cost. It's entirely custom-made for the engine.

The moment that I realized that declarative configs were not for me was when I realized that this declarative language, which the author wrote an entire PhD thesis over and was specifically designed for the purpose of game modding, would still not be expressive for the things I was envisioning. In the end Lua, a general-purpose language that had existed for decades, was the better choice. There was no need to muck around with writing new languages or munging the declarative data into the shape I wanted - the data could just be output from a script.

On the other hand I understand if having a Turing-complete language for configuration is a bad thing because of security or too much expressiveness that hinders static analysis because of unseen edge cases. It depends on if the "scripting" features are hacks intended to get around the fundamental limitations of DSLs or a deliberately constructed featureset.

Also the reason I became so attached to declarative configs in the first place was the prospect of writing an editor frontend to interactively create new data entries. That's probably the reason Azure went with JSON instead of a programming language - they have a template editor in the web portal for filling in the parameterized variables the config declares. This is probably an ease-of-use tradeoff so people don't need to program to deploy things. As someone who uses scripts as configs, how to properly write an editor for them escapes me. I was thinking of having to parse the scripts into an AST and use heuristics to discover where data is inserted, but of course you can program anything so this won't always work.

Still, in my opinion I would choose something like Lua any day over the nth domain-specific proprietary reimplementation of 2% of JavaScript on top of JSON.

[1] https://github.com/SFTtech/nyan