github.com/kubernetes/utils@v0.0.0-20190308190857-21c4ce38f2a7/nsenter/nsenter_test.go (about) 1 // +build linux 2 3 /* 4 Copyright 2018 The Kubernetes Authors. 5 6 Licensed under the Apache License, Version 2.0 (the "License"); 7 you may not use this file except in compliance with the License. 8 You may obtain a copy of the License at 9 10 http://www.apache.org/licenses/LICENSE-2.0 11 12 Unless required by applicable law or agreed to in writing, software 13 distributed under the License is distributed on an "AS IS" BASIS, 14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 See the License for the specific language governing permissions and 16 limitations under the License. 17 */ 18 19 package nsenter 20 21 import ( 22 "io/ioutil" 23 "os" 24 "path/filepath" 25 "testing" 26 27 "k8s.io/utils/exec" 28 ) 29 30 func TestExec(t *testing.T) { 31 tests := []struct { 32 name string 33 command string 34 args []string 35 expectedOutput string 36 expectError bool 37 }{ 38 { 39 name: "simple command", 40 command: "echo", 41 args: []string{"hello", "world"}, 42 expectedOutput: "hello world\n", 43 }, 44 { 45 name: "nozero exit code", 46 command: "false", 47 expectError: true, 48 }, 49 } 50 51 executor := fakeExec{ 52 rootfsPath: "/rootfs", 53 } 54 for _, test := range tests { 55 ns := NSEnter{ 56 hostRootFsPath: "/rootfs", 57 executor: executor, 58 } 59 cmd := ns.Exec(test.command, test.args) 60 outBytes, err := cmd.CombinedOutput() 61 out := string(outBytes) 62 if err != nil && !test.expectError { 63 t.Errorf("Test %q: unexpected error: %s", test.name, err) 64 } 65 if err == nil && test.expectError { 66 t.Errorf("Test %q: expected error, got none", test.name) 67 } 68 if test.expectedOutput != out { 69 t.Errorf("test %q: expected output %q, got %q", test.name, test.expectedOutput, out) 70 } 71 } 72 } 73 74 func TestKubeletPath(t *testing.T) { 75 tests := []struct { 76 rootfs string 77 hostpath string 78 expectedKubeletPath string 79 }{ 80 { 81 // simple join 82 "/rootfs", 83 "/some/path", 84 "/rootfs/some/path", 85 }, 86 { 87 // squash slashes 88 "/rootfs/", 89 "//some/path", 90 "/rootfs/some/path", 91 }, 92 } 93 94 for _, test := range tests { 95 ns := NSEnter{ 96 hostRootFsPath: test.rootfs, 97 } 98 out := ns.KubeletPath(test.hostpath) 99 if out != test.expectedKubeletPath { 100 t.Errorf("Expected path %q, got %q", test.expectedKubeletPath, out) 101 } 102 103 } 104 } 105 106 func TestEvalSymlinks(t *testing.T) { 107 tests := []struct { 108 name string 109 mustExist bool 110 prepare func(tmpdir string) (src string, expectedDst string, err error) 111 expectError bool 112 }{ 113 { 114 name: "simple file /src", 115 mustExist: true, 116 prepare: func(tmpdir string) (src string, expectedDst string, err error) { 117 src = filepath.Join(tmpdir, "src") 118 err = ioutil.WriteFile(src, []byte{}, 0644) 119 return src, src, err 120 }, 121 }, 122 { 123 name: "non-existing file /src", 124 mustExist: true, 125 prepare: func(tmpdir string) (src string, expectedDst string, err error) { 126 src = filepath.Join(tmpdir, "src") 127 return src, "", nil 128 }, 129 expectError: true, 130 }, 131 { 132 name: "non-existing file /src/ with mustExist=false", 133 mustExist: false, 134 prepare: func(tmpdir string) (src string, expectedDst string, err error) { 135 src = filepath.Join(tmpdir, "src") 136 return src, src, nil 137 }, 138 }, 139 { 140 name: "non-existing file /existing/path/src with mustExist=false with existing directories", 141 mustExist: false, 142 prepare: func(tmpdir string) (src string, expectedDst string, err error) { 143 src = filepath.Join(tmpdir, "existing/path") 144 if err := os.MkdirAll(src, 0755); err != nil { 145 return "", "", err 146 } 147 src = filepath.Join(src, "src") 148 return src, src, nil 149 }, 150 }, 151 { 152 name: "simple symlink /src -> /dst", 153 mustExist: false, 154 prepare: func(tmpdir string) (src string, expectedDst string, err error) { 155 dst := filepath.Join(tmpdir, "dst") 156 if err = ioutil.WriteFile(dst, []byte{}, 0644); err != nil { 157 return "", "", err 158 } 159 src = filepath.Join(tmpdir, "src") 160 err = os.Symlink(dst, src) 161 return src, dst, err 162 }, 163 }, 164 { 165 name: "dangling symlink /src -> /non-existing-path", 166 mustExist: true, 167 prepare: func(tmpdir string) (src string, expectedDst string, err error) { 168 dst := filepath.Join(tmpdir, "non-existing-path") 169 src = filepath.Join(tmpdir, "src") 170 err = os.Symlink(dst, src) 171 return src, "", err 172 }, 173 expectError: true, 174 }, 175 { 176 name: "dangling symlink /src -> /non-existing-path with mustExist=false", 177 mustExist: false, 178 prepare: func(tmpdir string) (src string, expectedDst string, err error) { 179 dst := filepath.Join(tmpdir, "non-existing-path") 180 src = filepath.Join(tmpdir, "src") 181 err = os.Symlink(dst, src) 182 return src, dst, err 183 }, 184 }, 185 { 186 name: "symlink to directory /src/file, where /src is link to /dst", 187 mustExist: true, 188 prepare: func(tmpdir string) (src string, expectedDst string, err error) { 189 dst := filepath.Join(tmpdir, "dst") 190 if err = os.Mkdir(dst, 0755); err != nil { 191 return "", "", err 192 } 193 dstFile := filepath.Join(dst, "file") 194 if err = ioutil.WriteFile(dstFile, []byte{}, 0644); err != nil { 195 return "", "", err 196 } 197 198 src = filepath.Join(tmpdir, "src") 199 if err = os.Symlink(dst, src); err != nil { 200 return "", "", err 201 } 202 srcFile := filepath.Join(src, "file") 203 return srcFile, dstFile, nil 204 }, 205 }, 206 { 207 name: "symlink to non-existing directory: /src/file, where /src is link to /dst and dst does not exist", 208 mustExist: true, 209 prepare: func(tmpdir string) (src string, expectedDst string, err error) { 210 dst := filepath.Join(tmpdir, "dst") 211 212 src = filepath.Join(tmpdir, "src") 213 if err = os.Symlink(dst, src); err != nil { 214 return "", "", err 215 } 216 srcFile := filepath.Join(src, "file") 217 return srcFile, "", nil 218 }, 219 expectError: true, 220 }, 221 { 222 name: "symlink to non-existing directory: /src/file, where /src is link to /dst and dst does not exist with mustExist=false", 223 mustExist: false, 224 prepare: func(tmpdir string) (src string, expectedDst string, err error) { 225 dst := filepath.Join(tmpdir, "dst") 226 dstFile := filepath.Join(dst, "file") 227 228 src = filepath.Join(tmpdir, "src") 229 if err = os.Symlink(dst, src); err != nil { 230 return "", "", err 231 } 232 srcFile := filepath.Join(src, "file") 233 return srcFile, dstFile, nil 234 }, 235 }, 236 } 237 238 for _, test := range tests { 239 ns := NSEnter{ 240 hostRootFsPath: "/rootfs", 241 executor: fakeExec{ 242 rootfsPath: "/rootfs", 243 }, 244 } 245 246 tmpdir, err := ioutil.TempDir("", "nsenter-hostpath-") 247 if err != nil { 248 t.Fatal(err) 249 } 250 defer os.RemoveAll(tmpdir) 251 252 src, expectedDst, err := test.prepare(tmpdir) 253 if err != nil { 254 t.Error(err) 255 continue 256 } 257 258 dst, err := ns.EvalSymlinks(src, test.mustExist) 259 if err != nil && !test.expectError { 260 t.Errorf("Test %q: unexpected error: %s", test.name, err) 261 } 262 if err == nil && test.expectError { 263 t.Errorf("Test %q: expected error, got none", test.name) 264 } 265 if dst != expectedDst { 266 t.Errorf("Test %q: expected destination %q, got %q", test.name, expectedDst, dst) 267 } 268 } 269 } 270 271 func TestNewNsenter(t *testing.T) { 272 // Create a symlink /tmp/xyz/rootfs -> / and use it as rootfs path 273 // It should resolve all binaries correctly, the test runs on Linux 274 275 tmpdir, err := ioutil.TempDir("", "nsenter-hostpath-") 276 if err != nil { 277 t.Fatal(err) 278 } 279 defer os.RemoveAll(tmpdir) 280 281 rootfs := filepath.Join(tmpdir, "rootfs") 282 if err = os.Symlink("/", rootfs); err != nil { 283 t.Fatal(err) 284 } 285 286 _, err = NewNsenter(rootfs, exec.New()) 287 if err != nil { 288 t.Errorf("Error: %s", err) 289 } 290 } 291 292 func TestNewNsenterError(t *testing.T) { 293 // Create empty dir /tmp/xyz/rootfs and use it as rootfs path 294 // It should resolve all binaries correctly, the test runs on Linux 295 296 tmpdir, err := ioutil.TempDir("", "nsenter-hostpath-") 297 if err != nil { 298 t.Fatal(err) 299 } 300 defer os.RemoveAll(tmpdir) 301 302 rootfs := filepath.Join(tmpdir, "rootfs") 303 if err = os.MkdirAll(rootfs, 0755); err != nil { 304 t.Fatal(err) 305 } 306 307 _, err = NewNsenter(rootfs, exec.New()) 308 if err == nil { 309 t.Errorf("Expected error, got none") 310 } 311 }