Skip to content

Commit 3e5da4c

Browse files
committed
quadlet install: multiple quadlets from single file should share app
Quadlets installed from `.quadlet` file now belongs to a single application, anyone file removed from this application removes all the other files as well. Signed-off-by: flouthoc <flouthoc.git@gmail.com>
1 parent 5e8c0b9 commit 3e5da4c

File tree

3 files changed

+75
-2
lines changed

3 files changed

+75
-2
lines changed

docs/source/markdown/podman-quadlet-install.1.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ This command allows you to:
1818

1919
* Install multiple Quadlets from a single file with `.quadlets` extension where each Quadlet is separated by a `---` delimiter. When using multiple quadlets in a single file, each quadlet section must include a `# FileName=<name>` comment to specify the name for that quadlet.
2020

21-
Note: If a quadlet is part of an application, removing that specific quadlet will remove the entire application. When a quadlet is installed from a directory, all files installed from that directory—including both quadlet and non-quadlet files—are considered part of a single application.
21+
Note: If a quadlet is part of an application, removing that specific quadlet will remove the entire application. When a quadlet is installed from a directory, all files installed from that directory—including both quadlet and non-quadlet files—are considered part of a single application. Similarly, when multiple quadlets are installed from a single `.quadlets` file, they are all considered part of the same application.
2222

2323
Note: In case user wants to install Quadlet application then first path should be the path to application directory.
2424

pkg/domain/infra/abi/quadlet.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,15 @@ func (ic *ContainerEngine) QuadletInstall(ctx context.Context, pathsOrURLs []str
164164
for _, toInstall := range paths {
165165
validateQuadletFile := false
166166
if assetFile == "" {
167-
assetFile = "." + filepath.Base(toInstall) + ".asset"
167+
// Check if this is a .quadlets file - if so, treat as an app
168+
ext := strings.ToLower(filepath.Ext(toInstall))
169+
if ext == ".quadlets" {
170+
// For .quadlets files, use .app extension to group all quadlets as one application
171+
baseName := strings.TrimSuffix(filepath.Base(toInstall), filepath.Ext(toInstall))
172+
assetFile = "." + baseName + ".app"
173+
} else {
174+
assetFile = "." + filepath.Base(toInstall) + ".asset"
175+
}
168176
validateQuadletFile = true
169177
}
170178
switch {
@@ -385,6 +393,14 @@ func (ic *ContainerEngine) installQuadlet(_ context.Context, path, destName, ins
385393
if err != nil {
386394
return "", fmt.Errorf("error while writing non-quadlet filename: %w", err)
387395
}
396+
} else if strings.HasSuffix(assetFile, ".app") {
397+
// For quadlet files that are part of an application (indicated by .app extension),
398+
// also write the quadlet filename to the .app file for proper application tracking
399+
quadletName := filepath.Base(finalPath)
400+
err := appendStringToFile(filepath.Join(installDir, assetFile), quadletName)
401+
if err != nil {
402+
return "", fmt.Errorf("error while writing quadlet filename to app file: %w", err)
403+
}
388404
}
389405
return finalPath, nil
390406
}

test/system/254-podman-quadlet-multi.bats

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,3 +180,60 @@ EOF
180180
run_podman 125 quadlet install $multi_quadlet_file
181181
assert "$output" =~ "missing required.*FileName" "error should mention missing FileName"
182182
}
183+
184+
@test "quadlet verb - multi-quadlet file creates application" {
185+
# Test that quadlets from a .quadlets file are treated as part of the same application
186+
local install_dir=$(get_quadlet_install_dir)
187+
local multi_quadlet_file=$PODMAN_TMPDIR/myapp.quadlets
188+
189+
cat > $multi_quadlet_file <<EOF
190+
# FileName=webapp
191+
[Container]
192+
Image=$IMAGE
193+
ContainerName=webapp
194+
PublishPort=8080:80
195+
196+
---
197+
198+
# FileName=webdb
199+
[Volume]
200+
Label=app=myapp
201+
EOF
202+
203+
# Install the multi-quadlet file
204+
run_podman quadlet install $multi_quadlet_file
205+
206+
# Verify both quadlets were installed
207+
assert "$output" =~ "webapp.container" "install output should contain webapp.container"
208+
assert "$output" =~ "webdb.volume" "install output should contain webdb.volume"
209+
210+
# Check that the .app file was created (not individual .asset files)
211+
[[ -f "$install_dir/.myapp.app" ]] || die ".myapp.app file should exist"
212+
[[ ! -f "$install_dir/.webapp.container.asset" ]] || die "individual .asset files should not exist"
213+
[[ ! -f "$install_dir/.webdb.volume.asset" ]] || die "individual .asset files should not exist"
214+
215+
# Verify the .app file contains both quadlet names
216+
run cat "$install_dir/.myapp.app"
217+
assert "$output" =~ "webapp.container" ".app file should contain webapp.container"
218+
assert "$output" =~ "webdb.volume" ".app file should contain webdb.volume"
219+
220+
# Test quadlet list to verify both quadlets show the same app name
221+
run_podman quadlet list
222+
local webapp_line=$(echo "$output" | grep "webapp.container")
223+
local webdb_line=$(echo "$output" | grep "webdb.volume")
224+
225+
# Both lines should contain the same app name (.myapp.app)
226+
assert "$webapp_line" =~ "\\.myapp\\.app" "webapp should show .myapp.app as app"
227+
assert "$webdb_line" =~ "\\.myapp\\.app" "webdb should show .myapp.app as app"
228+
229+
# Test removing the application by removing one quadlet should remove both
230+
run_podman quadlet rm webapp.container
231+
232+
# Both quadlets should be removed since they're part of the same app
233+
run_podman quadlet list
234+
assert "$output" !~ "webapp.container" "webapp.container should be removed"
235+
assert "$output" !~ "webdb.volume" "webdb.volume should also be removed as part of same app"
236+
237+
# The .app file should also be removed
238+
[[ ! -f "$install_dir/.myapp.app" ]] || die ".myapp.app file should be removed"
239+
}

0 commit comments

Comments
 (0)