Compare commits
6 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
7c240e5828 | |
|
|
da2b3fbac8 | |
|
|
ebb124d8cd | |
|
|
68d571ec42 | |
|
|
d973c2aa1d | |
|
|
94742398cd |
|
|
@ -12,7 +12,7 @@ on:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
# Common versions
|
# Common versions
|
||||||
GO_VERSION: '1.22'
|
GO_VERSION: '1.23'
|
||||||
GOLANGCI_VERSION: 'v1.55.2'
|
GOLANGCI_VERSION: 'v1.55.2'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
@ -27,6 +27,14 @@ jobs:
|
||||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||||
with:
|
with:
|
||||||
go-version: ${{ env.GO_VERSION }}
|
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
|
- name: Cache Go Dependencies
|
||||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||||
with:
|
with:
|
||||||
|
|
@ -47,13 +55,69 @@ jobs:
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
|
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||||
with:
|
with:
|
||||||
go-version: ${{ env.GO_VERSION }}
|
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
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
make build
|
make build
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
run: |
|
run: |
|
||||||
make test
|
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 ./...
|
||||||
|
|
@ -6,7 +6,6 @@ on:
|
||||||
- created
|
- created
|
||||||
|
|
||||||
env:
|
env:
|
||||||
# Common versions
|
|
||||||
GO_VERSION: '1.22'
|
GO_VERSION: '1.22'
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
|
@ -15,101 +14,137 @@ jobs:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
TARGETS: [ linux/amd64, darwin/amd64, windows/amd64, linux/arm64, darwin/arm64 ]
|
include:
|
||||||
|
- os: linux
|
||||||
|
arch: amd64
|
||||||
|
- os: linux
|
||||||
|
arch: arm64
|
||||||
|
- os: darwin
|
||||||
|
arch: amd64
|
||||||
|
- os: darwin
|
||||||
|
arch: arm64
|
||||||
|
- os: windows
|
||||||
|
arch: amd64
|
||||||
env:
|
env:
|
||||||
GO_BUILD_ENV: GO111MODULE=on CGO_ENABLED=0
|
GO_BUILD_ENV: GO111MODULE=on CGO_ENABLED=0
|
||||||
DIST_DIRS: find * -type d -exec
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
- name: Checkout
|
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
with:
|
||||||
|
fetch-depth: 0 # Needed for version.sh to work properly
|
||||||
|
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
|
||||||
with:
|
with:
|
||||||
go-version: ${{ env.GO_VERSION }}
|
go-version: ${{ env.GO_VERSION }}
|
||||||
- name: Get release
|
cache: true # Enable built-in Go caching
|
||||||
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
|
- name: Get ldflags
|
||||||
id: get_ldflags
|
id: get_ldflags
|
||||||
run: |
|
run: |
|
||||||
LDFLAGS=$(./version.sh)
|
LDFLAGS=$(./version.sh)
|
||||||
echo "LDFLAGS=${LDFLAGS}" >> $GITHUB_ENV
|
echo "LDFLAGS=${LDFLAGS}" >> $GITHUB_OUTPUT
|
||||||
- name: Build
|
|
||||||
|
- name: Build kubectl-kruise
|
||||||
run: |
|
run: |
|
||||||
${{ env.GO_BUILD_ENV }} GOOS=${{ steps.get_matrix.outputs.OS }} GOARCH=${{ steps.get_matrix.outputs.ARCH }} \
|
${{ env.GO_BUILD_ENV }} GOOS=${{ matrix.os }} GOARCH=${{ matrix.arch }} \
|
||||||
go build -ldflags "${{ env.LDFLAGS }}" \
|
go build -ldflags "${{ steps.get_ldflags.outputs.LDFLAGS }}" \
|
||||||
-o _bin/kubectl-kruise/${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}/kubectl-kruise -v \
|
-o _bin/kubectl-kruise/${{ matrix.os }}-${{ matrix.arch }}/kubectl-kruise${{ matrix.os == 'windows' && '.exe' || '' }} \
|
||||||
./cmd/plugin/main.go
|
./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
|
- name: Build resourcedistribution-generator
|
||||||
run: |
|
run: |
|
||||||
${{ env.GO_BUILD_ENV }} GOOS=${{ steps.get_matrix.outputs.OS }} GOARCH=${{ steps.get_matrix.outputs.ARCH }} \
|
${{ env.GO_BUILD_ENV }} GOOS=${{ matrix.os }} GOARCH=${{ matrix.arch }} \
|
||||||
go build -ldflags "${{ env.LDFLAGS }}" \
|
go build -ldflags "${{ steps.get_ldflags.outputs.LDFLAGS }}" \
|
||||||
-o _bin/resourcedistribution-generator/${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}/resourcedistributiongenerator -v \
|
-o _bin/resourcedistribution-generator/${{ matrix.os }}-${{ matrix.arch }}/resourcedistributiongenerator${{ matrix.os == 'windows' && '.exe' || '' }} \
|
||||||
./cmd/resourcedistributiongenerator/main.go
|
./cmd/resourcedistributiongenerator/main.go
|
||||||
- name: Compress resourcedistribution-generator
|
|
||||||
|
- name: Package artifacts
|
||||||
run: |
|
run: |
|
||||||
cd _bin/resourcedistribution-generator && \
|
# Package kubectl-kruise
|
||||||
${{ env.DIST_DIRS }} tar -zcf resourcedistribution-generator-{}.tar.gz {} \; && \
|
cd _bin/kubectl-kruise/${{ matrix.os }}-${{ matrix.arch }}
|
||||||
cd .. && \
|
cp ../../../LICENSE .
|
||||||
sha256sum resourcedistribution-generator/resourcedistribution-generator-* >> sha256-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.txt \
|
cp ../../../README.md .
|
||||||
- name: Upload resourcedistribution-generator tar.gz
|
if [ "${{ matrix.os }}" = "windows" ]; then
|
||||||
uses: actions/upload-release-asset@v1.0.2
|
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
|
||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.get_release.outputs.upload_url }}
|
name: sha256sums-${{ matrix.os }}-${{ matrix.arch }}
|
||||||
asset_path: ./_bin/resourcedistribution-generator/resourcedistribution-generator-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.tar.gz
|
path: _bin/sha256-${{ matrix.os }}-${{ matrix.arch }}.txt
|
||||||
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: 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
|
retention-days: 1
|
||||||
upload-sha256sums:
|
|
||||||
|
- name: Upload build artifacts
|
||||||
|
uses: actions/upload-artifact@v4.4.3
|
||||||
|
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
|
||||||
|
retention-days: 1
|
||||||
|
|
||||||
|
upload-release-assets:
|
||||||
needs: build_and_upload
|
needs: build_and_upload
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
name: upload-sha256sums
|
permissions:
|
||||||
|
contents: write
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
- name: Get release
|
|
||||||
id: get_release
|
- name: Download all artifacts
|
||||||
uses: bruceadams/get-release@v1.2.2
|
|
||||||
- name: Download artifacts
|
|
||||||
uses: actions/download-artifact@v4.1.7
|
uses: actions/download-artifact@v4.1.7
|
||||||
with:
|
with:
|
||||||
pattern: sha256sums-*
|
pattern: "*"
|
||||||
merge-multiple: true
|
merge-multiple: true
|
||||||
path: sha256sums
|
path: artifacts
|
||||||
- shell: bash
|
|
||||||
|
- name: Prepare release assets
|
||||||
run: |
|
run: |
|
||||||
cat sha256sums/*.txt > sha256sums.txt
|
mkdir -p release-assets
|
||||||
- name: Upload Checksums
|
|
||||||
uses: actions/upload-release-asset@v1.0.2
|
# 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
|
||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.get_release.outputs.upload_url }}
|
files: release-assets/*
|
||||||
asset_path: sha256sums.txt
|
fail_on_unmatched_files: true
|
||||||
asset_name: sha256sums-${{ steps.get_release.outputs.tag_name }}.txt
|
|
||||||
asset_content_type: text/plain
|
|
||||||
- name: Update kubectl plugin version in krew-index
|
- name: Update kubectl plugin version in krew-index
|
||||||
uses: rajatjindal/krew-release-bot@v0.0.43
|
uses: rajatjindal/krew-release-bot@v0.0.46
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
# Temporary exclusion - proxy/tokenizer vulnerabilities don't affect our usage
|
||||||
|
CVE-2025-22870
|
||||||
|
CVE-2025-22872
|
||||||
54
README.md
54
README.md
|
|
@ -198,6 +198,60 @@ kubectl kruise migrate CloneSet --from Deployment --src-name deployment-demo --d
|
||||||
#### kubectl kruise autoscale SUBCOMMAND [options]
|
#### kubectl kruise autoscale SUBCOMMAND [options]
|
||||||
* [ ] kubectl kruise autoscale
|
* [ ] 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
|
### Contributing
|
||||||
We encourage you to help out by reporting issues, improving documentation, fixing bugs, or adding new features.
|
We encourage you to help out by reporting issues, improving documentation, fixing bugs, or adding new features.
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,8 @@ Restart a resource
|
||||||
|
|
||||||
Restart a resource.
|
Restart a resource.
|
||||||
|
|
||||||
Resource will be rollout restarted.
|
Resource will be rollout restarted. Supported kinds include:
|
||||||
|
CloneSet, DaemonSet, Deployment, StatefulSet, and UnitedDeployment.
|
||||||
|
|
||||||
```
|
```
|
||||||
kubectl-kruise rollout restart RESOURCE
|
kubectl-kruise rollout restart RESOURCE
|
||||||
|
|
@ -21,6 +22,9 @@ kubectl-kruise rollout restart RESOURCE
|
||||||
|
|
||||||
# Restart a daemonset
|
# Restart a daemonset
|
||||||
kubectl-kruise rollout restart daemonset/abc
|
kubectl-kruise rollout restart daemonset/abc
|
||||||
|
|
||||||
|
# Restart a UnitedDeployment
|
||||||
|
kubectl-kruise rollout restart uniteddeployment/my-app
|
||||||
```
|
```
|
||||||
|
|
||||||
### Options
|
### Options
|
||||||
|
|
|
||||||
4
go.mod
4
go.mod
|
|
@ -1,8 +1,8 @@
|
||||||
module github.com/openkruise/kruise-tools
|
module github.com/openkruise/kruise-tools
|
||||||
|
|
||||||
go 1.22.0
|
go 1.23.0
|
||||||
|
|
||||||
toolchain go1.22.4
|
toolchain go1.23.4
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/go-errors/errors v1.4.2
|
github.com/go-errors/errors v1.4.2
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,10 @@ var (
|
||||||
kubectl-kruise rollout restart cloneset/abc
|
kubectl-kruise rollout restart cloneset/abc
|
||||||
|
|
||||||
# Restart a daemonset
|
# Restart a daemonset
|
||||||
kubectl-kruise rollout restart daemonset/abc`)
|
kubectl-kruise rollout restart daemonset/abc
|
||||||
|
|
||||||
|
# Restart a UnitedDeployment
|
||||||
|
kubectl-kruise rollout restart uniteddeployment/my-app`)
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewRolloutRestartOptions returns an initialized RestartOptions instance
|
// NewRolloutRestartOptions returns an initialized RestartOptions instance
|
||||||
|
|
@ -80,7 +83,7 @@ func NewRolloutRestartOptions(streams genericclioptions.IOStreams) *RestartOptio
|
||||||
func NewCmdRolloutRestart(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
|
func NewCmdRolloutRestart(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
|
||||||
o := NewRolloutRestartOptions(streams)
|
o := NewRolloutRestartOptions(streams)
|
||||||
|
|
||||||
validArgs := []string{"deployment", "daemonset", "statefulset", "cloneset"}
|
validArgs := []string{"deployment", "daemonset", "statefulset", "cloneset", "uniteddeployment"}
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "restart RESOURCE",
|
Use: "restart RESOURCE",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,132 @@
|
||||||
|
/*
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue