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  }