|
| 1 | +# What is yatee? |
| 2 | + |
| 3 | +Yatee is a basic YAML templating engine whose input is a valid YAML file. |
| 4 | + |
| 5 | +# What does it support? |
| 6 | + |
| 7 | +If, for, variable expansion, arithmetic expressions. |
| 8 | + |
| 9 | +# Show me some examples! |
| 10 | + |
| 11 | + version: "3.4" |
| 12 | + services: |
| 13 | + "@for i in 0..2": |
| 14 | + replica$i: |
| 15 | + image: superduperserver:latest |
| 16 | + command: /run $i |
| 17 | + port: |
| 18 | + - $(5000 + ($i*2)) |
| 19 | + - $(5001 + ($i * 2)) |
| 20 | + "@if ${myapp.debug}": |
| 21 | + debugger: |
| 22 | + image: debug |
| 23 | + "@if ! ${myapp.debug}": |
| 24 | + monitor: |
| 25 | + image: monitor |
| 26 | + "@for i in $myapp.services": |
| 27 | + "$i": |
| 28 | + image: $i:latest |
| 29 | + |
| 30 | +When processed with the following settings file: |
| 31 | + |
| 32 | + myapp: |
| 33 | + debug: false |
| 34 | + services: |
| 35 | + - nginx |
| 36 | + - redis |
| 37 | + |
| 38 | +Will produce the following output: |
| 39 | + |
| 40 | + services: |
| 41 | + monitor: |
| 42 | + image: monitor |
| 43 | + nginx: |
| 44 | + image: nginx:latest |
| 45 | + redis: |
| 46 | + image: redis:latest |
| 47 | + replica0: |
| 48 | + command: /run 0 |
| 49 | + image: superduperserver:latest |
| 50 | + port: |
| 51 | + - "5000" |
| 52 | + - "5001" |
| 53 | + replica1: |
| 54 | + command: /run 1 |
| 55 | + image: superduperserver:latest |
| 56 | + port: |
| 57 | + - "5002" |
| 58 | + - "5003" |
| 59 | + |
| 60 | +# How do I invoke it? |
| 61 | + |
| 62 | + ./yatee TEMPLATE_FILE SETTINGS_FILES... |
| 63 | + |
| 64 | +# How do I use it as a library? |
| 65 | + |
| 66 | +The yatee go package exports the following two functions: |
| 67 | + |
| 68 | + // LoadSettings loads a set of settings file and produce a property dictionary |
| 69 | + func LoadSettings(files []string) (map[string]interface{}, error) |
| 70 | + // Process resolves input templated yaml using values given in settings |
| 71 | + func Process(inputString string, settings map[string]interface{}) (map[interface{}] interface{}, error) |
| 72 | + |
| 73 | +# Tell me more about the templating |
| 74 | + |
| 75 | +## All features at a glance |
| 76 | + |
| 77 | +- `$foo.bar and ${foo.bar}` are replaced by the value of `foo.bar` in the settings structure. Nesting is allowed. |
| 78 | +- `${foo?IF_TRUE:IF_FALSE}` is replaced by IF_TRUE if `foo` in settings is true (not empty, 0 or `false`). |
| 79 | +- `$(expr)` is evaluated as an arithmetic expression. Integers, parenthesis, and the operators |
| 80 | + '+-*/%' are supported. Note that there is no operator precedence, evaluation is from left to right. |
| 81 | +- `$$` is replaced by a single literal `$` without any variable expansion. |
| 82 | +- A YAML key of `@for VAR in begin..end` or `@for VAR in VALUE LIST` will inject the value in the |
| 83 | + parent node for each value of VAR. |
| 84 | +- A YAML key of `@if VALUE` will inject its content in the parent node only if VAULE |
| 85 | + is not false (0, empty or 'false'). A prefix '!' is supported to negate the value. A `@else` dict can be specified |
| 86 | + under the `@if` node, and will be injected if the condition is false. |
| 87 | +- A YAML key of `@switch VALUE` will inject it's sub-key's value matching VALUE to the parent node, or |
| 88 | + inject the value under the `default` key if present and no match is found. |
| 89 | +- A YAML value of `@if (EXPR) VALUE` in a list will be replaced by `VALUE` if `EXPR` is true, |
| 90 | + suppressed otherwise |
| 91 | + |
| 92 | +## Variable expansion examples |
| 93 | + |
| 94 | +All examples below use the following settings: |
| 95 | + |
| 96 | + app: |
| 97 | + debug: true |
| 98 | + release: false |
| 99 | + foo: bar |
| 100 | + bar: baz |
| 101 | + count: 2 |
| 102 | + |
| 103 | +Input | Output |
| 104 | +----- | ------ |
| 105 | +${app.debug} | true |
| 106 | +${foo}${bar} | barbaz |
| 107 | +${$foo} | baz |
| 108 | +$(1+2*3) | 9 |
| 109 | +$(1+(2*3)) | 7 |
| 110 | +$($count + 40) | 42 |
| 111 | +${app.debug?foo:bar} | foo |
| 112 | +${app.release?foo:bar} | bar |
| 113 | +$$foo | $$foo |
| 114 | +$$$foo | $$bar |
| 115 | + |
| 116 | +## Control flow examples |
| 117 | + |
| 118 | +Using the same settings as above. |
| 119 | + |
| 120 | +### If |
| 121 | + |
| 122 | + "@if !$app.release": |
| 123 | + shown: nope |
| 124 | + "@else": |
| 125 | + shown: yes |
| 126 | + somelist: |
| 127 | + - a |
| 128 | + - @if ($app.debug) b |
| 129 | + - @if ($app.release) c |
| 130 | + - d |
| 131 | + |
| 132 | +produces: |
| 133 | + |
| 134 | + shown: yes |
| 135 | + somelist: |
| 136 | + - a |
| 137 | + - b |
| 138 | + - d |
| 139 | + |
| 140 | +### For |
| 141 | + |
| 142 | + "@for v in 0..$(count)": |
| 143 | + key$v: val$($v + 1) |
| 144 | + "@for v in a b c": |
| 145 | + key$v: val$v |
| 146 | + |
| 147 | +produces: |
| 148 | + |
| 149 | + key0: val1 |
| 150 | + key1: val2 |
| 151 | + keya: vala |
| 152 | + keyb: valb |
| 153 | + keyc: valc |
| 154 | + |
| 155 | +### Switch |
| 156 | + |
| 157 | + "@switch $foo": |
| 158 | + baz: |
| 159 | + isbaz: 1 |
| 160 | + bar: |
| 161 | + isbar: 1 |
| 162 | + default: |
| 163 | + isother: 1 |
| 164 | + "@switch $bar": |
| 165 | + foo: |
| 166 | + isfoo: 2 |
| 167 | + default: |
| 168 | + isother:2 |
| 169 | + |
| 170 | +produces |
| 171 | + |
| 172 | + isbar: 1 |
| 173 | + isother: 2 |
0 commit comments