tests-always-included / mo

Mustache templates in pure bash
Other
563 stars 67 forks source link

Arrays in console? #46

Closed terion-name closed 3 years ago

terion-name commented 3 years ago

I am trying to render a template just from a console, not inside of a bash script.

Template:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - https://github.com/terion-name/k8s-templates.git/packs/default_https/
  - ../../../cluster/regcred/
  {{#resources}}
  - {{.}}
  {{/resources}}

Running in console:

$ resources=$(find . -type f  -maxdepth 2 | grep /resources/)
$ echo $resources
./resources/nginx-config.yml
./resources/app-config.yml
$  cat ../../../resources/https-app.template.yml |  mo

And no, list is not rendering. Why?

fidian commented 3 years ago

That's because $resources is not an array.

$ mkdir x
$ cd x
$ touch resource1 resource2
$ resources=$(find . -type f | grep resource)
$ echo "$resources"
./resource2
./resource1
$ set | grep ^resource=
resources=$'./resource2\n./resource1'
$

You'll see two lines from the echo, but that's a single string variable. You can see it's a single string instead of an array by looking at the output from set. If it were an array, you would see this.

$ resources=( resource1 resource2 )
$ set | grep ^resources=
resources=([0]="resource1" [1]="resource2")
$

However, even if you do make your files an array, you need to source mo into the environment in order to get it to use the arrays. When you run it as a command (unsourced), then the shell can't pass an array to the process. Environment variables are reduced to a single string when spawning a process. Here's proof:

$ resources=( resource1 resource2 )
$ echo -e "{{#resources}}\n{{.}}\n{{/resources}}" > template
$ mo template
$

That fails because the array can't be sent to the command in a newly spawned process.

$ resources=( resource1 resource2 )
$ echo -e "{{#resources}}\n{{.}}\n{{/resources}}" > template
$ . `which mo`
$ mo template
resource1
resource2
$

That one worked because the command was sourced into the environment. It loads a function, mo (conveniently the same name) into Bash so it doesn't spawn a subshell and allows arrays.

If you look at the demo/ folder, you might see some other examples that will show this off some more.

Feel free to reopen this issue or make a new one if this didn't fully answer your question.