Merge pull request #381 from hashicorp/f-getter-refactor
client/drivers: Refactor to use Getter wrapper
This commit is contained in:
commit
e494a24335
|
@ -2,17 +2,15 @@ package driver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"path"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/go-getter"
|
|
||||||
"github.com/hashicorp/nomad/client/allocdir"
|
"github.com/hashicorp/nomad/client/allocdir"
|
||||||
"github.com/hashicorp/nomad/client/config"
|
"github.com/hashicorp/nomad/client/config"
|
||||||
"github.com/hashicorp/nomad/client/driver/executor"
|
"github.com/hashicorp/nomad/client/driver/executor"
|
||||||
|
"github.com/hashicorp/nomad/client/getter"
|
||||||
"github.com/hashicorp/nomad/nomad/structs"
|
"github.com/hashicorp/nomad/nomad/structs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -55,29 +53,24 @@ func (d *ExecDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle,
|
||||||
return nil, fmt.Errorf("missing command for exec driver")
|
return nil, fmt.Errorf("missing command for exec driver")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a location to download the artifact.
|
||||||
|
taskDir, ok := ctx.AllocDir.TaskDirs[d.DriverContext.taskName]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("Could not find task directory for task: %v", d.DriverContext.taskName)
|
||||||
|
}
|
||||||
|
|
||||||
// Check if an artificat is specified and attempt to download it
|
// Check if an artificat is specified and attempt to download it
|
||||||
source, ok := task.Config["artifact_source"]
|
source, ok := task.Config["artifact_source"]
|
||||||
if ok && source != "" {
|
if ok && source != "" {
|
||||||
// Proceed to download an artifact to be executed.
|
// Proceed to download an artifact to be executed.
|
||||||
// We use go-getter to support a variety of protocols, but need to change
|
_, err := getter.GetArtifact(
|
||||||
// file permissions of the resulted download to be executable
|
filepath.Join(taskDir, allocdir.TaskLocal),
|
||||||
|
task.Config["artifact_source"],
|
||||||
// Create a location to download the artifact.
|
task.Config["checksum"],
|
||||||
taskDir, ok := ctx.AllocDir.TaskDirs[d.DriverContext.taskName]
|
d.logger,
|
||||||
if !ok {
|
)
|
||||||
return nil, fmt.Errorf("Could not find task directory for task: %v", d.DriverContext.taskName)
|
if err != nil {
|
||||||
}
|
return nil, err
|
||||||
destDir := filepath.Join(taskDir, allocdir.TaskLocal)
|
|
||||||
|
|
||||||
artifactName := path.Base(source)
|
|
||||||
artifactFile := filepath.Join(destDir, artifactName)
|
|
||||||
if err := getter.GetFile(artifactFile, source); err != nil {
|
|
||||||
return nil, fmt.Errorf("Error downloading artifact for Exec driver: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add execution permissions to the newly downloaded artifact
|
|
||||||
if err := syscall.Chmod(artifactFile, 0755); err != nil {
|
|
||||||
log.Printf("[ERR] driver.exec: Error making artifact executable: %s", err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -123,11 +123,12 @@ func TestExecDriver_Start_Wait(t *testing.T) {
|
||||||
func TestExecDriver_Start_Artifact_basic(t *testing.T) {
|
func TestExecDriver_Start_Artifact_basic(t *testing.T) {
|
||||||
ctestutils.ExecCompatible(t)
|
ctestutils.ExecCompatible(t)
|
||||||
file := "hi_linux_amd64"
|
file := "hi_linux_amd64"
|
||||||
|
checksum := "sha256:6f99b4c5184726e601ecb062500aeb9537862434dfe1898dbe5c68d9f50c179c"
|
||||||
|
|
||||||
task := &structs.Task{
|
task := &structs.Task{
|
||||||
Name: "sleep",
|
Name: "sleep",
|
||||||
Config: map[string]string{
|
Config: map[string]string{
|
||||||
"artifact_source": fmt.Sprintf("https://dl.dropboxusercontent.com/u/47675/jar_thing/%s", file),
|
"artifact_source": fmt.Sprintf("https://dl.dropboxusercontent.com/u/47675/jar_thing/%s?checksum=%s", file, checksum),
|
||||||
"command": filepath.Join("$NOMAD_TASK_DIR", file),
|
"command": filepath.Join("$NOMAD_TASK_DIR", file),
|
||||||
},
|
},
|
||||||
Resources: basicResources,
|
Resources: basicResources,
|
||||||
|
|
|
@ -4,17 +4,16 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/go-getter"
|
|
||||||
"github.com/hashicorp/nomad/client/allocdir"
|
"github.com/hashicorp/nomad/client/allocdir"
|
||||||
"github.com/hashicorp/nomad/client/config"
|
"github.com/hashicorp/nomad/client/config"
|
||||||
"github.com/hashicorp/nomad/client/driver/executor"
|
"github.com/hashicorp/nomad/client/driver/executor"
|
||||||
|
"github.com/hashicorp/nomad/client/getter"
|
||||||
"github.com/hashicorp/nomad/nomad/structs"
|
"github.com/hashicorp/nomad/nomad/structs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -89,26 +88,24 @@ func (d *JavaDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *JavaDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, error) {
|
func (d *JavaDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, error) {
|
||||||
// Get the jar source
|
|
||||||
source, ok := task.Config["jar_source"]
|
|
||||||
if !ok || source == "" {
|
|
||||||
return nil, fmt.Errorf("missing jar source for Java Jar driver")
|
|
||||||
}
|
|
||||||
|
|
||||||
taskDir, ok := ctx.AllocDir.TaskDirs[d.DriverContext.taskName]
|
taskDir, ok := ctx.AllocDir.TaskDirs[d.DriverContext.taskName]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("Could not find task directory for task: %v", d.DriverContext.taskName)
|
return nil, fmt.Errorf("Could not find task directory for task: %v", d.DriverContext.taskName)
|
||||||
}
|
}
|
||||||
|
|
||||||
destDir := filepath.Join(taskDir, allocdir.TaskLocal)
|
// Proceed to download an artifact to be executed.
|
||||||
|
path, err := getter.GetArtifact(
|
||||||
// Create a location to download the binary.
|
filepath.Join(taskDir, allocdir.TaskLocal),
|
||||||
jarName := path.Base(source)
|
task.Config["artifact_source"],
|
||||||
jarPath := filepath.Join(destDir, jarName)
|
task.Config["checksum"],
|
||||||
if err := getter.GetFile(jarPath, source); err != nil {
|
d.logger,
|
||||||
return nil, fmt.Errorf("Error downloading source for Java driver: %s", err)
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jarName := filepath.Base(path)
|
||||||
|
|
||||||
// Get the environment variables.
|
// Get the environment variables.
|
||||||
envVars := TaskEnvironmentVariables(ctx, task)
|
envVars := TaskEnvironmentVariables(ctx, task)
|
||||||
|
|
||||||
|
|
|
@ -97,10 +97,9 @@ func TestJavaDriver_Start_Wait(t *testing.T) {
|
||||||
task := &structs.Task{
|
task := &structs.Task{
|
||||||
Name: "demo-app",
|
Name: "demo-app",
|
||||||
Config: map[string]string{
|
Config: map[string]string{
|
||||||
"jar_source": "https://dl.dropboxusercontent.com/u/47675/jar_thing/demoapp.jar",
|
"artifact_source": "https://dl.dropboxusercontent.com/u/47675/jar_thing/demoapp.jar",
|
||||||
// "jar_source": "https://s3-us-west-2.amazonaws.com/java-jar-thing/demoapp.jar",
|
"jvm_options": "-Xmx2048m -Xms256m",
|
||||||
// "args": "-d64",
|
"checksum": "sha256:58d6e8130308d32e197c5108edd4f56ddf1417408f743097c2e662df0f0b17c8",
|
||||||
"jvm_options": "-Xmx2048m -Xms256m",
|
|
||||||
},
|
},
|
||||||
Resources: basicResources,
|
Resources: basicResources,
|
||||||
}
|
}
|
||||||
|
@ -145,9 +144,7 @@ func TestJavaDriver_Start_Kill_Wait(t *testing.T) {
|
||||||
task := &structs.Task{
|
task := &structs.Task{
|
||||||
Name: "demo-app",
|
Name: "demo-app",
|
||||||
Config: map[string]string{
|
Config: map[string]string{
|
||||||
"jar_source": "https://dl.dropboxusercontent.com/u/47675/jar_thing/demoapp.jar",
|
"artifact_source": "https://dl.dropboxusercontent.com/u/47675/jar_thing/demoapp.jar",
|
||||||
// "jar_source": "https://s3-us-west-2.amazonaws.com/java-jar-thing/demoapp.jar",
|
|
||||||
// "args": "-d64",
|
|
||||||
},
|
},
|
||||||
Resources: basicResources,
|
Resources: basicResources,
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,8 @@ package driver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/sha256"
|
|
||||||
"encoding/hex"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
@ -17,9 +14,9 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/go-getter"
|
|
||||||
"github.com/hashicorp/nomad/client/allocdir"
|
"github.com/hashicorp/nomad/client/allocdir"
|
||||||
"github.com/hashicorp/nomad/client/config"
|
"github.com/hashicorp/nomad/client/config"
|
||||||
|
"github.com/hashicorp/nomad/client/getter"
|
||||||
"github.com/hashicorp/nomad/nomad/structs"
|
"github.com/hashicorp/nomad/nomad/structs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -82,7 +79,7 @@ func (d *QemuDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool,
|
||||||
// image and save it to the Drivers Allocation Dir
|
// image and save it to the Drivers Allocation Dir
|
||||||
func (d *QemuDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, error) {
|
func (d *QemuDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, error) {
|
||||||
// Get the image source
|
// Get the image source
|
||||||
source, ok := task.Config["image_source"]
|
source, ok := task.Config["artifact_source"]
|
||||||
if !ok || source == "" {
|
if !ok || source == "" {
|
||||||
return nil, fmt.Errorf("Missing source image Qemu driver")
|
return nil, fmt.Errorf("Missing source image Qemu driver")
|
||||||
}
|
}
|
||||||
|
@ -99,34 +96,18 @@ func (d *QemuDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle,
|
||||||
return nil, fmt.Errorf("Could not find task directory for task: %v", d.DriverContext.taskName)
|
return nil, fmt.Errorf("Could not find task directory for task: %v", d.DriverContext.taskName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a location to download the binary.
|
// Proceed to download an artifact to be executed.
|
||||||
destDir := filepath.Join(taskDir, allocdir.TaskLocal)
|
vmPath, err := getter.GetArtifact(
|
||||||
vmID := fmt.Sprintf("qemu-vm-%s-%s", structs.GenerateUUID(), filepath.Base(source))
|
filepath.Join(taskDir, allocdir.TaskLocal),
|
||||||
vmPath := filepath.Join(destDir, vmID)
|
task.Config["artifact_source"],
|
||||||
if err := getter.GetFile(vmPath, source); err != nil {
|
task.Config["checksum"],
|
||||||
return nil, fmt.Errorf("Error downloading artifact for Qemu driver: %s", err)
|
d.logger,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute and check checksum
|
vmID := filepath.Base(vmPath)
|
||||||
if check, ok := task.Config["checksum"]; ok {
|
|
||||||
d.logger.Printf("[DEBUG] Running checksum on (%s)", vmID)
|
|
||||||
hasher := sha256.New()
|
|
||||||
file, err := os.Open(vmPath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Failed to open file for checksum")
|
|
||||||
}
|
|
||||||
|
|
||||||
defer file.Close()
|
|
||||||
io.Copy(hasher, file)
|
|
||||||
|
|
||||||
sum := hex.EncodeToString(hasher.Sum(nil))
|
|
||||||
if sum != check {
|
|
||||||
return nil, fmt.Errorf(
|
|
||||||
"Error in Qemu: checksums did not match.\nExpected (%s), got (%s)",
|
|
||||||
check,
|
|
||||||
sum)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse configuration arguments
|
// Parse configuration arguments
|
||||||
// Create the base arguments
|
// Create the base arguments
|
||||||
|
|
|
@ -54,10 +54,10 @@ func TestQemuDriver_Start(t *testing.T) {
|
||||||
task := &structs.Task{
|
task := &structs.Task{
|
||||||
Name: "linux",
|
Name: "linux",
|
||||||
Config: map[string]string{
|
Config: map[string]string{
|
||||||
"image_source": "https://dl.dropboxusercontent.com/u/47675/jar_thing/linux-0.2.img",
|
"artifact_source": "https://dl.dropboxusercontent.com/u/47675/jar_thing/linux-0.2.img",
|
||||||
"checksum": "a5e836985934c3392cbbd9b26db55a7d35a8d7ae1deb7ca559dd9c0159572544",
|
"checksum": "sha256:a5e836985934c3392cbbd9b26db55a7d35a8d7ae1deb7ca559dd9c0159572544",
|
||||||
"accelerator": "tcg",
|
"accelerator": "tcg",
|
||||||
"guest_ports": "22,8080",
|
"guest_ports": "22,8080",
|
||||||
},
|
},
|
||||||
Resources: &structs.Resources{
|
Resources: &structs.Resources{
|
||||||
MemoryMB: 512,
|
MemoryMB: 512,
|
||||||
|
@ -103,11 +103,11 @@ func TestQemuDriver_RequiresMemory(t *testing.T) {
|
||||||
task := &structs.Task{
|
task := &structs.Task{
|
||||||
Name: "linux",
|
Name: "linux",
|
||||||
Config: map[string]string{
|
Config: map[string]string{
|
||||||
"image_source": "https://dl.dropboxusercontent.com/u/47675/jar_thing/linux-0.2.img",
|
"artifact_source": "https://dl.dropboxusercontent.com/u/47675/jar_thing/linux-0.2.img",
|
||||||
"accelerator": "tcg",
|
"accelerator": "tcg",
|
||||||
"host_port": "8080",
|
"host_port": "8080",
|
||||||
"guest_port": "8081",
|
"guest_port": "8081",
|
||||||
"checksum": "a5e836985934c3392cbbd9b26db55a7d35a8d7ae1deb7ca559dd9c0159572544",
|
"checksum": "sha256:a5e836985934c3392cbbd9b26db55a7d35a8d7ae1deb7ca559dd9c0159572544",
|
||||||
// ssh u/p would be here
|
// ssh u/p would be here
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,21 +2,18 @@ package driver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/go-getter"
|
|
||||||
"github.com/hashicorp/nomad/client/allocdir"
|
"github.com/hashicorp/nomad/client/allocdir"
|
||||||
"github.com/hashicorp/nomad/client/config"
|
"github.com/hashicorp/nomad/client/config"
|
||||||
"github.com/hashicorp/nomad/client/driver/args"
|
"github.com/hashicorp/nomad/client/driver/args"
|
||||||
|
"github.com/hashicorp/nomad/client/getter"
|
||||||
"github.com/hashicorp/nomad/nomad/structs"
|
"github.com/hashicorp/nomad/nomad/structs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -83,23 +80,14 @@ func (d *RawExecDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandl
|
||||||
source, ok := task.Config["artifact_source"]
|
source, ok := task.Config["artifact_source"]
|
||||||
if ok && source != "" {
|
if ok && source != "" {
|
||||||
// Proceed to download an artifact to be executed.
|
// Proceed to download an artifact to be executed.
|
||||||
// We use go-getter to support a variety of protocols, but need to change
|
_, err := getter.GetArtifact(
|
||||||
// file permissions of the resulted download to be executable
|
filepath.Join(taskDir, allocdir.TaskLocal),
|
||||||
|
task.Config["artifact_source"],
|
||||||
// Create a location to download the artifact.
|
task.Config["checksum"],
|
||||||
destDir := filepath.Join(taskDir, allocdir.TaskLocal)
|
d.logger,
|
||||||
|
)
|
||||||
artifactName := path.Base(source)
|
if err != nil {
|
||||||
artifactFile := filepath.Join(destDir, artifactName)
|
return nil, err
|
||||||
if err := getter.GetFile(artifactFile, source); err != nil {
|
|
||||||
return nil, fmt.Errorf("Error downloading artifact for Raw Exec driver: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add execution permissions to the newly downloaded artifact
|
|
||||||
if runtime.GOOS != "windows" {
|
|
||||||
if err := syscall.Chmod(artifactFile, 0755); err != nil {
|
|
||||||
log.Printf("[ERR] driver.raw_exec: Error making artifact executable: %s", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,12 +94,14 @@ func TestRawExecDriver_StartOpen_Wait(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRawExecDriver_Start_Artifact_basic(t *testing.T) {
|
func TestRawExecDriver_Start_Artifact_basic(t *testing.T) {
|
||||||
var file string
|
var file, checksum string
|
||||||
switch runtime.GOOS {
|
switch runtime.GOOS {
|
||||||
case "darwin":
|
case "darwin":
|
||||||
file = "hi_darwin_amd64"
|
file = "hi_darwin_amd64"
|
||||||
|
checksum = "md5:d7f2fdb13b36dcb7407721d78926b335"
|
||||||
default:
|
default:
|
||||||
file = "hi_linux_amd64"
|
file = "hi_linux_amd64"
|
||||||
|
checksum = "md5:a9b14903a8942748e4f8474e11f795d3"
|
||||||
}
|
}
|
||||||
|
|
||||||
task := &structs.Task{
|
task := &structs.Task{
|
||||||
|
@ -107,6 +109,7 @@ func TestRawExecDriver_Start_Artifact_basic(t *testing.T) {
|
||||||
Config: map[string]string{
|
Config: map[string]string{
|
||||||
"artifact_source": fmt.Sprintf("https://dl.dropboxusercontent.com/u/47675/jar_thing/%s", file),
|
"artifact_source": fmt.Sprintf("https://dl.dropboxusercontent.com/u/47675/jar_thing/%s", file),
|
||||||
"command": filepath.Join("$NOMAD_TASK_DIR", file),
|
"command": filepath.Join("$NOMAD_TASK_DIR", file),
|
||||||
|
"checksum": checksum,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
driverCtx := testDriverContext(task.Name)
|
driverCtx := testDriverContext(task.Name)
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
package getter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net/url"
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
gg "github.com/hashicorp/go-getter"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetArtifact(destDir, source, checksum string, logger *log.Logger) (string, error) {
|
||||||
|
if source == "" {
|
||||||
|
return "", fmt.Errorf("Source url is empty in Artifact Getter")
|
||||||
|
}
|
||||||
|
u, err := url.Parse(source)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// if checksum is seperate, apply to source
|
||||||
|
if checksum != "" {
|
||||||
|
source = strings.Join([]string{source, fmt.Sprintf("checksum=%s", checksum)}, "?")
|
||||||
|
logger.Printf("[DEBUG] client.getter: Applying checksum to Artifact Source URL, new url: %s", source)
|
||||||
|
}
|
||||||
|
|
||||||
|
artifactFile := filepath.Join(destDir, path.Base(u.Path))
|
||||||
|
if err := gg.GetFile(artifactFile, source); err != nil {
|
||||||
|
return "", fmt.Errorf("Error downloading artifact: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add execution permissions to the newly downloaded artifact
|
||||||
|
if runtime.GOOS != "windows" {
|
||||||
|
if err := syscall.Chmod(artifactFile, 0755); err != nil {
|
||||||
|
logger.Printf("[ERR] driver.raw_exec: Error making artifact executable: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return artifactFile, nil
|
||||||
|
}
|
|
@ -0,0 +1,111 @@
|
||||||
|
package getter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetArtifact_basic(t *testing.T) {
|
||||||
|
|
||||||
|
logger := log.New(os.Stderr, "", log.LstdFlags)
|
||||||
|
|
||||||
|
// TODO: Use http.TestServer to serve these files from fixtures dir
|
||||||
|
passing := []struct {
|
||||||
|
Source, Checksum string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"https://dl.dropboxusercontent.com/u/47675/jar_thing/hi_darwin_amd64",
|
||||||
|
"sha256:66aa0f05fc0cfcf1e5ed8cc5307b5df51e33871d6b295a60e0f9f6dd573da977",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"https://dl.dropboxusercontent.com/u/47675/jar_thing/hi_linux_amd64",
|
||||||
|
"sha256:6f99b4c5184726e601ecb062500aeb9537862434dfe1898dbe5c68d9f50c179c",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"https://dl.dropboxusercontent.com/u/47675/jar_thing/hi_linux_amd64",
|
||||||
|
"md5:a9b14903a8942748e4f8474e11f795d3",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"https://dl.dropboxusercontent.com/u/47675/jar_thing/hi_linux_amd64?checksum=sha256:6f99b4c5184726e601ecb062500aeb9537862434dfe1898dbe5c68d9f50c179c",
|
||||||
|
"",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"https://dl.dropboxusercontent.com/u/47675/jar_thing/hi_linux_amd64",
|
||||||
|
"",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, p := range passing {
|
||||||
|
destDir, err := ioutil.TempDir("", fmt.Sprintf("nomad-test-%d", i))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error in TestGetArtifact_basic makeing TempDir: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
path, err := GetArtifact(destDir, p.Source, p.Checksum, logger)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("TestGetArtifact_basic unexpected failure here: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.Checksum != "" {
|
||||||
|
if ok := strings.Contains(path, p.Checksum); ok {
|
||||||
|
t.Fatalf("path result should not contain the checksum, got: %s", path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify artifact exists
|
||||||
|
if _, err := os.Stat(path); err != nil {
|
||||||
|
t.Fatalf("source path error: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetArtifact_fails(t *testing.T) {
|
||||||
|
|
||||||
|
logger := log.New(os.Stderr, "", log.LstdFlags)
|
||||||
|
|
||||||
|
failing := []struct {
|
||||||
|
Source, Checksum string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"",
|
||||||
|
"sha256:66aa0f05fc0cfcf1e5ed8cc5307b5d",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/u/47675/jar_thing/hi_darwin_amd64",
|
||||||
|
"sha256:66aa0f05fc0cfcf1e5ed8cc5307b5d",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"https://dl.dropboxusercontent.com/u/47675/jar_thing/hi_darwin_amd64",
|
||||||
|
"sha256:66aa0f05fc0cfcf1e5ed8cc5307b5d",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"https://dl.dropboxusercontent.com/u/47675/jar_thing/hi_linux_amd64",
|
||||||
|
"sha257:6f99b4c5184726e601ecb062500aeb9537862434dfe1898dbe5c68d9f50c179c",
|
||||||
|
},
|
||||||
|
// malformed checksum
|
||||||
|
{
|
||||||
|
"https://dl.dropboxusercontent.com/u/47675/jar_thing/hi_linux_amd64",
|
||||||
|
"6f99b4c5184726e601ecb062500aeb9537862434dfe1898dbe5c68d9f50c179c",
|
||||||
|
},
|
||||||
|
// 404
|
||||||
|
{
|
||||||
|
"https://dl.dropboxusercontent.com/u/47675/jar_thing/hi_linux_amd86",
|
||||||
|
"",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for i, p := range failing {
|
||||||
|
destDir, err := ioutil.TempDir("", fmt.Sprintf("nomad-test-%d", i))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error in TestGetArtifact_basic makeing TempDir: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = GetArtifact(destDir, p.Source, p.Checksum, logger)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("TestGetArtifact_basic expected failure, but got none")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,6 +24,10 @@ The `exec` driver supports the following configuration in the job spec:
|
||||||
* `artifact_source` – (Optional) Source location of an executable artifact. Must be accessible
|
* `artifact_source` – (Optional) Source location of an executable artifact. Must be accessible
|
||||||
from the Nomad client. If you specify an `artifact_source` to be executed, you
|
from the Nomad client. If you specify an `artifact_source` to be executed, you
|
||||||
must reference it in the `command` as show in the examples below
|
must reference it in the `command` as show in the examples below
|
||||||
|
* `checksum` - **(Optional)** The checksum type and value for the `artifact_source` image.
|
||||||
|
The format is `type:value`, where type is any of `md5`, `sha1`, `sha256`, or `sha512`,
|
||||||
|
and the value is the computed checksum. If a checksum is supplied and does not
|
||||||
|
match the downloaded artifact, the driver will fail to start
|
||||||
* `args` - The argument list to the command, space seperated. Optional.
|
* `args` - The argument list to the command, space seperated. Optional.
|
||||||
|
|
||||||
## Client Requirements
|
## Client Requirements
|
||||||
|
@ -53,6 +57,7 @@ To execute a binary specified by `artifact_source`:
|
||||||
```
|
```
|
||||||
config {
|
config {
|
||||||
artifact_source = "https://dl.dropboxusercontent.com/u/1234/binary.bin"
|
artifact_source = "https://dl.dropboxusercontent.com/u/1234/binary.bin"
|
||||||
|
checksum = "sha256:abd123445ds4555555555"
|
||||||
command = "$NOMAD_TASK_DIR/binary.bin"
|
command = "$NOMAD_TASK_DIR/binary.bin"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
|
@ -18,8 +18,12 @@ HTTP from the Nomad client.
|
||||||
|
|
||||||
The `java` driver supports the following configuration in the job spec:
|
The `java` driver supports the following configuration in the job spec:
|
||||||
|
|
||||||
* `jar_source` - **(Required)** The hosted location of the source Jar file. Must be accessible
|
* `artifact_source` - **(Required)** The hosted location of the source Jar file. Must be accessible
|
||||||
from the Nomad client
|
from the Nomad client
|
||||||
|
* `checksum` - **(Optional)** The checksum type and value for the `artifact_source` image.
|
||||||
|
The format is `type:value`, where type is any of `md5`, `sha1`, `sha256`, or `sha512`,
|
||||||
|
and the value is the computed checksum. If a checksum is supplied and does not
|
||||||
|
match the downloaded artifact, the driver will fail to start
|
||||||
|
|
||||||
* `args` - **(Optional)** The argument list for the `java` command, space separated.
|
* `args` - **(Optional)** The argument list for the `java` command, space separated.
|
||||||
|
|
||||||
|
@ -29,10 +33,27 @@ from the Nomad client
|
||||||
## Client Requirements
|
## Client Requirements
|
||||||
|
|
||||||
The `java` driver requires Java to be installed and in your systems `$PATH`.
|
The `java` driver requires Java to be installed and in your systems `$PATH`.
|
||||||
The `jar_source` must be accessible by the node running Nomad. This can be an
|
The `artifact_source` must be accessible by the node running Nomad. This can be an
|
||||||
internal source, private to your cluster, but it must be reachable by the client
|
internal source, private to your cluster, but it must be reachable by the client
|
||||||
over HTTP.
|
over HTTP.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
A simple config block to run a Java Jar:
|
||||||
|
|
||||||
|
```json
|
||||||
|
# Define a task to run
|
||||||
|
task "web" {
|
||||||
|
# Run a Java Jar
|
||||||
|
driver = "java"
|
||||||
|
|
||||||
|
config {
|
||||||
|
artifact_source = "https://dl.dropboxusercontent.com/u/1234/hello.jar"
|
||||||
|
checksum = "md5:123445555555555"
|
||||||
|
jvm_options = "-Xmx2048m -Xms256m"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Client Attributes
|
## Client Attributes
|
||||||
|
|
||||||
The `java` driver will set the following client attributes:
|
The `java` driver will set the following client attributes:
|
||||||
|
|
|
@ -23,10 +23,12 @@ The `Qemu` driver can execute any regular `qemu` image (e.g. `qcow`, `img`,
|
||||||
|
|
||||||
The `Qemu` driver supports the following configuration in the job spec:
|
The `Qemu` driver supports the following configuration in the job spec:
|
||||||
|
|
||||||
* `image_source` - **(Required)** The hosted location of the source Qemu image. Must be accessible
|
* `artifact_source` - **(Required)** The hosted location of the source Qemu image. Must be accessible
|
||||||
from the Nomad client, via HTTP.
|
from the Nomad client, via HTTP.
|
||||||
* `checksum` - **(Required)** The SHA256 checksum of the `qemu` image. If the
|
* `checksum` - **(Optional)** The checksum type and value for the `artifact_source` image.
|
||||||
checksums do not match, the `Qemu` driver will fail to start the image
|
The format is `type:value`, where type is any of `md5`, `sha1`, `sha256`, or `sha512`,
|
||||||
|
and the value is the computed checksum. If a checksum is supplied and does not
|
||||||
|
match the downloaded artifact, the driver will fail to start
|
||||||
* `accelerator` - (Optional) The type of accelerator to use in the invocation.
|
* `accelerator` - (Optional) The type of accelerator to use in the invocation.
|
||||||
If the host machine has `Qemu` installed with KVM support, users can specify `kvm` for the `accelerator`. Default is `tcg`
|
If the host machine has `Qemu` installed with KVM support, users can specify `kvm` for the `accelerator`. Default is `tcg`
|
||||||
* `host_port` - **(Required)** Port on the host machine to forward to the guest
|
* `host_port` - **(Required)** Port on the host machine to forward to the guest
|
||||||
|
@ -38,7 +40,7 @@ in the `Task` specification
|
||||||
## Client Requirements
|
## Client Requirements
|
||||||
|
|
||||||
The `Qemu` driver requires Qemu to be installed and in your system's `$PATH`.
|
The `Qemu` driver requires Qemu to be installed and in your system's `$PATH`.
|
||||||
The `image_source` must be accessible by the node running Nomad. This can be an
|
The `artifact_source` must be accessible by the node running Nomad. This can be an
|
||||||
internal source, private to your cluster, but it must be reachable by the client
|
internal source, private to your cluster, but it must be reachable by the client
|
||||||
over HTTP.
|
over HTTP.
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,10 @@ The `raw_exec` driver supports the following configuration in the job spec:
|
||||||
* `artifact_source` – (Optional) Source location of an executable artifact. Must be accessible
|
* `artifact_source` – (Optional) Source location of an executable artifact. Must be accessible
|
||||||
from the Nomad client. If you specify an `artifact_source` to be executed, you
|
from the Nomad client. If you specify an `artifact_source` to be executed, you
|
||||||
must reference it in the `command` as show in the examples below
|
must reference it in the `command` as show in the examples below
|
||||||
|
* `checksum` - **(Optional)** The checksum type and value for the `artifact_source` image.
|
||||||
|
The format is `type:value`, where type is any of `md5`, `sha1`, `sha256`, or `sha512`,
|
||||||
|
and the value is the computed checksum. If a checksum is supplied and does not
|
||||||
|
match the downloaded artifact, the driver will fail to start
|
||||||
* `args` - The argument list to the command, space seperated. Optional.
|
* `args` - The argument list to the command, space seperated. Optional.
|
||||||
|
|
||||||
## Client Requirements
|
## Client Requirements
|
||||||
|
@ -57,6 +61,7 @@ To execute a binary specified by `artifact_source`:
|
||||||
```
|
```
|
||||||
config {
|
config {
|
||||||
artifact_source = "https://dl.dropboxusercontent.com/u/1234/binary.bin"
|
artifact_source = "https://dl.dropboxusercontent.com/u/1234/binary.bin"
|
||||||
|
checksum = "sha256:133jifjiofu9090fsadjofsdjlk"
|
||||||
command = "$NOMAD_TASK_DIR/binary.bin"
|
command = "$NOMAD_TASK_DIR/binary.bin"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
Loading…
Reference in New Issue