diff --git a/.golangci.yaml b/.golangci.yaml index 12a876f34..9af9432e5 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -27,7 +27,6 @@ linters: - nolintlint - prealloc - revive - # - rowserrcheck - staticcheck - stylecheck - typecheck @@ -75,6 +74,9 @@ linters-settings: - k8s.io/klog: "please use `sigs.k8s.io/kwok/pkg/log instead" - golang.org/x/exp/slog: "please use `sigs.k8s.io/kwok/pkg/log` instead" - log: "please use `sigs.k8s.io/kwok/pkg/log` instead" + # Use sigs.k8s.io/kwok/pkg/utils/yaml, which is a wrapper around yaml + - k8s.io/apimachinery/pkg/util/yaml: "please use `sigs.k8s.io/kwok/pkg/utils/yaml` instead" + - sigs.k8s.io/yaml: "please use `sigs.k8s.io/kwok/pkg/utils/yaml` instead" # Use sigs.k8s.io/kwok/pkg/utils/wait, which is a wrapper around wait - k8s.io/apimachinery/pkg/util/wait: "please use `sigs.k8s.io/kwok/pkg/utils/wait` instead" # Use sigs.k8s.io/kwok/pkg/utils/slices, which is a wrapper around slices @@ -106,8 +108,10 @@ issues: - revive source: _ "embed" run: + concurrency: 1 timeout: 10m - allow-parallel-runners: true + allow-parallel-runners: false skip-dirs-use-default: true skip-files: - ".*\\.zz_generated\\..*" + go: '1.20' diff --git a/go.mod b/go.mod index 6df1a7722..195eca7e0 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,7 @@ module sigs.k8s.io/kwok go 1.20 require ( - github.com/ahmetb/gen-crd-api-reference-docs v0.3.0 github.com/blang/semver/v4 v4.0.0 - github.com/client9/misspell v0.3.4 github.com/compose-spec/compose-go v1.8.2 // fixation github.com/containerd/go-cni v1.1.9 github.com/containernetworking/plugins v1.3.0 @@ -28,7 +26,6 @@ require ( golang.org/x/sync v0.3.0 golang.org/x/sys v0.11.0 golang.org/x/term v0.11.0 - gopkg.in/yaml.v3 v3.0.1 k8s.io/api v0.28.0 k8s.io/apimachinery v0.28.0 k8s.io/apiserver v0.28.0 @@ -37,7 +34,6 @@ require ( k8s.io/cri-api v0.28.0 k8s.io/kubelet v0.28.0 k8s.io/utils v0.0.0-20230726121419-3b25d923346b - mvdan.cc/sh/v3 v3.7.0 sigs.k8s.io/controller-runtime v0.15.1 sigs.k8s.io/controller-tools v0.12.1 sigs.k8s.io/kustomize/kustomize/v5 v5.1.1 @@ -66,7 +62,6 @@ require ( github.com/golang/protobuf v1.5.3 // indirect github.com/google/gnostic-models v0.6.8 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/renameio/v2 v2.0.0 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.3.0 // indirect github.com/imdario/mergo v0.3.16 // indirect @@ -85,10 +80,10 @@ require ( github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e // indirect github.com/pkg/errors v0.9.1 // indirect github.com/prometheus/common v0.44.0 // indirect github.com/prometheus/procfs v0.10.1 // indirect + github.com/rogpeppe/go-internal v1.10.1-0.20230524175051-ec119421bb97 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/stoewer/go-strcase v1.3.0 // indirect github.com/wzshiming/trie v0.1.1 // indirect @@ -109,12 +104,11 @@ require ( gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apiextensions-apiserver v0.27.3 // indirect k8s.io/gengo v0.0.0-20220902162205-c0856e24416d // indirect - k8s.io/klog v0.2.0 // indirect k8s.io/klog/v2 v2.100.1 // indirect k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect - mvdan.cc/editorconfig v0.2.0 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/kustomize/api v0.14.0 // indirect sigs.k8s.io/kustomize/cmd/config v0.11.3 // indirect diff --git a/go.sum b/go.sum index 4afb7aefb..07869147d 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,3 @@ -github.com/ahmetb/gen-crd-api-reference-docs v0.3.0 h1:+XfOU14S4bGuwyvCijJwhhBIjYN+YXS18jrCY2EzJaY= -github.com/ahmetb/gen-crd-api-reference-docs v0.3.0/go.mod h1:TdjdkYhlOifCQWPs1UdTma97kQQMozf5h26hTuG70u8= github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230512164433-5d1fd1a340c9 h1:goHVqTbFX3AIo0tzGr14pgfAW2ZfPChKO21Z9MGf/gk= github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230512164433-5d1fd1a340c9/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= @@ -12,8 +10,6 @@ github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/compose-spec/compose-go v1.8.2 h1:sUQvDxnPgpcOyoxC/lz7mFTrTlHeZ6LWyuASYetkOqw= github.com/compose-spec/compose-go v1.8.2/go.mod h1:Tb5Ae2PsYN3GTqYqzl2IRbTPiJtPZZjMw8UKUvmehFk= github.com/containerd/go-cni v1.1.9 h1:ORi7P1dYzCwVM6XPN4n3CbkuOx/NZ2DOqy+SHRdo9rU= @@ -40,7 +36,6 @@ github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCv github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= -github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= @@ -93,8 +88,6 @@ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20230323073829-e72429f035bd h1:r8yyd+DJDmsUhGrRBxH5Pj7KeFK5l+Y3FsgT8keqKtk= -github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg= -github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= @@ -160,9 +153,6 @@ github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAl github.com/onsi/gomega v1.27.7 h1:fVih9JD6ogIiHUN6ePK7HJidyEDpWGVB5mzM7cWNXoU= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -176,11 +166,10 @@ github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= github.com/rogpeppe/go-internal v1.10.1-0.20230524175051-ec119421bb97 h1:3RPlVWzZ/PDqmVuf/FKHARG5EMid/tl7cv54Sw/QRVY= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/rogpeppe/go-internal v1.10.1-0.20230524175051-ec119421bb97/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -337,11 +326,8 @@ k8s.io/code-generator v0.28.0 h1:msdkRVJNVFgdiIJ8REl/d3cZsMB9HByFcWMmn13NyuE= k8s.io/code-generator v0.28.0/go.mod h1:ueeSJZJ61NHBa0ccWLey6mwawum25vX61nRZ6WOzN9A= k8s.io/cri-api v0.28.0 h1:TVidtHNi425IaKF50oDD5hRvQuK7wB4NQAfTVOcr9QA= k8s.io/cri-api v0.28.0/go.mod h1:xXygwvSOGcT/2KXg8sMYTHns2xFem3949kCQn5IS1k4= -k8s.io/gengo v0.0.0-20201203183100-97869a43a9d9/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/gengo v0.0.0-20220902162205-c0856e24416d h1:U9tB195lKdzwqicbJvyJeOXV7Klv+wNAWENRnXEGi08= k8s.io/gengo v0.0.0-20220902162205-c0856e24416d/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/klog v0.2.0 h1:0ElL0OHzF3N+OhoJTL0uca20SxtYt4X4+bzHeqrB83c= -k8s.io/klog v0.2.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= @@ -351,10 +337,6 @@ k8s.io/kubelet v0.28.0 h1:H/3JAkLIungVF+WLpqrxhgJ4gzwsbN8VA8LOTYsEX3U= k8s.io/kubelet v0.28.0/go.mod h1:i8jUg4ltbRusT3ExOhSAeqETuHdoHTZcTT2cPr9RTgc= k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -mvdan.cc/editorconfig v0.2.0 h1:XL+7ys6ls/RKrkUNFQvEwIvNHh+JKx8Mj1pUV5wQxQE= -mvdan.cc/editorconfig v0.2.0/go.mod h1:lvnnD3BNdBYkhq+B4uBuFFKatfp02eB6HixDvEz91C0= -mvdan.cc/sh/v3 v3.7.0 h1:lSTjdP/1xsddtaKfGg7Myu7DnlHItd3/M2tomOcNNBg= -mvdan.cc/sh/v3 v3.7.0/go.mod h1:K2gwkaesF/D7av7Kxl0HbF5kGOd2ArupNTX3X44+8l8= sigs.k8s.io/controller-runtime v0.15.1 h1:9UvgKD4ZJGcj24vefUFgZFP3xej/3igL9BsOUTb/+4c= sigs.k8s.io/controller-runtime v0.15.1/go.mod h1:7ngYvp1MLT+9GeZ+6lH3LOlcHkp/+tzA/fmHa4iq9kk= sigs.k8s.io/controller-tools v0.12.1 h1:GyQqxzH5wksa4n3YDIJdJJOopztR5VDM+7qsyg5yE4U= diff --git a/hack/tools/tools.go b/hack/tools/tools.go index 497535fb7..ed3c1733a 100644 --- a/hack/tools/tools.go +++ b/hack/tools/tools.go @@ -28,15 +28,6 @@ import ( // controller-gen _ "sigs.k8s.io/controller-tools/cmd/controller-gen" - // gen-crd-api-reference-docs - _ "github.com/ahmetb/gen-crd-api-reference-docs" - - // shfmt - _ "mvdan.cc/sh/v3/cmd/shfmt" - - // misspell - _ "github.com/client9/misspell/cmd/misspell" - // kustomize _ "sigs.k8s.io/kustomize/kustomize/v5" ) diff --git a/hack/update-all.sh b/hack/update-all.sh index b29c5aa49..1095ece54 100755 --- a/hack/update-all.sh +++ b/hack/update-all.sh @@ -43,6 +43,11 @@ if [[ "${UPDATE_GO_MOD:-true}" == "true" ]]; then "${ROOT_DIR}"/hack/update-go-mod.sh || failed+=(go-mod) fi +if [[ "${UPDATE_GO_LINT:-true}" == "true" ]]; then + echo "[*] Update go lint..." + "${ROOT_DIR}"/hack/update-go-lint.sh || failed+=(go-lint) +fi + if [[ "${UPDATE_ENDS_NEWLINE:-true}" == "true" ]]; then echo "[*] Update ends newline..." "${ROOT_DIR}"/hack/update-ends-newline.sh || failed+=(ends-newline) diff --git a/hack/update-api-docs.sh b/hack/update-api-docs.sh index 7ca3e0e0c..1f897fb77 100755 --- a/hack/update-api-docs.sh +++ b/hack/update-api-docs.sh @@ -24,7 +24,7 @@ ROOT_DIR="$(realpath "${DIR}/..")" function gendoc() { local confdir="${ROOT_DIR}/hack/api_docs" - go run github.com/ahmetb/gen-crd-api-reference-docs \ + go run github.com/ahmetb/gen-crd-api-reference-docs@v0.3.0 \ -template-dir "${confdir}" \ -config "${confdir}/config.json" \ "$@" diff --git a/hack/update-go-lint.sh b/hack/update-go-lint.sh new file mode 100755 index 000000000..874857e9a --- /dev/null +++ b/hack/update-go-lint.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# Copyright 2023 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +DIR="$(dirname "${BASH_SOURCE[0]}")" + +ROOT_DIR="$(realpath "${DIR}/..")" + +COMMAND=(go run github.com/golangci/golangci-lint/cmd/golangci-lint@v1.51.2) + +cd "${ROOT_DIR}" && "${COMMAND[@]}" run -c "${ROOT_DIR}/.golangci.yaml" --fix diff --git a/hack/update-shell-format.sh b/hack/update-shell-format.sh index 5f9d17f23..2e8069a74 100755 --- a/hack/update-shell-format.sh +++ b/hack/update-shell-format.sh @@ -31,7 +31,7 @@ function format() { -o -path ./demo/node_modules/\* \ -o -path ./site/themes/\* \ \)) - go run mvdan.cc/sh/v3/cmd/shfmt -w -i=2 "${findfiles[@]}" + go run mvdan.cc/sh/v3/cmd/shfmt@v3.7.0 -w -i=2 "${findfiles[@]}" } cd "${ROOT_DIR}" && format diff --git a/hack/update-spelling.sh b/hack/update-spelling.sh index 30441fe6c..b04dc3c58 100755 --- a/hack/update-spelling.sh +++ b/hack/update-spelling.sh @@ -40,7 +40,7 @@ function update() { -o -path ./demo/node_modules/\* \ -o -path ./site/themes/\* \ \)) - go run github.com/client9/misspell/cmd/misspell \ + go run github.com/client9/misspell/cmd/misspell@v0.3.4 \ -locale US -w -i "${ignore}" "${files[@]}" } diff --git a/hack/verify-all.sh b/hack/verify-all.sh index 5a00988f2..8918ddaf3 100755 --- a/hack/verify-all.sh +++ b/hack/verify-all.sh @@ -43,6 +43,11 @@ if [[ "${VERIFY_GO_FORMAT:-true}" == "true" ]]; then "${ROOT_DIR}"/hack/verify-go-format.sh || failed+=(go-format) fi +if [[ "${VERIFY_GO_LINT:-true}" == "true" ]]; then + echo "[*] Verifying go lint..." + "${ROOT_DIR}"/hack/verify-go-lint.sh || failed+=(go-lint) +fi + if [[ "${VERIFY_CODEGEN:-true}" == "true" ]]; then echo "[*] Verifying codegen..." "${ROOT_DIR}"/hack/verify-codegen.sh || failed+=(codegen) diff --git a/hack/verify-go-lint.sh b/hack/verify-go-lint.sh new file mode 100755 index 000000000..6c7ddeb39 --- /dev/null +++ b/hack/verify-go-lint.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# Copyright 2023 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +DIR="$(dirname "${BASH_SOURCE[0]}")" + +ROOT_DIR="$(realpath "${DIR}/..")" + +COMMAND=(go run github.com/golangci/golangci-lint/cmd/golangci-lint@v1.51.2) + +cd "${ROOT_DIR}" && "${COMMAND[@]}" run -c "${ROOT_DIR}/.golangci.yaml" diff --git a/kustomize/crd/bases/kwok.x-k8s.io_attaches.yaml b/kustomize/crd/bases/kwok.x-k8s.io_attaches.yaml index 6827282f1..2afad92d9 100644 --- a/kustomize/crd/bases/kwok.x-k8s.io_attaches.yaml +++ b/kustomize/crd/bases/kwok.x-k8s.io_attaches.yaml @@ -46,11 +46,7 @@ spec: type: array logsFile: description: LogsFile is the file from which the attach starts - minLength: 1 type: string - required: - - containers - - logsFile type: object type: array required: diff --git a/kustomize/crd/bases/kwok.x-k8s.io_clusterattaches.yaml b/kustomize/crd/bases/kwok.x-k8s.io_clusterattaches.yaml index 14ec3cb0d..5264222ea 100644 --- a/kustomize/crd/bases/kwok.x-k8s.io_clusterattaches.yaml +++ b/kustomize/crd/bases/kwok.x-k8s.io_clusterattaches.yaml @@ -46,11 +46,7 @@ spec: type: array logsFile: description: LogsFile is the file from which the attach starts - minLength: 1 type: string - required: - - containers - - logsFile type: object type: array selector: diff --git a/kustomize/crd/bases/kwok.x-k8s.io_clusterlogs.yaml b/kustomize/crd/bases/kwok.x-k8s.io_clusterlogs.yaml index 3546c06bc..9b54ea0c0 100644 --- a/kustomize/crd/bases/kwok.x-k8s.io_clusterlogs.yaml +++ b/kustomize/crd/bases/kwok.x-k8s.io_clusterlogs.yaml @@ -50,12 +50,7 @@ spec: logsFile: description: LogsFile is the file from which the log forward starts - minLength: 1 type: string - required: - - containers - - follow - - logsFile type: object type: array selector: diff --git a/kustomize/crd/bases/kwok.x-k8s.io_logs.yaml b/kustomize/crd/bases/kwok.x-k8s.io_logs.yaml index b9436f0a3..ddb269b11 100644 --- a/kustomize/crd/bases/kwok.x-k8s.io_logs.yaml +++ b/kustomize/crd/bases/kwok.x-k8s.io_logs.yaml @@ -50,12 +50,7 @@ spec: logsFile: description: LogsFile is the file from which the log forward starts - minLength: 1 type: string - required: - - containers - - follow - - logsFile type: object type: array required: diff --git a/pkg/apis/internalversion/zz_generated.conversion.go b/pkg/apis/internalversion/zz_generated.conversion.go index 50bede41b..fdf7af486 100644 --- a/pkg/apis/internalversion/zz_generated.conversion.go +++ b/pkg/apis/internalversion/zz_generated.conversion.go @@ -602,7 +602,9 @@ func Convert_v1alpha1_Attach_To_internalversion_Attach(in *v1alpha1.Attach, out func autoConvert_internalversion_AttachConfig_To_v1alpha1_AttachConfig(in *AttachConfig, out *v1alpha1.AttachConfig, s conversion.Scope) error { out.Containers = *(*[]string)(unsafe.Pointer(&in.Containers)) - out.LogsFile = in.LogsFile + if err := v1.Convert_string_To_Pointer_string(&in.LogsFile, &out.LogsFile, s); err != nil { + return err + } return nil } @@ -613,7 +615,9 @@ func Convert_internalversion_AttachConfig_To_v1alpha1_AttachConfig(in *AttachCon func autoConvert_v1alpha1_AttachConfig_To_internalversion_AttachConfig(in *v1alpha1.AttachConfig, out *AttachConfig, s conversion.Scope) error { out.Containers = *(*[]string)(unsafe.Pointer(&in.Containers)) - out.LogsFile = in.LogsFile + if err := v1.Convert_Pointer_string_To_string(&in.LogsFile, &out.LogsFile, s); err != nil { + return err + } return nil } @@ -623,7 +627,17 @@ func Convert_v1alpha1_AttachConfig_To_internalversion_AttachConfig(in *v1alpha1. } func autoConvert_internalversion_AttachSpec_To_v1alpha1_AttachSpec(in *AttachSpec, out *v1alpha1.AttachSpec, s conversion.Scope) error { - out.Attaches = *(*[]v1alpha1.AttachConfig)(unsafe.Pointer(&in.Attaches)) + if in.Attaches != nil { + in, out := &in.Attaches, &out.Attaches + *out = make([]v1alpha1.AttachConfig, len(*in)) + for i := range *in { + if err := Convert_internalversion_AttachConfig_To_v1alpha1_AttachConfig(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Attaches = nil + } return nil } @@ -633,7 +647,17 @@ func Convert_internalversion_AttachSpec_To_v1alpha1_AttachSpec(in *AttachSpec, o } func autoConvert_v1alpha1_AttachSpec_To_internalversion_AttachSpec(in *v1alpha1.AttachSpec, out *AttachSpec, s conversion.Scope) error { - out.Attaches = *(*[]AttachConfig)(unsafe.Pointer(&in.Attaches)) + if in.Attaches != nil { + in, out := &in.Attaches, &out.Attaches + *out = make([]AttachConfig, len(*in)) + for i := range *in { + if err := Convert_v1alpha1_AttachConfig_To_internalversion_AttachConfig(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Attaches = nil + } return nil } @@ -672,7 +696,17 @@ func Convert_v1alpha1_ClusterAttach_To_internalversion_ClusterAttach(in *v1alpha func autoConvert_internalversion_ClusterAttachSpec_To_v1alpha1_ClusterAttachSpec(in *ClusterAttachSpec, out *v1alpha1.ClusterAttachSpec, s conversion.Scope) error { out.Selector = (*v1alpha1.ObjectSelector)(unsafe.Pointer(in.Selector)) - out.Attaches = *(*[]v1alpha1.AttachConfig)(unsafe.Pointer(&in.Attaches)) + if in.Attaches != nil { + in, out := &in.Attaches, &out.Attaches + *out = make([]v1alpha1.AttachConfig, len(*in)) + for i := range *in { + if err := Convert_internalversion_AttachConfig_To_v1alpha1_AttachConfig(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Attaches = nil + } return nil } @@ -683,7 +717,17 @@ func Convert_internalversion_ClusterAttachSpec_To_v1alpha1_ClusterAttachSpec(in func autoConvert_v1alpha1_ClusterAttachSpec_To_internalversion_ClusterAttachSpec(in *v1alpha1.ClusterAttachSpec, out *ClusterAttachSpec, s conversion.Scope) error { out.Selector = (*ObjectSelector)(unsafe.Pointer(in.Selector)) - out.Attaches = *(*[]AttachConfig)(unsafe.Pointer(&in.Attaches)) + if in.Attaches != nil { + in, out := &in.Attaches, &out.Attaches + *out = make([]AttachConfig, len(*in)) + for i := range *in { + if err := Convert_v1alpha1_AttachConfig_To_internalversion_AttachConfig(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Attaches = nil + } return nil } @@ -772,7 +816,17 @@ func Convert_v1alpha1_ClusterLogs_To_internalversion_ClusterLogs(in *v1alpha1.Cl func autoConvert_internalversion_ClusterLogsSpec_To_v1alpha1_ClusterLogsSpec(in *ClusterLogsSpec, out *v1alpha1.ClusterLogsSpec, s conversion.Scope) error { out.Selector = (*v1alpha1.ObjectSelector)(unsafe.Pointer(in.Selector)) - out.Logs = *(*[]v1alpha1.Log)(unsafe.Pointer(&in.Logs)) + if in.Logs != nil { + in, out := &in.Logs, &out.Logs + *out = make([]v1alpha1.Log, len(*in)) + for i := range *in { + if err := Convert_internalversion_Log_To_v1alpha1_Log(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Logs = nil + } return nil } @@ -783,7 +837,17 @@ func Convert_internalversion_ClusterLogsSpec_To_v1alpha1_ClusterLogsSpec(in *Clu func autoConvert_v1alpha1_ClusterLogsSpec_To_internalversion_ClusterLogsSpec(in *v1alpha1.ClusterLogsSpec, out *ClusterLogsSpec, s conversion.Scope) error { out.Selector = (*ObjectSelector)(unsafe.Pointer(in.Selector)) - out.Logs = *(*[]Log)(unsafe.Pointer(&in.Logs)) + if in.Logs != nil { + in, out := &in.Logs, &out.Logs + *out = make([]Log, len(*in)) + for i := range *in { + if err := Convert_v1alpha1_Log_To_internalversion_Log(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Logs = nil + } return nil } @@ -1613,8 +1677,12 @@ func Convert_v1alpha1_KwokctlResource_To_internalversion_KwokctlResource(in *con func autoConvert_internalversion_Log_To_v1alpha1_Log(in *Log, out *v1alpha1.Log, s conversion.Scope) error { out.Containers = *(*[]string)(unsafe.Pointer(&in.Containers)) - out.LogsFile = in.LogsFile - out.Follow = in.Follow + if err := v1.Convert_string_To_Pointer_string(&in.LogsFile, &out.LogsFile, s); err != nil { + return err + } + if err := v1.Convert_bool_To_Pointer_bool(&in.Follow, &out.Follow, s); err != nil { + return err + } return nil } @@ -1625,8 +1693,12 @@ func Convert_internalversion_Log_To_v1alpha1_Log(in *Log, out *v1alpha1.Log, s c func autoConvert_v1alpha1_Log_To_internalversion_Log(in *v1alpha1.Log, out *Log, s conversion.Scope) error { out.Containers = *(*[]string)(unsafe.Pointer(&in.Containers)) - out.LogsFile = in.LogsFile - out.Follow = in.Follow + if err := v1.Convert_Pointer_string_To_string(&in.LogsFile, &out.LogsFile, s); err != nil { + return err + } + if err := v1.Convert_Pointer_bool_To_bool(&in.Follow, &out.Follow, s); err != nil { + return err + } return nil } @@ -1664,7 +1736,17 @@ func Convert_v1alpha1_Logs_To_internalversion_Logs(in *v1alpha1.Logs, out *Logs, } func autoConvert_internalversion_LogsSpec_To_v1alpha1_LogsSpec(in *LogsSpec, out *v1alpha1.LogsSpec, s conversion.Scope) error { - out.Logs = *(*[]v1alpha1.Log)(unsafe.Pointer(&in.Logs)) + if in.Logs != nil { + in, out := &in.Logs, &out.Logs + *out = make([]v1alpha1.Log, len(*in)) + for i := range *in { + if err := Convert_internalversion_Log_To_v1alpha1_Log(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Logs = nil + } return nil } @@ -1674,7 +1756,17 @@ func Convert_internalversion_LogsSpec_To_v1alpha1_LogsSpec(in *LogsSpec, out *v1 } func autoConvert_v1alpha1_LogsSpec_To_internalversion_LogsSpec(in *v1alpha1.LogsSpec, out *LogsSpec, s conversion.Scope) error { - out.Logs = *(*[]Log)(unsafe.Pointer(&in.Logs)) + if in.Logs != nil { + in, out := &in.Logs, &out.Logs + *out = make([]Log, len(*in)) + for i := range *in { + if err := Convert_v1alpha1_Log_To_internalversion_Log(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Logs = nil + } return nil } diff --git a/pkg/apis/v1alpha1/attach_types.go b/pkg/apis/v1alpha1/attach_types.go index 95d7a8cf3..8da79c2be 100644 --- a/pkg/apis/v1alpha1/attach_types.go +++ b/pkg/apis/v1alpha1/attach_types.go @@ -63,11 +63,9 @@ type AttachSpec struct { // AttachConfig holds information how to attach. type AttachConfig struct { // Containers is list of container names. - Containers []string `json:"containers"` + Containers []string `json:"containers,omitempty"` // LogsFile is the file from which the attach starts - // +kubebuilder:validation:Required - // +kubebuilder:validation:MinLength=1 - LogsFile string `json:"logsFile"` + LogsFile *string `json:"logsFile,omitempty"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/pkg/apis/v1alpha1/logs_types.go b/pkg/apis/v1alpha1/logs_types.go index f41811cb6..0d59717f1 100644 --- a/pkg/apis/v1alpha1/logs_types.go +++ b/pkg/apis/v1alpha1/logs_types.go @@ -63,13 +63,11 @@ type LogsSpec struct { // Log holds information how to forward logs. type Log struct { // Containers is list of container names. - Containers []string `json:"containers"` + Containers []string `json:"containers,omitempty"` // LogsFile is the file from which the log forward starts - // +kubebuilder:validation:Required - // +kubebuilder:validation:MinLength=1 - LogsFile string `json:"logsFile"` + LogsFile *string `json:"logsFile,omitempty"` // Follow up if true - Follow bool `json:"follow"` + Follow *bool `json:"follow,omitempty"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/pkg/apis/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/v1alpha1/zz_generated.deepcopy.go index 9fd80dc90..ded7eca0f 100644 --- a/pkg/apis/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/v1alpha1/zz_generated.deepcopy.go @@ -61,6 +61,11 @@ func (in *AttachConfig) DeepCopyInto(out *AttachConfig) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.LogsFile != nil { + in, out := &in.LogsFile, &out.LogsFile + *out = new(string) + **out = **in + } return } @@ -880,6 +885,16 @@ func (in *Log) DeepCopyInto(out *Log) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.LogsFile != nil { + in, out := &in.LogsFile, &out.LogsFile + *out = new(string) + **out = **in + } + if in.Follow != nil { + in, out := &in.Follow, &out.Follow + *out = new(bool) + **out = **in + } return } diff --git a/pkg/config/config.go b/pkg/config/config.go index 7f50023b1..835a177b8 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -28,8 +28,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" - utilyaml "k8s.io/apimachinery/pkg/util/yaml" - "sigs.k8s.io/yaml" configv1alpha1 "sigs.k8s.io/kwok/pkg/apis/config/v1alpha1" "sigs.k8s.io/kwok/pkg/apis/internalversion" @@ -40,6 +38,7 @@ import ( "sigs.k8s.io/kwok/pkg/utils/maps" "sigs.k8s.io/kwok/pkg/utils/patch" "sigs.k8s.io/kwok/pkg/utils/path" + "sigs.k8s.io/kwok/pkg/utils/yaml" ) var ( @@ -389,10 +388,25 @@ func SaveTo(ctx context.Context, w io.Writer, objs []InternalObject) error { return nil } +// UnmarshalWithType unmarshals the given raw message into the internal object. +func UnmarshalWithType[T InternalObject, D string | []byte](raw D) (t T, err error) { + obj, err := Unmarshal(raw) + if err != nil { + return t, err + } + t, ok := obj.(T) + if !ok { + return t, fmt.Errorf("unexpected type %T %s", obj, log.KObj(obj)) + } + return t, nil +} + // Unmarshal unmarshals the given raw message into the internal object. -func Unmarshal(raw []byte) (InternalObject, error) { +func Unmarshal[D string | []byte](d D) (InternalObject, error) { meta := metav1.TypeMeta{} + raw := []byte(d) + raw, err := yaml.YAMLToJSON(raw) if err != nil { return nil, err @@ -516,7 +530,7 @@ func loadRawFromFile(p string) ([]json.RawMessage, error) { func loadRaw(r io.Reader) ([]json.RawMessage, error) { var raws []json.RawMessage - decoder := utilyaml.NewYAMLToJSONDecoder(r) + decoder := yaml.NewDecoder(r) for { var raw json.RawMessage err := decoder.Decode(&raw) diff --git a/pkg/consts/consts.go b/pkg/consts/consts.go index 4964924c0..88586fef6 100644 --- a/pkg/consts/consts.go +++ b/pkg/consts/consts.go @@ -45,8 +45,9 @@ var ( DockerComposeVersion = "2.17.2" DockerComposeBinaryPrefix = "https://github.com/docker/compose/releases/download" - KindVersion = "0.19.0" - KindBinaryPrefix = "https://github.com/kubernetes-sigs/kind/releases/download" + KindVersion = "0.19.0" + KindBinaryPrefix = "https://github.com/kubernetes-sigs/kind/releases/download" + KindNodeImagePrefix = "docker.io/kindest" DashboardVersion = "2.7.0" DashboardBinaryPrefix = "" @@ -60,8 +61,6 @@ var ( JaegerBinaryPrefix = "https://github.com/jaegertracing/jaeger/releases/download" JaegerImagePrefix = "docker.io/jaegertracing" - KindNodeImagePrefix = "docker.io/kindest" - DefaultUnlimitedQPS = 5000.0 DefaultUnlimitedBurst = 10000 ) diff --git a/pkg/kwok/cmd/root.go b/pkg/kwok/cmd/root.go index 1539daf91..9877650f8 100644 --- a/pkg/kwok/cmd/root.go +++ b/pkg/kwok/cmd/root.go @@ -286,13 +286,18 @@ func runE(ctx context.Context, flags *flagpole) error { return err } + err = ctr.Start(ctx) + if err != nil { + return err + } + serverAddress := flags.Options.ServerAddress if serverAddress == "" && flags.Options.NodePort != 0 { serverAddress = "0.0.0.0:" + format.String(flags.Options.NodePort) } if serverAddress != "" { - config := server.Config{ + conf := server.Config{ TypedKwokClient: typedKwokClient, EnableCRDs: flags.Options.EnableCRDs, ClusterPortForwards: clusterPortForwards, @@ -304,9 +309,11 @@ func runE(ctx context.Context, flags *flagpole) error { ClusterAttaches: clusterAttaches, Attaches: attaches, Metrics: metrics, - Controller: ctr, + DataSource: ctr, + NodeCacheGetter: ctr.GetNodeCache(), + PodCacheGetter: ctr.GetPodCache(), } - svc, err := server.NewServer(config) + svc, err := server.NewServer(conf) if err != nil { return fmt.Errorf("failed to create server: %w", err) } @@ -347,11 +354,6 @@ func runE(ctx context.Context, flags *flagpole) error { }() } - err = ctr.Start(ctx) - if err != nil { - return err - } - <-ctx.Done() return nil } @@ -401,14 +403,10 @@ func waitForReady(ctx context.Context, clientset kubernetes.Interface) error { func getDefaultNodeStages(lease bool) ([]*internalversion.Stage, error) { nodeStages := []*internalversion.Stage{} - nodeInit, err := config.Unmarshal([]byte(nodefast.DefaultNodeInit)) + nodeInitStage, err := config.UnmarshalWithType[*internalversion.Stage](nodefast.DefaultNodeInit) if err != nil { return nil, err } - nodeInitStage, ok := nodeInit.(*internalversion.Stage) - if !ok { - return nil, fmt.Errorf("failed to convert node init to stage") - } nodeStages = append(nodeStages, nodeInitStage) rawHeartbeat := nodeheartbeat.DefaultNodeHeartbeat @@ -416,14 +414,10 @@ func getDefaultNodeStages(lease bool) ([]*internalversion.Stage, error) { rawHeartbeat = nodeheartbeatwithlease.DefaultNodeHeartbeatWithLease } - nodeHeartbeat, err := config.Unmarshal([]byte(rawHeartbeat)) + nodeHeartbeatStage, err := config.UnmarshalWithType[*internalversion.Stage](rawHeartbeat) if err != nil { return nil, err } - nodeHeartbeatStage, ok := nodeHeartbeat.(*internalversion.Stage) - if !ok { - return nil, fmt.Errorf("failed to convert node init to stage") - } nodeStages = append(nodeStages, nodeHeartbeatStage) return nodeStages, nil } @@ -433,16 +427,5 @@ func getDefaultPodStages() ([]*internalversion.Stage, error) { podfast.DefaultPodReady, podfast.DefaultPodComplete, podfast.DefaultPodDelete, - }, func(s string) (*internalversion.Stage, error) { - iobj, err := config.Unmarshal([]byte(s)) - if err != nil { - return nil, err - } - stage, ok := iobj.(*internalversion.Stage) - if !ok { - return nil, fmt.Errorf("failed to convert pod init to stage") - } - - return stage, nil - }) + }, config.UnmarshalWithType[*internalversion.Stage, string]) } diff --git a/pkg/kwok/controllers/controller.go b/pkg/kwok/controllers/controller.go index 966273bfb..2d544738a 100644 --- a/pkg/kwok/controllers/controller.go +++ b/pkg/kwok/controllers/controller.go @@ -35,7 +35,6 @@ import ( clientcorev1 "k8s.io/client-go/kubernetes/typed/core/v1" "k8s.io/client-go/tools/record" "k8s.io/utils/clock" - "sigs.k8s.io/yaml" "sigs.k8s.io/kwok/pkg/apis/internalversion" "sigs.k8s.io/kwok/pkg/apis/v1alpha1" @@ -47,6 +46,7 @@ import ( "sigs.k8s.io/kwok/pkg/utils/informer" "sigs.k8s.io/kwok/pkg/utils/queue" "sigs.k8s.io/kwok/pkg/utils/slices" + "sigs.k8s.io/kwok/pkg/utils/yaml" ) var ( @@ -483,11 +483,6 @@ func (c *Controller) Start(ctx context.Context) error { return nil } -// GetNodeInfo returns the node info for the given node -func (c *Controller) GetNodeInfo(nodeName string) (*NodeInfo, bool) { - return c.nodes.Get(nodeName) -} - // ListNodes returns all nodes func (c *Controller) ListNodes() []string { return c.nodes.List() @@ -508,6 +503,15 @@ func (c *Controller) GetNodeCache() informer.Getter[*corev1.Node] { return c.nodeCacheGetter } +// StartedContainersTotal returns the total number of containers started +func (c *Controller) StartedContainersTotal(nodeName string) int64 { + nodeInfo, ok := c.nodes.Get(nodeName) + if !ok { + return 0 + } + return nodeInfo.StartedContainer.Load() +} + // Identity returns a unique identifier for this controller func Identity() (string, error) { hostname, err := os.Hostname() diff --git a/pkg/kwok/controllers/controller_test.go b/pkg/kwok/controllers/controller_test.go index 441dc3121..627388a6c 100644 --- a/pkg/kwok/controllers/controller_test.go +++ b/pkg/kwok/controllers/controller_test.go @@ -71,18 +71,18 @@ func TestController(t *testing.T) { }, } - nodeInit, _ := config.Unmarshal([]byte(nodefast.DefaultNodeInit)) - nodeStages := []*internalversion.Stage{nodeInit.(*internalversion.Stage)} + nodeInit, _ := config.UnmarshalWithType[*internalversion.Stage](nodefast.DefaultNodeInit) + nodeStages := []*internalversion.Stage{nodeInit} podStages, _ := slices.MapWithError([]string{ podfast.DefaultPodReady, podfast.DefaultPodComplete, podfast.DefaultPodDelete, }, func(s string) (*internalversion.Stage, error) { - iobj, err := config.Unmarshal([]byte(s)) + stage, err := config.UnmarshalWithType[*internalversion.Stage](s) if err != nil { return nil, err } - return iobj.(*internalversion.Stage), nil + return stage, nil }) tests := []struct { diff --git a/pkg/kwok/controllers/node_controller.go b/pkg/kwok/controllers/node_controller.go index 1bffde665..7ac9b2f55 100644 --- a/pkg/kwok/controllers/node_controller.go +++ b/pkg/kwok/controllers/node_controller.go @@ -167,17 +167,15 @@ func NewNodeController(conf NodeControllerConfig) (*NodeController, error) { readOnlyFunc: conf.ReadOnlyFunc, enableMetrics: conf.EnableMetrics, } - funcMap := gotpl.FuncMap{ + + funcMap := maps.Merge(gotpl.FuncMap{ "NodeIP": c.funcNodeIP, "NodeName": c.funcNodeName, "NodePort": c.funcNodePort, "NodeConditions": func() interface{} { return nodeConditionsData }, - } - for k, v := range conf.FuncMap { - funcMap[k] = v - } + }, conf.FuncMap) c.renderer = gotpl.NewRenderer(funcMap) return c, nil } diff --git a/pkg/kwok/controllers/node_controller_test.go b/pkg/kwok/controllers/node_controller_test.go index a0688fe11..a35e298b5 100644 --- a/pkg/kwok/controllers/node_controller_test.go +++ b/pkg/kwok/controllers/node_controller_test.go @@ -75,8 +75,8 @@ func TestNodeController(t *testing.T) { return node.Annotations["node"] == "true" } - nodeInit, _ := config.Unmarshal([]byte(nodefast.DefaultNodeInit)) - nodeStages := []*internalversion.Stage{nodeInit.(*internalversion.Stage)} + nodeInit, _ := config.UnmarshalWithType[*internalversion.Stage](nodefast.DefaultNodeInit) + nodeStages := []*internalversion.Stage{nodeInit} lifecycle, _ := NewLifecycle(nodeStages) nodes, err := NewNodeController(NodeControllerConfig{ diff --git a/pkg/kwok/controllers/pod_controller.go b/pkg/kwok/controllers/pod_controller.go index 4230e315b..7855e7706 100644 --- a/pkg/kwok/controllers/pod_controller.go +++ b/pkg/kwok/controllers/pod_controller.go @@ -134,15 +134,12 @@ func NewPodController(conf PodControllerConfig) (*PodController, error) { readOnlyFunc: conf.ReadOnlyFunc, enableMetrics: conf.EnableMetrics, } - funcMap := gotpl.FuncMap{ + funcMap := maps.Merge(gotpl.FuncMap{ "NodeIP": c.funcNodeIP, "PodIP": c.funcPodIP, "NodeIPWith": c.funcNodeIPWith, "PodIPWith": c.funcPodIPWith, - } - for k, v := range conf.FuncMap { - funcMap[k] = v - } + }, conf.FuncMap) c.renderer = gotpl.NewRenderer(funcMap) return c, nil } diff --git a/pkg/kwok/controllers/pod_controller_test.go b/pkg/kwok/controllers/pod_controller_test.go index 953d2830a..2af473034 100644 --- a/pkg/kwok/controllers/pod_controller_test.go +++ b/pkg/kwok/controllers/pod_controller_test.go @@ -172,13 +172,7 @@ func TestPodController(t *testing.T) { podfast.DefaultPodReady, podfast.DefaultPodComplete, podfast.DefaultPodDelete, - }, func(s string) (*internalversion.Stage, error) { - iobj, err := config.Unmarshal([]byte(s)) - if err != nil { - return nil, err - } - return iobj.(*internalversion.Stage), nil - }) + }, config.UnmarshalWithType[*internalversion.Stage, string]) ctx := context.Background() ctx = log.NewContext(ctx, log.NewLogger(os.Stderr, log.LevelDebug)) diff --git a/pkg/kwok/metrics/metrics.go b/pkg/kwok/metrics/metrics.go index d5f56529f..88cb1390a 100644 --- a/pkg/kwok/metrics/metrics.go +++ b/pkg/kwok/metrics/metrics.go @@ -28,7 +28,6 @@ import ( corev1 "k8s.io/api/core/v1" "sigs.k8s.io/kwok/pkg/apis/internalversion" - "sigs.k8s.io/kwok/pkg/kwok/controllers" "sigs.k8s.io/kwok/pkg/kwok/metrics/cel" "sigs.k8s.io/kwok/pkg/log" "sigs.k8s.io/kwok/pkg/utils/informer" @@ -37,7 +36,7 @@ import ( // UpdateHandler handles updating metrics on request type UpdateHandler struct { - controller *controllers.Controller + dataSource DataSource environment *cel.Environment nodeCacheGetter informer.Getter[*corev1.Node] podCacheGetter informer.Getter[*corev1.Pod] @@ -50,10 +49,17 @@ type UpdateHandler struct { histograms maps.SyncMap[string, Histogram] } +// DataSource is the interface for getting data for metrics +type DataSource interface { + ListPods(nodeName string) ([]log.ObjectRef, bool) +} + // UpdateHandlerConfig is configuration for a single node type UpdateHandlerConfig struct { - Controller *controllers.Controller - Environment *cel.Environment + DataSource DataSource + Environment *cel.Environment + NodeCacheGetter informer.Getter[*corev1.Node] + PodCacheGetter informer.Getter[*corev1.Pod] } // NewMetricsUpdateHandler creates new metric update handler based on the config @@ -64,21 +70,16 @@ func NewMetricsUpdateHandler(conf UpdateHandlerConfig) *UpdateHandler { ) h := &UpdateHandler{ - controller: conf.Controller, + dataSource: conf.DataSource, environment: conf.Environment, - nodeCacheGetter: conf.Controller.GetNodeCache(), - podCacheGetter: conf.Controller.GetPodCache(), + nodeCacheGetter: conf.NodeCacheGetter, + podCacheGetter: conf.PodCacheGetter, registry: registry, handler: handler, } return h } -func (h *UpdateHandler) getPodsInfo(nodeName string) ([]log.ObjectRef, bool) { - podsInfo, ok := h.controller.ListPods(nodeName) - return podsInfo, ok -} - func (h *UpdateHandler) getOrRegisterGauge(metricConfig *internalversion.MetricConfig, data cel.Data) (Gauge, string, error) { key, labels, err := h.createKeyAndLabels(metricConfig, data) if err != nil { @@ -196,7 +197,7 @@ func (h *UpdateHandler) updateGauge(ctx context.Context, metricConfig *internalv gauge.Set(result) return []string{key}, nil case internalversion.DimensionPod: - pods, ok := h.getPodsInfo(nodeName) + pods, ok := h.dataSource.ListPods(nodeName) if !ok { logger.Warn("pods not found") return nil, nil @@ -224,7 +225,7 @@ func (h *UpdateHandler) updateGauge(ctx context.Context, metricConfig *internalv } return keys, nil case internalversion.DimensionContainer: - pods, ok := h.getPodsInfo(nodeName) + pods, ok := h.dataSource.ListPods(nodeName) if !ok { logger.Warn("pods not found") return nil, nil @@ -290,7 +291,7 @@ func (h *UpdateHandler) updateCounter(ctx context.Context, metricConfig *interna counter.Set(result) return []string{key}, nil case internalversion.DimensionPod: - pods, ok := h.getPodsInfo(nodeName) + pods, ok := h.dataSource.ListPods(nodeName) if !ok { logger.Warn("pods not found") return nil, nil @@ -318,7 +319,7 @@ func (h *UpdateHandler) updateCounter(ctx context.Context, metricConfig *interna } return keys, nil case internalversion.DimensionContainer: - pods, ok := h.getPodsInfo(nodeName) + pods, ok := h.dataSource.ListPods(nodeName) if !ok { logger.Warn("pods not found") return nil, nil @@ -385,7 +386,7 @@ func (h *UpdateHandler) updateHistogram(ctx context.Context, metricConfig *inter } return []string{key}, nil case internalversion.DimensionPod: - pods, ok := h.getPodsInfo(nodeName) + pods, ok := h.dataSource.ListPods(nodeName) if !ok { logger.Warn("pods not found") return nil, nil @@ -419,7 +420,7 @@ func (h *UpdateHandler) updateHistogram(ctx context.Context, metricConfig *inter } return keys, nil case internalversion.DimensionContainer: - pods, ok := h.getPodsInfo(nodeName) + pods, ok := h.dataSource.ListPods(nodeName) if !ok { logger.Warn("pods not found") return nil, nil diff --git a/pkg/kwok/server/metrics.go b/pkg/kwok/server/metrics.go index 9c2ade345..ad977c9ac 100644 --- a/pkg/kwok/server/metrics.go +++ b/pkg/kwok/server/metrics.go @@ -39,17 +39,10 @@ func (s *Server) InstallMetrics(ctx context.Context) error { promHandler.ServeHTTP(resp.ResponseWriter, req.Request) } - controller := s.controller env, err := cel.NewEnvironment(cel.NodeEvaluatorConfig{ - EnableEvaluatorCache: true, - EnableResultCache: true, - StartedContainersTotal: func(nodeName string) int64 { - nodeInfo, ok := controller.GetNodeInfo(nodeName) - if !ok { - return 0 - } - return nodeInfo.StartedContainer.Load() - }, + EnableEvaluatorCache: true, + EnableResultCache: true, + StartedContainersTotal: s.dataSource.StartedContainersTotal, }) if err != nil { return fmt.Errorf("failed to create CEL environment: %w", err) @@ -115,8 +108,10 @@ func (s *Server) getMetrics(metric *internalversion.Metric, env *cel.Environment handler, ok := s.metricsUpdateHandler.Load(nodeName) if !ok { handler = metrics.NewMetricsUpdateHandler(metrics.UpdateHandlerConfig{ - Controller: s.controller, - Environment: env, + Environment: env, + DataSource: s.dataSource, + NodeCacheGetter: s.nodeCacheGetter, + PodCacheGetter: s.podCacheGetter, }) s.metricsUpdateHandler.Store(nodeName, handler) } diff --git a/pkg/kwok/server/server.go b/pkg/kwok/server/server.go index d087c51d7..8b2bf1013 100644 --- a/pkg/kwok/server/server.go +++ b/pkg/kwok/server/server.go @@ -26,15 +26,16 @@ import ( "github.com/emicklei/go-restful/v3" "github.com/wzshiming/cmux" "github.com/wzshiming/cmux/pattern" + corev1 "k8s.io/api/core/v1" remotecommandconsts "k8s.io/apimachinery/pkg/util/remotecommand" "sigs.k8s.io/kwok/pkg/apis/internalversion" "sigs.k8s.io/kwok/pkg/apis/v1alpha1" "sigs.k8s.io/kwok/pkg/client/clientset/versioned" "sigs.k8s.io/kwok/pkg/config/resources" - "sigs.k8s.io/kwok/pkg/kwok/controllers" "sigs.k8s.io/kwok/pkg/kwok/metrics" "sigs.k8s.io/kwok/pkg/log" + "sigs.k8s.io/kwok/pkg/utils/informer" "sigs.k8s.io/kwok/pkg/utils/maps" "sigs.k8s.io/kwok/pkg/utils/pools" "sigs.k8s.io/kwok/pkg/utils/slices" @@ -69,7 +70,16 @@ type Server struct { metricsWebService *restful.WebService metricsUpdateHandler maps.SyncMap[string, *metrics.UpdateHandler] - controller *controllers.Controller + dataSource DataSource + nodeCacheGetter informer.Getter[*corev1.Node] + podCacheGetter informer.Getter[*corev1.Pod] +} + +// DataSource is the interface that provides data for the server handlers. +type DataSource interface { + metrics.DataSource + ListNodes() []string + StartedContainersTotal(nodeName string) int64 } // Config holds configurations needed by the server handlers. @@ -86,31 +96,36 @@ type Config struct { ClusterAttaches []*internalversion.ClusterAttach Attaches []*internalversion.Attach Metrics []*internalversion.Metric - Controller *controllers.Controller + + DataSource DataSource + NodeCacheGetter informer.Getter[*corev1.Node] + PodCacheGetter informer.Getter[*corev1.Pod] } // NewServer creates a new Server. -func NewServer(config Config) (*Server, error) { +func NewServer(conf Config) (*Server, error) { container := restful.NewContainer() s := &Server{ - typedKwokClient: config.TypedKwokClient, - enableCRDs: config.EnableCRDs, + typedKwokClient: conf.TypedKwokClient, + enableCRDs: conf.EnableCRDs, restfulCont: container, idleTimeout: 1 * time.Hour, streamCreationTimeout: remotecommandconsts.DefaultStreamCreationTimeout, - clusterPortForwards: resources.NewStaticGetter(config.ClusterPortForwards), - portForwards: resources.NewStaticGetter(config.PortForwards), - clusterExecs: resources.NewStaticGetter(config.ClusterExecs), - execs: resources.NewStaticGetter(config.Execs), - clusterLogs: resources.NewStaticGetter(config.ClusterLogs), - logs: resources.NewStaticGetter(config.Logs), - clusterAttaches: resources.NewStaticGetter(config.ClusterAttaches), - attaches: resources.NewStaticGetter(config.Attaches), - metrics: resources.NewStaticGetter(config.Metrics), - - controller: config.Controller, + clusterPortForwards: resources.NewStaticGetter(conf.ClusterPortForwards), + portForwards: resources.NewStaticGetter(conf.PortForwards), + clusterExecs: resources.NewStaticGetter(conf.ClusterExecs), + execs: resources.NewStaticGetter(conf.Execs), + clusterLogs: resources.NewStaticGetter(conf.ClusterLogs), + logs: resources.NewStaticGetter(conf.Logs), + clusterAttaches: resources.NewStaticGetter(conf.ClusterAttaches), + attaches: resources.NewStaticGetter(conf.Attaches), + metrics: resources.NewStaticGetter(conf.Metrics), + + dataSource: conf.DataSource, + podCacheGetter: conf.PodCacheGetter, + nodeCacheGetter: conf.NodeCacheGetter, bufPool: pools.NewPool(func() []byte { return make([]byte, 32*1024) diff --git a/pkg/kwok/server/service_discovery.go b/pkg/kwok/server/service_discovery.go index a76d647bf..c15e910d2 100644 --- a/pkg/kwok/server/service_discovery.go +++ b/pkg/kwok/server/service_discovery.go @@ -43,7 +43,7 @@ func (s *Server) prometheusDiscovery(rw http.ResponseWriter, req *http.Request) for _, m := range metrics { if strings.Contains(m.Spec.Path, "{nodeName}") { if listNode == nil { - listNode = s.controller.ListNodes() + listNode = s.dataSource.ListNodes() } for _, nodeName := range listNode { targets = append(targets, prometheusStaticConfig{ diff --git a/pkg/kwokctl/cmd/logs/logs.go b/pkg/kwokctl/cmd/logs/logs.go index 06129b360..5d7797d24 100644 --- a/pkg/kwokctl/cmd/logs/logs.go +++ b/pkg/kwokctl/cmd/logs/logs.go @@ -41,7 +41,7 @@ func NewCommand(ctx context.Context) *cobra.Command { cmd := &cobra.Command{ Use: "logs [command]", - Short: "Logs one of [audit, etcd, kube-apiserver, kube-controller-manager, kube-scheduler, kwok-controller, prometheus]", + Short: "Logs one of [audit, etcd, kube-apiserver, kube-controller-manager, kube-scheduler, kwok-controller, dashboard, prometheus, jaeger]", RunE: func(cmd *cobra.Command, args []string) error { if len(args) == 0 { return cmd.Help() diff --git a/pkg/kwokctl/cmd/scale/scale.go b/pkg/kwokctl/cmd/scale/scale.go index 61f85c6a4..222334ce7 100644 --- a/pkg/kwokctl/cmd/scale/scale.go +++ b/pkg/kwokctl/cmd/scale/scale.go @@ -98,25 +98,21 @@ func runE(ctx context.Context, flags *flagpole, args []string) error { return krc.Name == resourceKind }) if !ok { - var resourceData []byte + var resourceData string switch resourceKind { default: return fmt.Errorf("resource %s is not exists", resourceKind) case "pod": - resourceData = []byte(resource.DefaultPod) + resourceData = resource.DefaultPod case "node": - resourceData = []byte(resource.DefaultNode) + resourceData = resource.DefaultNode } logger.Info("No resource found, use default resource", "resource", resourceKind) - iobj, err := config.Unmarshal(resourceData) + krc, err = config.UnmarshalWithType[*internalversion.KwokctlResource](resourceData) if err != nil { return err } - krc, ok = iobj.(*internalversion.KwokctlResource) - if !ok { - return fmt.Errorf("resource %T is not a kwokctl resource", iobj) - } } parameters, err := scale.NewParameters(ctx, krc.Parameters, flags.Params) diff --git a/pkg/kwokctl/runtime/cluster.go b/pkg/kwokctl/runtime/cluster.go index de62e108a..f8e908b4c 100644 --- a/pkg/kwokctl/runtime/cluster.go +++ b/pkg/kwokctl/runtime/cluster.go @@ -100,11 +100,10 @@ func (c *Cluster) Config(ctx context.Context) (*internalversion.KwokctlConfigura } c.conf = conf logger := log.FromContext(ctx) + logger = logger.With("kwokctlVersion", consts.Version) if conf.Status.Version == "" { - logger.Warn("The cluster was created by an older version of kwokctl, "+ + logger.Warn("The cluster was created by a older version of kwokctl, " + "please recreate the cluster", - "createdByVersion", "<0.3.0", - "kwokctlVersion", consts.Version, ) conf.Status.Version = "0.0.0" } else if conf.Status.Version != consts.Version { @@ -121,13 +120,11 @@ func (c *Cluster) Config(ctx context.Context) (*internalversion.KwokctlConfigura logger.Warn("The cluster was created by a older version of kwokctl, "+ "please recreate the cluster", "createdByVersion", conf.Status.Version, - "kwokctlVersion", consts.Version, ) case currentVer.GT(ver): logger.Warn("The cluster was created by a newer version of kwokctl, "+ "please upgrade kwokctl or recreate the cluster", "createdByVersion", conf.Status.Version, - "kwokctlVersion", consts.Version, ) } } @@ -182,8 +179,7 @@ func (c *Cluster) Save(ctx context.Context) error { } if conf.Status.Version == "" { - c.conf = c.conf.DeepCopy() - c.conf.Status.Version = consts.Version + conf.Status.Version = consts.Version } others := config.FilterWithoutTypeFromContext[*internalversion.KwokctlConfiguration](ctx) @@ -207,29 +203,22 @@ func (c *Cluster) Save(ctx context.Context) error { func (c *Cluster) getDefaultStages(updateFrequency int64, lease bool) ([]config.InternalObject, error) { objs := []config.InternalObject{} - nodeInit, err := config.Unmarshal([]byte(nodefast.DefaultNodeInit)) + nodeInitStage, err := config.UnmarshalWithType[*internalversion.Stage](nodefast.DefaultNodeInit) if err != nil { return nil, err } - if _, ok := nodeInit.(*internalversion.Stage); !ok { - return nil, fmt.Errorf("failed to get node init stage %T", nodeInit) - } - objs = append(objs, nodeInit) + objs = append(objs, nodeInitStage) rawHeartbeat := nodeheartbeat.DefaultNodeHeartbeat if lease { rawHeartbeat = nodeheartbeatwithlease.DefaultNodeHeartbeatWithLease } - nodeHeartbeat, err := config.Unmarshal([]byte(rawHeartbeat)) + nodeHeartbeatStage, err := config.UnmarshalWithType[*internalversion.Stage](rawHeartbeat) if err != nil { return nil, err } - nodeHeartbeatStage, ok := nodeHeartbeat.(*internalversion.Stage) - if !ok { - return nil, fmt.Errorf("failed to get node nodeheartbeat stage %T", nodeHeartbeat) - } if updateFrequency > 0 { durationMilliseconds := format.ElemOrDefault(nodeHeartbeatStage.Spec.Delay.DurationMilliseconds) jitterDurationMilliseconds := format.ElemOrDefault(nodeHeartbeatStage.Spec.Delay.JitterDurationMilliseconds) @@ -286,7 +275,8 @@ func (c *Cluster) Ready(ctx context.Context) (bool, error) { if !bytes.Equal(out.Bytes(), []byte("ok")) { logger := log.FromContext(ctx) logger.Debug("Check Ready", - "method", "get /healthz", + "method", "get", + "path", "/healthz", "response", out, ) return false, nil diff --git a/pkg/kwokctl/runtime/compose/cluster.go b/pkg/kwokctl/runtime/compose/cluster.go index 0b21c2bd7..df56a4e13 100644 --- a/pkg/kwokctl/runtime/compose/cluster.go +++ b/pkg/kwokctl/runtime/compose/cluster.go @@ -25,8 +25,6 @@ import ( "strings" "time" - "sigs.k8s.io/yaml" - "sigs.k8s.io/kwok/pkg/consts" "sigs.k8s.io/kwok/pkg/kwokctl/components" "sigs.k8s.io/kwok/pkg/kwokctl/dryrun" @@ -41,6 +39,7 @@ import ( "sigs.k8s.io/kwok/pkg/utils/net" "sigs.k8s.io/kwok/pkg/utils/path" "sigs.k8s.io/kwok/pkg/utils/wait" + "sigs.k8s.io/kwok/pkg/utils/yaml" ) // Cluster is an implementation of Runtime for docker. diff --git a/pkg/kwokctl/snapshot/load.go b/pkg/kwokctl/snapshot/load.go index 93bb3a79d..b364f8ac6 100644 --- a/pkg/kwokctl/snapshot/load.go +++ b/pkg/kwokctl/snapshot/load.go @@ -118,7 +118,7 @@ func (l *loader) Load(ctx context.Context, r io.Reader) error { start := time.Now() decoder := yaml.NewDecoder(r) - err := decoder.Decode(func(obj *unstructured.Unstructured) error { + err := decoder.DecodeToUnstructured(func(obj *unstructured.Unstructured) error { if err := ctx.Err(); err != nil { return err } diff --git a/pkg/log/logger.go b/pkg/log/logger.go index 55ceae963..951488d79 100644 --- a/pkg/log/logger.go +++ b/pkg/log/logger.go @@ -23,8 +23,7 @@ import ( "os" "time" - //nolint:depguard - "golang.org/x/exp/slog" + "golang.org/x/exp/slog" //nolint:depguard "golang.org/x/term" ) diff --git a/pkg/log/logger_ctl.go b/pkg/log/logger_ctl.go index 7a074b859..ec2e22679 100644 --- a/pkg/log/logger_ctl.go +++ b/pkg/log/logger_ctl.go @@ -27,8 +27,7 @@ import ( "unicode/utf8" "github.com/wzshiming/ctc" - //nolint:depguard - "golang.org/x/exp/slog" + "golang.org/x/exp/slog" //nolint:depguard "golang.org/x/term" "sigs.k8s.io/kwok/pkg/utils/format" diff --git a/pkg/log/logger_ctl_test.go b/pkg/log/logger_ctl_test.go index 2d0d3da5d..aa2c6f0bc 100644 --- a/pkg/log/logger_ctl_test.go +++ b/pkg/log/logger_ctl_test.go @@ -21,8 +21,7 @@ import ( "sort" "testing" - //nolint:depguard - "golang.org/x/exp/slog" + "golang.org/x/exp/slog" //nolint:depguard ) func Test_quoteRangeTable(t *testing.T) { diff --git a/pkg/log/logger_noop.go b/pkg/log/logger_noop.go index 57b104c80..013a779f3 100644 --- a/pkg/log/logger_noop.go +++ b/pkg/log/logger_noop.go @@ -19,8 +19,7 @@ package log import ( "context" - //nolint:depguard - "golang.org/x/exp/slog" + "golang.org/x/exp/slog" //nolint:depguard ) var noop = wrapSlog(noopHandler{}, LevelInfo) diff --git a/pkg/log/wrapper.go b/pkg/log/wrapper.go index 9a152d18d..e2874cf7a 100644 --- a/pkg/log/wrapper.go +++ b/pkg/log/wrapper.go @@ -24,8 +24,7 @@ import ( "strings" "time" - //nolint:depguard - "golang.org/x/exp/slog" + "golang.org/x/exp/slog" //nolint:depguard ) // Level is the logging level. diff --git a/pkg/utils/gotpl/renderer.go b/pkg/utils/gotpl/renderer.go index 880415b9f..a347ad0fd 100644 --- a/pkg/utils/gotpl/renderer.go +++ b/pkg/utils/gotpl/renderer.go @@ -23,11 +23,10 @@ import ( "strings" "text/template" - "sigs.k8s.io/yaml" - "sigs.k8s.io/kwok/pkg/utils/maps" "sigs.k8s.io/kwok/pkg/utils/pools" "sigs.k8s.io/kwok/pkg/utils/slices" + "sigs.k8s.io/kwok/pkg/utils/yaml" ) // FuncMap is a map of functions that can be used in templates. diff --git a/pkg/utils/maps/maps.go b/pkg/utils/maps/maps.go new file mode 100644 index 000000000..ca50c864b --- /dev/null +++ b/pkg/utils/maps/maps.go @@ -0,0 +1,56 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package maps + +// Keys returns the keys of the map m. +// The keys will be in an indeterminate order. +func Keys[M ~map[K]V, K comparable, V any](m M) []K { + r := make([]K, 0, len(m)) + for k := range m { + r = append(r, k) + } + return r +} + +// Values returns the values of the map m. +// The values will be in an indeterminate order. +func Values[M ~map[K]V, K comparable, V any](m M) []V { + r := make([]V, 0, len(m)) + for _, v := range m { + r = append(r, v) + } + return r +} + +// Merge merges the maps in m into a single map. +// If a key is present in multiple maps, the value from the last map will be used. +func Merge[M ~map[K]V, K comparable, V any](m ...M) M { + if len(m) == 0 { + return nil + } + if len(m) == 1 { + return m[0] + } + + r := make(M) + for _, m := range m { + for k, v := range m { + r[k] = v + } + } + return r +} diff --git a/pkg/utils/wait/wait.go b/pkg/utils/wait/wait.go index 80fe1c8d5..8f16d4878 100644 --- a/pkg/utils/wait/wait.go +++ b/pkg/utils/wait/wait.go @@ -20,8 +20,7 @@ import ( "context" "time" - //nolint:depguard - "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/apimachinery/pkg/util/wait" //nolint:depguard ) const ( diff --git a/pkg/utils/yaml/decoder.go b/pkg/utils/yaml/decoder.go index d169b535c..4cabcf630 100644 --- a/pkg/utils/yaml/decoder.go +++ b/pkg/utils/yaml/decoder.go @@ -20,51 +20,39 @@ import ( "errors" "io" - yamlv3 "gopkg.in/yaml.v3" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" - "sigs.k8s.io/yaml" + "k8s.io/apimachinery/pkg/util/yaml" //nolint:depguard ) // Decoder is a YAML decoder. type Decoder struct { - decoder *yamlv3.Decoder + decoder *yaml.YAMLToJSONDecoder } // NewDecoder returns a new YAML decoder. func NewDecoder(r io.Reader) *Decoder { return &Decoder{ - decoder: yamlv3.NewDecoder(r), + decoder: yaml.NewYAMLToJSONDecoder(r), } } -// Decode decodes YAML into a list of unstructured objects. -func (d *Decoder) Decode(visitFunc func(obj *unstructured.Unstructured) error) error { - var tmp map[string]interface{} +// Decode decodes YAML into an object. +func (d *Decoder) Decode(obj any) error { + return d.decoder.Decode(obj) +} + +// DecodeToUnstructured decodes YAML into a list of unstructured objects. +func (d *Decoder) DecodeToUnstructured(visitFunc func(obj *unstructured.Unstructured) error) error { for { - err := d.decoder.Decode(&tmp) + obj := &unstructured.Unstructured{} + err := d.Decode(obj) if err != nil { if errors.Is(err, io.EOF) { return nil } return err } - if len(tmp) == 0 { - continue - } - data, err := yamlv3.Marshal(tmp) - if err != nil { - return err - } - data, err = yaml.YAMLToJSON(data) - if err != nil { - return err - } - obj := &unstructured.Unstructured{} - err = obj.UnmarshalJSON(data) - if err != nil { - return err - } if obj.IsList() { err = obj.EachListItem(func(object runtime.Object) error { diff --git a/pkg/utils/yaml/decoder_test.go b/pkg/utils/yaml/decoder_test.go index 904f8387c..b98966c75 100644 --- a/pkg/utils/yaml/decoder_test.go +++ b/pkg/utils/yaml/decoder_test.go @@ -29,7 +29,7 @@ import ( "sigs.k8s.io/kwok/pkg/utils/slices" ) -func TestDecoder(t *testing.T) { +func TestDecodeToUnstructured(t *testing.T) { tests := []struct { name string data string @@ -88,12 +88,12 @@ spec: for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := []*unstructured.Unstructured{} - err := NewDecoder(bytes.NewBufferString(tt.data)).Decode(func(obj *unstructured.Unstructured) error { + err := NewDecoder(bytes.NewBufferString(tt.data)).DecodeToUnstructured(func(obj *unstructured.Unstructured) error { got = append(got, obj) return nil }) if (err != nil) != tt.wantErr { - t.Errorf("Decode() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("DecodeToUnstructured() error = %v, wantErr %v", err, tt.wantErr) return } diff --git a/pkg/utils/yaml/encoder.go b/pkg/utils/yaml/encoder.go index 627f0d3b7..1879372ea 100644 --- a/pkg/utils/yaml/encoder.go +++ b/pkg/utils/yaml/encoder.go @@ -21,7 +21,6 @@ import ( "sync/atomic" "k8s.io/apimachinery/pkg/runtime" - "sigs.k8s.io/yaml" ) // Encoder is a YAML encoder. @@ -48,7 +47,7 @@ func (p *Encoder) Encode(obj runtime.Object) error { } } - output, err := yaml.Marshal(obj) + output, err := Marshal(obj) if err != nil { return err } diff --git a/pkg/utils/maps/ref.go b/pkg/utils/yaml/ref.go similarity index 70% rename from pkg/utils/maps/ref.go rename to pkg/utils/yaml/ref.go index 2d9bd5fa2..80cae3040 100644 --- a/pkg/utils/maps/ref.go +++ b/pkg/utils/yaml/ref.go @@ -14,13 +14,16 @@ See the License for the specific language governing permissions and limitations under the License. */ -package maps +package yaml import ( - "golang.org/x/exp/maps" + "sigs.k8s.io/yaml" //nolint:depguard ) -// Keys returns the keys of the map. -func Keys[M ~map[K]V, K comparable, V any](m M) []K { - return maps.Keys(m) -} +// The following functions are exported for testing purposes only. +var ( + YAMLToJSON = yaml.YAMLToJSON + JSONToYAML = yaml.JSONToYAML + Unmarshal = yaml.Unmarshal + Marshal = yaml.Marshal +) diff --git a/site/content/en/docs/generated/kwokctl.md b/site/content/en/docs/generated/kwokctl.md index 37060b50f..da3f33e1e 100644 --- a/site/content/en/docs/generated/kwokctl.md +++ b/site/content/en/docs/generated/kwokctl.md @@ -25,7 +25,7 @@ kwokctl [command] [flags] * [kwokctl export](kwokctl_export.md) - Exports one of [logs] * [kwokctl get](kwokctl_get.md) - Gets one of [artifacts, clusters, kubeconfig] * [kwokctl kubectl](kwokctl_kubectl.md) - kubectl in cluster -* [kwokctl logs](kwokctl_logs.md) - Logs one of [audit, etcd, kube-apiserver, kube-controller-manager, kube-scheduler, kwok-controller, prometheus] +* [kwokctl logs](kwokctl_logs.md) - Logs one of [audit, etcd, kube-apiserver, kube-controller-manager, kube-scheduler, kwok-controller, dashboard, prometheus, jaeger] * [kwokctl scale](kwokctl_scale.md) - Scale a resource in cluster * [kwokctl snapshot](kwokctl_snapshot.md) - Snapshot [save, restore, export] one of cluster * [kwokctl start](kwokctl_start.md) - Start one of [cluster] diff --git a/site/content/en/docs/generated/kwokctl_logs.md b/site/content/en/docs/generated/kwokctl_logs.md index 77d4aa7a2..f65e29797 100644 --- a/site/content/en/docs/generated/kwokctl_logs.md +++ b/site/content/en/docs/generated/kwokctl_logs.md @@ -1,6 +1,6 @@ ## kwokctl logs -Logs one of [audit, etcd, kube-apiserver, kube-controller-manager, kube-scheduler, kwok-controller, prometheus] +Logs one of [audit, etcd, kube-apiserver, kube-controller-manager, kube-scheduler, kwok-controller, dashboard, prometheus, jaeger] ``` kwokctl logs [command] [flags]