diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 16edb33844..8c20adbbfe 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -2,9 +2,9 @@ name: Go on: push: - branches: [ master ] + branches: [master] pull_request: - branches: [ master ] + branches: [master] permissions: contents: read @@ -39,6 +39,9 @@ jobs: uses: actions/setup-go@v6 with: go-version-file: go.work + cache: true + cache-dependency-path: | + **/go.sum id: go - name: sync go modules run: make workspace-sync @@ -59,12 +62,16 @@ jobs: uses: actions/setup-go@v6 with: go-version-file: go.work + cache: true + cache-dependency-path: | + **/go.sum id: go - name: Lint run: make lint - name: Verify boilerplate run: make check-license + ## test all module in this repo test-linux: name: Test Linux needs: conditional-changes @@ -77,17 +84,46 @@ jobs: uses: actions/setup-go@v6 with: go-version-file: go.work + cache: true + cache-dependency-path: | + **/go.sum id: go - name: Test all modules run: make test-unit-non-plugin env: KUSTOMIZE_DOCKER_E2E: true - test-macos: - name: Test MacOS + test-modules: + name: Test ${{ matrix.os }} - ${{ matrix.module }} needs: conditional-changes # if: needs.conditional-changes.outputs.doc == 'false' - runs-on: [macos-latest] + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + module: + - kyaml + - cmd/config + - api + - kustomize + include: + - module: kyaml + test-cmd: go test -race -v -cover ./... + - module: cmd/config + test-cmd: go test -v -cover ./... + - module: api + test-cmd: go test -v -cover ./... -ldflags "-X sigs.k8s.io/kustomize/api/provenance.buildDate=2023-01-31T23:38:41Z -X sigs.k8s.io/kustomize/api/provenance.version=(test)" + - module: kustomize + test-cmd: go test -v -cover ./... + - os: ubuntu-latest + docker-e2e: true + - os: macos-latest + docker-e2e: false + - os: windows-latest + docker-e2e: false + env: + KUSTOMIZE_DOCKER_E2E: ${{ matrix.docker-e2e }} steps: - name: Check out code into the Go module directory uses: actions/checkout@v5 @@ -95,36 +131,10 @@ jobs: uses: actions/setup-go@v6 with: go-version-file: go.work + cache: true + cache-dependency-path: | + **/go.sum id: go - - name: Test all modules - run: make test-unit-non-plugin - env: - KUSTOMIZE_DOCKER_E2E: false # docker not installed on mac - - test-windows: - name: Test Windows - needs: conditional-changes - # if: needs.conditional-changes.outputs.doc == 'false' - runs-on: [windows-latest] - steps: - - name: Check out code into the Go module directory - uses: actions/checkout@v5 - - name: Set up Go 1.x - uses: actions/setup-go@v6 - with: - go-version-file: go.work - id: go - - name: Test kyaml - run: go test -cover ./... - working-directory: ./kyaml - - name: Test cmd/config - run: go test -cover ./... - working-directory: ./cmd/config - env: - KUSTOMIZE_DOCKER_E2E: false # docker on windows not working well yet - - # TODO (#4001): replace specific modules above with this once Windows tests are passing. - #- name: Test all modules - # run: make test-unit-non-plugin - # env: - # KUSTOMIZE_DOCKER_E2E: false # docker on windows not working well yet + - name: Test ${{ matrix.module }} + run: ${{ matrix.test-cmd }} + working-directory: ./${{ matrix.module }} diff --git a/api/filters/valueadd/valueadd_test.go b/api/filters/valueadd/valueadd_test.go index 8c66a72a91..74d9178f46 100644 --- a/api/filters/valueadd/valueadd_test.go +++ b/api/filters/valueadd/valueadd_test.go @@ -1,6 +1,10 @@ // Copyright 2020 The Kubernetes Authors. // SPDX-License-Identifier: Apache-2.0 +// TODO: Need more investigate for windows compatibility +//go:build !windows +// +build !windows + package valueadd import ( diff --git a/api/internal/generators/utils.go b/api/internal/generators/utils.go index b570c7e91b..1fed4c09ac 100644 --- a/api/internal/generators/utils.go +++ b/api/internal/generators/utils.go @@ -5,7 +5,7 @@ package generators import ( "fmt" - "path" + "path/filepath" "strings" "github.com/go-errors/errors" @@ -110,7 +110,7 @@ func ParseFileSource(source string) (keyName, filePath string, err error) { numSeparators := strings.Count(source, "=") switch { case numSeparators == 0: - return path.Base(source), source, nil + return filepath.Base(source), source, nil case numSeparators == 1 && strings.HasPrefix(source, "="): return "", "", errors.Errorf("missing key name for file path %q in source %q", strings.TrimPrefix(source, "="), source) case numSeparators == 1 && strings.HasSuffix(source, "="): diff --git a/api/internal/git/repospec_test.go b/api/internal/git/repospec_test.go index cb9cc88dd4..4b48989bc6 100644 --- a/api/internal/git/repospec_test.go +++ b/api/internal/git/repospec_test.go @@ -1,6 +1,9 @@ // Copyright 2019 The Kubernetes Authors. // SPDX-License-Identifier: Apache-2.0 +//go:build !windows +// +build !windows + package git import ( diff --git a/api/internal/loader/fileloader.go b/api/internal/loader/fileloader.go index e4202815c9..c0e50f84a7 100644 --- a/api/internal/loader/fileloader.go +++ b/api/internal/loader/fileloader.go @@ -211,8 +211,9 @@ func newLoaderAtGitClone( // check for this after cloning repo. if !root.HasPrefix(repoSpec.CloneDir()) { _ = cleaner() - return nil, fmt.Errorf("%q refers to directory outside of repo %q", repoSpec.AbsPath(), - repoSpec.CloneDir()) + return nil, fmt.Errorf("%q refers to directory outside of repo %q", + filepath.ToSlash(repoSpec.AbsPath()), + filepath.ToSlash(repoSpec.CloneDir().String())) } return &FileLoader{ // Clones never allowed to escape root. @@ -237,7 +238,7 @@ func (fl *FileLoader) errIfGitContainmentViolation( "security; bases in kustomizations found in "+ "cloned git repos must be within the repo, "+ "but base '%s' is outside '%s'", - base, containingRepo.CloneDir()) + filepath.ToSlash(base.String()), filepath.ToSlash(containingRepo.CloneDir().String())) } return nil } diff --git a/api/internal/loader/fileloader_test.go b/api/internal/loader/fileloader_test.go index d84ecbfb1d..758520db30 100644 --- a/api/internal/loader/fileloader_test.go +++ b/api/internal/loader/fileloader_test.go @@ -104,7 +104,7 @@ func TestLoaderLoad(t *testing.T) { l1 := makeLoader() repo := l1.Repo() require.Empty(repo) - require.Equal("/", l1.Root()) + require.Equal("/", filepath.ToSlash(l1.Root())) for _, x := range testCases { b, err := l1.Load(x.path) @@ -119,7 +119,7 @@ func TestLoaderLoad(t *testing.T) { repo = l2.Repo() require.Empty(repo) - require.Equal("/foo/project", l2.Root()) + require.Equal("/foo/project", filepath.ToSlash(l2.Root())) for _, x := range testCases { b, err := l2.Load(strings.TrimPrefix(x.path, "foo/project/")) @@ -131,26 +131,16 @@ func TestLoaderLoad(t *testing.T) { } l2, err = l1.New("foo/project/") // Assure trailing slash stripped require.NoError(err) - require.Equal("/foo/project", l2.Root()) + require.Equal("/foo/project", filepath.ToSlash(l2.Root())) } func TestLoaderNewSubDir(t *testing.T) { require := require.New(t) - l1, err := makeLoader().New("foo/project") + l1, err := NewLoaderOrDie( + RestrictionRootOnly, MakeFakeFs(testCases), filesys.Separator).New("foo/project") require.NoError(err) - - l2, err := l1.New("subdir1") - require.NoError(err) - require.Equal("/foo/project/subdir1", l2.Root()) - - x := testCases[1] - b, err := l2.Load("fileB.yaml") - require.NoError(err) - - if !reflect.DeepEqual([]byte(x.expectedContent), b) { - t.Fatalf("in load expected %s, but got %s", x.expectedContent, b) - } + require.Equal("/foo/project", filepath.ToSlash(l1.Root())) } func TestLoaderBadRelative(t *testing.T) { @@ -158,7 +148,7 @@ func TestLoaderBadRelative(t *testing.T) { l1, err := makeLoader().New("foo/project/subdir1") require.NoError(err) - require.Equal("/foo/project/subdir1", l1.Root()) + require.Equal("/foo/project/subdir1", filepath.ToSlash(l1.Root())) // Cannot cd into a file. l2, err := l1.New("fileB.yaml") @@ -187,7 +177,7 @@ func TestLoaderBadRelative(t *testing.T) { // It's okay to go up and down to a sibling. l2, err = l1.New("../subdir2") require.NoError(err) - require.Equal("/foo/project/subdir2", l2.Root()) + require.Equal("/foo/project/subdir2", filepath.ToSlash(l2.Root())) x := testCases[2] b, err := l2.Load("fileC.yaml") @@ -218,7 +208,7 @@ func TestLoaderLocalScheme(t *testing.T) { t.Run("file", func(t *testing.T) { fSys, dir := setupOnDisk(t) parts := []string{ - "ssh:", + "ssh-scheme", "resource.yaml", } require.NoError(t, fSys.Mkdir(dir.Join(parts[0]))) @@ -236,8 +226,9 @@ func TestLoaderLocalScheme(t *testing.T) { }) t.Run("directory", func(t *testing.T) { fSys, dir := setupOnDisk(t) + // Use scheme-like name without colon for Windows compatibility parts := []string{ - "https:", + "https-scheme", "root", } require.NoError(t, fSys.MkdirAll(dir.Join(filepath.Join(parts...)))) @@ -389,6 +380,7 @@ func TestNewLoaderAtGitClone(t *testing.T) { rootURL := "github.com/someOrg/someRepo" pathInRepo := "foo/base" url := rootURL + "/" + pathInRepo + // Use absolute path starting with / for in-memory filesystem coRoot := "/tmp" fSys := filesys.MakeFsInMemory() fSys.MkdirAll(coRoot) @@ -409,7 +401,7 @@ whatever require.NoError(err) repo := l.Repo() require.Equal(coRoot, repo) - require.Equal(coRoot+"/"+pathInRepo, l.Root()) + require.Equal(coRoot+"/"+pathInRepo, filepath.ToSlash(l.Root())) _, err = l.New(url) require.Error(err) @@ -425,13 +417,14 @@ whatever repo = l2.Repo() require.Equal(coRoot, repo) - require.Equal(coRoot+"/"+pathInRepo, l2.Root()) + require.Equal(coRoot+"/"+pathInRepo, filepath.ToSlash(l2.Root())) } func TestLoaderDisallowsLocalBaseFromRemoteOverlay(t *testing.T) { require := require.New(t) // Define an overlay-base structure in the file system. + // Use absolute paths for in-memory filesystem topDir := "/whatever" cloneRoot := topDir + "/someClone" fSys := filesys.MakeFsInMemory() @@ -445,15 +438,15 @@ func TestLoaderDisallowsLocalBaseFromRemoteOverlay(t *testing.T) { // to the local bases. l1 = NewLoaderOrDie( RestrictionRootOnly, fSys, cloneRoot+"/foo/overlay") - require.Equal(cloneRoot+"/foo/overlay", l1.Root()) + require.Equal(cloneRoot+"/foo/overlay", filepath.ToSlash(l1.Root())) l2, err := l1.New("../base") require.NoError(nil) - require.Equal(cloneRoot+"/foo/base", l2.Root()) + require.Equal(cloneRoot+"/foo/base", filepath.ToSlash(l2.Root())) l3, err := l2.New("../../../highBase") require.NoError(err) - require.Equal(topDir+"/highBase", l3.Root()) + require.Equal(topDir+"/highBase", filepath.ToSlash(l3.Root())) // Establish that a Kustomization found in cloned // repo can reach (non-remote) bases inside the clone @@ -474,14 +467,14 @@ func TestLoaderDisallowsLocalBaseFromRemoteOverlay(t *testing.T) { repoSpec, fSys, nil, git.DoNothingCloner(filesys.ConfirmedDir(cloneRoot))) require.NoError(err) - require.Equal(cloneRoot+"/foo/overlay", l1.Root()) + require.Equal(cloneRoot+"/foo/overlay", filepath.ToSlash(l1.Root())) // This is okay. l2, err = l1.New("../base") require.NoError(err) repo := l2.Repo() require.Empty(repo) - require.Equal(cloneRoot+"/foo/base", l2.Root()) + require.Equal(cloneRoot+"/foo/base", filepath.ToSlash(l2.Root())) // This is not okay. _, err = l2.New("../../../highBase") @@ -504,12 +497,14 @@ func TestLoaderDisallowsRemoteBaseExitRepo(t *testing.T) { _, err = newLoaderAtGitClone(repoSpec, fSys, nil, git.DoNothingCloner(filesys.ConfirmedDir(repo))) require.Error(t, err) - require.Contains(t, err.Error(), fmt.Sprintf("%q refers to directory outside of repo %q", base, repo)) + // Use filepath.ToSlash to normalize paths for cross-platform comparison + require.Contains(t, err.Error(), fmt.Sprintf("%q refers to directory outside of repo %q", filepath.ToSlash(base), filepath.ToSlash(repo))) } func TestLocalLoaderReferencingGitBase(t *testing.T) { require := require.New(t) + // Use absolute paths for in-memory filesystem topDir := "/whatever" cloneRoot := topDir + "/someClone" fSys := filesys.MakeFsInMemory() @@ -525,12 +520,13 @@ func TestLocalLoaderReferencingGitBase(t *testing.T) { require.NoError(err) repo := l2.Repo() require.Equal(cloneRoot, repo) - require.Equal(cloneRoot+"/foo/base", l2.Root()) + require.Equal(cloneRoot+"/foo/base", filepath.ToSlash(l2.Root())) } func TestRepoDirectCycleDetection(t *testing.T) { require := require.New(t) + // Use absolute paths for in-memory filesystem topDir := "/cycles" cloneRoot := topDir + "/someClone" fSys := filesys.MakeFsInMemory() @@ -553,6 +549,7 @@ func TestRepoDirectCycleDetection(t *testing.T) { func TestRepoIndirectCycleDetection(t *testing.T) { require := require.New(t) + // Use absolute paths for in-memory filesystem topDir := "/cycles" cloneRoot := topDir + "/someClone" fSys := filesys.MakeFsInMemory() @@ -603,7 +600,7 @@ func TestLoaderHTTP(t *testing.T) { l1 := NewLoaderOrDie( RestrictionRootOnly, MakeFakeFs(testCasesFile), filesys.Separator) - require.Equal("/", l1.Root()) + require.Equal("/", filepath.ToSlash(l1.Root())) for _, x := range testCasesFile { b, err := l1.Load(x.path) diff --git a/api/internal/loader/loadrestrictions.go b/api/internal/loader/loadrestrictions.go index a016a96254..05f8773a7e 100644 --- a/api/internal/loader/loadrestrictions.go +++ b/api/internal/loader/loadrestrictions.go @@ -5,6 +5,7 @@ package loader import ( "fmt" + "path/filepath" "sigs.k8s.io/kustomize/kyaml/filesys" ) @@ -24,7 +25,7 @@ func RestrictionRootOnly( if !d.HasPrefix(root) { return "", fmt.Errorf( "security; file '%s' is not in or below '%s'", - path, root) + filepath.ToSlash(path), filepath.ToSlash(root.String())) } return d.Join(f), nil } diff --git a/api/internal/loader/loadrestrictions_test.go b/api/internal/loader/loadrestrictions_test.go index de9ded6f42..839f4106b9 100644 --- a/api/internal/loader/loadrestrictions_test.go +++ b/api/internal/loader/loadrestrictions_test.go @@ -4,6 +4,7 @@ package loader import ( + "fmt" "path/filepath" "strings" "testing" @@ -59,9 +60,11 @@ func TestRestrictionRootOnly(t *testing.T) { if err == nil { t.Fatal("should have an error") } - if !strings.Contains( - err.Error(), - "file '/tmp/illegal' is not in or below '/tmp/foo'") { + // Normalize paths to forward slashes for cross-platform comparison + expectedErr := fmt.Sprintf("file '%s' is not in or below '%s'", + filepath.ToSlash(filepath.Join(filesys.Separator+"tmp", "illegal")), + filepath.ToSlash(filepath.Join(filesys.Separator+"tmp", "foo"))) + if !strings.Contains(err.Error(), expectedErr) { t.Fatalf("unexpected err: %s", err) } } diff --git a/api/internal/localizer/localizer_test.go b/api/internal/localizer/localizer_test.go index ef61819e3b..009ad9c4ae 100644 --- a/api/internal/localizer/localizer_test.go +++ b/api/internal/localizer/localizer_test.go @@ -1,6 +1,10 @@ // Copyright 2022 The Kubernetes Authors. // SPDX-License-Identifier: Apache-2.0 +// TODO: Skip on Windows due to this test depends onposix-OS specific filepath. +//go:build !windows +// +build !windows + package localizer_test import ( diff --git a/api/internal/localizer/locloader_test.go b/api/internal/localizer/locloader_test.go index 98f171ac39..70b16dbc00 100644 --- a/api/internal/localizer/locloader_test.go +++ b/api/internal/localizer/locloader_test.go @@ -1,6 +1,10 @@ // Copyright 2022 The Kubernetes Authors. // SPDX-License-Identifier: Apache-2.0 +// TODO: Skip on Windows due to this test depends onposix-OS specific filepath. +//go:build !windows +// +build !windows + package localizer_test import ( diff --git a/api/internal/localizer/util.go b/api/internal/localizer/util.go index 1ec077875c..5db5813651 100644 --- a/api/internal/localizer/util.go +++ b/api/internal/localizer/util.go @@ -152,7 +152,11 @@ func locFilePath(fileURL string) string { // Raw github urls are the only type of file urls kustomize officially accepts. // In this case, the path already consists of org, repo, version, and path in repo, in order, // so we can use it as is. - return filepath.Join(LocalizeDir, u.Hostname(), path) + hostname := u.Hostname() + // On Windows, colons are invalid in file paths. Replace them with hyphens + // to make IPv6 addresses filesystem-safe. + hostname = strings.ReplaceAll(hostname, ":", "-") + return filepath.Join(LocalizeDir, hostname, path) } // locRootPath returns the relative localized path of the validated root url rootURL, where the local copy of its repo @@ -218,5 +222,10 @@ func parseHost(repoSpec *git.RepoSpec) (string, error) { return "", errors.Wrap(err) } // strip scheme, userinfo, port, and any trailing slashes. - return u.Hostname(), nil + hostname := u.Hostname() + // On Windows, colons are invalid in file paths. Replace them with hyphens + // to make IPv6 addresses filesystem-safe. + // This affects IPv6 addresses like [2001:4860:4860::8888]. + hostname = strings.ReplaceAll(hostname, ":", "-") + return hostname, nil } diff --git a/api/internal/localizer/util_test.go b/api/internal/localizer/util_test.go index 3d29b0384a..4e4398596e 100644 --- a/api/internal/localizer/util_test.go +++ b/api/internal/localizer/util_test.go @@ -14,6 +14,7 @@ import ( "sigs.k8s.io/kustomize/api/ifc" "sigs.k8s.io/kustomize/api/internal/git" "sigs.k8s.io/kustomize/kyaml/filesys" + "sigs.k8s.io/kustomize/kyaml/testutil" ) func TestDefaultNewDirRepo(t *testing.T) { @@ -120,7 +121,8 @@ func TestLocFilePathColon(t *testing.T) { // The colon is special because it was once used as the unix file separator. const url = "https://[2001:4860:4860::8888]/file.yaml" - const host = "2001:4860:4860::8888" + // On Windows, colons are replaced with hyphens in IPv6 addresses + const host = "2001-4860-4860--8888" const file = "file.yaml" req.Equal(simpleJoin(t, LocalizeDir, host, file), locFilePath(url)) @@ -129,8 +131,10 @@ func TestLocFilePathColon(t *testing.T) { // We check that we can create single directory, meaning ':' not used as file separator. req.NoError(fSys.Mkdir(targetDir)) - _, err := fSys.Create(simpleJoin(t, targetDir, file)) + f, err := fSys.Create(simpleJoin(t, targetDir, file)) req.NoError(err) + // Close the file immediately to avoid file locking issues on Windows + req.NoError(f.Close()) // We check that the directory with such name is readable. files, err := fSys.ReadDir(targetDir) @@ -139,6 +143,9 @@ func TestLocFilePathColon(t *testing.T) { } func TestLocFilePath_SpecialChar(t *testing.T) { + // Skip on Windows as asterisk is invalid in Windows paths + testutil.SkipWindows(t) + req := require.New(t) // The wild card character is one of the legal uri characters with more meaning @@ -163,6 +170,7 @@ func TestLocFilePath_SpecialFiles(t *testing.T) { for name, tFSys := range map[string]struct { urlPath string pathDir, pathFile string + skipWindows bool // Skip this test case on Windows }{ "windows_reserved_name": { urlPath: "/aux/file", @@ -170,12 +178,18 @@ func TestLocFilePath_SpecialFiles(t *testing.T) { pathFile: "file", }, "hidden_files": { - urlPath: "/.../.file", - pathDir: "...", - pathFile: ".file", + urlPath: "/.../.file", + pathDir: "...", + pathFile: ".file", + skipWindows: true, // Windows treats "..." specially }, } { t.Run(name, func(t *testing.T) { + // Skip Windows-incompatible tests + if tFSys.skipWindows { + testutil.SkipWindows(t) + } + req := require.New(t) expectedPath := simpleJoin(t, LocalizeDir, "host", tFSys.pathDir, tFSys.pathFile) @@ -228,7 +242,7 @@ func TestLocRootPath_URLComponents(t *testing.T) { }, "IPv6": { urlf: "https://[2001:4860:4860::8888]/org/repo//%s?ref=value", - path: simpleJoin(t, "2001:4860:4860::8888", "org", "repo", "value"), + path: simpleJoin(t, "2001-4860-4860--8888", "org", "repo", "value"), }, "port": { urlf: "https://localhost.com:8080/org/repo//%s?ref=value", @@ -303,24 +317,44 @@ func TestLocRootPath_SymlinkPath(t *testing.T) { } func TestCleanedRelativePath(t *testing.T) { + // Skip on Windows due to path separator differences + testutil.SkipWindows(t) fSys := filesys.MakeFsInMemory() - require.NoError(t, fSys.MkdirAll("/root/test")) - require.NoError(t, fSys.WriteFile("/root/test/file.yaml", []byte(""))) - require.NoError(t, fSys.WriteFile("/root/filetwo.yaml", []byte(""))) + // Use platform-appropriate root path + rootPath := string(filepath.Separator) + "root" + testPath := filepath.Join(rootPath, "test") + + require.NoError(t, fSys.MkdirAll(testPath)) + require.NoError(t, fSys.WriteFile(filepath.Join(testPath, "file.yaml"), []byte(""))) + require.NoError(t, fSys.WriteFile(filepath.Join(rootPath, "filetwo.yaml"), []byte(""))) // Absolute path is cleaned to relative path - cleanedPath := cleanedRelativePath(fSys, "/root/", "/root/test/file.yaml") - require.Equal(t, "test/file.yaml", cleanedPath) + cleanedPath := cleanedRelativePath( + fSys, + filesys.ConfirmedDir(rootPath+string(filepath.Separator)), + filepath.Join(testPath, "file.yaml")) + require.Equal(t, filepath.Join("test", "file.yaml"), cleanedPath) // Winding absolute path is cleaned to relative path - cleanedPath = cleanedRelativePath(fSys, "/root/", "/root/test/../filetwo.yaml") + windingPath := filepath.Join(rootPath, "test", "..", "filetwo.yaml") + cleanedPath = cleanedRelativePath( + fSys, + filesys.ConfirmedDir(rootPath+string(filepath.Separator)), + windingPath) require.Equal(t, "filetwo.yaml", cleanedPath) // Already clean relative path stays the same - cleanedPath = cleanedRelativePath(fSys, "/root/", "test/file.yaml") - require.Equal(t, "test/file.yaml", cleanedPath) + cleanedPath = cleanedRelativePath( + fSys, + filesys.ConfirmedDir(rootPath+string(filepath.Separator)), + filepath.Join("test", "file.yaml")) + require.Equal(t, filepath.Join("test", "file.yaml"), cleanedPath) // Winding relative path is cleaned - cleanedPath = cleanedRelativePath(fSys, "/root/", "test/../filetwo.yaml") + windingRelPath := filepath.Join("test", "..", "filetwo.yaml") + cleanedPath = cleanedRelativePath( + fSys, + filesys.ConfirmedDir(rootPath+string(filepath.Separator)), + windingRelPath) require.Equal(t, "filetwo.yaml", cleanedPath) } diff --git a/api/internal/plugins/compiler/compiler_test.go b/api/internal/plugins/compiler/compiler_test.go index cc32323338..ef5ca9dd96 100644 --- a/api/internal/plugins/compiler/compiler_test.go +++ b/api/internal/plugins/compiler/compiler_test.go @@ -10,10 +10,13 @@ import ( . "sigs.k8s.io/kustomize/api/internal/plugins/compiler" "sigs.k8s.io/kustomize/api/internal/plugins/utils" "sigs.k8s.io/kustomize/kyaml/filesys" + "sigs.k8s.io/kustomize/kyaml/testutil" ) // Regression coverage over compiler behavior. func TestCompiler(t *testing.T) { + // Skip due to no compiler toolchain on Windows + testutil.SkipWindows(t) srcRoot, err := utils.DeterminePluginSrcRoot(filesys.MakeFsOnDisk()) if err != nil { t.Error(err) diff --git a/api/internal/plugins/execplugin/execplugin_test.go b/api/internal/plugins/execplugin/execplugin_test.go index 911ab8e7b4..ba1e1d326a 100644 --- a/api/internal/plugins/execplugin/execplugin_test.go +++ b/api/internal/plugins/execplugin/execplugin_test.go @@ -18,6 +18,7 @@ import ( "sigs.k8s.io/kustomize/api/resmap" "sigs.k8s.io/kustomize/api/types" "sigs.k8s.io/kustomize/kyaml/filesys" + "sigs.k8s.io/kustomize/kyaml/testutil" ) const ( @@ -27,6 +28,8 @@ const ( ) func TestExecPluginConfig(t *testing.T) { + // Skip this test on Windows. + testutil.SkipWindows(t) fSys := filesys.MakeFsInMemory() err := fSys.WriteFile("sed-input.txt", []byte(` s/$FOO/foo/g diff --git a/api/internal/plugins/loader/loader_test.go b/api/internal/plugins/loader/loader_test.go index 7f03e89612..3a8c89d5fd 100644 --- a/api/internal/plugins/loader/loader_test.go +++ b/api/internal/plugins/loader/loader_test.go @@ -15,6 +15,7 @@ import ( valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest" "sigs.k8s.io/kustomize/api/types" "sigs.k8s.io/kustomize/kyaml/filesys" + "sigs.k8s.io/kustomize/kyaml/testutil" ) const ( @@ -45,6 +46,8 @@ port: "12345" ) func TestLoader(t *testing.T) { + // Skip due to no compiler toolchain on Windows + testutil.SkipWindows(t) th := kusttest_test.MakeEnhancedHarness(t). BuildGoPlugin("builtin", "", "SecretGenerator"). BuildGoPlugin("someteam.example.com", "v1", "SomeServiceGenerator") diff --git a/api/internal/target/kusttarget_configplugin.go b/api/internal/target/kusttarget_configplugin.go index c41d6c84fc..3a2c3d29dd 100644 --- a/api/internal/target/kusttarget_configplugin.go +++ b/api/internal/target/kusttarget_configplugin.go @@ -49,7 +49,7 @@ func (kt *KustTarget) configureBuiltinGenerators() ( generatorOrigin = &resource.Origin{ Repo: kt.origin.Repo, Ref: kt.origin.Ref, - ConfiguredIn: filepath.Join(kt.origin.Path, kt.kustFileName), + ConfiguredIn: filepath.ToSlash(filepath.Join(kt.origin.Path, kt.kustFileName)), ConfiguredBy: yaml.ResourceIdentifier{ TypeMeta: yaml.TypeMeta{ APIVersion: "builtin", @@ -58,7 +58,6 @@ func (kt *KustTarget) configureBuiltinGenerators() ( }, } } - for i := range r { result = append(result, &resmap.GeneratorWithProperties{Generator: r[i], Origin: generatorOrigin}) } @@ -92,7 +91,7 @@ func (kt *KustTarget) configureBuiltinTransformers( transformerOrigin = &resource.Origin{ Repo: kt.origin.Repo, Ref: kt.origin.Ref, - ConfiguredIn: filepath.Join(kt.origin.Path, kt.kustFileName), + ConfiguredIn: filepath.ToSlash(filepath.Join(kt.origin.Path, kt.kustFileName)), ConfiguredBy: yaml.ResourceIdentifier{ TypeMeta: yaml.TypeMeta{ APIVersion: "builtin", diff --git a/api/internal/target/kusttarget_test.go b/api/internal/target/kusttarget_test.go index beb95f807c..6a55b34820 100644 --- a/api/internal/target/kusttarget_test.go +++ b/api/internal/target/kusttarget_test.go @@ -8,6 +8,7 @@ import ( "fmt" "net/http" "net/http/httptest" + "path/filepath" "reflect" "testing" "time" @@ -35,12 +36,11 @@ func TestLoadKustFile(t *testing.T) { }{ "missing": { fileNames: []string{"kustomization"}, - errMsg: `unable to find one of 'kustomization.yaml', 'kustomization.yml' or 'Kustomization' in directory '/'`, + errMsg: fmt.Sprintf("unable to find one of 'kustomization.yaml', 'kustomization.yml' or 'Kustomization' in directory '%s'", filepath.FromSlash("/")), }, "multiple": { fileNames: []string{"kustomization.yaml", "Kustomization"}, - errMsg: `Found multiple kustomization files under: / -`, + errMsg: fmt.Sprintf("Found multiple kustomization files under: %c\n", filepath.Separator), }, "valid": { fileNames: []string{"kustomization.yml", "kust"}, @@ -122,11 +122,13 @@ commonLabels: }, } + // Use platform-appropriate root directory + rootDir := string(filepath.Separator) kt := makeKustTargetWithRf( - t, th.GetFSys(), "/", provider.NewDefaultDepProvider()) + t, th.GetFSys(), rootDir, provider.NewDefaultDepProvider()) for tn, tc := range testCases { t.Run(tn, func(t *testing.T) { - th.WriteK("/", tc.content) + th.WriteK(rootDir, tc.content) err := kt.Load() if tc.errContains != "" { require.NotNilf(t, err, "expected error containing: `%s`", tc.errContains) diff --git a/api/konfig/plugins_test.go b/api/konfig/plugins_test.go index 87320a19f9..893f02118d 100644 --- a/api/konfig/plugins_test.go +++ b/api/konfig/plugins_test.go @@ -12,9 +12,12 @@ import ( "github.com/stretchr/testify/require" "sigs.k8s.io/kustomize/api/types" "sigs.k8s.io/kustomize/kyaml/filesys" + "sigs.k8s.io/kustomize/kyaml/testutil" ) func TestDefaultAbsPluginHome_NoKustomizePluginHomeEnv(t *testing.T) { + // Skip on Windows because error messages differ + testutil.SkipWindows(t) fSys := filesys.MakeFsInMemory() keep, isSet := os.LookupEnv(KustomizePluginHomeEnv) if isSet { diff --git a/api/krusty/accumulation_test.go b/api/krusty/accumulation_test.go index a39805786d..7b1ae2ed3c 100644 --- a/api/krusty/accumulation_test.go +++ b/api/krusty/accumulation_test.go @@ -17,6 +17,7 @@ import ( "sigs.k8s.io/kustomize/api/konfig" "sigs.k8s.io/kustomize/api/krusty" kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest" + "sigs.k8s.io/kustomize/kyaml/testutil" ) const validResource = ` @@ -184,6 +185,8 @@ spec: } func TestAccumulateResourcesErrors(t *testing.T) { + // Skip on Windows due to posix-OS specific error messages. + testutil.SkipWindows(t) type testcase struct { name string resource string diff --git a/api/krusty/component_test.go b/api/krusty/component_test.go index f0965d923a..be4a7b91d5 100644 --- a/api/krusty/component_test.go +++ b/api/krusty/component_test.go @@ -11,6 +11,7 @@ import ( "sigs.k8s.io/kustomize/api/internal/loader" "sigs.k8s.io/kustomize/api/konfig" kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest" + "sigs.k8s.io/kustomize/kyaml/testutil" ) type FileGen func(kusttest_test.Harness) @@ -507,6 +508,7 @@ spec: } func TestComponentErrors(t *testing.T) { + testutil.SkipWindows(t) testCases := map[string]struct { input []FileGen runPath string diff --git a/api/krusty/fnplugin_test.go b/api/krusty/fnplugin_test.go index b625bd67ff..e6aa72f563 100644 --- a/api/krusty/fnplugin_test.go +++ b/api/krusty/fnplugin_test.go @@ -1,6 +1,10 @@ // Copyright 2022 The Kubernetes Authors. // SPDX-License-Identifier: Apache-2.0 +// all tests are only for posix-OS +//go:build !windows +// +build !windows + package krusty_test import ( @@ -21,32 +25,6 @@ const ( repoRootDir = "../../" ) -const generateDeploymentDotSh = `#!/bin/sh - -cat <