twpayne / chezmoi

Manage your dotfiles across multiple diverse machines, securely.
https://www.chezmoi.io/
MIT License
12.85k stars 477 forks source link

Loop through a template #2586

Closed bonecountysheriff closed 1 year ago

bonecountysheriff commented 1 year ago

What exactly are you trying to do?

I'm trying to configure SSH for multiple users on github and gitlab and am considering using chezmoi templates for the purpose since I already use it for managing dotfiles.

The config file is located at ~/.ssh/config. SSH configuration feels quite inflexible and doesn't support features like including an external file or looping. So everything needs to be done by chezmoi. I'm starting with a template file which looks something like this.

config.tmpl

Host gitlab-$name
    User git
    HostName gitlab.com
    IdentityFile ~/.ssh/$name

Host github-$name
    User git
    HostName github.com
    IdentityFile ~/.ssh/$name

In the above template, suppose $name assumes three different values - user1, user2 and user3. Then the output (final config) should be the following.

~/.ssh/config

Host gitlab-user1
    User git
    HostName gitlab.com
    IdentityFile ~/.ssh/user1

Host github-user1
    User git
    HostName github.com
    IdentityFile ~/.ssh/user1

Host gitlab-user2
    User git
    HostName gitlab.com
    IdentityFile ~/.ssh/user2

Host github-user2
    User git
    HostName github.com
    IdentityFile ~/.ssh/user2

Host gitlab-user3
    User git
    HostName gitlab.com
    IdentityFile ~/.ssh/user3

Host github-user3
    User git
    HostName github.com
    IdentityFile ~/.ssh/user3

I have looked through chezmoi's template guide, but there was no mention of loops. I was hoping if this could be achieved in a different way.

Where else have you checked for solutions?

Output of chezmoi doctor

```console $ chezmoi doctor RESULT CHECK MESSAGE warning version v2.27.0, built at 2022-11-09T13:20:09Z warning latest-version v2.27.1 ok os-arch linux/amd64 (Arch Linux) ok uname Linux archlinux 6.0.8-arch1-1 #1 SMP PREEMPT_DYNAMIC Thu, 10 Nov 2022 21:14:24 +0000 x86_64 GNU/Linux ok go-version go1.19.3 (gc) ok executable /usr/bin/chezmoi ok config-file no config file found error source-dir open ~/.local/share/chezmoi: no such file or directory ok suspicious-entries ~/.local/share/chezmoi: no such file or directory error working-tree open ~/.local/share/chezmoi: no such file or directory ok dest-dir ~ is a directory ok umask 022 ok cd-command found /bin/zsh ok cd-args /bin/zsh info diff-command not set warning edit-command vi not found in $PATH ok edit-args vi ok git-command found /usr/bin/git, version 2.38.1 warning merge-command vimdiff not found in $PATH ok shell-command found /bin/zsh ok shell-args /bin/zsh info age-command age not found in $PATH ok gpg-command found /usr/bin/gpg, version 2.2.40 info pinentry-command not set info 1password-command op not found in $PATH info bitwarden-command bw not found in $PATH info gopass-command gopass not found in $PATH info keepassxc-command keepassxc-cli not found in $PATH info keepassxc-db not set info keeper-command keeper not found in $PATH info lastpass-command lpass not found in $PATH info pass-command pass not found in $PATH info passhole-command ph not found in $PATH info vault-command vault not found in $PATH info secret-command not set ```
twpayne commented 1 year ago

chezmoi uses Go'stext/template package for templates. For loops, use the range action.

bonecountysheriff commented 1 year ago

Thank you for the quick reply, I'm going through the documentation for go templates right now and if everything works, I'll close the issue right away.

bradenhilton commented 1 year ago
{{ range $_, $name := list "user1" "user2" "user3" -}}
{{   range $_, $host := list "gitlab" "github" -}}
Host {{ $host -}}-{{- $name }}
    User git
    HostName {{ $host -}}.com
    IdentityFile ~/.ssh/{{- $name }}

{{   end -}}
{{ end -}}
bonecountysheriff commented 1 year ago

Thanks a lot @bradenhilton, I really like this solution. The documentation on this has been a little hard to find. May I know what the hyphens and $_ are for?

It seems some of the usernames must not be present in the dotfiles. Is there a way add them from outside the config file?

bradenhilton commented 1 year ago

The hyphens are there to control whitespace, the ones around the variables (e.g. {{ $host -}}) aren't actually necessary in my example but I add them habitually.

$_ was used because range can assign a index and element variable. It is similarly unnecessary and was also used habitually.

As for your other question, I'm sorry but I don't understand. How are you gathering the usernames currently?

bonecountysheriff commented 1 year ago

I just add them manually without any template.

I meant to ask if there is a way to assign an array from the command line for example. Something like this -

prompt> name=(some array) chezmoi apply filename
twpayne commented 1 year ago

I meant to ask if there is a way to assign an array from the command line for example. Something like this -

prompt> name=(some array) chezmoi apply filename

This is possible, but you should not do it.

Firstly, this is possible because you can set an environment variable and then read it in a template with the env template function.

Secondly, you should not do this because you'll have to specify name= every time you run a chezmoi command that evaluates the source state, like chezmoi diff, chezmoi status, or chezmoi apply. If you want to store structured data in a semi-permanent way such that you don't have to specify it every time then consider using a .chezmoidata file.