...

Source file src/sigs.k8s.io/kustomize/api/internal/loader/fileloader_test.go

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

     1  /// Copyright 2019 The Kubernetes Authors.
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package loader
     5  
     6  import (
     7  	"bytes"
     8  	"fmt"
     9  	"io"
    10  	"net/http"
    11  	"os"
    12  	"path"
    13  	"path/filepath"
    14  	"reflect"
    15  	"strings"
    16  	"testing"
    17  
    18  	"github.com/stretchr/testify/require"
    19  	"sigs.k8s.io/kustomize/api/ifc"
    20  	"sigs.k8s.io/kustomize/api/internal/git"
    21  	"sigs.k8s.io/kustomize/api/konfig"
    22  	"sigs.k8s.io/kustomize/kyaml/filesys"
    23  )
    24  
    25  func TestIsRemoteFile(t *testing.T) {
    26  	cases := map[string]struct {
    27  		url   string
    28  		valid bool
    29  	}{
    30  		"https file": {
    31  			"https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/examples/helloWorld/configMap.yaml",
    32  			true,
    33  		},
    34  		"malformed https": {
    35  			// TODO(annasong): Maybe we want to fix this. Needs more research.
    36  			"https:/raw.githubusercontent.com/kubernetes-sigs/kustomize/master/examples/helloWorld/configMap.yaml",
    37  			true,
    38  		},
    39  		"https dir": {
    40  			"https://github.com/kubernetes-sigs/kustomize//examples/helloWorld/",
    41  			true,
    42  		},
    43  		"no scheme": {
    44  			"github.com/kubernetes-sigs/kustomize//examples/helloWorld/",
    45  			false,
    46  		},
    47  		"ssh": {
    48  			"ssh://git@github.com/kubernetes-sigs/kustomize.git",
    49  			false,
    50  		},
    51  		"local": {
    52  			"pod.yaml",
    53  			false,
    54  		},
    55  	}
    56  	for name, test := range cases {
    57  		test := test
    58  		t.Run(name, func(t *testing.T) {
    59  			require.Equal(t, test.valid, IsRemoteFile(test.url))
    60  		})
    61  	}
    62  }
    63  
    64  type testData struct {
    65  	path            string
    66  	expectedContent string
    67  }
    68  
    69  var testCases = []testData{
    70  	{
    71  		path:            "foo/project/fileA.yaml",
    72  		expectedContent: "fileA content",
    73  	},
    74  	{
    75  		path:            "foo/project/subdir1/fileB.yaml",
    76  		expectedContent: "fileB content",
    77  	},
    78  	{
    79  		path:            "foo/project/subdir2/fileC.yaml",
    80  		expectedContent: "fileC content",
    81  	},
    82  	{
    83  		path:            "foo/project/fileD.yaml",
    84  		expectedContent: "fileD content",
    85  	},
    86  }
    87  
    88  func MakeFakeFs(td []testData) filesys.FileSystem {
    89  	fSys := filesys.MakeFsInMemory()
    90  	for _, x := range td {
    91  		fSys.WriteFile(x.path, []byte(x.expectedContent))
    92  	}
    93  	return fSys
    94  }
    95  
    96  func makeLoader() *FileLoader {
    97  	return NewLoaderOrDie(
    98  		RestrictionRootOnly, MakeFakeFs(testCases), filesys.Separator)
    99  }
   100  
   101  func TestLoaderLoad(t *testing.T) {
   102  	require := require.New(t)
   103  
   104  	l1 := makeLoader()
   105  	repo := l1.Repo()
   106  	require.Empty(repo)
   107  	require.Equal("/", l1.Root())
   108  
   109  	for _, x := range testCases {
   110  		b, err := l1.Load(x.path)
   111  		require.NoError(err)
   112  
   113  		if !reflect.DeepEqual([]byte(x.expectedContent), b) {
   114  			t.Fatalf("in load expected %s, but got %s", x.expectedContent, b)
   115  		}
   116  	}
   117  	l2, err := l1.New("foo/project")
   118  	require.NoError(err)
   119  
   120  	repo = l2.Repo()
   121  	require.Empty(repo)
   122  	require.Equal("/foo/project", l2.Root())
   123  
   124  	for _, x := range testCases {
   125  		b, err := l2.Load(strings.TrimPrefix(x.path, "foo/project/"))
   126  		require.NoError(err)
   127  
   128  		if !reflect.DeepEqual([]byte(x.expectedContent), b) {
   129  			t.Fatalf("in load expected %s, but got %s", x.expectedContent, b)
   130  		}
   131  	}
   132  	l2, err = l1.New("foo/project/") // Assure trailing slash stripped
   133  	require.NoError(err)
   134  	require.Equal("/foo/project", l2.Root())
   135  }
   136  
   137  func TestLoaderNewSubDir(t *testing.T) {
   138  	require := require.New(t)
   139  
   140  	l1, err := makeLoader().New("foo/project")
   141  	require.NoError(err)
   142  
   143  	l2, err := l1.New("subdir1")
   144  	require.NoError(err)
   145  	require.Equal("/foo/project/subdir1", l2.Root())
   146  
   147  	x := testCases[1]
   148  	b, err := l2.Load("fileB.yaml")
   149  	require.NoError(err)
   150  
   151  	if !reflect.DeepEqual([]byte(x.expectedContent), b) {
   152  		t.Fatalf("in load expected %s, but got %s", x.expectedContent, b)
   153  	}
   154  }
   155  
   156  func TestLoaderBadRelative(t *testing.T) {
   157  	require := require.New(t)
   158  
   159  	l1, err := makeLoader().New("foo/project/subdir1")
   160  	require.NoError(err)
   161  	require.Equal("/foo/project/subdir1", l1.Root())
   162  
   163  	// Cannot cd into a file.
   164  	l2, err := l1.New("fileB.yaml")
   165  	require.Error(err)
   166  
   167  	// It's not okay to stay at the same place.
   168  	l2, err = l1.New(filesys.SelfDir)
   169  	require.Error(err)
   170  
   171  	// It's not okay to go up and back down into same place.
   172  	l2, err = l1.New("../subdir1")
   173  	require.Error(err)
   174  
   175  	// It's not okay to go up via a relative path.
   176  	l2, err = l1.New("..")
   177  	require.Error(err)
   178  
   179  	// It's not okay to go up via an absolute path.
   180  	l2, err = l1.New("/foo/project")
   181  	require.Error(err)
   182  
   183  	// It's not okay to go to the root.
   184  	l2, err = l1.New("/")
   185  	require.Error(err)
   186  
   187  	// It's okay to go up and down to a sibling.
   188  	l2, err = l1.New("../subdir2")
   189  	require.NoError(err)
   190  	require.Equal("/foo/project/subdir2", l2.Root())
   191  
   192  	x := testCases[2]
   193  	b, err := l2.Load("fileC.yaml")
   194  	require.NoError(err)
   195  	if !reflect.DeepEqual([]byte(x.expectedContent), b) {
   196  		t.Fatalf("in load expected %s, but got %s", x.expectedContent, b)
   197  	}
   198  
   199  	// It's not OK to go over to a previously visited directory.
   200  	// Must disallow going back and forth in a cycle.
   201  	l1, err = l2.New("../subdir1")
   202  	require.Error(err)
   203  }
   204  
   205  func TestNewEmptyLoader(t *testing.T) {
   206  	_, err := makeLoader().New("")
   207  	require.Error(t, err)
   208  }
   209  
   210  func TestNewRemoteLoaderDoesNotExist(t *testing.T) {
   211  	_, err := makeLoader().New("https://example.com/org/repo")
   212  	require.ErrorContains(t, err, "fetch")
   213  }
   214  
   215  func TestLoaderLocalScheme(t *testing.T) {
   216  	// It is unlikely but possible for a reference with a url scheme to
   217  	// actually refer to a local file or directory.
   218  	t.Run("file", func(t *testing.T) {
   219  		fSys, dir := setupOnDisk(t)
   220  		parts := []string{
   221  			"ssh:",
   222  			"resource.yaml",
   223  		}
   224  		require.NoError(t, fSys.Mkdir(dir.Join(parts[0])))
   225  		const content = "resource config"
   226  		require.NoError(t, fSys.WriteFile(
   227  			dir.Join(filepath.Join(parts...)),
   228  			[]byte(content),
   229  		))
   230  		actualContent, err := NewLoaderOrDie(RestrictionRootOnly,
   231  			fSys,
   232  			dir.String(),
   233  		).Load(strings.Join(parts, "//"))
   234  		require.NoError(t, err)
   235  		require.Equal(t, content, string(actualContent))
   236  	})
   237  	t.Run("directory", func(t *testing.T) {
   238  		fSys, dir := setupOnDisk(t)
   239  		parts := []string{
   240  			"https:",
   241  			"root",
   242  		}
   243  		require.NoError(t, fSys.MkdirAll(dir.Join(filepath.Join(parts...))))
   244  		ldr, err := NewLoaderOrDie(RestrictionRootOnly,
   245  			fSys,
   246  			dir.String(),
   247  		).New(strings.Join(parts, "//"))
   248  		require.NoError(t, err)
   249  		require.Empty(t, ldr.Repo())
   250  	})
   251  }
   252  
   253  const (
   254  	contentOk           = "hi there, i'm OK data"
   255  	contentExteriorData = "i am data from outside the root"
   256  )
   257  
   258  // Create a structure like this
   259  //
   260  //	/tmp/kustomize-test-random
   261  //	├── base
   262  //	│   ├── okayData
   263  //	│   ├── symLinkToOkayData -> okayData
   264  //	│   └── symLinkToExteriorData -> ../exteriorData
   265  //	└── exteriorData
   266  func commonSetupForLoaderRestrictionTest(t *testing.T) (string, filesys.FileSystem) {
   267  	t.Helper()
   268  	fSys, tmpDir := setupOnDisk(t)
   269  	dir := tmpDir.String()
   270  
   271  	fSys.Mkdir(filepath.Join(dir, "base"))
   272  
   273  	fSys.WriteFile(
   274  		filepath.Join(dir, "base", "okayData"), []byte(contentOk))
   275  
   276  	fSys.WriteFile(
   277  		filepath.Join(dir, "exteriorData"), []byte(contentExteriorData))
   278  
   279  	os.Symlink(
   280  		filepath.Join(dir, "base", "okayData"),
   281  		filepath.Join(dir, "base", "symLinkToOkayData"))
   282  	os.Symlink(
   283  		filepath.Join(dir, "exteriorData"),
   284  		filepath.Join(dir, "base", "symLinkToExteriorData"))
   285  	return dir, fSys
   286  }
   287  
   288  // Make sure everything works when loading files
   289  // in or below the loader root.
   290  func doSanityChecksAndDropIntoBase(
   291  	t *testing.T, l ifc.Loader) ifc.Loader {
   292  	t.Helper()
   293  	require := require.New(t)
   294  
   295  	data, err := l.Load(path.Join("base", "okayData"))
   296  	require.NoError(err)
   297  	require.Equal(contentOk, string(data))
   298  
   299  	data, err = l.Load("exteriorData")
   300  	require.NoError(err)
   301  	require.Equal(contentExteriorData, string(data))
   302  
   303  	// Drop in.
   304  	l, err = l.New("base")
   305  	require.NoError(err)
   306  
   307  	// Reading okayData works.
   308  	data, err = l.Load("okayData")
   309  	require.NoError(err)
   310  	require.Equal(contentOk, string(data))
   311  
   312  	// Reading local symlink to okayData works.
   313  	data, err = l.Load("symLinkToOkayData")
   314  	require.NoError(err)
   315  	require.Equal(contentOk, string(data))
   316  
   317  	return l
   318  }
   319  
   320  func TestRestrictionRootOnlyInRealLoader(t *testing.T) {
   321  	require := require.New(t)
   322  	dir, fSys := commonSetupForLoaderRestrictionTest(t)
   323  
   324  	var l ifc.Loader
   325  
   326  	l = NewLoaderOrDie(RestrictionRootOnly, fSys, dir)
   327  
   328  	l = doSanityChecksAndDropIntoBase(t, l)
   329  
   330  	// Reading symlink to exteriorData fails.
   331  	_, err := l.Load("symLinkToExteriorData")
   332  	require.Error(err)
   333  	require.Contains(err.Error(), "is not in or below")
   334  
   335  	// Attempt to read "up" fails, though earlier we were
   336  	// able to read this file when root was "..".
   337  	_, err = l.Load("../exteriorData")
   338  	require.Error(err)
   339  	require.Contains(err.Error(), "is not in or below")
   340  }
   341  
   342  func TestRestrictionNoneInRealLoader(t *testing.T) {
   343  	dir, fSys := commonSetupForLoaderRestrictionTest(t)
   344  
   345  	var l ifc.Loader
   346  
   347  	l = NewLoaderOrDie(RestrictionNone, fSys, dir)
   348  
   349  	l = doSanityChecksAndDropIntoBase(t, l)
   350  
   351  	// Reading symlink to exteriorData works.
   352  	_, err := l.Load("symLinkToExteriorData")
   353  	require.NoError(t, err)
   354  
   355  	// Attempt to read "up" works.
   356  	_, err = l.Load("../exteriorData")
   357  	require.NoError(t, err)
   358  }
   359  
   360  func splitOnNthSlash(v string, n int) (string, string) {
   361  	left := ""
   362  	for i := 0; i < n; i++ {
   363  		k := strings.Index(v, "/")
   364  		if k < 0 {
   365  			break
   366  		}
   367  		left += v[:k+1]
   368  		v = v[k+1:]
   369  	}
   370  	return left[:len(left)-1], v
   371  }
   372  
   373  func TestSplit(t *testing.T) {
   374  	p := "a/b/c/d/e/f/g"
   375  	if left, right := splitOnNthSlash(p, 2); left != "a/b" || right != "c/d/e/f/g" {
   376  		t.Fatalf("got left='%s', right='%s'", left, right)
   377  	}
   378  	if left, right := splitOnNthSlash(p, 3); left != "a/b/c" || right != "d/e/f/g" {
   379  		t.Fatalf("got left='%s', right='%s'", left, right)
   380  	}
   381  	if left, right := splitOnNthSlash(p, 6); left != "a/b/c/d/e/f" || right != "g" {
   382  		t.Fatalf("got left='%s', right='%s'", left, right)
   383  	}
   384  }
   385  
   386  func TestNewLoaderAtGitClone(t *testing.T) {
   387  	require := require.New(t)
   388  
   389  	rootURL := "github.com/someOrg/someRepo"
   390  	pathInRepo := "foo/base"
   391  	url := rootURL + "/" + pathInRepo
   392  	coRoot := "/tmp"
   393  	fSys := filesys.MakeFsInMemory()
   394  	fSys.MkdirAll(coRoot)
   395  	fSys.MkdirAll(coRoot + "/" + pathInRepo)
   396  	fSys.WriteFile(
   397  		coRoot+"/"+pathInRepo+"/"+
   398  			konfig.DefaultKustomizationFileName(),
   399  		[]byte(`
   400  whatever
   401  `))
   402  
   403  	repoSpec, err := git.NewRepoSpecFromURL(url)
   404  	require.NoError(err)
   405  
   406  	l, err := newLoaderAtGitClone(
   407  		repoSpec, fSys, nil,
   408  		git.DoNothingCloner(filesys.ConfirmedDir(coRoot)))
   409  	require.NoError(err)
   410  	repo := l.Repo()
   411  	require.Equal(coRoot, repo)
   412  	require.Equal(coRoot+"/"+pathInRepo, l.Root())
   413  
   414  	_, err = l.New(url)
   415  	require.Error(err)
   416  
   417  	_, err = l.New(rootURL + "/" + "foo")
   418  	require.Error(err)
   419  
   420  	pathInRepo = "foo/overlay"
   421  	fSys.MkdirAll(coRoot + "/" + pathInRepo)
   422  	url = rootURL + "/" + pathInRepo
   423  	l2, err := l.New(url)
   424  	require.NoError(err)
   425  
   426  	repo = l2.Repo()
   427  	require.Equal(coRoot, repo)
   428  	require.Equal(coRoot+"/"+pathInRepo, l2.Root())
   429  }
   430  
   431  func TestLoaderDisallowsLocalBaseFromRemoteOverlay(t *testing.T) {
   432  	require := require.New(t)
   433  
   434  	// Define an overlay-base structure in the file system.
   435  	topDir := "/whatever"
   436  	cloneRoot := topDir + "/someClone"
   437  	fSys := filesys.MakeFsInMemory()
   438  	fSys.MkdirAll(topDir + "/highBase")
   439  	fSys.MkdirAll(cloneRoot + "/foo/base")
   440  	fSys.MkdirAll(cloneRoot + "/foo/overlay")
   441  
   442  	var l1 ifc.Loader
   443  
   444  	// Establish that a local overlay can navigate
   445  	// to the local bases.
   446  	l1 = NewLoaderOrDie(
   447  		RestrictionRootOnly, fSys, cloneRoot+"/foo/overlay")
   448  	require.Equal(cloneRoot+"/foo/overlay", l1.Root())
   449  
   450  	l2, err := l1.New("../base")
   451  	require.NoError(nil)
   452  	require.Equal(cloneRoot+"/foo/base", l2.Root())
   453  
   454  	l3, err := l2.New("../../../highBase")
   455  	require.NoError(err)
   456  	require.Equal(topDir+"/highBase", l3.Root())
   457  
   458  	// Establish that a Kustomization found in cloned
   459  	// repo can reach (non-remote) bases inside the clone
   460  	// but cannot reach a (non-remote) base outside the
   461  	// clone but legitimately on the local file system.
   462  	// This is to avoid a surprising interaction between
   463  	// a remote K and local files.  The remote K would be
   464  	// non-functional on its own since by definition it
   465  	// would refer to a non-remote base file that didn't
   466  	// exist in its own repository, so presumably the
   467  	// remote K would be deliberately designed to phish
   468  	// for local K's.
   469  	repoSpec, err := git.NewRepoSpecFromURL(
   470  		"github.com/someOrg/someRepo/foo/overlay")
   471  	require.NoError(err)
   472  
   473  	l1, err = newLoaderAtGitClone(
   474  		repoSpec, fSys, nil,
   475  		git.DoNothingCloner(filesys.ConfirmedDir(cloneRoot)))
   476  	require.NoError(err)
   477  	require.Equal(cloneRoot+"/foo/overlay", l1.Root())
   478  
   479  	// This is okay.
   480  	l2, err = l1.New("../base")
   481  	require.NoError(err)
   482  	repo := l2.Repo()
   483  	require.Empty(repo)
   484  	require.Equal(cloneRoot+"/foo/base", l2.Root())
   485  
   486  	// This is not okay.
   487  	_, err = l2.New("../../../highBase")
   488  	require.Error(err)
   489  	require.Contains(err.Error(),
   490  		"base '/whatever/highBase' is outside '/whatever/someClone'")
   491  }
   492  
   493  func TestLoaderDisallowsRemoteBaseExitRepo(t *testing.T) {
   494  	fSys, dir := setupOnDisk(t)
   495  
   496  	repo := dir.Join("repo")
   497  	require.NoError(t, fSys.Mkdir(repo))
   498  
   499  	base := filepath.Join(repo, "base")
   500  	require.NoError(t, os.Symlink(dir.String(), base))
   501  
   502  	repoSpec, err := git.NewRepoSpecFromURL("https://github.com/org/repo/base")
   503  	require.NoError(t, err)
   504  
   505  	_, err = newLoaderAtGitClone(repoSpec, fSys, nil, git.DoNothingCloner(filesys.ConfirmedDir(repo)))
   506  	require.Error(t, err)
   507  	require.Contains(t, err.Error(), fmt.Sprintf("%q refers to directory outside of repo %q", base, repo))
   508  }
   509  
   510  func TestLocalLoaderReferencingGitBase(t *testing.T) {
   511  	require := require.New(t)
   512  
   513  	topDir := "/whatever"
   514  	cloneRoot := topDir + "/someClone"
   515  	fSys := filesys.MakeFsInMemory()
   516  	fSys.MkdirAll(topDir)
   517  	fSys.MkdirAll(cloneRoot + "/foo/base")
   518  
   519  	l1 := newLoaderAtConfirmedDir(
   520  		RestrictionRootOnly, filesys.ConfirmedDir(topDir), fSys, nil,
   521  		git.DoNothingCloner(filesys.ConfirmedDir(cloneRoot)))
   522  	require.Equal(topDir, l1.Root())
   523  
   524  	l2, err := l1.New("github.com/someOrg/someRepo/foo/base")
   525  	require.NoError(err)
   526  	repo := l2.Repo()
   527  	require.Equal(cloneRoot, repo)
   528  	require.Equal(cloneRoot+"/foo/base", l2.Root())
   529  }
   530  
   531  func TestRepoDirectCycleDetection(t *testing.T) {
   532  	require := require.New(t)
   533  
   534  	topDir := "/cycles"
   535  	cloneRoot := topDir + "/someClone"
   536  	fSys := filesys.MakeFsInMemory()
   537  	fSys.MkdirAll(topDir)
   538  	fSys.MkdirAll(cloneRoot)
   539  
   540  	l1 := newLoaderAtConfirmedDir(
   541  		RestrictionRootOnly, filesys.ConfirmedDir(topDir), fSys, nil,
   542  		git.DoNothingCloner(filesys.ConfirmedDir(cloneRoot)))
   543  	p1 := "github.com/someOrg/someRepo/foo"
   544  	rs1, err := git.NewRepoSpecFromURL(p1)
   545  	require.NoError(err)
   546  
   547  	l1.repoSpec = rs1
   548  	_, err = l1.New(p1)
   549  	require.Error(err)
   550  	require.Contains(err.Error(), "cycle detected")
   551  }
   552  
   553  func TestRepoIndirectCycleDetection(t *testing.T) {
   554  	require := require.New(t)
   555  
   556  	topDir := "/cycles"
   557  	cloneRoot := topDir + "/someClone"
   558  	fSys := filesys.MakeFsInMemory()
   559  	fSys.MkdirAll(topDir)
   560  	fSys.MkdirAll(cloneRoot)
   561  
   562  	l0 := newLoaderAtConfirmedDir(
   563  		RestrictionRootOnly, filesys.ConfirmedDir(topDir), fSys, nil,
   564  		git.DoNothingCloner(filesys.ConfirmedDir(cloneRoot)))
   565  
   566  	p1 := "github.com/someOrg/someRepo1"
   567  	p2 := "github.com/someOrg/someRepo2"
   568  
   569  	l1, err := l0.New(p1)
   570  	require.NoError(err)
   571  
   572  	l2, err := l1.New(p2)
   573  	require.NoError(err)
   574  
   575  	_, err = l2.New(p1)
   576  	require.Error(err)
   577  	require.Contains(err.Error(), "cycle detected")
   578  }
   579  
   580  // Inspired by https://hassansin.github.io/Unit-Testing-http-client-in-Go
   581  type fakeRoundTripper func(req *http.Request) *http.Response
   582  
   583  func (f fakeRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
   584  	return f(req), nil
   585  }
   586  
   587  func makeFakeHTTPClient(fn fakeRoundTripper) *http.Client {
   588  	return &http.Client{
   589  		Transport: fn,
   590  	}
   591  }
   592  
   593  // TestLoaderHTTP test http file loader
   594  func TestLoaderHTTP(t *testing.T) {
   595  	require := require.New(t)
   596  
   597  	var testCasesFile = []testData{
   598  		{
   599  			path:            "http/file.yaml",
   600  			expectedContent: "file content",
   601  		},
   602  	}
   603  
   604  	l1 := NewLoaderOrDie(
   605  		RestrictionRootOnly, MakeFakeFs(testCasesFile), filesys.Separator)
   606  	require.Equal("/", l1.Root())
   607  
   608  	for _, x := range testCasesFile {
   609  		b, err := l1.Load(x.path)
   610  		require.NoError(err)
   611  		if !reflect.DeepEqual([]byte(x.expectedContent), b) {
   612  			t.Fatalf("in load expected %s, but got %s", x.expectedContent, b)
   613  		}
   614  	}
   615  
   616  	var testCasesHTTP = []testData{
   617  		{
   618  			path:            "http://example.com/resource.yaml",
   619  			expectedContent: "http content",
   620  		},
   621  		{
   622  			path:            "https://example.com/resource.yaml",
   623  			expectedContent: "https content",
   624  		},
   625  	}
   626  
   627  	for _, x := range testCasesHTTP {
   628  		hc := makeFakeHTTPClient(func(req *http.Request) *http.Response {
   629  			u := req.URL.String()
   630  			require.Equal(x.path, u)
   631  			return &http.Response{
   632  				StatusCode: 200,
   633  				Body:       io.NopCloser(bytes.NewBufferString(x.expectedContent)),
   634  				Header:     make(http.Header),
   635  			}
   636  		})
   637  		l2 := l1
   638  		l2.http = hc
   639  		b, err := l2.Load(x.path)
   640  		require.NoError(err)
   641  		if !reflect.DeepEqual([]byte(x.expectedContent), b) {
   642  			t.Fatalf("in load expected %s, but got %s", x.expectedContent, b)
   643  		}
   644  	}
   645  
   646  	var testCaseUnsupported = []testData{
   647  		{
   648  			path:            "httpsnotreal://example.com/resource.yaml",
   649  			expectedContent: "invalid",
   650  		},
   651  	}
   652  	for _, x := range testCaseUnsupported {
   653  		hc := makeFakeHTTPClient(func(req *http.Request) *http.Response {
   654  			t.Fatalf("unexpected request to URL %s", req.URL.String())
   655  			return nil
   656  		})
   657  		l2 := l1
   658  		l2.http = hc
   659  		_, err := l2.Load(x.path)
   660  		require.Error(err)
   661  	}
   662  }
   663  
   664  // setupOnDisk sets up a file system on disk and directory that is cleaned after
   665  // test completion.
   666  // TODO(annasong): Move all loader tests that require real file system into
   667  // api/krusty.
   668  func setupOnDisk(t *testing.T) (filesys.FileSystem, filesys.ConfirmedDir) {
   669  	t.Helper()
   670  
   671  	fSys := filesys.MakeFsOnDisk()
   672  	dir, err := filesys.NewTmpConfirmedDir()
   673  	require.NoError(t, err)
   674  	t.Cleanup(func() {
   675  		_ = fSys.RemoveAll(dir.String())
   676  	})
   677  	return fSys, dir
   678  }
   679  

View as plain text