Skip to content

Commit bb6dec4

Browse files
committed
quadlet: Support [Install] for templated units
For a base template like `[email protected]` the WantedBy and RequiredBy keys does nothing. However, if a DefaultInstance= key is specified that is used by default. However, even if the DefaultInstance= is not given, the Install section is still useful, because you can instantiate the generic template by making a symlink for it, and that symlink will then pick up the instance id. So, for example, this [email protected] will not enable anything on boot. ``` [Container] Image=foo Exec=sleep 100 [Install] WantedBy=other.container ``` But if you have a symlink '[email protected]` -> `[email protected]' then the `foo@instance` service will be marked as wanted by `other`. In addition, even if the main template doesn't have an Install section, you can instantiate it with a symlink like above, and then enabling it using a dropin file like [email protected]/install.conf containing: ``` [Install] WantedBy=other.container ``` Signed-off-by: Alexander Larsson <[email protected]>
1 parent 7e1942e commit bb6dec4

File tree

1 file changed

+27
-10
lines changed

1 file changed

+27
-10
lines changed

cmd/quadlet/main.go

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -345,19 +345,36 @@ func enableServiceFile(outputPath string, service *parser.UnitFile) {
345345
symlinks = append(symlinks, filepath.Clean(alias))
346346
}
347347

348-
wantedBy := service.LookupAllStrv(quadlet.InstallGroup, "WantedBy")
349-
for _, wantedByUnit := range wantedBy {
350-
// Only allow filenames, not paths
351-
if !strings.Contains(wantedByUnit, "/") {
352-
symlinks = append(symlinks, fmt.Sprintf("%s.wants/%s", wantedByUnit, service.Filename))
348+
serviceFilename := service.Filename
349+
templateBase, templateInstance := service.GetTemplateParts()
350+
351+
// For non-instantiated template service we only support installs if a
352+
// DefaultInstance is given. Otherwise we ignore the Install group, but
353+
// it is still useful when instantiating the unit via a symlink.
354+
if templateBase != "" && templateInstance == "" {
355+
if defaultInstance, ok := service.Lookup(quadlet.InstallGroup, "DefaultInstance"); ok {
356+
parts := strings.SplitN(templateBase, "@", 2)
357+
serviceFilename = parts[0] + "@" + defaultInstance + parts[1]
358+
} else {
359+
serviceFilename = ""
353360
}
354361
}
355362

356-
requiredBy := service.LookupAllStrv(quadlet.InstallGroup, "RequiredBy")
357-
for _, requiredByUnit := range requiredBy {
358-
// Only allow filenames, not paths
359-
if !strings.Contains(requiredByUnit, "/") {
360-
symlinks = append(symlinks, fmt.Sprintf("%s.requires/%s", requiredByUnit, service.Filename))
363+
if serviceFilename != "" {
364+
wantedBy := service.LookupAllStrv(quadlet.InstallGroup, "WantedBy")
365+
for _, wantedByUnit := range wantedBy {
366+
// Only allow filenames, not paths
367+
if !strings.Contains(wantedByUnit, "/") {
368+
symlinks = append(symlinks, fmt.Sprintf("%s.wants/%s", wantedByUnit, serviceFilename))
369+
}
370+
}
371+
372+
requiredBy := service.LookupAllStrv(quadlet.InstallGroup, "RequiredBy")
373+
for _, requiredByUnit := range requiredBy {
374+
// Only allow filenames, not paths
375+
if !strings.Contains(requiredByUnit, "/") {
376+
symlinks = append(symlinks, fmt.Sprintf("%s.requires/%s", requiredByUnit, serviceFilename))
377+
}
361378
}
362379
}
363380

0 commit comments

Comments
 (0)