From 15ca54b9d352f7285d1ee072d9afe6d776286296 Mon Sep 17 00:00:00 2001 From: "Justin Terry (VM)" Date: Tue, 27 Nov 2018 12:40:36 -0800 Subject: [PATCH] Store the runhcs.exe path for faster invocation Signed-off-by: Justin Terry (VM) --- pkg/go-runhcs/runhcs.go | 32 +++++++++-- pkg/go-runhcs/runhcs_integration_test.go | 7 +++ pkg/go-runhcs/runhcs_test.go | 67 ++++++++++++++++++++++-- 3 files changed, 100 insertions(+), 6 deletions(-) create mode 100644 pkg/go-runhcs/runhcs_integration_test.go diff --git a/pkg/go-runhcs/runhcs.go b/pkg/go-runhcs/runhcs.go index 24dc467e4f..5d5205abdb 100644 --- a/pkg/go-runhcs/runhcs.go +++ b/pkg/go-runhcs/runhcs.go @@ -9,6 +9,7 @@ import ( "path/filepath" "strings" "sync" + "sync/atomic" irunhcs "github.com/Microsoft/hcsshim/internal/runhcs" "github.com/containerd/go-runc" @@ -23,10 +24,35 @@ const ( Text Format = "text" // JSON is the JSON formatted log output. JSON Format = "json" - - command = "runhcs" ) +var runhcsPath atomic.Value + +func getCommandPath() string { + const command = "runhcs.exe" + + pathi := runhcsPath.Load() + if pathi == nil { + path, err := exec.LookPath(command) + if err != nil { + // Failed to look up command just use it directly and let the + // Windows loader find it. + path = command + runhcsPath.Store(path) + return path + } + apath, err := filepath.Abs(path) + if err != nil { + // We couldnt make `path` an `AbsPath`. Just use `path` directly and + // let the Windows loader find it. + apath = path + } + runhcsPath.Store(apath) + return apath + } + return pathi.(string) +} + var bytesBufferPool = sync.Pool{ New: func() interface{} { return bytes.NewBuffer(nil) @@ -84,7 +110,7 @@ func (r *Runhcs) args() []string { } func (r *Runhcs) command(context context.Context, args ...string) *exec.Cmd { - cmd := exec.CommandContext(context, command, append(r.args(), args...)...) + cmd := exec.CommandContext(context, getCommandPath(), append(r.args(), args...)...) cmd.Env = os.Environ() return cmd } diff --git a/pkg/go-runhcs/runhcs_integration_test.go b/pkg/go-runhcs/runhcs_integration_test.go new file mode 100644 index 0000000000..c6d9604e58 --- /dev/null +++ b/pkg/go-runhcs/runhcs_integration_test.go @@ -0,0 +1,7 @@ +// +build runhcs_test + +package runhcs + +import ( + _ "github.com/Microsoft/hcsshim/functional/manifest" +) diff --git a/pkg/go-runhcs/runhcs_test.go b/pkg/go-runhcs/runhcs_test.go index c6d9604e58..bdbae1bffb 100644 --- a/pkg/go-runhcs/runhcs_test.go +++ b/pkg/go-runhcs/runhcs_test.go @@ -1,7 +1,68 @@ -// +build runhcs_test - package runhcs import ( - _ "github.com/Microsoft/hcsshim/functional/manifest" + "os" + "path/filepath" + "sync/atomic" + "testing" ) + +func resetRunhcsPath() { + runhcsPath = atomic.Value{} +} + +func TestGetCommandPath_NoLookPath(t *testing.T) { + resetRunhcsPath() + + path := getCommandPath() + if path != "runhcs.exe" { + t.Fatalf("expected path 'runhcs.exe' got '%s'", path) + } + pathi := runhcsPath.Load() + if pathi == nil { + t.Fatal("cache state should be set after first query") + } + if path != pathi.(string) { + t.Fatalf("expected: '%s' in cache got '%s'", path, pathi.(string)) + } +} + +func TestGetCommandPath_WithLookPath(t *testing.T) { + resetRunhcsPath() + + wd, err := os.Getwd() + if err != nil { + t.Fatalf("failed to get cwd with err: %v", err) + } + fakePath := filepath.Join(wd, "runhcs.exe") + f, err := os.Create(fakePath) + if err != nil { + t.Fatalf("failed to create fake runhcs.exe in path with err: %v", err) + } + f.Close() + defer os.Remove(fakePath) + + path := getCommandPath() + if path != fakePath { + t.Fatalf("expected fake path '%s' got '%s'", fakePath, path) + } + pathi := runhcsPath.Load() + if pathi == nil { + t.Fatal("cache state should be set after first query") + } + if path != pathi.(string) { + t.Fatalf("expected: '%s' in cache got '%s'", fakePath, pathi.(string)) + } +} + +func TestGetCommandPath_WithCache(t *testing.T) { + resetRunhcsPath() + + value := "this is a test" + runhcsPath.Store(value) + + path := getCommandPath() + if path != value { + t.Fatalf("expected fake cached path: '%s' got '%s'", value, path) + } +}