Compare commits

..

No commits in common. "master" and "v1.2.0" have entirely different histories.

12 changed files with 128 additions and 470 deletions

View File

@ -12,7 +12,7 @@ on:
env:
# Common versions
GO_VERSION: '1.23'
GO_VERSION: '1.22'
GOLANGCI_VERSION: 'v1.55.2'
jobs:
@ -27,14 +27,6 @@ jobs:
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
with:
go-version: ${{ env.GO_VERSION }}
- name: Verify go.mod is tidy
run: |
go mod tidy
if [ -n "$(git status --porcelain go.mod go.sum)" ]; then
echo "go.mod or go.sum is not tidy"
git diff go.mod go.sum
exit 1
fi
- name: Cache Go Dependencies
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
with:
@ -55,69 +47,13 @@ jobs:
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: true
- name: Setup Go
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
with:
go-version: ${{ env.GO_VERSION }}
- name: Cache Go modules and build cache
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
with:
path: |
~/go/pkg/mod
~/.cache/go-build
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-go-
- name: Verify go.mod is tidy
run: |
go mod tidy
if [ -n "$(git status --porcelain go.mod go.sum)" ]; then
echo "go.mod or go.sum is not tidy"
git diff go.mod go.sum
exit 1
fi
- name: Build
run: |
make build
- name: Test
run: |
make test
security-scan:
name: Security Vulnerability Scan
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: true
- name: Setup Go
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
with:
go-version: ${{ env.GO_VERSION }}
- name: Cache Go Dependencies
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-go-
- name: Generate go.list file for Nancy
run: go list -json -deps ./... > go.list
- name: Run Nancy vulnerability scan
uses: sonatype-nexus-community/nancy-github-action@main
with:
nancyCommand: sleuth
goListFile: go.list
- name: Install and run govulncheck
run: |
go install golang.org/x/vuln/cmd/govulncheck@latest
govulncheck ./...

View File

@ -6,6 +6,7 @@ on:
- created
env:
# Common versions
GO_VERSION: '1.22'
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@ -14,137 +15,101 @@ jobs:
runs-on: ubuntu-24.04
strategy:
matrix:
include:
- os: linux
arch: amd64
- os: linux
arch: arm64
- os: darwin
arch: amd64
- os: darwin
arch: arm64
- os: windows
arch: amd64
TARGETS: [ linux/amd64, darwin/amd64, windows/amd64, linux/arm64, darwin/arm64 ]
env:
GO_BUILD_ENV: GO111MODULE=on CGO_ENABLED=0
DIST_DIRS: find * -type d -exec
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0 # Needed for version.sh to work properly
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup Go
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
with:
go-version: ${{ env.GO_VERSION }}
cache: true # Enable built-in Go caching
- name: Get release
id: get_release
uses: bruceadams/get-release@v1.2.2
- name: Get matrix
id: get_matrix
run: |
TARGETS=${{matrix.TARGETS}}
echo ::set-output name=OS::${TARGETS%/*}
echo ::set-output name=ARCH::${TARGETS#*/}
- name: Get ldflags
id: get_ldflags
run: |
LDFLAGS=$(./version.sh)
echo "LDFLAGS=${LDFLAGS}" >> $GITHUB_OUTPUT
- name: Build kubectl-kruise
echo "LDFLAGS=${LDFLAGS}" >> $GITHUB_ENV
- name: Build
run: |
${{ env.GO_BUILD_ENV }} GOOS=${{ matrix.os }} GOARCH=${{ matrix.arch }} \
go build -ldflags "${{ steps.get_ldflags.outputs.LDFLAGS }}" \
-o _bin/kubectl-kruise/${{ matrix.os }}-${{ matrix.arch }}/kubectl-kruise${{ matrix.os == 'windows' && '.exe' || '' }} \
${{ env.GO_BUILD_ENV }} GOOS=${{ steps.get_matrix.outputs.OS }} GOARCH=${{ steps.get_matrix.outputs.ARCH }} \
go build -ldflags "${{ env.LDFLAGS }}" \
-o _bin/kubectl-kruise/${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}/kubectl-kruise -v \
./cmd/plugin/main.go
- name: Compress
run: |
cd _bin/kubectl-kruise && \
${{ env.DIST_DIRS }} cp ../../LICENSE {} \; && \
${{ env.DIST_DIRS }} cp ../../README.md {} \; && \
${{ env.DIST_DIRS }} tar -zcf kubectl-kruise-{}.tar.gz {} \; && \
cd .. && \
sha256sum kubectl-kruise/kubectl-kruise-* >> sha256-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.txt \
- name: Upload Kubectl-kruise tar.gz
uses: actions/upload-release-asset@v1.0.2
with:
upload_url: ${{ steps.get_release.outputs.upload_url }}
asset_path: ./_bin/kubectl-kruise/kubectl-kruise-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.tar.gz
asset_name: kubectl-kruise-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}-${{ steps.get_release.outputs.tag_name }}.tar.gz
asset_content_type: binary/octet-stream
- name: Build resourcedistribution-generator
run: |
${{ env.GO_BUILD_ENV }} GOOS=${{ matrix.os }} GOARCH=${{ matrix.arch }} \
go build -ldflags "${{ steps.get_ldflags.outputs.LDFLAGS }}" \
-o _bin/resourcedistribution-generator/${{ matrix.os }}-${{ matrix.arch }}/resourcedistributiongenerator${{ matrix.os == 'windows' && '.exe' || '' }} \
${{ env.GO_BUILD_ENV }} GOOS=${{ steps.get_matrix.outputs.OS }} GOARCH=${{ steps.get_matrix.outputs.ARCH }} \
go build -ldflags "${{ env.LDFLAGS }}" \
-o _bin/resourcedistribution-generator/${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}/resourcedistributiongenerator -v \
./cmd/resourcedistributiongenerator/main.go
- name: Package artifacts
- name: Compress resourcedistribution-generator
run: |
# Package kubectl-kruise
cd _bin/kubectl-kruise/${{ matrix.os }}-${{ matrix.arch }}
cp ../../../LICENSE .
cp ../../../README.md .
if [ "${{ matrix.os }}" = "windows" ]; then
zip -r kubectl-kruise-${{ matrix.os }}-${{ matrix.arch }}.zip .
else
tar -czf kubectl-kruise-${{ matrix.os }}-${{ matrix.arch }}.tar.gz .
fi
cd ../../..
# Package resourcedistribution-generator
cd _bin/resourcedistribution-generator/${{ matrix.os }}-${{ matrix.arch }}
if [ "${{ matrix.os }}" = "windows" ]; then
zip -r resourcedistribution-generator-${{ matrix.os }}-${{ matrix.arch }}.zip .
else
tar -czf resourcedistribution-generator-${{ matrix.os }}-${{ matrix.arch }}.tar.gz .
fi
cd ../../..
- name: Generate checksums
run: |
cd _bin
find . -name "*.tar.gz" -o -name "*.zip" | xargs sha256sum > sha256-${{ matrix.os }}-${{ matrix.arch }}.txt
- name: Upload checksums artifact
uses: actions/upload-artifact@v4.4.3
cd _bin/resourcedistribution-generator && \
${{ env.DIST_DIRS }} tar -zcf resourcedistribution-generator-{}.tar.gz {} \; && \
cd .. && \
sha256sum resourcedistribution-generator/resourcedistribution-generator-* >> sha256-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.txt \
- name: Upload resourcedistribution-generator tar.gz
uses: actions/upload-release-asset@v1.0.2
with:
name: sha256sums-${{ matrix.os }}-${{ matrix.arch }}
path: _bin/sha256-${{ matrix.os }}-${{ matrix.arch }}.txt
retention-days: 1
- name: Upload build artifacts
uses: actions/upload-artifact@v4.4.3
upload_url: ${{ steps.get_release.outputs.upload_url }}
asset_path: ./_bin/resourcedistribution-generator/resourcedistribution-generator-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.tar.gz
asset_name: resourcedistribution-generator-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}-${{ steps.get_release.outputs.tag_name }}.tar.gz
asset_content_type: binary/octet-stream
- name: Post sha256
uses: actions/upload-artifact@v4
with:
name: binaries-${{ matrix.os }}-${{ matrix.arch }}
path: |
_bin/kubectl-kruise/${{ matrix.os }}-${{ matrix.arch }}/*.tar.gz
_bin/kubectl-kruise/${{ matrix.os }}-${{ matrix.arch }}/*.zip
_bin/resourcedistribution-generator/${{ matrix.os }}-${{ matrix.arch }}/*.tar.gz
_bin/resourcedistribution-generator/${{ matrix.os }}-${{ matrix.arch }}/*.zip
name: sha256sums-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}
path: ./_bin/sha256-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.txt
retention-days: 1
upload-release-assets:
upload-sha256sums:
needs: build_and_upload
runs-on: ubuntu-latest
permissions:
contents: write
name: upload-sha256sums
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Download all artifacts
uses: actions/checkout@v4
- name: Get release
id: get_release
uses: bruceadams/get-release@v1.2.2
- name: Download artifacts
uses: actions/download-artifact@v4.1.7
with:
pattern: "*"
pattern: sha256sums-*
merge-multiple: true
path: artifacts
- name: Prepare release assets
path: sha256sums
- shell: bash
run: |
mkdir -p release-assets
# Move binary archives to release assets
find artifacts -name "*.tar.gz" -o -name "*.zip" | while read file; do
filename=$(basename "$file")
# Add version tag to filename
name_part="${filename%.*}"
ext="${filename##*.}"
if [[ "$filename" == *.tar.gz ]]; then
ext="tar.gz"
name_part="${filename%.tar.gz}"
fi
cp "$file" "release-assets/${name_part}-${GITHUB_REF_NAME}.${ext}"
done
# Combine all checksums
cat artifacts/sha256-*.txt > release-assets/sha256sums-${GITHUB_REF_NAME}.txt
- name: Upload release assets
uses: softprops/action-gh-release@v2.0.8
cat sha256sums/*.txt > sha256sums.txt
- name: Upload Checksums
uses: actions/upload-release-asset@v1.0.2
with:
files: release-assets/*
fail_on_unmatched_files: true
upload_url: ${{ steps.get_release.outputs.upload_url }}
asset_path: sha256sums.txt
asset_name: sha256sums-${{ steps.get_release.outputs.tag_name }}.txt
asset_content_type: text/plain
- name: Update kubectl plugin version in krew-index
uses: rajatjindal/krew-release-bot@v0.0.46
uses: rajatjindal/krew-release-bot@v0.0.43

View File

@ -1,3 +0,0 @@
# Temporary exclusion - proxy/tokenizer vulnerabilities don't affect our usage
CVE-2025-22870
CVE-2025-22872

View File

@ -198,60 +198,6 @@ kubectl kruise migrate CloneSet --from Deployment --src-name deployment-demo --d
#### kubectl kruise autoscale SUBCOMMAND [options]
* [ ] kubectl kruise autoscale
## Security
This project includes automated vulnerability scanning to ensure the security of dependencies.
### Vulnerability Scanning
We use two complementary tools to scan for vulnerabilities in our Go dependencies:
1. **Nancy by Sonatype** - Comprehensive dependency scanning against the Sonatype OSS Index
2. **govulncheck** - Official Go vulnerability scanner with call graph analysis to reduce false positives
### CI/CD Security Integration
Security scans are automatically run:
- On every push to `master` and `release*` branches
- On every pull request
- Daily at 2 AM UTC via scheduled workflow
### Handling Vulnerabilities
If vulnerabilities are found:
1. **Review the vulnerability report** - Check if the vulnerability affects your usage
2. **Update dependencies** - Upgrade to a non-vulnerable version if available
3. **Apply workarounds** - If no update is available, consider alternative approaches
4. **Temporary exclusions** - For false positives or accepted risks, add the CVE ID to `.nancy-ignore`
#### Excluding Vulnerabilities
To exclude specific vulnerabilities from Nancy scans, add the CVE ID or OSS Index ID to the `.nancy-ignore` file:
```
# Example: Exclude a specific CVE
CVE-2021-12345
# Example: Exclude by OSS Index ID
9eb9a5bc-8310-4104-bf85-3a820d28ba79
```
### Running Security Scans Locally
To run vulnerability scans locally:
```bash
# Install tools
go install github.com/sonatype-nexus-community/nancy@latest
go install golang.org/x/vuln/cmd/govulncheck@latest
# Run Nancy scan
go list -json -deps ./... > go.list
nancy sleuth --loud
# Run govulncheck
govulncheck ./...
```
### Contributing
We encourage you to help out by reporting issues, improving documentation, fixing bugs, or adding new features.

View File

@ -6,8 +6,7 @@ Restart a resource
Restart a resource.
Resource will be rollout restarted. Supported kinds include:
CloneSet, DaemonSet, Deployment, StatefulSet, and UnitedDeployment.
Resource will be rollout restarted.
```
kubectl-kruise rollout restart RESOURCE
@ -22,9 +21,6 @@ kubectl-kruise rollout restart RESOURCE
# Restart a daemonset
kubectl-kruise rollout restart daemonset/abc
# Restart a UnitedDeployment
kubectl-kruise rollout restart uniteddeployment/my-app
```
### Options

BIN
go.list

Binary file not shown.

12
go.mod
View File

@ -1,8 +1,8 @@
module github.com/openkruise/kruise-tools
go 1.23.0
go 1.22.0
toolchain go1.23.4
toolchain go1.22.4
require (
github.com/go-errors/errors v1.4.2
@ -93,11 +93,3 @@ require (
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
)
replace (
golang.org/x/net => golang.org/x/net v0.33.0
golang.org/x/sync => golang.org/x/sync v0.10.0
golang.org/x/sys => golang.org/x/sys v0.19.0
golang.org/x/term => golang.org/x/term v0.19.0
golang.org/x/text => golang.org/x/text v0.21.0
)

62
go.sum
View File

@ -201,9 +201,10 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA=
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA=
@ -213,25 +214,55 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ=
golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
@ -240,7 +271,6 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@ -60,10 +60,10 @@ var (
rolloutExample = templates.Examples(`
# Describe the rollout named rollout-demo within namespace default
kubectl-kruise describe rollout rollout-demo -n default
kubectl-kruise describe rollout rollout-demo/default
# Watch for changes to the rollout named rollout-demo
kubectl-kruise describe rollout rollout-demo -n default -w`)
kubectl-kruise describe rollout rollout-demo/default -w`)
)
type DescribeRolloutOptions struct {
@ -158,7 +158,11 @@ func (o *DescribeRolloutOptions) Complete(f cmdutil.Factory, args []string) erro
return err
}
o.Resources = []string{args[0]}
parts := strings.Split(args[0], "/")
if len(parts) == 2 {
o.Resources = []string{parts[0]}
o.Namespace = parts[1]
}
o.RolloutViewerFn = internalpolymorphichelpers.RolloutViewerFn
o.Builder = f.NewBuilder

View File

@ -65,10 +65,7 @@ var (
kubectl-kruise rollout restart cloneset/abc
# Restart a daemonset
kubectl-kruise rollout restart daemonset/abc
# Restart a UnitedDeployment
kubectl-kruise rollout restart uniteddeployment/my-app`)
kubectl-kruise rollout restart daemonset/abc`)
)
// NewRolloutRestartOptions returns an initialized RestartOptions instance
@ -83,7 +80,7 @@ func NewRolloutRestartOptions(streams genericclioptions.IOStreams) *RestartOptio
func NewCmdRolloutRestart(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
o := NewRolloutRestartOptions(streams)
validArgs := []string{"deployment", "daemonset", "statefulset", "cloneset", "uniteddeployment"}
validArgs := []string{"deployment", "daemonset", "statefulset", "cloneset"}
cmd := &cobra.Command{
Use: "restart RESOURCE",

View File

@ -1,73 +0,0 @@
/*
Copyright 2025 The Kruise 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 utils
import "testing"
func TestInt32Min(t *testing.T) {
testCases := []struct {
name string
a int32
items []int32
expected int32
}{
{
name: "No extra items",
a: 10,
items: []int32{},
expected: 10,
},
{
name: "All positive numbers",
a: 10,
items: []int32{5, 20, 12},
expected: 5,
},
{
name: "With negative numbers",
a: -5,
items: []int32{10, -2, -10},
expected: -10,
},
{
name: "With zero",
a: 1,
items: []int32{5, 0, 2},
expected: 0,
},
{
name: "All numbers are the same",
a: 7,
items: []int32{7, 7, 7},
expected: 7,
},
{
name: "Initial value 'a' is the minimum",
a: 3,
items: []int32{10, 5, 8},
expected: 3,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
if got := Int32Min(tc.a, tc.items...); got != tc.expected {
t.Errorf("Int32Min() = %v, want %v", got, tc.expected)
}
})
}
}

View File

@ -1,132 +0,0 @@
/*
Copyright 2025 The Kruise 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 utils
import (
"testing"
appsv1 "k8s.io/api/apps/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// Helper function for string pointers
func strPtr(s string) *string { return &s }
func TestIsKruiseRolloutsAnnotation(t *testing.T) {
testCases := []struct {
name string
input *string
expected bool
}{
{name: "Nil string", input: nil, expected: false},
{name: "Kruise prefix", input: strPtr("rollouts.kruise.io/annotation"), expected: true},
{name: "Non-matching string", input: strPtr("other.domain/key"), expected: false},
{name: "Exact prefix", input: strPtr("rollouts.kruise.io/"), expected: true},
{name: "Empty string", input: strPtr(""), expected: false},
{name: "Substring match", input: strPtr("pre/rollouts.kruise.io/suffix"), expected: true},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
if got := IsKruiseRolloutsAnnotation(tc.input); got != tc.expected {
t.Errorf("expected %v, got %v", tc.expected, got)
}
})
}
}
func TestInCanaryProgress(t *testing.T) {
testCases := []struct {
name string
deployment *appsv1.Deployment
expected bool
}{
{
name: "Not paused",
deployment: &appsv1.Deployment{
Spec: appsv1.DeploymentSpec{Paused: false},
ObjectMeta: metav1.ObjectMeta{Annotations: map[string]string{InRolloutProgressingAnnotation: "true"}},
},
expected: false,
},
{
name: "Missing progressing annotation",
deployment: &appsv1.Deployment{
Spec: appsv1.DeploymentSpec{Paused: true},
ObjectMeta: metav1.ObjectMeta{Annotations: map[string]string{}},
},
expected: false,
},
{
name: "Has strategy annotation",
deployment: &appsv1.Deployment{
Spec: appsv1.DeploymentSpec{Paused: true},
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
InRolloutProgressingAnnotation: "true",
DeploymentStrategyAnnotation: "partition",
},
},
},
expected: false,
},
{
name: "Valid canary state",
deployment: &appsv1.Deployment{
Spec: appsv1.DeploymentSpec{Paused: true},
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{InRolloutProgressingAnnotation: "true"},
},
},
expected: true,
},
{
name: "Nil annotations",
deployment: &appsv1.Deployment{
Spec: appsv1.DeploymentSpec{Paused: true},
ObjectMeta: metav1.ObjectMeta{},
},
expected: false,
},
{
name: "Explicit empty annotations",
deployment: &appsv1.Deployment{
Spec: appsv1.DeploymentSpec{Paused: true},
ObjectMeta: metav1.ObjectMeta{Annotations: map[string]string{}},
},
expected: false,
},
{
name: "Only strategy annotation present",
deployment: &appsv1.Deployment{
Spec: appsv1.DeploymentSpec{Paused: true},
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{DeploymentStrategyAnnotation: "partition"},
},
},
expected: false,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
if got := InCanaryProgress(tc.deployment); got != tc.expected {
t.Errorf("expected %v, got %v", tc.expected, got)
}
})
}
}