Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Assemble templates using the new base setting #3072

Merged
merged 14 commits into from
Mar 4, 2025

Conversation

jandubois
Copy link
Member

@jandubois jandubois commented Jan 1, 2025

This PR creates initial support for multi-file templates, mostly based on the suggestions I gave in #2520 (reply in thread).

Instance create vs. start stages

The basic idea behind "template embedding" is that when an instance is created, the lima.yaml that is stored in the instance directory will embed settings from additional
base template(s) and external scripts into a single composite document.

Once the instance is created, there are no longer external references and the instance can be started while offline, even if it was created from online template fragments.

Merging default settings from base templates

Merging of templates is controlled by the new base property, which takes the name of
a base template, e.g.

base: template://docker

It is expected that in most instances only a single base template is needed, but it is possible to provide a list:

base:
- variables.yaml
- http://example.com/template.yaml

The base template can in turn have their own base templates. For example my.yaml instance may be based on template://docker, which in turn could be based on template://ubuntu.

Merging is performed by copying every property from the base template that does not yet exist in the main template. For list properties the lists are appended. More details and exceptions are documented below.

Embedding of external provisioning scripts

Both provisioning scripts and probe scripts can now be located with the new file property specifying a template locator (details below). The file will be loaded and inlined under the script property. Therefore file and script are mutually exclusive.

provision:
- mode: user
  file: my-script.sh
probes:
- file: template://docker-probe.sh

Relative template locators

The values of the base and file properties are "template locators". They are the usual local filenames or file://, https://, or template://URLs.

In addition they can also be relative locators: names that don't have a URL scheme and don't start with a /. These names are resolved relative to the template in which they occur (similar to relative href properties in HTML).

base: base.yaml
provision:
- file: script.sh

If this template is loaded as templates/main.yaml, then the referenced template files will be fetched from templates/base.yaml and templates/script.sh.

If the template is loaded as template://main, then the files will be template://base.yaml and template://script.sh.

This means a template using relative locators will always fetch dependencies from the same (relative) location regardless of how it was loaded itself.

To make this work template://base.yaml needs to be equivalent to template://base. And it must be possible to use other file extensions, so template://script.sh loads the script and doesn't look for script.sh.yaml.

limactl template command

This PR adds new options to the limactl template copy subcommand.

  • --verbatim copies a file exactly as is.

  • --embed will merge in all external base templates and shell scripts.

  • --embed-all will also merge in templates and files referenced by template:// URLs.

  • --fill will apply override.yaml, default.yaml, and builtin defaults.

Without additional options the copy command will copy the file, but turn any relative locators into absolute locators. So the copy of the template will continue to reference the same base templates and scripts. Use the --verbatim option if you intend to copy those files locally as well.

Examples

Embedding a script

Merging in template://default

Detailed merging algorithm

Each template will recusively embed all dependencies in its base templates before merging them in.

Then each property, that does not exist in the main template will be copied over from the base template.

Properties that are lists are appended.

For provision and probes the order is reversed: the base entries are inserted before the main template entries, so that latter are executed last (see #2932 for discussion).

Special rules

The dns entries are not merged. The entries from a base template are only copied when the main template list is empty.

mountTypesSupported will have any duplicate entries removed.

The base property is removed if the base template has been embedded.

For provision and probes the file property is removed, and the actual content of the script is stored in the usual script property.

For minimumLimaVersion and vmOpts.qemy.minimumVersion the values are compared. and the base version is only copied when it is greater than the main version.

Combining list entries

Three list properties (additionalDisks, mounts, and networks) use combining logic based on a unique key (disk name, mount point, and interface name, respectively).

If a latter entry matches the key of an earlier entry, then any missing fields in the earlier entry are filled in from the latter entry, which is then deleted. This matches the logic already used for merging override.yaml and default.yaml.

There is a new wildcard feature now, where * will match any existing key, so can be used to provide defaults for all entries. This is mostly in preparation to use this mechanism for the builtin defaults.

For the combining list mechanism to work, all base templates must be merged (so all lists must contain the complete set of entries). Otherwise the key matching mechanism wouldn't work globally, but only for the parent template at each level.

@jandubois
Copy link
Member Author

This PR still needs some integration tests, but I wanted to create it before 2024 was over. 😄

@jandubois jandubois force-pushed the based-on branch 3 times, most recently from 757d8f3 to 4303fd9 Compare January 1, 2025 07:08
@jandubois jandubois force-pushed the based-on branch 4 times, most recently from b029e31 to d1fe948 Compare February 16, 2025 07:32
@jandubois jandubois changed the title Assemble templates using the new basedOn setting Assemble templates using the new base setting Feb 16, 2025
@jandubois jandubois force-pushed the based-on branch 6 times, most recently from 14b6902 to 4174183 Compare February 17, 2025 01:15
@jandubois jandubois marked this pull request as ready for review February 17, 2025 01:42
@jandubois
Copy link
Member Author

@AkihiroSuda I believe I've addressed all your code review feedback so far, as well as all the implications from our discussion about digest support (the schema has been updated, but the digest computation/checking is left for a future PR).

I've rebased this PR since you originally reviewed it, but any further changes are all in separate commits. I've not yet squashed them, in case it makes it easier for you to continue the review; but let me know if you prefer that I squash them now!

@jandubois
Copy link
Member Author

I will briefly to turn this into Draft mode again because I think there is another condition in useAbsLocators that is not fully implemented, and I need to figure out how to add a test for it.

@jandubois jandubois marked this pull request as draft February 18, 2025 18:22
@jandubois jandubois force-pushed the based-on branch 2 times, most recently from 71b28dd to af64433 Compare February 19, 2025 06:37
@jandubois jandubois marked this pull request as ready for review February 19, 2025 06:39
@jandubois
Copy link
Member Author

I had to rebase the PR to resolve the merge conflict with recent changes to pkg/limayaml/marshal.go. There are no other changes.

@AkihiroSuda AkihiroSuda requested a review from a team February 28, 2025 03:49
@AkihiroSuda
Copy link
Member

Let's merge, after another rebase to add the licensing boilerplate

@jandubois
Copy link
Member Author

Let's merge, after another rebase to add the licensing boilerplate

Rebased and copyright headers added...

jandubois added 13 commits March 3, 2025 12:18
It allows a template to be constructed by merging values from
one or more base templates together. This merge process will
maintain all comments from both the template and the bases.

The template is assembled before an instance is created, and
only the combined template is stored as lima.yaml in the instance
directory.

There merging semantics are otherwise similar to how lima.yaml
is combined with override.yaml, defaults.yaml, and the builtin
default values.

Signed-off-by: Jan Dubois <[email protected]>
Signed-off-by: Jan Dubois <[email protected]>
The default `copy --embed` option will no longer embed template:// urls.

Signed-off-by: Jan Dubois <[email protected]>
Instead of `base: template.yaml` the user can write:

```yaml
base:
- url: template.yaml
  digest: decafbad
```

Same thing for `file` properties of provisoning scripts and probes.

The digest values are currently being ignored; verification will happen
in a later PR.

Signed-off-by: Jan Dubois <[email protected]>
This is an integration test for the `base:` mechanism, and also updates
the images used by `test-misc` to match the latest updates.

Unrelated: also adds a test for setting the user shell

Signed-off-by: Jan Dubois <[email protected]>
because digest validation is not yet implemented.

Also adds missing unmarshalling for `base: {file: URL}` and related tests.

Signed-off-by: Jan Dubois <[email protected]>
@jandubois jandubois requested a review from AkihiroSuda March 3, 2025 21:29
Copy link
Member

@AkihiroSuda AkihiroSuda left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks

@AkihiroSuda AkihiroSuda merged commit 47ace06 into lima-vm:master Mar 4, 2025
31 checks passed
@AkihiroSuda
Copy link
Member

Created release/1.0 branch before merging this PR, so that we can release v1.0.x if we need

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

Successfully merging this pull request may close these issues.

3 participants