From e7e038f376bd4324a478b123779fdf427f720068 Mon Sep 17 00:00:00 2001 From: Shiming Zhang Date: Tue, 4 Jul 2023 13:47:21 +0800 Subject: [PATCH] Support windows binary --- .github/workflows/test.yaml | 57 ++++++++++++++++++--------- pkg/config/config.go | 2 +- pkg/kwokctl/runtime/binary/cluster.go | 2 +- pkg/kwokctl/runtime/exec.go | 11 +++--- pkg/utils/file/download.go | 2 +- pkg/utils/path/path.go | 18 ++++++++- pkg/utils/version/version_test.go | 6 +++ test/kwokctl/helper.sh | 6 +++ 8 files changed, 74 insertions(+), 30 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 962b389112..88d19b04fd 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -106,24 +106,32 @@ jobs: strategy: fail-fast: false matrix: - os: - - ubuntu-latest - - macos-latest + include: + # Windows # Linux containers are not supported on Windows Runner # https://github.com/orgs/community/discussions/25491#discussioncomment-3248089 - # - windows-latest - kwokctl-runtime: - - binary - - docker - - podman - - kind - - kind-podman - exclude: + - os: windows-latest + kwokctl-runtime: binary + + # MacOS - os: macos-latest - kwokctl-runtime: podman + kwokctl-runtime: binary + - os: macos-latest + kwokctl-runtime: docker - os: macos-latest + kwokctl-runtime: kind + + # Linux + - os: ubuntu-latest + kwokctl-runtime: binary + - os: ubuntu-latest + kwokctl-runtime: docker + - os: ubuntu-latest + kwokctl-runtime: podman + - os: ubuntu-latest + kwokctl-runtime: kind + - os: ubuntu-latest kwokctl-runtime: kind-podman - include: # nerdctl is still very early and has many bugs and differences in docker behavior, # so we need to verify that it works on every release. - os: ubuntu-latest @@ -158,22 +166,33 @@ jobs: # https://www.downloadkubernetes.com - name: Download Kubernetes Source Code uses: actions/checkout@v3 - if: ${{ matrix.kwokctl-runtime == 'binary' && matrix.os == 'macos-latest' }} + if: ${{ matrix.kwokctl-runtime == 'binary' && ( matrix.os == 'macos-latest' || matrix.os == 'windows-latest' ) }} with: repository: kubernetes/kubernetes path: kubernetes ref: v1.27.3 - - name: Build Kubernetes Binary + - name: Build Kubernetes Binary for Windows + if: ${{ matrix.kwokctl-runtime == 'binary' && matrix.os == 'windows-latest' }} + shell: bash + run: | + export GOBIN="$(go env GOPATH)/bin" + cd "${GITHUB_WORKSPACE}/kubernetes" && go install ./cmd/{kube-apiserver,kube-controller-manager,kube-scheduler} + mkdir -p ~/.kwok && cat > ~/.kwok/kwok.yaml << EOF + kind: KwokctlConfiguration + apiVersion: config.kwok.x-k8s.io/v1alpha1 + options: + kubeBinaryPrefix: '${GOBIN//\\//}' + EOF + - name: Build Kubernetes Binary for MacOS if: ${{ matrix.kwokctl-runtime == 'binary' && matrix.os == 'macos-latest' }} shell: bash run: | cd "${GITHUB_WORKSPACE}/kubernetes" && make WHAT="cmd/kube-apiserver cmd/kube-controller-manager cmd/kube-scheduler" - mkdir -p ~/.kwok - cat > ~/.kwok/kwok.yaml << EOF + mkdir -p ~/.kwok && cat > ~/.kwok/kwok.yaml << EOF kind: KwokctlConfiguration apiVersion: config.kwok.x-k8s.io/v1alpha1 options: - kubeBinaryPrefix: "${GITHUB_WORKSPACE}/kubernetes/_output/bin" + kubeBinaryPrefix: '${GITHUB_WORKSPACE}/kubernetes/_output/bin' EOF # TODO: workaround for https://github.com/actions/runner-images/issues/7753 (caused by https://bugs.launchpad.net/ubuntu/+source/libpod/+bug/2024394). @@ -228,7 +247,7 @@ jobs: sudo systemctl daemon-reload - name: Make pki directory - if: ${{ matrix.kwokctl-runtime == 'binary' }} + if: ${{ matrix.kwokctl-runtime == 'binary' && matrix.os != 'windows-latest' }} shell: bash run: | sudo mkdir -p /var/run/kubernetes diff --git a/pkg/config/config.go b/pkg/config/config.go index 709a6ef17e..07ca8f44e2 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -455,7 +455,7 @@ func loadRaw(r io.Reader) ([]json.RawMessage, error) { if errors.Is(err, io.EOF) { break } - return nil, err + return nil, fmt.Errorf("failed to decode %q: %w", raw, err) } if len(raw) == 0 { // Ignore empty documents diff --git a/pkg/kwokctl/runtime/binary/cluster.go b/pkg/kwokctl/runtime/binary/cluster.go index d45af4bee4..8bae962d1b 100644 --- a/pkg/kwokctl/runtime/binary/cluster.go +++ b/pkg/kwokctl/runtime/binary/cluster.go @@ -732,7 +732,7 @@ func (c *Cluster) Logs(ctx context.Context, name string, out io.Writer) error { f, err := os.OpenFile(logs, os.O_RDONLY, 0640) if err != nil { - return err + return fmt.Errorf("failed to open %s: %w", logs, err) } defer func() { err = f.Close() diff --git a/pkg/kwokctl/runtime/exec.go b/pkg/kwokctl/runtime/exec.go index 4a86ffa866..d658721546 100644 --- a/pkg/kwokctl/runtime/exec.go +++ b/pkg/kwokctl/runtime/exec.go @@ -21,7 +21,6 @@ import ( "context" "fmt" "os" - "path/filepath" "strconv" "strings" @@ -36,7 +35,7 @@ import ( // ForkExec forks a new process and execs the given command. // The process will be terminated when the context is canceled. func (c *Cluster) ForkExec(ctx context.Context, dir string, name string, args ...string) error { - pidPath := path.Join(dir, "pids", filepath.Base(name)+".pid") + pidPath := path.Join(dir, "pids", path.OnlyName(name)+".pid") if file.Exists(pidPath) { pidData, err := os.ReadFile(pidPath) if err == nil { @@ -50,7 +49,7 @@ func (c *Cluster) ForkExec(ctx context.Context, dir string, name string, args .. } ctx = exec.WithDir(ctx, dir) ctx = exec.WithFork(ctx, true) - logPath := path.Join(dir, "logs", filepath.Base(name)+".log") + logPath := path.Join(dir, "logs", path.OnlyName(name)+".log") logFile, err := c.OpenFile(logPath) if err != nil { return fmt.Errorf("open log file %s: %w", logPath, err) @@ -80,7 +79,7 @@ func (c *Cluster) ForkExec(ctx context.Context, dir string, name string, args .. // ForkExecKill kills the process if it is running. func (c *Cluster) ForkExecKill(ctx context.Context, dir string, name string) error { - pidPath := path.Join(dir, "pids", filepath.Base(name)+".pid") + pidPath := path.Join(dir, "pids", path.OnlyName(name)+".pid") if !file.Exists(pidPath) { // No pid file exists, which means the process has been terminated logger := log.FromContext(ctx) @@ -116,7 +115,7 @@ func (c *Cluster) ForkExecKill(ctx context.Context, dir string, name string) err // ForkExecIsRunning checks if the process is running. func (c *Cluster) ForkExecIsRunning(ctx context.Context, dir string, name string) bool { - pidPath := path.Join(dir, "pids", filepath.Base(name)+".pid") + pidPath := path.Join(dir, "pids", path.OnlyName(name)+".pid") if !file.Exists(pidPath) { logger := log.FromContext(ctx) logger.Debug("Stat file not exists", @@ -206,7 +205,7 @@ func FormatExec(ctx context.Context, name string, args ...string) string { _, _ = fmt.Fprintf(out, "%s ", strings.Join(opt.Env, " ")) } - _, _ = fmt.Fprintf(out, "%s", path.Base(name)) + _, _ = fmt.Fprintf(out, "%s", path.OnlyName(name)) for _, arg := range args { _, _ = fmt.Fprintf(out, " %s", arg) diff --git a/pkg/utils/file/download.go b/pkg/utils/file/download.go index 15b971f9e2..c4469805aa 100644 --- a/pkg/utils/file/download.go +++ b/pkg/utils/file/download.go @@ -48,7 +48,7 @@ func DownloadWithCacheAndExtract(ctx context.Context, cacheDir, src, dest string return err } err = untar(ctx, cacheTar, func(file string) (string, bool) { - if path.Base(file) == match { + if path.OnlyName(file) == match { return cache, true } return "", false diff --git a/pkg/utils/path/path.go b/pkg/utils/path/path.go index 61f58e6a05..d9249aa91a 100644 --- a/pkg/utils/path/path.go +++ b/pkg/utils/path/path.go @@ -66,7 +66,11 @@ func Expand(path string) (string, error) { } } - return filepath.Abs(path) + p, err := filepath.Abs(path) + if err != nil { + return "", err + } + return Clean(p), nil } // RelFromHome returns a path relative to the home directory. @@ -89,10 +93,20 @@ func Join(elem ...string) string { // Dir is a wrapper around filepath.Dir. func Dir(path string) string { - return filepath.Dir(path) + return Clean(filepath.Dir(path)) } // Base is a wrapper around filepath.Base. func Base(path string) string { return filepath.Base(path) } + +// Ext is a wrapper around filepath.Ext. +func Ext(path string) string { + return filepath.Ext(path) +} + +// OnlyName returns the file name without extension. +func OnlyName(path string) string { + return strings.TrimSuffix(Base(path), Ext(path)) +} diff --git a/pkg/utils/version/version_test.go b/pkg/utils/version/version_test.go index f8815faf28..94df909a3d 100644 --- a/pkg/utils/version/version_test.go +++ b/pkg/utils/version/version_test.go @@ -39,6 +39,12 @@ func TestParseFromOutput(t *testing.T) { }, want: semver.MustParse("1.26.0"), }, + { + args: args{ + s: "Kubernetes v0.0.0-master+$Format:%H$", + }, + want: semver.MustParse("255.0.0"), + }, { args: args{ s: "prometheus, version 2.35.0 (branch: HEAD)", diff --git a/test/kwokctl/helper.sh b/test/kwokctl/helper.sh index cd511e8ae7..09a3a3271e 100644 --- a/test/kwokctl/helper.sh +++ b/test/kwokctl/helper.sh @@ -31,6 +31,12 @@ LOCAL_PATH="${ROOT_DIR}/bin/${GOOS}/${GOARCH}" export KWOK_CONTROLLER_BINARY="${LOCAL_PATH}/kwok" export KWOKCTL_CONTROLLER_BINARY="${LOCAL_PATH}/kwokctl" + +if [[ "${GOOS}" == "windows" ]]; then + KWOK_CONTROLLER_BINARY="${KWOK_CONTROLLER_BINARY}.exe" + KWOKCTL_CONTROLLER_BINARY="${KWOKCTL_CONTROLLER_BINARY}.exe" +fi + export KWOK_CONTROLLER_IMAGE="localhost/kwok:${VERSION}" export PATH="${LOCAL_PATH}:${PATH}"