mirror of
https://github.com/containers/podman.git
synced 2025-11-29 09:37:38 +08:00
cmd/podman: add replace flag to quadlet install
Signed-off-by: Celso Henrique Souza Silva <celsohenrique367@gmail.com> Fixes: #26930
This commit is contained in:
committed by
nothiaki
parent
b342596e1c
commit
0ea4eaee70
@@ -36,6 +36,7 @@ podman quadlet install https://github.com/containers/podman/blob/main/test/e2e/q
|
|||||||
func installFlags(cmd *cobra.Command) {
|
func installFlags(cmd *cobra.Command) {
|
||||||
flags := cmd.Flags()
|
flags := cmd.Flags()
|
||||||
flags.BoolVar(&installOptions.ReloadSystemd, "reload-systemd", true, "Reload systemd after installing Quadlets")
|
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")
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|||||||
@@ -28,6 +28,12 @@ Reload systemd after installing Quadlets (default true).
|
|||||||
In order to disable it users need to manually set the value
|
In order to disable it users need to manually set the value
|
||||||
of this flag to `false`.
|
of this flag to `false`.
|
||||||
|
|
||||||
|
#### **--replace**, **-r**
|
||||||
|
|
||||||
|
Replace the Quadlet installation even if the generated unit file already exists (default false).
|
||||||
|
In order to enable it, users need to manually set the value
|
||||||
|
of this flag to `true`. This flag is used primarily to update an existing unit.
|
||||||
|
|
||||||
## EXAMPLES
|
## EXAMPLES
|
||||||
|
|
||||||
Install quadlet from a file.
|
Install quadlet from a file.
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ package entities
|
|||||||
type QuadletInstallOptions struct {
|
type QuadletInstallOptions struct {
|
||||||
// Whether to reload systemd after installation is completed
|
// Whether to reload systemd after installation is completed
|
||||||
ReloadSystemd bool
|
ReloadSystemd bool
|
||||||
|
// Replace the installation even if the quadlet already exists
|
||||||
|
Replace bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// QuadletInstallReport contains the output of the `quadlet install` command
|
// QuadletInstallReport contains the output of the `quadlet install` command
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ func (ic *ContainerEngine) QuadletInstall(ctx context.Context, pathsOrURLs []str
|
|||||||
installReport.QuadletErrors[toInstall] = fmt.Errorf("populating temporary file: %w", err)
|
installReport.QuadletErrors[toInstall] = fmt.Errorf("populating temporary file: %w", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
installedPath, err := ic.installQuadlet(ctx, tmpFile.Name(), quadletFileName, installDir, assetFile, validateQuadletFile)
|
installedPath, err := ic.installQuadlet(ctx, tmpFile.Name(), quadletFileName, installDir, assetFile, validateQuadletFile, options.Replace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
installReport.QuadletErrors[toInstall] = err
|
installReport.QuadletErrors[toInstall] = err
|
||||||
continue
|
continue
|
||||||
@@ -210,7 +210,7 @@ func (ic *ContainerEngine) QuadletInstall(ctx context.Context, pathsOrURLs []str
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// If toInstall is a single file, execute the original logic
|
// If toInstall is a single file, execute the original logic
|
||||||
installedPath, err := ic.installQuadlet(ctx, toInstall, "", installDir, assetFile, validateQuadletFile)
|
installedPath, err := ic.installQuadlet(ctx, toInstall, "", installDir, assetFile, validateQuadletFile, options.Replace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
installReport.QuadletErrors[toInstall] = err
|
installReport.QuadletErrors[toInstall] = err
|
||||||
continue
|
continue
|
||||||
@@ -254,7 +254,7 @@ func getFileName(resp *http.Response, fileURL string) (string, error) {
|
|||||||
// Perform some minimal validation, but not much.
|
// Perform some minimal validation, but not much.
|
||||||
// We can't know about a lot of problems without running the Quadlet binary, which we
|
// We can't know about a lot of problems without running the Quadlet binary, which we
|
||||||
// only want to do once.
|
// only want to do once.
|
||||||
func (ic *ContainerEngine) installQuadlet(_ context.Context, path, destName, installDir, assetFile string, isQuadletFile bool) (string, error) {
|
func (ic *ContainerEngine) installQuadlet(_ context.Context, path, destName, installDir, assetFile string, isQuadletFile, replace bool) (string, error) {
|
||||||
// First, validate that the source path exists and is a file
|
// First, validate that the source path exists and is a file
|
||||||
stat, err := os.Stat(path)
|
stat, err := os.Stat(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -274,9 +274,15 @@ func (ic *ContainerEngine) installQuadlet(_ context.Context, path, destName, ins
|
|||||||
return "", fmt.Errorf("%q is not a supported Quadlet file type", filepath.Ext(finalPath))
|
return "", fmt.Errorf("%q is not a supported Quadlet file type", filepath.Ext(finalPath))
|
||||||
}
|
}
|
||||||
|
|
||||||
file, err := os.OpenFile(finalPath, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0o644)
|
var osFlags = os.O_CREATE | os.O_WRONLY
|
||||||
|
|
||||||
|
if !replace {
|
||||||
|
osFlags |= os.O_EXCL
|
||||||
|
}
|
||||||
|
|
||||||
|
file, err := os.OpenFile(finalPath, osFlags, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, fs.ErrExist) {
|
if errors.Is(err, fs.ErrExist) && !replace {
|
||||||
return "", fmt.Errorf("a Quadlet with name %s already exists, refusing to overwrite", filepath.Base(finalPath))
|
return "", fmt.Errorf("a Quadlet with name %s already exists, refusing to overwrite", filepath.Base(finalPath))
|
||||||
}
|
}
|
||||||
return "", fmt.Errorf("unable to open file %s: %w", filepath.Base(finalPath), err)
|
return "", fmt.Errorf("unable to open file %s: %w", filepath.Base(finalPath), err)
|
||||||
|
|||||||
@@ -461,4 +461,43 @@ EOF
|
|||||||
assert $status -eq 0 "quadlet rm --ignore should succeed even for non-existent quadlets"
|
assert $status -eq 0 "quadlet rm --ignore should succeed even for non-existent quadlets"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "quadlet install --replace" {
|
||||||
|
local install_dir=$(get_quadlet_install_dir)
|
||||||
|
# Create a test quadlet file
|
||||||
|
local quadlet_file=$PODMAN_TMPDIR/alpine-quadlet.container
|
||||||
|
local initial_exec='Exec=sh -c "echo STARTED CONTAINER; trap '\''exit'\'' SIGTERM; while :; do sleep 0.1; done"'
|
||||||
|
cat > $quadlet_file <<EOF
|
||||||
|
[Container]
|
||||||
|
Image=$IMAGE
|
||||||
|
$initial_exec
|
||||||
|
EOF
|
||||||
|
# Test quadlet install
|
||||||
|
run_podman quadlet install $quadlet_file
|
||||||
|
# Verify install output contains the quadlet name on a single line
|
||||||
|
assert "$output" =~ "alpine-quadlet.container" "install output should contain quadlet name"
|
||||||
|
|
||||||
|
# Without replace should fail
|
||||||
|
run_podman 125 quadlet install $quadlet_file
|
||||||
|
assert "$output" =~ "refusing to overwrite" "reinstall without --replace must fail with the overwrite error message"
|
||||||
|
|
||||||
|
cat > $quadlet_file <<EOF
|
||||||
|
[Container]
|
||||||
|
Image=$IMAGE
|
||||||
|
Exec=sh -c "echo STARTED CONTAINER UPDATED; trap 'exit' SIGTERM; while :; do sleep 0.1; done"
|
||||||
|
EOF
|
||||||
|
# With replace should pass and update quadlet
|
||||||
|
run_podman quadlet install --replace $quadlet_file
|
||||||
|
|
||||||
|
# Verify install output contains the quadlet name on a single line
|
||||||
|
assert "$output" =~ "alpine-quadlet.container" "install output should contain quadlet name"
|
||||||
|
|
||||||
|
run_podman quadlet print alpine-quadlet.container
|
||||||
|
|
||||||
|
assert "$output" !~ "$initial_exec" "Printed content must not show the initial version"
|
||||||
|
assert "$output" == "$(<$quadlet_file)" "Printed content must match the updated file content"
|
||||||
|
|
||||||
|
# Clean up
|
||||||
|
run_podman quadlet rm alpine-quadlet.container
|
||||||
|
}
|
||||||
|
|
||||||
# vim: filetype=sh
|
# vim: filetype=sh
|
||||||
|
|||||||
Reference in New Issue
Block a user