Compare commits

..

24 Commits

Author SHA1 Message Date
Parship Chowdhury 7c240e5828
Add support for sonatype nancy vulnerability scanning (#153)
* added sonatype nancy vulnerability scanning

Signed-off-by: Parship Chowdhury <i.am.parship@gmail.com>

* fix 1

Signed-off-by: Parship Chowdhury <i.am.parship@gmail.com>

* fix 2

Signed-off-by: Parship Chowdhury <i.am.parship@gmail.com>

* vulnerability check fixed

Signed-off-by: Parship Chowdhury <i.am.parship@gmail.com>

---------

Signed-off-by: Parship Chowdhury <i.am.parship@gmail.com>
2025-07-22 21:26:30 +08:00
Gautam Manchandani da2b3fbac8
added unit test for util package (#138)
Signed-off-by: GautamBytes <manchandanigautam@gmail.com>
2025-07-21 13:00:51 +08:00
Gautam Manchandani ebb124d8cd
updated actions and enhanced build process (#137)
Signed-off-by: GautamBytes <manchandanigautam@gmail.com>
2025-07-08 09:51:29 +08:00
Gautam Manchandani 68d571ec42
add Go module & build cache to speed up CI (#135)
Signed-off-by: GautamBytes <manchandanigautam@gmail.com>
Co-authored-by: Jeremy <hantmac@outlook.com>
2025-07-06 22:41:44 +08:00
Gautam Manchandani d973c2aa1d
verify go.mod & go.sum consistency in CI (#136)
Signed-off-by: GautamBytes <manchandanigautam@gmail.com>
2025-07-06 18:22:15 +08:00
Gautam Manchandani 94742398cd
support UnitedDeployment in kubectl-kruise rollout restart (#128)
Signed-off-by: GautamBytes <manchandanigautam@gmail.com>
2025-06-23 17:01:26 +08:00
Zhen Zhang 0fc1342e14
fix namespace setting (#127)
Signed-off-by: 守辰 <shouchen.zz@alibaba-inc.com>
2025-06-16 21:37:47 +08:00
Zhen Zhang c9efb12a8a
fix build problem by replace go dependency (#125)
Signed-off-by: shouchen.zz <shouchen.zz@gmail.com>
Co-authored-by: shouchen.zz <shouchen.zz@gmail.com>
2025-06-06 23:03:31 +08:00
dependabot[bot] 60858fed19
Bump golang.org/x/net in the go_modules group across 1 directory (#123)
Bumps the go_modules group with 1 update in the / directory: [golang.org/x/net](https://github.com/golang/net).


Updates `golang.org/x/net` from 0.33.0 to 0.38.0
- [Commits](https://github.com/golang/net/compare/v0.33.0...v0.38.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-version: 0.38.0
  dependency-type: indirect
  dependency-group: go_modules
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-15 16:00:11 +08:00
Vaibhav K f3a7f4bd33
add kubectl kruise get all command (#119)
* feat/cmd: add support for kruise get all command

Signed-off-by: Vaibhav <vaibhaavv8@gmail.com>

* add viewer for crr, cronjob, Resource Distribution, United Deployments, Broadcast

Signed-off-by: Vaibhav <vaibhaavv8@gmail.com>

* add viewer for sidecar, podprobe, imagepull, podBudget

Signed-off-by: Vaibhav <vaibhaavv8@gmail.com>

* fix golangci-lint

Signed-off-by: Vaibhav <vaibhaavv8@gmail.com>

---------

Signed-off-by: Vaibhav <vaibhaavv8@gmail.com>
2025-05-15 15:57:49 +08:00
Zhen Zhang b8db027748
update kruise-api to 1.8.0 (#124)
Signed-off-by: 守辰 <shouchen.zz@alibaba-inc.com>
2025-04-21 14:21:27 +08:00
Harkirat Singh 82ce71b931
feat: add support for blue-green in describe rollout (#122)
Signed-off-by: Harkirat Singh <multaniharry714@gmail.com>
2025-03-20 19:25:06 +08:00
Ai Ranthem 791f2b6075
Feature: rollout undo command supports fast rollback (#117)
* add rollout rollback command
* generate doc
* update ci
---------

Signed-off-by: AiRanthem <zhongtianyun.zty@alibaba-inc.com>
2025-03-12 19:30:07 +08:00
dependabot[bot] a4fc9a3051
Bump golang.org/x/net from 0.24.0 to 0.33.0 (#116)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.24.0 to 0.33.0.
- [Commits](https://github.com/golang/net/compare/v0.24.0...v0.33.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-10 16:29:09 +08:00
Ai Ranthem 355ed0a11a
can approve blue-green release (#115)
Signed-off-by: AiRanthem <zhongtianyun.zty@alibaba-inc.com>
2025-02-07 13:01:23 +08:00
Kiraat f422c7d1cd
feat: show pods related to current step of the Rollout in describe cmd (#111)
* feat: show pods related to current step of the Rollout in describe cmd

Signed-off-by: maanugh <manusin46@gmail.com>
2025-01-30 08:32:58 +08:00
myname4423 2d0a16f996
fix a rollout version bug (#113)
Signed-off-by: yunbo <yunbo10124scut@gmail.com>
Co-authored-by: yunbo <yunbo10124scut@gmail.com>
2024-12-09 14:55:15 +08:00
Kiraat 9d68939d6c
feat: add support for v1alpha1 resources (#112)
* feat: add support for v1alpha1 resources

Signed-off-by: maanugh <manusin46@gmail.com>
2024-11-26 09:54:59 +08:00
Kiraat 631fde0936
feat: add support for describe command (#96)
* feat: add support for rollout describe command

Signed-off-by: maanugh <manusin46@gmail.com>
2024-11-13 09:40:47 +08:00
hantmac cafa34158f fix 2024-11-11 09:38:37 +08:00
hantmac 6193994cfe fix 2024-11-11 09:38:37 +08:00
hantmac 7935dd511e fix 2024-11-11 09:38:37 +08:00
hantmac 33d8021ea2 fix: ci download sha256 file
Signed-off-by: hantmac <hantmac@outlook.com>
2024-11-11 09:38:37 +08:00
Jeremy 93a0cefcfd
fix: shasum file in release ci (#109) 2024-11-06 15:29:22 +08:00
75 changed files with 2806 additions and 230 deletions

View File

@ -12,48 +12,112 @@ on:
env:
# Common versions
GO_VERSION: '1.20'
GOLANGCI_VERSION: 'v1.51'
GO_VERSION: '1.23'
GOLANGCI_VERSION: 'v1.55.2'
jobs:
golangci-lint:
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: true
- name: Setup Go
uses: actions/setup-go@v2
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@v2
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: Lint golang code
uses: golangci/golangci-lint-action@v3.5.0
uses: golangci/golangci-lint-action@2226d7cb06a077cd73e56eedd38eecad18e5d837 # v6.5.0
with:
version: ${{ env.GOLANGCI_VERSION }}
args: --verbose
build-and-test:
name: ci-build
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: true
- name: Setup Go
uses: actions/setup-go@v2
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,111 +6,145 @@ on:
- created
env:
# Common versions
GO_VERSION: '1.20'
GO_VERSION: '1.22'
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
jobs:
build_and_upload:
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
strategy:
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:
GO_BUILD_ENV: GO111MODULE=on CGO_ENABLED=0
DIST_DIRS: find * -type d -exec
steps:
- uses: actions/checkout@v4
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0 # Needed for version.sh to work properly
- name: Setup Go
uses: actions/setup-go@v4
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
with:
go-version: ${{ env.GO_VERSION }}
- 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#*/}
cache: true # Enable built-in Go caching
- name: Get ldflags
id: get_ldflags
run: |
LDFLAGS=$(./version.sh)
echo "LDFLAGS=${LDFLAGS}" >> $GITHUB_ENV
- name: Build
echo "LDFLAGS=${LDFLAGS}" >> $GITHUB_OUTPUT
- name: Build kubectl-kruise
run: |
${{ 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 \
${{ 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' || '' }} \
./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=${{ 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 \
${{ 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' || '' }} \
./cmd/resourcedistributiongenerator/main.go
- name: Compress resourcedistribution-generator
- name: Package artifacts
run: |
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
# 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
with:
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: sha256sums
path: ./_bin/sha256-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.txt
name: sha256sums-${{ matrix.os }}-${{ matrix.arch }}
path: _bin/sha256-${{ matrix.os }}-${{ matrix.arch }}.txt
retention-days: 1
upload-sha256sums-plugin:
- 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
runs-on: ubuntu-latest
name: upload-sha256sums
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Get release
id: get_release
uses: bruceadams/get-release@v1.2.2
- name: Download sha256sums
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Download all artifacts
uses: actions/download-artifact@v4.1.7
with:
name: sha256sums
- shell: bash
pattern: "*"
merge-multiple: true
path: artifacts
- name: Prepare release assets
run: |
for file in *.txt
do
cat ${file} >> sha256sums.txt
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
- name: Upload Checksums
uses: actions/upload-release-asset@v1.0.2
# 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:
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
files: release-assets/*
fail_on_unmatched_files: true
- name: Update kubectl plugin version in krew-index
uses: rajatjindal/krew-release-bot@v0.0.43
uses: rajatjindal/krew-release-bot@v0.0.46

3
.nancy-ignore Normal file
View File

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

View File

@ -103,6 +103,9 @@ $ kubectl kruise rollout approve rollout/rollout-demo -n ns-demo`
# undo a kruise rollout resource
$ kubectl kruise rollout undo rollout/rollout-demo
# Fast rollback during blue-green release (will go back to a previous step with no traffic and most replicas)
$ kubectl kruise rollout undo rollout/rollout-demo --fast
```
### set
@ -195,6 +198,60 @@ 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

@ -24,6 +24,7 @@ kubectl-kruise [flags]
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--disable-compression If true, opt-out of response compression for all requests to the server
-h, --help help for kubectl-kruise
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
@ -44,9 +45,11 @@ kubectl-kruise [flags]
### SEE ALSO
* [kubectl-kruise create](kubectl-kruise_create.md) - Create a resource from a file or from stdin.
* [kubectl-kruise describe](kubectl-kruise_describe.md) - Show details of a specific resource or group of resources
* [kubectl-kruise expose](kubectl-kruise_expose.md) - Take a workload(e.g. deployment, cloneset), service or pod and expose it as a new Kubernetes Service
* [kubectl-kruise migrate](kubectl-kruise_migrate.md) - Migrate from K8s original workloads to Kruise workloads
* [kubectl-kruise rollout](kubectl-kruise_rollout.md) - Manage the rollout of a resource
* [kubectl-kruise scaledown](kubectl-kruise_scaledown.md) - Scaledown a cloneset with selective Pods
* [kubectl-kruise set](kubectl-kruise_set.md) - Set specific features on objects
###### Auto generated by spf13/cobra on 12-Mar-2025

View File

@ -42,7 +42,7 @@ kubectl-kruise create -f FILENAME
-l, --selector string Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)
--show-managed-fields If true, keep the managedFields when printing objects in JSON or YAML format.
--template string Template string or path to template file to use when -o=go-template, -o=go-template-file. The template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].
--validate string Must be one of: strict (or true), warn, ignore (or false).
--validate string[="strict"] Must be one of: strict (or true), warn, ignore (or false).
"true" or "strict" will use a schema to validate the input and fail the request if invalid. It will perform server side validation if ServerSideFieldValidation is enabled on the api-server, but will fall back to less reliable client-side validation if not.
"warn" will warn about unknown or duplicate fields without blocking the request if server-side field validation is enabled on the API server, and behave as "ignore" otherwise.
"false" or "ignore" will not perform any schema validation, silently dropping any unknown or duplicate fields. (default "strict")
@ -61,6 +61,7 @@ kubectl-kruise create -f FILENAME
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--disable-compression If true, opt-out of response compression for all requests to the server
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
--match-server-version Require server version to match client version
@ -84,3 +85,4 @@ kubectl-kruise create -f FILENAME
* [kubectl-kruise create broadcastJob](kubectl-kruise_create_broadcastJob.md) - Create a broadcastJob with the specified name.
* [kubectl-kruise create job](kubectl-kruise_create_job.md) - Create a job with the specified name.
###### Auto generated by spf13/cobra on 12-Mar-2025

View File

@ -45,7 +45,7 @@ kubectl-kruise create ContainerRecreateRequest NAME --pod=podName [--containers=
--show-managed-fields If true, keep the managedFields when printing objects in JSON or YAML format.
--template string Template string or path to template file to use when -o=go-template, -o=go-template-file. The template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].
-u, --unreadyGracePeriodSeconds int UnreadyGracePeriodSeconds is the optional duration in seconds to mark Pod as not ready over this duration before executing preStop hook and stopping the container
--validate string Must be one of: strict (or true), warn, ignore (or false).
--validate string[="strict"] Must be one of: strict (or true), warn, ignore (or false).
"true" or "strict" will use a schema to validate the input and fail the request if invalid. It will perform server side validation if ServerSideFieldValidation is enabled on the api-server, but will fall back to less reliable client-side validation if not.
"warn" will warn about unknown or duplicate fields without blocking the request if server-side field validation is enabled on the API server, and behave as "ignore" otherwise.
"false" or "ignore" will not perform any schema validation, silently dropping any unknown or duplicate fields. (default "strict")
@ -63,6 +63,7 @@ kubectl-kruise create ContainerRecreateRequest NAME --pod=podName [--containers=
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--disable-compression If true, opt-out of response compression for all requests to the server
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
--match-server-version Require server version to match client version
@ -83,3 +84,4 @@ kubectl-kruise create ContainerRecreateRequest NAME --pod=podName [--containers=
* [kubectl-kruise create](kubectl-kruise_create.md) - Create a resource from a file or from stdin.
###### Auto generated by spf13/cobra on 12-Mar-2025

View File

@ -36,7 +36,7 @@ kubectl-kruise create broadcastJob NAME --image=image [--from=cronjob/name] -- [
--save-config If true, the configuration of current object will be saved in its annotation. Otherwise, the annotation will be unchanged. This flag is useful when you want to perform kubectl apply on this object in the future.
--show-managed-fields If true, keep the managedFields when printing objects in JSON or YAML format.
--template string Template string or path to template file to use when -o=go-template, -o=go-template-file. The template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].
--validate string Must be one of: strict (or true), warn, ignore (or false).
--validate string[="strict"] Must be one of: strict (or true), warn, ignore (or false).
"true" or "strict" will use a schema to validate the input and fail the request if invalid. It will perform server side validation if ServerSideFieldValidation is enabled on the api-server, but will fall back to less reliable client-side validation if not.
"warn" will warn about unknown or duplicate fields without blocking the request if server-side field validation is enabled on the API server, and behave as "ignore" otherwise.
"false" or "ignore" will not perform any schema validation, silently dropping any unknown or duplicate fields. (default "strict")
@ -54,6 +54,7 @@ kubectl-kruise create broadcastJob NAME --image=image [--from=cronjob/name] -- [
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--disable-compression If true, opt-out of response compression for all requests to the server
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
--match-server-version Require server version to match client version
@ -74,3 +75,4 @@ kubectl-kruise create broadcastJob NAME --image=image [--from=cronjob/name] -- [
* [kubectl-kruise create](kubectl-kruise_create.md) - Create a resource from a file or from stdin.
###### Auto generated by spf13/cobra on 12-Mar-2025

View File

@ -36,7 +36,7 @@ kubectl-kruise create job NAME --image=image [--from=cronjob/name] -- [COMMAND]
--save-config If true, the configuration of current object will be saved in its annotation. Otherwise, the annotation will be unchanged. This flag is useful when you want to perform kubectl apply on this object in the future.
--show-managed-fields If true, keep the managedFields when printing objects in JSON or YAML format.
--template string Template string or path to template file to use when -o=go-template, -o=go-template-file. The template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].
--validate string Must be one of: strict (or true), warn, ignore (or false).
--validate string[="strict"] Must be one of: strict (or true), warn, ignore (or false).
"true" or "strict" will use a schema to validate the input and fail the request if invalid. It will perform server side validation if ServerSideFieldValidation is enabled on the api-server, but will fall back to less reliable client-side validation if not.
"warn" will warn about unknown or duplicate fields without blocking the request if server-side field validation is enabled on the API server, and behave as "ignore" otherwise.
"false" or "ignore" will not perform any schema validation, silently dropping any unknown or duplicate fields. (default "strict")
@ -54,6 +54,7 @@ kubectl-kruise create job NAME --image=image [--from=cronjob/name] -- [COMMAND]
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--disable-compression If true, opt-out of response compression for all requests to the server
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
--match-server-version Require server version to match client version
@ -74,3 +75,4 @@ kubectl-kruise create job NAME --image=image [--from=cronjob/name] -- [COMMAND]
* [kubectl-kruise create](kubectl-kruise_create.md) - Create a resource from a file or from stdin.
###### Auto generated by spf13/cobra on 12-Mar-2025

View File

@ -0,0 +1,60 @@
## kubectl-kruise describe
Show details of a specific resource or group of resources
### Synopsis
Show details of a rollout.
```
kubectl-kruise describe SUBCOMMAND
```
### Examples
```
# Describe the rollout named rollout-demo
kubectl-kruise describe rollout rollout-demo
```
### Options
```
-h, --help help for describe
```
### Options inherited from parent commands
```
--as string Username to impersonate for the operation. User could be a regular user or a service account in a namespace.
--as-group stringArray Group to impersonate for the operation, this flag can be repeated to specify multiple groups.
--as-uid string UID to impersonate for the operation.
--cache-dir string Default cache directory (default "$HOME/.kube/cache")
--certificate-authority string Path to a cert file for the certificate authority
--client-certificate string Path to a client certificate file for TLS
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--disable-compression If true, opt-out of response compression for all requests to the server
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
--match-server-version Require server version to match client version
-n, --namespace string If present, the namespace scope for this CLI request
--password string Password for basic authentication to the API server
--profile string Name of profile to capture. One of (none|cpu|heap|goroutine|threadcreate|block|mutex) (default "none")
--profile-output string Name of the file to write the profile to (default "profile.pprof")
--request-timeout string The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests. (default "0")
-s, --server string The address and port of the Kubernetes API server
--tls-server-name string Server name to use for server certificate validation. If it is not provided, the hostname used to contact the server is used
--token string Bearer token for authentication to the API server
--user string The name of the kubeconfig user to use
--username string Username for basic authentication to the API server
--warnings-as-errors Treat warnings received from the server as errors and exit with a non-zero exit code
```
### SEE ALSO
* [kubectl-kruise](kubectl-kruise.md) - kubectl-kruise controls the OpenKruise CRs
* [kubectl-kruise describe rollout](kubectl-kruise_describe_rollout.md) - Get details about a rollout
###### Auto generated by spf13/cobra on 12-Mar-2025

View File

@ -0,0 +1,66 @@
## kubectl-kruise describe rollout
Get details about a rollout
### Synopsis
Get details about and visual representation of a rollout.
```
kubectl-kruise describe rollout SUBCOMMAND
```
### Examples
```
# Describe the rollout named rollout-demo within namespace default
kubectl-kruise describe rollout rollout-demo/default
# Watch for changes to the rollout named rollout-demo
kubectl-kruise describe rollout rollout-demo/default -w
```
### Options
```
--all Show all pods in the rollout
-h, --help help for rollout
--no-color If true, print output without color
--timeout int Timeout after specified seconds
-w, --watch Watch for changes to the rollout
```
### Options inherited from parent commands
```
--as string Username to impersonate for the operation. User could be a regular user or a service account in a namespace.
--as-group stringArray Group to impersonate for the operation, this flag can be repeated to specify multiple groups.
--as-uid string UID to impersonate for the operation.
--cache-dir string Default cache directory (default "$HOME/.kube/cache")
--certificate-authority string Path to a cert file for the certificate authority
--client-certificate string Path to a client certificate file for TLS
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--disable-compression If true, opt-out of response compression for all requests to the server
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
--match-server-version Require server version to match client version
-n, --namespace string If present, the namespace scope for this CLI request
--password string Password for basic authentication to the API server
--profile string Name of profile to capture. One of (none|cpu|heap|goroutine|threadcreate|block|mutex) (default "none")
--profile-output string Name of the file to write the profile to (default "profile.pprof")
--request-timeout string The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests. (default "0")
-s, --server string The address and port of the Kubernetes API server
--tls-server-name string Server name to use for server certificate validation. If it is not provided, the hostname used to contact the server is used
--token string Bearer token for authentication to the API server
--user string The name of the kubeconfig user to use
--username string Username for basic authentication to the API server
--warnings-as-errors Treat warnings received from the server as errors and exit with a non-zero exit code
```
### SEE ALSO
* [kubectl-kruise describe](kubectl-kruise_describe.md) - Show details of a specific resource or group of resources
###### Auto generated by spf13/cobra on 12-Mar-2025

View File

@ -85,6 +85,7 @@ kubectl-kruise expose (-f FILENAME | TYPE NAME) [--port=port] [--protocol=TCP|UD
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--disable-compression If true, opt-out of response compression for all requests to the server
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
--match-server-version Require server version to match client version
@ -105,3 +106,4 @@ kubectl-kruise expose (-f FILENAME | TYPE NAME) [--port=port] [--protocol=TCP|UD
* [kubectl-kruise](kubectl-kruise.md) - kubectl-kruise controls the OpenKruise CRs
###### Auto generated by spf13/cobra on 12-Mar-2025

View File

@ -51,6 +51,7 @@ kubectl-kruise migrate [DST_KIND] --from [SRC_KIND] [flags]
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--disable-compression If true, opt-out of response compression for all requests to the server
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
--match-server-version Require server version to match client version
@ -71,3 +72,4 @@ kubectl-kruise migrate [DST_KIND] --from [SRC_KIND] [flags]
* [kubectl-kruise](kubectl-kruise.md) - kubectl-kruise controls the OpenKruise CRs
###### Auto generated by spf13/cobra on 12-Mar-2025

View File

@ -5,16 +5,16 @@ Manage the rollout of a resource
### Synopsis
Manage the rollout of a resource.
Valid resource types include:
* deployments
* daemonsets
* statefulsets
* clonesets
* statefulsets.apps.kruise.io
* daemonsets.apps.kruise.io
* rollouts.rollouts.kruise.io
* deployments
* daemonsets
* statefulsets
* clonesets
* statefulsets.apps.kruise.io
* daemonsets.apps.kruise.io
* rollouts.rollouts.kruise.io
```
kubectl-kruise rollout SUBCOMMAND
@ -48,6 +48,7 @@ kubectl-kruise rollout SUBCOMMAND
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--disable-compression If true, opt-out of response compression for all requests to the server
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
--match-server-version Require server version to match client version
@ -75,3 +76,4 @@ kubectl-kruise rollout SUBCOMMAND
* [kubectl-kruise rollout status](kubectl-kruise_rollout_status.md) - Show the status of the rollout
* [kubectl-kruise rollout undo](kubectl-kruise_rollout_undo.md) - Undo a previous rollout
###### Auto generated by spf13/cobra on 12-Mar-2025

View File

@ -17,7 +17,7 @@ kubectl-kruise rollout approve RESOURCE
```
# approve a kruise rollout resource named "rollout-demo" in "ns-demo" namespace
kubectl-kruise rollout approve rollout-demo -n ns-demo
kubectl-kruise rollout approve rollout/rollout-demo -n ns-demo
```
### Options
@ -45,6 +45,7 @@ kubectl-kruise rollout approve RESOURCE
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--disable-compression If true, opt-out of response compression for all requests to the server
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
--match-server-version Require server version to match client version
@ -65,3 +66,4 @@ kubectl-kruise rollout approve RESOURCE
* [kubectl-kruise rollout](kubectl-kruise_rollout.md) - Manage the rollout of a resource
###### Auto generated by spf13/cobra on 12-Mar-2025

View File

@ -49,6 +49,7 @@ kubectl-kruise rollout history (TYPE NAME | TYPE/NAME) [flags]
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--disable-compression If true, opt-out of response compression for all requests to the server
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
--match-server-version Require server version to match client version
@ -69,3 +70,4 @@ kubectl-kruise rollout history (TYPE NAME | TYPE/NAME) [flags]
* [kubectl-kruise rollout](kubectl-kruise_rollout.md) - Manage the rollout of a resource
###### Auto generated by spf13/cobra on 12-Mar-2025

View File

@ -47,6 +47,7 @@ kubectl-kruise rollout pause RESOURCE
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--disable-compression If true, opt-out of response compression for all requests to the server
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
--match-server-version Require server version to match client version
@ -67,3 +68,4 @@ kubectl-kruise rollout pause RESOURCE
* [kubectl-kruise rollout](kubectl-kruise_rollout.md) - Manage the rollout of a resource
###### Auto generated by spf13/cobra on 12-Mar-2025

View File

@ -6,7 +6,8 @@ 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
@ -21,6 +22,9 @@ 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
@ -48,6 +52,7 @@ kubectl-kruise rollout restart RESOURCE
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--disable-compression If true, opt-out of response compression for all requests to the server
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
--match-server-version Require server version to match client version
@ -68,3 +73,4 @@ kubectl-kruise rollout restart RESOURCE
* [kubectl-kruise rollout](kubectl-kruise_rollout.md) - Manage the rollout of a resource
###### Auto generated by spf13/cobra on 12-Mar-2025

View File

@ -47,6 +47,7 @@ kubectl-kruise rollout resume RESOURCE
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--disable-compression If true, opt-out of response compression for all requests to the server
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
--match-server-version Require server version to match client version
@ -67,3 +68,4 @@ kubectl-kruise rollout resume RESOURCE
* [kubectl-kruise rollout](kubectl-kruise_rollout.md) - Manage the rollout of a resource
###### Auto generated by spf13/cobra on 12-Mar-2025

View File

@ -50,6 +50,7 @@ kubectl-kruise rollout status (TYPE NAME | TYPE/NAME) [flags]
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--disable-compression If true, opt-out of response compression for all requests to the server
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
--match-server-version Require server version to match client version
@ -70,3 +71,4 @@ kubectl-kruise rollout status (TYPE NAME | TYPE/NAME) [flags]
* [kubectl-kruise rollout](kubectl-kruise_rollout.md) - Manage the rollout of a resource
###### Auto generated by spf13/cobra on 12-Mar-2025

View File

@ -27,6 +27,9 @@ kubectl-kruise rollout undo (TYPE NAME | TYPE/NAME) [flags]
# Rollback to workload via rollout api object
kubectl-kruise rollout undo rollout/abc
# Fast rollback during blue-green release (will go back to a previous step with no traffic and most replicas)
kubectl-kruise rollout undo rollout/abc --fast
```
### Options
@ -34,6 +37,7 @@ kubectl-kruise rollout undo (TYPE NAME | TYPE/NAME) [flags]
```
--allow-missing-template-keys If true, ignore any errors in templates when a field or map key is missing in the template. Only applies to golang and jsonpath output formats. (default true)
--dry-run string[="unchanged"] Must be "none", "server", or "client". If client strategy, only print the object that would be sent, without sending it. If server strategy, submit server-side request without persisting the resource. (default "none")
--fast fast rollback for blue-green release
-f, --filename strings Filename, directory, or URL to files identifying the resource to get from a server.
-h, --help help for undo
-k, --kustomize string Process the kustomization directory. This flag can't be used together with -f or -R.
@ -56,6 +60,7 @@ kubectl-kruise rollout undo (TYPE NAME | TYPE/NAME) [flags]
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--disable-compression If true, opt-out of response compression for all requests to the server
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
--match-server-version Require server version to match client version
@ -76,3 +81,4 @@ kubectl-kruise rollout undo (TYPE NAME | TYPE/NAME) [flags]
* [kubectl-kruise rollout](kubectl-kruise_rollout.md) - Manage the rollout of a resource
###### Auto generated by spf13/cobra on 12-Mar-2025

View File

@ -38,6 +38,7 @@ kubectl-kruise scaledown [CLONESET] --pods [POD1,POD2] -n [NAMESPACE]
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--disable-compression If true, opt-out of response compression for all requests to the server
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
--match-server-version Require server version to match client version
@ -58,3 +59,4 @@ kubectl-kruise scaledown [CLONESET] --pods [POD1,POD2] -n [NAMESPACE]
* [kubectl-kruise](kubectl-kruise.md) - kubectl-kruise controls the OpenKruise CRs
###### Auto generated by spf13/cobra on 12-Mar-2025

View File

@ -30,6 +30,7 @@ kubectl-kruise set SUBCOMMAND
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--disable-compression If true, opt-out of response compression for all requests to the server
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
--match-server-version Require server version to match client version
@ -56,3 +57,4 @@ kubectl-kruise set SUBCOMMAND
* [kubectl-kruise set serviceaccount](kubectl-kruise_set_serviceaccount.md) - Update ServiceAccount of a resource
* [kubectl-kruise set subject](kubectl-kruise_set_subject.md) - Update User, Group or ServiceAccount in a RoleBinding/ClusterRoleBinding
###### Auto generated by spf13/cobra on 12-Mar-2025

View File

@ -12,7 +12,7 @@ Update environment variables on a pod template.
Possible resources include (case insensitive):
pod (po), deployment (deploy), statefulset (sts), daemonset (ds), replicaset (rs), cloneset (clone), statefulset.apps.kruise.io (asts), daemonset.apps.kruise.io (ads)
pod (po), deployment (deploy), statefulset (sts), daemonset (ds), replicaset (rs), cloneset (clone), statefulset.apps.kruise.io (asts), daemonset.apps.kruise.io (ads)
```
kubectl-kruise set env RESOURCE/NAME KEY_1=VAL_1 ... KEY_N=VAL_N
@ -93,6 +93,7 @@ kubectl-kruise set env RESOURCE/NAME KEY_1=VAL_1 ... KEY_N=VAL_N
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--disable-compression If true, opt-out of response compression for all requests to the server
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
--match-server-version Require server version to match client version
@ -113,3 +114,4 @@ kubectl-kruise set env RESOURCE/NAME KEY_1=VAL_1 ... KEY_N=VAL_N
* [kubectl-kruise set](kubectl-kruise_set.md) - Set specific features on objects
###### Auto generated by spf13/cobra on 12-Mar-2025

View File

@ -8,7 +8,7 @@ Update existing container image(s) of resources.
Possible resources include (case insensitive):
pod (po), deployment (deploy), statefulset (sts), daemonset (ds), replicaset (rs), cloneset (clone), statefulset.apps.kruise.io (asts), daemonset.apps.kruise.io (ads)
pod (po), deployment (deploy), statefulset (sts), daemonset (ds), replicaset (rs), cloneset (clone), statefulset.apps.kruise.io (asts), daemonset.apps.kruise.io (ads)
```
kubectl-kruise set image (-f FILENAME | TYPE NAME) CONTAINER_NAME_1=CONTAINER_IMAGE_1 ... CONTAINER_NAME_N=CONTAINER_IMAGE_N
@ -59,6 +59,7 @@ kubectl-kruise set image (-f FILENAME | TYPE NAME) CONTAINER_NAME_1=CONTAINER_IM
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--disable-compression If true, opt-out of response compression for all requests to the server
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
--match-server-version Require server version to match client version
@ -79,3 +80,4 @@ kubectl-kruise set image (-f FILENAME | TYPE NAME) CONTAINER_NAME_1=CONTAINER_IM
* [kubectl-kruise set](kubectl-kruise_set.md) - Set specific features on objects
###### Auto generated by spf13/cobra on 12-Mar-2025

View File

@ -10,7 +10,7 @@ Specify compute resource requirements (cpu, memory) for any resource that define
Possible resources include (case insensitive):
pod (po), deployment (deploy), statefulset (sts), daemonset (ds), replicaset (rs), cloneset (clone), statefulset.apps.kruise.io (asts), daemonset.apps.kruise.io (ads)
pod (po), deployment (deploy), statefulset (sts), daemonset (ds), replicaset (rs), cloneset (clone), statefulset.apps.kruise.io (asts), daemonset.apps.kruise.io (ads)
```
kubectl-kruise set resources (-f FILENAME | TYPE NAME) ([--limits=LIMITS & --requests=REQUESTS]
@ -64,6 +64,7 @@ kubectl-kruise set resources (-f FILENAME | TYPE NAME) ([--limits=LIMITS & --re
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--disable-compression If true, opt-out of response compression for all requests to the server
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
--match-server-version Require server version to match client version
@ -84,3 +85,4 @@ kubectl-kruise set resources (-f FILENAME | TYPE NAME) ([--limits=LIMITS & --re
* [kubectl-kruise set](kubectl-kruise_set.md) - Set specific features on objects
###### Auto generated by spf13/cobra on 12-Mar-2025

View File

@ -6,7 +6,7 @@ Set the selector on a resource
Set the selector on a resource. Note that the new selector will overwrite the old selector if the resource had one prior to the invocation of 'set selector'.
A selector must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to 63 characters. If --resource-version is specified, then updates will use this resource version, otherwise the existing resource-version will be used. Note: currently selectors can only be set on Service objects.
A selector must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to 63 characters. If --resource-version is specified, then updates will use this resource version, otherwise the existing resource-version will be used. Note: currently selectors can only be set on Service objects.
```
kubectl-kruise set selector (-f FILENAME | TYPE NAME) EXPRESSIONS [--resource-version=version]
@ -48,6 +48,7 @@ kubectl-kruise set selector (-f FILENAME | TYPE NAME) EXPRESSIONS [--resource-ve
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--disable-compression If true, opt-out of response compression for all requests to the server
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
--match-server-version Require server version to match client version
@ -68,3 +69,4 @@ kubectl-kruise set selector (-f FILENAME | TYPE NAME) EXPRESSIONS [--resource-ve
* [kubectl-kruise set](kubectl-kruise_set.md) - Set specific features on objects
###### Auto generated by spf13/cobra on 12-Mar-2025

View File

@ -52,6 +52,7 @@ kubectl-kruise set serviceaccount (-f FILENAME | TYPE NAME) SERVICE_ACCOUNT
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--disable-compression If true, opt-out of response compression for all requests to the server
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
--match-server-version Require server version to match client version
@ -72,3 +73,4 @@ kubectl-kruise set serviceaccount (-f FILENAME | TYPE NAME) SERVICE_ACCOUNT
* [kubectl-kruise set](kubectl-kruise_set.md) - Set specific features on objects
###### Auto generated by spf13/cobra on 12-Mar-2025

View File

@ -55,6 +55,7 @@ kubectl-kruise set subject (-f FILENAME | TYPE NAME) [--user=username] [--group=
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--disable-compression If true, opt-out of response compression for all requests to the server
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
--match-server-version Require server version to match client version
@ -74,3 +75,4 @@ kubectl-kruise set subject (-f FILENAME | TYPE NAME) [--user=username] [--group=
* [kubectl-kruise set](kubectl-kruise_set.md) - Set specific features on objects
###### Auto generated by spf13/cobra on 12-Mar-2025

View File

@ -28,6 +28,10 @@ options:
usage: The name of the kubeconfig cluster to use
- name: context
usage: The name of the kubeconfig context to use
- name: disable-compression
default_value: "false"
usage: |
If true, opt-out of response compression for all requests to the server
- name: help
shorthand: h
default_value: "false"
@ -75,6 +79,7 @@ options:
Treat warnings received from the server as errors and exit with a non-zero exit code
see_also:
- kubectl-kruise create - Create a resource from a file or from stdin.
- kubectl-kruise describe - Show details of a specific resource or group of resources
- kubectl-kruise expose - Take a workload(e.g. deployment, cloneset), service or pod and expose it as a new Kubernetes Service
- kubectl-kruise migrate - Migrate from K8s original workloads to Kruise workloads
- kubectl-kruise rollout - Manage the rollout of a resource

View File

@ -98,6 +98,10 @@ inherited_options:
usage: The name of the kubeconfig cluster to use
- name: context
usage: The name of the kubeconfig context to use
- name: disable-compression
default_value: "false"
usage: |
If true, opt-out of response compression for all requests to the server
- name: insecure-skip-tls-verify
default_value: "false"
usage: |

View File

@ -79,6 +79,10 @@ inherited_options:
usage: The name of the kubeconfig cluster to use
- name: context
usage: The name of the kubeconfig context to use
- name: disable-compression
default_value: "false"
usage: |
If true, opt-out of response compression for all requests to the server
- name: insecure-skip-tls-verify
default_value: "false"
usage: |

View File

@ -68,6 +68,10 @@ inherited_options:
usage: The name of the kubeconfig cluster to use
- name: context
usage: The name of the kubeconfig context to use
- name: disable-compression
default_value: "false"
usage: |
If true, opt-out of response compression for all requests to the server
- name: insecure-skip-tls-verify
default_value: "false"
usage: |

View File

@ -68,6 +68,10 @@ inherited_options:
usage: The name of the kubeconfig cluster to use
- name: context
usage: The name of the kubeconfig context to use
- name: disable-compression
default_value: "false"
usage: |
If true, opt-out of response compression for all requests to the server
- name: insecure-skip-tls-verify
default_value: "false"
usage: |

View File

@ -0,0 +1,83 @@
name: kubectl-kruise describe
synopsis: Show details of a specific resource or group of resources
description: Show details of a rollout.
usage: kubectl-kruise describe SUBCOMMAND
options:
- name: help
shorthand: h
default_value: "false"
usage: help for describe
inherited_options:
- name: as
usage: |
Username to impersonate for the operation. User could be a regular user or a service account in a namespace.
- name: as-group
default_value: '[]'
usage: |
Group to impersonate for the operation, this flag can be repeated to specify multiple groups.
- name: as-uid
usage: UID to impersonate for the operation.
- name: cache-dir
default_value: $HOME/.kube/cache
usage: Default cache directory
- name: certificate-authority
usage: Path to a cert file for the certificate authority
- name: client-certificate
usage: Path to a client certificate file for TLS
- name: client-key
usage: Path to a client key file for TLS
- name: cluster
usage: The name of the kubeconfig cluster to use
- name: context
usage: The name of the kubeconfig context to use
- name: disable-compression
default_value: "false"
usage: |
If true, opt-out of response compression for all requests to the server
- name: insecure-skip-tls-verify
default_value: "false"
usage: |
If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
- name: kubeconfig
usage: Path to the kubeconfig file to use for CLI requests.
- name: match-server-version
default_value: "false"
usage: Require server version to match client version
- name: namespace
shorthand: "n"
usage: If present, the namespace scope for this CLI request
- name: password
usage: Password for basic authentication to the API server
- name: profile
default_value: none
usage: |
Name of profile to capture. One of (none|cpu|heap|goroutine|threadcreate|block|mutex)
- name: profile-output
default_value: profile.pprof
usage: Name of the file to write the profile to
- name: request-timeout
default_value: "0"
usage: |
The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests.
- name: server
shorthand: s
usage: The address and port of the Kubernetes API server
- name: tls-server-name
usage: |
Server name to use for server certificate validation. If it is not provided, the hostname used to contact the server is used
- name: token
usage: Bearer token for authentication to the API server
- name: user
usage: The name of the kubeconfig user to use
- name: username
usage: Username for basic authentication to the API server
- name: warnings-as-errors
default_value: "false"
usage: |
Treat warnings received from the server as errors and exit with a non-zero exit code
example: |4-
# Describe the rollout named rollout-demo
kubectl-kruise describe rollout rollout-demo
see_also:
- kubectl-kruise - kubectl-kruise controls the OpenKruise CRs
- kubectl-kruise describe rollout - Get details about a rollout

View File

@ -0,0 +1,93 @@
name: kubectl-kruise describe rollout
synopsis: Get details about a rollout
description: Get details about and visual representation of a rollout.
usage: kubectl-kruise describe rollout SUBCOMMAND
options:
- name: all
default_value: "false"
usage: Show all pods in the rollout
- name: help
shorthand: h
default_value: "false"
usage: help for rollout
- name: no-color
default_value: "false"
usage: If true, print output without color
- name: timeout
default_value: "0"
usage: Timeout after specified seconds
- name: watch
shorthand: w
default_value: "false"
usage: Watch for changes to the rollout
inherited_options:
- name: as
usage: |
Username to impersonate for the operation. User could be a regular user or a service account in a namespace.
- name: as-group
default_value: '[]'
usage: |
Group to impersonate for the operation, this flag can be repeated to specify multiple groups.
- name: as-uid
usage: UID to impersonate for the operation.
- name: cache-dir
default_value: $HOME/.kube/cache
usage: Default cache directory
- name: certificate-authority
usage: Path to a cert file for the certificate authority
- name: client-certificate
usage: Path to a client certificate file for TLS
- name: client-key
usage: Path to a client key file for TLS
- name: cluster
usage: The name of the kubeconfig cluster to use
- name: context
usage: The name of the kubeconfig context to use
- name: disable-compression
default_value: "false"
usage: |
If true, opt-out of response compression for all requests to the server
- name: insecure-skip-tls-verify
default_value: "false"
usage: |
If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
- name: kubeconfig
usage: Path to the kubeconfig file to use for CLI requests.
- name: match-server-version
default_value: "false"
usage: Require server version to match client version
- name: namespace
shorthand: "n"
usage: If present, the namespace scope for this CLI request
- name: password
usage: Password for basic authentication to the API server
- name: profile
default_value: none
usage: |
Name of profile to capture. One of (none|cpu|heap|goroutine|threadcreate|block|mutex)
- name: profile-output
default_value: profile.pprof
usage: Name of the file to write the profile to
- name: request-timeout
default_value: "0"
usage: |
The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests.
- name: server
shorthand: s
usage: The address and port of the Kubernetes API server
- name: tls-server-name
usage: |
Server name to use for server certificate validation. If it is not provided, the hostname used to contact the server is used
- name: token
usage: Bearer token for authentication to the API server
- name: user
usage: The name of the kubeconfig user to use
- name: username
usage: Username for basic authentication to the API server
- name: warnings-as-errors
default_value: "false"
usage: |
Treat warnings received from the server as errors and exit with a non-zero exit code
example: " # Describe the rollout named rollout-demo within namespace default\n kubectl-kruise describe rollout rollout-demo/default\n \n # Watch for changes to the rollout named rollout-demo\n kubectl-kruise describe rollout rollout-demo/default -w"
see_also:
- kubectl-kruise describe - Show details of a specific resource or group of resources

View File

@ -123,6 +123,10 @@ inherited_options:
usage: The name of the kubeconfig cluster to use
- name: context
usage: The name of the kubeconfig context to use
- name: disable-compression
default_value: "false"
usage: |
If true, opt-out of response compression for all requests to the server
- name: insecure-skip-tls-verify
default_value: "false"
usage: |

View File

@ -52,6 +52,10 @@ inherited_options:
usage: The name of the kubeconfig cluster to use
- name: context
usage: The name of the kubeconfig context to use
- name: disable-compression
default_value: "false"
usage: |
If true, opt-out of response compression for all requests to the server
- name: insecure-skip-tls-verify
default_value: "false"
usage: |

View File

@ -1,6 +1,6 @@
name: kubectl-kruise rollout
synopsis: Manage the rollout of a resource
description: "Manage the rollout of a resource.\n \n Valid resource types include:\n\n * deployments\n * daemonsets\n * statefulsets\n * clonesets\n * statefulsets.apps.kruise.io\n * daemonsets.apps.kruise.io\n * rollouts.rollouts.kruise.io"
description: "Manage the rollout of a resource.\n \n Valid resource types include:\n\n * deployments\n * daemonsets\n * statefulsets\n * clonesets\n * statefulsets.apps.kruise.io\n * daemonsets.apps.kruise.io\n * rollouts.rollouts.kruise.io"
usage: kubectl-kruise rollout SUBCOMMAND
options:
- name: help
@ -30,6 +30,10 @@ inherited_options:
usage: The name of the kubeconfig cluster to use
- name: context
usage: The name of the kubeconfig context to use
- name: disable-compression
default_value: "false"
usage: |
If true, opt-out of response compression for all requests to the server
- name: insecure-skip-tls-verify
default_value: "false"
usage: |

View File

@ -62,6 +62,10 @@ inherited_options:
usage: The name of the kubeconfig cluster to use
- name: context
usage: The name of the kubeconfig context to use
- name: disable-compression
default_value: "false"
usage: |
If true, opt-out of response compression for all requests to the server
- name: insecure-skip-tls-verify
default_value: "false"
usage: |
@ -103,6 +107,6 @@ inherited_options:
default_value: "false"
usage: |
Treat warnings received from the server as errors and exit with a non-zero exit code
example: " # approve a kruise rollout resource named \"rollout-demo\" in \"ns-demo\" namespace\n \n kubectl-kruise rollout approve rollout-demo -n ns-demo"
example: " # approve a kruise rollout resource named \"rollout-demo\" in \"ns-demo\" namespace\n \n kubectl-kruise rollout approve rollout/rollout-demo -n ns-demo"
see_also:
- kubectl-kruise rollout - Manage the rollout of a resource

View File

@ -63,6 +63,10 @@ inherited_options:
usage: The name of the kubeconfig cluster to use
- name: context
usage: The name of the kubeconfig context to use
- name: disable-compression
default_value: "false"
usage: |
If true, opt-out of response compression for all requests to the server
- name: insecure-skip-tls-verify
default_value: "false"
usage: |

View File

@ -62,6 +62,10 @@ inherited_options:
usage: The name of the kubeconfig cluster to use
- name: context
usage: The name of the kubeconfig context to use
- name: disable-compression
default_value: "false"
usage: |
If true, opt-out of response compression for all requests to the server
- name: insecure-skip-tls-verify
default_value: "false"
usage: |

View File

@ -3,7 +3,7 @@ synopsis: Restart a resource
description: |-
Restart a resource.
Resource will be rollout restarted.
Resource will be rollout restarted.
usage: kubectl-kruise rollout restart RESOURCE
options:
- name: allow-missing-template-keys
@ -62,6 +62,10 @@ inherited_options:
usage: The name of the kubeconfig cluster to use
- name: context
usage: The name of the kubeconfig context to use
- name: disable-compression
default_value: "false"
usage: |
If true, opt-out of response compression for all requests to the server
- name: insecure-skip-tls-verify
default_value: "false"
usage: |

View File

@ -62,6 +62,10 @@ inherited_options:
usage: The name of the kubeconfig cluster to use
- name: context
usage: The name of the kubeconfig context to use
- name: disable-compression
default_value: "false"
usage: |
If true, opt-out of response compression for all requests to the server
- name: insecure-skip-tls-verify
default_value: "false"
usage: |

View File

@ -63,6 +63,10 @@ inherited_options:
usage: The name of the kubeconfig cluster to use
- name: context
usage: The name of the kubeconfig context to use
- name: disable-compression
default_value: "false"
usage: |
If true, opt-out of response compression for all requests to the server
- name: insecure-skip-tls-verify
default_value: "false"
usage: |

View File

@ -11,6 +11,9 @@ options:
default_value: none
usage: |
Must be "none", "server", or "client". If client strategy, only print the object that would be sent, without sending it. If server strategy, submit server-side request without persisting the resource.
- name: fast
default_value: "false"
usage: fast rollback for blue-green release
- name: filename
shorthand: f
default_value: '[]'
@ -66,6 +69,10 @@ inherited_options:
usage: The name of the kubeconfig cluster to use
- name: context
usage: The name of the kubeconfig context to use
- name: disable-compression
default_value: "false"
usage: |
If true, opt-out of response compression for all requests to the server
- name: insecure-skip-tls-verify
default_value: "false"
usage: |
@ -107,6 +114,6 @@ inherited_options:
default_value: "false"
usage: |
Treat warnings received from the server as errors and exit with a non-zero exit code
example: " # Rollback to the previous cloneset\n kubectl-kruise rollout undo cloneset/abc\n \n # Rollback to the previous Advanced StatefulSet\n kubectl-kruise rollout undo asts/abc\n \n # Rollback to daemonset revision 3\n kubectl-kruise rollout undo daemonset/abc --to-revision=3\n \n # Rollback to the previous deployment with dry-run\n kubectl-kruise rollout undo --dry-run=server deployment/abc\n \n # Rollback to workload via rollout api object\n kubectl-kruise rollout undo rollout/abc"
example: " # Rollback to the previous cloneset\n kubectl-kruise rollout undo cloneset/abc\n \n # Rollback to the previous Advanced StatefulSet\n kubectl-kruise rollout undo asts/abc\n \n # Rollback to daemonset revision 3\n kubectl-kruise rollout undo daemonset/abc --to-revision=3\n \n # Rollback to the previous deployment with dry-run\n kubectl-kruise rollout undo --dry-run=server deployment/abc\n \n # Rollback to workload via rollout api object\n kubectl-kruise rollout undo rollout/abc\n \n # Fast rollback during blue-green release (will go back to a previous step with no traffic and most replicas)\n kubectl-kruise rollout undo rollout/abc --fast"
see_also:
- kubectl-kruise rollout - Manage the rollout of a resource

View File

@ -32,6 +32,10 @@ inherited_options:
usage: The name of the kubeconfig cluster to use
- name: context
usage: The name of the kubeconfig context to use
- name: disable-compression
default_value: "false"
usage: |
If true, opt-out of response compression for all requests to the server
- name: insecure-skip-tls-verify
default_value: "false"
usage: |

View File

@ -33,6 +33,10 @@ inherited_options:
usage: The name of the kubeconfig cluster to use
- name: context
usage: The name of the kubeconfig context to use
- name: disable-compression
default_value: "false"
usage: |
If true, opt-out of response compression for all requests to the server
- name: insecure-skip-tls-verify
default_value: "false"
usage: |

View File

@ -9,7 +9,7 @@ description: |-
Possible resources include (case insensitive):
pod (po), deployment (deploy), statefulset (sts), daemonset (ds), replicaset (rs), cloneset (clone), statefulset.apps.kruise.io (asts), daemonset.apps.kruise.io (ads)
pod (po), deployment (deploy), statefulset (sts), daemonset (ds), replicaset (rs), cloneset (clone), statefulset.apps.kruise.io (asts), daemonset.apps.kruise.io (ads)
usage: kubectl-kruise set env RESOURCE/NAME KEY_1=VAL_1 ... KEY_N=VAL_N
options:
- name: all
@ -114,6 +114,10 @@ inherited_options:
usage: The name of the kubeconfig cluster to use
- name: context
usage: The name of the kubeconfig context to use
- name: disable-compression
default_value: "false"
usage: |
If true, opt-out of response compression for all requests to the server
- name: insecure-skip-tls-verify
default_value: "false"
usage: |

View File

@ -5,7 +5,7 @@ description: |-
Possible resources include (case insensitive):
pod (po), deployment (deploy), statefulset (sts), daemonset (ds), replicaset (rs), cloneset (clone), statefulset.apps.kruise.io (asts), daemonset.apps.kruise.io (ads)
pod (po), deployment (deploy), statefulset (sts), daemonset (ds), replicaset (rs), cloneset (clone), statefulset.apps.kruise.io (asts), daemonset.apps.kruise.io (ads)
usage: kubectl-kruise set image (-f FILENAME | TYPE NAME) CONTAINER_NAME_1=CONTAINER_IMAGE_1 ... CONTAINER_NAME_N=CONTAINER_IMAGE_N
options:
- name: all
@ -84,6 +84,10 @@ inherited_options:
usage: The name of the kubeconfig cluster to use
- name: context
usage: The name of the kubeconfig context to use
- name: disable-compression
default_value: "false"
usage: |
If true, opt-out of response compression for all requests to the server
- name: insecure-skip-tls-verify
default_value: "false"
usage: |

View File

@ -8,7 +8,7 @@ description: |-
Possible resources include (case insensitive):
pod (po), deployment (deploy), statefulset (sts), daemonset (ds), replicaset (rs), cloneset (clone), statefulset.apps.kruise.io (asts), daemonset.apps.kruise.io (ads)
pod (po), deployment (deploy), statefulset (sts), daemonset (ds), replicaset (rs), cloneset (clone), statefulset.apps.kruise.io (asts), daemonset.apps.kruise.io (ads)
usage: kubectl-kruise set resources (-f FILENAME | TYPE NAME) ([--limits=LIMITS & --requests=REQUESTS]
options:
- name: all
@ -98,6 +98,10 @@ inherited_options:
usage: The name of the kubeconfig cluster to use
- name: context
usage: The name of the kubeconfig context to use
- name: disable-compression
default_value: "false"
usage: |
If true, opt-out of response compression for all requests to the server
- name: insecure-skip-tls-verify
default_value: "false"
usage: |

View File

@ -3,7 +3,7 @@ synopsis: Set the selector on a resource
description: |-
Set the selector on a resource. Note that the new selector will overwrite the old selector if the resource had one prior to the invocation of 'set selector'.
A selector must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to 63 characters. If --resource-version is specified, then updates will use this resource version, otherwise the existing resource-version will be used. Note: currently selectors can only be set on Service objects.
A selector must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to 63 characters. If --resource-version is specified, then updates will use this resource version, otherwise the existing resource-version will be used. Note: currently selectors can only be set on Service objects.
usage: kubectl-kruise set selector (-f FILENAME | TYPE NAME) EXPRESSIONS [--resource-version=version]
options:
- name: all
@ -76,6 +76,10 @@ inherited_options:
usage: The name of the kubeconfig cluster to use
- name: context
usage: The name of the kubeconfig context to use
- name: disable-compression
default_value: "false"
usage: |
If true, opt-out of response compression for all requests to the server
- name: insecure-skip-tls-verify
default_value: "false"
usage: |

View File

@ -80,6 +80,10 @@ inherited_options:
usage: The name of the kubeconfig cluster to use
- name: context
usage: The name of the kubeconfig context to use
- name: disable-compression
default_value: "false"
usage: |
If true, opt-out of response compression for all requests to the server
- name: insecure-skip-tls-verify
default_value: "false"
usage: |

View File

@ -86,6 +86,10 @@ inherited_options:
usage: The name of the kubeconfig cluster to use
- name: context
usage: The name of the kubeconfig context to use
- name: disable-compression
default_value: "false"
usage: |
If true, opt-out of response compression for all requests to the server
- name: insecure-skip-tls-verify
default_value: "false"
usage: |

BIN
go.list Normal file

Binary file not shown.

51
go.mod
View File

@ -1,25 +1,27 @@
module github.com/openkruise/kruise-tools
go 1.20
go 1.23.0
toolchain go1.23.4
require (
github.com/go-errors/errors v1.4.2
github.com/lithammer/dedent v1.1.0
github.com/moby/term v0.0.0-20221205130635-1aeaba878587
github.com/openkruise/kruise-api v1.7.1
github.com/openkruise/kruise-rollout-api v0.5.1
github.com/openkruise/kruise-api v1.8.0
github.com/openkruise/kruise-rollout-api v0.6.0
github.com/spf13/cobra v1.8.1
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.9.0
k8s.io/api v0.28.9
k8s.io/apimachinery v0.28.9
k8s.io/cli-runtime v0.28.9
k8s.io/client-go v0.28.9
k8s.io/component-base v0.28.9
k8s.io/api v0.30.11
k8s.io/apimachinery v0.30.11
k8s.io/cli-runtime v0.30.11
k8s.io/client-go v0.30.11
k8s.io/component-base v0.30.11
k8s.io/klog/v2 v2.120.1
k8s.io/kubectl v0.28.9
k8s.io/kubectl v0.30.11
k8s.io/utils v0.0.0-20230726121419-3b25d923346b
sigs.k8s.io/controller-runtime v0.16.6
sigs.k8s.io/controller-runtime v0.18.6
sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3
sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3
)
@ -33,23 +35,23 @@ require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
github.com/evanphx/json-patch/v5 v5.6.0 // indirect
github.com/evanphx/json-patch/v5 v5.9.0 // indirect
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect
github.com/fatih/camelcase v1.0.0 // indirect
github.com/fvbommel/sortorder v1.1.0 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/swag v0.22.3 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
github.com/google/btree v1.0.1 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
@ -64,6 +66,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
@ -71,22 +74,30 @@ require (
github.com/xlab/treeprint v1.2.0 // indirect
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect
golang.org/x/net v0.24.0 // indirect
golang.org/x/net v0.38.0 // indirect
golang.org/x/oauth2 v0.17.0 // indirect
golang.org/x/sync v0.5.0 // indirect
golang.org/x/sys v0.19.0 // indirect
golang.org/x/term v0.19.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/sync v0.12.0 // indirect
golang.org/x/sys v0.31.0 // indirect
golang.org/x/term v0.30.0 // indirect
golang.org/x/text v0.23.0 // indirect
golang.org/x/time v0.3.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect
sigs.k8s.io/gateway-api v0.5.1 // indirect
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
sigs.k8s.io/gateway-api v0.7.1 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/kustomize/kustomize/v5 v5.0.4-0.20230601165947-6ce0bf390ce3 // indirect
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
)

154
go.sum
View File

@ -5,11 +5,14 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk=
github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
@ -20,6 +23,7 @@ github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lV
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -29,20 +33,20 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U=
github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww=
github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=
github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg=
github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ=
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM=
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4=
github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8=
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fvbommel/sortorder v1.1.0 h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQmYw=
github.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=
github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg=
github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
@ -50,13 +54,12 @@ github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En
github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g=
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo=
github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@ -88,18 +91,20 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
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-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
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.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ=
github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
@ -110,6 +115,7 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@ -121,6 +127,7 @@ github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
@ -136,28 +143,37 @@ github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU=
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
github.com/openkruise/kruise-api v1.7.1 h1:pF+tPHWY1SS0X7sXTOIHZ5sNb5h5MBy1D7h6bJI5yW8=
github.com/openkruise/kruise-api v1.7.1/go.mod h1:ZD94u+GSQGtKrDfFhMVpQhzjr7g7UlXhYfRoNp/EhJs=
github.com/openkruise/kruise-rollout-api v0.5.1 h1:wZug9vIfkTjfGANEWX7//NhFLpsL4ZU3kZq8kFSYk7I=
github.com/openkruise/kruise-rollout-api v0.5.1/go.mod h1:Db/+T+VaMtE++qTmBkW+lkBFO7zO5fgTZibfnKKfGaM=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/onsi/ginkgo/v2 v2.17.1 h1:V++EzdbhI4ZV4ev0UTIj0PzhzOcReJFyJaLjtSF55M8=
github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs=
github.com/onsi/gomega v1.32.0 h1:JRYU78fJ1LPxlckP6Txi/EYqJvjtMrDC04/MM5XRHPk=
github.com/onsi/gomega v1.32.0/go.mod h1:a4x4gW6Pz2yK1MAmvluYme5lvYTn61afQ2ETw/8n4Lg=
github.com/openkruise/kruise-api v1.8.0 h1:DoUb873uuf2Bhoajim+9tb/X0eFpwIxRydc4Awfeeiw=
github.com/openkruise/kruise-api v1.8.0/go.mod h1:XRpoTk7VFgh9r5HRUZurwhiC3cpCf5BX8X4beZLcIfA=
github.com/openkruise/kruise-rollout-api v0.6.0 h1:pv8Y3UPCWqrZgOU5uzoEC0lSWfr+x0NSMfFhXJ9wLvg=
github.com/openkruise/kruise-rollout-api v0.6.0/go.mod h1:qnSk54oRTv5JRp1m6fm5Qf+z1ClUhkGiKPtjP5Phtm8=
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
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=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8=
github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY=
github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY=
github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg=
github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY=
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
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/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
@ -166,6 +182,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
@ -181,11 +198,12 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY=
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
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-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=
@ -195,55 +213,25 @@ 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/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.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
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/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.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.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
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/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/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/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.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.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
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/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=
@ -252,12 +240,15 @@ 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.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY=
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=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw=
gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
@ -294,29 +285,30 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
k8s.io/api v0.28.9 h1:E7VEXXCAlSrp+08zq4zgd+ko6Ttu0Mw+XoXlIkDTVW0=
k8s.io/api v0.28.9/go.mod h1:AnCsDYf3SHjfa8mPG5LGYf+iF4mie+3peLQR51MMCgw=
k8s.io/apiextensions-apiserver v0.28.9 h1:yzPHp+4IASHeu7XIPkAKJrY4UjWdjiAjOcQMd6oNKj0=
k8s.io/apimachinery v0.28.9 h1:aXz4Zxsw+Pk4KhBerAtKRxNN1uSMWKfciL/iOdBfXvA=
k8s.io/apimachinery v0.28.9/go.mod h1:zUG757HaKs6Dc3iGtKjzIpBfqTM4yiRsEe3/E7NX15o=
k8s.io/cli-runtime v0.28.9 h1:TfEV/UgCiXewliUHOHsUMZ1bfENhqcqKkA/hqQ/HwvQ=
k8s.io/cli-runtime v0.28.9/go.mod h1:PgxW97xCDbtWgsuo2nahMc2/MxcSDgscdwm8XZ7973A=
k8s.io/client-go v0.28.9 h1:mmMvejwc/KDjMLmDpyaxkWNzlWRCJ6ht7Qsbsnwn39Y=
k8s.io/client-go v0.28.9/go.mod h1:GFDy3rUNId++WGrr0hRaBrs+y1eZz5JtVZODEalhRMo=
k8s.io/component-base v0.28.9 h1:ySM2PR8Z/xaUSG1Akd3yM6dqUezTltI7S5aV41MMuuc=
k8s.io/component-base v0.28.9/go.mod h1:QtWzscEhCKRfHV24/S+11BwWjVxhC6fd3RYoEgZcWFU=
k8s.io/api v0.30.11 h1:TpkiTTxQ6GSwHnqKOPeQRRFcBknTjOBwFYjWmn25Z1U=
k8s.io/api v0.30.11/go.mod h1:DZzjCDcat14fMx/4Fm3h5lsbVStfHmgNzNDMy7JQMqU=
k8s.io/apiextensions-apiserver v0.30.1 h1:4fAJZ9985BmpJG6PkoxVRpXv9vmPUOVzl614xarePws=
k8s.io/apiextensions-apiserver v0.30.1/go.mod h1:R4GuSrlhgq43oRY9sF2IToFh7PVlF1JjfWdoG3pixk4=
k8s.io/apimachinery v0.30.11 h1:+qV/yXI2R7BxX1zeyELDFb0PopX22znfq5w+icav49k=
k8s.io/apimachinery v0.30.11/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
k8s.io/cli-runtime v0.30.11 h1:rJBIprFSmMX61uwFWv07C8+VVeEDRnxAwipP511iWGQ=
k8s.io/cli-runtime v0.30.11/go.mod h1:yQ5Xh33U2NRdYvB3RBKBuLBHz7PrmGsnPSRFExsMnKg=
k8s.io/client-go v0.30.11 h1:yamC5zf/g5ztZO3SELklaOSZKTOAL3Q0v0i6GBvq+Mg=
k8s.io/client-go v0.30.11/go.mod h1:umPRna4oj2zLU03T1m7Cla+yMzRFyhuR+jAbDZNDqlM=
k8s.io/component-base v0.30.11 h1:y0GDnKad+VFWKlfWqnu3oHKL5eRQ3AC8xBNwLGnMdyc=
k8s.io/component-base v0.30.11/go.mod h1:JSQ3NPwvwGijXtApFqBYtsBitdbfXnwwLJkWuttRMV0=
k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5OhxCKlKJy0sHc+PcDwFB24dQ=
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM=
k8s.io/kubectl v0.28.9 h1:FTf/aapuuFxPmt8gYUeqUmcsgG0gKC2ei6n+TO5sGOw=
k8s.io/kubectl v0.28.9/go.mod h1:ip/zTUr1MM/H2M+YbPHnSKLt0x6kb85SJtRSjwEGDfs=
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
k8s.io/kubectl v0.30.11 h1:pBk1AzDpndHl9oBfqJS9J2CGYNyik+x/QanXSERM7gE=
k8s.io/kubectl v0.30.11/go.mod h1:a8AoybYsyppPEctupfJk4uaSy9uUWdvNfqRmSzbPPCQ=
k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI=
k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/controller-runtime v0.16.6 h1:FiXwTuFF5ZJKmozfP2Z0j7dh6kmxP4Ou1KLfxgKKC3I=
sigs.k8s.io/controller-runtime v0.16.6/go.mod h1:+dQzkZxnylD0u49e0a+7AR+vlibEBaThmPca7lTyUsI=
sigs.k8s.io/gateway-api v0.5.1 h1:EqzgOKhChzyve9rmeXXbceBYB6xiM50vDfq0kK5qpdw=
sigs.k8s.io/gateway-api v0.5.1/go.mod h1:x0AP6gugkFV8fC/oTlnOMU0pnmuzIR8LfIPRVUjxSqA=
sigs.k8s.io/controller-runtime v0.18.6 h1:UnEoLBLDpQwzJ2jYh6aTdiMhGjNDR7IdFn9YEqHIccc=
sigs.k8s.io/controller-runtime v0.18.6/go.mod h1:Dcsa9v8AEBWa3sQNJHsuWPT4ICv99irl5wj83NiC12U=
sigs.k8s.io/gateway-api v0.7.1 h1:Tts2jeepVkPA5rVG/iO+S43s9n7Vp7jCDhZDQYtPigQ=
sigs.k8s.io/gateway-api v0.7.1/go.mod h1:Xv0+ZMxX0lu1nSSDIIPEfbVztgNZ+3cfiYrJsa2Ooso=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 h1:XX3Ajgzov2RKUdc5jW3t5jwY7Bo7dcRm+tFxT+NfgY0=

View File

@ -19,6 +19,7 @@ package api
import (
kruiseappsv1alpha1 "github.com/openkruise/kruise-api/apps/v1alpha1"
kruiseappsv1beta1 "github.com/openkruise/kruise-api/apps/v1beta1"
kruisepolicyv1alpha1 "github.com/openkruise/kruise-api/policy/v1alpha1"
kruiserolloutsv1alpha1 "github.com/openkruise/kruise-rollout-api/rollouts/v1alpha1"
kruiserolloutsv1beta1 "github.com/openkruise/kruise-rollout-api/rollouts/v1beta1"
apps "k8s.io/api/apps/v1"
@ -42,6 +43,7 @@ func init() {
_ = kruiseappsv1beta1.AddToScheme(Scheme)
_ = kruiserolloutsv1alpha1.AddToScheme(Scheme)
_ = kruiserolloutsv1beta1.AddToScheme(Scheme)
_ = kruisepolicyv1alpha1.AddToScheme(Scheme)
}
func GetScheme() *runtime.Scheme {

View File

@ -24,8 +24,10 @@ import (
"github.com/spf13/cobra"
"github.com/openkruise/kruise-tools/pkg/cmd/create"
"github.com/openkruise/kruise-tools/pkg/cmd/describe"
cmdexec "github.com/openkruise/kruise-tools/pkg/cmd/exec"
"github.com/openkruise/kruise-tools/pkg/cmd/expose"
"github.com/openkruise/kruise-tools/pkg/cmd/get"
"github.com/openkruise/kruise-tools/pkg/cmd/migrate"
krollout "github.com/openkruise/kruise-tools/pkg/cmd/rollout"
"github.com/openkruise/kruise-tools/pkg/cmd/scaledown"
@ -443,6 +445,8 @@ func NewKubectlCommand(in io.Reader, out, err io.Writer) *cobra.Command {
cmds.AddCommand(alpha)
cmds.AddCommand(NewCmdGenerateDocs(f, ioStreams))
cmds.AddCommand(NewAutoCompleteCommand())
cmds.AddCommand(get.NewCmdGet(f, ioStreams))
cmds.AddCommand(describe.NewCmdDescibe(f, ioStreams))
cmds.AddCommand(cmdconfig.NewCmdConfig(clientcmd.NewDefaultPathOptions(), ioStreams))
cmds.AddCommand(plugin.NewCmdPlugin(ioStreams))
cmds.AddCommand(version.NewCmdVersion(f, ioStreams))

View File

@ -0,0 +1,50 @@
package describe
/*
Copyright 2021 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.
*/
import (
"github.com/spf13/cobra"
"k8s.io/cli-runtime/pkg/genericclioptions"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
)
var (
describeLong = templates.LongDesc(i18n.T(`
Show details of a rollout.`))
describeExample = templates.Examples(`
# Describe the rollout named rollout-demo
kubectl-kruise describe rollout rollout-demo`)
)
// NewCmdRollout returns a Command instance for 'rollout' sub command
func NewCmdDescibe(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
cmd := &cobra.Command{
Use: "describe SUBCOMMAND",
DisableFlagsInUseLine: true,
Short: i18n.T("Show details of a specific resource or group of resources"),
Long: describeLong,
Example: describeExample,
Run: cmdutil.DefaultSubCommandRun(streams.Out),
}
// subcommands
cmd.AddCommand(NewCmdDescribeRollout(f, streams))
return cmd
}

View File

@ -0,0 +1,806 @@
/*
Copyright 2024 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 describe
import (
"context"
"fmt"
"reflect"
"sort"
"strconv"
"strings"
"text/tabwriter"
"time"
kruiseappsv1alpha1 "github.com/openkruise/kruise-api/apps/v1alpha1"
kruiseappsv1beta1 "github.com/openkruise/kruise-api/apps/v1beta1"
rolloutsapi "github.com/openkruise/kruise-rollout-api/client/clientset/versioned"
rolloutv1alpha1types "github.com/openkruise/kruise-rollout-api/client/clientset/versioned/typed/rollouts/v1alpha1"
rolloutsv1beta1types "github.com/openkruise/kruise-rollout-api/client/clientset/versioned/typed/rollouts/v1beta1"
rolloutsapiv1alpha1 "github.com/openkruise/kruise-rollout-api/rollouts/v1alpha1"
rolloutsapiv1beta1 "github.com/openkruise/kruise-rollout-api/rollouts/v1beta1"
internalapi "github.com/openkruise/kruise-tools/pkg/api"
internalpolymorphichelpers "github.com/openkruise/kruise-tools/pkg/internal/polymorphichelpers"
"github.com/spf13/cobra"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/duration"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/cli-runtime/pkg/resource"
"k8s.io/client-go/kubernetes/scheme"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
)
const (
tableFormat = "%-19s%v\n"
)
var (
rolloutLong = templates.LongDesc(i18n.T(`
Get details about and visual representation of a rollout.`))
rolloutExample = templates.Examples(`
# Describe the rollout named rollout-demo within namespace default
kubectl-kruise describe rollout rollout-demo -n default
# Watch for changes to the rollout named rollout-demo
kubectl-kruise describe rollout rollout-demo -n default -w`)
)
type DescribeRolloutOptions struct {
genericclioptions.IOStreams
Builder func() *resource.Builder
Namespace string
EnforceNamespace bool
Resources []string
RolloutViewerFn func(runtime.Object) (interface{}, error)
Watch bool
NoColor bool
All bool
TimeoutSeconds int
RolloutsV1beta1Client rolloutsv1beta1types.RolloutInterface
RolloutsV1alpha1Client rolloutv1alpha1types.RolloutInterface
}
type WorkloadInfo struct {
Name string
Kind string
Images []string
Replicas struct {
Desired int32
Current int32
Updated int32
Ready int32
Available int32
}
Pod []struct {
Name string
BatchID string
Status string
Ready string
Age string
Restarts string
Revision string
}
CurrentRevision string
UpdateRevision string
}
type RolloutInfo struct {
Name string
Namespace string
Phase string
Message string
ObservedGeneration int64
Generation int64
CurrentStepIndex int32
CurrentStepState string
CanaryStrategy rolloutsapiv1beta1.CanaryStrategy
BlueGreenStrategy rolloutsapiv1beta1.BlueGreenStrategy
TrafficRoutingRef string
WorkloadRef RolloutWorkloadRef
StrategyType string
}
func NewCmdDescribeRollout(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
o := &DescribeRolloutOptions{IOStreams: streams}
cmd := &cobra.Command{
Use: "rollout SUBCOMMAND",
DisableFlagsInUseLine: true,
Short: i18n.T("Get details about a rollout"),
Long: rolloutLong,
Example: rolloutExample,
Aliases: []string{"rollouts", "ro"},
Run: func(cmd *cobra.Command, args []string) {
cmdutil.CheckErr(o.Complete(f, args))
cmdutil.CheckErr(o.Run())
},
}
cmd.Flags().BoolVarP(&o.Watch, "watch", "w", false, "Watch for changes to the rollout")
cmd.Flags().BoolVar(&o.NoColor, "no-color", false, "If true, print output without color")
cmd.Flags().IntVar(&o.TimeoutSeconds, "timeout", 0, "Timeout after specified seconds")
cmd.Flags().BoolVar(&o.All, "all", false, "Show all pods in the rollout")
return cmd
}
func (o *DescribeRolloutOptions) Complete(f cmdutil.Factory, args []string) error {
var err error
if len(args) == 0 {
return fmt.Errorf("required rollout name not specified")
}
o.Resources = args
o.Namespace, o.EnforceNamespace, err = f.ToRawKubeConfigLoader().Namespace()
if err != nil {
return err
}
o.Resources = []string{args[0]}
o.RolloutViewerFn = internalpolymorphichelpers.RolloutViewerFn
o.Builder = f.NewBuilder
config, err := f.ToRESTConfig()
if err != nil {
return err
}
rolloutsClientset, err := rolloutsapi.NewForConfig(config)
if err != nil {
return err
}
o.RolloutsV1beta1Client = rolloutsClientset.RolloutsV1beta1().Rollouts(o.Namespace)
o.RolloutsV1alpha1Client = rolloutsClientset.RolloutsV1alpha1().Rollouts(o.Namespace)
return nil
}
func (o *DescribeRolloutOptions) Run() error {
rolloutName := o.Resources[0]
r := o.Builder().
WithScheme(internalapi.GetScheme(), scheme.Scheme.PrioritizedVersionsAllGroups()...).
NamespaceParam(o.Namespace).DefaultNamespace().
ResourceNames("rollouts.rollouts.kruise.io", rolloutName).
ContinueOnError().
Latest().
Flatten().
Do()
if err := r.Err(); err != nil {
return err
}
if !o.Watch {
return r.Visit(o.describeRollout)
}
return o.watchRollout(r)
}
func (o *DescribeRolloutOptions) describeRollout(info *resource.Info, err error) error {
if err != nil {
return err
}
rollout, err := o.RolloutViewerFn(info.Object)
if err != nil {
return err
}
o.printRolloutInfo(rollout)
return nil
}
func (o *DescribeRolloutOptions) watchRollout(r *resource.Result) error {
infos, err := r.Infos()
if err != nil {
return err
}
if len(infos) != 1 {
return fmt.Errorf("watch is only supported on a single rollout")
}
info := infos[0]
var watcher watch.Interface
switch info.Object.(type) {
case *rolloutsapiv1beta1.Rollout:
watcher, err = o.RolloutsV1beta1Client.Watch(context.TODO(), metav1.ListOptions{
FieldSelector: "metadata.name=" + info.Name,
})
case *rolloutsapiv1alpha1.Rollout:
watcher, err = o.RolloutsV1alpha1Client.Watch(context.TODO(), metav1.ListOptions{
FieldSelector: "metadata.name=" + info.Name,
})
default:
return fmt.Errorf("unsupported rollout type %T", info.Object)
}
if err != nil {
return err
}
defer watcher.Stop()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
if o.TimeoutSeconds > 0 {
ctx, cancel = context.WithTimeout(ctx, time.Duration(o.TimeoutSeconds)*time.Second)
defer cancel()
}
return o.watchRolloutUpdates(ctx, watcher)
}
func (o *DescribeRolloutOptions) watchRolloutUpdates(ctx context.Context, watcher watch.Interface) error {
for {
select {
case event, ok := <-watcher.ResultChan():
if !ok {
return nil
}
if event.Type == watch.Added || event.Type == watch.Modified {
var rollout interface{}
switch obj := event.Object.(type) {
case *rolloutsapiv1beta1.Rollout:
rollout = obj
case *rolloutsapiv1alpha1.Rollout:
rollout = obj
default:
continue
}
o.clearScreen()
o.printRolloutInfo(rollout)
}
case <-ctx.Done():
return ctx.Err()
}
}
}
func (o *DescribeRolloutOptions) clearScreen() {
fmt.Fprint(o.Out, "\033[2J\033[H")
}
type RolloutWorkloadRef struct {
Kind string
Name string
StableRevision string
CanaryRevision string
UpdatedRevision string
PodTemplateHash string
CurrentStepIndex int32
}
func (o *DescribeRolloutOptions) GetResources(rollout RolloutWorkloadRef) (*WorkloadInfo, error) {
resources := []string{rollout.Kind + "/" + rollout.Name}
r := o.Builder().
WithScheme(internalapi.GetScheme(), scheme.Scheme.PrioritizedVersionsAllGroups()...).
NamespaceParam(o.Namespace).DefaultNamespace().
ResourceTypeOrNameArgs(true, resources...).
ContinueOnError().
Latest().
Flatten().
Do()
if err := r.Err(); err != nil {
return nil, err
}
obj, err := r.Object()
if err != nil {
return nil, err
}
workloadInfo := &WorkloadInfo{}
objValue := reflect.ValueOf(obj).Elem()
workloadInfo.Name = objValue.FieldByName("Name").String()
workloadInfo.Kind = objValue.Type().Name()
podTemplateSpec := objValue.FieldByName("Spec").FieldByName("Template").FieldByName("Spec")
containers := podTemplateSpec.FieldByName("Containers")
for i := 0; i < containers.Len(); i++ {
container := containers.Index(i)
workloadInfo.Images = append(workloadInfo.Images, container.FieldByName("Image").String())
}
// Deployment,StatefulSet,CloneSet,Advanced StatefulSet,Advanced DaemonSet
switch o := obj.(type) {
case *appsv1.Deployment:
workloadInfo.Replicas.Desired = *o.Spec.Replicas
workloadInfo.Replicas.Current = o.Status.Replicas
workloadInfo.Replicas.Updated = o.Status.UpdatedReplicas
workloadInfo.Replicas.Ready = o.Status.ReadyReplicas
workloadInfo.Replicas.Available = o.Status.AvailableReplicas
case *appsv1.StatefulSet:
workloadInfo.Replicas.Desired = *o.Spec.Replicas
workloadInfo.Replicas.Current = o.Status.Replicas
workloadInfo.Replicas.Updated = o.Status.UpdatedReplicas
workloadInfo.Replicas.Ready = o.Status.ReadyReplicas
workloadInfo.Replicas.Available = o.Status.AvailableReplicas
case *kruiseappsv1alpha1.DaemonSet:
workloadInfo.Replicas.Desired = o.Spec.BurstReplicas.IntVal
workloadInfo.Replicas.Current = o.Status.CurrentNumberScheduled
workloadInfo.Replicas.Updated = o.Status.UpdatedNumberScheduled
workloadInfo.Replicas.Ready = o.Status.NumberReady
workloadInfo.Replicas.Available = o.Status.NumberAvailable
case *kruiseappsv1beta1.StatefulSet:
workloadInfo.Replicas.Desired = *o.Spec.Replicas
workloadInfo.Replicas.Current = o.Status.Replicas
workloadInfo.Replicas.Updated = o.Status.UpdatedReplicas
workloadInfo.Replicas.Ready = o.Status.ReadyReplicas
workloadInfo.Replicas.Available = o.Status.AvailableReplicas
case *kruiseappsv1alpha1.CloneSet:
workloadInfo.Replicas.Desired = *o.Spec.Replicas
workloadInfo.Replicas.Current = o.Status.Replicas
workloadInfo.Replicas.Updated = o.Status.UpdatedReplicas
workloadInfo.Replicas.Ready = o.Status.ReadyReplicas
workloadInfo.Replicas.Available = o.Status.AvailableReplicas
default:
return nil, fmt.Errorf("unsupported workload kind %T", obj)
}
workloadInfo.CurrentRevision = rollout.StableRevision
workloadInfo.UpdateRevision = rollout.CanaryRevision
if rollout.UpdatedRevision != "" {
workloadInfo.UpdateRevision = rollout.UpdatedRevision
}
var labelSelectorParam string
switch obj.(type) {
case *appsv1.Deployment:
labelSelectorParam = "pod-template-hash"
default:
labelSelectorParam = "controller-revision-hash"
}
selectorParam := rollout.PodTemplateHash
if selectorParam == "" {
selectorParam = rollout.StableRevision
}
labelSelectors := []string{
fmt.Sprintf("%s=%s", labelSelectorParam, selectorParam),
}
if !o.All && rollout.CurrentStepIndex != 0 {
labelSelectors = append(labelSelectors,
fmt.Sprintf("rollouts.kruise.io/rollout-batch-id=%v",
rollout.CurrentStepIndex))
}
// Fetch pods
r2 := o.Builder().
WithScheme(internalapi.GetScheme(), scheme.Scheme.PrioritizedVersionsAllGroups()...).
NamespaceParam(o.Namespace).DefaultNamespace().
ResourceTypes("pods").
LabelSelectorParam(strings.Join(labelSelectors, ",")).
Latest().
Flatten().
Do()
if err := r2.Err(); err != nil {
return nil, err
}
err = r2.Visit(func(info *resource.Info, err error) error {
if err != nil {
return err
}
pod, ok := info.Object.(*corev1.Pod)
if !ok {
return fmt.Errorf("expected *corev1.Pod, got %T", info.Object)
}
podInfo := struct {
Name string
BatchID string
Status string
Ready string
Age string
Restarts string
Revision string
}{
Name: pod.Name,
BatchID: pod.Labels["rollouts.kruise.io/rollout-batch-id"],
Status: string(pod.Status.Phase),
Age: duration.HumanDuration(time.Since(pod.CreationTimestamp.Time)),
Restarts: "0",
}
if pod.DeletionTimestamp != nil {
podInfo.Status = "Terminating"
}
if len(pod.Status.ContainerStatuses) > 0 {
restartCount := 0
for _, containerStatus := range pod.Status.ContainerStatuses {
restartCount += int(containerStatus.RestartCount)
}
podInfo.Restarts = strconv.Itoa(restartCount)
}
// Calculate ready status
readyContainers := 0
for _, containerStatus := range pod.Status.ContainerStatuses {
if containerStatus.Ready {
readyContainers++
}
}
podInfo.Ready = fmt.Sprintf("%d/%d", readyContainers, len(pod.Spec.Containers))
// Calculate revision
if pod.Labels["pod-template-hash"] != "" {
podInfo.Revision = pod.Labels["pod-template-hash"]
} else if pod.Labels["controller-revision-hash"] != "" {
podInfo.Revision = pod.Labels["controller-revision-hash"]
}
workloadInfo.Pod = append(workloadInfo.Pod, podInfo)
return nil
})
if err != nil {
return nil, err
}
// Sort pods by batch ID and ready count
sort.Slice(workloadInfo.Pod, func(i, j int) bool {
if workloadInfo.Pod[i].BatchID != workloadInfo.Pod[j].BatchID {
return workloadInfo.Pod[i].BatchID < workloadInfo.Pod[j].BatchID
}
iReady := strings.Split(workloadInfo.Pod[i].Ready, "/")
jReady := strings.Split(workloadInfo.Pod[j].Ready, "/")
iReadyCount, _ := strconv.Atoi(iReady[0])
jReadyCount, _ := strconv.Atoi(jReady[0])
return iReadyCount > jReadyCount
})
return workloadInfo, nil
}
func (o *DescribeRolloutOptions) colorizeIcon(phase string) string {
if o.NoColor || phase == "" {
return ""
}
switch phase {
case string(rolloutsapiv1beta1.RolloutPhaseHealthy), string(corev1.PodRunning):
return "\033[32m✔\033[0m"
case string(rolloutsapiv1beta1.RolloutPhaseProgressing), string(corev1.PodPending):
return "\033[33m⚠\033[0m"
case string(rolloutsapiv1beta1.RolloutPhaseDisabled), string(corev1.PodUnknown), string(rolloutsapiv1beta1.RolloutPhaseTerminating), string(rolloutsapiv1beta1.RolloutPhaseDisabling), string(corev1.PodFailed):
return "\033[31m✘\033[0m"
case string(rolloutsapiv1beta1.RolloutPhaseInitial):
return "\033[33m⚠\033[0m"
default:
return ""
}
}
func (o *DescribeRolloutOptions) printTrafficRouting(trafficRouting []rolloutsapiv1beta1.TrafficRoutingRef) {
if len(trafficRouting) == 0 {
return
}
fmt.Fprint(o.Out, "Traffic Routings:\n")
for _, trafficRouting := range trafficRouting {
fmt.Fprintf(o.Out, tableFormat, " - Service: ", trafficRouting.Service)
if trafficRouting.Ingress != nil {
fmt.Fprintln(o.Out, ` Ingress: `)
fmt.Fprintf(o.Out, tableFormat, " classType: ", trafficRouting.Ingress.ClassType)
fmt.Fprintf(o.Out, tableFormat, " name: ", trafficRouting.Ingress.Name)
}
if trafficRouting.Gateway != nil {
fmt.Fprintln(o.Out, ` Gateway: `)
fmt.Fprintf(o.Out, tableFormat, " HttpRouteName: ", trafficRouting.Gateway.HTTPRouteName)
}
if trafficRouting.CustomNetworkRefs != nil {
fmt.Fprintln(o.Out, ` CustomNetworkRefs: `)
for _, customNetworkRef := range trafficRouting.CustomNetworkRefs {
fmt.Fprintf(o.Out, tableFormat, " name: ", customNetworkRef.Name)
fmt.Fprintf(o.Out, tableFormat, " kind: ", customNetworkRef.Kind)
fmt.Fprintf(o.Out, tableFormat, " apiVersion: ", customNetworkRef.APIVersion)
}
}
}
}
func convertCustomNetworkRefs(refs []rolloutsapiv1alpha1.CustomNetworkRef) []rolloutsapiv1beta1.ObjectRef {
var result []rolloutsapiv1beta1.ObjectRef
for _, ref := range refs {
result = append(result, rolloutsapiv1beta1.ObjectRef{
Name: ref.Name,
Kind: ref.Kind,
APIVersion: ref.APIVersion,
})
}
return result
}
func extractRolloutInfo(obj interface{}) *RolloutInfo {
info := &RolloutInfo{}
switch r := obj.(type) {
case *rolloutsapiv1beta1.Rollout:
info.Name = r.Name
info.Namespace = r.Namespace
info.Phase = string(r.Status.Phase)
info.Message = r.Status.Message
info.ObservedGeneration = r.Status.ObservedGeneration
info.Generation = r.GetObjectMeta().GetGeneration()
if r.Spec.Strategy.BlueGreen != nil {
info.CurrentStepIndex = r.Status.BlueGreenStatus.CurrentStepIndex
info.CurrentStepState = string(r.Status.BlueGreenStatus.CurrentStepState)
info.WorkloadRef = RolloutWorkloadRef{
Kind: r.Spec.WorkloadRef.Kind,
Name: r.Spec.WorkloadRef.Name,
StableRevision: r.Status.BlueGreenStatus.StableRevision,
UpdatedRevision: r.Status.BlueGreenStatus.UpdatedRevision,
PodTemplateHash: r.Status.BlueGreenStatus.PodTemplateHash,
CurrentStepIndex: r.Status.BlueGreenStatus.CurrentStepIndex,
}
} else {
info.CurrentStepIndex = r.Status.CanaryStatus.CurrentStepIndex
info.CurrentStepState = string(r.Status.CanaryStatus.CurrentStepState)
info.WorkloadRef = RolloutWorkloadRef{
Kind: r.Spec.WorkloadRef.Kind,
Name: r.Spec.WorkloadRef.Name,
StableRevision: r.Status.CanaryStatus.StableRevision,
CanaryRevision: r.Status.CanaryStatus.CanaryRevision,
PodTemplateHash: r.Status.CanaryStatus.PodTemplateHash,
CurrentStepIndex: r.Status.CanaryStatus.CurrentStepIndex,
}
}
if r.Spec.Strategy.Canary != nil {
info.CanaryStrategy = *r.Spec.Strategy.Canary
info.StrategyType = "Canary"
info.TrafficRoutingRef = r.Spec.Strategy.Canary.TrafficRoutingRef
} else if r.Spec.Strategy.BlueGreen != nil {
info.BlueGreenStrategy = *r.Spec.Strategy.BlueGreen
info.StrategyType = "BlueGreen"
}
case *rolloutsapiv1alpha1.Rollout:
info.Name = r.Name
info.Namespace = r.Namespace
info.Phase = string(r.Status.Phase)
info.Message = r.Status.Message
info.ObservedGeneration = r.Status.ObservedGeneration
info.Generation = r.GetObjectMeta().GetGeneration()
info.CurrentStepIndex = r.Status.CanaryStatus.CurrentStepIndex
info.CurrentStepState = string(r.Status.CanaryStatus.CurrentStepState)
info.WorkloadRef = RolloutWorkloadRef{
Kind: r.Spec.ObjectRef.WorkloadRef.Kind,
Name: r.Spec.ObjectRef.WorkloadRef.Name,
StableRevision: r.Status.CanaryStatus.StableRevision,
CanaryRevision: r.Status.CanaryStatus.CanaryRevision,
PodTemplateHash: r.Status.CanaryStatus.PodTemplateHash,
CurrentStepIndex: r.Status.CanaryStatus.CurrentStepIndex,
}
if r.Spec.Strategy.Canary != nil {
info.StrategyType = "Canary"
info.TrafficRoutingRef = r.ObjectMeta.Annotations["rollouts.kruise.io/trafficrouting"]
}
// BlueGreen strategy is not supported in v1alpha1 API
}
if obj.(*rolloutsapiv1beta1.Rollout).Spec.Strategy.Canary != nil {
info.CanaryStrategy = *obj.(*rolloutsapiv1beta1.Rollout).Spec.Strategy.Canary
} else if obj.(*rolloutsapiv1beta1.Rollout).Spec.Strategy.BlueGreen != nil {
info.BlueGreenStrategy = *obj.(*rolloutsapiv1beta1.Rollout).Spec.Strategy.BlueGreen
}
return info
}
func (o *DescribeRolloutOptions) fetchAndPrintTrafficRoutingRef(ref string) {
r := o.Builder().
WithScheme(internalapi.GetScheme(), scheme.Scheme.PrioritizedVersionsAllGroups()...).
NamespaceParam(o.Namespace).DefaultNamespace().
ResourceNames("trafficroutings.rollouts.kruise.io", ref).
ContinueOnError().
Latest().
Flatten().
Do()
if err := r.Err(); err != nil {
fmt.Fprintf(o.Out, "Error getting TrafficRoutingRef: %v\n", err)
return
}
err := r.Visit(func(info *resource.Info, err error) error {
if err != nil {
return err
}
trafficRouting, ok := info.Object.(*rolloutsapiv1alpha1.TrafficRouting)
if !ok {
return fmt.Errorf("expected *rolloutsapiv1alpha1.TrafficRouting")
}
var trafficRoutingRef []rolloutsapiv1beta1.TrafficRoutingRef
for _, ref := range trafficRouting.Spec.ObjectRef {
trafficRoutingRef = append(trafficRoutingRef, rolloutsapiv1beta1.TrafficRoutingRef{
Service: ref.Service,
Ingress: (*rolloutsapiv1beta1.IngressTrafficRouting)(ref.Ingress),
Gateway: (*rolloutsapiv1beta1.GatewayTrafficRouting)(ref.Gateway),
CustomNetworkRefs: convertCustomNetworkRefs(ref.CustomNetworkRefs),
})
}
o.printTrafficRouting(trafficRoutingRef)
return nil
})
if err != nil {
return
}
}
func (o *DescribeRolloutOptions) printRolloutInfo(rollout interface{}) {
info := extractRolloutInfo(rollout)
// Print basic info
fmt.Fprintf(o.Out, tableFormat, "Name:", info.Name)
fmt.Fprintf(o.Out, tableFormat, "Namespace:", info.Namespace)
if info.ObservedGeneration == info.Generation {
fmt.Fprintf(o.Out, tableFormat, "Status:", o.colorizeIcon(info.Phase)+" "+info.Phase)
if info.Message != "" {
fmt.Fprintf(o.Out, tableFormat, "Message:", info.Message)
}
}
// Print strategy
fmt.Fprintf(o.Out, tableFormat, "Strategy:", info.StrategyType)
if info.StrategyType == "Canary" {
fmt.Fprintf(o.Out, tableFormat, " Step:", strconv.Itoa(int(info.CurrentStepIndex))+"/"+strconv.Itoa(len(info.CanaryStrategy.Steps)))
fmt.Fprint(o.Out, " Steps:\n")
o.printSteps(info)
o.printTrafficRouting(info.CanaryStrategy.TrafficRoutings)
} else if info.StrategyType == "BlueGreen" {
fmt.Fprintf(o.Out, tableFormat, " Step:", strconv.Itoa(int(info.CurrentStepIndex))+"/"+strconv.Itoa(len(info.BlueGreenStrategy.Steps)))
fmt.Fprint(o.Out, " Steps:\n")
o.printSteps(info)
o.printTrafficRouting(info.BlueGreenStrategy.TrafficRoutings)
}
if info.TrafficRoutingRef != "" {
o.fetchAndPrintTrafficRoutingRef(info.TrafficRoutingRef)
}
// Print workload info
workloadInfo, err := o.GetResources(info.WorkloadRef)
if err != nil {
fmt.Fprintf(o.Out, "Error getting resources: %v\n", err)
return
}
// Print images
for i, image := range workloadInfo.Images {
if i == 0 {
fmt.Fprintf(o.Out, tableFormat, "Images:", image)
} else {
fmt.Fprintf(o.Out, tableFormat, "", image)
}
}
// Print revisions
fmt.Fprintf(o.Out, tableFormat, "Current Revision:", workloadInfo.CurrentRevision)
fmt.Fprintf(o.Out, tableFormat, "Update Revision:", workloadInfo.UpdateRevision)
// Print replicas
if info.ObservedGeneration == info.Generation {
o.printReplicas(workloadInfo)
}
// Print pods
if len(workloadInfo.Pod) > 0 {
o.printPods(workloadInfo)
}
}
func (o *DescribeRolloutOptions) printSteps(info *RolloutInfo) {
currentStepIndex := int(info.CurrentStepIndex)
Steps := info.CanaryStrategy.Steps
if info.StrategyType == "BlueGreen" {
Steps = info.BlueGreenStrategy.Steps
}
for i, step := range Steps {
isCurrentStep := (i + 1) == currentStepIndex
if isCurrentStep {
fmt.Fprint(o.Out, "\033[32m")
}
if step.Replicas != nil {
fmt.Fprintf(o.Out, tableFormat, " - Replicas: ", step.Replicas)
}
if step.Traffic != nil {
fmt.Fprintf(o.Out, tableFormat, " Traffic: ", *step.Traffic)
}
if len(step.Matches) > 0 {
fmt.Fprintln(o.Out, " Matches: ")
for _, match := range step.Matches {
fmt.Fprintln(o.Out, " - Headers: ")
for _, header := range match.Headers {
fmt.Fprintf(o.Out, tableFormat, " - Name:", header.Name)
fmt.Fprintf(o.Out, tableFormat, " Value:", header.Value)
fmt.Fprintf(o.Out, tableFormat, " Type:", *header.Type)
}
}
}
if isCurrentStep {
fmt.Fprintf(o.Out, tableFormat, " State:", info.CurrentStepState)
fmt.Fprint(o.Out, "\033[0m")
}
}
}
func (o *DescribeRolloutOptions) printReplicas(info *WorkloadInfo) {
fmt.Fprint(o.Out, "Replicas:\n")
fmt.Fprintf(o.Out, tableFormat, " Desired:", info.Replicas.Desired)
fmt.Fprintf(o.Out, tableFormat, " Updated:", info.Replicas.Updated)
fmt.Fprintf(o.Out, tableFormat, " Current:", info.Replicas.Current)
fmt.Fprintf(o.Out, tableFormat, " Ready:", info.Replicas.Ready)
fmt.Fprintf(o.Out, tableFormat, " Available:", info.Replicas.Available)
}
func (o *DescribeRolloutOptions) printPods(info *WorkloadInfo) {
w := tabwriter.NewWriter(o.Out, 0, 0, 2, ' ', 0)
fmt.Fprintln(w, "NAME\tREADY\tBATCH ID\tREVISION\tAGE\tRESTARTS\tSTATUS")
for _, pod := range info.Pod {
fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s %s\n",
pod.Name,
pod.Ready,
pod.BatchID,
pod.Revision,
pod.Age,
pod.Restarts,
o.colorizeIcon(pod.Status),
pod.Status,
)
}
w.Flush()
}

421
pkg/cmd/get/get.go Normal file
View File

@ -0,0 +1,421 @@
/*
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 get
import (
"fmt"
"time"
kruiseappsv1alpha1 "github.com/openkruise/kruise-api/apps/v1alpha1"
kruiseappsv1beta1 "github.com/openkruise/kruise-api/apps/v1beta1"
kruisepolicyv1alpha1 "github.com/openkruise/kruise-api/policy/v1alpha1"
rolloutv1alpha1 "github.com/openkruise/kruise-rollout-api/rollouts/v1alpha1"
rolloutv1beta1 "github.com/openkruise/kruise-rollout-api/rollouts/v1beta1"
internalpolymorphichelpers "github.com/openkruise/kruise-tools/pkg/internal/polymorphichelpers"
"github.com/spf13/cobra"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/cli-runtime/pkg/resource"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/scheme"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
)
var (
getLong = templates.Examples(i18n.T(`
Display one or many resources related to kruise.`))
getExample = templates.Examples(i18n.T(`
# List all resources in the default namespace
kubectl-kruise get all
# List all resources in the specific namespace
kubectl-kruise get all -n namespace
# Watch all resources in the default namespace
kubectl-kruise get all -w`))
)
type GetOptions struct {
genericclioptions.IOStreams
Builder func() *resource.Builder
Resources []string
Namespace string
EnforceNamespace bool
GetViewerFn internalpolymorphichelpers.GetViewerFunc
}
func NewCmdGet(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
o := &GetOptions{IOStreams: streams}
cmd := &cobra.Command{
Use: "get all",
DisableFlagsInUseLine: true,
Short: i18n.T("Display one or many resources"),
Long: getLong,
Example: getExample,
Run: func(cmd *cobra.Command, args []string) {
cmdutil.CheckErr(o.Complete(f, args))
cmdutil.CheckErr(o.Run())
},
}
cmd.Flags().StringVarP(&o.Namespace, "namespace", "n", o.Namespace, "If present, the namespace scope for this CLI request")
return cmd
}
func (o *GetOptions) Complete(f cmdutil.Factory, args []string) error {
var err error
if len(args) == 0 {
return fmt.Errorf("required resource not specified")
}
o.Resources = args
o.Namespace, o.EnforceNamespace, err = f.ToRawKubeConfigLoader().Namespace()
if err != nil {
return err
}
o.GetViewerFn = internalpolymorphichelpers.GetViewerFn
o.Builder = f.NewBuilder
return nil
}
func (o *GetOptions) Run() error {
if len(o.Resources) == 0 {
return fmt.Errorf("you must specify the type of resource to get")
}
if o.Resources[0] == "all" {
resourceTypes := []string{
"clonesets.apps.kruise.io",
"statefulsets.apps.kruise.io",
"daemonsets.apps.kruise.io",
"rollouts.rollouts.kruise.io",
"broadcastjobs.apps.kruise.io",
"containerrecreaterequests.apps.kruise.io",
"advancedcronjobs.apps.kruise.io",
"resourcedistributions.apps.kruise.io",
"uniteddeployments.apps.kruise.io",
"sidecarsets.apps.kruise.io",
"podprobemarkers.apps.kruise.io",
"imagepulljobs.apps.kruise.io",
"podunavailablebudgets.policy.kruise.io",
}
for _, resourceType := range resourceTypes {
b := o.Builder().
WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...).
NamespaceParam(o.Namespace).DefaultNamespace().
ResourceTypeOrNameArgs(true, resourceType).
ContinueOnError().
Latest().
Flatten()
if resourceType == "sidecarsets.apps.kruise.io" {
b = b.AllNamespaces(true)
}
infos, err := b.Do().Infos()
if err != nil {
return err
}
if len(infos) > 0 {
// Print resource type header and table header only if there are resources
fmt.Fprintf(o.Out, "\n%s:\n", resourceType)
switch resourceType {
case "clonesets.apps.kruise.io":
fmt.Fprintf(o.Out, "%-12s\t%-8s\t%-8s\t%-14s\t%-18s\t%-8s\t%-8s\t%-s\n",
"NAME", "DESIRED", "UPDATED", "UPDATED_READY", "UPDATED_AVAILABLE", "READY", "TOTAL", "AGE")
case "statefulsets.apps.kruise.io":
fmt.Fprintf(o.Out, "%-12s\t%-8s\t%-8s\t%-8s\t%-8s\t%-s\n",
"NAME", "DESIRED", "CURRENT", "UPDATED", "READY", "AGE")
case "daemonsets.apps.kruise.io":
fmt.Fprintf(o.Out, "%-8s\t%-8s\t%-8s\t%-8s\t%-8s\t%-8s\t%-8s\t%-s\n",
"NAME", "DESIRED", "CURRENT", "READY", "UP-TO-DATE", "AVAILABLE", "NODE SELECTOR", "AGE")
case "rollouts.rollouts.kruise.io":
fmt.Fprintf(o.Out, "%-20s\t%-8s\t%-12s\t%-12s\t%-40s\t%-s\n",
"NAME", "STATUS", "CANARY_STEP", "CANARY_STATE", "MESSAGE", "AGE")
case "broadcastjobs.apps.kruise.io":
fmt.Fprintf(o.Out, "%-12s\t%-8s\t%-8s\t%-8s\t%-8s\t%-s\n",
"NAME", "DESIRED", "ACTIVE", "SUCCEEDED", "FAILED", "AGE")
case "containerrecreaterequests.apps.kruise.io":
fmt.Fprintf(o.Out, "%-12s\t%-8s\t%-8s\t%-8s\t%-s\n",
"NAME", "PHASE", "COMPLETED", "FAILED", "AGE")
case "advancedcronjobs.apps.kruise.io":
fmt.Fprintf(o.Out, "%-12s\t%-8s\t%-8s\t%-8s\t%-8s\t%-s\n",
"NAME", "SCHEDULE", "SUSPEND", "ACTIVE", "LAST SCHEDULE", "AGE")
case "resourcedistributions.apps.kruise.io":
fmt.Fprintf(o.Out, "%-12s\t%-8s\t%-8s\t%-8s\t%-s\n",
"NAME", "TARGETS", "SUCCEEDED", "FAILED", "AGE")
case "uniteddeployments.apps.kruise.io":
fmt.Fprintf(o.Out, "%-12s\t%-8s\t%-8s\t%-8s\t%-8s\t%-s\n",
"NAME", "DESIRED", "UPDATED", "READY", "AVAILABLE", "AGE")
case "sidecarsets.apps.kruise.io":
fmt.Fprintf(o.Out, "%-12s\t%-8s\t%-8s\t%-8s\t%-8s\t%-s\n",
"NAME", "MATCHED", "UPDATED", "READY", "INJECTED", "AGE")
case "podprobemarkers.apps.kruise.io":
fmt.Fprintf(o.Out, "%-12s\t%-8s\t%-8s\t%-s\n",
"NAME", "TARGETS", "PROBES", "AGE")
case "imagepulljobs.apps.kruise.io":
fmt.Fprintf(o.Out, "%-12s\t%-8s\t%-8s\t%-8s\t%-8s\t%-s\n",
"NAME", "PHASE", "COMPLETED", "FAILED", "TOTAL", "AGE")
case "podunavailablebudgets.policy.kruise.io":
fmt.Fprintf(o.Out, "%-12s\t%-8s\t%-8s\t%-8s\t%-8s\t%-s\n",
"NAME", "MAXUNAVAILABLE", "UNAVAILABLE", "DISRUPTIONS", "TARGETS", "AGE")
}
for _, info := range infos {
if err := o.printResourceInfo(info.Object, resourceType); err != nil {
return err
}
}
}
}
return nil
}
// Handle single resource type
b := o.Builder().
WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...).
NamespaceParam(o.Namespace).DefaultNamespace().
ResourceTypeOrNameArgs(true, o.Resources...).
ContinueOnError().
Latest().
Flatten()
infos, err := b.Do().Infos()
if err != nil {
return err
}
if len(infos) > 0 {
switch o.Resources[0] {
case "clonesets.apps.kruise.io":
fmt.Fprintf(o.Out, "%-12s\t%-8s\t%-8s\t%-14s\t%-18s\t%-8s\t%-8s\t%-s\n",
"NAME", "DESIRED", "UPDATED", "UPDATED_READY", "UPDATED_AVAILABLE", "READY", "TOTAL", "AGE")
case "statefulsets.apps.kruise.io":
fmt.Fprintf(o.Out, "%-12s\t%-8s\t%-8s\t%-8s\t%-8s\t%-s\n",
"NAME", "DESIRED", "CURRENT", "UPDATED", "READY", "AGE")
case "daemonsets.apps.kruise.io":
fmt.Fprintf(o.Out, "%-8s\t%-8s\t%-8s\t%-8s\t%-8s\t%-8s\t%-8s\t%-s\n",
"NAME", "DESIRED", "CURRENT", "READY", "UP-TO-DATE", "AVAILABLE", "NODE SELECTOR", "AGE")
case "rollouts.rollouts.kruise.io":
fmt.Fprintf(o.Out, "%-20s\t%-8s\t%-12s\t%-12s\t%-40s\t%-s\n",
"NAME", "STATUS", "CANARY_STEP", "CANARY_STATE", "MESSAGE", "AGE")
case "broadcastjobs.apps.kruise.io":
fmt.Fprintf(o.Out, "%-12s\t%-8s\t%-8s\t%-8s\t%-8s\t%-s\n",
"NAME", "DESIRED", "ACTIVE", "SUCCEEDED", "FAILED", "AGE")
case "containerrecreaterequests.apps.kruise.io":
fmt.Fprintf(o.Out, "%-12s\t%-8s\t%-8s\t%-8s\t%-s\n",
"NAME", "PHASE", "COMPLETED", "FAILED", "AGE")
case "advancedcronjobs.apps.kruise.io":
fmt.Fprintf(o.Out, "%-12s\t%-8s\t%-8s\t%-8s\t%-8s\t%-s\n",
"NAME", "SCHEDULE", "SUSPEND", "ACTIVE", "LAST SCHEDULE", "AGE")
case "resourcedistributions.apps.kruise.io":
fmt.Fprintf(o.Out, "%-12s\t%-8s\t%-8s\t%-8s\t%-s\n",
"NAME", "TARGETS", "SUCCEEDED", "FAILED", "AGE")
case "uniteddeployments.apps.kruise.io":
fmt.Fprintf(o.Out, "%-12s\t%-8s\t%-8s\t%-8s\t%-8s\t%-s\n",
"NAME", "DESIRED", "UPDATED", "READY", "AVAILABLE", "AGE")
}
for _, info := range infos {
if err := o.printResourceInfo(info.Object, o.Resources[0]); err != nil {
return err
}
}
}
return nil
}
func (o *GetOptions) printResourceInfo(obj runtime.Object, resourceType string) error {
metaObj, ok := obj.(v1.Object)
if !ok {
return fmt.Errorf("object does not implement v1.Object interface")
}
name := metaObj.GetName()
age := time.Since(metaObj.GetCreationTimestamp().Time).Round(time.Second)
// Print based on resource type
switch resourceType {
case "clonesets.apps.kruise.io":
cloneset, ok := obj.(*kruiseappsv1alpha1.CloneSet)
if !ok {
return fmt.Errorf("object is not a CloneSet")
}
desired := cloneset.Spec.Replicas
updated := cloneset.Status.UpdatedReplicas
updatedReady := cloneset.Status.UpdatedReadyReplicas
updatedAvailable := cloneset.Status.UpdatedAvailableReplicas
ready := cloneset.Status.ReadyReplicas
total := cloneset.Status.Replicas
fmt.Fprintf(o.Out, "%-12s\t%-8d\t%-8d\t%-14d\t%-18d\t%-8d\t%-8d\t%-s\n",
name, *desired, updated, updatedReady, updatedAvailable, ready, total, age)
case "statefulsets.apps.kruise.io":
statefulset, ok := obj.(*kruiseappsv1beta1.StatefulSet)
if !ok {
return fmt.Errorf("object is not a StatefulSet")
}
desired := statefulset.Spec.Replicas
current := statefulset.Status.CurrentReplicas
updated := statefulset.Status.UpdatedReplicas
ready := statefulset.Status.ReadyReplicas
fmt.Fprintf(o.Out, "%-12s\t%-8d\t%-8d\t%-8d\t%-8d\t%-s\n",
name, *desired, current, updated, ready, age)
case "daemonsets.apps.kruise.io":
daemonset, ok := obj.(*kruiseappsv1alpha1.DaemonSet)
if !ok {
return fmt.Errorf("object is not a DaemonSet")
}
desired := daemonset.Status.DesiredNumberScheduled
current := daemonset.Status.CurrentNumberScheduled
ready := daemonset.Status.NumberReady
updated := daemonset.Status.UpdatedNumberScheduled
available := daemonset.Status.NumberAvailable
nodeSelector := daemonset.Spec.Template.Spec.NodeSelector
fmt.Fprintf(o.Out, "%-8s\t%-8d\t%-8d\t%-8d\t%-8d\t%-8d\t%-8s\t%-s\n",
name, desired, current, ready, updated, available, fmt.Sprintf("%v", nodeSelector), age)
case "rollouts.rollouts.kruise.io":
rollout, ok := obj.(*rolloutv1beta1.Rollout)
if !ok {
rolloutV1alpha1, ok := obj.(*rolloutv1alpha1.Rollout)
if !ok {
return fmt.Errorf("object is not a Rollout")
}
status := rolloutV1alpha1.Status.Phase
canaryStep := int32(0)
canaryState := string(rolloutv1alpha1.CanaryStepStateCompleted)
message := rolloutV1alpha1.Status.Message
if rolloutV1alpha1.Status.CanaryStatus != nil {
canaryStep = rolloutV1alpha1.Status.CanaryStatus.CurrentStepIndex
canaryState = string(rolloutV1alpha1.Status.CanaryStatus.CurrentStepState)
}
fmt.Fprintf(o.Out, "%-20s\t%-8s\t%-12d\t%-12s\t%-40s\t%-s\n",
name, status, canaryStep, canaryState, message, age)
return nil
}
status := rollout.Status.Phase
canaryStep := int32(0)
canaryState := string(rolloutv1beta1.CanaryStepStateCompleted)
message := rollout.Status.Message
if rollout.Status.CanaryStatus != nil {
canaryStep = rollout.Status.CanaryStatus.CurrentStepIndex
canaryState = string(rollout.Status.CanaryStatus.CurrentStepState)
}
fmt.Fprintf(o.Out, "%-20s\t%-8s\t%-12d\t%-12s\t%-40s\t%-s\n",
name, status, canaryStep, canaryState, message, age)
case "broadcastjobs.apps.kruise.io":
broadcastjob, ok := obj.(*kruiseappsv1alpha1.BroadcastJob)
if !ok {
return fmt.Errorf("object is not a BroadcastJob")
}
desired := broadcastjob.Spec.Parallelism
active := broadcastjob.Status.Active
successful := broadcastjob.Status.Succeeded
failed := broadcastjob.Status.Failed
fmt.Fprintf(o.Out, "%-12s\t%-8s\t%-8d\t%-8d\t%-8d\t%-s\n",
name, desired.String(), active, successful, failed, age)
case "containerrecreaterequests.apps.kruise.io":
containerrecreaterequest, ok := obj.(*kruiseappsv1alpha1.ContainerRecreateRequest)
if !ok {
return fmt.Errorf("object is not a ContainerRecreateRequest")
}
phase := containerrecreaterequest.Status.Phase
fmt.Fprintf(o.Out, "%-12s\t%-8s\t%-8s\t%-8s\t%-s\n",
name, phase, "-", "-", age)
case "advancedcronjobs.apps.kruise.io":
advancedcronjob, ok := obj.(*kruiseappsv1alpha1.AdvancedCronJob)
if !ok {
return fmt.Errorf("object is not a AdvancedCronJob")
}
schedule := advancedcronjob.Spec.Schedule
suspend := advancedcronjob.Spec.Paused
active := len(advancedcronjob.Status.Active)
lastSchedule := advancedcronjob.Status.LastScheduleTime
fmt.Fprintf(o.Out, "%-12s\t%-8s\t%-8v\t%-8d\t%-8s\t%-s\n",
name, schedule, suspend, active, lastSchedule, age)
case "resourcedistributions.apps.kruise.io":
_, ok := obj.(*kruiseappsv1alpha1.ResourceDistribution)
if !ok {
return fmt.Errorf("object is not a ResourceDistribution")
}
fmt.Fprintf(o.Out, "%-12s\t%-8s\t%-8s\t%-8s\t%-s\n",
name, "-", "-", "-", age)
case "uniteddeployments.apps.kruise.io":
uniteddeployment, ok := obj.(*kruiseappsv1alpha1.UnitedDeployment)
if !ok {
return fmt.Errorf("object is not a UnitedDeployment")
}
desired := uniteddeployment.Spec.Replicas
updated := uniteddeployment.Status.UpdatedReplicas
ready := uniteddeployment.Status.ReadyReplicas
total := uniteddeployment.Status.Replicas
fmt.Fprintf(o.Out, "%-12s\t%-8d\t%-8d\t%-8d\t%-8d\t%-s\n",
name, *desired, updated, ready, total, age)
case "sidecarsets.apps.kruise.io":
sidecarset, ok := obj.(*kruiseappsv1alpha1.SidecarSet)
if !ok {
return fmt.Errorf("object is not a SidecarSet")
}
matched := sidecarset.Status.MatchedPods
updated := sidecarset.Status.UpdatedPods
ready := sidecarset.Status.ReadyPods
fmt.Fprintf(o.Out, "%-12s\t%-8d\t%-8d\t%-8d\t%-8s\t%-s\n",
name, matched, updated, ready, "-", age)
case "podprobemarkers.apps.kruise.io":
podprobemarker, ok := obj.(*kruiseappsv1alpha1.PodProbeMarker)
if !ok {
return fmt.Errorf("object is not a PodProbeMarker")
}
targets := len(podprobemarker.Spec.Selector.MatchLabels)
probes := len(podprobemarker.Spec.Probes)
fmt.Fprintf(o.Out, "%-12s\t%-8d\t%-8d\t%-s\n",
name, targets, probes, age)
case "imagepulljobs.apps.kruise.io":
imagepulljob, ok := obj.(*kruiseappsv1alpha1.ImagePullJob)
if !ok {
return fmt.Errorf("object is not a ImagePullJob")
}
completed := imagepulljob.Status.Succeeded
failed := imagepulljob.Status.Failed
total := imagepulljob.Status.Desired
fmt.Fprintf(o.Out, "%-12s\t%-8s\t%-8d\t%-8d\t%-8d\t%-s\n",
name, "-", completed, failed, total, age)
case "podunavailablebudgets.policy.kruise.io":
pub, ok := obj.(*kruisepolicyv1alpha1.PodUnavailableBudget)
if !ok {
return fmt.Errorf("object is not a PodUnavailableBudget")
}
maxUnavailable := pub.Spec.MaxUnavailable
unavailable := pub.Status.UnavailablePods
disruptions := pub.Status.DisruptedPods
targets := len(pub.Spec.Selector.MatchLabels)
fmt.Fprintf(o.Out, "%-12s\t%-8s\t%-8d\t%-8d\t%-8d\t%-s\n",
name, maxUnavailable.String(), len(unavailable), len(disruptions), targets, age)
}
return nil
}

View File

@ -128,7 +128,7 @@ func (o *ApproveOptions) Validate() error {
}
// RunApprove performs the execution of 'rollout approve' sub command
func (o ApproveOptions) RunApprove() error {
func (o *ApproveOptions) RunApprove() error {
r := o.Builder().
WithScheme(internalapi.GetScheme(), scheme.Scheme.PrioritizedVersionsAllGroups()...).
NamespaceParam(o.Namespace).DefaultNamespace().

View File

@ -65,7 +65,10 @@ var (
kubectl-kruise rollout restart cloneset/abc
# 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
@ -80,7 +83,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"}
validArgs := []string{"deployment", "daemonset", "statefulset", "cloneset", "uniteddeployment"}
cmd := &cobra.Command{
Use: "restart RESOURCE",

View File

@ -20,15 +20,19 @@ package rollout
import (
"fmt"
rolloutsapi "github.com/openkruise/kruise-rollout-api/rollouts/v1beta1"
rolloutsapiv1alpha1 "github.com/openkruise/kruise-rollout-api/rollouts/v1alpha1"
rolloutsapiv1beta1 "github.com/openkruise/kruise-rollout-api/rollouts/v1beta1"
internalapi "github.com/openkruise/kruise-tools/pkg/api"
"github.com/openkruise/kruise-tools/pkg/cmd/util"
internalpolymorphichelpers "github.com/openkruise/kruise-tools/pkg/internal/polymorphichelpers"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/errors"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/cli-runtime/pkg/printers"
"k8s.io/cli-runtime/pkg/resource"
"k8s.io/kubectl/pkg/cmd/set"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/scheme"
"k8s.io/kubectl/pkg/util/i18n"
@ -49,6 +53,8 @@ type UndoOptions struct {
EnforceNamespace bool
RESTClientGetter genericclioptions.RESTClientGetter
Fast bool // fast rollback for blue-green
resource.FilenameOptions
genericclioptions.IOStreams
}
@ -71,7 +77,10 @@ var (
kubectl-kruise rollout undo --dry-run=server deployment/abc
# Rollback to workload via rollout api object
kubectl-kruise rollout undo rollout/abc`)
kubectl-kruise rollout undo rollout/abc
# Fast rollback during blue-green release (will go back to a previous step with no traffic and most replicas)
kubectl-kruise rollout undo rollout/abc --fast`)
)
// NewRolloutUndoOptions returns an initialized UndoOptions instance
@ -98,12 +107,17 @@ func NewCmdRolloutUndo(f cmdutil.Factory, streams genericclioptions.IOStreams) *
Run: func(cmd *cobra.Command, args []string) {
cmdutil.CheckErr(o.Complete(f, cmd, args))
cmdutil.CheckErr(o.Validate())
cmdutil.CheckErr(o.RunUndo())
if o.Fast {
cmdutil.CheckErr(o.FastUndo())
} else {
cmdutil.CheckErr(o.RunUndo())
}
},
ValidArgs: validArgs,
}
cmd.Flags().Int64Var(&o.ToRevision, "to-revision", o.ToRevision, "The revision to rollback to. Default to 0 (last revision).")
cmd.Flags().BoolVar(&o.Fast, "fast", false, "fast rollback for blue-green release")
usage := "identifying the resource to get from a server."
cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage)
cmdutil.AddDryRunFlag(cmd)
@ -143,6 +157,76 @@ func (o *UndoOptions) Validate() error {
return nil
}
func (o *UndoOptions) FastUndo() error {
r := o.Builder().
WithScheme(internalapi.GetScheme(), scheme.Scheme.PrioritizedVersionsAllGroups()...).
NamespaceParam(o.Namespace).DefaultNamespace().
FilenameParam(o.EnforceNamespace, &o.FilenameOptions).
ResourceTypeOrNameArgs(true, o.Resources...).
ContinueOnError().
Latest().
Flatten().
Do()
if err := r.Err(); err != nil {
return err
}
allErrs := []error{}
infos, err := r.Infos()
if err != nil {
// restore previous command behavior where
// an error caused by retrieving infos due to
// at least a single broken object did not result
// in an immediate return, but rather an overall
// aggregation of errors.
allErrs = append(allErrs, err)
}
for _, patch := range set.CalculatePatches(infos, scheme.DefaultJSONEncoder(), internalpolymorphichelpers.DefaultFastRollbackFunc) {
info := patch.Info
if patch.Err != nil {
resourceString := info.Mapping.Resource.Resource
if len(info.Mapping.Resource.Group) > 0 {
resourceString = resourceString + "." + info.Mapping.Resource.Group
}
allErrs = append(allErrs, fmt.Errorf("error: %s %q %v", resourceString, info.Name, patch.Err))
continue
}
if string(patch.Patch) == "{}" || len(patch.Patch) == 0 {
printer, err := o.ToPrinter("already rolled back")
if err != nil {
allErrs = append(allErrs, err)
continue
}
if err = printer.PrintObj(info.Object, o.Out); err != nil {
allErrs = append(allErrs, err)
}
continue
}
obj, err := util.PatchSubResource(info.Client, info.Mapping.Resource.Resource, "status", info.Namespace, info.Name, info.Namespaced(), types.MergePatchType, patch.Patch, nil)
if err != nil {
allErrs = append(allErrs, fmt.Errorf("failed to patch: %v", err))
continue
}
info.Refresh(obj, true)
printer, err := o.ToPrinter("rolled back" +
"")
if err != nil {
allErrs = append(allErrs, err)
continue
}
if err = printer.PrintObj(info.Object, o.Out); err != nil {
allErrs = append(allErrs, err)
}
}
return errors.NewAggregate(allErrs)
}
// RunUndo performs the execution of 'rollout undo' sub command
func (o *UndoOptions) RunUndo() error {
r := o.Builder().
@ -197,11 +281,10 @@ func (o *UndoOptions) RunUndo() error {
if obj == nil {
return fmt.Errorf("Rollout object not found")
}
ro, ok := obj.(*rolloutsapi.Rollout)
if !ok {
return fmt.Errorf("unsupported version of Rollout")
workloadRef, err := getWorkloadRefFromRollout(obj)
if err != nil {
return err
}
workloadRef := ro.Spec.WorkloadRef
gv, err := schema.ParseGroupVersion(workloadRef.APIVersion)
if err != nil {
return err
@ -246,3 +329,19 @@ func (o *UndoOptions) RunUndo() error {
aggErrs = append(aggErrs, err)
return errors.NewAggregate(aggErrs)
}
func getWorkloadRefFromRollout(obj interface{}) (workloadRef *rolloutsapiv1beta1.ObjectRef, err error) {
switch rollout := obj.(type) {
case *rolloutsapiv1alpha1.Rollout:
workloadRef = &rolloutsapiv1beta1.ObjectRef{
Kind: rollout.Spec.ObjectRef.WorkloadRef.Kind,
APIVersion: rollout.Spec.ObjectRef.WorkloadRef.APIVersion,
Name: rollout.Spec.ObjectRef.WorkloadRef.Name,
}
case *rolloutsapiv1beta1.Rollout:
workloadRef = &rollout.Spec.WorkloadRef
default:
return nil, fmt.Errorf("unsupported version of Rollout")
}
return workloadRef, nil
}

View File

@ -0,0 +1,8 @@
package polymorphichelpers
import (
rolloutschema "github.com/openkruise/kruise-rollout-api/rollouts/v1beta1"
"k8s.io/apimachinery/pkg/runtime"
)
type RolloutViewer func(obj runtime.Unstructured) (*rolloutschema.Rollout, error)

View File

@ -0,0 +1,55 @@
/*
Copyright 2024 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 polymorphichelpers
import (
"fmt"
kruiseappsv1alpha1 "github.com/openkruise/kruise-api/apps/v1alpha1"
kruiseappsv1beta1 "github.com/openkruise/kruise-api/apps/v1beta1"
kruisepolicyv1alpha1 "github.com/openkruise/kruise-api/policy/v1alpha1"
rolloutv1alpha1 "github.com/openkruise/kruise-rollout-api/rollouts/v1alpha1"
rolloutv1beta1 "github.com/openkruise/kruise-rollout-api/rollouts/v1beta1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/cli-runtime/pkg/printers"
)
// getViewer returns a printer for Kruise resources
func getViewer(obj runtime.Object) (interface{}, error) {
switch obj.(type) {
case *kruiseappsv1alpha1.CloneSet,
*kruiseappsv1beta1.StatefulSet,
*kruiseappsv1alpha1.DaemonSet,
*rolloutv1beta1.Rollout,
*rolloutv1alpha1.Rollout,
*kruiseappsv1alpha1.BroadcastJob,
*kruiseappsv1alpha1.ContainerRecreateRequest,
*kruiseappsv1alpha1.AdvancedCronJob,
*kruiseappsv1alpha1.ResourceDistribution,
*kruiseappsv1alpha1.UnitedDeployment,
*kruiseappsv1alpha1.SidecarSet,
*kruiseappsv1alpha1.PodProbeMarker,
*kruiseappsv1alpha1.ImagePullJob,
*kruisepolicyv1alpha1.PodUnavailableBudget:
return printers.NewTablePrinter(printers.PrintOptions{
WithKind: true,
WithNamespace: true,
}), nil
default:
return nil, fmt.Errorf("no viewer has been implemented for %T", obj)
}
}

View File

@ -25,6 +25,7 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/client-go/rest"
"k8s.io/kubectl/pkg/cmd/set"
)
// LogsForObjectFunc is a function type that can tell you how to get logs for a runtime.object
@ -51,6 +52,10 @@ type StatusViewerFunc func(mapping *meta.RESTMapping) (StatusViewer, error)
// StatusViewerFn gives a way to easily override the function for unit testing if needed
var StatusViewerFn StatusViewerFunc = statusViewer
type RolloutViewerFunc func(obj runtime.Object) (interface{}, error)
var RolloutViewerFn RolloutViewerFunc = rolloutViewer
// UpdatePodSpecForObjectFunc will call the provided function on the pod spec this object supports,
// return false if no pod spec is supported, or return an error.
type UpdatePodSpecForObjectFunc func(obj runtime.Object, fn func(*v1.PodSpec) error) (bool, error)
@ -58,6 +63,10 @@ type UpdatePodSpecForObjectFunc func(obj runtime.Object, fn func(*v1.PodSpec) er
// UpdatePodSpecForObjectFn gives a way to easily override the function for unit testing if needed
var UpdatePodSpecForObjectFn UpdatePodSpecForObjectFunc = updatePodSpecForObject
type GetViewerFunc func(obj runtime.Object) (interface{}, error)
var GetViewerFn GetViewerFunc = getViewer
// MapBasedSelectorForObjectFunc will call the provided function on mapping the baesd selector for object,
// return "" if object is not supported, or return an error.
type MapBasedSelectorForObjectFunc func(object runtime.Object) (string, error)
@ -120,3 +129,6 @@ type ObjectRestarterFunc func(runtime.Object) ([]byte, error)
// ObjectRestarterFn gives a way to easily override the function for unit testing if needed.
// Returns the patched object in bytes and any error that occurred during the encoding.
var ObjectRestarterFn ObjectRestarterFunc = defaultObjectRestarter
// DefaultFastRollbackFunc is a function type that rollbacks a rollout process.
var DefaultFastRollbackFunc set.PatchFn = defaultRolloutRollbackGetter(-1)

View File

@ -36,10 +36,20 @@ func defaultObjectApprover(obj runtime.Object) ([]byte, error) {
obj.Status.CanaryStatus.CurrentStepState = rolloutsapiv1alpha1.CanaryStepStateReady
return runtime.Encode(scheme.Codecs.LegacyCodec(rolloutsapiv1alpha1.GroupVersion), obj)
case *rolloutsapiv1beta1.Rollout:
if obj.Status.CanaryStatus == nil || obj.Status.CanaryStatus.CurrentStepState != rolloutsapiv1beta1.CanaryStepStatePaused {
return nil, errors.New("does not allow to approve, because current canary state is not 'StepPaused'")
switch {
case obj.Status.CanaryStatus != nil:
if obj.Status.CanaryStatus.CurrentStepState != rolloutsapiv1beta1.CanaryStepStatePaused {
return nil, fmt.Errorf("does not allow to approve, because current canary state is not '%s'", rolloutsapiv1beta1.CanaryStepStatePaused)
}
obj.Status.CanaryStatus.CurrentStepState = rolloutsapiv1beta1.CanaryStepStateReady
case obj.Status.BlueGreenStatus != nil:
if obj.Status.BlueGreenStatus.CurrentStepState != rolloutsapiv1beta1.CanaryStepStatePaused {
return nil, fmt.Errorf("does not allow to approve, because current blue-green state is not '%s'", rolloutsapiv1beta1.CanaryStepStatePaused)
}
obj.Status.BlueGreenStatus.CurrentStepState = rolloutsapiv1beta1.CanaryStepStateReady
default:
return nil, fmt.Errorf("no need to approve: not in canary or blue-green progress")
}
obj.Status.CanaryStatus.CurrentStepState = rolloutsapiv1beta1.CanaryStepStateReady
return runtime.Encode(scheme.Codecs.LegacyCodec(rolloutsapiv1beta1.GroupVersion), obj)
default:

View File

@ -0,0 +1,38 @@
/*
Copyright 2018 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 polymorphichelpers
import (
"fmt"
"k8s.io/apimachinery/pkg/runtime"
rolloutv1alpha1 "github.com/openkruise/kruise-rollout-api/rollouts/v1alpha1"
rolloutv1beta1 "github.com/openkruise/kruise-rollout-api/rollouts/v1beta1"
)
// statusViewer returns a StatusViewer for printing rollout status.
func rolloutViewer(obj runtime.Object) (interface{}, error) {
if rollout, ok := obj.(*rolloutv1beta1.Rollout); ok {
return rollout, nil
}
if rollout, ok := obj.(*rolloutv1alpha1.Rollout); ok {
return rollout, nil
}
return nil, fmt.Errorf("unknown rollout type: %T", obj)
}

View File

@ -0,0 +1,79 @@
package polymorphichelpers
import (
"fmt"
"github.com/openkruise/kruise-rollout-api/rollouts/v1beta1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/klog/v2"
"k8s.io/kubectl/pkg/scheme"
)
func defaultRolloutRollbackGetter(targetStep int32) func(runtime.Object) ([]byte, error) {
return func(obj runtime.Object) ([]byte, error) {
switch rollout := obj.(type) {
case *v1beta1.Rollout:
steps := rollout.Spec.Strategy.GetSteps()
curStep := rollout.Status.CurrentStepIndex
if len(steps) < int(curStep) {
return nil, fmt.Errorf("has %d steps, but current step is too large %d", len(steps), curStep)
}
if curStep <= 1 {
return nil, fmt.Errorf("already at the first step")
}
if targetStep == -1 {
s, err := findPreviousStepWithNoTrafficAndMostReplicas(steps, rollout.Status.CurrentStepIndex)
if err != nil {
return nil, err
}
targetStep = s
}
if targetStep >= rollout.Status.CurrentStepIndex {
return nil, fmt.Errorf("specified step %d is not a previous step (current step is %d)", targetStep, rollout.Status.CurrentStepIndex)
}
style := rollout.Spec.Strategy.GetRollingStyle()
switch style {
case v1beta1.BlueGreenRollingStyle:
rollout.Status.BlueGreenStatus.NextStepIndex = targetStep
default:
// canary and partition
rollout.Status.CanaryStatus.NextStepIndex = targetStep
}
return runtime.Encode(scheme.Codecs.LegacyCodec(v1beta1.GroupVersion), rollout)
default:
return nil, fmt.Errorf("rollback is not supported on given object")
}
}
}
func findPreviousStepWithNoTrafficAndMostReplicas(steps []v1beta1.CanaryStep, curStep int32) (int32, error) {
maxReplicas := 0
var targetStep int32 = -1
for i := curStep - 2; i >= 0; i-- {
step := steps[i]
if hasTraffic(step) {
klog.V(5).InfoS("has traffic", "step", i+1)
continue
}
replicas, _ := intstr.GetScaledValueFromIntOrPercent(step.Replicas, 100, true)
klog.V(5).InfoS("replicas percent", "percent", replicas, "step", i+1, "obj", step)
if replicas > maxReplicas {
maxReplicas = replicas
targetStep = i + 1
}
}
if targetStep == -1 {
return 0, fmt.Errorf("no previous step with no traffic found")
}
return targetStep, nil
}
func hasTraffic(step v1beta1.CanaryStep) bool {
if step.Traffic == nil {
return false
}
is := intstr.FromString(*step.Traffic)
trafficPercent, _ := intstr.GetScaledValueFromIntOrPercent(&is, 100, true)
return trafficPercent != 0
}

View File

@ -0,0 +1,162 @@
package polymorphichelpers
import (
"encoding/json"
"testing"
"github.com/openkruise/kruise-rollout-api/rollouts/v1alpha1"
"github.com/openkruise/kruise-rollout-api/rollouts/v1beta1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/kubectl/pkg/scheme"
"sigs.k8s.io/controller-runtime/pkg/client"
)
func init() {
_ = v1beta1.AddToScheme(scheme.Scheme)
}
func TestRolloutRollbackGetter(t *testing.T) {
getRollout := func(currentIdx int32, steps []v1beta1.CanaryStep) []client.Object {
canary := &v1beta1.Rollout{
Status: v1beta1.RolloutStatus{
CurrentStepIndex: currentIdx,
},
}
canary.Spec.Strategy.Canary = &v1beta1.CanaryStrategy{
Steps: steps,
EnableExtraWorkloadForCanary: true,
}
canary.Status.CanaryStatus = &v1beta1.CanaryStatus{}
blueGreen := canary.DeepCopy()
blueGreen.Spec.Strategy.BlueGreen = &v1beta1.BlueGreenStrategy{
Steps: steps,
}
blueGreen.Status.BlueGreenStatus = &v1beta1.BlueGreenStatus{}
return []client.Object{canary, blueGreen}
}
newStep := func(replicas string, traffic string) v1beta1.CanaryStep {
r := intstr.FromString(replicas)
var trafficPtr *string
if traffic != "" {
trafficPtr = &traffic
}
return v1beta1.CanaryStep{
Replicas: &r,
TrafficRoutingStrategy: v1beta1.TrafficRoutingStrategy{
Traffic: trafficPtr,
},
}
}
tests := []struct {
name string
rollout []client.Object
targetStep int32
expectedStep int32
expectedErr string
}{
{
name: "valid rollback to previous step",
rollout: getRollout(3, []v1beta1.CanaryStep{
newStep("10%", ""),
newStep("20%", ""),
newStep("30%", ""),
}),
targetStep: 2,
expectedStep: 2,
},
{
name: "invalid rollback to same or future step",
rollout: getRollout(3, []v1beta1.CanaryStep{
newStep("10%", ""),
newStep("20%", ""),
newStep("30%", ""),
}),
targetStep: 3,
expectedErr: "specified step 3 is not a previous step (current step is 3)",
},
{
name: "rollback to previous step with no traffic and most replicas",
rollout: getRollout(4, []v1beta1.CanaryStep{
newStep("10%", ""),
newStep("20%", ""),
newStep("30%", "50%"),
newStep("40%", "50%"),
}),
targetStep: -1,
expectedStep: 2,
},
{
name: "no previous step with no traffic found",
rollout: getRollout(5, []v1beta1.CanaryStep{
newStep("10%", "10%"),
newStep("20%", "10%"),
newStep("30%", "10%"),
newStep("40%", "10%"),
newStep("50%", "10%"),
}),
targetStep: -1,
expectedErr: "no previous step with no traffic found",
},
{
name: "already at the first step",
rollout: getRollout(1, []v1beta1.CanaryStep{
newStep("10%", ""),
}),
targetStep: 2,
expectedErr: "already at the first step",
},
{
name: "current step index out of range",
rollout: getRollout(3, []v1beta1.CanaryStep{
newStep("10%", ""),
newStep("20%", ""),
}),
targetStep: 2,
expectedErr: "has 2 steps, but current step is too large 3",
},
{
name: "not supported object",
rollout: []client.Object{&v1alpha1.Rollout{}},
expectedErr: "rollback is not supported on given object",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
rollback := defaultRolloutRollbackGetter(tt.targetStep)
for _, rollout := range tt.rollout {
data, err := rollback(rollout)
if tt.expectedErr != "" {
if err == nil || err.Error() != tt.expectedErr {
t.Errorf("expected error %v, got %v", tt.expectedErr, err)
}
return
}
if err != nil {
t.Errorf("unexpected error: %v", err)
return
}
var updatedRollout v1beta1.Rollout
if err := json.Unmarshal(data, &updatedRollout); err != nil {
t.Errorf("failed to unmarshal updated rollout: %v", err)
return
}
var nextStepIndex int32
if updatedRollout.Spec.Strategy.GetRollingStyle() == v1beta1.BlueGreenRollingStyle {
nextStepIndex = updatedRollout.Status.BlueGreenStatus.NextStepIndex
} else {
nextStepIndex = updatedRollout.Status.CanaryStatus.NextStepIndex
}
if nextStepIndex != tt.expectedStep {
t.Errorf("expected next step index %d, got %d", tt.expectedStep, nextStepIndex)
}
}
})
}
}

View File

@ -22,10 +22,7 @@ import (
"sync"
"time"
appsv1alpha1 "github.com/openkruise/kruise-api/apps/v1alpha1"
"github.com/openkruise/kruise-tools/pkg/api"
"github.com/openkruise/kruise-tools/pkg/migration"
"github.com/openkruise/kruise-tools/pkg/utils"
"k8s.io/client-go/discovery"
apps "k8s.io/api/apps/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -35,10 +32,15 @@ import (
"k8s.io/apimachinery/pkg/util/uuid"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/rest"
"k8s.io/client-go/restmapper"
"k8s.io/client-go/util/workqueue"
"sigs.k8s.io/controller-runtime/pkg/cache"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
appsv1alpha1 "github.com/openkruise/kruise-api/apps/v1alpha1"
"github.com/openkruise/kruise-tools/pkg/api"
"github.com/openkruise/kruise-tools/pkg/migration"
"github.com/openkruise/kruise-tools/pkg/utils"
)
var (
@ -81,10 +83,16 @@ func NewControl(cfg *rest.Config, stopChan <-chan struct{}) (migration.Control,
if err != nil {
return nil, err
}
mapper, err := apiutil.NewDiscoveryRESTMapper(cfg, c)
// Get a mapper
dc, err := discovery.NewDiscoveryClientForConfigAndClient(cfg, c)
if err != nil {
return nil, err
}
gr, err := restmapper.GetAPIGroupResources(dc)
if err != nil {
return nil, err
}
mapper := restmapper.NewDiscoveryRESTMapper(gr)
ctrl := &control{
stopChan: stopChan,

73
pkg/utils/math_test.go Normal file
View File

@ -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)
}
})
}
}

132
pkg/utils/misc_test.go Normal file
View File

@ -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)
}
})
}
}