...

Source file src/k8s.io/utils/nsenter/nsenter_test.go

Documentation: k8s.io/utils/nsenter

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

View as plain text