github.com/dkerwin/nomad@v0.3.3-0.20160525181927-74554135514b/client/getter/getter_test.go (about)

     1  package getter
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"log"
     7  	"net/http"
     8  	"net/http/httptest"
     9  	"os"
    10  	"path/filepath"
    11  	"reflect"
    12  	"strings"
    13  	"testing"
    14  
    15  	"github.com/hashicorp/nomad/client/driver/env"
    16  	"github.com/hashicorp/nomad/nomad/mock"
    17  	"github.com/hashicorp/nomad/nomad/structs"
    18  )
    19  
    20  func TestGetArtifact_FileAndChecksum(t *testing.T) {
    21  	// Create the test server hosting the file to download
    22  	ts := httptest.NewServer(http.FileServer(http.Dir(filepath.Dir("./test-fixtures/"))))
    23  	defer ts.Close()
    24  
    25  	// Create a temp directory to download into
    26  	taskDir, err := ioutil.TempDir("", "nomad-test")
    27  	if err != nil {
    28  		t.Fatalf("failed to make temp directory: %v", err)
    29  	}
    30  	defer os.RemoveAll(taskDir)
    31  
    32  	// Create the artifact
    33  	file := "test.sh"
    34  	artifact := &structs.TaskArtifact{
    35  		GetterSource: fmt.Sprintf("%s/%s", ts.URL, file),
    36  		GetterOptions: map[string]string{
    37  			"checksum": "md5:bce963762aa2dbfed13caf492a45fb72",
    38  		},
    39  	}
    40  
    41  	// Download the artifact
    42  	taskEnv := env.NewTaskEnvironment(mock.Node())
    43  	logger := log.New(os.Stderr, "", log.LstdFlags)
    44  	if err := GetArtifact(taskEnv, artifact, taskDir, logger); err != nil {
    45  		t.Fatalf("GetArtifact failed: %v", err)
    46  	}
    47  
    48  	// Verify artifact exists
    49  	if _, err := os.Stat(filepath.Join(taskDir, file)); err != nil {
    50  		t.Fatalf("file not found: %s", err)
    51  	}
    52  }
    53  
    54  func TestGetArtifact_File_RelativeDest(t *testing.T) {
    55  	// Create the test server hosting the file to download
    56  	ts := httptest.NewServer(http.FileServer(http.Dir(filepath.Dir("./test-fixtures/"))))
    57  	defer ts.Close()
    58  
    59  	// Create a temp directory to download into
    60  	taskDir, err := ioutil.TempDir("", "nomad-test")
    61  	if err != nil {
    62  		t.Fatalf("failed to make temp directory: %v", err)
    63  	}
    64  	defer os.RemoveAll(taskDir)
    65  
    66  	// Create the artifact
    67  	file := "test.sh"
    68  	relative := "foo/"
    69  	artifact := &structs.TaskArtifact{
    70  		GetterSource: fmt.Sprintf("%s/%s", ts.URL, file),
    71  		GetterOptions: map[string]string{
    72  			"checksum": "md5:bce963762aa2dbfed13caf492a45fb72",
    73  		},
    74  		RelativeDest: relative,
    75  	}
    76  
    77  	// Download the artifact
    78  	taskEnv := env.NewTaskEnvironment(mock.Node())
    79  	logger := log.New(os.Stderr, "", log.LstdFlags)
    80  	if err := GetArtifact(taskEnv, artifact, taskDir, logger); err != nil {
    81  		t.Fatalf("GetArtifact failed: %v", err)
    82  	}
    83  
    84  	// Verify artifact was downloaded to the correct path
    85  	if _, err := os.Stat(filepath.Join(taskDir, relative, file)); err != nil {
    86  		t.Fatalf("file not found: %s", err)
    87  	}
    88  }
    89  
    90  func TestGetGetterUrl_Interprolation(t *testing.T) {
    91  	// Create the artifact
    92  	artifact := &structs.TaskArtifact{
    93  		GetterSource: "${NOMAD_META_ARTIFACT}",
    94  	}
    95  
    96  	url := "foo.com"
    97  	taskEnv := env.NewTaskEnvironment(mock.Node()).SetTaskMeta(map[string]string{"artifact": url})
    98  	act, err := getGetterUrl(taskEnv, artifact)
    99  	if err != nil {
   100  		t.Fatalf("getGetterUrl() failed: %v", err)
   101  	}
   102  
   103  	if act != url {
   104  		t.Fatalf("getGetterUrl() returned %q; want %q", act, url)
   105  	}
   106  }
   107  
   108  func TestGetArtifact_InvalidChecksum(t *testing.T) {
   109  	// Create the test server hosting the file to download
   110  	ts := httptest.NewServer(http.FileServer(http.Dir(filepath.Dir("./test-fixtures/"))))
   111  	defer ts.Close()
   112  
   113  	// Create a temp directory to download into
   114  	taskDir, err := ioutil.TempDir("", "nomad-test")
   115  	if err != nil {
   116  		t.Fatalf("failed to make temp directory: %v", err)
   117  	}
   118  	defer os.RemoveAll(taskDir)
   119  
   120  	// Create the artifact with an incorrect checksum
   121  	file := "test.sh"
   122  	artifact := &structs.TaskArtifact{
   123  		GetterSource: fmt.Sprintf("%s/%s", ts.URL, file),
   124  		GetterOptions: map[string]string{
   125  			"checksum": "md5:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
   126  		},
   127  	}
   128  
   129  	// Download the artifact and expect an error
   130  	taskEnv := env.NewTaskEnvironment(mock.Node())
   131  	logger := log.New(os.Stderr, "", log.LstdFlags)
   132  	if err := GetArtifact(taskEnv, artifact, taskDir, logger); err == nil {
   133  		t.Fatalf("GetArtifact should have failed")
   134  	}
   135  }
   136  
   137  func createContents(basedir string, fileContents map[string]string, t *testing.T) {
   138  	for relPath, content := range fileContents {
   139  		folder := basedir
   140  		if strings.Index(relPath, "/") != -1 {
   141  			// Create the folder.
   142  			folder = filepath.Join(basedir, filepath.Dir(relPath))
   143  			if err := os.Mkdir(folder, 0777); err != nil {
   144  				t.Fatalf("failed to make directory: %v", err)
   145  			}
   146  		}
   147  
   148  		// Create a file in the existing folder.
   149  		file := filepath.Join(folder, filepath.Base(relPath))
   150  		if err := ioutil.WriteFile(file, []byte(content), 0777); err != nil {
   151  			t.Fatalf("failed to write data to file %v: %v", file, err)
   152  		}
   153  	}
   154  }
   155  
   156  func checkContents(basedir string, fileContents map[string]string, t *testing.T) {
   157  	for relPath, content := range fileContents {
   158  		path := filepath.Join(basedir, relPath)
   159  		actual, err := ioutil.ReadFile(path)
   160  		if err != nil {
   161  			t.Fatalf("failed to read file %q: %v", path, err)
   162  		}
   163  
   164  		if !reflect.DeepEqual(actual, []byte(content)) {
   165  			t.Fatalf("%q: expected %q; got %q", path, content, string(actual))
   166  		}
   167  	}
   168  }
   169  
   170  func TestGetArtifact_Archive(t *testing.T) {
   171  	// Create the test server hosting the file to download
   172  	ts := httptest.NewServer(http.FileServer(http.Dir(filepath.Dir("./test-fixtures/"))))
   173  	defer ts.Close()
   174  
   175  	// Create a temp directory to download into and create some of the same
   176  	// files that exist in the artifact to ensure they are overridden
   177  	taskDir, err := ioutil.TempDir("", "nomad-test")
   178  	if err != nil {
   179  		t.Fatalf("failed to make temp directory: %v", err)
   180  	}
   181  	defer os.RemoveAll(taskDir)
   182  
   183  	create := map[string]string{
   184  		"exist/my.config": "to be replaced",
   185  		"untouched":       "existing top-level",
   186  	}
   187  	createContents(taskDir, create, t)
   188  
   189  	file := "archive.tar.gz"
   190  	artifact := &structs.TaskArtifact{
   191  		GetterSource: fmt.Sprintf("%s/%s", ts.URL, file),
   192  		GetterOptions: map[string]string{
   193  			"checksum": "sha1:20bab73c72c56490856f913cf594bad9a4d730f6",
   194  		},
   195  	}
   196  
   197  	taskEnv := env.NewTaskEnvironment(mock.Node())
   198  	logger := log.New(os.Stderr, "", log.LstdFlags)
   199  	if err := GetArtifact(taskEnv, artifact, taskDir, logger); err != nil {
   200  		t.Fatalf("GetArtifact failed: %v", err)
   201  	}
   202  
   203  	// Verify the unarchiving overrode files properly.
   204  	expected := map[string]string{
   205  		"untouched":       "existing top-level",
   206  		"exist/my.config": "hello world\n",
   207  		"new/my.config":   "hello world\n",
   208  		"test.sh":         "sleep 1\n",
   209  	}
   210  	checkContents(taskDir, expected, t)
   211  }