---
title: BOSHのops-fileをyttのoverlayで書き直す
tags: ["YAML", "BOSH", "ytt"]
categories: ["Dev", "ytt"]
date: 2020-04-19T13:56:46Z
updated: 2020-08-18T07:38:31Z
---

[cf-for-k8s](https://github.com/cloudfoundry/cf-for-k8s)で多用されている、[ytt](https://get-ytt.io/)のoverlayの書き方を身に付ける練習として、BOSHのops fileをyttで書き直してみる。
題材として、[https://bosh.io/docs/cli-ops-files/#ops](https://bosh.io/docs/cli-ops-files/#ops)を`ytt`で実現してみる。

次のドキュメントを参考にした。
* https://github.com/k14s/ytt/blob/master/docs/lang-ref-ytt-overlay.md
* https://static.sched.com/hosted_files/helmsummit2019/34/ytt%20-%20helm%20summit%202019.pdf

以下の`base.yml`をカスタマイズしていく。

```yaml
key: 1

key2:
  nested:
    super_nested: 2
  other: 3

array: [4,5,6]

items:
- name: item7
- name: item8
- name: item8
```

**目次**
<!-- toc -->

以降、デフォルトのOpeationである`@overlay/merge`は省略し、記述していない。

### Hash

> Set `key` to `10` ...

ops-fileの場合
```yaml
- type: replace
  path: /key
  value: 10
```

yttの場合

`hash-replace.yml`
```yaml
#@ load("@ytt:overlay", "overlay")

#@overlay/match by=overlay.all
---
key: 10
```


```
$ ytt -f base.yml -f hash-replace.yml
key: 10
key2:
  nested:
    super_nested: 2
  other: 3
array:
- 4
- 5
- 6
items:
- name: item7
- name: item8
- name: item8
```

> overlay fileの`---`の上の`#@overlay/match by=***`は、複数あるYAMLブロックのうちのどのブロックを対象とするかを指定する条件式である。<br>
> BOSHの場合は1つのYAMLブロックしかサポートしていないため、移行の際は`by=overlay.all`または、念のため`by=overlay.all,expects=1`で良いはず。<br>
> Kubernetesの場合は通常、複数のYAMLブロックを扱うので、`by=overlay.subset({"kind": "Ingress"})`などで条件を絞る必要がある。

---
> Remove `key`...


ops-fileの場合
```yaml
- type: remove
  path: /key
```

yttの場合

`hash-remove.yml`
```yaml
#@ load("@ytt:overlay", "overlay")

#@overlay/match by=overlay.all
---
#@overlay/remove
key: 
```

```
$ ytt -f base.yml -f hash-remove.yml
key2:
  nested:
    super_nested: 2
  other: 3
array:
- 4
- 5
- 6
items:
- name: item7
- name: item8
- name: item8
```

---
> Errors because `key_not_there` is expected (and does not have ?)...

ops-fileの場合

```yaml
- type: replace
  path: /key_not_there
  value: 10
```

yttの場合

`hash-replace-error.yml `
```yaml
#@ load("@ytt:overlay", "overlay")

#@overlay/match by=overlay.all
---
key_not_there: 10
```

```
$ ytt -f base.yml -f hash-replace-error.yml 
ytt: Error: Overlaying (in following order: hash-replace-error.yml): Document on line hash-replace-error.yml:4: Map item (key 'key_not_there') on line hash-replace-error.yml:5: Expected number of matched nodes to be 1, but was 0
```
---
> Errors because `key_not_there` is expected (does not have ?)...

ops-fileの場合
```yaml
- type: remove
  path: /key_not_there
```

yttの場合

`hash-remove-error.yml `
```yml
#@ load("@ytt:overlay", "overlay")

#@overlay/match by=overlay.all
---
#@overlay/remove
key_not_there:
```

```
$ ytt -f base.yml -f hash-remove-error.yml 
ytt: Error: Overlaying (in following order: hash-remove-error.yml): Document on line hash-remove-error.yml:4: Map item (key 'key_not_there') on line hash-remove-error.yml:6: Expected number of matched nodes to be 1, but was 0
```
---

> Creates `new_key` and sets it to `10` (note the `?`)...

ops-fileの場合
```yaml
- type: replace
  path: /new_key?
  value: 10
```

yttの場合

`hash-create.yml `
```yaml
#@ load("@ytt:overlay", "overlay")

#@overlay/match by=overlay.all
---
#@overlay/match missing_ok=True
new_key: 10
```

```
$ ytt -f base.yml -f hash-create.yml 
key: 1
key2:
  nested:
    super_nested: 2
  other: 3
array:
- 4
- 5
- 6
items:
- name: item7
- name: item8
- name: item8
new_key: 10
```
---
> Requires that `key2` and nested hashes exist; and sets `super_nested` to `10`...

ops-fileの場合
```yaml
- type: replace
  path: /key2/nested/super_nested
  value: 10
```

yttの場合

`hash-replace-nested.yml`
```yaml
#@ load("@ytt:overlay", "overlay")

#@overlay/match by=overlay.all
---
key2:
  nested:
    super_nested: 10
```

```
$ ytt -f base.yml -f hash-replace-nested.yml 
key: 1
key2:
  nested:
    super_nested: 10
  other: 3
array:
- 4
- 5
- 6
items:
- name: item7
- name: item8
- name: item8
```
---

> Requires that `key2` and `nested` hashes exist; and removes `super_nested`...

yaml pacthの場合
```yaml
- type: remove
  path: /key2/nested/super_nested
```

yttの場合

`hash-remove-nested.yml`

```yaml
#@ load("@ytt:overlay", "overlay")

#@overlay/match by=overlay.all
---
key2:
  nested:
   #@overlay/remove
   super_nested:
```

```
$ ytt -f base.yml -f hash-remove-nested.yml
key: 1
key2:
  nested: {}
  other: 3
array:
- 4
- 5
- 6
items:
- name: item7
- name: item8
- name: item8
```

---

> Requires that `key2` hash exists; allows `nested`, `another_nested` and `super_nested` not to exist because `?` carries over to nested keys; and `creates another_nested` and `super_nested` before setting `super_nested` to `10`...

ops-fileの場合
```yaml
- type: replace
  path: /key2/nested?/another_nested/super_nested
  value: 10
```

yttの場合

`hash-create-nested.yml`
```yaml
#@ load("@ytt:overlay", "overlay")

#@overlay/match by=overlay.all
---
key2:
  nested:
   #@overlay/match missing_ok=True
   another_nested:
     super_nested: 10
```

```
$ ytt -f base.yml -f hash-create-nested.yml 
key: 1
key2:
  nested:
    super_nested: 2
    another_nested:
      super_nested: 10
  other: 3
array:
- 4
- 5
- 6
items:
- name: item7
- name: item8
- name: item8
```

---

### Array

> Requires `array` to exist and be an array; and replaces 0th item in `array` array with `10`...



ops-fileの場合
```yaml
- type: replace
  path: /array/0
  value: 10
```

yttの場合

`array-replace-0th.yml `
```yaml
#@ load("@ytt:overlay", "overlay")

#@overlay/match by=overlay.all
---
array:
#@overlay/match by=overlay.index(0)
- 10
```

```
$ ytt -f base.yml -f array-replace-0th.yml
key: 1
key2:
  nested:
    super_nested: 2
  other: 3
array:
- 10
- 5
- 6
items:
- name: item7
- name: item8
- name: item8
```

---
> Requires `array` to exist and be an array; and removes the 0th item in `array`...


ops-fileの場合
```yaml
- type: remove
  path: /array/0
```

yttの場合

`array-remove-0th.yml `
```yaml
#@ load("@ytt:overlay", "overlay")

#@overlay/match by=overlay.all
---
array:
#@overlay/match by=overlay.index(0)
#@overlay/remove
- 
```

```
$ ytt -f base.yml -f array-remove-0th.yml      
key: 1
key2:
  nested:
    super_nested: 2
  other: 3
array:
- 5
- 6
items:
- name: item7
- name: item8
- name: item8
```
---
> Requires `array` to exist and be an array; and appends `10` to the end of `array`...



ops-fileの場合
```yaml
- type: replace
  path: /array/-
  value: 10
```

yttの場合

`array-append.yml`
```yaml
#@ load("@ytt:overlay", "overlay")

#@overlay/match by=overlay.all
---
array:
#@overlay/append
- 10
```

```
$ ytt -f base.yml -f array-append.yml 
key: 1
key2:
  nested:
    super_nested: 2
  other: 3
array:
- 4
- 5
- 6
- 10
items:
- name: item7
- name: item8
- name: item8
```
---
> Creates `array2` array since it does not exist; and appends `10` to the end of `array2`...


ops-fileの場合
```yaml
- type: replace
  path: /array2?/-
  value: 10
```

yttの場合

`array-create.yml`
```yaml
#@ load("@ytt:overlay", "overlay")

#@overlay/match by=overlay.all
---
#@overlay/match missing_ok=True
array2:
- 10
```

```
$ ytt -f base.yml -f array-create.yml
key: 1
key2:
  nested:
    super_nested: 2
  other: 3
array:
- 4
- 5
- 6
items:
- name: item7
- name: item8
- name: item8
array2:
- 10
```
---
> Requires `array` to exist and be an array; and inserts 10 after 0th item in `array` array...



ops-fileの場合
```yaml
- type: replace
  path: /array/0:after
  value: 10
```

yttの場合

`array-insert-after.yml`
```yaml
#@ load("@ytt:overlay", "overlay")

#@overlay/match by=overlay.all
---
array:
#@overlay/match by=overlay.index(0)
#@overlay/insert after=True
- 10
```

```
$ ytt -f base.yml -f array-insert-after.yml 
key: 1
key2:
  nested:
    super_nested: 2
  other: 3
array:
- 4
- 10
- 5
- 6
items:
- name: item7
- name: item8
- name: item8
```
---
> Requires `array` to exist and be an array; and inserts `10` before 0th item at the beginning of `array` array...



ops-fileの場合
```yaml
- type: replace
  path: /array/0:before
  value: 10
```

yttの場合

`array-insert-before.yml`
```yaml
#@ load("@ytt:overlay", "overlay")

#@overlay/match by=overlay.all
---
array:
#@overlay/match by=overlay.index(0)
#@overlay/insert before=True
- 10
```

```
$ ytt -f base.yml -f array-insert-before.yml 
key: 1
key2:
  nested:
    super_nested: 2
  other: 3
array:
- 10
- 4
- 5
- 6
items:
- name: item7
- name: item8
- name: item8
```
---

### Arrays of hashes

> Finds and removes array item with matching key `name` with value `item7`...


ops-fileの場合
```yaml
- type: remove
  path: /items/name=item7
```

yttの場合

`find-and-remove-array-item.yml`
```yaml
#@ load("@ytt:overlay", "overlay")

#@overlay/match by=overlay.all
---
items:
#@overlay/match by="name"
#@overlay/remove
- name: item7
```

```
$ ytt -f base.yml -f find-and-remove-array-item.yml 
key: 1
key2:
  nested:
    super_nested: 2
  other: 3
array:
- 4
- 5
- 6
items:
- name: item8
- name: item8
```
---
> Errors because there are two values that have `item8` as their `name`...


ops-fileの場合
```yaml
- type: replace
  path: /items/name=item8/count
  value: 10
```

yttの場合

`find-and-replace-array-item-error.yml `
```yaml
#@ load("@ytt:overlay", "overlay")

#@overlay/match by=overlay.all
---
items:
#@overlay/match by="name", missing_ok=True
- name: item8
  count: 10
```

```
$ ytt -f base.yml -f find-and-replace-array-item-error.yml 
ytt: Error: Overlaying (in following order: find-and-replace-array-item-error.yml): Document on line find-and-replace-array-item-error.yml:4: Map item (key 'items') on line find-and-replace-array-item-error.yml:5: Array item on line find-and-replace-array-item-error.yml:7: Expected number of matched nodes to be 1, but was 2 (lines: base.yml:12, base.yml:13)
```
---
> Appends array item with matching key `name` with value `item9` because values ends with `?` and item does not exist; creates `count` and sets it to `10` within created array item...

ops-fileの場合
```yaml
- type: replace
  path: /items/name=item9?/count
  value: 10
```

yttの場合

`find-and-append-array-item.yml `
```yaml
#@ load("@ytt:overlay", "overlay")

#@overlay/match by=overlay.all
---
items:
#@overlay/match by="name", missing_ok=True
- name: item9
  count: 10
```

```
$ ytt -f base.yml -f find-and-append-array-item.yml 
key: 1
key2:
  nested:
    super_nested: 2
  other: 3
array:
- 4
- 5
- 6
items:
- name: item7
- name: item8
- name: item8
- name: item9
  count: 10
```
---
> Finds array item with matching key `name` with value `item7`; and adds hash `name: item6` before found array item...


ops-fileの場合
```yaml
- type: replace
  path: /items/name=item7:before
  value:
    name: item6
```

yttの場合

`find-and-insert-array-item-before.yml `
```yaml
#@ load("@ytt:overlay", "overlay")

#@overlay/match by=overlay.all
---
items:
#@overlay/match by=overlay.subset({"name": "item7"})
#@overlay/insert before=True
- name: item6
```

```
$ ytt -f base.yml -f find-and-insert-array-item-before.yml 
key: 1
key2:
  nested:
    super_nested: 2
  other: 3
array:
- 4
- 5
- 6
items:
- name: item6
- name: item7
- name: item8
- name: item8
```
