open-nomad/client/allocrunner/taskrunner/getter/util_test.go

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

217 lines
5.1 KiB
Go
Raw Normal View History

package getter
import (
"errors"
"os"
"path/filepath"
"testing"
"github.com/hashicorp/go-getter"
"github.com/hashicorp/nomad/ci"
"github.com/hashicorp/nomad/client/testutil"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/shoenig/go-landlock"
"github.com/shoenig/test/must"
)
func TestUtil_getURL(t *testing.T) {
ci.Parallel(t)
cases := []struct {
name string
artifact *structs.TaskArtifact
expURL string
expErr *Error
}{{
name: "basic http",
artifact: &structs.TaskArtifact{GetterSource: "example.com"},
expURL: "example.com",
expErr: nil,
}, {
name: "bad url",
artifact: &structs.TaskArtifact{GetterSource: "::example.com"},
expURL: "",
expErr: &Error{
URL: "::example.com",
Err: errors.New(`failed to parse source URL "::example.com": parse "::example.com": missing protocol scheme`),
Recoverable: false,
},
}, {
name: "option",
artifact: &structs.TaskArtifact{
GetterSource: "git::github.com/hashicorp/nomad",
GetterOptions: map[string]string{"sshkey": "abc123"},
},
expURL: "git::github.com/hashicorp/nomad?sshkey=abc123",
expErr: nil,
}, {
name: "github case",
artifact: &structs.TaskArtifact{
GetterSource: "git@github.com:hashicorp/nomad.git",
GetterOptions: map[string]string{"sshkey": "abc123"},
},
expURL: "git@github.com:hashicorp/nomad.git?sshkey=abc123",
expErr: nil,
}}
env := noopTaskEnv("/path/to/task")
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
result, err := getURL(env, tc.artifact)
err2, _ := err.(*Error)
must.Equal(t, tc.expErr, err2)
must.Eq(t, tc.expURL, result)
})
}
}
func TestUtil_getDestination(t *testing.T) {
ci.Parallel(t)
env := noopTaskEnv("/path/to/task")
t.Run("ok", func(t *testing.T) {
result, err := getDestination(env, &structs.TaskArtifact{
RelativeDest: "local/downloads",
})
must.NoError(t, err)
must.Eq(t, "/path/to/task/local/downloads", result)
})
t.Run("escapes", func(t *testing.T) {
result, err := getDestination(env, &structs.TaskArtifact{
RelativeDest: "../../../../../../../etc",
})
must.EqError(t, err, "artifact destination path escapes alloc directory")
must.Eq(t, "", result)
})
}
func TestUtil_getMode(t *testing.T) {
ci.Parallel(t)
cases := []struct {
mode string
exp getter.ClientMode
}{
{mode: structs.GetterModeFile, exp: getter.ClientModeFile},
{mode: structs.GetterModeDir, exp: getter.ClientModeDir},
{mode: structs.GetterModeAny, exp: getter.ClientModeAny},
}
for _, tc := range cases {
t.Run(tc.mode, func(t *testing.T) {
artifact := &structs.TaskArtifact{GetterMode: tc.mode}
result := getMode(artifact)
must.Eq(t, tc.exp, result)
})
}
}
func TestUtil_getHeaders(t *testing.T) {
ci.Parallel(t)
env := upTaskEnv("/path/to/task")
t.Run("empty", func(t *testing.T) {
result := getHeaders(env, &structs.TaskArtifact{
GetterHeaders: nil,
})
must.Nil(t, result)
})
t.Run("replacments", func(t *testing.T) {
result := getHeaders(env, &structs.TaskArtifact{
GetterHeaders: map[string]string{
"color": "red",
"number": "six",
},
})
must.MapEq(t, map[string][]string{
"Color": {"RED"},
"Number": {"SIX"},
}, result)
})
}
func TestUtil_getTaskDir(t *testing.T) {
ci.Parallel(t)
env := noopTaskEnv("/path/to/alloc/task")
allocDir, taskDir := getWritableDirs(env)
must.Eq(t, "/path/to/alloc", allocDir)
must.Eq(t, "/path/to/alloc/task", taskDir)
}
func TestUtil_environment(t *testing.T) {
// not parallel
testutil.RequireLinux(t)
t.Run("default", func(t *testing.T) {
result := environment("/a/b/c", "")
must.Eq(t, []string{
"PATH=/usr/local/bin:/usr/bin:/bin",
"TMPDIR=/a/b/c/tmp",
}, result)
})
t.Run("append", func(t *testing.T) {
t.Setenv("ONE", "1")
t.Setenv("TWO", "2")
result := environment("/a/b/c", "ONE,TWO")
must.Eq(t, []string{
"ONE=1",
"PATH=/usr/local/bin:/usr/bin:/bin",
"TMPDIR=/a/b/c/tmp",
"TWO=2",
}, result)
})
t.Run("override", func(t *testing.T) {
t.Setenv("PATH", "/opt/bin")
t.Setenv("TMPDIR", "/scratch")
result := environment("/a/b/c", "PATH,TMPDIR")
must.Eq(t, []string{
"PATH=/opt/bin",
"TMPDIR=/scratch",
}, result)
})
t.Run("missing", func(t *testing.T) {
result := environment("/a/b/c", "DOES_NOT_EXIST")
must.Eq(t, []string{
"DOES_NOT_EXIST=",
"PATH=/usr/local/bin:/usr/bin:/bin",
"TMPDIR=/a/b/c/tmp",
}, result)
})
}
func TestUtil_loadVersionControlGlobalConfigs(t *testing.T) {
const filePerm = 0o644
const dirPerm = 0o755
fakeEtc := t.TempDir()
var (
gitFile = filepath.Join(fakeEtc, "gitconfig")
hgFile = filepath.Join(fakeEtc, "hgrc")
hgDir = filepath.Join(fakeEtc, "hgrc.d")
)
err := os.WriteFile(gitFile, []byte("git"), filePerm)
must.NoError(t, err)
err = os.WriteFile(hgFile, []byte("hg"), filePerm)
must.NoError(t, err)
err = os.Mkdir(hgDir, dirPerm)
must.NoError(t, err)
paths := loadVersionControlGlobalConfigs(gitFile, hgFile, hgDir)
must.SliceEqual(t, []*landlock.Path{
landlock.File(gitFile, "r"),
landlock.File(hgFile, "r"),
landlock.Dir(hgDir, "r"),
}, paths)
}