YAML Considered Harmful

A presentation at Devoxx Poland in June 2019 in Kraków, Poland by Philipp Krenn

Slide 1

Slide 1

YAML Considered Harmful Philipp Krenn @xeraa

Slide 2

Slide 2

Who is a YAML engineer?

Slide 3

Slide 3

https://homepages.cwi.nl/~storm/teaching/reader/ Dijkstra68.pdf

Slide 4

Slide 4

Why YAML? Human readable Comments

Slide 5

Slide 5

Whitespace Sensitive It depends

Slide 6

Slide 6

Issues http://www.yamllint.com ports: - 80:80 - 20:20

Slide 7

Slide 7

Issues https://docs.docker.com/compose/compose-file/ #short-syntax-1 ports: - “80:80” - 73200

Slide 8

Slide 8

Issues countries: - DE - FR - GB - IE - NO - PT

Slide 9

Slide 9

Issues surname: Null windows_drive: c: version: 1.0

Slide 10

Slide 10

Abuse Behavior instead of data

Slide 11

Slide 11

Gitlab Deploying itself in 1,100+ lines https://gitlab.com/gitlab-org/gitlab-ce/blob/ master/.gitlab-ci.yml

Slide 12

Slide 12

package-and-qa: image: ruby:2.5-alpine stage: test before_script: [] dependencies: [] cache: {} variables: GIT_DEPTH: “1” API_TOKEN: “${GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN}” retry: 0 script: - apk add —update openssl curl jq - gem install gitlab —no-document - source ./scripts/review_apps/review-apps.sh - wait_for_job_to_be_done “gitlab:assets:compile” - ./scripts/trigger-build omnibus when: manual only: - /.+/@gitlab-org/gitlab-ce - /.+/@gitlab-org/gitlab-ee

Slide 13

Slide 13

https://gitlab.com/gitlab-org/gitlab-ce/blob/master/scripts/review_apps/review-apps.sh [[ “$TRACE” ]] && set -x export TILLER_NAMESPACE=”$KUBE_NAMESPACE” function deployExists() { local namespace=”${1}” local deploy=”${2}” echoinfo “Checking if ${deploy} exists in the ${namespace} namespace…” true helm status —tiller-namespace “${namespace}” “${deploy}” >/dev/null 2>&1 local deploy_exists=$? echoinfo “Deployment status for ${deploy} is ${deploy_exists}” return $deploy_exists } …

Slide 14

Slide 14

Helm Templates apiVersion: v1 kind: ConfigMap metadata: name: {{ .Release.Name }}-configmap labels: {{- include “mychart.app” . | nindent 4 }} data: myvalue: “Hello World” {{- range $key, $val := .Values.favorite }} {{ $key }}: {{ $val | quote }} {{- end }} {{- include “mychart.app” . | nindent 2 }}

Slide 15

Slide 15

If you want a DSL, use a DSL

Slide 16

Slide 16

Or Maybe Jsonnet

Slide 17

Slide 17

Alternative Data Format: XML <?xml version=”1.0” encoding=”UTF-8” ?> <!—Last modified 1 April 2001 by John Doe—> <title>XML Example</title> <owner> <name>John Doe</name> </owner> <database> <server>192.168.1.1</server> <ports> <port>8001</port> <port>8002</port> <port>8003</port> </ports> </database> <servers> <server name=”alpha”> <ip>10.0.0.1</ip> <dc>eqdc10</dc> </server> <server name=”beta”> <ip>10.0.0.2</ip> <dc>eqdc10</dc> </server> </servers>

Slide 18

Slide 18

Alternative Data Format: JSON { “_comment”: “Last modified 1 April 2001 by John Doe”, “title”: “JSON Example”, “owner”: { “name”: “John Doe” }, “database”: { “server”: “192.168.1.1”, “ports”: [ 8001, 8002, 8003 ] }, “servers”: { “alpha”: { “ip”: “10.0.0.1”, “dc”: “eqdc10” }, “beta”: { “ip”: “10.0.0.2”, “dc”: “eqdc10” } } }

Slide 19

Slide 19

Alternative Data Format: INI ; Last modified 1 April 2001 by John Doe [owner] name=John Doe organization=Acme Widgets Inc. [database] ; use IP address in case network name resolution is not working server=192.168.1.1 port=8001 [servers] serverAlphaIp=10.0.0.1 serverAlphaDc=eqdc10 serverBetaIp=10.0.0.2 serverBetaDc=eqdc10

Slide 20

Slide 20

Alternative Data Format: TOML # Last modified 1 April 2001 by John Doe title = “TOML Example” [owner] name = “John Doe” dob = 1970-01-01T01:00:00-02:00 # First class dates [database] server = “192.168.1.1” ports = [ 8001, 8002, 8003 ] [servers] [servers.alpha] ip = “10.0.0.1” dc = “eqdc10” [servers.beta] ip = “10.0.0.2” dc = “eqdc10”

Slide 21

Slide 21

Alternative Data Format: JSONx JSONx is an IBM® standard format to represent JSON as XML

Slide 22

Slide 22

Back to Better YAML

Slide 23

Slide 23

Editors Help Example https://marketplace.visualstudio.com/items?itemName=oderwat.indent-rainbow

Slide 24

Slide 24

Linters Help (Sometimes) $ yamllint bad.yml bad.yml 12:5 warning 19:13 error 17:17 error truthy value should be one of [false, true] (truthy) no new line character at the end of file (new-line-at-end-of-file) syntax error: mapping values are not allowed here

Slide 25

Slide 25

Convert from JSON (Maybe) #!/usr/local/bin/python3 import yaml import sys import json OUT=open(‘output.yaml’,’w’) IN=open(sys.argv[1], ‘r’) JSON = json.load(IN) IN.close() yaml.dump(JSON, OUT) OUT.close()

Slide 26

Slide 26

More Indentation & Quoting owner: name: John Doe database: server: 192.168.1.1 ports: - 8001 - 8002 owner: name: “John Doe” database: server: “192.168.1.1” ports: - 8001 - 8002

Slide 27

Slide 27

YAML Considered Harmful Philipp Krenn @xeraa