...

Source file src/sigs.k8s.io/kustomize/api/internal/localizer/util_test.go

Documentation: sigs.k8s.io/kustomize/api/internal/localizer

     1  // Copyright 2022 The Kubernetes Authors.
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package localizer //nolint:testpackage
     5  
     6  import (
     7  	"fmt"
     8  	"os"
     9  	"path/filepath"
    10  	"strings"
    11  	"testing"
    12  
    13  	"github.com/stretchr/testify/require"
    14  	"sigs.k8s.io/kustomize/api/ifc"
    15  	"sigs.k8s.io/kustomize/api/internal/git"
    16  	"sigs.k8s.io/kustomize/kyaml/filesys"
    17  )
    18  
    19  func TestDefaultNewDirRepo(t *testing.T) {
    20  	for name, test := range map[string]struct {
    21  		url, dst string
    22  	}{
    23  		"simple": {
    24  			url: "https://github.com/org/repo?ref=value",
    25  			dst: "localized-repo-value",
    26  		},
    27  		"slashed_ref": {
    28  			url: "https://github.com/org/repo?ref=group/version",
    29  			dst: "localized-repo-group-version",
    30  		},
    31  	} {
    32  		t.Run(name, func(t *testing.T) {
    33  			repoSpec, err := git.NewRepoSpecFromURL(test.url)
    34  			require.NoError(t, err)
    35  			require.Equal(t, test.dst, defaultNewDir(&fakeLoader{t.TempDir()}, repoSpec))
    36  		})
    37  	}
    38  }
    39  
    40  type fakeLoader struct {
    41  	root string
    42  }
    43  
    44  func (fl *fakeLoader) Root() string {
    45  	return fl.root
    46  }
    47  func (fl *fakeLoader) Repo() string {
    48  	return fl.root
    49  }
    50  func (fl *fakeLoader) Load(_ string) ([]byte, error) {
    51  	return []byte{}, nil
    52  }
    53  func (fl *fakeLoader) New(path string) (ifc.Loader, error) {
    54  	return &fakeLoader{path}, nil
    55  }
    56  func (fl *fakeLoader) Cleanup() error {
    57  	return nil
    58  }
    59  
    60  func TestUrlBase(t *testing.T) {
    61  	require.Equal(t, "repo", urlBase("https://github.com/org/repo"))
    62  }
    63  
    64  func TestUrlBaseTrailingSlash(t *testing.T) {
    65  	require.Equal(t, "repo", urlBase("github.com/org/repo//"))
    66  }
    67  
    68  // simpleJoin is filepath.Join() without the side effects of filepath.Clean()
    69  func simpleJoin(t *testing.T, elems ...string) string {
    70  	t.Helper()
    71  
    72  	return strings.Join(elems, string(filepath.Separator))
    73  }
    74  
    75  func TestLocFilePath(t *testing.T) {
    76  	for name, tUnit := range map[string]struct {
    77  		url, path string
    78  	}{
    79  		"official": {
    80  			url:  "https://raw.githubusercontent.com/org/repo/ref/path/to/file.yaml",
    81  			path: simpleJoin(t, "raw.githubusercontent.com", "org", "repo", "ref", "path", "to", "file.yaml"),
    82  		},
    83  		"http-scheme": {
    84  			url:  "http://host/path",
    85  			path: simpleJoin(t, "host", "path"),
    86  		},
    87  		"extraneous_components": {
    88  			url:  "http://userinfo@host:1234/path/file?query",
    89  			path: simpleJoin(t, "host", "path", "file"),
    90  		},
    91  		"empty_path": {
    92  			url:  "https://host",
    93  			path: "host",
    94  		},
    95  		"empty_path_segment": {
    96  			url:  "https://host//",
    97  			path: "host",
    98  		},
    99  		"percent-encoded_path": {
   100  			url:  "https://host/file%2Eyaml",
   101  			path: simpleJoin(t, "host", "file%2Eyaml"),
   102  		},
   103  		"dot-segments": {
   104  			url:  "https://host/path/blah/../to/foo/bar/../../file/./",
   105  			path: simpleJoin(t, "host", "path", "to", "file"),
   106  		},
   107  		"extraneous_dot-segments": {
   108  			url:  "https://host/foo/bar/baz/../../../../file",
   109  			path: simpleJoin(t, "host", "file"),
   110  		},
   111  	} {
   112  		t.Run(name, func(t *testing.T) {
   113  			require.Equal(t, simpleJoin(t, LocalizeDir, tUnit.path), locFilePath(tUnit.url))
   114  		})
   115  	}
   116  }
   117  
   118  func TestLocFilePathColon(t *testing.T) {
   119  	req := require.New(t)
   120  
   121  	// The colon is special because it was once used as the unix file separator.
   122  	const url = "https://[2001:4860:4860::8888]/file.yaml"
   123  	const host = "2001:4860:4860::8888"
   124  	const file = "file.yaml"
   125  	req.Equal(simpleJoin(t, LocalizeDir, host, file), locFilePath(url))
   126  
   127  	fSys := filesys.MakeFsOnDisk()
   128  	targetDir := simpleJoin(t, t.TempDir(), host)
   129  
   130  	// We check that we can create single directory, meaning ':' not used as file separator.
   131  	req.NoError(fSys.Mkdir(targetDir))
   132  	_, err := fSys.Create(simpleJoin(t, targetDir, file))
   133  	req.NoError(err)
   134  
   135  	// We check that the directory with such name is readable.
   136  	files, err := fSys.ReadDir(targetDir)
   137  	req.NoError(err)
   138  	req.Equal([]string{file}, files)
   139  }
   140  
   141  func TestLocFilePath_SpecialChar(t *testing.T) {
   142  	req := require.New(t)
   143  
   144  	// The wild card character is one of the legal uri characters with more meaning
   145  	// to the system, so we test it here.
   146  	const wildcard = "*"
   147  	req.Equal(simpleJoin(t, LocalizeDir, "host", wildcard), locFilePath("https://host/*"))
   148  
   149  	fSys := filesys.MakeFsOnDisk()
   150  	testDir := t.TempDir()
   151  	req.NoError(fSys.Mkdir(simpleJoin(t, testDir, "a")))
   152  	req.NoError(fSys.WriteFile(simpleJoin(t, testDir, "b"), []byte{}))
   153  
   154  	// We check that we can create and read from wild card-named file.
   155  	// We check that the file system is not matching it to existing file names.
   156  	req.NoError(fSys.WriteFile(simpleJoin(t, testDir, wildcard), []byte("test")))
   157  	content, err := fSys.ReadFile(simpleJoin(t, testDir, wildcard))
   158  	req.NoError(err)
   159  	req.Equal("test", string(content))
   160  }
   161  
   162  func TestLocFilePath_SpecialFiles(t *testing.T) {
   163  	for name, tFSys := range map[string]struct {
   164  		urlPath           string
   165  		pathDir, pathFile string
   166  	}{
   167  		"windows_reserved_name": {
   168  			urlPath:  "/aux/file",
   169  			pathDir:  "aux",
   170  			pathFile: "file",
   171  		},
   172  		"hidden_files": {
   173  			urlPath:  "/.../.file",
   174  			pathDir:  "...",
   175  			pathFile: ".file",
   176  		},
   177  	} {
   178  		t.Run(name, func(t *testing.T) {
   179  			req := require.New(t)
   180  
   181  			expectedPath := simpleJoin(t, LocalizeDir, "host", tFSys.pathDir, tFSys.pathFile)
   182  			req.Equal(expectedPath, locFilePath("https://host"+tFSys.urlPath))
   183  
   184  			fSys := filesys.MakeFsOnDisk()
   185  			targetDir := simpleJoin(t, t.TempDir(), tFSys.pathDir)
   186  			req.NoError(fSys.Mkdir(targetDir))
   187  			req.NoError(fSys.WriteFile(simpleJoin(t, targetDir, tFSys.pathFile), []byte("test")))
   188  
   189  			content, err := fSys.ReadFile(simpleJoin(t, targetDir, tFSys.pathFile))
   190  			req.NoError(err)
   191  			req.Equal([]byte("test"), content)
   192  		})
   193  	}
   194  }
   195  
   196  func makeConfirmedDir(t *testing.T) (filesys.FileSystem, filesys.ConfirmedDir) {
   197  	t.Helper()
   198  
   199  	fSys := filesys.MakeFsOnDisk()
   200  	testDir, err := filesys.NewTmpConfirmedDir()
   201  	require.NoError(t, err)
   202  	t.Cleanup(func() {
   203  		_ = fSys.RemoveAll(testDir.String())
   204  	})
   205  
   206  	return fSys, testDir
   207  }
   208  
   209  func TestLocRootPath_URLComponents(t *testing.T) {
   210  	for name, test := range map[string]struct {
   211  		urlf, path string
   212  	}{
   213  		"ssh": {
   214  			urlf: "ssh://git@github.com/org/repo//%s?ref=value",
   215  			path: simpleJoin(t, "github.com", "org", "repo", "value"),
   216  		},
   217  		"rel_ssh": {
   218  			urlf: "git@github.com:org/repo//%s?ref=value",
   219  			path: simpleJoin(t, "github.com", "org", "repo", "value"),
   220  		},
   221  		"https": {
   222  			urlf: "https://gitlab.com/org/repo//%s?ref=value",
   223  			path: simpleJoin(t, "gitlab.com", "org", "repo", "value"),
   224  		},
   225  		"file": {
   226  			urlf: "file:///var/run/repo//%s?ref=value",
   227  			path: simpleJoin(t, FileSchemeDir, "var", "run", "repo", "value"),
   228  		},
   229  		"IPv6": {
   230  			urlf: "https://[2001:4860:4860::8888]/org/repo//%s?ref=value",
   231  			path: simpleJoin(t, "2001:4860:4860::8888", "org", "repo", "value"),
   232  		},
   233  		"port": {
   234  			urlf: "https://localhost.com:8080/org/repo//%s?ref=value",
   235  			path: simpleJoin(t, "localhost.com", "org", "repo", "value"),
   236  		},
   237  		"no_org": {
   238  			urlf: "https://github.com/repo//%s?ref=value",
   239  			path: simpleJoin(t, "github.com", "repo", "value"),
   240  		},
   241  		".git_suffix": {
   242  			urlf: "https://github.com/org1/org2/repo.git//%s?ref=value",
   243  			path: simpleJoin(t, "github.com", "org1", "org2", "repo", "value"),
   244  		},
   245  		"dot-segments": {
   246  			urlf: "https://github.com/./../org/../org/repo.git//%s?ref=value",
   247  			path: simpleJoin(t, "github.com", "org", "repo", "value"),
   248  		},
   249  		"no_path_delimiter": {
   250  			urlf: "https://github.com/org/repo/%s?ref=value",
   251  			path: simpleJoin(t, "github.com", "org", "repo", "value"),
   252  		},
   253  		"illegal_windows_dir": {
   254  			urlf: "https://gitlab.com/org./repo..git//%s?ref=value",
   255  			path: simpleJoin(t, "gitlab.com", "org.", "repo.", "value"),
   256  		},
   257  		"ref_has_slash": {
   258  			urlf: "https://gitlab.com/org/repo//%s?ref=group/version/kind",
   259  			path: simpleJoin(t, "gitlab.com", "org", "repo", "group", "version", "kind"),
   260  		},
   261  	} {
   262  		t.Run(name, func(t *testing.T) {
   263  			u := fmt.Sprintf(test.urlf, "path/to/root")
   264  			path := simpleJoin(t, LocalizeDir, test.path, "path", "to", "root")
   265  
   266  			fSys, testDir := makeConfirmedDir(t)
   267  			repoDir := simpleJoin(t, testDir.String(), "repo_random-hash")
   268  			require.NoError(t, fSys.Mkdir(repoDir))
   269  			rootDir := simpleJoin(t, repoDir, "path", "to", "root")
   270  			require.NoError(t, fSys.MkdirAll(rootDir))
   271  
   272  			actual, err := locRootPath(u, repoDir, filesys.ConfirmedDir(rootDir), fSys)
   273  			require.NoError(t, err)
   274  			require.Equal(t, path, actual)
   275  
   276  			require.NoError(t, fSys.MkdirAll(simpleJoin(t, testDir.String(), path)))
   277  		})
   278  	}
   279  }
   280  
   281  func TestLocRootPath_Repo(t *testing.T) {
   282  	const url = "https://github.com/org/repo?ref=value"
   283  	expected := simpleJoin(t, LocalizeDir, "github.com", "org", "repo", "value")
   284  
   285  	fSys, testDir := makeConfirmedDir(t)
   286  	actual, err := locRootPath(url, testDir.String(), testDir, fSys)
   287  	require.NoError(t, err)
   288  	require.Equal(t, expected, actual)
   289  }
   290  
   291  func TestLocRootPath_SymlinkPath(t *testing.T) {
   292  	const url = "https://github.com/org/repo//symlink?ref=value"
   293  
   294  	fSys, repoDir := makeConfirmedDir(t)
   295  	rootDir := simpleJoin(t, repoDir.String(), "actual-root")
   296  	require.NoError(t, fSys.Mkdir(rootDir))
   297  	require.NoError(t, os.Symlink(rootDir, simpleJoin(t, repoDir.String(), "symlink")))
   298  
   299  	expected := simpleJoin(t, LocalizeDir, "github.com", "org", "repo", "value", "actual-root")
   300  	actual, err := locRootPath(url, repoDir.String(), filesys.ConfirmedDir(rootDir), fSys)
   301  	require.NoError(t, err)
   302  	require.Equal(t, expected, actual)
   303  }
   304  

View as plain text