Kind: kustomize integration is broken on windows

Created on 16 Dec 2018  ยท  5Comments  ยท  Source: kubernetes-sigs/kind

... due to the fake filesystem paths:

C:\Users\benjamin\Downloads\kind-0.0.1\kind-0.0.1>C:\Users\benjamin\go\bin\kind.exe create cluster
Creating cluster 'kind-1' ...
 โœ“ Ensuring node image (kindest/node:v1.12.3) ๐Ÿ–ผ
 โœ“ [kind-1-control-plane] Creating node container ๐Ÿ“ฆ
 โœ“ [kind-1-control-plane] Fixing mounts ๐Ÿ—ป
 โœ“ [kind-1-control-plane] Starting systemd ๐Ÿ–ฅ
 โœ— [kind-1-control-plane] Waiting for docker to be ready ๐Ÿ‹
Error: failed to create cluster: failed to create kubeadm config: cannot read file "C:\\kustomization.yaml"
Usage:
  kind create cluster [flags]

Flags:
      --config string   path to a kind config file
  -h, --help            help for cluster
      --image string    node docker image to use for booting the cluster
      --name string     cluster context name (default "1")
      --retain          retain nodes for debugging when cluster creation fails
      --wait duration   Wait for control plane node to be ready (default 0s)

Global Flags:
      --loglevel string   logrus log level [panic, fatal, error, warning, info, debug] (default "warning")

failed to create cluster: failed to create kubeadm config: cannot read file "C:\\kustomization.yaml"

This is likely a very simple fix.

/kind bug
/priority important-soon
/assign

kinbug lifecyclactive prioritimportant-soon

Most helpful comment

fakeDir = C:\\ is OK, i guess.

for /f %i in ('C:\Users\benjamin\go\bin\kind.exe get kubeconfig-path') do set KUBECONFIG=%i

should be:

for /f "delims=*" %i in ('kind get kubeconfig-path') do set KUBECONFIG="%i"

to handle spaces in paths.

All 5 comments

--- a/vendor/sigs.k8s.io/kustomize/pkg/loader/loader.go
+++ b/vendor/sigs.k8s.io/kustomize/pkg/loader/loader.go
@@ -20,6 +20,7 @@ package loader
 import (
        "fmt"
        "path/filepath"
        "sigs.k8s.io/kustomize/pkg/ifc"

        "sigs.k8s.io/kustomize/pkg/fs"
@@ -38,11 +39,11 @@ func NewLoader(target, r string, fSys fs.FileSystem) (ifc.Lo
ader, error) {

        l := newFileLoaderAtRoot(r, fSys)
        if isRootLoaderPath(r) {
-               absPath, err := filepath.Abs(target)
+               cleanPath, err := filepath.Clean(target)
                if err != nil {
                        return nil, err
                }
-               target = absPath
+               target = cleanPath
        }

but note that upstream has diverged.

problem here is that Abs() on Windows calls GetFullPathNameW and that obtains drives + path:
https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getfullpathnamea

while having a drive letter makes perfect sense for NTFS it does not for kustomize's fake FS. Clean() might be sufficient here instead.


EDIT: seems like the problem is more complicated in kustomize.
the FS file paths are not portable due to all usages of Abs() and IsAbs().

quick hack at this looks like:

--- a/pkg/kustomize/kustomize.go
+++ b/pkg/kustomize/kustomize.go
@@ -21,6 +21,8 @@ import (
        "bytes"
        "fmt"
        "io/ioutil"
+       "path/filepath"
+       "runtime"

        "sigs.k8s.io/kustomize/k8sdeps"
        "sigs.k8s.io/kustomize/pkg/commands/build"
@@ -51,13 +53,17 @@ func Build(resources, patches []string, patchesJSON6902 []PatchJSON6902) (string
        memFS := fs.MakeFakeFS()
        var kustomization bytes.Buffer
        fakeDir := "/"
+       // for windows at least we need this to be a drive because kustomize uses filepath.Abs()
+       if runtime.GOOS == "windows" {
+               fakeDir = `C:\\`
+       }

        // NOTE: we always write this header as you cannot build without any resources
        kustomization.WriteString("resources:\n")
        for i, resource := range resources {
                // this cannot error per docs
                name := fmt.Sprintf("resource-%d.yaml", i)
-               _ = memFS.WriteFile(fakeDir+name, []byte(resource))
+               _ = memFS.WriteFile(filepath.Join(fakeDir, name), []byte(resource))
                fmt.Fprintf(&kustomization, " - %s\n", name)
        }

@@ -67,7 +73,7 @@ func Build(resources, patches []string, patchesJSON6902 []PatchJSON6902) (string
        for i, patch := range patches {
                // this cannot error per docs
                name := fmt.Sprintf("patch-%d.yaml", i)
-               _ = memFS.WriteFile(fakeDir+name, []byte(patch))
+               _ = memFS.WriteFile(filepath.Join(fakeDir, name), []byte(patch))
                fmt.Fprintf(&kustomization, " - %s\n", name)
        }

@@ -77,7 +83,7 @@ func Build(resources, patches []string, patchesJSON6902 []PatchJSON6902) (string
        for i, patch := range patchesJSON6902 {
                // this cannot error per docs
                name := fmt.Sprintf("patch-json6902-%d.yaml", i)
-               _ = memFS.WriteFile(fakeDir+name, []byte(patch.Patch))
+               _ = memFS.WriteFile(filepath.Join(fakeDir, name), []byte(patch.Patch))
                fmt.Fprintf(&kustomization, " - path: %s\n", name)
                fmt.Fprintf(&kustomization, "   target:\n")
                fmt.Fprintf(&kustomization, "     group: %s\n", patch.Group)
@@ -91,7 +97,7 @@ func Build(resources, patches []string, patchesJSON6902 []PatchJSON6902) (string
                }
        }

-       memFS.WriteFile(fakeDir+"kustomization.yaml", kustomization.Bytes())
+       memFS.WriteFile(filepath.Join(fakeDir, "kustomization.yaml"), kustomization.Bytes())

We'll also need to update the KUBECONFIG instructions though, something like:
for /f %i in ('C:\Users\benjamin\go\bin\kind.exe get kubeconfig-path') do set KUBECONFIG=%i

And we'll need to update how we get $HOME/.kube when writing it. These are all pretty easy fixes though.

/lifecycle active

fakeDir = C:\\ is OK, i guess.

for /f %i in ('C:\Users\benjamin\go\bin\kind.exe get kubeconfig-path') do set KUBECONFIG=%i

should be:

for /f "delims=*" %i in ('kind get kubeconfig-path') do set KUBECONFIG="%i"

to handle spaces in paths.

Thanks, yeah. I'm going to do a bit more testing later before sending any patches, I think any drive letter should work since it just needs an absolute looking path.

Can confirm, even Y:\\ works on my windows 10 box, and I certainly don't have a Y drive :-)

I'll do a little more tinkering off and on and try to submit a patch sometime tomorrow.

Was this page helpful?
0 / 5 - 0 ratings