Skip to content
This repository has been archived by the owner on Oct 30, 2018. It is now read-only.

Ability to use variables in Linuxkit configuration? #163

Closed
xtuc opened this issue Oct 10, 2017 · 8 comments
Closed

Ability to use variables in Linuxkit configuration? #163

xtuc opened this issue Oct 10, 2017 · 8 comments

Comments

@xtuc
Copy link

xtuc commented Oct 10, 2017

This is a feature request.

It would be great to have a variable system in the Linuxkit configuration file.

Of course an alternative is to use sed before building the image but I don't want to do that.

- Use case

My VM is in a custom network where 1.2.3.4 is the ip of my host. As you can see in my example, a DNS server and a Docker registry are bind to that ip.

linuxkit.yml:

services:
[...]
files:
  - path: /etc/docker/daemon.json
    contents: |
      {
        "insecure-registries": ["1.2.3.4:5000"],
        "dns": ["1.2.3.4"]
      }

My idea is to use a variables or args key in the configuration and then be able to reference them, like in the following example:

linuxkit.yml:

variables:
  hostip: "1.2.3.4"

services:
[...]
files:
  - path: /etc/docker/daemon.json
    contents: |
      {
        "insecure-registries": ["${hostip}:5000"],
        "dns": ["${hostip}"]
      }

Technically it could be a first pass during configuration parsing to "search and replace" these pattern. Another solution would be to replace them as you need to use the values but that would add unnecessary to every piece of the codebase.

If you don't want the replacement, you should be able to escape by adding a backslash before: \${hostip}.

Edit:
i'm using a Docker daemon to be able to start arbitrary images dynamically in the VM. Not a weird hack.

- A picture of a cute animal (not mandatory but encouraged)

cute whale

@justincormack
Copy link
Collaborator

This has come up before, and it is still unclear what the best answer is and we don't really want to commit to a templating system too early.

For many use cases, you can use Yaml aliases. For example the bit below reuses the capabilities between two services:

onshutdown:
  - name: shutdown
    image: busybox:latest
    command: ["/bin/echo", "so long and thanks for all the fish"]
    capabilities: &CAPS ["CAP_NET_BIND_SERVICE", "CAP_CHOWN", "CAP_SETUID", "CAP_SETGID", "CAP_DAC_OVERRIDE"]
services:
  - name: rngd
    image: linuxkit/rngd:6565ae49f6be29d4e64614a4df3978b972956ebf
  - name: nginx
    image: nginx:alpine
    capabilities: *CAPS

I am not sure you can template strings with aliases in yaml though. You may be better off just using a file from the host, you can do

files:
  - path: /etc/docker/daemon.json
    source: daemon.json

and just put the right IPs in on the host.

@ijc
Copy link
Collaborator

ijc commented Oct 10, 2017

You can also put just the dynamic bit in a separate file which you generate at build time (using whatever you would have used to set the variables) and then do moby build linux.yml dynamic.yml. That works well if what you want to do is add a new thing to the files section or add a whole new service (see projects/kubernetes for an example of doing both of these). It won't work if you want/need to replace or modify an service from the first file in the second though.

@xtuc
Copy link
Author

xtuc commented Oct 10, 2017

@justincormack

I didn't find the previous discussions about that (that's why I opened a new issue).

For many use cases, you can use Yaml aliases

YAML value aliases are good but as you mentioned string concatenation is not possible.

@ijc

You can also put just the dynamic bit in a separate file

That's a good idea, but unfortunately my configuration is spread across files and services currently.


Another solution that came to my mind is to use a custom metadata server (kinda like with AWS or GCP platforms) and write configuration at runtime. This will slowdown the overall boot time and I would be forced to have an dedicated and available IP/service everywhere. It's not really practical.

What do you think about a new tool to generate a templated config? So that we don't integrate it to the core and you can just stop maintaining at some point if it turns out to be a bad idea.
It would be a more standart sed.

@ijc
Copy link
Collaborator

ijc commented Oct 10, 2017

That's a good idea, but unfortunately my configuration is spread across files and services currently.

I'm not sure if you are adding or modify services, but to clarify, you can add entirely new services in the second/third yaml file, you just can't (easily) change the properties of a service defined in one yml file using a later (in moby command line order) file.

The projects/kube example uses that technique to add either a docker or cri-containerd service to a base depending on the requested runtime.

Another solution that came to my mind is to use a custom metadata server

Maybe pkg/metadata could be augmented with a new "static file" provider, so instead of going to the network it would just "retrieve" the file from a known location inside the image itself (which you could then add files files)?

It would be a more standart sed.

By coincidence I was looking for a YML equivalent of jq (which targets json) earlier. I found yq which looks promising but haven't tried it yet.

Perhaps it could provide the level of external templating needed?

@xtuc
Copy link
Author

xtuc commented Oct 10, 2017

I'm not sure if you are adding or modify services

Sorry I meant modifying existing services, I could re-declare them in each additional file but it will be tedious to manage later.

The metadata based on a file is not dynamic enough for me. Part of the issue is that in my case I will end up with one additional config file per machine, as I said before it would be tedious to manage.

I will give yq a try, thanks. I will let you know.

@xtuc
Copy link
Author

xtuc commented Oct 14, 2017

@ijc yq does only help you navigate in the YAML as an object. I cannot really implement a templating engine.

I ended up implementing a metadata server (very similar to the AWS one). It's currently written in Bash and lives in its own image.

I still have some configuration duplicated in the file but it's manageable.

@mmariani
Copy link

I have previously used https://github.com/wrouesnel/p2cli
Basically it renders a https://github.com/flosch/pongo2 template and you can provide variables however you want: envvar, json, yaml.
Dockerfile here: wrouesnel/p2cli#9

Then having rewritten the bash scripts to Python, I've switched to Jinja2 which is very similar but more complete.

@justincormack
Copy link
Collaborator

Should be moved to linuxkit repo.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants