refactor: write contents to stdout before writing to a file
Rather than writing directly to the file - thus utilizing whatever user docker is being executed as - we copy the file to stdout and then write it to the temp file. This ensures permissions on the file are as expected from Dokku's end. Closes #7336
This commit is contained in:
@@ -104,14 +104,6 @@ func CopyFromImage(appName string, image string, source string, destination stri
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpFile, err := os.CreateTemp(os.TempDir(), fmt.Sprintf("dokku-%s-%s", MustGetEnv("DOKKU_PID"), "CopyFromImage"))
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Cannot create temporary file: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
defer tmpFile.Close()
|
|
||||||
defer os.Remove(tmpFile.Name())
|
|
||||||
|
|
||||||
globalRunArgs := MustGetEnv("DOKKU_GLOBAL_RUN_ARGS")
|
globalRunArgs := MustGetEnv("DOKKU_GLOBAL_RUN_ARGS")
|
||||||
createLabelArgs := []string{"--label", fmt.Sprintf("com.dokku.app-name=%s", appName), globalRunArgs}
|
createLabelArgs := []string{"--label", fmt.Sprintf("com.dokku.app-name=%s", appName), globalRunArgs}
|
||||||
containerID, err := DockerContainerCreate(image, createLabelArgs)
|
containerID, err := DockerContainerCreate(image, createLabelArgs)
|
||||||
@@ -125,7 +117,7 @@ func CopyFromImage(appName string, image string, source string, destination stri
|
|||||||
// ref: https://github.com/dotcloud/docker/issues/3986
|
// ref: https://github.com/dotcloud/docker/issues/3986
|
||||||
result, err := CallExecCommand(ExecCommandInput{
|
result, err := CallExecCommand(ExecCommandInput{
|
||||||
Command: DockerBin(),
|
Command: DockerBin(),
|
||||||
Args: []string{"container", "cp", fmt.Sprintf("%s:%s", containerID, source), tmpFile.Name()},
|
Args: []string{"container", "cp", "--quiet", fmt.Sprintf("%s:%s", containerID, source), "-"},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Unable to copy file %s from image: %w", source, err)
|
return fmt.Errorf("Unable to copy file %s from image: %w", source, err)
|
||||||
@@ -134,6 +126,43 @@ func CopyFromImage(appName string, image string, source string, destination stri
|
|||||||
return fmt.Errorf("Unable to copy file %s from image: %v", source, result.StderrContents())
|
return fmt.Errorf("Unable to copy file %s from image: %v", source, result.StderrContents())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tarContents := result.StdoutContents()
|
||||||
|
if tarContents == "" {
|
||||||
|
return fmt.Errorf("Unable to copy file %s from image", source)
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract the contents via tar
|
||||||
|
// tar -xOf -
|
||||||
|
result, err = CallExecCommand(ExecCommandInput{
|
||||||
|
Command: "tar",
|
||||||
|
Args: []string{"-xOf", "-"},
|
||||||
|
Stdin: strings.NewReader(tarContents),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Unable to extract contents from tar: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
contents = result.StdoutContents()
|
||||||
|
|
||||||
|
tmpFile, err := os.CreateTemp(os.TempDir(), fmt.Sprintf("dokku-%s-%s", MustGetEnv("DOKKU_PID"), "CopyFromImage"))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Cannot create temporary file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if err := tmpFile.Close(); err != nil {
|
||||||
|
LogWarn(fmt.Sprintf("Unable to close temporary file: %v", err))
|
||||||
|
}
|
||||||
|
if err := os.Remove(tmpFile.Name()); err != nil {
|
||||||
|
LogWarn(fmt.Sprintf("Unable to remove temporary file: %v", err))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// write contents to tmpFile
|
||||||
|
if _, err := tmpFile.Write([]byte(contents)); err != nil {
|
||||||
|
return fmt.Errorf("Unable to write to temporary file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
fi, err := os.Stat(tmpFile.Name())
|
fi, err := os.Stat(tmpFile.Name())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
Reference in New Issue
Block a user