fix rollout and game struct err (#158)

Signed-off-by: 刘硕 <liushuo@zetyun.com>
Co-authored-by: 刘硕 <liushuo@zetyun.com>
This commit is contained in:
ls-2018 2024-02-22 10:36:01 +08:00 committed by GitHub
parent 544cf948d8
commit fc9b63d512
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
30 changed files with 866 additions and 226 deletions

View File

@ -73,7 +73,7 @@ jobs:
- uses: actions/checkout@v1
- uses: actions/setup-python@v4
with:
python-version: '3.10'
python-version: '3.10'
- name: TypoCheck
run: |
pip3 install bs4 markdown html2markdown language_tool_python
@ -84,6 +84,9 @@ jobs:
steps:
- uses: actions/checkout@v1
- uses: actions/setup-go@v4
- uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: StructCheck
run: |
cd .github/workflows && go run .
cd .github/workflows && python3 version_struct_check.py

12
.github/workflows/game/struct_check.go vendored Normal file
View File

@ -0,0 +1,12 @@
package main
import (
"check/utils"
kruiseGamev1alpha1 "github.com/openkruise/kruise-game/apis/v1alpha1"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
)
func main() {
kruiseGamev1alpha1.AddToScheme(clientgoscheme.Scheme)
utils.Handle()
}

1
.github/workflows/game/utils vendored Symbolic link
View File

@ -0,0 +1 @@
../utils

View File

@ -1,30 +0,0 @@
module github.com/openkruise/openkruise.io
go 1.18
require (
github.com/openkruise/kruise v1.5.1
github.com/pkg/errors v0.9.1
k8s.io/apimachinery v0.28.2
k8s.io/client-go v0.28.2
)
require (
github.com/go-logr/logr v1.2.4 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
golang.org/x/net v0.13.0 // indirect
golang.org/x/text v0.11.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
k8s.io/api v0.28.2 // indirect
k8s.io/klog/v2 v2.100.1 // indirect
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 // indirect
sigs.k8s.io/controller-runtime v0.12.1 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)

View File

@ -1,97 +0,0 @@
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=
github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI=
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
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/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
github.com/openkruise/kruise v1.5.1 h1:Pwr99gkrJkW3uNH64RoCRXCXScP+oKxXDAEPJ2til3s=
github.com/openkruise/kruise v1.5.1/go.mod h1:ISWcBIPWGmmPi9mWjY8eRsqRAxd8vjgmam6CtmamfiA=
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/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
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.13.0 h1:Nvo8UFsZ8X3BhAC9699Z1j7XQ3rsZnUUm7jfBEk1ueY=
golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
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/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.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
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.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
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/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=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
k8s.io/api v0.28.2 h1:9mpl5mOb6vXZvqbQmankOfPIGiudghwCoLl1EYfUZbw=
k8s.io/api v0.28.2/go.mod h1:RVnJBsjU8tcMq7C3iaRSGMeaKt2TWEUXcpIt/90fjEg=
k8s.io/apimachinery v0.28.2 h1:KCOJLrc6gu+wV1BYgwik4AF4vXOlVJPdiqn0yAWWwXQ=
k8s.io/apimachinery v0.28.2/go.mod h1:RdzF87y/ngqk9H4z3EL2Rppv5jj95vGS/HaFXrLDApU=
k8s.io/client-go v0.28.2 h1:DNoYI1vGq0slMBN/SWKMZMw0Rq+0EQW6/AK4v9+3VeY=
k8s.io/client-go v0.28.2/go.mod h1:sMkApowspLuc7omj1FOSUxSoqjr+d5Q0Yc0LOFnYFJY=
k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg=
k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 h1:qY1Ad8PODbnymg2pRbkyMT/ylpTrCM8P2RJ0yroCyIk=
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/controller-runtime v0.12.1 h1:4BJY01xe9zKQti8oRjj/NeHKRXthf1YkYJAgLONFFoI=
sigs.k8s.io/controller-runtime v0.12.1/go.mod h1:BKhxlA4l7FPK4AQcsuL4X6vZeWnKDXez/vp1Y8dxTU0=
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/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=
sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E=
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=

View File

@ -0,0 +1,12 @@
package main
import (
"check/utils"
kruiseApi "github.com/openkruise/kruise/apis"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
)
func main() {
kruiseApi.AddToScheme(clientgoscheme.Scheme)
utils.Handle()
}

1
.github/workflows/kruise/utils vendored Symbolic link
View File

@ -0,0 +1 @@
../utils

View File

@ -0,0 +1,12 @@
package main
import (
"check/utils"
kruiseRolloutApi "github.com/openkruise/rollouts/api"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
)
func main() {
kruiseRolloutApi.AddToScheme(clientgoscheme.Scheme)
utils.Handle()
}

1
.github/workflows/rollouts-0.5/utils vendored Symbolic link
View File

@ -0,0 +1 @@
../utils

View File

@ -0,0 +1,12 @@
package main
import (
"check/utils"
kruiseRolloutApi "github.com/openkruise/rollouts/api/v1alpha1"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
)
func main() {
kruiseRolloutApi.AddToScheme(clientgoscheme.Scheme)
utils.Handle()
}

1
.github/workflows/rollouts/utils vendored Symbolic link
View File

@ -0,0 +1 @@
../utils

120
.github/workflows/utils/json/json.go vendored Normal file
View File

@ -0,0 +1,120 @@
/*
Copyright 2015 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 json
import (
"encoding/json"
"fmt"
"io"
kjson "sigs.k8s.io/json"
)
// NewEncoder delegates to json.NewEncoder
// It is only here so this package can be a drop-in for common encoding/json uses
func NewEncoder(w io.Writer) *json.Encoder {
return json.NewEncoder(w)
}
// Marshal delegates to json.Marshal
// It is only here so this package can be a drop-in for common encoding/json uses
func Marshal(v interface{}) ([]byte, error) {
return json.Marshal(v)
}
// limit recursive depth to prevent stack overflow errors
const maxDepth = 10000
// Unmarshal unmarshals the given data.
// Object keys are case-sensitive.
// Numbers decoded into interface{} fields are converted to int64 or float64.
func Unmarshal(data []byte, v interface{}) error {
return kjson.UnmarshalCaseSensitivePreserveInts(data, v)
}
// ConvertInterfaceNumbers converts any json.Number values to int64 or float64.
// Values which are map[string]interface{} or []interface{} are recursively visited
func ConvertInterfaceNumbers(v *interface{}, depth int) error {
var err error
switch v2 := (*v).(type) {
case json.Number:
*v, err = convertNumber(v2)
case map[string]interface{}:
err = ConvertMapNumbers(v2, depth+1)
case []interface{}:
err = ConvertSliceNumbers(v2, depth+1)
}
return err
}
// ConvertMapNumbers traverses the map, converting any json.Number values to int64 or float64.
// values which are map[string]interface{} or []interface{} are recursively visited
func ConvertMapNumbers(m map[string]interface{}, depth int) error {
if depth > maxDepth {
return fmt.Errorf("exceeded max depth of %d", maxDepth)
}
var err error
for k, v := range m {
switch v := v.(type) {
case json.Number:
m[k], err = convertNumber(v)
case map[string]interface{}:
err = ConvertMapNumbers(v, depth+1)
case []interface{}:
err = ConvertSliceNumbers(v, depth+1)
}
if err != nil {
return err
}
}
return nil
}
// ConvertSliceNumbers traverses the slice, converting any json.Number values to int64 or float64.
// values which are map[string]interface{} or []interface{} are recursively visited
func ConvertSliceNumbers(s []interface{}, depth int) error {
if depth > maxDepth {
return fmt.Errorf("exceeded max depth of %d", maxDepth)
}
var err error
for i, v := range s {
switch v := v.(type) {
case json.Number:
s[i], err = convertNumber(v)
case map[string]interface{}:
err = ConvertMapNumbers(v, depth+1)
case []interface{}:
err = ConvertSliceNumbers(v, depth+1)
}
if err != nil {
return err
}
}
return nil
}
// convertNumber converts a json.Number to an int64 or float64, or returns an error
func convertNumber(n json.Number) (interface{}, error) {
// Attempt to convert to an int64 first
if i, err := n.Int64(); err == nil {
return i, nil
}
// Return a float64 (default json.Decode() behavior)
// An overflow will return an error
return n.Float64()
}

View File

@ -1,25 +1,18 @@
package main
package utils
import (
"check/utils/yaml"
"encoding/base64"
rawJson "encoding/json"
"fmt"
"log"
//kruise "github.com/openkruise/kruise-api"
"io/fs"
"io/ioutil"
kruise "github.com/openkruise/kruise/apis"
"github.com/pkg/errors"
"io/ioutil"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer/json"
"k8s.io/apimachinery/pkg/util/yaml"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
"k8s.io/klog"
"os"
"path/filepath"
"regexp"
"strings"
)
@ -45,48 +38,64 @@ func VerifyUnmarshalStrict(schemes []*runtime.Scheme, gvk schema.GroupVersionKin
return nil
}
var compile, _ = regexp.Compile("```(?is)(.*?)```")
func RemoveInvalidCharacter(txt string) string {
_data := txt
for i := 10; i >= 3; i-- {
_data = strings.ReplaceAll(_data, strings.Repeat(".", i), "")
}
_data = strings.Trim(_data, " \n")
func main() {
kruise.AddToScheme(clientgoscheme.Scheme)
hasError := false
filepath.WalkDir("../..", func(path string, d fs.DirEntry, err error) error {
if !strings.HasSuffix(path, ".md") {
return nil
}
fmt.Println(path)
file, _ := ioutil.ReadFile(path)
for _, item := range compile.FindAllStringSubmatch(string(file), -1) {
if len(item) <= 1 {
continue
}
_data := strings.ReplaceAll(strings.TrimPrefix(item[1], "yaml"), "...", "")
for _, data := range strings.Split(_data, yamlSeparator) {
t := map[string]interface{}{}
yaml.Unmarshal([]byte(data), &(t))
gvk, _ := getGroupVersionKind(t)
if !strings.Contains(gvk.Group, "kruise") {
continue
}
err := VerifyUnmarshalStrict([]*runtime.Scheme{clientgoscheme.Scheme}, gvk, []byte(data))
switch _err := err.(type) {
case base64.CorruptInputError:
case nil:
default:
log.Fatalln(_err)
fmt.Println("file://" + path)
fmt.Println(data)
hasError = true
}
}
}
return nil
})
if hasError {
os.Exit(1)
if strings.HasPrefix(strings.ToLower(_data), "yaml") {
_data = _data[4:]
} else if strings.HasPrefix(strings.ToLower(_data), "yml") {
_data = _data[3:]
}
if strings.HasPrefix(strings.ToLower(_data), "shell\n") {
_data = strings.TrimPrefix(_data, "shell\n")
}
if strings.HasPrefix(strings.ToLower(_data), "cat ") {
_data = strings.Join(strings.Split(_data, "\n")[1:], "\n")
}
_data = strings.TrimSuffix(_data, "\nEOF")
return _data
}
type Item struct {
Yaml string `json:"yaml"`
Path string `json:"path"`
}
func Handle() {
jsonFilePath := os.Args[1]
file, _ := ioutil.ReadFile(jsonFilePath)
var fs []Item
rawJson.Unmarshal(file, &fs)
pan := false
for _, it := range fs {
tmpYaml := RemoveInvalidCharacter(it.Yaml)
t := map[string]interface{}{}
yaml.Unmarshal([]byte(tmpYaml), &(t))
gvk, _ := getGroupVersionKind(t)
if !strings.Contains(strings.ToLower(tmpYaml), "apiversion") {
continue
}
if !strings.Contains(gvk.Group, "kruise") {
continue
}
err := VerifyUnmarshalStrict([]*runtime.Scheme{clientgoscheme.Scheme}, gvk, []byte(tmpYaml))
switch _err := err.(type) {
case base64.CorruptInputError:
case nil:
default:
pan = true
klog.Errorln(it.Path)
klog.Errorln(it.Yaml, _err)
}
}
if pan {
klog.Fatalln("")
}
}
// getGroupVersionKind returns the GroupVersionKind of the object

395
.github/workflows/utils/yaml/decoder.go vendored Normal file
View File

@ -0,0 +1,395 @@
/*
Copyright 2014 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 yaml
import (
"bufio"
"bytes"
json2 "check/utils/json"
"encoding/json"
"fmt"
"io"
"sigs.k8s.io/yaml"
"strings"
"unicode"
)
// Unmarshal unmarshals the given data
// If v is a *map[string]interface{}, *[]interface{}, or *interface{} numbers
// are converted to int64 or float64
func Unmarshal(data []byte, v interface{}) error {
preserveIntFloat := func(d *json.Decoder) *json.Decoder {
d.UseNumber()
return d
}
switch v := v.(type) {
case *map[string]interface{}:
if err := yaml.Unmarshal(data, v, preserveIntFloat); err != nil {
return err
}
return json2.ConvertMapNumbers(*v, 0)
case *[]interface{}:
if err := yaml.Unmarshal(data, v, preserveIntFloat); err != nil {
return err
}
return json2.ConvertSliceNumbers(*v, 0)
case *interface{}:
if err := yaml.Unmarshal(data, v, preserveIntFloat); err != nil {
return err
}
return json2.ConvertInterfaceNumbers(v, 0)
default:
return yaml.Unmarshal(data, v)
}
}
// UnmarshalStrict unmarshals the given data
// strictly (erroring when there are duplicate fields).
func UnmarshalStrict(data []byte, v interface{}) error {
preserveIntFloat := func(d *json.Decoder) *json.Decoder {
d.UseNumber()
return d
}
switch v := v.(type) {
case *map[string]interface{}:
if err := yaml.UnmarshalStrict(data, v, preserveIntFloat); err != nil {
return err
}
return json2.ConvertMapNumbers(*v, 0)
case *[]interface{}:
if err := yaml.UnmarshalStrict(data, v, preserveIntFloat); err != nil {
return err
}
return json2.ConvertSliceNumbers(*v, 0)
case *interface{}:
if err := yaml.UnmarshalStrict(data, v, preserveIntFloat); err != nil {
return err
}
return json2.ConvertInterfaceNumbers(v, 0)
default:
return yaml.UnmarshalStrict(data, v)
}
}
// ToJSON converts a single YAML document into a JSON document
// or returns an error. If the document appears to be JSON the
// YAML decoding path is not used (so that error messages are
// JSON specific).
func ToJSON(data []byte) ([]byte, error) {
if hasJSONPrefix(data) {
return data, nil
}
return yaml.YAMLToJSON(data)
}
// YAMLToJSONDecoder decodes YAML documents from an io.Reader by
// separating individual documents. It first converts the YAML
// body to JSON, then unmarshals the JSON.
type YAMLToJSONDecoder struct {
reader Reader
}
// NewYAMLToJSONDecoder decodes YAML documents from the provided
// stream in chunks by converting each document (as defined by
// the YAML spec) into its own chunk, converting it to JSON via
// yaml.YAMLToJSON, and then passing it to json.Decoder.
func NewYAMLToJSONDecoder(r io.Reader) *YAMLToJSONDecoder {
reader := bufio.NewReader(r)
return &YAMLToJSONDecoder{
reader: NewYAMLReader(reader),
}
}
// Decode reads a YAML document as JSON from the stream or returns
// an error. The decoding rules match json.Unmarshal, not
// yaml.Unmarshal.
func (d *YAMLToJSONDecoder) Decode(into interface{}) error {
bytes, err := d.reader.Read()
if err != nil && err != io.EOF {
return err
}
if len(bytes) != 0 {
err := yaml.Unmarshal(bytes, into)
if err != nil {
return YAMLSyntaxError{err}
}
}
return err
}
// YAMLDecoder reads chunks of objects and returns ErrShortBuffer if
// the data is not sufficient.
type YAMLDecoder struct {
r io.ReadCloser
scanner *bufio.Scanner
remaining []byte
}
// NewDocumentDecoder decodes YAML documents from the provided
// stream in chunks by converting each document (as defined by
// the YAML spec) into its own chunk. io.ErrShortBuffer will be
// returned if the entire buffer could not be read to assist
// the caller in framing the chunk.
func NewDocumentDecoder(r io.ReadCloser) io.ReadCloser {
scanner := bufio.NewScanner(r)
// the size of initial allocation for buffer 4k
buf := make([]byte, 4*1024)
// the maximum size used to buffer a token 5M
scanner.Buffer(buf, 5*1024*1024)
scanner.Split(splitYAMLDocument)
return &YAMLDecoder{
r: r,
scanner: scanner,
}
}
// Read reads the previous slice into the buffer, or attempts to read
// the next chunk.
// TODO: switch to readline approach.
func (d *YAMLDecoder) Read(data []byte) (n int, err error) {
left := len(d.remaining)
if left == 0 {
// return the next chunk from the stream
if !d.scanner.Scan() {
err := d.scanner.Err()
if err == nil {
err = io.EOF
}
return 0, err
}
out := d.scanner.Bytes()
d.remaining = out
left = len(out)
}
// fits within data
if left <= len(data) {
copy(data, d.remaining)
d.remaining = nil
return left, nil
}
// caller will need to reread
copy(data, d.remaining[:len(data)])
d.remaining = d.remaining[len(data):]
return len(data), io.ErrShortBuffer
}
func (d *YAMLDecoder) Close() error {
return d.r.Close()
}
const yamlSeparator = "\n---"
const separator = "---"
// splitYAMLDocument is a bufio.SplitFunc for splitting YAML streams into individual documents.
func splitYAMLDocument(data []byte, atEOF bool) (advance int, token []byte, err error) {
if atEOF && len(data) == 0 {
return 0, nil, nil
}
sep := len([]byte(yamlSeparator))
if i := bytes.Index(data, []byte(yamlSeparator)); i >= 0 {
// We have a potential document terminator
i += sep
after := data[i:]
if len(after) == 0 {
// we can't read any more characters
if atEOF {
return len(data), data[:len(data)-sep], nil
}
return 0, nil, nil
}
if j := bytes.IndexByte(after, '\n'); j >= 0 {
return i + j + 1, data[0 : i-sep], nil
}
return 0, nil, nil
}
// If we're at EOF, we have a final, non-terminated line. Return it.
if atEOF {
return len(data), data, nil
}
// Request more data.
return 0, nil, nil
}
// decoder is a convenience interface for Decode.
type decoder interface {
Decode(into interface{}) error
}
// YAMLOrJSONDecoder attempts to decode a stream of JSON documents or
// YAML documents by sniffing for a leading { character.
type YAMLOrJSONDecoder struct {
r io.Reader
bufferSize int
decoder decoder
}
type JSONSyntaxError struct {
Offset int64
Err error
}
func (e JSONSyntaxError) Error() string {
return fmt.Sprintf("json: offset %d: %s", e.Offset, e.Err.Error())
}
type YAMLSyntaxError struct {
err error
}
func (e YAMLSyntaxError) Error() string {
return e.err.Error()
}
// NewYAMLOrJSONDecoder returns a decoder that will process YAML documents
// or JSON documents from the given reader as a stream. bufferSize determines
// how far into the stream the decoder will look to figure out whether this
// is a JSON stream (has whitespace followed by an open brace).
func NewYAMLOrJSONDecoder(r io.Reader, bufferSize int) *YAMLOrJSONDecoder {
return &YAMLOrJSONDecoder{
r: r,
bufferSize: bufferSize,
}
}
// Decode unmarshals the next object from the underlying stream into the
// provide object, or returns an error.
func (d *YAMLOrJSONDecoder) Decode(into interface{}) error {
if d.decoder == nil {
buffer, _, isJSON := GuessJSONStream(d.r, d.bufferSize)
if isJSON {
d.decoder = json.NewDecoder(buffer)
} else {
d.decoder = NewYAMLToJSONDecoder(buffer)
}
}
err := d.decoder.Decode(into)
if syntax, ok := err.(*json.SyntaxError); ok {
return JSONSyntaxError{
Offset: syntax.Offset,
Err: syntax,
}
}
return err
}
type Reader interface {
Read() ([]byte, error)
}
type YAMLReader struct {
reader Reader
}
func NewYAMLReader(r *bufio.Reader) *YAMLReader {
return &YAMLReader{
reader: &LineReader{reader: r},
}
}
// Read returns a full YAML document.
func (r *YAMLReader) Read() ([]byte, error) {
var buffer bytes.Buffer
for {
line, err := r.reader.Read()
if err != nil && err != io.EOF {
return nil, err
}
sep := len([]byte(separator))
if i := bytes.Index(line, []byte(separator)); i == 0 {
// We have a potential document terminator
i += sep
trimmed := strings.TrimSpace(string(line[i:]))
// We only allow comments and spaces following the yaml doc separator, otherwise we'll return an error
if len(trimmed) > 0 && string(trimmed[0]) != "#" {
return nil, YAMLSyntaxError{
err: fmt.Errorf("invalid Yaml document separator: %s", trimmed),
}
}
if buffer.Len() != 0 {
return buffer.Bytes(), nil
}
if err == io.EOF {
return nil, err
}
}
if err == io.EOF {
if buffer.Len() != 0 {
// If we're at EOF, we have a final, non-terminated line. Return it.
return buffer.Bytes(), nil
}
return nil, err
}
buffer.Write(line)
}
}
type LineReader struct {
reader *bufio.Reader
}
// Read returns a single line (with '\n' ended) from the underlying reader.
// An error is returned iff there is an error with the underlying reader.
func (r *LineReader) Read() ([]byte, error) {
var (
isPrefix bool = true
err error = nil
line []byte
buffer bytes.Buffer
)
for isPrefix && err == nil {
line, isPrefix, err = r.reader.ReadLine()
buffer.Write(line)
}
buffer.WriteByte('\n')
return buffer.Bytes(), err
}
// GuessJSONStream scans the provided reader up to size, looking
// for an open brace indicating this is JSON. It will return the
// bufio.Reader it creates for the consumer.
func GuessJSONStream(r io.Reader, size int) (io.Reader, []byte, bool) {
buffer := bufio.NewReaderSize(r, size)
b, _ := buffer.Peek(size)
return buffer, b, hasJSONPrefix(b)
}
// IsJSONBuffer scans the provided buffer, looking
// for an open brace indicating this is JSON.
func IsJSONBuffer(buf []byte) bool {
return hasJSONPrefix(buf)
}
var jsonPrefix = []byte("{")
// hasJSONPrefix returns true if the provided buffer appears to start with
// a JSON open brace.
func hasJSONPrefix(buf []byte) bool {
return hasPrefix(buf, jsonPrefix)
}
// Return true if the first non-whitespace bytes in buf is
// prefix.
func hasPrefix(buf []byte, prefix []byte) bool {
trim := bytes.TrimLeftFunc(buf, unicode.IsSpace)
return bytes.HasPrefix(trim, prefix)
}

View File

@ -0,0 +1,178 @@
import json
import os
import re
import subprocess
import sys
from collections import defaultdict
kruise_version_map = defaultdict(list)
kruise_game_version_map = defaultdict(list)
rollouts_version_map = defaultdict(list)
kruise_api_version_map = {
"policy.kruise.io/v1alpha1": "master",
"policy.kruise.io/v1beta1": "master",
"policy.kruise.io/v1": "master",
"apps.kruise.io/v1alpha1": "master",
"apps.kruise.io/v1beta1": "master",
"apps.kruise.io/v1": "master",
}
rollouts_api_version_map = {
"rollouts.kruise.io/v1alpha1": "master",
"rollouts.kruise.io/v1beta1": "master",
"rollouts.kruise.io/v1": "master",
}
game_api_version_map = {
"game.kruise.io/v1alpha1": "master",
"game.kruise.io/v1beta1": "master",
"game.kruise.io/v1": "master",
}
def fill_version_map():
def find_apiVersion(txt):
for item in txt.split('\n'):
if item.strip().lower().startswith('apiversion:'):
return item[len('apiversion:'):].strip()
def read_file(path, _d, v_m):
with open(path, 'r', encoding='utf8') as f:
text = f.read()
for match in re.finditer(r'```yaml(.*?)```', text, re.DOTALL):
content = match.group(1)
for yamlTxt in content.split('\n---'):
apiVersion = find_apiVersion(yamlTxt)
if apiVersion != "":
_d[v_m.get(apiVersion, 'master')].append(dict(yaml=content, path=path))
for cwd, dirs, files in os.walk('../..'):
for file in files:
p = os.path.join(cwd, file)
if not p.endswith('.md'):
continue
if 'rollouts' in p.lower():
read_file(p, rollouts_version_map, rollouts_api_version_map)
elif 'game' in p.lower():
read_file(p, kruise_game_version_map, game_api_version_map)
else:
read_file(p, kruise_version_map, kruise_api_version_map)
def _exec(command):
print(command)
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = process.communicate()
print("stdout:", stdout.decode())
print("stderr:", stderr.decode())
returncode = process.returncode
if returncode != 0:
sys.exit(returncode)
def _download_version(_f, version):
cmd = _f.format(version=version)
print(cmd)
code, out = subprocess.getstatusoutput(cmd)
print(out)
if code != 0:
sys.exit(code)
return code, out
kruise_format = 'cd ./kruise && ' \
'rm -rf go.* && ' \
'wget https://raw.githubusercontent.com/openkruise/kruise/{version}/go.mod && ' \
'go mod edit -module=check && ' \
'go get github.com/openkruise/kruise@{version} && ' \
'go mod edit -replace=github.com/openkruise/kruise=github.com/openkruise/kruise@{version} && ' \
'go get k8s.io/klog/v2 && ' \
'go get sigs.k8s.io/json && ' \
'go get sigs.k8s.io/yaml && ' \
'go mod tidy'
game_format = 'cd ./game && ' \
'rm -rf go.* && ' \
'wget https://raw.githubusercontent.com/openkruise/kruise-game/{version}/go.mod && ' \
'go mod edit -module=check && ' \
'go get github.com/openkruise/kruise-game@{version} && ' \
'go mod edit -replace=github.com/openkruise/kruise-game=github.com/openkruise/kruise-game@{version} && ' \
'go get k8s.io/klog/v2 && ' \
'go get sigs.k8s.io/yaml && ' \
'go get sigs.k8s.io/json && ' \
'go mod tidy'
rollouts_format = 'cd ./rollouts && ' \
'rm -rf go.* && ' \
'wget https://raw.githubusercontent.com/openkruise/rollouts/{version}/go.mod && ' \
'go mod edit -module=check && ' \
'go get github.com/openkruise/rollouts@{version} && ' \
'go mod edit -replace=github.com/openkruise/rollouts=github.com/openkruise/rollouts@{version} && ' \
'go get k8s.io/klog/v2 && ' \
'go get sigs.k8s.io/json && ' \
'go get sigs.k8s.io/yaml && ' \
'go mod tidy'
rollouts_0_5_format = 'cd ./rollouts-0.5 && ' \
'rm -rf go.* && ' \
'wget https://raw.githubusercontent.com/openkruise/rollouts/{version}/go.mod && ' \
'go mod edit -module=check && ' \
'go get github.com/openkruise/rollouts@{version} && ' \
'go mod edit -replace=github.com/openkruise/rollouts=github.com/openkruise/rollouts@{version} && ' \
'go get k8s.io/klog/v2 && ' \
'go get sigs.k8s.io/json && ' \
'go get sigs.k8s.io/yaml && ' \
'go mod tidy'
tmp_file_path = '/tmp/files.json'
def write_info(files):
with open(tmp_file_path, 'w', encoding='utf8') as f:
f.write(json.dumps(files, ensure_ascii=False, indent=4))
def handle():
for version, files in rollouts_version_map.items():
if version and version != 'master':
print(version)
less_0_5 = False
for item in ['0.1', '0.2', '0.3', '0.4']:
if version.startswith(item):
less_0_5 = True
if less_0_5:
_download_version(rollouts_format, "v" + version)
else:
_download_version(rollouts_0_5_format, "v" + version)
else:
print("master")
os.system(rollouts_format.format(version="master"))
write_info(files)
_exec('cd ./rollouts && go run . ' + tmp_file_path)
for version, files in kruise_game_version_map.items():
if version and version != 'master':
print(version)
_download_version(game_format, "v" + version)
else:
print("master")
_exec(game_format.format(version="master"))
write_info(files)
_exec('cd ./game && go run . ' + tmp_file_path)
for version, files in kruise_version_map.items():
if version and version != 'master':
print(version)
_download_version(kruise_format, "v" + version)
else:
print("master")
_exec(kruise_format.format(version="master"))
write_info(files)
_exec('cd ./kruise && go run . ' + tmp_file_path)
if __name__ == '__main__':
fill_version_map()
handle()

3
.gitignore vendored
View File

@ -21,3 +21,6 @@ npm-debug.log*
yarn-debug.log*
yarn-error.log*
.github/workflows/game/go.*
.github/workflows/kruise/go.*
.github/workflows/rollouts/go.*

View File

@ -312,6 +312,7 @@ spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/acs/minecraft-demo:1.12.2
name: minecraft
updateStrategy:
rollingUpdate:
podUpdatePolicy: InPlaceIfPossible
maxUnavailable: 100%

View File

@ -502,7 +502,7 @@ spec:
- name: PortProtocols
value: "xxx"
- name: Fixed
value: true
value: "true"
gameServerTemplate:
spec:
containers:

View File

@ -645,7 +645,7 @@ spec:
- name: PortProtocols
value: "xxx"
- name: Fixed
value: true
value: "true"
gameServerTemplate:
spec:
containers:

View File

@ -756,7 +756,7 @@ spec:
- name: PortProtocols
value: "xxx"
- name: Fixed
value: true
value: "true"
gameServerTemplate:
spec:
containers:

View File

@ -93,13 +93,15 @@ kind: Rollout
metadata:
namespace: <your-workload-ns>
spec:
trafficRoutings:
- service: <service-name-that-is-related-your-workload>
ingress:
classType: <traffic-type> # 例如nginx | higress默认为 "nginx"
name: <ingress-name-that-is-related-the-service>
gateway: # 或者选择使用 Ingress 或 GatewayAPI
httpRouteName: <gateway-api-httpRoute-name>
strategy:
canary:
trafficRoutings:
- service: <service-name-that-is-related-your-workload>
ingress:
classType: <traffic-type> # 例如nginx | higress默认为 "nginx"
name: <ingress-name-that-is-related-the-service>
gateway: # 或者选择使用 Ingress 或 GatewayAPI
httpRouteName: <gateway-api-httpRoute-name>
```
| 字段 | 类型 | 默认值 | 说明 |

View File

@ -38,11 +38,11 @@ spec:
value: pc
- replicas: 50%
- replicas: 100%
trafficRoutings:
- service: service-demo
ingress:
classType: nginx
name: ingress-demo
trafficRoutings:
- service: service-demo
ingress:
classType: nginx
name: ingress-demo
```
### 行为解释

View File

@ -25,11 +25,11 @@ spec:
canary:
steps:
- weight: 20
trafficRoutings:
- service: service-demo
ingress:
classType: nginx
name: ingress-demo
trafficRoutings:
- service: service-demo
ingress:
classType: nginx
name: ingress-demo
```
### 行为解释

View File

@ -93,13 +93,15 @@ kind: Rollout
metadata:
namespace: <your-workload-ns>
spec:
trafficRoutings:
- service: <service-name-that-is-related-your-workload>
ingress:
classType: <traffic-type> # 例如nginx | higress默认为 "nginx"
name: <ingress-name-that-is-related-the-service>
gateway: # 或者选择使用 Ingress 或 GatewayAPI
httpRouteName: <gateway-api-httpRoute-name>
strategy:
canary:
trafficRoutings:
- service: <service-name-that-is-related-your-workload>
ingress:
classType: <traffic-type> # 例如nginx | higress默认为 "nginx"
name: <ingress-name-that-is-related-the-service>
gateway: # 或者选择使用 Ingress 或 GatewayAPI
httpRouteName: <gateway-api-httpRoute-name>
```
| 字段 | 类型 | 默认值 | 说明 |

View File

@ -38,11 +38,11 @@ spec:
value: pc
- replicas: 50%
- replicas: 100%
trafficRoutings:
- service: service-demo
ingress:
classType: nginx
name: ingress-demo
trafficRoutings:
- service: service-demo
ingress:
classType: nginx
name: ingress-demo
```
### 行为解释

View File

@ -25,11 +25,11 @@ spec:
canary:
steps:
- weight: 20
trafficRoutings:
- service: service-demo
ingress:
classType: nginx
name: ingress-demo
trafficRoutings:
- service: service-demo
ingress:
classType: nginx
name: ingress-demo
```
### 行为解释

View File

@ -307,6 +307,7 @@ spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/acs/minecraft-demo:1.12.2
name: minecraft
updateStrategy:
rollingUpdate:
podUpdatePolicy: InPlaceIfPossible
maxUnavailable: 100%

View File

@ -29,7 +29,8 @@ apiVersion: rollouts.kruise.io/v1beta1
kind: Rollout
...
spec:
...
strategy:
canary:
trafficRoutings:
- service: <stable-service>
customNetworkRefs:

View File

@ -242,7 +242,7 @@ spec:
- traffic: 5%
replicas: 1 or 10%
pause:
duration: {}
duration: 0
matches:
- headers:
- type: Exact # or "RegularExpression"
@ -280,7 +280,7 @@ spec:
- weight: 5
replicas: 1 or 10%
pause:
duration: {}
duration: 0
matches:
- headers:
- type: Exact # or "RegularExpression"

View File

@ -48,12 +48,12 @@ spec:
apiVersion: apps/v1
kind: Deployment
name: workload-demo
strategy:
canary:
steps:
- replicas: 1
- replicas: 50%
- replicas: 100%
strategy:
canary:
steps:
- replicas: 1
- replicas: 50%
- replicas: 100%
```
</TabItem>