Skip to content

Handle uninstantiated template quadlets#28380

Open
simonbrauner wants to merge 1 commit into
containers:mainfrom
simonbrauner:issue-26960
Open

Handle uninstantiated template quadlets#28380
simonbrauner wants to merge 1 commit into
containers:mainfrom
simonbrauner:issue-26960

Conversation

@simonbrauner
Copy link
Copy Markdown
Contributor

@simonbrauner simonbrauner commented Mar 26, 2026

Checklist

Ensure you have completed the following checklist for your pull request to be reviewed:

  • Certify you wrote the patch or otherwise have the right to pass it on as an open-source patch by signing all
    commits. (git commit -s). (If needed, use git commit -s --amend). The author email must match
    the sign-off email address. See CONTRIBUTING.md
    for more information.
  • Referenced issues using Fixes: #00000 in commit message (if applicable)
  • Tests have been added/updated (or no tests are needed)
  • Documentation has been updated (or no documentation changes are needed)
  • All commits pass make validatepr (format/lint checks)
  • Release note entered in the section below (or None if no user-facing changes)

Does this PR introduce a user-facing change?

`podman quadlet list` and `podman quadlet rm` works with uninstantiated templates`

@simonbrauner
Copy link
Copy Markdown
Contributor Author

The issue proposes to disregard template files, so this would be a quick fix.

diff --git a/pkg/domain/infra/abi/quadlet.go b/pkg/domain/infra/abi/quadlet.go
index 34652ebbc4..c8a4dc24ed 100644
--- a/pkg/domain/infra/abi/quadlet.go
+++ b/pkg/domain/infra/abi/quadlet.go
@@ -708,6 +708,12 @@ func (ic *ContainerEngine) QuadletList(ctx context.Context, options entities.Qua
                        reports = append(reports, &report)
                        continue
                }
+
+               if strings.Contains(serviceName, "@.") {
+                       // Template file, skipping
+                       continue
+               }
+
                partialReports[serviceName] = report
                allServiceNames = append(allServiceNames, serviceName)
        }

I will try to use a different way to query systemd, so that templates could also be included in the listing.

@simonbrauner simonbrauner force-pushed the issue-26960 branch 2 times, most recently from 64918ba to 8194502 Compare March 30, 2026 10:33
@simonbrauner simonbrauner force-pushed the issue-26960 branch 3 times, most recently from e27140d to 28a5a12 Compare April 14, 2026 09:28
@simonbrauner simonbrauner changed the title Handle template files in quadlet list Handle uninstantiated template quadlets Apr 14, 2026
@simonbrauner simonbrauner force-pushed the issue-26960 branch 2 times, most recently from c20f56e to 9266aa5 Compare April 15, 2026 11:25
@packit-as-a-service
Copy link
Copy Markdown

[NON-BLOCKING] Packit jobs failed. @containers/packit-build please check. Everyone else, feel free to ignore.

@simonbrauner simonbrauner marked this pull request as ready for review April 15, 2026 12:46
@simonbrauner simonbrauner force-pushed the issue-26960 branch 2 times, most recently from bd08c84 to 36d7f3c Compare April 20, 2026 14:40
@packit-as-a-service
Copy link
Copy Markdown

tmt tests failed for commit 36d7f3c. @lsm5, @psss, @thrix please check.

}
}

if len(templateServiceNames) != 0 {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

There can still be running instances of the templates removed, right? I wonder if we should distinguish between the removal of concrete services and templated ones. Because while concrete services are stopped before they are removed, it's not the same for template services, and iiuc the user can't really tell the difference while running podman quadlet rm <concrete_svc> <template_svc>, unless I'm missing something.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, that is right. I documented it that way

When the argument is uninstantiated template quadlet, this command removes the
template quadlet file (e.g. `templateName@.container`) and the generated systemd
template unit (e.g. `templateName@.service`, unless **--reload-systemd** is set to `false`).
Instances of the systemd template unit (e.g. `templateName@instanceName.service`)
may persist, and can be removed with **systemctl(1)**.

It seemed reasonable to do it this way for the minimal fix of the issue, but there could be a follow up which elaborates on this.

On one hand, perhaps it would be nice to help users to manage instances, but there are plenty of ways how instances can be created:

  • from a file which has instance name already - podman quadlet install templateName@instanceName.container
  • by creating a symlink to template name in ~/.config/containers/systemd/
  • DefaultInstance
  • systemctl --user start
  • Systemd dependency (Wants key for example)

so it could be messy to cover all the cases.

On the other hand, instances of templates could be even considered out of scope, as quadlets are about generating services, and what the services are used for is responsibility of systemd. So from this point of view - my fix is consistent, it removes the .container file and the .service file generated from it for both concrete units and templates.

Comment thread docs/source/markdown/podman-quadlet-list.1.md.in Outdated
Comment thread pkg/systemd/quadlet/quadlet.go Outdated
@packit-as-a-service
Copy link
Copy Markdown

tmt tests failed for commit c3ecb25. @lsm5, @psss, @thrix please check.

@simonbrauner
Copy link
Copy Markdown
Contributor Author

/packit rebuild-failed

@packit-as-a-service
Copy link
Copy Markdown

[NON-BLOCKING] Packit jobs failed. @containers/packit-build please check. Everyone else, feel free to ignore.

@simonbrauner
Copy link
Copy Markdown
Contributor Author

/packit rebuild-failed

@packit-as-a-service
Copy link
Copy Markdown

tmt tests failed for commit c3ecb25. @lsm5, @psss, @thrix please check.

@psss
Copy link
Copy Markdown

psss commented May 4, 2026

tmt tests failed for commit c3ecb25. @lsm5, @psss, @thrix please check.

Should be fixed once rebased on the latest main.

@simonbrauner
Copy link
Copy Markdown
Contributor Author

simonbrauner commented May 4, 2026

Removing all instances when template is removed could be tricky as sleep@1.service is an instance of template:

sleep@1.service - A templated sleepy container
   Loaded: loaded (/home/sbrauner/.config/containers/systemd/sleep@.container; generated)

but sleep@2.service is just a service which supports the %i substitution but otherwise works just as regular concrete service and is not related to sleep@.container at all:

sleep@2.service - A templated sleepy container
   Loaded: loaded (/home/sbrauner/.config/containers/systemd/sleep@2.container; generated)

https://0pointer.de/blog/projects/instances.html

I'll try to solve it by looking at the SourcePath property in systemd.

@mheon mheon added the 6.0 Breaking changes for Podman 6.0 label May 4, 2026
@simonbrauner simonbrauner marked this pull request as draft May 5, 2026 13:18
@simonbrauner simonbrauner marked this pull request as ready for review May 6, 2026 16:27
@simonbrauner
Copy link
Copy Markdown
Contributor Author

simonbrauner commented May 6, 2026

I changed rm in a way that it fails when there are running instances of template if --force is not set, and it tries to remove the instances if --force is set.

@packit-as-a-service
Copy link
Copy Markdown

[NON-BLOCKING] Packit jobs failed. @containers/packit-build please check. Everyone else, feel free to ignore.

Comment thread test/system/253-podman-quadlet.bats
Comment thread pkg/domain/infra/abi/quadlet.go Outdated
continue
}

if sourcePath == templateQuadletPath {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I would consider using filepath.Clean.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

Comment thread pkg/domain/infra/abi/quadlet.go Outdated
report.UnitName = templateServiceName

if _, ok := unitFilesFound[templateServiceName]; ok {
report.Status = "loaded template"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I would define Status as constants.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

Comment thread pkg/domain/infra/abi/quadlet.go
@simonbrauner simonbrauner marked this pull request as draft May 13, 2026 06:52
@simonbrauner simonbrauner force-pushed the issue-26960 branch 2 times, most recently from 071ffed to be7265c Compare May 14, 2026 11:48
Comment thread pkg/domain/infra/abi/quadlet.go
@simonbrauner simonbrauner force-pushed the issue-26960 branch 6 times, most recently from b192bec to 28c1ce4 Compare May 14, 2026 15:28
@simonbrauner simonbrauner marked this pull request as ready for review May 14, 2026 15:28
Copy link
Copy Markdown
Member

@Honny1 Honny1 left a comment

Choose a reason for hiding this comment

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

I didn't check the CI failures, but they seem to be serious. Also, please check the REST API to see if there are any actions for updates.


// Uninstantiated template units need to be handled separately, because
// ListUnitsBy* functions do not return anything for templates.
unitFiles, err := conn.ListUnitFilesByPatternsContext(ctx, []string{}, templateServiceNames)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What happens if templateServiceNames is empty? Will ListUnitFilesByPatternsContext list all unitFiles or empty unitFiles?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

templateServiceNames []
NAME        UNIT NAME   PATH ON DISK  STATUS      APPLICATION  POD

ListUnitFilesByPatternsContext returns units matched by at least one pattern, so empty list of templateServiceNames means that there are no patterns, so nothing will match.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We don't need to list unit files when templateServiceNames is empty.

as input and removes all the Quadlets which belongs to that specific application.

When the argument is uninstantiated template quadlet, this command removes the template quadlet file (e.g. `templateName@.container`) and the generated systemd template unit (e.g. `templateName@.service`). If there are running instances of that systemd template, the command fails if **--force** option is not set, and tries to remove the instances if **--force** option is set. Instances which were not running may persist, and can be removed with **systemctl(1)**.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
Flag `--force` stops active instances of the template so removal can proceed. It does not disable or remove instance units (e.g. `foo@bar.service`). Use `systemctl(1)` to disable or reset instances that remain after the template quadlet is removed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I don't know whether this is accurate.

so removal can proceed it is not that the template removal could not proceed with running instances, it's just that user probably does not want to remove definition of something that is running.

disable or reset instances enable/disable does not work because the service is transient or generated. Restart does not work, as systemd does not have anything to reload from. I don't know if there is something reasonable to do with systemctl, so I'm thinking, maybe I should just get rid of the systemctl(1) bit and only say that if --force then stop_instances else fail?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Sure, it is better.

@simonbrauner simonbrauner marked this pull request as draft May 15, 2026 11:37
@simonbrauner simonbrauner force-pushed the issue-26960 branch 3 times, most recently from 26bb0c4 to 09dd82a Compare May 18, 2026 12:01
Fixes: containers#26960

Signed-off-by: Šimon Brauner <sbrauner@redhat.com>
@github-actions github-actions Bot added the kind/api-change Change to remote API; merits scrutiny label May 18, 2026
@simonbrauner
Copy link
Copy Markdown
Contributor Author

@Honny1

I didn't check the CI failures, but they seem to be serious.

Starting the container from the test didn't work, so I removed that part.

please check the REST API to see if there are any actions for updates.

This is just a bugfix, the functionality is the same (just extended to templates), maybe except for the semantics of removing a template, so I addressed that specifically.

@simonbrauner simonbrauner marked this pull request as ready for review May 18, 2026 13:10
@Luap99 Luap99 removed the 6.0 Breaking changes for Podman 6.0 label May 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind/api-change Change to remote API; merits scrutiny

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants