mirror of
https://github.com/containerd/containerd.git
synced 2026-08-09 01:21:15 +00:00
Set SystemTemp env var to config temp on Windows
Since Go 1.21, os.MkdirTemp/os.TempDir resolve the temp directory via Windows' GetTempPath2W. For processes running as SYSTEM (as containerd does when running under the SCM), that API reads the temp location from the SystemTemp environment variable rather than TMP/TEMP. As a result, the existing TMP/TEMP overrides no longer steer the layer-extraction tempdir for the containerd service, so it falls back to the default C:\\Windows\\SystemTemp and unpacks on the SystemDrive, reintroducing the cross-volume copy the 'temp' config option was meant to avoid. Set SystemTemp to config.TempDir alongside TEMP/TMP so the override keeps working on Go 1.21+. Factor the env-var setting out of CreateTopLevelDirectories into a small setTempDirEnv helper and add a focused unit test (TestSetTempDirEnv) that verifies the expected variables are set: TEMP/TMP/SystemTemp on Windows, TMPDIR on other platforms. Ref: https://cs.opensource.google/go/go/+/refs/tags/go1.21.0:src/os/file_windows.go Signed-off-by: Maksim An <maksiman@microsoft.com>
This commit is contained in:
@@ -92,22 +92,34 @@ func CreateTopLevelDirectories(config *srvconfig.Config) error {
|
||||
if err := os.Chmod(config.TempDir, 0o700); err != nil && !errors.Is(err, os.ErrPermission) {
|
||||
return err
|
||||
}
|
||||
if runtime.GOOS == "windows" {
|
||||
// On Windows, the Host Compute Service (vmcompute) will read the
|
||||
// TEMP/TMP setting from the calling process when creating the
|
||||
// tempdir to extract an image layer to. This allows the
|
||||
// administrator to align the tempdir location with the same volume
|
||||
// as the snapshot dir to avoid a copy operation when moving the
|
||||
// extracted layer to the snapshot dir location.
|
||||
os.Setenv("TEMP", config.TempDir)
|
||||
os.Setenv("TMP", config.TempDir)
|
||||
} else {
|
||||
os.Setenv("TMPDIR", config.TempDir)
|
||||
}
|
||||
setTempDirEnv(config.TempDir)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// setTempDirEnv points the process' temp-directory environment variables at
|
||||
// tempDir so that components (and the OS) honor the configured temp location.
|
||||
func setTempDirEnv(tempDir string) {
|
||||
if runtime.GOOS == "windows" {
|
||||
// On Windows, the Host Compute Service (vmcompute) will read the
|
||||
// TEMP/TMP setting from the calling process when creating the
|
||||
// tempdir to extract an image layer to. This allows the
|
||||
// administrator to align the tempdir location with the same volume
|
||||
// as the snapshot dir to avoid a copy operation when moving the
|
||||
// extracted layer to the snapshot dir location.
|
||||
os.Setenv("TEMP", tempDir)
|
||||
os.Setenv("TMP", tempDir)
|
||||
// Since Go 1.21, os.MkdirTemp/os.TempDir resolve the temp dir via
|
||||
// Windows' GetTempPath2W. For processes running as SYSTEM (as
|
||||
// containerd does under the SCM), that API reads SystemTemp rather
|
||||
// than TEMP/TMP, so set it too to keep the override effective.
|
||||
// https://cs.opensource.google/go/go/+/refs/tags/go1.21.0:src/os/file_windows.go
|
||||
os.Setenv("SystemTemp", tempDir)
|
||||
} else {
|
||||
os.Setenv("TMPDIR", tempDir)
|
||||
}
|
||||
}
|
||||
|
||||
// New creates and initializes a new containerd server
|
||||
func New(ctx context.Context, config *srvconfig.Config) (*Server, error) {
|
||||
if err := apply(ctx, config); err != nil {
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"context"
|
||||
"iter"
|
||||
"os"
|
||||
"runtime"
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
@@ -172,3 +173,25 @@ func TestMigration(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetTempDirEnv(t *testing.T) {
|
||||
const tempDir = "/tmp/path/for/testing/temp"
|
||||
|
||||
var keys []string
|
||||
if runtime.GOOS == "windows" {
|
||||
keys = []string{"TEMP", "TMP", "SystemTemp"}
|
||||
} else {
|
||||
keys = []string{"TMPDIR"}
|
||||
}
|
||||
for _, k := range keys {
|
||||
t.Setenv(k, "")
|
||||
}
|
||||
|
||||
setTempDirEnv(tempDir)
|
||||
|
||||
for _, k := range keys {
|
||||
if got := os.Getenv(k); got != tempDir {
|
||||
t.Errorf("expected %s=%q, got %q", k, tempDir, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user