Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ type HTTP struct {
// A Docker describes Docker engine settings.
type Docker struct {
Bin string `json:"bin"`
Tmp string `json:"tmp"`
}

// setBoxDefaults sets default box properties
Expand Down
45 changes: 43 additions & 2 deletions internal/config/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"errors"
"os"
"os/exec"
"path/filepath"
"strings"

Expand Down Expand Up @@ -176,8 +177,30 @@ func readConfig(path string) (*Config, error) {
}
if cfg.Docker == nil {
cfg.Docker = &Docker{Bin: "docker"}
} else if cfg.Docker.Bin == "" {
cfg.Docker.Bin = "docker"
} else {
if cfg.Docker.Bin == "" {
cfg.Docker.Bin = "docker"
} else {
bin := cfg.Docker.Bin
_, err := exec.LookPath(bin)
if err != nil {
return nil, err
}
}
if cfg.Docker.Tmp == "" {
cfg.Docker.Tmp = tempDir()
} else {
tmp := cfg.Docker.Tmp
dir, err := expandTilde(tmp)
if err != nil {
return nil, err
}
err = os.MkdirAll(dir, 0o755)
if err != nil {
return nil, err
}
cfg.Docker.Tmp = dir
}
}

return cfg, err
Expand Down Expand Up @@ -232,6 +255,24 @@ func readBoxesFile(path string) (map[string]*Box, error) {
return boxes, err
}

// tempDir returns the directory to use for temporary files.
var tempDir = os.TempDir

// userHomeDir returns the current user's home directory.
var userHomeDir = os.UserHomeDir

// expandTilde expands strings like "~/.local" with the path.
func expandTilde(dir string) (string, error) {
if strings.HasPrefix(dir, "~/") {
homeDir, err := userHomeDir()
if err != nil {
return "", err
}
dir = strings.Replace(dir, "~", homeDir, 1)
}
return dir, nil
}

// readCommands reads command configs from a set of JSON files in the given path.
func readCommands(cfg *Config, path string, pattern string) (*Config, error) {
logx.Debug("reading commands from %s/%s", path, pattern)
Expand Down
27 changes: 27 additions & 0 deletions internal/config/load_test.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
package config

import (
"path/filepath"
"testing"

"github.com/nalgeon/be"
)

func TestRead(t *testing.T) {
cfg, err := Read("testdata")

be.Err(t, err, nil)
be.Equal(t, cfg.PoolSize, 8)
be.Equal(t, cfg.Verbose, true)
be.Equal(t, cfg.Box.Memory, 64)
be.Equal(t, cfg.Step.User, "sandbox")

// docker
be.Equal(t, cfg.Docker.Bin, "docker")
be.Equal(t, cfg.Docker.Tmp, "")

// alpine box
be.True(t, cfg.Boxes["custom-alpine"] != nil)
be.Equal(t, cfg.Boxes["custom-alpine"].Image, "custom/alpine")
Expand All @@ -23,3 +29,24 @@ func TestRead(t *testing.T) {
be.True(t, cfg.Commands["python"] != nil)
be.True(t, cfg.Commands["python"]["run"] != nil)
}

func TestReadDocker(t *testing.T) {
temp := filepath.Join(t.TempDir(), "TEMP")
tempDir = func() string { return temp }

cfg, err := readConfig(filepath.Join("testdata", "docker.json"))

be.Err(t, err, nil)
be.Equal(t, cfg.Docker.Bin, "docker")
be.Equal(t, cfg.Docker.Tmp, temp)
}

func TestExpandTilde(t *testing.T) {
home := filepath.Join(t.TempDir(), "HOME")
userHomeDir = func() (string, error) { return home, nil }

tmp, err := expandTilde("~/tmp")
be.Err(t, err, nil)

be.Equal(t, tmp, home+"/tmp")
}
10 changes: 10 additions & 0 deletions internal/config/testdata/docker.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"box": {
},
"step": {
},
"docker": {
"bin": "",
"tmp": ""
}
}
5 changes: 3 additions & 2 deletions internal/engine/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,19 @@ type Docker struct {
cfg *config.Config
cmd *config.Command
exe string // docker
tmp string // TMPDIR
}

// NewDocker creates a new Docker engine for a specific command.
func NewDocker(cfg *config.Config, sandbox, command string) Engine {
cmd := cfg.Commands[sandbox][command]
return &Docker{cfg, cmd, cfg.Docker.Bin}
return &Docker{cfg, cmd, cfg.Docker.Bin, cfg.Docker.Tmp}
}

// Exec executes the command and returns the output.
func (e *Docker) Exec(req Request) Execution {
// all steps operate in the same temp directory
dir, err := fileio.MkdirTemp(0777)
dir, err := fileio.MkdirTemp(e.tmp, 0777)
if err != nil {
err = NewExecutionError("create temp dir", err)
return Fail(req.ID, err)
Expand Down
4 changes: 2 additions & 2 deletions internal/fileio/fileio.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,8 @@ func JoinDir(dir string, name string) (string, error) {

// MkdirTemp creates a new temporary directory with given permissions
// and returns the pathname of the new directory.
func MkdirTemp(perm fs.FileMode) (string, error) {
dir, err := os.MkdirTemp("", "")
func MkdirTemp(dir string, perm fs.FileMode) (string, error) {
dir, err := os.MkdirTemp(dir, "")
if err != nil {
return "", err
}
Expand Down
4 changes: 2 additions & 2 deletions internal/fileio/fileio_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ func TestJoinDir(t *testing.T) {
func TestMkdirTemp(t *testing.T) {
t.Run("default permissions", func(t *testing.T) {
const perm = 0755
dir, err := MkdirTemp(perm)
dir, err := MkdirTemp("", perm)
be.Err(t, err, nil)
defer func() { _ = os.Remove(dir) }()

Expand All @@ -292,7 +292,7 @@ func TestMkdirTemp(t *testing.T) {

t.Run("non-default permissions", func(t *testing.T) {
const perm = 0777
dir, err := MkdirTemp(perm)
dir, err := MkdirTemp(t.TempDir(), perm)
be.Err(t, err, nil)
defer func() { _ = os.Remove(dir) }()

Expand Down