github.com/iqoqo/nomad@v0.11.3-0.20200911112621-d7021c74d101/client/allocwatcher/alloc_watcher_unix_test.go (about) 1 // +build !windows 2 3 package allocwatcher 4 5 import ( 6 "archive/tar" 7 "bytes" 8 "context" 9 "fmt" 10 "io" 11 "io/ioutil" 12 "os" 13 "path/filepath" 14 "syscall" 15 "testing" 16 17 ctestutil "github.com/hashicorp/nomad/client/testutil" 18 "github.com/hashicorp/nomad/helper/testlog" 19 ) 20 21 // TestPrevAlloc_StreamAllocDir_Ok asserts that streaming a tar to an alloc dir 22 // works. 23 func TestPrevAlloc_StreamAllocDir_Ok(t *testing.T) { 24 ctestutil.RequireRoot(t) 25 t.Parallel() 26 dir, err := ioutil.TempDir("", "") 27 if err != nil { 28 t.Fatalf("err: %v", err) 29 } 30 defer os.RemoveAll(dir) 31 32 // Create foo/ 33 fooDir := filepath.Join(dir, "foo") 34 if err := os.Mkdir(fooDir, 0777); err != nil { 35 t.Fatalf("err: %v", err) 36 } 37 38 // Change ownership of foo/ to test #3702 (any non-root user is fine) 39 const uid, gid = 1, 1 40 if err := os.Chown(fooDir, uid, gid); err != nil { 41 t.Fatalf("err : %v", err) 42 } 43 44 dirInfo, err := os.Stat(fooDir) 45 if err != nil { 46 t.Fatalf("err: %v", err) 47 } 48 49 // Create foo/bar 50 f, err := os.Create(filepath.Join(fooDir, "bar")) 51 if err != nil { 52 t.Fatalf("err: %v", err) 53 } 54 if _, err := f.WriteString("123"); err != nil { 55 t.Fatalf("err: %v", err) 56 } 57 if err := f.Chmod(0644); err != nil { 58 t.Fatalf("err: %v", err) 59 } 60 fInfo, err := f.Stat() 61 if err != nil { 62 t.Fatalf("err: %v", err) 63 } 64 f.Close() 65 66 // Create foo/baz -> bar symlink 67 if err := os.Symlink("bar", filepath.Join(dir, "foo", "baz")); err != nil { 68 t.Fatalf("err: %v", err) 69 } 70 linkInfo, err := os.Lstat(filepath.Join(dir, "foo", "baz")) 71 if err != nil { 72 t.Fatalf("err: %v", err) 73 } 74 75 buf := new(bytes.Buffer) 76 tw := tar.NewWriter(buf) 77 78 walkFn := func(path string, fileInfo os.FileInfo, err error) error { 79 // filepath.Walk passes in an error 80 if err != nil { 81 return fmt.Errorf("error from filepath.Walk(): %s", err) 82 } 83 // Include the path of the file name relative to the alloc dir 84 // so that we can put the files in the right directories 85 link := "" 86 if fileInfo.Mode()&os.ModeSymlink != 0 { 87 target, err := os.Readlink(path) 88 if err != nil { 89 return fmt.Errorf("error reading symlink: %v", err) 90 } 91 link = target 92 } 93 hdr, err := tar.FileInfoHeader(fileInfo, link) 94 if err != nil { 95 return fmt.Errorf("error creating file header: %v", err) 96 } 97 hdr.Name = fileInfo.Name() 98 tw.WriteHeader(hdr) 99 100 // If it's a directory or symlink we just write the header into the tar 101 if fileInfo.IsDir() || (fileInfo.Mode()&os.ModeSymlink != 0) { 102 return nil 103 } 104 105 // Write the file into the archive 106 file, err := os.Open(path) 107 if err != nil { 108 return err 109 } 110 defer file.Close() 111 112 if _, err := io.Copy(tw, file); err != nil { 113 return err 114 } 115 116 return nil 117 } 118 119 if err := filepath.Walk(dir, walkFn); err != nil { 120 t.Fatalf("err: %v", err) 121 } 122 tw.Close() 123 124 dir1, err := ioutil.TempDir("", "nomadtest-") 125 if err != nil { 126 t.Fatalf("err: %v", err) 127 } 128 defer os.RemoveAll(dir1) 129 130 rc := ioutil.NopCloser(buf) 131 prevAlloc := &remotePrevAlloc{logger: testlog.HCLogger(t)} 132 if err := prevAlloc.streamAllocDir(context.Background(), rc, dir1); err != nil { 133 t.Fatalf("err: %v", err) 134 } 135 136 // Ensure foo is present 137 fi, err := os.Stat(filepath.Join(dir1, "foo")) 138 if err != nil { 139 t.Fatalf("err: %v", err) 140 } 141 if fi.Mode() != dirInfo.Mode() { 142 t.Fatalf("mode: %v", fi.Mode()) 143 } 144 stat := fi.Sys().(*syscall.Stat_t) 145 if stat.Uid != uid || stat.Gid != gid { 146 t.Fatalf("foo/ has incorrect ownership: expected %d:%d found %d:%d", 147 uid, gid, stat.Uid, stat.Gid) 148 } 149 150 fi1, err := os.Stat(filepath.Join(dir1, "bar")) 151 if err != nil { 152 t.Fatalf("err: %v", err) 153 } 154 if fi1.Mode() != fInfo.Mode() { 155 t.Fatalf("mode: %v", fi1.Mode()) 156 } 157 158 fi2, err := os.Lstat(filepath.Join(dir1, "baz")) 159 if err != nil { 160 t.Fatalf("err: %v", err) 161 } 162 if fi2.Mode() != linkInfo.Mode() { 163 t.Fatalf("mode: %v", fi2.Mode()) 164 } 165 }