View on GitHub

swisspush

Community Contributions by Developers in the Swiss Postal IT

29 January 2020 - Laurent Bovet

❤️ YAML ?

YAML is ubiquitous. Wether you love it or hate it, you have no choice but using it. It established itself as the configuration format for all things cloud/devops/serverless (choose your buzzword).

The main characteristic of YAML is the role played by semantic indentation. It makes lazy humans save typing braces to delimit block they would indent anyway.

YAMLJSON
hello:
  foo: bar            
{
  "hello": {
    "foo": "bar"       
  }
}

Humans like YAML because it focuses on the content

Complexity Increase

Automation is at the heart of everything in raise of Infrastructure-as-Code, Cloud, DevOps, GitOps, etc. Containerization also contributes to the exponentially growing number of configuration combinations.

Inevitably, a need for structure and factorization arised.

Text Templating to the Rescue

That’s why most of the tools ingesting YAML configuration support some kind of templating.

The first generation approach relies on existing text templating libraries (Jinja, Go templates, Helm, …). It is a clever but lazy move because it does not work well when indentation comes into play.

Whoever struggled with toYaml in Helm charts is a victim of YAML text templating.

From a user experience point of view, the opening and closing symbols that YAML avoided come back in the templating language.

  {{ if eq .Values.favorite.drink "coffee" }}
  mug: true
  {{ end }}

Alternative: a Dedicated Language

To avoid the drawbacks of text templating, one can adopt a configuration language providing the programmatic features needed to tackle the complexity and generate the YAML. This is typically the approach taken by Jsonnet. It is a powerful language that natively understands the data structure.

  Martini: {
    ingredients: [
      {
        kind: $['Tom Collins'].ingredients[0].kind,
        qty: 2,
      },
      { kind: 'Dry White Vermouth', qty: 1 },
    ]
  }

It can output in many formats, including YAML.

So, everyone should adopt this no? Why is it not the case?

Try to switch to a new language, you will just add a new one to your already bloated Babel tower.

It is difficult to adopt Jsonnet because it cannot be introduced progressively. You have to make a dramatic switch in order to get the benefits. Few organizations are capable of driving such changes in a top-down way.

As all the examples and litterature about YAML-based tools are written in YAML, using Jsonnet imposes to systematically translate them.

And note that these unwanted opening and closing braces are back again…

Enters Structural YAML Templating

So, the truth is in a middle way.

Could we write plain YAML and add programmatic features to it in some undisturbing way?

YTT does this with a language written in YAML comments.

  #@ for/end echo in data.values.echos:
  - name: #@ name(echo)
    image: hashicorp/http-echo
    args:
    - #@ "-listen=:" + str(echo.port)
    - #@ "-text=" + echo.text

The structure of YAML is preserved and understood by the tool. Is this the ultimate definitive way to solve the problem?

As a developer, don’t you a feel slight discomfort when you write code inside comments?

As YTT is designed as replacement of text templating for configuration files, it provides a set of operations optimized for the task. Some features like overlays are powerful, some others like the model for loading template values are limitating.

Leveraging YAML Tags

Thinking about this, I reminded some work I did with YAML about ten years ago. It is a dependency injection system for Python à la Spring Framework. It uses the YAML tag system to create a configuration corresponding to Spring’s Application Context. This YAML, thanks to the tag system and anchors is directly deserialized as wired singletons forming the application structure.

YAML’s strength is in the tags

With YAML tags in and mind inspiration from YTT and Jsonnet, came the design of Yglu ᕄ !?.

InputOutput
greeting: !- Hello
greeter: !()
  length: !? len($)
  message: !? $_.greeting + ', ' + $  
names: !-
  - world
  - foo
  - bar
messages:
  - !for $_.names: !()
     - !? ($_.greeter)($)          
messages:
- length: 5
  message: Hello, world        
- length: 3
  message: Hello, foo
- length: 3
  message: Hello, bar

Find more examples in the online playground and the test samples.

With the tag system and a powerful expression language (YAQL, in this case), YAML structural templating features can be truly idiomatic.

Wrap-Up

Leveraging YAML tags for creating a balanced DSL with a functional expression language brings YAML templating to a next level.

It allows for introducing YAML factorization progressively, integrate with existing YAML tooling and provide an idiomatic user experience.

It is probably the correct base for the tools to come. Maybe with other expression languages, but certainly with YAML tags.

Yglu ᕄ !?


blog comments powered by Disqus