mirror of https://github.com/containers/podman.git
Merge pull request #12867 from cdoern/scp
switch podman image scp from depending on machinectl to just os/exec
This commit is contained in:
commit
5659b0734c
|
@ -17,7 +17,6 @@ import (
|
||||||
"github.com/containers/podman/v4/cmd/podman/system/connection"
|
"github.com/containers/podman/v4/cmd/podman/system/connection"
|
||||||
"github.com/containers/podman/v4/libpod/define"
|
"github.com/containers/podman/v4/libpod/define"
|
||||||
"github.com/containers/podman/v4/pkg/domain/entities"
|
"github.com/containers/podman/v4/pkg/domain/entities"
|
||||||
"github.com/containers/podman/v4/pkg/rootless"
|
|
||||||
"github.com/containers/podman/v4/utils"
|
"github.com/containers/podman/v4/utils"
|
||||||
scpD "github.com/dtylman/scp"
|
scpD "github.com/dtylman/scp"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -337,21 +336,9 @@ func GetServiceInformation(cliConnections []string, cfg *config.Config) (map[str
|
||||||
|
|
||||||
// execPodman executes the podman save/load command given the podman binary
|
// execPodman executes the podman save/load command given the podman binary
|
||||||
func execPodman(podman string, command []string) error {
|
func execPodman(podman string, command []string) error {
|
||||||
if rootless.IsRootless() {
|
|
||||||
cmd := exec.Command(podman)
|
cmd := exec.Command(podman)
|
||||||
utils.CreateSCPCommand(cmd, command[1:])
|
utils.CreateSCPCommand(cmd, command[1:])
|
||||||
logrus.Debug("Executing podman command")
|
logrus.Debugf("Executing podman command: %q", cmd)
|
||||||
return cmd.Run()
|
|
||||||
}
|
|
||||||
machinectl, err := exec.LookPath("machinectl")
|
|
||||||
if err != nil {
|
|
||||||
cmd := exec.Command("su", "-l", "root", "--command")
|
|
||||||
cmd = utils.CreateSCPCommand(cmd, []string{strings.Join(command, " ")})
|
|
||||||
return cmd.Run()
|
|
||||||
}
|
|
||||||
cmd := exec.Command(machinectl, "shell", "-q", "root@.host")
|
|
||||||
cmd = utils.CreateSCPCommand(cmd, command)
|
|
||||||
logrus.Debug("Executing load command machinectl")
|
|
||||||
return cmd.Run()
|
return cmd.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
"github.com/containers/common/libimage"
|
"github.com/containers/common/libimage"
|
||||||
"github.com/containers/common/pkg/config"
|
"github.com/containers/common/pkg/config"
|
||||||
|
@ -782,7 +783,7 @@ func transferRootless(source entities.ImageScpOptions, dest entities.ImageScpOpt
|
||||||
return cmdLoad.Run()
|
return cmdLoad.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TransferRootful creates new podman processes using exec.Command and su/machinectl, transferring images between the given source and destination users
|
// TransferRootful creates new podman processes using exec.Command and a new uid/gid alongside a cleared environment
|
||||||
func transferRootful(source entities.ImageScpOptions, dest entities.ImageScpOptions, podman string, parentFlags []string) error {
|
func transferRootful(source entities.ImageScpOptions, dest entities.ImageScpOptions, podman string, parentFlags []string) error {
|
||||||
basicCommand := []string{podman}
|
basicCommand := []string{podman}
|
||||||
basicCommand = append(basicCommand, parentFlags...)
|
basicCommand = append(basicCommand, parentFlags...)
|
||||||
|
@ -794,12 +795,9 @@ func transferRootful(source entities.ImageScpOptions, dest entities.ImageScpOpti
|
||||||
}
|
}
|
||||||
saveCommand = append(saveCommand, []string{"--output", source.File, source.Image}...)
|
saveCommand = append(saveCommand, []string{"--output", source.File, source.Image}...)
|
||||||
loadCommand = append(loadCommand, []string{"--input", dest.File}...)
|
loadCommand = append(loadCommand, []string{"--input", dest.File}...)
|
||||||
save := []string{strings.Join(saveCommand, " ")}
|
|
||||||
load := []string{strings.Join(loadCommand, " ")}
|
|
||||||
|
|
||||||
// if executing using sudo or transferring between two users, the TransferRootless approach will not work, default to using machinectl or su as necessary.
|
// if executing using sudo or transferring between two users, the TransferRootless approach will not work, the new process needs to be set up
|
||||||
// the approach using sudo is preferable and more straightforward. There is no reason for using sudo in these situations
|
// with the proper uid and gid as well as environmental variables.
|
||||||
// since the feature is meant to transfer from root to rootless an vice versa without explicit sudo evocaiton.
|
|
||||||
var uSave *user.User
|
var uSave *user.User
|
||||||
var uLoad *user.User
|
var uLoad *user.User
|
||||||
var err error
|
var err error
|
||||||
|
@ -830,20 +828,11 @@ func transferRootful(source entities.ImageScpOptions, dest entities.ImageScpOpti
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
machinectl, err := exec.LookPath("machinectl")
|
err = execPodman(uSave, saveCommand)
|
||||||
if err != nil {
|
|
||||||
logrus.Warn("defaulting to su since machinectl is not available, su will fail if no user session is available")
|
|
||||||
err = execSu(uSave, save)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return execSu(uLoad, load)
|
return execPodman(uLoad, loadCommand)
|
||||||
}
|
|
||||||
err = execMachine(uSave, saveCommand, machinectl)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return execMachine(uLoad, loadCommand, machinectl)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func lookupUser(u string) (*user.User, error) {
|
func lookupUser(u string) (*user.User, error) {
|
||||||
|
@ -853,21 +842,37 @@ func lookupUser(u string) (*user.User, error) {
|
||||||
return user.Lookup(u)
|
return user.Lookup(u)
|
||||||
}
|
}
|
||||||
|
|
||||||
func execSu(execUser *user.User, command []string) error {
|
func execPodman(execUser *user.User, command []string) error {
|
||||||
cmd := exec.Command("su", "-l", execUser.Username, "--command")
|
cmdLogin, err := utils.LoginUser(execUser.Username)
|
||||||
cmd = utils.CreateSCPCommand(cmd, command)
|
if err != nil {
|
||||||
logrus.Debugf("Executing via su: %q", cmd)
|
return err
|
||||||
return cmd.Run()
|
}
|
||||||
}
|
defer func() error {
|
||||||
|
err := cmdLogin.Process.Kill()
|
||||||
func execMachine(execUser *user.User, command []string, machinectl string) error {
|
if err != nil {
|
||||||
verb := machinectl
|
return err
|
||||||
args := []string{"shell", "-q", execUser.Username + "@.host"}
|
}
|
||||||
if execUser.Uid == "0" {
|
return cmdLogin.Wait()
|
||||||
args = append([]string{verb}, args...)
|
}()
|
||||||
verb = "sudo"
|
cmd := exec.Command(command[0], command[1:]...)
|
||||||
}
|
cmd.Env = []string{"PATH=" + os.Getenv("PATH"), "TERM=" + os.Getenv("TERM")}
|
||||||
cmd := utils.CreateSCPCommand(exec.Command(verb, args...), command)
|
cmd.Stderr = os.Stderr
|
||||||
logrus.Debugf("Executing via machinectl: %q", cmd)
|
cmd.Stdout = os.Stdout
|
||||||
|
uid, err := strconv.ParseInt(execUser.Uid, 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
gid, err := strconv.ParseInt(execUser.Gid, 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||||
|
Credential: &syscall.Credential{
|
||||||
|
Uid: uint32(uid),
|
||||||
|
Gid: uint32(gid),
|
||||||
|
Groups: nil,
|
||||||
|
NoSetGroups: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
return cmd.Run()
|
return cmd.Run()
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,10 +104,6 @@ verify_iid_and_name() {
|
||||||
# If we can't sudo, we can't test.
|
# If we can't sudo, we can't test.
|
||||||
_sudo true || skip "cannot sudo to $notme"
|
_sudo true || skip "cannot sudo to $notme"
|
||||||
|
|
||||||
# FIXME FIXME FIXME: it'd be reeeeeeally nice if we could pass --root
|
|
||||||
# to the non-self user, hence avoid vandalizing
|
|
||||||
# their storage.
|
|
||||||
|
|
||||||
# Preserve digest of original image; we will compare against it later
|
# Preserve digest of original image; we will compare against it later
|
||||||
run_podman image inspect --format '{{.Digest}}' $IMAGE
|
run_podman image inspect --format '{{.Digest}}' $IMAGE
|
||||||
src_digest=$output
|
src_digest=$output
|
||||||
|
@ -117,12 +113,8 @@ verify_iid_and_name() {
|
||||||
run_podman tag $IMAGE $newname
|
run_podman tag $IMAGE $newname
|
||||||
|
|
||||||
# Copy it there.
|
# Copy it there.
|
||||||
# FIXME: the first '.*' in the expect string below is unfortunate; it's
|
|
||||||
# a workaround for Ubuntu which gripes:
|
|
||||||
# "warning.*defaulting to su since machinectl is not available"
|
|
||||||
# Reexamine this once #12829 is fixed
|
|
||||||
run_podman image scp $newname ${notme}@localhost::
|
run_podman image scp $newname ${notme}@localhost::
|
||||||
is "$output" ".*Copying blob .*Copying config.*Writing manifest.*Storing signatures"
|
is "$output" "Copying blob .*Copying config.*Writing manifest.*Storing signatures"
|
||||||
|
|
||||||
# confirm that image was copied. FIXME: also try $PODMAN image inspect?
|
# confirm that image was copied. FIXME: also try $PODMAN image inspect?
|
||||||
_sudo $PODMAN image exists $newname
|
_sudo $PODMAN image exists $newname
|
||||||
|
@ -132,13 +124,6 @@ verify_iid_and_name() {
|
||||||
run_podman image scp -q ${notme}@localhost::$newname
|
run_podman image scp -q ${notme}@localhost::$newname
|
||||||
|
|
||||||
expect="Loaded image(s): $newname"
|
expect="Loaded image(s): $newname"
|
||||||
# FIXME FIXME FIXME: ubuntu has no machinectl, emits useless warning message instead
|
|
||||||
if ! is_rootless; then
|
|
||||||
# FIXME: root on fedora uses machinectl, which emits useless \n and \r (#12829)
|
|
||||||
NL=$'\n'
|
|
||||||
CR=$'\r'
|
|
||||||
expect="$NL$expect$CR"
|
|
||||||
fi
|
|
||||||
is "$output" "$expect" "-q silences output"
|
is "$output" "$expect" "-q silences output"
|
||||||
|
|
||||||
# Confirm that we have it, and that its digest matches our original
|
# Confirm that we have it, and that its digest matches our original
|
||||||
|
@ -150,8 +135,6 @@ verify_iid_and_name() {
|
||||||
run_podman untag $IMAGE $newname
|
run_podman untag $IMAGE $newname
|
||||||
|
|
||||||
# Negative test for nonexistent image.
|
# Negative test for nonexistent image.
|
||||||
# FIXME FIXME: cannot test on root, because it uses machinectl (#12829)
|
|
||||||
if is_rootless; then
|
|
||||||
# FIXME: error message is 2 lines, the 2nd being "exit status 125".
|
# FIXME: error message is 2 lines, the 2nd being "exit status 125".
|
||||||
# FIXME: is that fixable, or do we have to live with it?
|
# FIXME: is that fixable, or do we have to live with it?
|
||||||
nope="nope.nope/nonesuch:notag"
|
nope="nope.nope/nonesuch:notag"
|
||||||
|
@ -160,7 +143,6 @@ verify_iid_and_name() {
|
||||||
|
|
||||||
run_podman 125 image scp $nope ${notme}@localhost::
|
run_podman 125 image scp $nope ${notme}@localhost::
|
||||||
is "$output" "Error: $nope: image not known.*" "Pushing nonexistent image"
|
is "$output" "Error: $nope: image not known.*" "Pushing nonexistent image"
|
||||||
fi
|
|
||||||
|
|
||||||
# Negative test for copying to a different name
|
# Negative test for copying to a different name
|
||||||
run_podman 125 image scp $IMAGE ${notme}@localhost::newname:newtag
|
run_podman 125 image scp $IMAGE ${notme}@localhost::newname:newtag
|
||||||
|
|
|
@ -238,3 +238,18 @@ func CreateSCPCommand(cmd *exec.Cmd, command []string) *exec.Cmd {
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoginUser starts the user process on the host so that image scp can use systemd-run
|
||||||
|
func LoginUser(user string) (*exec.Cmd, error) {
|
||||||
|
sleep, err := exec.LookPath("sleep")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
machinectl, err := exec.LookPath("machinectl")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
cmd := exec.Command(machinectl, "shell", "-q", user+"@.host", sleep, "inf")
|
||||||
|
err = cmd.Start()
|
||||||
|
return cmd, err
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue