Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cmd/podman/quadlet/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ func installFlags(cmd *cobra.Command) {
flags := cmd.Flags()
flags.BoolVar(&installOptions.ReloadSystemd, "reload-systemd", true, "Reload systemd after installing Quadlets")
flags.BoolVarP(&installOptions.Replace, "replace", "r", false, "Replace the installation even if the quadlet already exists")
flags.StringVar(&installOptions.Application, "application", "", "Group quadlets and associated file in a directory named after the application")
_ = quadletInstallCmd.RegisterFlagCompletionFunc("application", completion.AutocompleteNone)
}

func init() {
Expand Down
6 changes: 4 additions & 2 deletions cmd/podman/quadlet/remove.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@ var (
quadletRmDescription = `Remove one or more installed Quadlets from the current user`

quadletRmCmd = &cobra.Command{
Use: "rm [options] QUADLET [QUADLET...]",
Use: "rm [options] [QUADLET|APPLICATION...]",
Short: "Remove Quadlets",
Long: quadletRmDescription,
RunE: rm,
ValidArgsFunction: common.AutocompleteQuadlets,
Example: `podman quadlet rm test.container
podman quadlet rm --force mysql.container
podman quadlet rm --all --reload-systemd=false`,
podman quadlet rm --all --reload-systemd=false
podman quadlet rm --recursive djangoapp`,
}

removeOptions entities.QuadletRemoveOptions
Expand All @@ -35,6 +36,7 @@ func rmFlags(cmd *cobra.Command) {
flags.BoolVarP(&removeOptions.All, "all", "a", false, "Remove all Quadlets for the current user")
flags.BoolVarP(&removeOptions.Ignore, "ignore", "i", false, "Do not error for Quadlets that do not exist")
flags.BoolVar(&removeOptions.ReloadSystemd, "reload-systemd", true, "Reload systemd after removal")
flags.BoolVar(&removeOptions.Recursive, "recursive", false, "Remove all Quadlets belonging to the specified application and its directory")
}

func init() {
Expand Down
2 changes: 1 addition & 1 deletion cmd/quadlet/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ func process() bool {
Debugf("Starting quadlet-generator, output to: %s", outputPath)
}

sourcePathsMap := quadlet.GetUnitDirs(isUserFlag)
sourcePathsMap := quadlet.GetUnitDirs(isUserFlag, true)

var units []*parser.UnitFile
for _, d := range sourcePathsMap {
Expand Down
21 changes: 17 additions & 4 deletions docs/source/markdown/podman-quadlet-install.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,29 @@ This command allows you to:

* Install a single Quadlet file, optionally followed by additional non-Quadlet files.

* Specify a directory containing multiple Quadlet files and other non-Quadlet files for installation ( example a config file for a quadlet container ).
* Specify a directory containing multiple Quadlet files and other non-Quadlet files for installation (for example a config file for a quadlet container).

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

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.
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.

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

## OPTIONS

#### **--application**=*string*

You can specify an application name, all files will be installed under a
directory with the application name. The application name is required when
specifying a directory path. An application name can't have a quadlet extension
as suffix. For example `foo.container` isn't a valid application name.

#### **--reload-systemd**

Reload systemd after installing Quadlets (default true).
Expand All @@ -48,7 +61,7 @@ $ podman quadlet install test-service-quadlet.container
Install quadlet from a dir.

```
$ podman quadlet install /home/user/work/quadlet-app/
$ podman quadlet install --application=foo /home/user/work/quadlet-app/
/home/user/.config/containers/systemd/myquadlet1.container
/home/user/.config/containers/systemd/myquadlet2.container
/install/path/myquadlet1.container
Expand Down
10 changes: 9 additions & 1 deletion docs/source/markdown/podman-quadlet-rm.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
podman\-quadlet\-rm - Removes an installed quadlet

## SYNOPSIS
**podman quadlet rm** [*options*] *quadlet* [*quadlet*]...
**podman quadlet rm** [*options*] *quadlet|application* [*quadlet|application*]...

## DESCRIPTION

Expand All @@ -29,6 +29,10 @@ Remove running quadlets.

Do not error for Quadlets that do not exist.

#### **--recursive**

Required when removing applications (default false).

#### **--reload-systemd**

Reload systemd after removing Quadlets (default true).
Expand All @@ -40,6 +44,10 @@ of this flag to `false`.
```
$ podman quadlet rm myquadlet.container
myquadlet.container
$ podman quadlet rm --recursive myapp
web.container
data.container
data.volume
```

## SEE ALSO
Expand Down
17 changes: 9 additions & 8 deletions pkg/api/handlers/libpod/quadlets.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,10 +180,10 @@ func InstallQuadlets(w http.ResponseWriter, r *http.Request) {

// Parse query parameters
query := struct {
Replace bool `schema:"replace"`
ReloadSystemd bool `schema:"reload-systemd"`
Replace bool `schema:"replace"`
ReloadSystemd bool `schema:"reload-systemd"`
Application string `schema:"application"`
}{
Replace: false,
ReloadSystemd: true, // Default to true like CLI
}

Expand Down Expand Up @@ -227,18 +227,15 @@ func InstallQuadlets(w http.ResponseWriter, r *http.Request) {
countQuadletFiles++
}
}
switch {
case countQuadletFiles > 1:
utils.Error(w, http.StatusBadRequest, fmt.Errorf("only a single quadlet file is allowed per request"))
return
case countQuadletFiles == 0:
if countQuadletFiles == 0 {
utils.Error(w, http.StatusBadRequest, fmt.Errorf("no quadlet files found in request"))
return
}

containerEngine := abi.ContainerEngine{Libpod: runtime}
installOptions := entities.QuadletInstallOptions{
Replace: query.Replace,
Application: query.Application,
ReloadSystemd: query.ReloadSystemd,
}

Expand Down Expand Up @@ -268,6 +265,7 @@ func RemoveQuadlet(w http.ResponseWriter, r *http.Request) {
Force bool `schema:"force"`
Ignore bool `schema:"ignore"`
ReloadSystemd bool `schema:"reload-systemd"`
Recursive bool `schema:"recursive"`
}{
ReloadSystemd: true, // Default to true like CLI
}
Expand All @@ -288,6 +286,7 @@ func RemoveQuadlet(w http.ResponseWriter, r *http.Request) {
Force: query.Force,
Ignore: query.Ignore,
ReloadSystemd: query.ReloadSystemd,
Recursive: query.Recursive,
}

removeReport, err := containerEngine.QuadletRemove(r.Context(), []string{name}, removeOptions)
Expand Down Expand Up @@ -324,6 +323,7 @@ func RemoveQuadlets(w http.ResponseWriter, r *http.Request) {
Force bool `schema:"force"`
Ignore bool `schema:"ignore"`
ReloadSystemd bool `schema:"reload-systemd"`
Recursive bool `schema:"recursive"`
Quadlets []string `schema:"quadlets"`
}{
ReloadSystemd: true, // Default to true like CLI
Expand Down Expand Up @@ -352,6 +352,7 @@ func RemoveQuadlets(w http.ResponseWriter, r *http.Request) {
All: query.All,
Ignore: query.Ignore,
ReloadSystemd: query.ReloadSystemd,
Recursive: query.Recursive,
}

removeReport, err := containerEngine.QuadletRemove(r.Context(), query.Quadlets, removeOptions)
Expand Down
4 changes: 4 additions & 0 deletions pkg/domain/entities/quadlet.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ type QuadletInstallOptions struct {
ReloadSystemd bool
// Replace the installation even if the quadlet already exists
Replace bool
// The application to install the quadlet to
Application string
}

// QuadletInstallReport contains the output of the `quadlet install` command
Expand Down Expand Up @@ -56,6 +58,8 @@ type QuadletRemoveOptions struct {
Ignore bool
// ReloadSystemd determines whether systemd will be reloaded after the Quadlet is removed.
ReloadSystemd bool
// You can specify recursive when targeting an application
Recursive bool
}

// QuadletRemoveReport contains the results of an operation to remove obe or more quadlets
Expand Down
Loading