Don't try to resolve host path if copying to container from stdin.

Fixes: #25472

Signed-off-by: David Negstad <David.Negstad@microsoft.com>
This commit is contained in:
David Negstad
2025-03-04 21:31:19 -08:00
committed by Matt Heon
parent b716aa17e2
commit 180d55165d
3 changed files with 110 additions and 11 deletions

View File

@ -339,17 +339,19 @@ func copyToContainer(container string, containerPath string, hostPath string) er
return err
}
hostInfo := &copy.FileInfo{}
var err error
isStdin := false
if hostPath == "-" {
hostPath = os.Stdin.Name()
isStdin = true
}
// Make sure that host path exists.
hostInfo, err := copy.ResolveHostPath(hostPath)
} else {
// Make sure that host path exists if not copying from stdin.
hostInfo, err = copy.ResolveHostPath(hostPath)
if err != nil {
return fmt.Errorf("%q could not be found on the host: %w", hostPath, err)
}
}
containerBaseName, containerInfo, containerResolvedToParentDir, err := resolvePathOnDestinationContainer(container, containerPath, isStdin)
if err != nil {

View File

@ -1,8 +1,11 @@
package e2e_test
import (
"archive/tar"
"bytes"
"fmt"
"io"
"io/fs"
"net"
"net/http"
"net/url"
@ -253,6 +256,87 @@ var _ = Describe("run basic podman commands", func() {
Expect(run).To(Exit(0))
Expect(build.outputToString()).To(ContainSubstring(name))
})
It("Copy ops", func() {
var (
stdinDirectory = "stdin-dir"
stdinFile = "file.txt"
)
now := time.Now()
tarBuffer := &bytes.Buffer{}
tw := tar.NewWriter(tarBuffer)
// Write a directory header to the tar
err := tw.WriteHeader(&tar.Header{
Name: stdinDirectory,
Mode: int64(0640 | fs.ModeDir),
Gid: 1000,
ModTime: now,
ChangeTime: now,
AccessTime: now,
Typeflag: tar.TypeDir,
})
Expect(err).ToNot(HaveOccurred())
// Write a file header to the tar
err = tw.WriteHeader(&tar.Header{
Name: path.Join(stdinDirectory, stdinFile),
Mode: 0755,
Uid: 1000,
ModTime: now,
ChangeTime: now,
AccessTime: now,
})
Expect(err).ToNot(HaveOccurred())
err = tw.Close()
Expect(err).ToNot(HaveOccurred())
name := randomString()
i := new(initMachine)
session, err := mb.setName(name).setCmd(i.withImage(mb.imagePath).withNow()).run()
Expect(err).ToNot(HaveOccurred())
Expect(session).To(Exit(0))
bm := basicMachine{}
newImgs, err := mb.setCmd(bm.withPodmanCommand([]string{"pull", "quay.io/libpod/alpine_nginx"})).run()
Expect(err).ToNot(HaveOccurred())
Expect(newImgs).To(Exit(0))
Expect(newImgs.outputToStringSlice()).To(HaveLen(1))
createAlp, err := mb.setCmd(bm.withPodmanCommand([]string{"create", "quay.io/libpod/alpine_nginx"})).run()
Expect(err).ToNot(HaveOccurred())
Expect(createAlp).To(Exit(0))
Expect(createAlp.outputToStringSlice()).To(HaveLen(1))
// Testing stdin copy with archive mode disabled (ownership will be determined by the tar file)
containerID := createAlp.outputToStringSlice()[0]
cpTar, err := mb.setCmd(bm.withPodmanCommand([]string{"cp", "-a=false", "-", containerID + ":/tmp"})).setStdin(tarBuffer).run()
Expect(err).ToNot(HaveOccurred())
Expect(cpTar).To(Exit(0))
start, err := mb.setCmd(bm.withPodmanCommand([]string{"start", containerID})).run()
Expect(err).ToNot(HaveOccurred())
Expect(start).To(Exit(0))
// Check the directory is created with the appropriate mode, uid, gid
exec, err := mb.setCmd(bm.withPodmanCommand([]string{"exec", containerID, "stat", "-c", "%a %u %g", "/tmp/stdin-dir"})).run()
Expect(err).ToNot(HaveOccurred())
Expect(exec).To(Exit(0))
execStdOut := exec.outputToStringSlice()
Expect(execStdOut).To(HaveLen(1))
Expect(execStdOut[0]).To(Equal("640 0 1000"))
// Check the file is created with the appropriate mode, uid, gid
exec, err = mb.setCmd(bm.withPodmanCommand([]string{"exec", containerID, "stat", "-c", "%a %u %g", "/tmp/stdin-dir/file.txt"})).run()
Expect(err).ToNot(HaveOccurred())
Expect(exec).To(Exit(0))
execStdOut = exec.outputToStringSlice()
Expect(execStdOut).To(HaveLen(1))
Expect(execStdOut[0]).To(Equal("755 1000 0"))
})
})
func testHTTPServer(port string, shouldErr bool, expectedResponse string) {

View File

@ -3,6 +3,7 @@ package e2e_test
import (
"encoding/json"
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
@ -44,6 +45,7 @@ type machineSession struct {
type machineTestBuilder struct {
cmd []string
stdin io.Reader
imagePath string
name string
names []string
@ -139,6 +141,13 @@ func (m *machineTestBuilder) setCmd(mc machineCommand) *machineTestBuilder {
m.names = append(m.names, m.name)
}
m.cmd = mc.buildCmd(m)
m.stdin = nil
return m
}
// setStdin sets the stdin for the next command to be run
func (m *machineTestBuilder) setStdin(data io.Reader) *machineTestBuilder {
m.stdin = data
return m
}
@ -152,7 +161,7 @@ func (m *machineTestBuilder) setTimeout(timeout time.Duration) *machineTestBuild
func (m *machineTestBuilder) toQemuInspectInfo() ([]machine.InspectInfo, int, error) {
args := []string{"machine", "inspect"}
args = append(args, m.names...)
session, err := runWrapper(m.podmanBinary, args, defaultTimeout, true)
session, err := runWrapper(m.podmanBinary, args, nil, defaultTimeout, true)
if err != nil {
return nil, -1, err
}
@ -162,20 +171,24 @@ func (m *machineTestBuilder) toQemuInspectInfo() ([]machine.InspectInfo, int, er
}
func (m *machineTestBuilder) runWithoutWait() (*machineSession, error) {
return runWrapper(m.podmanBinary, m.cmd, m.timeout, false)
return runWrapper(m.podmanBinary, m.cmd, m.stdin, m.timeout, false)
}
func (m *machineTestBuilder) run() (*machineSession, error) {
s, err := runWrapper(m.podmanBinary, m.cmd, m.timeout, true)
s, err := runWrapper(m.podmanBinary, m.cmd, m.stdin, m.timeout, true)
return s, err
}
func runWrapper(podmanBinary string, cmdArgs []string, timeout time.Duration, wait bool) (*machineSession, error) {
func runWrapper(podmanBinary string, cmdArgs []string, stdinData io.Reader, timeout time.Duration, wait bool) (*machineSession, error) {
if len(os.Getenv("DEBUG")) > 0 {
cmdArgs = append([]string{"--log-level=debug"}, cmdArgs...)
}
GinkgoWriter.Println(podmanBinary + " " + strings.Join(cmdArgs, " "))
c := exec.Command(podmanBinary, cmdArgs...)
if stdinData != nil {
c.Stdin = stdinData
}
session, err := Start(c, GinkgoWriter, GinkgoWriter)
if err != nil {
Fail(fmt.Sprintf("Unable to start session: %q", err))