The @Provided construct adds a ton of complexity that is rarely used and in a very narrow scope. Instead, add a basic pattern matching facility to the configuration loader that rewrites, ignores or structurally enforces certain mustache patterns, e.g.
# Make sure {{thermos.*}} matches the ThermosContext structural
Match("thermos") >> AssumeEnvironment(thermos = ThermosContext)
# {{packer[foo][bar][baz]}} should be replaced with inject_packer_bindings(foo, bar, baz)
Match("packer")[Any][Any][Any] >> inject_packer_bindings
# {{mesos.instance}} should be passed-through as {{mesos.instance}}
Match("mesos").instance >> Identity
These could then be injected into a generic ConfigLoader.
This is trading one kind of complexity for another, but Match => Bind is more powerful and useful than just the @Provided case.
The @Provided construct adds a ton of complexity that is rarely used and in a very narrow scope. Instead, add a basic pattern matching facility to the configuration loader that rewrites, ignores or structurally enforces certain mustache patterns, e.g.
These could then be injected into a generic ConfigLoader.
This is trading one kind of complexity for another, but Match => Bind is more powerful and useful than just the @Provided case.