Compare commits
59 Commits
Author | SHA1 | Date |
---|---|---|
|
87f7e652ab | |
|
b2806f5dec | |
|
885497f5df | |
|
0c89ec8ca0 | |
|
087483f1ec | |
|
0fbc3ed8c4 | |
|
561de4fcbb | |
|
c19c76203e | |
|
deaa5f38b5 | |
|
6554cfcf08 | |
|
402cb9cd90 | |
|
2aa692dc2f | |
|
ca0a71ff52 | |
|
744430356d | |
|
6094e966ac | |
|
3e66fa1ad8 | |
|
7baf47d70e | |
|
334fa1cbf3 | |
|
3562934ae5 | |
|
faa2d03338 | |
|
5bbbc046b0 | |
|
efbd8ba8f9 | |
|
056c77dbd2 | |
|
3f66aae0ae | |
|
09e01cb95b | |
|
6854752435 | |
|
f0363f28c0 | |
|
d2613132aa | |
|
5378dc2cf7 | |
|
78273c2998 | |
|
16a3f0acc1 | |
|
6fae7085e5 | |
|
e7652cbc7c | |
|
db761a979c | |
|
aa28f4e12e | |
|
1e8af4a4c1 | |
|
62794dc883 | |
|
3eeb7b4ddc | |
|
07c1731e8a | |
|
25b053b8be | |
|
0ff23f6636 | |
|
678d4d2b34 | |
|
1e84129ff1 | |
|
83eedb354e | |
|
862040870d | |
|
e19a89c16e | |
|
bc580a3ae7 | |
|
897b42292c | |
|
75b1b90dc9 | |
|
9dcf3659d2 | |
|
07b7f20f6a | |
|
d41b1fa7d7 | |
|
a9a9430a9a | |
|
23f1e97f4e | |
|
57f9853f23 | |
|
76d33b830a | |
|
657c6d8079 | |
|
29862589aa | |
|
72e1c0b936 |
|
@ -10,24 +10,24 @@ on:
|
|||
|
||||
env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.17'
|
||||
GOLANGCI_VERSION: 'v1.42'
|
||||
GO_VERSION: '1.20'
|
||||
GOLANGCI_VERSION: 'v2.1'
|
||||
|
||||
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@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- 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') }}
|
||||
|
@ -36,25 +36,27 @@ jobs:
|
|||
run: |
|
||||
make generate
|
||||
- name: Lint golang code
|
||||
uses: golangci/golangci-lint-action@v2
|
||||
uses: golangci/golangci-lint-action@4afd733a84b1f43292c63897423277bb7f4313a9 # v8.0.0
|
||||
with:
|
||||
version: ${{ env.GOLANGCI_VERSION }}
|
||||
args: --verbose
|
||||
skip-pkg-cache: true
|
||||
mod: readonly
|
||||
|
||||
unit-tests:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Fetch History
|
||||
run: git fetch --prune --unshallow
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- 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') }}
|
||||
|
@ -62,11 +64,12 @@ jobs:
|
|||
- name: Run Unit Tests
|
||||
run: |
|
||||
make test
|
||||
git status
|
||||
[[ -z $(git status -s) ]] || (printf "Existing modified/untracked files.\nPlease run \"make generate manifests\" and push again.\n"; exit 1)
|
||||
- name: Publish Unit Test Coverage
|
||||
uses: codecov/codecov-action@v1
|
||||
uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5.4.3
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
flags: unittests
|
||||
file: cover.out
|
||||
- name: Check diff
|
||||
run: '[[ -z $(git status -s) ]] || (printf "Existing modified/untracked files.\nPlease run \"make generate manifests\" and push again.\n"; exit 1)'
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
name: Docker Image CI
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.HUB_KRUISE }}
|
||||
- name: Build the Docker image
|
||||
run: |
|
||||
docker buildx create --use --platform=linux/amd64,linux/arm64,linux/ppc64le --name multi-platform-builder
|
||||
docker buildx ls
|
||||
IMG=openkruise/kruise-rollout:${{ github.ref_name }} make docker-multiarch
|
|
@ -0,0 +1,121 @@
|
|||
name: E2E-Advanced-Deployment-1.24
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- release-*
|
||||
pull_request: {}
|
||||
workflow_dispatch: {}
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.20'
|
||||
KIND_CLUSTER_NAME: 'ci-testing'
|
||||
KIND_VERSION: 'v0.14.0'
|
||||
KIND_IMAGE: 'kindest/node:v1.24.6'
|
||||
|
||||
jobs:
|
||||
|
||||
rollout:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Setup Kind Cluster
|
||||
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
|
||||
with:
|
||||
node_image: ${{ env.KIND_IMAGE }}
|
||||
cluster_name: ${{ env.KIND_CLUSTER_NAME }}
|
||||
config: ./test/kind-conf.yaml
|
||||
version: ${{ env.KIND_VERSION }}
|
||||
- name: Build image
|
||||
run: |
|
||||
export IMAGE="openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID}"
|
||||
docker build --pull --no-cache . -t $IMAGE
|
||||
kind load docker-image --name=${KIND_CLUSTER_NAME} $IMAGE || { echo >&2 "kind not installed or error loading image: $IMAGE"; exit 1; }
|
||||
- name: Install Kruise
|
||||
run: |
|
||||
set -ex
|
||||
kubectl cluster-info
|
||||
make helm
|
||||
helm repo add openkruise https://openkruise.github.io/charts/
|
||||
helm repo update
|
||||
helm install kruise openkruise/kruise --version 1.7.0
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-system | grep '1/1' | grep kruise-controller-manager | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "2" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 3
|
||||
done
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-system | grep '1/1' | grep kruise-controller-manager | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "2" ]; then
|
||||
echo "Wait for kruise-manager ready successfully"
|
||||
else
|
||||
echo "Timeout to wait for kruise-manager ready"
|
||||
exit 1
|
||||
fi
|
||||
- name: Install Kruise Rollout
|
||||
run: |
|
||||
set -ex
|
||||
kubectl cluster-info
|
||||
IMG=openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID} ./scripts/deploy_kind.sh
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-rollout | grep '1/1' | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "1" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 3
|
||||
done
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-rollout | grep '1/1' | wc -l)
|
||||
kubectl get node -o yaml
|
||||
kubectl get all -n kruise-rollout -o yaml
|
||||
set -e
|
||||
if [ "$PODS" -eq "1" ]; then
|
||||
echo "Wait for kruise-rollout ready successfully"
|
||||
else
|
||||
echo "Timeout to wait for kruise-rollout ready"
|
||||
exit 1
|
||||
fi
|
||||
- name: Run E2E Tests For Advance Deployment
|
||||
run: |
|
||||
export KUBECONFIG=/home/runner/.kube/config
|
||||
make ginkgo
|
||||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='Advanced Deployment' test/e2e
|
||||
retVal=$?
|
||||
if [ "${retVal}" -ne 0 ];then
|
||||
echo "test fail, dump kruise-rollout logs"
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
fi
|
||||
exit $retVal
|
||||
- name: Run E2E Tests For Canary rollout of Advance Deployment
|
||||
run: |
|
||||
export KUBECONFIG=/home/runner/.kube/config
|
||||
make ginkgo
|
||||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='Canary rollout with Ingress using advance deployment' test/e2e
|
||||
retVal=$?
|
||||
if [ "${retVal}" -ne 0 ];then
|
||||
echo "test fail, dump kruise-rollout logs"
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
fi
|
||||
exit $retVal
|
|
@ -0,0 +1,121 @@
|
|||
name: E2E-Advanced-Deployment-1.26
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- release-*
|
||||
pull_request: {}
|
||||
workflow_dispatch: {}
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.20'
|
||||
KIND_VERSION: 'v0.18.0'
|
||||
KIND_IMAGE: 'kindest/node:v1.26.3'
|
||||
KIND_CLUSTER_NAME: 'ci-testing'
|
||||
|
||||
jobs:
|
||||
|
||||
rollout:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Setup Kind Cluster
|
||||
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
|
||||
with:
|
||||
node_image: ${{ env.KIND_IMAGE }}
|
||||
cluster_name: ${{ env.KIND_CLUSTER_NAME }}
|
||||
config: ./test/kind-conf.yaml
|
||||
version: ${{ env.KIND_VERSION }}
|
||||
- name: Build image
|
||||
run: |
|
||||
export IMAGE="openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID}"
|
||||
docker build --pull --no-cache . -t $IMAGE
|
||||
kind load docker-image --name=${KIND_CLUSTER_NAME} $IMAGE || { echo >&2 "kind not installed or error loading image: $IMAGE"; exit 1; }
|
||||
- name: Install Kruise
|
||||
run: |
|
||||
set -ex
|
||||
kubectl cluster-info
|
||||
make helm
|
||||
helm repo add openkruise https://openkruise.github.io/charts/
|
||||
helm repo update
|
||||
helm install kruise openkruise/kruise --version 1.7.0
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-system | grep '1/1' | grep kruise-controller-manager | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "2" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 3
|
||||
done
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-system | grep '1/1' | grep kruise-controller-manager | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "2" ]; then
|
||||
echo "Wait for kruise-manager ready successfully"
|
||||
else
|
||||
echo "Timeout to wait for kruise-manager ready"
|
||||
exit 1
|
||||
fi
|
||||
- name: Install Kruise Rollout
|
||||
run: |
|
||||
set -ex
|
||||
kubectl cluster-info
|
||||
IMG=openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID} ./scripts/deploy_kind.sh
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-rollout | grep '1/1' | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "1" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 3
|
||||
done
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-rollout | grep '1/1' | wc -l)
|
||||
kubectl get node -o yaml
|
||||
kubectl get all -n kruise-rollout -o yaml
|
||||
set -e
|
||||
if [ "$PODS" -eq "1" ]; then
|
||||
echo "Wait for kruise-rollout ready successfully"
|
||||
else
|
||||
echo "Timeout to wait for kruise-rollout ready"
|
||||
exit 1
|
||||
fi
|
||||
- name: Run E2E Tests For Deployment Controller
|
||||
run: |
|
||||
export KUBECONFIG=/home/runner/.kube/config
|
||||
make ginkgo
|
||||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='Advanced Deployment' test/e2e
|
||||
retVal=$?
|
||||
if [ "${retVal}" -ne 0 ];then
|
||||
echo "test fail, dump kruise-rollout logs"
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
fi
|
||||
exit $retVal
|
||||
- name: Run E2E Tests For Canary rollout of Advance Deployment
|
||||
run: |
|
||||
export KUBECONFIG=/home/runner/.kube/config
|
||||
make ginkgo
|
||||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='Canary rollout with Ingress using advance deployment' test/e2e
|
||||
retVal=$?
|
||||
if [ "${retVal}" -ne 0 ];then
|
||||
echo "test fail, dump kruise-rollout logs"
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
fi
|
||||
exit $retVal
|
|
@ -0,0 +1,121 @@
|
|||
name: E2E-Advanced-Deployment-1.28
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- release-*
|
||||
pull_request: {}
|
||||
workflow_dispatch: {}
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.20'
|
||||
KIND_VERSION: 'v0.22.0'
|
||||
KIND_IMAGE: 'kindest/node:v1.28.7'
|
||||
KIND_CLUSTER_NAME: 'ci-testing'
|
||||
|
||||
jobs:
|
||||
|
||||
rollout:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Setup Kind Cluster
|
||||
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
|
||||
with:
|
||||
node_image: ${{ env.KIND_IMAGE }}
|
||||
cluster_name: ${{ env.KIND_CLUSTER_NAME }}
|
||||
config: ./test/kind-conf.yaml
|
||||
version: ${{ env.KIND_VERSION }}
|
||||
- name: Build image
|
||||
run: |
|
||||
export IMAGE="openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID}"
|
||||
docker build --pull --no-cache . -t $IMAGE
|
||||
kind load docker-image --name=${KIND_CLUSTER_NAME} $IMAGE || { echo >&2 "kind not installed or error loading image: $IMAGE"; exit 1; }
|
||||
- name: Install Kruise
|
||||
run: |
|
||||
set -ex
|
||||
kubectl cluster-info
|
||||
make helm
|
||||
helm repo add openkruise https://openkruise.github.io/charts/
|
||||
helm repo update
|
||||
helm install kruise openkruise/kruise --version 1.7.0
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-system | grep '1/1' | grep kruise-controller-manager | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "2" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 3
|
||||
done
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-system | grep '1/1' | grep kruise-controller-manager | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "2" ]; then
|
||||
echo "Wait for kruise-manager ready successfully"
|
||||
else
|
||||
echo "Timeout to wait for kruise-manager ready"
|
||||
exit 1
|
||||
fi
|
||||
- name: Install Kruise Rollout
|
||||
run: |
|
||||
set -ex
|
||||
kubectl cluster-info
|
||||
IMG=openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID} ./scripts/deploy_kind.sh
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-rollout | grep '1/1' | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "1" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 3
|
||||
done
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-rollout | grep '1/1' | wc -l)
|
||||
kubectl get node -o yaml
|
||||
kubectl get all -n kruise-rollout -o yaml
|
||||
set -e
|
||||
if [ "$PODS" -eq "1" ]; then
|
||||
echo "Wait for kruise-rollout ready successfully"
|
||||
else
|
||||
echo "Timeout to wait for kruise-rollout ready"
|
||||
exit 1
|
||||
fi
|
||||
- name: Run E2E Tests For Deployment Controller
|
||||
run: |
|
||||
export KUBECONFIG=/home/runner/.kube/config
|
||||
make ginkgo
|
||||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='Advanced Deployment' test/e2e
|
||||
retVal=$?
|
||||
if [ "${retVal}" -ne 0 ];then
|
||||
echo "test fail, dump kruise-rollout logs"
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
fi
|
||||
exit $retVal
|
||||
- name: Run E2E Tests For Canary rollout of Advance Deployment
|
||||
run: |
|
||||
export KUBECONFIG=/home/runner/.kube/config
|
||||
make ginkgo
|
||||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='Canary rollout with Ingress using advance deployment' test/e2e
|
||||
retVal=$?
|
||||
if [ "${retVal}" -ne 0 ];then
|
||||
echo "test fail, dump kruise-rollout logs"
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
fi
|
||||
exit $retVal
|
|
@ -1,4 +1,4 @@
|
|||
name: E2E-CloneSet-1.23
|
||||
name: E2E-CloneSet-1.24
|
||||
|
||||
on:
|
||||
push:
|
||||
|
@ -8,30 +8,35 @@ on:
|
|||
pull_request: {}
|
||||
workflow_dispatch: {}
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.17'
|
||||
KIND_IMAGE: 'kindest/node:v1.23.3'
|
||||
GO_VERSION: '1.20'
|
||||
KIND_VERSION: 'v0.14.0'
|
||||
KIND_IMAGE: 'kindest/node:v1.24.6'
|
||||
KIND_CLUSTER_NAME: 'ci-testing'
|
||||
|
||||
jobs:
|
||||
|
||||
rollout:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- 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@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Setup Kind Cluster
|
||||
uses: helm/kind-action@v1.2.0
|
||||
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
|
||||
with:
|
||||
node_image: ${{ env.KIND_IMAGE }}
|
||||
cluster_name: ${{ env.KIND_CLUSTER_NAME }}
|
||||
config: ./test/kind-conf.yaml
|
||||
version: ${{ env.KIND_VERSION }}
|
||||
- name: Build image
|
||||
run: |
|
||||
export IMAGE="openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID}"
|
||||
|
@ -44,7 +49,7 @@ jobs:
|
|||
make helm
|
||||
helm repo add openkruise https://openkruise.github.io/charts/
|
||||
helm repo update
|
||||
helm install kruise openkruise/kruise
|
||||
helm install kruise openkruise/kruise --version 1.7.0
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
|
@ -97,14 +102,8 @@ jobs:
|
|||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='CloneSet canary rollout with Ingress' test/e2e
|
||||
retVal=$?
|
||||
# kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
restartCount=$(kubectl get pod -n kruise-rollout --no-headers | awk '{print $4}')
|
||||
if [ "${restartCount}" -eq "0" ];then
|
||||
echo "Kruise-rollout has not restarted"
|
||||
else
|
||||
kubectl get pod -n kruise-rollout --no-headers
|
||||
echo "Kruise-rollout has restarted, abort!!!"
|
||||
kubectl get pod -n kruise-rollout --no-headers| awk '{print $1}' | xargs kubectl logs -p -n kruise-rollout
|
||||
exit 1
|
||||
if [ "${retVal}" -ne 0 ];then
|
||||
echo "test fail, dump kruise-rollout logs"
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
fi
|
||||
exit $retVal
|
|
@ -1,4 +1,4 @@
|
|||
name: E2E-CloneSet-1.19
|
||||
name: E2E-CloneSet-1.26
|
||||
|
||||
on:
|
||||
push:
|
||||
|
@ -8,30 +8,34 @@ on:
|
|||
pull_request: {}
|
||||
workflow_dispatch: {}
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.17'
|
||||
KIND_IMAGE: 'kindest/node:v1.19.16'
|
||||
GO_VERSION: '1.20'
|
||||
KIND_IMAGE: 'kindest/node:v1.26.3'
|
||||
KIND_CLUSTER_NAME: 'ci-testing'
|
||||
|
||||
jobs:
|
||||
|
||||
rollout:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- 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@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Setup Kind Cluster
|
||||
uses: helm/kind-action@v1.2.0
|
||||
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
|
||||
with:
|
||||
node_image: ${{ env.KIND_IMAGE }}
|
||||
cluster_name: ${{ env.KIND_CLUSTER_NAME }}
|
||||
config: ./test/kind-conf.yaml
|
||||
version: ${{ env.KIND_VERSION }}
|
||||
- name: Build image
|
||||
run: |
|
||||
export IMAGE="openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID}"
|
||||
|
@ -44,7 +48,7 @@ jobs:
|
|||
make helm
|
||||
helm repo add openkruise https://openkruise.github.io/charts/
|
||||
helm repo update
|
||||
helm install kruise openkruise/kruise
|
||||
helm install kruise openkruise/kruise --version 1.7.0
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
|
@ -97,14 +101,8 @@ jobs:
|
|||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='CloneSet canary rollout with Ingress' test/e2e
|
||||
retVal=$?
|
||||
# kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
restartCount=$(kubectl get pod -n kruise-rollout --no-headers | awk '{print $4}')
|
||||
if [ "${restartCount}" -eq "0" ];then
|
||||
echo "Kruise-rollout has not restarted"
|
||||
else
|
||||
kubectl get pod -n kruise-rollout --no-headers
|
||||
echo "Kruise-rollout has restarted, abort!!!"
|
||||
kubectl get pod -n kruise-rollout --no-headers| awk '{print $1}' | xargs kubectl logs -p -n kruise-rollout
|
||||
exit 1
|
||||
if [ "${retVal}" -ne 0 ];then
|
||||
echo "test fail, dump kruise-rollout logs"
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
fi
|
||||
exit $retVal
|
|
@ -0,0 +1,109 @@
|
|||
name: E2E-CloneSet-1.28
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- release-*
|
||||
pull_request: {}
|
||||
workflow_dispatch: {}
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.20'
|
||||
KIND_VERSION: 'v0.22.0'
|
||||
KIND_IMAGE: 'kindest/node:v1.28.7'
|
||||
KIND_CLUSTER_NAME: 'ci-testing'
|
||||
|
||||
jobs:
|
||||
|
||||
rollout:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Setup Kind Cluster
|
||||
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
|
||||
with:
|
||||
node_image: ${{ env.KIND_IMAGE }}
|
||||
cluster_name: ${{ env.KIND_CLUSTER_NAME }}
|
||||
config: ./test/kind-conf.yaml
|
||||
version: ${{ env.KIND_VERSION }}
|
||||
- name: Build image
|
||||
run: |
|
||||
export IMAGE="openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID}"
|
||||
docker build --pull --no-cache . -t $IMAGE
|
||||
kind load docker-image --name=${KIND_CLUSTER_NAME} $IMAGE || { echo >&2 "kind not installed or error loading image: $IMAGE"; exit 1; }
|
||||
- name: Install Kruise
|
||||
run: |
|
||||
set -ex
|
||||
kubectl cluster-info
|
||||
make helm
|
||||
helm repo add openkruise https://openkruise.github.io/charts/
|
||||
helm repo update
|
||||
helm install kruise openkruise/kruise --version 1.7.0
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-system | grep '1/1' | grep kruise-controller-manager | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "2" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 3
|
||||
done
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-system | grep '1/1' | grep kruise-controller-manager | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "2" ]; then
|
||||
echo "Wait for kruise-manager ready successfully"
|
||||
else
|
||||
echo "Timeout to wait for kruise-manager ready"
|
||||
exit 1
|
||||
fi
|
||||
- name: Install Kruise Rollout
|
||||
run: |
|
||||
set -ex
|
||||
kubectl cluster-info
|
||||
IMG=openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID} ./scripts/deploy_kind.sh
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-rollout | grep '1/1' | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "1" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 3
|
||||
done
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-rollout | grep '1/1' | wc -l)
|
||||
kubectl get node -o yaml
|
||||
kubectl get all -n kruise-rollout -o yaml
|
||||
set -e
|
||||
if [ "$PODS" -eq "1" ]; then
|
||||
echo "Wait for kruise-rollout ready successfully"
|
||||
else
|
||||
echo "Timeout to wait for kruise-rollout ready"
|
||||
exit 1
|
||||
fi
|
||||
- name: Run E2E Tests
|
||||
run: |
|
||||
export KUBECONFIG=/home/runner/.kube/config
|
||||
make ginkgo
|
||||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='CloneSet canary rollout with Ingress' test/e2e
|
||||
retVal=$?
|
||||
if [ "${retVal}" -ne 0 ];then
|
||||
echo "test fail, dump kruise-rollout logs"
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
fi
|
||||
exit $retVal
|
|
@ -0,0 +1,84 @@
|
|||
name: E2E-Custom
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- release-*
|
||||
pull_request: {}
|
||||
workflow_dispatch: {}
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.20'
|
||||
KIND_VERSION: 'v0.18.0'
|
||||
KIND_IMAGE: 'kindest/node:v1.26.3'
|
||||
KIND_CLUSTER_NAME: 'ci-testing'
|
||||
|
||||
jobs:
|
||||
|
||||
rollout:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Setup Kind Cluster
|
||||
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
|
||||
with:
|
||||
version: ${{ env.KIND_VERSION }}
|
||||
node_image: ${{ env.KIND_IMAGE }}
|
||||
cluster_name: ${{ env.KIND_CLUSTER_NAME }}
|
||||
config: ./test/kind-conf.yaml
|
||||
- name: Build image
|
||||
run: |
|
||||
export IMAGE="openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID}"
|
||||
docker build --pull --no-cache . -t $IMAGE
|
||||
kind load docker-image --name=${KIND_CLUSTER_NAME} $IMAGE || { echo >&2 "kind not installed or error loading image: $IMAGE"; exit 1; }
|
||||
- name: Install Kruise Rollout
|
||||
run: |
|
||||
set -ex
|
||||
kubectl cluster-info
|
||||
IMG=openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID} ./scripts/deploy_kind.sh
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-rollout | grep '1/1' | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "1" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 3
|
||||
done
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-rollout | grep '1/1' | wc -l)
|
||||
kubectl get node -o yaml
|
||||
kubectl get all -n kruise-rollout -o yaml
|
||||
set -e
|
||||
if [ "$PODS" -eq "1" ]; then
|
||||
echo "Wait for kruise-rollout ready successfully"
|
||||
else
|
||||
echo "Timeout to wait for kruise-rollout ready"
|
||||
exit 1
|
||||
fi
|
||||
- name: Run E2E Tests
|
||||
run: |
|
||||
export KUBECONFIG=/home/runner/.kube/config
|
||||
kubectl apply -f ./test/e2e/test_data/customNetworkProvider/istio_crd.yaml
|
||||
kubectl apply -f ./test/e2e/test_data/customNetworkProvider/lua_script_configmap.yaml
|
||||
make ginkgo
|
||||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='Canary rollout with custom network provider' test/e2e
|
||||
retVal=$?
|
||||
if [ "${retVal}" -ne 0 ];then
|
||||
echo "test fail, dump kruise-rollout logs"
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
fi
|
||||
exit $retVal
|
|
@ -1,4 +1,4 @@
|
|||
name: E2E-DaemonSet-1.23
|
||||
name: E2E-DaemonSet-1.24
|
||||
|
||||
on:
|
||||
push:
|
||||
|
@ -8,30 +8,35 @@ on:
|
|||
pull_request: {}
|
||||
workflow_dispatch: {}
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.17'
|
||||
KIND_IMAGE: 'kindest/node:v1.23.3'
|
||||
GO_VERSION: '1.20'
|
||||
KIND_VERSION: 'v0.14.0'
|
||||
KIND_IMAGE: 'kindest/node:v1.24.6'
|
||||
KIND_CLUSTER_NAME: 'ci-testing'
|
||||
|
||||
jobs:
|
||||
|
||||
rollout:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- 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@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Setup Kind Cluster
|
||||
uses: helm/kind-action@v1.2.0
|
||||
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
|
||||
with:
|
||||
node_image: ${{ env.KIND_IMAGE }}
|
||||
cluster_name: ${{ env.KIND_CLUSTER_NAME }}
|
||||
config: ./test/kind-conf.yaml
|
||||
version: ${{ env.KIND_VERSION }}
|
||||
- name: Build image
|
||||
run: |
|
||||
export IMAGE="openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID}"
|
||||
|
@ -44,7 +49,7 @@ jobs:
|
|||
make helm
|
||||
helm repo add openkruise https://openkruise.github.io/charts/
|
||||
helm repo update
|
||||
helm install kruise openkruise/kruise
|
||||
helm install kruise openkruise/kruise --version 1.7.0
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
|
@ -97,14 +102,8 @@ jobs:
|
|||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='DaemonSet canary rollout' test/e2e
|
||||
retVal=$?
|
||||
# kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
restartCount=$(kubectl get pod -n kruise-rollout --no-headers | awk '{print $4}')
|
||||
if [ "${restartCount}" -eq "0" ];then
|
||||
echo "Kruise-rollout has not restarted"
|
||||
else
|
||||
kubectl get pod -n kruise-rollout --no-headers
|
||||
echo "Kruise-rollout has restarted, abort!!!"
|
||||
kubectl get pod -n kruise-rollout --no-headers| awk '{print $1}' | xargs kubectl logs -p -n kruise-rollout
|
||||
exit 1
|
||||
if [ "${retVal}" -ne 0 ];then
|
||||
echo "test fail, dump kruise-rollout logs"
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
fi
|
||||
exit $retVal
|
|
@ -1,4 +1,4 @@
|
|||
name: E2E-DaemonSet-1.19
|
||||
name: E2E-DaemonSet-1.26
|
||||
|
||||
on:
|
||||
push:
|
||||
|
@ -8,30 +8,34 @@ on:
|
|||
pull_request: {}
|
||||
workflow_dispatch: {}
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.17'
|
||||
KIND_IMAGE: 'kindest/node:v1.19.16'
|
||||
GO_VERSION: '1.20'
|
||||
KIND_IMAGE: 'kindest/node:v1.26.3'
|
||||
KIND_CLUSTER_NAME: 'ci-testing'
|
||||
|
||||
jobs:
|
||||
|
||||
rollout:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- 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@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Setup Kind Cluster
|
||||
uses: helm/kind-action@v1.2.0
|
||||
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
|
||||
with:
|
||||
node_image: ${{ env.KIND_IMAGE }}
|
||||
cluster_name: ${{ env.KIND_CLUSTER_NAME }}
|
||||
config: ./test/kind-conf.yaml
|
||||
version: ${{ env.KIND_VERSION }}
|
||||
- name: Build image
|
||||
run: |
|
||||
export IMAGE="openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID}"
|
||||
|
@ -44,7 +48,7 @@ jobs:
|
|||
make helm
|
||||
helm repo add openkruise https://openkruise.github.io/charts/
|
||||
helm repo update
|
||||
helm install kruise openkruise/kruise
|
||||
helm install kruise openkruise/kruise --version 1.7.0
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
|
@ -97,14 +101,8 @@ jobs:
|
|||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='DaemonSet canary rollout' test/e2e
|
||||
retVal=$?
|
||||
# kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
restartCount=$(kubectl get pod -n kruise-rollout --no-headers | awk '{print $4}')
|
||||
if [ "${restartCount}" -eq "0" ];then
|
||||
echo "Kruise-rollout has not restarted"
|
||||
else
|
||||
kubectl get pod -n kruise-rollout --no-headers
|
||||
echo "Kruise-rollout has restarted, abort!!!"
|
||||
kubectl get pod -n kruise-rollout --no-headers| awk '{print $1}' | xargs kubectl logs -p -n kruise-rollout
|
||||
exit 1
|
||||
if [ "${retVal}" -ne 0 ];then
|
||||
echo "test fail, dump kruise-rollout logs"
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
fi
|
||||
exit $retVal
|
|
@ -0,0 +1,109 @@
|
|||
name: E2E-DaemonSet-1.28
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- release-*
|
||||
pull_request: {}
|
||||
workflow_dispatch: {}
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.20'
|
||||
KIND_VERSION: 'v0.22.0'
|
||||
KIND_IMAGE: 'kindest/node:v1.28.7'
|
||||
KIND_CLUSTER_NAME: 'ci-testing'
|
||||
|
||||
jobs:
|
||||
|
||||
rollout:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Setup Kind Cluster
|
||||
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
|
||||
with:
|
||||
node_image: ${{ env.KIND_IMAGE }}
|
||||
cluster_name: ${{ env.KIND_CLUSTER_NAME }}
|
||||
config: ./test/kind-conf.yaml
|
||||
version: ${{ env.KIND_VERSION }}
|
||||
- name: Build image
|
||||
run: |
|
||||
export IMAGE="openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID}"
|
||||
docker build --pull --no-cache . -t $IMAGE
|
||||
kind load docker-image --name=${KIND_CLUSTER_NAME} $IMAGE || { echo >&2 "kind not installed or error loading image: $IMAGE"; exit 1; }
|
||||
- name: Install Kruise
|
||||
run: |
|
||||
set -ex
|
||||
kubectl cluster-info
|
||||
make helm
|
||||
helm repo add openkruise https://openkruise.github.io/charts/
|
||||
helm repo update
|
||||
helm install kruise openkruise/kruise --version 1.7.0
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-system | grep '1/1' | grep kruise-controller-manager | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "2" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 3
|
||||
done
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-system | grep '1/1' | grep kruise-controller-manager | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "2" ]; then
|
||||
echo "Wait for kruise-manager ready successfully"
|
||||
else
|
||||
echo "Timeout to wait for kruise-manager ready"
|
||||
exit 1
|
||||
fi
|
||||
- name: Install Kruise Rollout
|
||||
run: |
|
||||
set -ex
|
||||
kubectl cluster-info
|
||||
IMG=openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID} ./scripts/deploy_kind.sh
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-rollout | grep '1/1' | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "1" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 3
|
||||
done
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-rollout | grep '1/1' | wc -l)
|
||||
kubectl get node -o yaml
|
||||
kubectl get all -n kruise-rollout -o yaml
|
||||
set -e
|
||||
if [ "$PODS" -eq "1" ]; then
|
||||
echo "Wait for kruise-rollout ready successfully"
|
||||
else
|
||||
echo "Timeout to wait for kruise-rollout ready"
|
||||
exit 1
|
||||
fi
|
||||
- name: Run E2E Tests
|
||||
run: |
|
||||
export KUBECONFIG=/home/runner/.kube/config
|
||||
make ginkgo
|
||||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='DaemonSet canary rollout' test/e2e
|
||||
retVal=$?
|
||||
if [ "${retVal}" -ne 0 ];then
|
||||
echo "test fail, dump kruise-rollout logs"
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
fi
|
||||
exit $retVal
|
|
@ -1,4 +1,4 @@
|
|||
name: E2E-Deployment-1.23
|
||||
name: E2E-Deployment-1.24
|
||||
|
||||
on:
|
||||
push:
|
||||
|
@ -8,30 +8,35 @@ on:
|
|||
pull_request: {}
|
||||
workflow_dispatch: {}
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.17'
|
||||
KIND_IMAGE: 'kindest/node:v1.23.3'
|
||||
GO_VERSION: '1.20'
|
||||
KIND_VERSION: 'v0.14.0'
|
||||
KIND_IMAGE: 'kindest/node:v1.24.6'
|
||||
KIND_CLUSTER_NAME: 'ci-testing'
|
||||
|
||||
jobs:
|
||||
|
||||
rollout:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- 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@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Setup Kind Cluster
|
||||
uses: helm/kind-action@v1.2.0
|
||||
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
|
||||
with:
|
||||
node_image: ${{ env.KIND_IMAGE }}
|
||||
cluster_name: ${{ env.KIND_CLUSTER_NAME }}
|
||||
config: ./test/kind-conf.yaml
|
||||
version: ${{ env.KIND_VERSION }}
|
||||
- name: Build image
|
||||
run: |
|
||||
export IMAGE="openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID}"
|
||||
|
@ -44,7 +49,7 @@ jobs:
|
|||
make helm
|
||||
helm repo add openkruise https://openkruise.github.io/charts/
|
||||
helm repo update
|
||||
helm install kruise openkruise/kruise
|
||||
helm install kruise openkruise/kruise --version 1.7.0
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
|
@ -97,14 +102,8 @@ jobs:
|
|||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='Deployment canary rollout with Ingress' test/e2e
|
||||
retVal=$?
|
||||
# kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
restartCount=$(kubectl get pod -n kruise-rollout --no-headers | awk '{print $4}')
|
||||
if [ "${restartCount}" -eq "0" ];then
|
||||
echo "Kruise-rollout has not restarted"
|
||||
else
|
||||
kubectl get pod -n kruise-rollout --no-headers
|
||||
echo "Kruise-rollout has restarted, abort!!!"
|
||||
kubectl get pod -n kruise-rollout --no-headers| awk '{print $1}' | xargs kubectl logs -p -n kruise-rollout
|
||||
exit 1
|
||||
if [ "${retVal}" -ne 0 ];then
|
||||
echo "test fail, dump kruise-rollout logs"
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
fi
|
||||
exit $retVal
|
|
@ -1,4 +1,4 @@
|
|||
name: E2E-Deployment-1.19
|
||||
name: E2E-Deployment-1.26
|
||||
|
||||
on:
|
||||
push:
|
||||
|
@ -8,30 +8,34 @@ on:
|
|||
pull_request: {}
|
||||
workflow_dispatch: {}
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.17'
|
||||
KIND_IMAGE: 'kindest/node:v1.19.16'
|
||||
GO_VERSION: '1.20'
|
||||
KIND_IMAGE: 'kindest/node:v1.26.3'
|
||||
KIND_CLUSTER_NAME: 'ci-testing'
|
||||
|
||||
jobs:
|
||||
|
||||
rollout:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- 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@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Setup Kind Cluster
|
||||
uses: helm/kind-action@v1.2.0
|
||||
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
|
||||
with:
|
||||
node_image: ${{ env.KIND_IMAGE }}
|
||||
cluster_name: ${{ env.KIND_CLUSTER_NAME }}
|
||||
config: ./test/kind-conf.yaml
|
||||
version: ${{ env.KIND_VERSION }}
|
||||
- name: Build image
|
||||
run: |
|
||||
export IMAGE="openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID}"
|
||||
|
@ -44,7 +48,7 @@ jobs:
|
|||
make helm
|
||||
helm repo add openkruise https://openkruise.github.io/charts/
|
||||
helm repo update
|
||||
helm install kruise openkruise/kruise
|
||||
helm install kruise openkruise/kruise --version 1.7.0
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
|
@ -97,14 +101,8 @@ jobs:
|
|||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='Deployment canary rollout with Ingress' test/e2e
|
||||
retVal=$?
|
||||
# kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
restartCount=$(kubectl get pod -n kruise-rollout --no-headers | awk '{print $4}')
|
||||
if [ "${restartCount}" -eq "0" ];then
|
||||
echo "Kruise-rollout has not restarted"
|
||||
else
|
||||
kubectl get pod -n kruise-rollout --no-headers
|
||||
echo "Kruise-rollout has restarted, abort!!!"
|
||||
kubectl get pod -n kruise-rollout --no-headers| awk '{print $1}' | xargs kubectl logs -p -n kruise-rollout
|
||||
exit 1
|
||||
if [ "${retVal}" -ne 0 ];then
|
||||
echo "test fail, dump kruise-rollout logs"
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
fi
|
||||
exit $retVal
|
|
@ -0,0 +1,109 @@
|
|||
name: E2E-Deployment-1.28
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- release-*
|
||||
pull_request: {}
|
||||
workflow_dispatch: {}
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.20'
|
||||
KIND_VERSION: 'v0.22.0'
|
||||
KIND_IMAGE: 'kindest/node:v1.28.7'
|
||||
KIND_CLUSTER_NAME: 'ci-testing'
|
||||
|
||||
jobs:
|
||||
|
||||
rollout:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Setup Kind Cluster
|
||||
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
|
||||
with:
|
||||
node_image: ${{ env.KIND_IMAGE }}
|
||||
cluster_name: ${{ env.KIND_CLUSTER_NAME }}
|
||||
config: ./test/kind-conf.yaml
|
||||
version: ${{ env.KIND_VERSION }}
|
||||
- name: Build image
|
||||
run: |
|
||||
export IMAGE="openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID}"
|
||||
docker build --pull --no-cache . -t $IMAGE
|
||||
kind load docker-image --name=${KIND_CLUSTER_NAME} $IMAGE || { echo >&2 "kind not installed or error loading image: $IMAGE"; exit 1; }
|
||||
- name: Install Kruise
|
||||
run: |
|
||||
set -ex
|
||||
kubectl cluster-info
|
||||
make helm
|
||||
helm repo add openkruise https://openkruise.github.io/charts/
|
||||
helm repo update
|
||||
helm install kruise openkruise/kruise --version 1.7.0
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-system | grep '1/1' | grep kruise-controller-manager | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "2" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 3
|
||||
done
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-system | grep '1/1' | grep kruise-controller-manager | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "2" ]; then
|
||||
echo "Wait for kruise-manager ready successfully"
|
||||
else
|
||||
echo "Timeout to wait for kruise-manager ready"
|
||||
exit 1
|
||||
fi
|
||||
- name: Install Kruise Rollout
|
||||
run: |
|
||||
set -ex
|
||||
kubectl cluster-info
|
||||
IMG=openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID} ./scripts/deploy_kind.sh
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-rollout | grep '1/1' | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "1" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 3
|
||||
done
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-rollout | grep '1/1' | wc -l)
|
||||
kubectl get node -o yaml
|
||||
kubectl get all -n kruise-rollout -o yaml
|
||||
set -e
|
||||
if [ "$PODS" -eq "1" ]; then
|
||||
echo "Wait for kruise-rollout ready successfully"
|
||||
else
|
||||
echo "Timeout to wait for kruise-rollout ready"
|
||||
exit 1
|
||||
fi
|
||||
- name: Run E2E Tests
|
||||
run: |
|
||||
export KUBECONFIG=/home/runner/.kube/config
|
||||
make ginkgo
|
||||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='Deployment canary rollout with Ingress' test/e2e
|
||||
retVal=$?
|
||||
if [ "${retVal}" -ne 0 ];then
|
||||
echo "test fail, dump kruise-rollout logs"
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
fi
|
||||
exit $retVal
|
|
@ -8,30 +8,35 @@ on:
|
|||
pull_request: {}
|
||||
workflow_dispatch: {}
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.17'
|
||||
KIND_IMAGE: 'kindest/node:v1.23.3'
|
||||
GO_VERSION: '1.20'
|
||||
KIND_VERSION: 'v0.14.0'
|
||||
KIND_IMAGE: 'kindest/node:v1.24.6'
|
||||
KIND_CLUSTER_NAME: 'ci-testing'
|
||||
|
||||
jobs:
|
||||
|
||||
rollout:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- 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@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Setup Kind Cluster
|
||||
uses: helm/kind-action@v1.2.0
|
||||
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
|
||||
with:
|
||||
node_image: ${{ env.KIND_IMAGE }}
|
||||
cluster_name: ${{ env.KIND_CLUSTER_NAME }}
|
||||
config: ./test/kind-conf.yaml
|
||||
version: ${{ env.KIND_VERSION }}
|
||||
- name: Build image
|
||||
run: |
|
||||
export IMAGE="openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID}"
|
||||
|
@ -70,14 +75,8 @@ jobs:
|
|||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='Canary rollout with Gateway API' test/e2e
|
||||
retVal=$?
|
||||
# kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
restartCount=$(kubectl get pod -n kruise-rollout --no-headers | awk '{print $4}')
|
||||
if [ "${restartCount}" -eq "0" ];then
|
||||
echo "Kruise-rollout has not restarted"
|
||||
else
|
||||
kubectl get pod -n kruise-rollout --no-headers
|
||||
echo "Kruise-rollout has restarted, abort!!!"
|
||||
kubectl get pod -n kruise-rollout --no-headers| awk '{print $1}' | xargs kubectl logs -p -n kruise-rollout
|
||||
exit 1
|
||||
if [ "${retVal}" -ne 0 ];then
|
||||
echo "test fail, dump kruise-rollout logs"
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
fi
|
||||
exit $retVal
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
name: E2E-Multiple-NetworkProvider
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- release-*
|
||||
pull_request: {}
|
||||
workflow_dispatch: {}
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.20'
|
||||
KIND_VERSION: 'v0.18.0'
|
||||
KIND_IMAGE: 'kindest/node:v1.26.3'
|
||||
KIND_CLUSTER_NAME: 'ci-testing'
|
||||
|
||||
jobs:
|
||||
|
||||
rollout:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Setup Kind Cluster
|
||||
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
|
||||
with:
|
||||
version: ${{ env.KIND_VERSION }}
|
||||
node_image: ${{ env.KIND_IMAGE }}
|
||||
cluster_name: ${{ env.KIND_CLUSTER_NAME }}
|
||||
config: ./test/kind-conf.yaml
|
||||
- name: Build image
|
||||
run: |
|
||||
export IMAGE="openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID}"
|
||||
docker build --pull --no-cache . -t $IMAGE
|
||||
kind load docker-image --name=${KIND_CLUSTER_NAME} $IMAGE || { echo >&2 "kind not installed or error loading image: $IMAGE"; exit 1; }
|
||||
- name: Install Kruise Rollout
|
||||
run: |
|
||||
set -ex
|
||||
kubectl cluster-info
|
||||
IMG=openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID} ./scripts/deploy_kind.sh
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-rollout | grep '1/1' | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "1" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 3
|
||||
done
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-rollout | grep '1/1' | wc -l)
|
||||
kubectl get node -o yaml
|
||||
kubectl get all -n kruise-rollout -o yaml
|
||||
set -e
|
||||
if [ "$PODS" -eq "1" ]; then
|
||||
echo "Wait for kruise-rollout ready successfully"
|
||||
else
|
||||
echo "Timeout to wait for kruise-rollout ready"
|
||||
exit 1
|
||||
fi
|
||||
- name: Run E2E Tests
|
||||
run: |
|
||||
export KUBECONFIG=/home/runner/.kube/config
|
||||
kubectl apply -f ./test/e2e/test_data/customNetworkProvider/istio_crd.yaml
|
||||
kubectl apply -f ./test/e2e/test_data/customNetworkProvider/lua_script_configmap.yaml
|
||||
make ginkgo
|
||||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='Canary rollout with multiple network providers' test/e2e
|
||||
retVal=$?
|
||||
if [ "${retVal}" -ne 0 ];then
|
||||
echo "test fail, dump kruise-rollout logs"
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
fi
|
||||
exit $retVal
|
|
@ -1,4 +1,4 @@
|
|||
name: E2E-Others-1.23
|
||||
name: E2E-Others-1.24
|
||||
|
||||
on:
|
||||
push:
|
||||
|
@ -8,30 +8,35 @@ on:
|
|||
pull_request: {}
|
||||
workflow_dispatch: {}
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.17'
|
||||
KIND_IMAGE: 'kindest/node:v1.23.3'
|
||||
GO_VERSION: '1.20'
|
||||
KIND_VERSION: 'v0.14.0'
|
||||
KIND_IMAGE: 'kindest/node:v1.24.6'
|
||||
KIND_CLUSTER_NAME: 'ci-testing'
|
||||
|
||||
jobs:
|
||||
|
||||
rollout:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- 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@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Setup Kind Cluster
|
||||
uses: helm/kind-action@v1.2.0
|
||||
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
|
||||
with:
|
||||
node_image: ${{ env.KIND_IMAGE }}
|
||||
cluster_name: ${{ env.KIND_CLUSTER_NAME }}
|
||||
config: ./test/kind-conf.yaml
|
||||
version: ${{ env.KIND_VERSION }}
|
||||
- name: Build image
|
||||
run: |
|
||||
export IMAGE="openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID}"
|
||||
|
@ -44,7 +49,7 @@ jobs:
|
|||
make helm
|
||||
helm repo add openkruise https://openkruise.github.io/charts/
|
||||
helm repo update
|
||||
helm install kruise openkruise/kruise
|
||||
helm install kruise openkruise/kruise --version 1.7.0
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
|
@ -97,14 +102,8 @@ jobs:
|
|||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='Others' test/e2e
|
||||
retVal=$?
|
||||
# kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
restartCount=$(kubectl get pod -n kruise-rollout --no-headers | awk '{print $4}')
|
||||
if [ "${restartCount}" -eq "0" ];then
|
||||
echo "Kruise-rollout has not restarted"
|
||||
else
|
||||
kubectl get pod -n kruise-rollout --no-headers
|
||||
echo "Kruise-rollout has restarted, abort!!!"
|
||||
kubectl get pod -n kruise-rollout --no-headers| awk '{print $1}' | xargs kubectl logs -p -n kruise-rollout
|
||||
exit 1
|
||||
if [ "${retVal}" -ne 0 ];then
|
||||
echo "test fail, dump kruise-rollout logs"
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
fi
|
||||
exit $retVal
|
|
@ -1,4 +1,4 @@
|
|||
name: E2E-Others-1.19
|
||||
name: E2E-Others-1.26
|
||||
|
||||
on:
|
||||
push:
|
||||
|
@ -8,30 +8,34 @@ on:
|
|||
pull_request: {}
|
||||
workflow_dispatch: {}
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.17'
|
||||
KIND_IMAGE: 'kindest/node:v1.19.16'
|
||||
GO_VERSION: '1.20'
|
||||
KIND_IMAGE: 'kindest/node:v1.26.3'
|
||||
KIND_CLUSTER_NAME: 'ci-testing'
|
||||
|
||||
jobs:
|
||||
|
||||
rollout:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- 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@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Setup Kind Cluster
|
||||
uses: helm/kind-action@v1.2.0
|
||||
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
|
||||
with:
|
||||
node_image: ${{ env.KIND_IMAGE }}
|
||||
cluster_name: ${{ env.KIND_CLUSTER_NAME }}
|
||||
config: ./test/kind-conf.yaml
|
||||
version: ${{ env.KIND_VERSION }}
|
||||
- name: Build image
|
||||
run: |
|
||||
export IMAGE="openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID}"
|
||||
|
@ -44,7 +48,7 @@ jobs:
|
|||
make helm
|
||||
helm repo add openkruise https://openkruise.github.io/charts/
|
||||
helm repo update
|
||||
helm install kruise openkruise/kruise
|
||||
helm install kruise openkruise/kruise --version 1.7.0
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
|
@ -97,14 +101,8 @@ jobs:
|
|||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='Others' test/e2e
|
||||
retVal=$?
|
||||
# kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
restartCount=$(kubectl get pod -n kruise-rollout --no-headers | awk '{print $4}')
|
||||
if [ "${restartCount}" -eq "0" ];then
|
||||
echo "Kruise-rollout has not restarted"
|
||||
else
|
||||
kubectl get pod -n kruise-rollout --no-headers
|
||||
echo "Kruise-rollout has restarted, abort!!!"
|
||||
kubectl get pod -n kruise-rollout --no-headers| awk '{print $1}' | xargs kubectl logs -p -n kruise-rollout
|
||||
exit 1
|
||||
if [ "${retVal}" -ne 0 ];then
|
||||
echo "test fail, dump kruise-rollout logs"
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
fi
|
||||
exit $retVal
|
|
@ -0,0 +1,109 @@
|
|||
name: E2E-Others-1.28
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- release-*
|
||||
pull_request: {}
|
||||
workflow_dispatch: {}
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.20'
|
||||
KIND_VERSION: 'v0.22.0'
|
||||
KIND_IMAGE: 'kindest/node:v1.28.7'
|
||||
KIND_CLUSTER_NAME: 'ci-testing'
|
||||
|
||||
jobs:
|
||||
|
||||
rollout:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Setup Kind Cluster
|
||||
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
|
||||
with:
|
||||
node_image: ${{ env.KIND_IMAGE }}
|
||||
cluster_name: ${{ env.KIND_CLUSTER_NAME }}
|
||||
config: ./test/kind-conf.yaml
|
||||
version: ${{ env.KIND_VERSION }}
|
||||
- name: Build image
|
||||
run: |
|
||||
export IMAGE="openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID}"
|
||||
docker build --pull --no-cache . -t $IMAGE
|
||||
kind load docker-image --name=${KIND_CLUSTER_NAME} $IMAGE || { echo >&2 "kind not installed or error loading image: $IMAGE"; exit 1; }
|
||||
- name: Install Kruise
|
||||
run: |
|
||||
set -ex
|
||||
kubectl cluster-info
|
||||
make helm
|
||||
helm repo add openkruise https://openkruise.github.io/charts/
|
||||
helm repo update
|
||||
helm install kruise openkruise/kruise --version 1.7.0
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-system | grep '1/1' | grep kruise-controller-manager | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "2" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 3
|
||||
done
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-system | grep '1/1' | grep kruise-controller-manager | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "2" ]; then
|
||||
echo "Wait for kruise-manager ready successfully"
|
||||
else
|
||||
echo "Timeout to wait for kruise-manager ready"
|
||||
exit 1
|
||||
fi
|
||||
- name: Install Kruise Rollout
|
||||
run: |
|
||||
set -ex
|
||||
kubectl cluster-info
|
||||
IMG=openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID} ./scripts/deploy_kind.sh
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-rollout | grep '1/1' | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "1" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 3
|
||||
done
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-rollout | grep '1/1' | wc -l)
|
||||
kubectl get node -o yaml
|
||||
kubectl get all -n kruise-rollout -o yaml
|
||||
set -e
|
||||
if [ "$PODS" -eq "1" ]; then
|
||||
echo "Wait for kruise-rollout ready successfully"
|
||||
else
|
||||
echo "Timeout to wait for kruise-rollout ready"
|
||||
exit 1
|
||||
fi
|
||||
- name: Run E2E Tests
|
||||
run: |
|
||||
export KUBECONFIG=/home/runner/.kube/config
|
||||
make ginkgo
|
||||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='Others' test/e2e
|
||||
retVal=$?
|
||||
if [ "${retVal}" -ne 0 ];then
|
||||
echo "test fail, dump kruise-rollout logs"
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
fi
|
||||
exit $retVal
|
|
@ -1,4 +1,4 @@
|
|||
name: E2E-StatefulSet-1.23
|
||||
name: E2E-StatefulSet-1.24
|
||||
|
||||
on:
|
||||
push:
|
||||
|
@ -8,30 +8,35 @@ on:
|
|||
pull_request: {}
|
||||
workflow_dispatch: {}
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.17'
|
||||
KIND_IMAGE: 'kindest/node:v1.23.3'
|
||||
GO_VERSION: '1.20'
|
||||
KIND_VERSION: 'v0.14.0'
|
||||
KIND_IMAGE: 'kindest/node:v1.24.6'
|
||||
KIND_CLUSTER_NAME: 'ci-testing'
|
||||
|
||||
jobs:
|
||||
|
||||
rollout:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- 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@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Setup Kind Cluster
|
||||
uses: helm/kind-action@v1.2.0
|
||||
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
|
||||
with:
|
||||
node_image: ${{ env.KIND_IMAGE }}
|
||||
cluster_name: ${{ env.KIND_CLUSTER_NAME }}
|
||||
config: ./test/kind-conf.yaml
|
||||
version: ${{ env.KIND_VERSION }}
|
||||
- name: Build image
|
||||
run: |
|
||||
export IMAGE="openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID}"
|
||||
|
@ -44,7 +49,7 @@ jobs:
|
|||
make helm
|
||||
helm repo add openkruise https://openkruise.github.io/charts/
|
||||
helm repo update
|
||||
helm install kruise openkruise/kruise
|
||||
helm install kruise openkruise/kruise --version 1.7.0
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
|
@ -97,14 +102,8 @@ jobs:
|
|||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='StatefulSet canary rollout with Ingress' test/e2e
|
||||
retVal=$?
|
||||
# kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
restartCount=$(kubectl get pod -n kruise-rollout --no-headers | awk '{print $4}')
|
||||
if [ "${restartCount}" -eq "0" ];then
|
||||
echo "Kruise-rollout has not restarted"
|
||||
else
|
||||
kubectl get pod -n kruise-rollout --no-headers
|
||||
echo "Kruise-rollout has restarted, abort!!!"
|
||||
kubectl get pod -n kruise-rollout --no-headers| awk '{print $1}' | xargs kubectl logs -p -n kruise-rollout
|
||||
exit 1
|
||||
if [ "${retVal}" -ne 0 ];then
|
||||
echo "test fail, dump kruise-rollout logs"
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
fi
|
||||
exit $retVal
|
|
@ -1,4 +1,4 @@
|
|||
name: E2E-StatefulSet-1.19
|
||||
name: E2E-StatefulSet-1.28
|
||||
|
||||
on:
|
||||
push:
|
||||
|
@ -8,30 +8,34 @@ on:
|
|||
pull_request: {}
|
||||
workflow_dispatch: {}
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.17'
|
||||
KIND_IMAGE: 'kindest/node:v1.19.16'
|
||||
GO_VERSION: '1.20'
|
||||
KIND_IMAGE: 'kindest/node:v1.26.3'
|
||||
KIND_CLUSTER_NAME: 'ci-testing'
|
||||
|
||||
jobs:
|
||||
|
||||
rollout:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- 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@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Setup Kind Cluster
|
||||
uses: helm/kind-action@v1.2.0
|
||||
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
|
||||
with:
|
||||
node_image: ${{ env.KIND_IMAGE }}
|
||||
cluster_name: ${{ env.KIND_CLUSTER_NAME }}
|
||||
config: ./test/kind-conf.yaml
|
||||
version: ${{ env.KIND_VERSION }}
|
||||
- name: Build image
|
||||
run: |
|
||||
export IMAGE="openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID}"
|
||||
|
@ -44,7 +48,7 @@ jobs:
|
|||
make helm
|
||||
helm repo add openkruise https://openkruise.github.io/charts/
|
||||
helm repo update
|
||||
helm install kruise openkruise/kruise
|
||||
helm install kruise openkruise/kruise --version 1.7.0
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
|
@ -97,14 +101,8 @@ jobs:
|
|||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='StatefulSet canary rollout with Ingress' test/e2e
|
||||
retVal=$?
|
||||
# kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
restartCount=$(kubectl get pod -n kruise-rollout --no-headers | awk '{print $4}')
|
||||
if [ "${restartCount}" -eq "0" ];then
|
||||
echo "Kruise-rollout has not restarted"
|
||||
else
|
||||
kubectl get pod -n kruise-rollout --no-headers
|
||||
echo "Kruise-rollout has restarted, abort!!!"
|
||||
kubectl get pod -n kruise-rollout --no-headers| awk '{print $1}' | xargs kubectl logs -p -n kruise-rollout
|
||||
exit 1
|
||||
if [ "${retVal}" -ne 0 ];then
|
||||
echo "test fail, dump kruise-rollout logs"
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
fi
|
||||
exit $retVal
|
|
@ -0,0 +1,109 @@
|
|||
name: E2E-StatefulSet-1.28
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- release-*
|
||||
pull_request: {}
|
||||
workflow_dispatch: {}
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.20'
|
||||
KIND_VERSION: 'v0.22.0'
|
||||
KIND_IMAGE: 'kindest/node:v1.28.7'
|
||||
KIND_CLUSTER_NAME: 'ci-testing'
|
||||
|
||||
jobs:
|
||||
|
||||
rollout:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Setup Kind Cluster
|
||||
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
|
||||
with:
|
||||
node_image: ${{ env.KIND_IMAGE }}
|
||||
cluster_name: ${{ env.KIND_CLUSTER_NAME }}
|
||||
config: ./test/kind-conf.yaml
|
||||
version: ${{ env.KIND_VERSION }}
|
||||
- name: Build image
|
||||
run: |
|
||||
export IMAGE="openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID}"
|
||||
docker build --pull --no-cache . -t $IMAGE
|
||||
kind load docker-image --name=${KIND_CLUSTER_NAME} $IMAGE || { echo >&2 "kind not installed or error loading image: $IMAGE"; exit 1; }
|
||||
- name: Install Kruise
|
||||
run: |
|
||||
set -ex
|
||||
kubectl cluster-info
|
||||
make helm
|
||||
helm repo add openkruise https://openkruise.github.io/charts/
|
||||
helm repo update
|
||||
helm install kruise openkruise/kruise --version 1.7.0
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-system | grep '1/1' | grep kruise-controller-manager | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "2" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 3
|
||||
done
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-system | grep '1/1' | grep kruise-controller-manager | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "2" ]; then
|
||||
echo "Wait for kruise-manager ready successfully"
|
||||
else
|
||||
echo "Timeout to wait for kruise-manager ready"
|
||||
exit 1
|
||||
fi
|
||||
- name: Install Kruise Rollout
|
||||
run: |
|
||||
set -ex
|
||||
kubectl cluster-info
|
||||
IMG=openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID} ./scripts/deploy_kind.sh
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-rollout | grep '1/1' | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "1" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 3
|
||||
done
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-rollout | grep '1/1' | wc -l)
|
||||
kubectl get node -o yaml
|
||||
kubectl get all -n kruise-rollout -o yaml
|
||||
set -e
|
||||
if [ "$PODS" -eq "1" ]; then
|
||||
echo "Wait for kruise-rollout ready successfully"
|
||||
else
|
||||
echo "Timeout to wait for kruise-rollout ready"
|
||||
exit 1
|
||||
fi
|
||||
- name: Run E2E Tests
|
||||
run: |
|
||||
export KUBECONFIG=/home/runner/.kube/config
|
||||
make ginkgo
|
||||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='StatefulSet canary rollout with Ingress' test/e2e
|
||||
retVal=$?
|
||||
if [ "${retVal}" -ne 0 ];then
|
||||
echo "test fail, dump kruise-rollout logs"
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
fi
|
||||
exit $retVal
|
|
@ -1,4 +1,4 @@
|
|||
name: E2E-Advanced-Deployment-1.19
|
||||
name: E2E-V1Beta1-BlueGreen-1.24
|
||||
|
||||
on:
|
||||
push:
|
||||
|
@ -8,30 +8,35 @@ on:
|
|||
pull_request: {}
|
||||
workflow_dispatch: {}
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.17'
|
||||
KIND_IMAGE: 'kindest/node:v1.19.16'
|
||||
GO_VERSION: '1.20'
|
||||
KIND_VERSION: 'v0.14.0'
|
||||
KIND_IMAGE: 'kindest/node:v1.24.6'
|
||||
KIND_CLUSTER_NAME: 'ci-testing'
|
||||
|
||||
jobs:
|
||||
|
||||
rollout:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- 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@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Setup Kind Cluster
|
||||
uses: helm/kind-action@v1.2.0
|
||||
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
|
||||
with:
|
||||
node_image: ${{ env.KIND_IMAGE }}
|
||||
cluster_name: ${{ env.KIND_CLUSTER_NAME }}
|
||||
config: ./test/kind-conf.yaml
|
||||
version: ${{ env.KIND_VERSION }}
|
||||
- name: Build image
|
||||
run: |
|
||||
export IMAGE="openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID}"
|
||||
|
@ -44,7 +49,7 @@ jobs:
|
|||
make helm
|
||||
helm repo add openkruise https://openkruise.github.io/charts/
|
||||
helm repo update
|
||||
helm install kruise openkruise/kruise
|
||||
helm install kruise openkruise/kruise --version 1.7.0
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
|
@ -81,23 +86,23 @@ jobs:
|
|||
done
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-rollout | grep '1/1' | wc -l)
|
||||
kubectl get node -o yaml
|
||||
kubectl get all -n kruise-rollout -o yaml
|
||||
set -e
|
||||
if [ "$PODS" -eq "1" ]; then
|
||||
echo "Wait for kruise-rollout ready successfully"
|
||||
else
|
||||
echo "Timeout to wait for kruise-rollout ready"
|
||||
kubectl get pod -n kruise-rollout --no-headers | awk '{print $1}' | xargs kubectl logs -p -n kruise-rollout
|
||||
kubectl get pod -n kruise-rollout --no-headers | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
exit 1
|
||||
fi
|
||||
- name: Run E2E Tests For Deployment Controller
|
||||
- name: Bluegreen Release Disable HPA
|
||||
run: |
|
||||
export KUBECONFIG=/home/runner/.kube/config
|
||||
make ginkgo
|
||||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='Advanced Deployment' test/e2e
|
||||
./bin/ginkgo -timeout 60m -v --focus='bluegreen disable hpa test case - autoscaling/v2 for v1.23' test/e2e
|
||||
retVal=$?
|
||||
# kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
restartCount=$(kubectl get pod -n kruise-rollout --no-headers | awk '{print $4}')
|
||||
if [ "${restartCount}" -eq "0" ];then
|
||||
echo "Kruise-rollout has not restarted"
|
||||
|
@ -108,14 +113,14 @@ jobs:
|
|||
exit 1
|
||||
fi
|
||||
exit $retVal
|
||||
- name: Run E2E Tests For Control Plane
|
||||
- name: Deployment Bluegreen Release
|
||||
run: |
|
||||
export KUBECONFIG=/home/runner/.kube/config
|
||||
make ginkgo
|
||||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='Advanced Deployment canary rollout with Ingress' test/e2e
|
||||
./bin/ginkgo -timeout 60m -v --focus='Bluegreen Release - Deployment - Ingress' test/e2e
|
||||
retVal=$?
|
||||
# kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
restartCount=$(kubectl get pod -n kruise-rollout --no-headers | awk '{print $4}')
|
||||
if [ "${restartCount}" -eq "0" ];then
|
||||
echo "Kruise-rollout has not restarted"
|
||||
|
@ -126,3 +131,15 @@ jobs:
|
|||
exit 1
|
||||
fi
|
||||
exit $retVal
|
||||
- name: CloneSet Bluegreen Release
|
||||
run: |
|
||||
export KUBECONFIG=/home/runner/.kube/config
|
||||
make ginkgo
|
||||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='Bluegreen Release - Cloneset - Ingress' test/e2e
|
||||
retVal=$?
|
||||
if [ "${retVal}" -ne 0 ];then
|
||||
echo "test fail, dump kruise-rollout logs"
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
fi
|
||||
exit $retVal
|
|
@ -1,4 +1,4 @@
|
|||
name: E2E-Advanced-Deployment-1.23
|
||||
name: E2E-V1Beta1-BlueGreen-1.26
|
||||
|
||||
on:
|
||||
push:
|
||||
|
@ -8,30 +8,34 @@ on:
|
|||
pull_request: {}
|
||||
workflow_dispatch: {}
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.17'
|
||||
KIND_IMAGE: 'kindest/node:v1.23.3'
|
||||
GO_VERSION: '1.20'
|
||||
KIND_IMAGE: 'kindest/node:v1.26.3'
|
||||
KIND_CLUSTER_NAME: 'ci-testing'
|
||||
|
||||
jobs:
|
||||
|
||||
rollout:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- 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@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Setup Kind Cluster
|
||||
uses: helm/kind-action@v1.2.0
|
||||
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
|
||||
with:
|
||||
node_image: ${{ env.KIND_IMAGE }}
|
||||
cluster_name: ${{ env.KIND_CLUSTER_NAME }}
|
||||
config: ./test/kind-conf.yaml
|
||||
version: ${{ env.KIND_VERSION }}
|
||||
- name: Build image
|
||||
run: |
|
||||
export IMAGE="openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID}"
|
||||
|
@ -44,7 +48,7 @@ jobs:
|
|||
make helm
|
||||
helm repo add openkruise https://openkruise.github.io/charts/
|
||||
helm repo update
|
||||
helm install kruise openkruise/kruise
|
||||
helm install kruise openkruise/kruise --version 1.7.0
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
|
@ -90,14 +94,14 @@ jobs:
|
|||
echo "Timeout to wait for kruise-rollout ready"
|
||||
exit 1
|
||||
fi
|
||||
- name: Run E2E Tests For Deployment Controller
|
||||
- name: Bluegreen Release Disable HPA
|
||||
run: |
|
||||
export KUBECONFIG=/home/runner/.kube/config
|
||||
make ginkgo
|
||||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='Advanced Deployment' test/e2e
|
||||
./bin/ginkgo -timeout 60m -v --focus='bluegreen disable hpa test case - autoscaling/v2 for v1.26' test/e2e
|
||||
retVal=$?
|
||||
# kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
restartCount=$(kubectl get pod -n kruise-rollout --no-headers | awk '{print $4}')
|
||||
if [ "${restartCount}" -eq "0" ];then
|
||||
echo "Kruise-rollout has not restarted"
|
||||
|
@ -108,14 +112,14 @@ jobs:
|
|||
exit 1
|
||||
fi
|
||||
exit $retVal
|
||||
- name: Run E2E Tests For Control Plane
|
||||
- name: Deployment Bluegreen Release
|
||||
run: |
|
||||
export KUBECONFIG=/home/runner/.kube/config
|
||||
make ginkgo
|
||||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='Advanced Deployment canary rollout with Ingress' test/e2e
|
||||
./bin/ginkgo -timeout 60m -v --focus='Bluegreen Release - Deployment - Ingress' test/e2e
|
||||
retVal=$?
|
||||
# kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
restartCount=$(kubectl get pod -n kruise-rollout --no-headers | awk '{print $4}')
|
||||
if [ "${restartCount}" -eq "0" ];then
|
||||
echo "Kruise-rollout has not restarted"
|
||||
|
@ -126,3 +130,15 @@ jobs:
|
|||
exit 1
|
||||
fi
|
||||
exit $retVal
|
||||
- name: CloneSet Bluegreen Release
|
||||
run: |
|
||||
export KUBECONFIG=/home/runner/.kube/config
|
||||
make ginkgo
|
||||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='Bluegreen Release - Cloneset - Ingress' test/e2e
|
||||
retVal=$?
|
||||
if [ "${retVal}" -ne 0 ];then
|
||||
echo "test fail, dump kruise-rollout logs"
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
fi
|
||||
exit $retVal
|
|
@ -0,0 +1,145 @@
|
|||
name: E2E-V1Beta1-BlueGreen-1.28
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- release-*
|
||||
pull_request: {}
|
||||
workflow_dispatch: {}
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.20'
|
||||
KIND_VERSION: 'v0.22.0'
|
||||
KIND_IMAGE: 'kindest/node:v1.28.7'
|
||||
KIND_CLUSTER_NAME: 'ci-testing'
|
||||
|
||||
jobs:
|
||||
|
||||
rollout:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Setup Kind Cluster
|
||||
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
|
||||
with:
|
||||
node_image: ${{ env.KIND_IMAGE }}
|
||||
cluster_name: ${{ env.KIND_CLUSTER_NAME }}
|
||||
config: ./test/kind-conf.yaml
|
||||
version: ${{ env.KIND_VERSION }}
|
||||
- name: Build image
|
||||
run: |
|
||||
export IMAGE="openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID}"
|
||||
docker build --pull --no-cache . -t $IMAGE
|
||||
kind load docker-image --name=${KIND_CLUSTER_NAME} $IMAGE || { echo >&2 "kind not installed or error loading image: $IMAGE"; exit 1; }
|
||||
- name: Install Kruise
|
||||
run: |
|
||||
set -ex
|
||||
kubectl cluster-info
|
||||
make helm
|
||||
helm repo add openkruise https://openkruise.github.io/charts/
|
||||
helm repo update
|
||||
helm install kruise openkruise/kruise --version 1.7.0
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-system | grep '1/1' | grep kruise-controller-manager | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "2" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 3
|
||||
done
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-system | grep '1/1' | grep kruise-controller-manager | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "2" ]; then
|
||||
echo "Wait for kruise-manager ready successfully"
|
||||
else
|
||||
echo "Timeout to wait for kruise-manager ready"
|
||||
exit 1
|
||||
fi
|
||||
- name: Install Kruise Rollout
|
||||
run: |
|
||||
set -ex
|
||||
kubectl cluster-info
|
||||
IMG=openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID} ./scripts/deploy_kind.sh
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-rollout | grep '1/1' | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "1" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 3
|
||||
done
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-rollout | grep '1/1' | wc -l)
|
||||
kubectl get node -o yaml
|
||||
kubectl get all -n kruise-rollout -o yaml
|
||||
set -e
|
||||
if [ "$PODS" -eq "1" ]; then
|
||||
echo "Wait for kruise-rollout ready successfully"
|
||||
else
|
||||
echo "Timeout to wait for kruise-rollout ready"
|
||||
exit 1
|
||||
fi
|
||||
- name: Bluegreen Release Disable HPA
|
||||
run: |
|
||||
export KUBECONFIG=/home/runner/.kube/config
|
||||
make ginkgo
|
||||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='bluegreen disable hpa test case - autoscaling/v2 for v1.26' test/e2e
|
||||
retVal=$?
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
restartCount=$(kubectl get pod -n kruise-rollout --no-headers | awk '{print $4}')
|
||||
if [ "${restartCount}" -eq "0" ];then
|
||||
echo "Kruise-rollout has not restarted"
|
||||
else
|
||||
kubectl get pod -n kruise-rollout --no-headers
|
||||
echo "Kruise-rollout has restarted, abort!!!"
|
||||
kubectl get pod -n kruise-rollout --no-headers| awk '{print $1}' | xargs kubectl logs -p -n kruise-rollout
|
||||
exit 1
|
||||
fi
|
||||
exit $retVal
|
||||
- name: Deployment Bluegreen Release
|
||||
run: |
|
||||
export KUBECONFIG=/home/runner/.kube/config
|
||||
make ginkgo
|
||||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='Bluegreen Release - Deployment - Ingress' test/e2e
|
||||
retVal=$?
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
restartCount=$(kubectl get pod -n kruise-rollout --no-headers | awk '{print $4}')
|
||||
if [ "${restartCount}" -eq "0" ];then
|
||||
echo "Kruise-rollout has not restarted"
|
||||
else
|
||||
kubectl get pod -n kruise-rollout --no-headers
|
||||
echo "Kruise-rollout has restarted, abort!!!"
|
||||
kubectl get pod -n kruise-rollout --no-headers| awk '{print $1}' | xargs kubectl logs -p -n kruise-rollout
|
||||
exit 1
|
||||
fi
|
||||
exit $retVal
|
||||
- name: CloneSet Bluegreen Release
|
||||
run: |
|
||||
export KUBECONFIG=/home/runner/.kube/config
|
||||
make ginkgo
|
||||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='Bluegreen Release - Cloneset - Ingress' test/e2e
|
||||
retVal=$?
|
||||
if [ "${retVal}" -ne 0 ];then
|
||||
echo "test fail, dump kruise-rollout logs"
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
fi
|
||||
exit $retVal
|
|
@ -0,0 +1,109 @@
|
|||
name: E2E-V1Beta1-JUMP-1.24
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- release-*
|
||||
pull_request: {}
|
||||
workflow_dispatch: {}
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.20'
|
||||
KIND_VERSION: 'v0.14.0'
|
||||
KIND_IMAGE: 'kindest/node:v1.24.6'
|
||||
KIND_CLUSTER_NAME: 'ci-testing'
|
||||
|
||||
jobs:
|
||||
|
||||
rollout:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Setup Kind Cluster
|
||||
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
|
||||
with:
|
||||
node_image: ${{ env.KIND_IMAGE }}
|
||||
cluster_name: ${{ env.KIND_CLUSTER_NAME }}
|
||||
config: ./test/kind-conf.yaml
|
||||
version: ${{ env.KIND_VERSION }}
|
||||
- name: Build image
|
||||
run: |
|
||||
export IMAGE="openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID}"
|
||||
docker build --pull --no-cache . -t $IMAGE
|
||||
kind load docker-image --name=${KIND_CLUSTER_NAME} $IMAGE || { echo >&2 "kind not installed or error loading image: $IMAGE"; exit 1; }
|
||||
- name: Install Kruise
|
||||
run: |
|
||||
set -ex
|
||||
kubectl cluster-info
|
||||
make helm
|
||||
helm repo add openkruise https://openkruise.github.io/charts/
|
||||
helm repo update
|
||||
helm install kruise openkruise/kruise --version 1.7.0
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-system | grep '1/1' | grep kruise-controller-manager | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "2" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 3
|
||||
done
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-system | grep '1/1' | grep kruise-controller-manager | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "2" ]; then
|
||||
echo "Wait for kruise-manager ready successfully"
|
||||
else
|
||||
echo "Timeout to wait for kruise-manager ready"
|
||||
exit 1
|
||||
fi
|
||||
- name: Install Kruise Rollout
|
||||
run: |
|
||||
set -ex
|
||||
kubectl cluster-info
|
||||
IMG=openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID} ./scripts/deploy_kind.sh
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-rollout | grep '1/1' | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "1" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 3
|
||||
done
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-rollout | grep '1/1' | wc -l)
|
||||
kubectl get node -o yaml
|
||||
kubectl get all -n kruise-rollout -o yaml
|
||||
set -e
|
||||
if [ "$PODS" -eq "1" ]; then
|
||||
echo "Wait for kruise-rollout ready successfully"
|
||||
else
|
||||
echo "Timeout to wait for kruise-rollout ready"
|
||||
exit 1
|
||||
fi
|
||||
- name: Run E2E Tests
|
||||
run: |
|
||||
export KUBECONFIG=/home/runner/.kube/config
|
||||
make ginkgo
|
||||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='Step Jump' test/e2e
|
||||
retVal=$?
|
||||
if [ "${retVal}" -ne 0 ];then
|
||||
echo "test fail, dump kruise-rollout logs"
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
fi
|
||||
exit $retVal
|
|
@ -0,0 +1,108 @@
|
|||
name: E2E-V1Beta1-JUMP-1.26
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- release-*
|
||||
pull_request: {}
|
||||
workflow_dispatch: {}
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.20'
|
||||
KIND_IMAGE: 'kindest/node:v1.26.3'
|
||||
KIND_CLUSTER_NAME: 'ci-testing'
|
||||
|
||||
jobs:
|
||||
|
||||
rollout:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Setup Kind Cluster
|
||||
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
|
||||
with:
|
||||
node_image: ${{ env.KIND_IMAGE }}
|
||||
cluster_name: ${{ env.KIND_CLUSTER_NAME }}
|
||||
config: ./test/kind-conf.yaml
|
||||
version: ${{ env.KIND_VERSION }}
|
||||
- name: Build image
|
||||
run: |
|
||||
export IMAGE="openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID}"
|
||||
docker build --pull --no-cache . -t $IMAGE
|
||||
kind load docker-image --name=${KIND_CLUSTER_NAME} $IMAGE || { echo >&2 "kind not installed or error loading image: $IMAGE"; exit 1; }
|
||||
- name: Install Kruise
|
||||
run: |
|
||||
set -ex
|
||||
kubectl cluster-info
|
||||
make helm
|
||||
helm repo add openkruise https://openkruise.github.io/charts/
|
||||
helm repo update
|
||||
helm install kruise openkruise/kruise --version 1.7.0
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-system | grep '1/1' | grep kruise-controller-manager | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "2" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 3
|
||||
done
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-system | grep '1/1' | grep kruise-controller-manager | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "2" ]; then
|
||||
echo "Wait for kruise-manager ready successfully"
|
||||
else
|
||||
echo "Timeout to wait for kruise-manager ready"
|
||||
exit 1
|
||||
fi
|
||||
- name: Install Kruise Rollout
|
||||
run: |
|
||||
set -ex
|
||||
kubectl cluster-info
|
||||
IMG=openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID} ./scripts/deploy_kind.sh
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-rollout | grep '1/1' | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "1" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 3
|
||||
done
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-rollout | grep '1/1' | wc -l)
|
||||
kubectl get node -o yaml
|
||||
kubectl get all -n kruise-rollout -o yaml
|
||||
set -e
|
||||
if [ "$PODS" -eq "1" ]; then
|
||||
echo "Wait for kruise-rollout ready successfully"
|
||||
else
|
||||
echo "Timeout to wait for kruise-rollout ready"
|
||||
exit 1
|
||||
fi
|
||||
- name: Run E2E Tests
|
||||
run: |
|
||||
export KUBECONFIG=/home/runner/.kube/config
|
||||
make ginkgo
|
||||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='Step Jump' test/e2e
|
||||
retVal=$?
|
||||
if [ "${retVal}" -ne 0 ];then
|
||||
echo "test fail, dump kruise-rollout logs"
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
fi
|
||||
exit $retVal
|
|
@ -0,0 +1,108 @@
|
|||
name: E2E-V1Beta1-JUMP-1.28
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- release-*
|
||||
pull_request: {}
|
||||
workflow_dispatch: {}
|
||||
|
||||
env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.20'
|
||||
KIND_VERSION: 'v0.22.0'
|
||||
KIND_IMAGE: 'kindest/node:v1.28.7'
|
||||
KIND_CLUSTER_NAME: 'ci-testing'
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
rollout:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Setup Kind Cluster
|
||||
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
|
||||
with:
|
||||
node_image: ${{ env.KIND_IMAGE }}
|
||||
cluster_name: ${{ env.KIND_CLUSTER_NAME }}
|
||||
config: ./test/kind-conf.yaml
|
||||
version: ${{ env.KIND_VERSION }}
|
||||
- name: Build image
|
||||
run: |
|
||||
export IMAGE="openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID}"
|
||||
docker build --pull --no-cache . -t $IMAGE
|
||||
kind load docker-image --name=${KIND_CLUSTER_NAME} $IMAGE || { echo >&2 "kind not installed or error loading image: $IMAGE"; exit 1; }
|
||||
- name: Install Kruise
|
||||
run: |
|
||||
set -ex
|
||||
kubectl cluster-info
|
||||
make helm
|
||||
helm repo add openkruise https://openkruise.github.io/charts/
|
||||
helm repo update
|
||||
helm install kruise openkruise/kruise --version 1.7.0
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-system | grep '1/1' | grep kruise-controller-manager | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "2" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 3
|
||||
done
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-system | grep '1/1' | grep kruise-controller-manager | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "2" ]; then
|
||||
echo "Wait for kruise-manager ready successfully"
|
||||
else
|
||||
echo "Timeout to wait for kruise-manager ready"
|
||||
exit 1
|
||||
fi
|
||||
- name: Install Kruise Rollout
|
||||
run: |
|
||||
set -ex
|
||||
kubectl cluster-info
|
||||
IMG=openkruise/kruise-rollout:e2e-${GITHUB_RUN_ID} ./scripts/deploy_kind.sh
|
||||
for ((i=1;i<10;i++));
|
||||
do
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-rollout | grep '1/1' | wc -l)
|
||||
set -e
|
||||
if [ "$PODS" -eq "1" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 3
|
||||
done
|
||||
set +e
|
||||
PODS=$(kubectl get pod -n kruise-rollout | grep '1/1' | wc -l)
|
||||
kubectl get node -o yaml
|
||||
kubectl get all -n kruise-rollout -o yaml
|
||||
set -e
|
||||
if [ "$PODS" -eq "1" ]; then
|
||||
echo "Wait for kruise-rollout ready successfully"
|
||||
else
|
||||
echo "Timeout to wait for kruise-rollout ready"
|
||||
exit 1
|
||||
fi
|
||||
- name: Run E2E Tests
|
||||
run: |
|
||||
export KUBECONFIG=/home/runner/.kube/config
|
||||
make ginkgo
|
||||
set +e
|
||||
./bin/ginkgo -timeout 60m -v --focus='Step Jump' test/e2e
|
||||
retVal=$?
|
||||
if [ "${retVal}" -ne 0 ];then
|
||||
echo "test fail, dump kruise-rollout logs"
|
||||
kubectl get pod -n kruise-rollout --no-headers | grep manager | awk '{print $1}' | xargs kubectl logs -n kruise-rollout
|
||||
fi
|
||||
exit $retVal
|
|
@ -10,12 +10,15 @@ on:
|
|||
- master
|
||||
- release-*
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
license_check:
|
||||
runs-on: ubuntu-latest
|
||||
name: Check for unapproved licenses
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Set up Ruby
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
|
|
|
@ -29,3 +29,5 @@ test/e2e/generated/bindata.go
|
|||
.vscode
|
||||
|
||||
.DS_Store
|
||||
|
||||
lua_configuration/networking.istio.io/**/testdata/*.lua
|
||||
|
|
132
.golangci.yml
132
.golangci.yml
|
@ -1,79 +1,77 @@
|
|||
# options for analysis running
|
||||
version: "2"
|
||||
run:
|
||||
# default concurrency is a available CPU number
|
||||
concurrency: 4
|
||||
|
||||
# timeout for analysis, e.g. 30s, 5m, default is 1m
|
||||
deadline: 5m
|
||||
|
||||
# exit code when at least one issue was found, default is 1
|
||||
issues-exit-code: 1
|
||||
|
||||
# include test files or not, default is true
|
||||
tests: true
|
||||
|
||||
# list of build tags, all linters use it. Default is empty list.
|
||||
#build-tags:
|
||||
# - mytag
|
||||
|
||||
# which dirs to skip: they won't be analyzed;
|
||||
# can use regexp here: generated.*, regexp is applied on full path;
|
||||
# default value is empty list, but next dirs are always skipped independently
|
||||
# from this option's value:
|
||||
# third_party$, testdata$, examples$, Godeps$, builtin$
|
||||
skip-dirs:
|
||||
- vendor
|
||||
|
||||
# which files to skip: they will be analyzed, but issues from them
|
||||
# won't be reported. Default value is empty list, but there is
|
||||
# no need to include all autogenerated files, we confidently recognize
|
||||
# autogenerated files. If it's not please let us know.
|
||||
skip-files:
|
||||
# - ".*\\.my\\.go$"
|
||||
# - lib/bad.go
|
||||
|
||||
# output configuration options
|
||||
output:
|
||||
# colored-line-number|line-number|json|tab|checkstyle, default is "colored-line-number"
|
||||
format: colored-line-number
|
||||
|
||||
# print lines of code with issue, default is true
|
||||
print-issued-lines: true
|
||||
|
||||
# print linter name in the end of issue text, default is true
|
||||
print-linter-name: true
|
||||
|
||||
|
||||
# all available settings of specific linters
|
||||
linters-settings:
|
||||
golint:
|
||||
# minimal confidence for issues, default is 0.8
|
||||
min-confidence: 0.8
|
||||
gofmt:
|
||||
# simplify code: gofmt with `-s` option, true by default
|
||||
simplify: true
|
||||
goimports:
|
||||
# put imports beginning with prefix after 3rd-party packages;
|
||||
# it's a comma-separated list of prefixes
|
||||
#local-prefixes: github.com/openkruise/rollouts
|
||||
misspell:
|
||||
# Correct spellings using locale preferences for US or UK.
|
||||
# Default is to use a neutral variety of English.
|
||||
# Setting locale to US will correct the British spelling of 'colour' to 'color'.
|
||||
locale: default
|
||||
#ignore-words:
|
||||
# - someword
|
||||
|
||||
formats:
|
||||
text:
|
||||
path: stdout
|
||||
colors: true
|
||||
linters:
|
||||
fast: false
|
||||
disable-all: true
|
||||
default: none
|
||||
enable:
|
||||
# TODO Enforce the below linters later
|
||||
- gofmt
|
||||
- goimports
|
||||
- depguard
|
||||
- govet
|
||||
- ineffassign
|
||||
- misspell
|
||||
issues:
|
||||
exclude:
|
||||
# staticcheck
|
||||
- 'SA1019: package github.com/golang/protobuf/proto is deprecated: Use the "google.golang.org/protobuf/proto" package instead'
|
||||
- unconvert
|
||||
- unused
|
||||
settings:
|
||||
misspell:
|
||||
# Correct spellings using locale preferences for US or UK.
|
||||
# Default is to use a neutral variety of English.
|
||||
# Setting locale to US will correct the British spelling of 'colour' to 'color'.
|
||||
locale: US
|
||||
ignore-rules:
|
||||
- finalise
|
||||
- Finalising
|
||||
- Cancelling
|
||||
depguard:
|
||||
rules:
|
||||
forbid-pkg-errors:
|
||||
deny:
|
||||
- pkg: "github.com/pkg/errors"
|
||||
desc: Should be replaced with standard lib errors or fmt.Errorf
|
||||
exclusions:
|
||||
generated: lax
|
||||
presets:
|
||||
- comments
|
||||
- common-false-positives
|
||||
- legacy
|
||||
- std-error-handling
|
||||
rules:
|
||||
- path: (.+)\.go$
|
||||
text: 'SA1019: package github.com/golang/protobuf/proto is deprecated: Use the "google.golang.org/protobuf/proto" package instead'
|
||||
paths:
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
- apis
|
||||
- pkg/client
|
||||
- vendor
|
||||
- test
|
||||
formatters:
|
||||
enable:
|
||||
- gofmt
|
||||
- goimports
|
||||
settings:
|
||||
gofmt:
|
||||
simplify: true
|
||||
goimports:
|
||||
# put imports beginning with prefix after 3rd-party packages;
|
||||
local-prefixes:
|
||||
- github.com/openkruise/rollouts
|
||||
exclusions:
|
||||
generated: lax
|
||||
paths:
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
- apis
|
||||
- pkg/client
|
||||
- vendor
|
||||
- test
|
||||
|
|
88
CHANGELOG.md
88
CHANGELOG.md
|
@ -1,5 +1,93 @@
|
|||
# Change Log
|
||||
|
||||
## v0.6.1
|
||||
### Key Features:
|
||||
- Introduced `rollout-batch-id` labeling for blue-green and canary style releases ([#250](https://github.com/openkruise/rollouts/pull/250),([#251](https://github.com/openkruise/rollouts/pull/251),[#261](https://github.com/openkruise/rollouts/pull/261),[@PersistentJZH](https://github.com/PersistentJZH),[@AiRanthem](https://github.com/AiRanthem))
|
||||
|
||||
### Bugfix:
|
||||
- The order of object in BatchRelease event handler is fixed ([#265](https://github.com/openkruise/rollouts/pull/265),[@z760087139](https://github.com/z760087139))
|
||||
|
||||
## v0.5.1
|
||||
### Bugfix:
|
||||
|
||||
- Fix Rollout v1alpha1 and v1beta1 version conversions with incorrectly converted partition fields. ([#200](https://github.com/openkruise/rollouts/pull/200),[@myname4423](https://github.com/myname4423))
|
||||
|
||||
## v0.6.0
|
||||
### Key Features:
|
||||
- 🎊 Support for blue-green style releases has been added ([#214](https://github.com/openkruise/rollouts/pull/214),[#229](https://github.com/openkruise/rollouts/pull/229),[#238](https://github.com/openkruise/rollouts/pull/238),[#220](https://github.com/openkruise/rollouts/pull/220),[@myname4423](https://github.com/myname4423))
|
||||
- ⭐ Traffic loss during rollouts in certain scenarios is avoided ([#226](https://github.com/openkruise/rollouts/pull/226),[#219](https://github.com/openkruise/rollouts/pull/219),[#222](https://github.com/openkruise/rollouts/pull/222),[@myname4423](https://github.com/myname4423))
|
||||
|
||||
### Other Features:
|
||||
- Enhanced flexibility by allowing free navigation between different steps within a rollout ([#218](https://github.com/openkruise/rollouts/pull/218),[@myname4423](https://github.com/myname4423))
|
||||
- Added support for HTTPQueryParamMatch and HTTPPathMatch of the Gateway API in traffic management ([#204](https://github.com/openkruise/rollouts/pull/204),[@lujiajing1126](https://github.com/lujiajing1126))
|
||||
- Integrated RequestHeaderModifier into LuaData, facilitating its use with custom network references like Istio ([#223](https://github.com/openkruise/rollouts/pull/223),[@lujiajing1126](https://github.com/lujiajing1126))
|
||||
- Introduced a composite provider to support multiple network providers ([#224](https://github.com/openkruise/rollouts/pull/224),[@lujiajing1126](https://github.com/lujiajing1126))
|
||||
- Got the canary service selector patched from pod template metadata ([#243](https://github.com/openkruise/rollouts/pull/243),[@lujiajing1126](https://github.com/lujiajing1126))
|
||||
- Patched label `rollout-batch-id` to pods even without `rollout-id` in the workload ([#248](https://github.com/openkruise/rollouts/pull/248),[@PersistentJZH](https://github.com/PersistentJZH))
|
||||
- Upgraded Gateway API version from 0.5.1 to 0.7.1 and Kubernetes version from 1.24 to 1.26 ([#237](https://github.com/openkruise/rollouts/pull/237),[@AiRanthem](https://github.com/AiRanthem))
|
||||
- Enabled the option to skip canary service generation when using `trafficRoutings.customNetworkRefs` ([#200](https://github.com/openkruise/rollouts/pull/200),[@myname4423](https://github.com/myname4423))
|
||||
|
||||
### Bugfix:
|
||||
- Filtered out ReplicaSets not part of the current Deployment to prevent frequent scaling issues when multiple deployments share the same selectors ([#191](https://github.com/openkruise/rollouts/pull/191),[@zhengjr9](https://github.com/zhengjr9))
|
||||
- Synced the observed `rollout-id` to the BatchRelease CR status ([#193](https://github.com/openkruise/rollouts/pull/193),[@veophi](https://github.com/veophi))
|
||||
- Checked deployment strategy during finalization to prevent random stuck states when used with KubeVela ([#198](https://github.com/openkruise/rollouts/pull/198),[@phantomnat](https://github.com/phantomnat))
|
||||
- Resolved a Lua encoding structural error ([#209](https://github.com/openkruise/rollouts/pull/209),[@ls-2018](https://github.com/ls-2018))
|
||||
- Corrected batch ID labeling in partition-style releases when pod recreation happens ([#246](https://github.com/openkruise/rollouts/pull/246),[@myname4423](https://github.com/myname4423))
|
||||
|
||||
### Breaking Changes:
|
||||
- Restricted the ability to set traffic percentage or match selectors in a partition-style release step when exceeding 30% replicas. Use the `rollouts.kruise.io/partition-replicas-limit` annotation to override this default threshold. Setting the threshold to 100% restores the previous behavior ([#225](https://github.com/openkruise/rollouts/pull/225),[@myname4423](https://github.com/myname4423))
|
||||
|
||||
## v0.5.0
|
||||
### Resources Graduating to BETA
|
||||
|
||||
After more than a year of development, we have now decided to upgrade the following resources to v1beta1, as follows:
|
||||
- Rollout
|
||||
- BatchRelease
|
||||
|
||||
Please refer to the [community documentation](https://openkruise.io/rollouts/user-manuals/api-specifications) for detailed api definitions.
|
||||
|
||||
**Note:** The v1alpha1 api is still available, and you can still use the v1alpha1 api in v0.5.0.
|
||||
But we still recommend that you migrate to v1beta1 gradually, as some of the new features will only be available in v1beta1,
|
||||
e.g., [Extensible Traffic Routing Based on Lua Script](https://openkruise.io/rollouts/developer-manuals/custom-network-provider/).
|
||||
|
||||
### Bump To V1beta1 Gateway API
|
||||
Support for GatewayAPI from v1alpha2 to v1beta1, you can use v1beta1 gateway API.
|
||||
|
||||
### Extensible Traffic Routing Based on Lua Script
|
||||
|
||||
The Gateway API is a standard gateway resource given by the K8S community, but there are still a large number of users in the community who are still using some customized gateway resources, such as VirtualService, Apisix, and so on.
|
||||
In order to adapt to this behavior and meet the diverse demands of the community for gateway resources, we support a traffic routing scheme based on Lua scripts.
|
||||
|
||||
Kruise Rollout utilizes a Lua-script-based customization approach for API Gateway resources (Istio VirtualService, Apisix ApisixRoute, Kuma TrafficRoute and etc.).
|
||||
Kruise Rollout involves invoking Lua scripts to retrieve and update the desired configurations of resources based on release strategies and the original configurations of API Gateway resources (including spec, labels, and annotations).
|
||||
It enables users to easily adapt and integrate various types of API Gateway resources without modifying existing code and configurations.
|
||||
|
||||
By using Kruise Rollout, users can:
|
||||
- Customize Lua scripts for handling API Gateway resources, allowing for flexible implementation of resource processing and providing support for a wider range of resources.
|
||||
- Utilize a common Rollout configuration template to configure different resources, reducing configuration complexity and facilitating user configuration.
|
||||
|
||||
### Traffic Routing with Istio
|
||||
Based on the lua script approach, now we add built-in support for Istio resources VirtualService,
|
||||
you can directly use Kruise Rollout to achieve Istio scenarios Canary, A/B Testing release.
|
||||
|
||||
### Others
|
||||
- Bug fix: wait grace period seconds after pod creation/upgrade. ([#185](https://github.com/openkruise/rollouts/pull/185), [@veophi](https://github.com/veophi))
|
||||
|
||||
## v0.4.0
|
||||
### Kruise-Rollout-Controller
|
||||
- Rollout Support Kruise Advanced DaemonSet. ([#134](https://github.com/openkruise/rollouts/pull/134), [@Yadan-Wei](https://github.com/Yadan-Wei))
|
||||
- Rollout support end-to-end canary deployment. ([#153](https://github.com/openkruise/rollouts/pull/153), [@zmberg](https://github.com/zmberg))
|
||||
- Rollout trafficTouting support requestHeaderModifier. ([#156](https://github.com/openkruise/rollouts/pull/156), [@zmberg](https://github.com/zmberg))
|
||||
- Rollout support disabled for a rollout. ([#155](https://github.com/openkruise/rollouts/pull/155), [@Kuromesi](https://github.com/Kuromesi))
|
||||
- Rollout support patch PodTemplateMetadata. ([#157](https://github.com/openkruise/rollouts/pull/157), [@zmberg](https://github.com/zmberg))
|
||||
- Rollout only webhook workload which has rollout CR. ([#158](https://github.com/openkruise/rollouts/pull/158), [@zmberg](https://github.com/zmberg))
|
||||
- Advanced deployment scale down old unhealthy pods firstly. ([#150](https://github.com/openkruise/rollouts/pull/150), [@veophi](https://github.com/veophi))
|
||||
- Update k8s registry references to registry.k8s.io. ([#126](https://github.com/openkruise/rollouts/pull/126), [@asa3311](https://github.com/asa3311))
|
||||
- When the data type of spec.replicas is int, cancel the upper 100 limit. ([#142](https://github.com/openkruise/rollouts/pull/142), [@MrSumeng](https://github.com/MrSumeng))
|
||||
- Add e2e test for advanced daemonSet. ([#143](https://github.com/openkruise/rollouts/pull/143), [@Janice1457](https://github.com/Janice1457))
|
||||
- Exclude workload deleted matching labels in webhook. ([#146](https://github.com/openkruise/rollouts/pull/146), [@wangyikewxgm](https://github.com/wangyikewxgm))
|
||||
- Optimize the modification of rollout to GatewayAPI httpRoute header. ([#137](https://github.com/openkruise/rollouts/pull/137), [@ZhangSetSail](https://github.com/ZhangSetSail))
|
||||
|
||||
## v0.3.0
|
||||
|
||||
### Kruise-Rollout-Controller
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
# Build the manager binary
|
||||
FROM golang:1.18 as builder
|
||||
FROM golang:1.20.14-alpine3.19 as builder
|
||||
|
||||
WORKDIR /workspace
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Build the manager binary
|
||||
ARG BASE_IMAGE=alpine
|
||||
ARG BASE_IMAGE_VERION=3.17
|
||||
FROM --platform=$BUILDPLATFORM golang:1.18-alpine3.17 as builder
|
||||
FROM --platform=$BUILDPLATFORM golang:1.19-alpine3.17 as builder
|
||||
|
||||
WORKDIR /workspace
|
||||
|
||||
|
@ -23,12 +23,25 @@ ARG BASE_IMAGE
|
|||
ARG BASE_IMAGE_VERION
|
||||
FROM ${BASE_IMAGE}:${BASE_IMAGE_VERION}
|
||||
|
||||
RUN apk add --no-cache ca-certificates=~20220614-r4 bash=~5.2.15-r0 expat=~2.5.0-r0 \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
RUN set -eux; \
|
||||
apk --no-cache --update upgrade && \
|
||||
apk --no-cache add ca-certificates && \
|
||||
apk --no-cache add tzdata && \
|
||||
rm -rf /var/cache/apk/* && \
|
||||
update-ca-certificates && \
|
||||
echo "only include root and nobody user" && \
|
||||
echo -e "root:x:0:0:root:/root:/bin/ash\nnobody:x:65534:65534:nobody:/:/sbin/nologin" | tee /etc/passwd && \
|
||||
echo -e "root:x:0:root\nnobody:x:65534:" | tee /etc/group && \
|
||||
rm -rf /usr/local/sbin/* && \
|
||||
rm -rf /usr/local/bin/* && \
|
||||
rm -rf /usr/sbin/* && \
|
||||
rm -rf /usr/bin/* && \
|
||||
rm -rf /sbin/* && \
|
||||
rm -rf /bin/*
|
||||
|
||||
WORKDIR /
|
||||
COPY --from=builder /workspace/manager .
|
||||
COPY lua_configuration /lua_configuration
|
||||
USER 1000
|
||||
USER 65534
|
||||
|
||||
ENTRYPOINT ["/manager"]
|
||||
|
|
37
Makefile
37
Makefile
|
@ -19,6 +19,24 @@ SHELL = /usr/bin/env bash -o pipefail
|
|||
|
||||
all: build
|
||||
|
||||
## Location to install dependencies to
|
||||
TESTBIN ?= $(shell pwd)/testbin
|
||||
$(TESTBIN):
|
||||
mkdir -p $(TESTBIN)
|
||||
|
||||
# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary.
|
||||
# Run `setup-envtest list` to list available versions.
|
||||
ENVTEST_K8S_VERSION ?= 1.28.0
|
||||
|
||||
ENVTEST ?= $(TESTBIN)/setup-envtest
|
||||
|
||||
.PHONY: envtest
|
||||
envtest: $(ENVTEST) ## Download envtest-setup locally if necessary.
|
||||
$(ENVTEST): $(TESTBIN)
|
||||
ifeq (, $(shell ls $(TESTBIN)/setup-envtest 2>/dev/null))
|
||||
GOBIN=$(TESTBIN) go install sigs.k8s.io/controller-runtime/tools/setup-envtest@c7e1dc9b5302d649d5531e19168dd7ea0013736d
|
||||
endif
|
||||
|
||||
##@ General
|
||||
|
||||
# The help target prints out all targets with their descriptions organized
|
||||
|
@ -51,10 +69,10 @@ vet: ## Run go vet against code.
|
|||
go vet ./...
|
||||
|
||||
ENVTEST_ASSETS_DIR=$(shell pwd)/testbin
|
||||
test: manifests generate fmt vet ## Run tests.
|
||||
mkdir -p ${ENVTEST_ASSETS_DIR}
|
||||
test -f ${ENVTEST_ASSETS_DIR}/setup-envtest.sh || curl -sSLo ${ENVTEST_ASSETS_DIR}/setup-envtest.sh https://raw.githubusercontent.com/kubernetes-sigs/controller-runtime/v0.8.3/hack/setup-envtest.sh
|
||||
source ${ENVTEST_ASSETS_DIR}/setup-envtest.sh; fetch_envtest_tools $(ENVTEST_ASSETS_DIR); setup_envtest_env $(ENVTEST_ASSETS_DIR); go test ./pkg/... -coverprofile cover.out
|
||||
test: manifests generate fmt vet envtest ## Run tests.
|
||||
echo $(ENVTEST)
|
||||
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)" go test -race ./pkg/... -coverprofile raw-cover.out
|
||||
grep -v "pkg/client" raw-cover.out > cover.out
|
||||
|
||||
##@ Build
|
||||
|
||||
|
@ -91,16 +109,17 @@ undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/confi
|
|||
|
||||
|
||||
CONTROLLER_GEN = $(shell pwd)/bin/controller-gen
|
||||
CONTROLLER_GEN_VERSION = v0.14.0
|
||||
controller-gen: ## Download controller-gen locally if necessary.
|
||||
ifeq ("$(shell $(CONTROLLER_GEN) --version)", "Version: v0.7.0")
|
||||
ifeq ("$(shell $(CONTROLLER_GEN) --version)", "Version: ${CONTROLLER_GEN_VERSION}")
|
||||
else
|
||||
rm -rf $(CONTROLLER_GEN)
|
||||
$(call go-get-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.7.0)
|
||||
$(call go-get-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@${CONTROLLER_GEN_VERSION})
|
||||
endif
|
||||
|
||||
KUSTOMIZE = $(shell pwd)/bin/kustomize
|
||||
kustomize: ## Download kustomize locally if necessary.
|
||||
$(call go-get-tool,$(KUSTOMIZE),sigs.k8s.io/kustomize/kustomize/v3@v3.8.7)
|
||||
$(call go-get-tool,$(KUSTOMIZE),sigs.k8s.io/kustomize/kustomize/v4@v4.5.5)
|
||||
|
||||
GINKGO = $(shell pwd)/bin/ginkgo
|
||||
ginkgo: ## Download ginkgo locally if necessary.
|
||||
|
@ -108,7 +127,7 @@ ginkgo: ## Download ginkgo locally if necessary.
|
|||
|
||||
HELM = $(shell pwd)/bin/helm
|
||||
helm: ## Download helm locally if necessary.
|
||||
$(call go-get-tool,$(HELM),helm.sh/helm/v3@v3.8.1)
|
||||
$(call go-get-tool,$(HELM),helm.sh/helm/v3/cmd/helm@v3.14.0)
|
||||
|
||||
# go-get-tool will 'go get' any package $2 and install it to $1.
|
||||
PROJECT_DIR := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||
|
@ -119,7 +138,7 @@ TMP_DIR=$$(mktemp -d) ;\
|
|||
cd $$TMP_DIR ;\
|
||||
go mod init tmp ;\
|
||||
echo "Downloading $(2)" ;\
|
||||
GOBIN=$(PROJECT_DIR)/bin go get $(2) ;\
|
||||
GOBIN=$(PROJECT_DIR)/bin go install $(2) ;\
|
||||
rm -rf $$TMP_DIR ;\
|
||||
}
|
||||
endef
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
Copyright 2023 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 apis
|
||||
|
||||
import (
|
||||
"github.com/openkruise/rollouts/api/v1alpha1"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Register the types with the Scheme so the components can map objects to GroupVersionKinds and back
|
||||
AddToSchemes = append(AddToSchemes, v1alpha1.SchemeBuilder.AddToScheme)
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
Copyright 2023 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 apis
|
||||
|
||||
import (
|
||||
"github.com/openkruise/rollouts/api/v1beta1"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Register the types with the Scheme so the components can map objects to GroupVersionKinds and back
|
||||
AddToSchemes = append(AddToSchemes, v1beta1.SchemeBuilder.AddToScheme)
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
Copyright 2023 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 apis
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// AddToSchemes may be used to add all resources defined in the project to a Scheme
|
||||
var AddToSchemes runtime.SchemeBuilder
|
||||
|
||||
// AddToScheme adds all Resources to the Scheme
|
||||
func AddToScheme(s *runtime.Scheme) error {
|
||||
return AddToSchemes.AddToScheme(s)
|
||||
}
|
|
@ -54,6 +54,16 @@ type ReleasePlan struct {
|
|||
// only support for canary deployment
|
||||
// +optional
|
||||
PatchPodTemplateMetadata *PatchPodTemplateMetadata `json:"patchPodTemplateMetadata,omitempty"`
|
||||
// RollingStyle can be "Canary", "Partiton" or "BlueGreen"
|
||||
RollingStyle RollingStyleType `json:"rollingStyle,omitempty"`
|
||||
// EnableExtraWorkloadForCanary indicates whether to create extra workload for canary
|
||||
// True corresponds to RollingStyle "Canary".
|
||||
// False corresponds to RollingStyle "Partiton".
|
||||
// Ignored in BlueGreen-style.
|
||||
// This field is about to deprecate, use RollingStyle instead.
|
||||
// If both of them are set, controller will only consider this
|
||||
// filed when RollingStyle is empty
|
||||
EnableExtraWorkloadForCanary bool `json:"enableExtraWorkloadForCanary"`
|
||||
}
|
||||
|
||||
type FinalizingPolicyType string
|
||||
|
@ -142,6 +152,6 @@ const (
|
|||
RolloutPhasePreparing RolloutPhase = "Preparing"
|
||||
// RolloutPhaseFinalizing indicates a rollout is finalizing
|
||||
RolloutPhaseFinalizing RolloutPhase = "Finalizing"
|
||||
// RolloutPhaseCompleted indicates a rollout is completed/cancelled/terminated
|
||||
// RolloutPhaseCompleted indicates a rollout is completed/canceled/terminated
|
||||
RolloutPhaseCompleted RolloutPhase = "Completed"
|
||||
)
|
||||
|
|
|
@ -0,0 +1,478 @@
|
|||
/*
|
||||
Copyright 2023 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 v1alpha1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
utilpointer "k8s.io/utils/pointer"
|
||||
"sigs.k8s.io/controller-runtime/pkg/conversion"
|
||||
|
||||
"github.com/openkruise/rollouts/api/v1beta1"
|
||||
)
|
||||
|
||||
func (src *Rollout) ConvertTo(dst conversion.Hub) error {
|
||||
switch t := dst.(type) {
|
||||
case *v1beta1.Rollout:
|
||||
obj := dst.(*v1beta1.Rollout)
|
||||
obj.ObjectMeta = src.ObjectMeta
|
||||
obj.Spec = v1beta1.RolloutSpec{}
|
||||
srcSpec := src.Spec
|
||||
obj.Spec.WorkloadRef = v1beta1.ObjectRef{
|
||||
APIVersion: srcSpec.ObjectRef.WorkloadRef.APIVersion,
|
||||
Kind: srcSpec.ObjectRef.WorkloadRef.Kind,
|
||||
Name: srcSpec.ObjectRef.WorkloadRef.Name,
|
||||
}
|
||||
obj.Spec.Disabled = srcSpec.Disabled
|
||||
obj.Spec.Strategy = v1beta1.RolloutStrategy{
|
||||
Paused: srcSpec.Strategy.Paused,
|
||||
Canary: &v1beta1.CanaryStrategy{
|
||||
FailureThreshold: srcSpec.Strategy.Canary.FailureThreshold,
|
||||
},
|
||||
}
|
||||
for _, step := range srcSpec.Strategy.Canary.Steps {
|
||||
o := v1beta1.CanaryStep{
|
||||
TrafficRoutingStrategy: ConversionToV1beta1TrafficRoutingStrategy(step.TrafficRoutingStrategy),
|
||||
Replicas: step.Replicas,
|
||||
Pause: v1beta1.RolloutPause{Duration: step.Pause.Duration},
|
||||
}
|
||||
if step.Replicas == nil && step.Weight != nil {
|
||||
o.Replicas = &intstr.IntOrString{
|
||||
Type: intstr.String,
|
||||
StrVal: fmt.Sprintf("%d", *step.Weight) + "%",
|
||||
}
|
||||
}
|
||||
obj.Spec.Strategy.Canary.Steps = append(obj.Spec.Strategy.Canary.Steps, o)
|
||||
}
|
||||
for _, ref := range srcSpec.Strategy.Canary.TrafficRoutings {
|
||||
o := ConversionToV1beta1TrafficRoutingRef(ref)
|
||||
obj.Spec.Strategy.Canary.TrafficRoutings = append(obj.Spec.Strategy.Canary.TrafficRoutings, o)
|
||||
}
|
||||
if srcSpec.Strategy.Canary.PatchPodTemplateMetadata != nil {
|
||||
obj.Spec.Strategy.Canary.PatchPodTemplateMetadata = &v1beta1.PatchPodTemplateMetadata{
|
||||
Annotations: map[string]string{},
|
||||
Labels: map[string]string{},
|
||||
}
|
||||
for k, v := range srcSpec.Strategy.Canary.PatchPodTemplateMetadata.Annotations {
|
||||
obj.Spec.Strategy.Canary.PatchPodTemplateMetadata.Annotations[k] = v
|
||||
}
|
||||
for k, v := range srcSpec.Strategy.Canary.PatchPodTemplateMetadata.Labels {
|
||||
obj.Spec.Strategy.Canary.PatchPodTemplateMetadata.Labels[k] = v
|
||||
}
|
||||
}
|
||||
if !strings.EqualFold(src.Annotations[RolloutStyleAnnotation], string(PartitionRollingStyle)) {
|
||||
obj.Spec.Strategy.Canary.EnableExtraWorkloadForCanary = true
|
||||
}
|
||||
if src.Annotations[TrafficRoutingAnnotation] != "" {
|
||||
obj.Spec.Strategy.Canary.TrafficRoutingRef = src.Annotations[TrafficRoutingAnnotation]
|
||||
}
|
||||
|
||||
// status
|
||||
obj.Status = v1beta1.RolloutStatus{
|
||||
ObservedGeneration: src.Status.ObservedGeneration,
|
||||
Phase: v1beta1.RolloutPhase(src.Status.Phase),
|
||||
Message: src.Status.Message,
|
||||
}
|
||||
for _, cond := range src.Status.Conditions {
|
||||
o := v1beta1.RolloutCondition{
|
||||
Type: v1beta1.RolloutConditionType(cond.Type),
|
||||
Status: cond.Status,
|
||||
LastUpdateTime: cond.LastUpdateTime,
|
||||
LastTransitionTime: cond.LastTransitionTime,
|
||||
Reason: cond.Reason,
|
||||
Message: cond.Message,
|
||||
}
|
||||
obj.Status.Conditions = append(obj.Status.Conditions, o)
|
||||
}
|
||||
if src.Status.CanaryStatus == nil {
|
||||
return nil
|
||||
}
|
||||
obj.Status.CanaryStatus = &v1beta1.CanaryStatus{
|
||||
CommonStatus: v1beta1.CommonStatus{
|
||||
ObservedWorkloadGeneration: src.Status.CanaryStatus.ObservedWorkloadGeneration,
|
||||
ObservedRolloutID: src.Status.CanaryStatus.ObservedRolloutID,
|
||||
RolloutHash: src.Status.CanaryStatus.RolloutHash,
|
||||
StableRevision: src.Status.CanaryStatus.StableRevision,
|
||||
PodTemplateHash: src.Status.CanaryStatus.PodTemplateHash,
|
||||
CurrentStepIndex: src.Status.CanaryStatus.CurrentStepIndex,
|
||||
CurrentStepState: v1beta1.CanaryStepState(src.Status.CanaryStatus.CurrentStepState),
|
||||
Message: src.Status.CanaryStatus.Message,
|
||||
LastUpdateTime: src.Status.CanaryStatus.LastUpdateTime,
|
||||
FinalisingStep: v1beta1.FinalisingStepType(src.Status.CanaryStatus.FinalisingStep),
|
||||
NextStepIndex: src.Status.CanaryStatus.NextStepIndex,
|
||||
},
|
||||
CanaryRevision: src.Status.CanaryStatus.CanaryRevision,
|
||||
CanaryReplicas: src.Status.CanaryStatus.CanaryReplicas,
|
||||
CanaryReadyReplicas: src.Status.CanaryStatus.CanaryReadyReplicas,
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("unsupported type %v", t)
|
||||
}
|
||||
}
|
||||
|
||||
func ConversionToV1beta1TrafficRoutingRef(src TrafficRoutingRef) (dst v1beta1.TrafficRoutingRef) {
|
||||
dst.Service = src.Service
|
||||
dst.GracePeriodSeconds = src.GracePeriodSeconds
|
||||
if src.Ingress != nil {
|
||||
dst.Ingress = &v1beta1.IngressTrafficRouting{
|
||||
ClassType: src.Ingress.ClassType,
|
||||
Name: src.Ingress.Name,
|
||||
}
|
||||
}
|
||||
if src.Gateway != nil {
|
||||
dst.Gateway = &v1beta1.GatewayTrafficRouting{
|
||||
HTTPRouteName: src.Gateway.HTTPRouteName,
|
||||
}
|
||||
}
|
||||
for _, ref := range src.CustomNetworkRefs {
|
||||
obj := v1beta1.ObjectRef{
|
||||
APIVersion: ref.APIVersion,
|
||||
Kind: ref.Kind,
|
||||
Name: ref.Name,
|
||||
}
|
||||
dst.CustomNetworkRefs = append(dst.CustomNetworkRefs, obj)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
func ConversionToV1beta1TrafficRoutingStrategy(src TrafficRoutingStrategy) (dst v1beta1.TrafficRoutingStrategy) {
|
||||
if src.Weight != nil {
|
||||
dst.Traffic = utilpointer.String(fmt.Sprintf("%d", *src.Weight) + "%")
|
||||
}
|
||||
dst.RequestHeaderModifier = src.RequestHeaderModifier
|
||||
for _, match := range src.Matches {
|
||||
obj := v1beta1.HttpRouteMatch{
|
||||
Headers: match.Headers,
|
||||
}
|
||||
dst.Matches = append(dst.Matches, obj)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
func (dst *Rollout) ConvertFrom(src conversion.Hub) error {
|
||||
switch t := src.(type) {
|
||||
case *v1beta1.Rollout:
|
||||
srcV1beta1 := src.(*v1beta1.Rollout)
|
||||
dst.ObjectMeta = srcV1beta1.ObjectMeta
|
||||
if !srcV1beta1.Spec.Strategy.IsCanaryStragegy() {
|
||||
// only v1beta1 supports bluegreen strategy
|
||||
// Don't log the message because it will print too often
|
||||
return nil
|
||||
}
|
||||
// spec
|
||||
dst.Spec = RolloutSpec{
|
||||
ObjectRef: ObjectRef{
|
||||
WorkloadRef: &WorkloadRef{
|
||||
APIVersion: srcV1beta1.Spec.WorkloadRef.APIVersion,
|
||||
Kind: srcV1beta1.Spec.WorkloadRef.Kind,
|
||||
Name: srcV1beta1.Spec.WorkloadRef.Name,
|
||||
},
|
||||
},
|
||||
Strategy: RolloutStrategy{
|
||||
Paused: srcV1beta1.Spec.Strategy.Paused,
|
||||
Canary: &CanaryStrategy{
|
||||
FailureThreshold: srcV1beta1.Spec.Strategy.Canary.FailureThreshold,
|
||||
},
|
||||
},
|
||||
Disabled: srcV1beta1.Spec.Disabled,
|
||||
}
|
||||
for _, step := range srcV1beta1.Spec.Strategy.Canary.Steps {
|
||||
obj := CanaryStep{
|
||||
TrafficRoutingStrategy: ConversionToV1alpha1TrafficRoutingStrategy(step.TrafficRoutingStrategy),
|
||||
Replicas: step.Replicas,
|
||||
Pause: RolloutPause{Duration: step.Pause.Duration},
|
||||
}
|
||||
dst.Spec.Strategy.Canary.Steps = append(dst.Spec.Strategy.Canary.Steps, obj)
|
||||
}
|
||||
for _, ref := range srcV1beta1.Spec.Strategy.Canary.TrafficRoutings {
|
||||
obj := ConversionToV1alpha1TrafficRoutingRef(ref)
|
||||
dst.Spec.Strategy.Canary.TrafficRoutings = append(dst.Spec.Strategy.Canary.TrafficRoutings, obj)
|
||||
}
|
||||
if srcV1beta1.Spec.Strategy.Canary.PatchPodTemplateMetadata != nil {
|
||||
dst.Spec.Strategy.Canary.PatchPodTemplateMetadata = &PatchPodTemplateMetadata{
|
||||
Annotations: map[string]string{},
|
||||
Labels: map[string]string{},
|
||||
}
|
||||
for k, v := range srcV1beta1.Spec.Strategy.Canary.PatchPodTemplateMetadata.Annotations {
|
||||
dst.Spec.Strategy.Canary.PatchPodTemplateMetadata.Annotations[k] = v
|
||||
}
|
||||
for k, v := range srcV1beta1.Spec.Strategy.Canary.PatchPodTemplateMetadata.Labels {
|
||||
dst.Spec.Strategy.Canary.PatchPodTemplateMetadata.Labels[k] = v
|
||||
}
|
||||
}
|
||||
if dst.Annotations == nil {
|
||||
dst.Annotations = map[string]string{}
|
||||
}
|
||||
if srcV1beta1.Spec.Strategy.Canary.EnableExtraWorkloadForCanary {
|
||||
dst.Annotations[RolloutStyleAnnotation] = strings.ToLower(string(CanaryRollingStyle))
|
||||
} else {
|
||||
dst.Annotations[RolloutStyleAnnotation] = strings.ToLower(string(PartitionRollingStyle))
|
||||
}
|
||||
if srcV1beta1.Spec.Strategy.Canary.TrafficRoutingRef != "" {
|
||||
dst.Annotations[TrafficRoutingAnnotation] = srcV1beta1.Spec.Strategy.Canary.TrafficRoutingRef
|
||||
}
|
||||
|
||||
// status
|
||||
dst.Status = RolloutStatus{
|
||||
ObservedGeneration: srcV1beta1.Status.ObservedGeneration,
|
||||
Phase: RolloutPhase(srcV1beta1.Status.Phase),
|
||||
Message: srcV1beta1.Status.Message,
|
||||
}
|
||||
for _, cond := range srcV1beta1.Status.Conditions {
|
||||
obj := RolloutCondition{
|
||||
Type: RolloutConditionType(cond.Type),
|
||||
Status: cond.Status,
|
||||
LastUpdateTime: cond.LastUpdateTime,
|
||||
LastTransitionTime: cond.LastTransitionTime,
|
||||
Reason: cond.Reason,
|
||||
Message: cond.Message,
|
||||
}
|
||||
dst.Status.Conditions = append(dst.Status.Conditions, obj)
|
||||
}
|
||||
if srcV1beta1.Status.CanaryStatus == nil {
|
||||
return nil
|
||||
}
|
||||
dst.Status.CanaryStatus = &CanaryStatus{
|
||||
ObservedWorkloadGeneration: srcV1beta1.Status.CanaryStatus.ObservedWorkloadGeneration,
|
||||
ObservedRolloutID: srcV1beta1.Status.CanaryStatus.ObservedRolloutID,
|
||||
RolloutHash: srcV1beta1.Status.CanaryStatus.RolloutHash,
|
||||
StableRevision: srcV1beta1.Status.CanaryStatus.StableRevision,
|
||||
CanaryRevision: srcV1beta1.Status.CanaryStatus.CanaryRevision,
|
||||
PodTemplateHash: srcV1beta1.Status.CanaryStatus.PodTemplateHash,
|
||||
CanaryReplicas: srcV1beta1.Status.CanaryStatus.CanaryReplicas,
|
||||
CanaryReadyReplicas: srcV1beta1.Status.CanaryStatus.CanaryReadyReplicas,
|
||||
CurrentStepIndex: srcV1beta1.Status.CanaryStatus.CurrentStepIndex,
|
||||
CurrentStepState: CanaryStepState(srcV1beta1.Status.CanaryStatus.CurrentStepState),
|
||||
Message: srcV1beta1.Status.CanaryStatus.Message,
|
||||
LastUpdateTime: srcV1beta1.Status.CanaryStatus.LastUpdateTime,
|
||||
FinalisingStep: FinalizeStateType(srcV1beta1.Status.CanaryStatus.FinalisingStep),
|
||||
NextStepIndex: srcV1beta1.Status.CanaryStatus.NextStepIndex,
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("unsupported type %v", t)
|
||||
}
|
||||
}
|
||||
|
||||
func ConversionToV1alpha1TrafficRoutingStrategy(src v1beta1.TrafficRoutingStrategy) (dst TrafficRoutingStrategy) {
|
||||
if src.Traffic != nil {
|
||||
is := intstr.FromString(*src.Traffic)
|
||||
weight, _ := intstr.GetScaledValueFromIntOrPercent(&is, 100, true)
|
||||
dst.Weight = utilpointer.Int32(int32(weight))
|
||||
}
|
||||
dst.RequestHeaderModifier = src.RequestHeaderModifier
|
||||
for _, match := range src.Matches {
|
||||
obj := HttpRouteMatch{
|
||||
Headers: match.Headers,
|
||||
}
|
||||
dst.Matches = append(dst.Matches, obj)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
func ConversionToV1alpha1TrafficRoutingRef(src v1beta1.TrafficRoutingRef) (dst TrafficRoutingRef) {
|
||||
dst.Service = src.Service
|
||||
dst.GracePeriodSeconds = src.GracePeriodSeconds
|
||||
if src.Ingress != nil {
|
||||
dst.Ingress = &IngressTrafficRouting{
|
||||
ClassType: src.Ingress.ClassType,
|
||||
Name: src.Ingress.Name,
|
||||
}
|
||||
}
|
||||
if src.Gateway != nil {
|
||||
dst.Gateway = &GatewayTrafficRouting{
|
||||
HTTPRouteName: src.Gateway.HTTPRouteName,
|
||||
}
|
||||
}
|
||||
for _, ref := range src.CustomNetworkRefs {
|
||||
obj := CustomNetworkRef{
|
||||
APIVersion: ref.APIVersion,
|
||||
Kind: ref.Kind,
|
||||
Name: ref.Name,
|
||||
}
|
||||
dst.CustomNetworkRefs = append(dst.CustomNetworkRefs, obj)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
func (src *BatchRelease) ConvertTo(dst conversion.Hub) error {
|
||||
switch t := dst.(type) {
|
||||
case *v1beta1.BatchRelease:
|
||||
obj := dst.(*v1beta1.BatchRelease)
|
||||
obj.ObjectMeta = src.ObjectMeta
|
||||
obj.Spec = v1beta1.BatchReleaseSpec{}
|
||||
srcSpec := src.Spec
|
||||
obj.Spec.WorkloadRef = v1beta1.ObjectRef{
|
||||
APIVersion: srcSpec.TargetRef.WorkloadRef.APIVersion,
|
||||
Kind: srcSpec.TargetRef.WorkloadRef.Kind,
|
||||
Name: srcSpec.TargetRef.WorkloadRef.Name,
|
||||
}
|
||||
obj.Spec.ReleasePlan = v1beta1.ReleasePlan{
|
||||
BatchPartition: srcSpec.ReleasePlan.BatchPartition,
|
||||
RolloutID: srcSpec.ReleasePlan.RolloutID,
|
||||
FailureThreshold: srcSpec.ReleasePlan.FailureThreshold,
|
||||
FinalizingPolicy: v1beta1.FinalizingPolicyType(srcSpec.ReleasePlan.FinalizingPolicy),
|
||||
}
|
||||
for _, batch := range srcSpec.ReleasePlan.Batches {
|
||||
o := v1beta1.ReleaseBatch{
|
||||
CanaryReplicas: batch.CanaryReplicas,
|
||||
}
|
||||
obj.Spec.ReleasePlan.Batches = append(obj.Spec.ReleasePlan.Batches, o)
|
||||
}
|
||||
if srcSpec.ReleasePlan.PatchPodTemplateMetadata != nil {
|
||||
obj.Spec.ReleasePlan.PatchPodTemplateMetadata = &v1beta1.PatchPodTemplateMetadata{
|
||||
Annotations: map[string]string{},
|
||||
Labels: map[string]string{},
|
||||
}
|
||||
for k, v := range srcSpec.ReleasePlan.PatchPodTemplateMetadata.Annotations {
|
||||
obj.Spec.ReleasePlan.PatchPodTemplateMetadata.Annotations[k] = v
|
||||
}
|
||||
for k, v := range srcSpec.ReleasePlan.PatchPodTemplateMetadata.Labels {
|
||||
obj.Spec.ReleasePlan.PatchPodTemplateMetadata.Labels[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
if strings.EqualFold(src.Annotations[RolloutStyleAnnotation], string(PartitionRollingStyle)) {
|
||||
obj.Spec.ReleasePlan.RollingStyle = v1beta1.PartitionRollingStyle
|
||||
}
|
||||
if strings.EqualFold(src.Annotations[RolloutStyleAnnotation], string(CanaryRollingStyle)) {
|
||||
obj.Spec.ReleasePlan.RollingStyle = v1beta1.CanaryRollingStyle
|
||||
}
|
||||
if strings.EqualFold(src.Annotations[RolloutStyleAnnotation], string(BlueGreenRollingStyle)) {
|
||||
obj.Spec.ReleasePlan.RollingStyle = v1beta1.BlueGreenRollingStyle
|
||||
}
|
||||
|
||||
obj.Spec.ReleasePlan.EnableExtraWorkloadForCanary = srcSpec.ReleasePlan.EnableExtraWorkloadForCanary
|
||||
|
||||
// status
|
||||
obj.Status = v1beta1.BatchReleaseStatus{
|
||||
StableRevision: src.Status.StableRevision,
|
||||
UpdateRevision: src.Status.UpdateRevision,
|
||||
ObservedGeneration: src.Status.ObservedGeneration,
|
||||
ObservedRolloutID: src.Status.ObservedRolloutID,
|
||||
ObservedWorkloadReplicas: src.Status.ObservedWorkloadReplicas,
|
||||
ObservedReleasePlanHash: src.Status.ObservedReleasePlanHash,
|
||||
CollisionCount: src.Status.CollisionCount,
|
||||
Phase: v1beta1.RolloutPhase(src.Status.Phase),
|
||||
}
|
||||
for _, cond := range src.Status.Conditions {
|
||||
o := v1beta1.RolloutCondition{
|
||||
Type: v1beta1.RolloutConditionType(cond.Type),
|
||||
Status: cond.Status,
|
||||
LastUpdateTime: cond.LastUpdateTime,
|
||||
LastTransitionTime: cond.LastTransitionTime,
|
||||
Reason: cond.Reason,
|
||||
Message: cond.Message,
|
||||
}
|
||||
obj.Status.Conditions = append(obj.Status.Conditions, o)
|
||||
}
|
||||
obj.Status.CanaryStatus = v1beta1.BatchReleaseCanaryStatus{
|
||||
CurrentBatchState: v1beta1.BatchReleaseBatchStateType(src.Status.CanaryStatus.CurrentBatchState),
|
||||
CurrentBatch: src.Status.CanaryStatus.CurrentBatch,
|
||||
BatchReadyTime: src.Status.CanaryStatus.BatchReadyTime,
|
||||
UpdatedReplicas: src.Status.CanaryStatus.UpdatedReplicas,
|
||||
UpdatedReadyReplicas: src.Status.CanaryStatus.UpdatedReadyReplicas,
|
||||
NoNeedUpdateReplicas: src.Status.CanaryStatus.NoNeedUpdateReplicas,
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("unsupported type %v", t)
|
||||
}
|
||||
}
|
||||
|
||||
func (dst *BatchRelease) ConvertFrom(src conversion.Hub) error {
|
||||
switch t := src.(type) {
|
||||
case *v1beta1.BatchRelease:
|
||||
srcV1beta1 := src.(*v1beta1.BatchRelease)
|
||||
dst.ObjectMeta = srcV1beta1.ObjectMeta
|
||||
dst.Spec = BatchReleaseSpec{}
|
||||
srcSpec := srcV1beta1.Spec
|
||||
dst.Spec.TargetRef.WorkloadRef = &WorkloadRef{
|
||||
APIVersion: srcSpec.WorkloadRef.APIVersion,
|
||||
Kind: srcSpec.WorkloadRef.Kind,
|
||||
Name: srcSpec.WorkloadRef.Name,
|
||||
}
|
||||
dst.Spec.ReleasePlan = ReleasePlan{
|
||||
BatchPartition: srcSpec.ReleasePlan.BatchPartition,
|
||||
RolloutID: srcSpec.ReleasePlan.RolloutID,
|
||||
FailureThreshold: srcSpec.ReleasePlan.FailureThreshold,
|
||||
FinalizingPolicy: FinalizingPolicyType(srcSpec.ReleasePlan.FinalizingPolicy),
|
||||
}
|
||||
for _, batch := range srcSpec.ReleasePlan.Batches {
|
||||
obj := ReleaseBatch{
|
||||
CanaryReplicas: batch.CanaryReplicas,
|
||||
}
|
||||
dst.Spec.ReleasePlan.Batches = append(dst.Spec.ReleasePlan.Batches, obj)
|
||||
}
|
||||
if srcSpec.ReleasePlan.PatchPodTemplateMetadata != nil {
|
||||
dst.Spec.ReleasePlan.PatchPodTemplateMetadata = &PatchPodTemplateMetadata{
|
||||
Annotations: map[string]string{},
|
||||
Labels: map[string]string{},
|
||||
}
|
||||
for k, v := range srcSpec.ReleasePlan.PatchPodTemplateMetadata.Annotations {
|
||||
dst.Spec.ReleasePlan.PatchPodTemplateMetadata.Annotations[k] = v
|
||||
}
|
||||
for k, v := range srcSpec.ReleasePlan.PatchPodTemplateMetadata.Labels {
|
||||
dst.Spec.ReleasePlan.PatchPodTemplateMetadata.Labels[k] = v
|
||||
}
|
||||
}
|
||||
if dst.Annotations == nil {
|
||||
dst.Annotations = map[string]string{}
|
||||
}
|
||||
dst.Annotations[RolloutStyleAnnotation] = strings.ToLower(string(srcV1beta1.Spec.ReleasePlan.RollingStyle))
|
||||
dst.Spec.ReleasePlan.RollingStyle = RollingStyleType(srcV1beta1.Spec.ReleasePlan.RollingStyle)
|
||||
dst.Spec.ReleasePlan.EnableExtraWorkloadForCanary = srcV1beta1.Spec.ReleasePlan.EnableExtraWorkloadForCanary
|
||||
|
||||
// status
|
||||
dst.Status = BatchReleaseStatus{
|
||||
StableRevision: srcV1beta1.Status.StableRevision,
|
||||
UpdateRevision: srcV1beta1.Status.UpdateRevision,
|
||||
ObservedGeneration: srcV1beta1.Status.ObservedGeneration,
|
||||
ObservedRolloutID: srcV1beta1.Status.ObservedRolloutID,
|
||||
ObservedWorkloadReplicas: srcV1beta1.Status.ObservedWorkloadReplicas,
|
||||
ObservedReleasePlanHash: srcV1beta1.Status.ObservedReleasePlanHash,
|
||||
CollisionCount: srcV1beta1.Status.CollisionCount,
|
||||
Phase: RolloutPhase(srcV1beta1.Status.Phase),
|
||||
}
|
||||
for _, cond := range srcV1beta1.Status.Conditions {
|
||||
obj := RolloutCondition{
|
||||
Type: RolloutConditionType(cond.Type),
|
||||
Status: cond.Status,
|
||||
LastUpdateTime: cond.LastUpdateTime,
|
||||
LastTransitionTime: cond.LastTransitionTime,
|
||||
Reason: cond.Reason,
|
||||
Message: cond.Message,
|
||||
}
|
||||
dst.Status.Conditions = append(dst.Status.Conditions, obj)
|
||||
}
|
||||
dst.Status.CanaryStatus = BatchReleaseCanaryStatus{
|
||||
CurrentBatchState: BatchReleaseBatchStateType(srcV1beta1.Status.CanaryStatus.CurrentBatchState),
|
||||
CurrentBatch: srcV1beta1.Status.CanaryStatus.CurrentBatch,
|
||||
BatchReadyTime: srcV1beta1.Status.CanaryStatus.BatchReadyTime,
|
||||
UpdatedReplicas: srcV1beta1.Status.CanaryStatus.UpdatedReplicas,
|
||||
UpdatedReadyReplicas: srcV1beta1.Status.CanaryStatus.UpdatedReadyReplicas,
|
||||
NoNeedUpdateReplicas: srcV1beta1.Status.CanaryStatus.NoNeedUpdateReplicas,
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("unsupported type %v", t)
|
||||
}
|
||||
}
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright 2023 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 v1alpha1
|
||||
|
||||
import (
|
||||
|
@ -43,6 +59,8 @@ const (
|
|||
PartitionRollingStyle RollingStyleType = "Partition"
|
||||
// CanaryRollingStyle means rolling in canary way, and will create a canary Deployment.
|
||||
CanaryRollingStyle RollingStyleType = "Canary"
|
||||
// BlueGreenRollingStyle means rolling in blue-green way, and will NOT create a canary Deployment.
|
||||
BlueGreenRollingStyle RollingStyleType = "BlueGreen"
|
||||
)
|
||||
|
||||
// DeploymentExtraStatus is extra status field for Advanced Deployment
|
||||
|
@ -58,7 +76,7 @@ type DeploymentExtraStatus struct {
|
|||
}
|
||||
|
||||
func SetDefaultDeploymentStrategy(strategy *DeploymentStrategy) {
|
||||
if strategy.RollingStyle == CanaryRollingStyle {
|
||||
if strategy.RollingStyle != PartitionRollingStyle {
|
||||
return
|
||||
}
|
||||
if strategy.RollingUpdate == nil {
|
||||
|
|
|
@ -20,7 +20,7 @@ import (
|
|||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
|
||||
gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1"
|
||||
)
|
||||
|
||||
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
|
||||
|
@ -121,6 +121,8 @@ type CanaryStrategy struct {
|
|||
// only support for canary deployment
|
||||
// +optional
|
||||
PatchPodTemplateMetadata *PatchPodTemplateMetadata `json:"patchPodTemplateMetadata,omitempty"`
|
||||
// canary service will not be generated if DisableGenerateCanaryService is true
|
||||
DisableGenerateCanaryService bool `json:"disableGenerateCanaryService,omitempty"`
|
||||
}
|
||||
|
||||
type PatchPodTemplateMetadata struct {
|
||||
|
@ -146,7 +148,7 @@ type HttpRouteMatch struct {
|
|||
// ANDed together, meaning, a request must match all the specified headers
|
||||
// to select the route.
|
||||
// +kubebuilder:validation:MaxItems=16
|
||||
Headers []gatewayv1alpha2.HTTPHeaderMatch `json:"headers,omitempty"`
|
||||
Headers []gatewayv1beta1.HTTPHeaderMatch `json:"headers,omitempty"`
|
||||
}
|
||||
|
||||
// RolloutPause defines a pause stage for a rollout
|
||||
|
@ -169,8 +171,6 @@ type RolloutStatus struct {
|
|||
// Conditions a list of conditions a rollout can have.
|
||||
// +optional
|
||||
Conditions []RolloutCondition `json:"conditions,omitempty"`
|
||||
// +optional
|
||||
//BlueGreenStatus *BlueGreenStatus `json:"blueGreenStatus,omitempty"`
|
||||
// Phase is the rollout phase.
|
||||
Phase RolloutPhase `json:"phase,omitempty"`
|
||||
// Message provides details on why the rollout is in its current phase
|
||||
|
@ -240,16 +240,28 @@ type CanaryStatus struct {
|
|||
CanaryReplicas int32 `json:"canaryReplicas"`
|
||||
// CanaryReadyReplicas the numbers of ready canary revision pods
|
||||
CanaryReadyReplicas int32 `json:"canaryReadyReplicas"`
|
||||
// CurrentStepIndex defines the current step of the rollout is on. If the current step index is null, the
|
||||
// controller will execute the rollout.
|
||||
// NextStepIndex defines the next step of the rollout is on.
|
||||
// In normal case, NextStepIndex is equal to CurrentStepIndex + 1
|
||||
// If the current step is the last step, NextStepIndex is equal to -1
|
||||
// Before the release, NextStepIndex is also equal to -1
|
||||
// 0 is not used and won't appear in any case
|
||||
// It is allowed to patch NextStepIndex by design,
|
||||
// e.g. if CurrentStepIndex is 2, user can patch NextStepIndex to 3 (if exists) to
|
||||
// achieve batch jump, or patch NextStepIndex to 1 to implement a re-execution of step 1
|
||||
// Patching it with a non-positive value is meaningless, which will be corrected
|
||||
// in the next reconciliation
|
||||
// achieve batch jump, or patch NextStepIndex to 1 to implement a re-execution of step 1
|
||||
NextStepIndex int32 `json:"nextStepIndex"`
|
||||
// +optional
|
||||
CurrentStepIndex int32 `json:"currentStepIndex"`
|
||||
CurrentStepState CanaryStepState `json:"currentStepState"`
|
||||
Message string `json:"message,omitempty"`
|
||||
LastUpdateTime *metav1.Time `json:"lastUpdateTime,omitempty"`
|
||||
CurrentStepIndex int32 `json:"currentStepIndex"`
|
||||
CurrentStepState CanaryStepState `json:"currentStepState"`
|
||||
Message string `json:"message,omitempty"`
|
||||
LastUpdateTime *metav1.Time `json:"lastUpdateTime,omitempty"`
|
||||
FinalisingStep FinalizeStateType `json:"finalisingStep"`
|
||||
}
|
||||
|
||||
type CanaryStepState string
|
||||
type FinalizeStateType string
|
||||
|
||||
const (
|
||||
CanaryStepStateUpgrade CanaryStepState = "StepUpgrade"
|
||||
|
|
|
@ -18,7 +18,7 @@ package v1alpha1
|
|||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
|
||||
gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -30,12 +30,15 @@ type TrafficRoutingRef struct {
|
|||
// Service holds the name of a service which selects pods with stable version and don't select any pods with canary version.
|
||||
Service string `json:"service"`
|
||||
// Optional duration in seconds the traffic provider(e.g. nginx ingress controller) consumes the service, ingress configuration changes gracefully.
|
||||
// +kubebuilder:default=3
|
||||
GracePeriodSeconds int32 `json:"gracePeriodSeconds,omitempty"`
|
||||
// Ingress holds Ingress specific configuration to route traffic, e.g. Nginx, Alb.
|
||||
Ingress *IngressTrafficRouting `json:"ingress,omitempty"`
|
||||
// Gateway holds Gateway specific configuration to route traffic
|
||||
// Gateway configuration only supports >= v0.4.0 (v1alpha2).
|
||||
Gateway *GatewayTrafficRouting `json:"gateway,omitempty"`
|
||||
// CustomNetworkRefs hold a list of custom providers to route traffic
|
||||
CustomNetworkRefs []CustomNetworkRef `json:"customNetworkRefs,omitempty"`
|
||||
}
|
||||
|
||||
// IngressTrafficRouting configuration for ingress controller to control traffic routing
|
||||
|
@ -87,7 +90,7 @@ type TrafficRoutingStrategy struct {
|
|||
// my-header: bar
|
||||
//
|
||||
// +optional
|
||||
RequestHeaderModifier *gatewayv1alpha2.HTTPRequestHeaderFilter `json:"requestHeaderModifier,omitempty"`
|
||||
RequestHeaderModifier *gatewayv1beta1.HTTPHeaderFilter `json:"requestHeaderModifier,omitempty"`
|
||||
// Matches define conditions used for matching the incoming HTTP requests to canary service.
|
||||
// Each match is independent, i.e. this rule will be matched if **any** one of the matches is satisfied.
|
||||
// If Gateway API, current only support one match.
|
||||
|
@ -149,6 +152,12 @@ type TrafficRoutingList struct {
|
|||
Items []TrafficRouting `json:"items"`
|
||||
}
|
||||
|
||||
type CustomNetworkRef struct {
|
||||
APIVersion string `json:"apiVersion"`
|
||||
Kind string `json:"kind"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
SchemeBuilder.Register(&TrafficRouting{}, &TrafficRoutingList{})
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
Copyright 2023 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.
|
||||
|
@ -25,7 +24,7 @@ import (
|
|||
"k8s.io/api/apps/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"sigs.k8s.io/gateway-api/apis/v1alpha2"
|
||||
"sigs.k8s.io/gateway-api/apis/v1beta1"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
|
@ -256,6 +255,21 @@ func (in *CanaryStrategy) DeepCopy() *CanaryStrategy {
|
|||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CustomNetworkRef) DeepCopyInto(out *CustomNetworkRef) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomNetworkRef.
|
||||
func (in *CustomNetworkRef) DeepCopy() *CustomNetworkRef {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomNetworkRef)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *DeploymentExtraStatus) DeepCopyInto(out *DeploymentExtraStatus) {
|
||||
*out = *in
|
||||
|
@ -333,7 +347,7 @@ func (in *HttpRouteMatch) DeepCopyInto(out *HttpRouteMatch) {
|
|||
*out = *in
|
||||
if in.Headers != nil {
|
||||
in, out := &in.Headers, &out.Headers
|
||||
*out = make([]v1alpha2.HTTPHeaderMatch, len(*in))
|
||||
*out = make([]v1beta1.HTTPHeaderMatch, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
|
@ -901,6 +915,11 @@ func (in *TrafficRoutingRef) DeepCopyInto(out *TrafficRoutingRef) {
|
|||
*out = new(GatewayTrafficRouting)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.CustomNetworkRefs != nil {
|
||||
in, out := &in.CustomNetworkRefs, &out.CustomNetworkRefs
|
||||
*out = make([]CustomNetworkRef, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficRoutingRef.
|
||||
|
@ -961,7 +980,7 @@ func (in *TrafficRoutingStrategy) DeepCopyInto(out *TrafficRoutingStrategy) {
|
|||
}
|
||||
if in.RequestHeaderModifier != nil {
|
||||
in, out := &in.RequestHeaderModifier, &out.RequestHeaderModifier
|
||||
*out = new(v1alpha2.HTTPRequestHeaderFilter)
|
||||
*out = new(v1beta1.HTTPHeaderFilter)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.Matches != nil {
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
Copyright 2023 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 v1beta1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
)
|
||||
|
||||
// ReleasePlan fines the details of the release plan
|
||||
type ReleasePlan struct {
|
||||
// Batches is the details on each batch of the ReleasePlan.
|
||||
//Users can specify their batch plan in this field, such as:
|
||||
// batches:
|
||||
// - canaryReplicas: 1 # batches 0
|
||||
// - canaryReplicas: 2 # batches 1
|
||||
// - canaryReplicas: 5 # batches 2
|
||||
// Not that these canaryReplicas should be a non-decreasing sequence.
|
||||
// +optional
|
||||
Batches []ReleaseBatch `json:"batches"`
|
||||
// All pods in the batches up to the batchPartition (included) will have
|
||||
// the target resource specification while the rest still is the stable revision.
|
||||
// This is designed for the operators to manually rollout.
|
||||
// Default is nil, which means no partition and will release all batches.
|
||||
// BatchPartition start from 0.
|
||||
// +optional
|
||||
BatchPartition *int32 `json:"batchPartition,omitempty"`
|
||||
// RolloutID indicates an id for each rollout progress
|
||||
RolloutID string `json:"rolloutID,omitempty"`
|
||||
// FailureThreshold indicates how many failed pods can be tolerated in all upgraded pods.
|
||||
// Only when FailureThreshold are satisfied, Rollout can enter ready state.
|
||||
// If FailureThreshold is nil, Rollout will use the MaxUnavailable of workload as its
|
||||
// FailureThreshold.
|
||||
// Defaults to nil.
|
||||
FailureThreshold *intstr.IntOrString `json:"failureThreshold,omitempty"`
|
||||
// FinalizingPolicy define the behavior of controller when phase enter Finalizing
|
||||
// Defaults to "Immediate"
|
||||
FinalizingPolicy FinalizingPolicyType `json:"finalizingPolicy,omitempty"`
|
||||
// PatchPodTemplateMetadata indicates patch configuration(e.g. labels, annotations) to the canary deployment podTemplateSpec.metadata
|
||||
// only support for canary deployment
|
||||
// +optional
|
||||
PatchPodTemplateMetadata *PatchPodTemplateMetadata `json:"patchPodTemplateMetadata,omitempty"`
|
||||
// RollingStyle can be "Canary", "Partiton" or "BlueGreen"
|
||||
RollingStyle RollingStyleType `json:"rollingStyle,omitempty"`
|
||||
// EnableExtraWorkloadForCanary indicates whether to create extra workload for canary
|
||||
// True corresponds to RollingStyle "Canary".
|
||||
// False corresponds to RollingStyle "Partiton".
|
||||
// Ignored in BlueGreen-style.
|
||||
// This field is about to deprecate, use RollingStyle instead.
|
||||
// If both of them are set, controller will only consider this
|
||||
// filed when RollingStyle is empty
|
||||
EnableExtraWorkloadForCanary bool `json:"enableExtraWorkloadForCanary"`
|
||||
}
|
||||
|
||||
type FinalizingPolicyType string
|
||||
|
||||
const (
|
||||
// WaitResumeFinalizingPolicyType will wait workload to be resumed, which means
|
||||
// controller will be hold at Finalizing phase until all pods of workload is upgraded.
|
||||
// WaitResumeFinalizingPolicyType only works in canary-style BatchRelease controller.
|
||||
WaitResumeFinalizingPolicyType FinalizingPolicyType = "WaitResume"
|
||||
// ImmediateFinalizingPolicyType will not to wait workload to be resumed.
|
||||
ImmediateFinalizingPolicyType FinalizingPolicyType = "Immediate"
|
||||
)
|
||||
|
||||
// ReleaseBatch is used to describe how each batch release should be
|
||||
type ReleaseBatch struct {
|
||||
// CanaryReplicas is the number of upgraded pods that should have in this batch.
|
||||
// it can be an absolute number (ex: 5) or a percentage of workload replicas.
|
||||
// batches[i].canaryReplicas should less than or equal to batches[j].canaryReplicas if i < j.
|
||||
CanaryReplicas intstr.IntOrString `json:"canaryReplicas"`
|
||||
}
|
||||
|
||||
// BatchReleaseStatus defines the observed state of a release plan
|
||||
type BatchReleaseStatus struct {
|
||||
// Conditions represents the observed process state of each phase during executing the release plan.
|
||||
Conditions []RolloutCondition `json:"conditions,omitempty"`
|
||||
// CanaryStatus describes the state of the canary rollout.
|
||||
CanaryStatus BatchReleaseCanaryStatus `json:"canaryStatus,omitempty"`
|
||||
// StableRevision is the pod-template-hash of stable revision pod template.
|
||||
StableRevision string `json:"stableRevision,omitempty"`
|
||||
// UpdateRevision is the pod-template-hash of update revision pod template.
|
||||
UpdateRevision string `json:"updateRevision,omitempty"`
|
||||
// ObservedGeneration is the most recent generation observed for this BatchRelease.
|
||||
// It corresponds to this BatchRelease's generation, which is updated on mutation
|
||||
// by the API Server, and only if BatchRelease Spec was changed, its generation will increase 1.
|
||||
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
|
||||
// ObservedRolloutID is the most recent rollout-id observed for this BatchRelease.
|
||||
// If RolloutID was changed, we will restart to roll out from batch 0,
|
||||
// to ensure the batch-id and rollout-id labels of Pods are correct.
|
||||
ObservedRolloutID string `json:"observedRolloutID,omitempty"`
|
||||
// ObservedWorkloadReplicas is observed replicas of target referenced workload.
|
||||
// This field is designed to deal with scaling event during rollout, if this field changed,
|
||||
// it means that the workload is scaling during rollout.
|
||||
ObservedWorkloadReplicas int32 `json:"observedWorkloadReplicas,omitempty"`
|
||||
// Count of hash collisions for creating canary Deployment. The controller uses this
|
||||
// field as a collision avoidance mechanism when it needs to create the name for the
|
||||
// newest canary Deployment.
|
||||
// +optional
|
||||
CollisionCount *int32 `json:"collisionCount,omitempty"`
|
||||
// ObservedReleasePlanHash is a hash code of observed itself spec.releasePlan.
|
||||
ObservedReleasePlanHash string `json:"observedReleasePlanHash,omitempty"`
|
||||
// Phase is the release plan phase, which indicates the current state of release
|
||||
// plan state machine in BatchRelease controller.
|
||||
Phase RolloutPhase `json:"phase,omitempty"`
|
||||
// Message provides details on why the rollout is in its current phase
|
||||
Message string `json:"message,omitempty"`
|
||||
}
|
||||
|
||||
type BatchReleaseCanaryStatus struct {
|
||||
// CurrentBatchState indicates the release state of the current batch.
|
||||
CurrentBatchState BatchReleaseBatchStateType `json:"batchState,omitempty"`
|
||||
// The current batch the rollout is working on/blocked, it starts from 0
|
||||
CurrentBatch int32 `json:"currentBatch"`
|
||||
// BatchReadyTime is the ready timestamp of the current batch or the last batch.
|
||||
// This field is updated once a batch ready, and the batches[x].pausedSeconds
|
||||
// relies on this field to calculate the real-time duration.
|
||||
BatchReadyTime *metav1.Time `json:"batchReadyTime,omitempty"`
|
||||
// UpdatedReplicas is the number of upgraded Pods.
|
||||
UpdatedReplicas int32 `json:"updatedReplicas,omitempty"`
|
||||
// UpdatedReadyReplicas is the number upgraded Pods that have a Ready Condition.
|
||||
UpdatedReadyReplicas int32 `json:"updatedReadyReplicas,omitempty"`
|
||||
// the number of pods that no need to rollback in rollback scene.
|
||||
NoNeedUpdateReplicas *int32 `json:"noNeedUpdateReplicas,omitempty"`
|
||||
}
|
||||
|
||||
type BatchReleaseBatchStateType string
|
||||
|
||||
const (
|
||||
// UpgradingBatchState indicates that current batch is at upgrading pod state
|
||||
UpgradingBatchState BatchReleaseBatchStateType = "Upgrading"
|
||||
// VerifyingBatchState indicates that current batch is at verifying whether it's ready state
|
||||
VerifyingBatchState BatchReleaseBatchStateType = "Verifying"
|
||||
// ReadyBatchState indicates that current batch is at batch ready state
|
||||
ReadyBatchState BatchReleaseBatchStateType = "Ready"
|
||||
)
|
||||
|
||||
const (
|
||||
// RolloutPhasePreparing indicates a rollout is preparing for next progress.
|
||||
RolloutPhasePreparing RolloutPhase = "Preparing"
|
||||
// RolloutPhaseFinalizing indicates a rollout is finalizing
|
||||
RolloutPhaseFinalizing RolloutPhase = "Finalizing"
|
||||
// RolloutPhaseCompleted indicates a rollout is completed/canceled/terminated
|
||||
RolloutPhaseCompleted RolloutPhase = "Completed"
|
||||
)
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
Copyright 2023 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 v1beta1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// +genclient
|
||||
// +k8s:openapi-gen=true
|
||||
// +kubebuilder:object:root=true
|
||||
// +kubebuilder:subresource:status
|
||||
// +kubebuilder:storageversion
|
||||
// +kubebuilder:printcolumn:name="KIND",type=string,JSONPath=`.spec.targetReference.workloadRef.kind`
|
||||
// +kubebuilder:printcolumn:name="PHASE",type=string,JSONPath=`.status.phase`
|
||||
// +kubebuilder:printcolumn:name="BATCH",type=integer,JSONPath=`.status.canaryStatus.currentBatch`
|
||||
// +kubebuilder:printcolumn:name="BATCH-STATE",type=string,JSONPath=`.status.canaryStatus.batchState`
|
||||
// +kubebuilder:printcolumn:name="AGE",type=date,JSONPath=".metadata.creationTimestamp"
|
||||
|
||||
type BatchRelease struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
Spec BatchReleaseSpec `json:"spec,omitempty"`
|
||||
Status BatchReleaseStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// BatchReleaseSpec defines how to describe an update between different compRevision
|
||||
type BatchReleaseSpec struct {
|
||||
// WorkloadRef contains enough information to let you identify a workload for Rollout
|
||||
// Batch release of the bypass
|
||||
WorkloadRef ObjectRef `json:"workloadRef,omitempty"`
|
||||
// ReleasePlan is the details on how to rollout the resources
|
||||
ReleasePlan ReleasePlan `json:"releasePlan"`
|
||||
}
|
||||
|
||||
// BatchReleaseList contains a list of BatchRelease
|
||||
// +kubebuilder:object:root=true
|
||||
type BatchReleaseList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata,omitempty"`
|
||||
Items []BatchRelease `json:"items"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
SchemeBuilder.Register(&BatchRelease{}, &BatchReleaseList{})
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
Copyright 2023 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 v1beta1
|
||||
|
||||
func (*Rollout) Hub() {}
|
||||
|
||||
func (*BatchRelease) Hub() {}
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
Copyright 2023 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 v1beta1
|
||||
|
||||
import (
|
||||
apps "k8s.io/api/apps/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
)
|
||||
|
||||
const (
|
||||
// DeploymentStrategyAnnotation is annotation for deployment,
|
||||
// which is strategy fields of Advanced Deployment.
|
||||
DeploymentStrategyAnnotation = "rollouts.kruise.io/deployment-strategy"
|
||||
|
||||
// DeploymentExtraStatusAnnotation is annotation for deployment,
|
||||
// which is extra status field of Advanced Deployment.
|
||||
DeploymentExtraStatusAnnotation = "rollouts.kruise.io/deployment-extra-status"
|
||||
|
||||
// DeploymentStableRevisionLabel is label for deployment,
|
||||
// which record the stable revision during the current rolling process.
|
||||
DeploymentStableRevisionLabel = "rollouts.kruise.io/stable-revision"
|
||||
|
||||
// AdvancedDeploymentControlLabel is label for deployment,
|
||||
// which labels whether the deployment is controlled by advanced-deployment-controller.
|
||||
AdvancedDeploymentControlLabel = "rollouts.kruise.io/controlled-by-advanced-deployment-controller"
|
||||
|
||||
// OriginalDeploymentStrategyAnnotation is annotation for workload in BlueGreen Release,
|
||||
// it will store the original setting of the workload, which will be used to restore the workload
|
||||
OriginalDeploymentStrategyAnnotation = "rollouts.kruise.io/original-deployment-strategy"
|
||||
|
||||
// MaxProgressSeconds is the value we set for ProgressDeadlineSeconds
|
||||
// MaxReadySeconds is the value we set for MinReadySeconds, which is one less than ProgressDeadlineSeconds
|
||||
// MaxInt32: 2147483647, ≈ 68 years
|
||||
MaxProgressSeconds = 1<<31 - 1
|
||||
MaxReadySeconds = MaxProgressSeconds - 1
|
||||
)
|
||||
|
||||
// DeploymentStrategy is strategy field for Advanced Deployment
|
||||
type DeploymentStrategy struct {
|
||||
// RollingStyle define the behavior of rolling for deployment.
|
||||
RollingStyle RollingStyleType `json:"rollingStyle,omitempty"`
|
||||
// original deployment strategy rolling update fields
|
||||
RollingUpdate *apps.RollingUpdateDeployment `json:"rollingUpdate,omitempty"`
|
||||
// Paused = true will block the upgrade of Pods
|
||||
Paused bool `json:"paused,omitempty"`
|
||||
// Partition describe how many Pods should be updated during rollout.
|
||||
// We use this field to implement partition-style rolling update.
|
||||
Partition intstr.IntOrString `json:"partition,omitempty"`
|
||||
}
|
||||
|
||||
type RollingStyleType string
|
||||
|
||||
const (
|
||||
// PartitionRollingStyle means rolling in batches just like CloneSet, and will NOT create any extra Deployment;
|
||||
PartitionRollingStyle RollingStyleType = "Partition"
|
||||
// CanaryRollingStyle means rolling in canary way, and will create a canary Deployment.
|
||||
CanaryRollingStyle RollingStyleType = "Canary"
|
||||
// BlueGreenRollingStyle means rolling in blue-green way, and will NOT create a extra Deployment.
|
||||
BlueGreenRollingStyle RollingStyleType = "BlueGreen"
|
||||
)
|
||||
|
||||
// DeploymentExtraStatus is extra status field for Advanced Deployment
|
||||
type DeploymentExtraStatus struct {
|
||||
// UpdatedReadyReplicas the number of pods that has been updated and ready.
|
||||
UpdatedReadyReplicas int32 `json:"updatedReadyReplicas,omitempty"`
|
||||
// ExpectedUpdatedReplicas is an absolute number calculated based on Partition
|
||||
// and Deployment.Spec.Replicas, means how many pods are expected be updated under
|
||||
// current strategy.
|
||||
// This field is designed to avoid users to fall into the details of algorithm
|
||||
// for Partition calculation.
|
||||
ExpectedUpdatedReplicas int32 `json:"expectedUpdatedReplicas,omitempty"`
|
||||
}
|
||||
|
||||
func SetDefaultDeploymentStrategy(strategy *DeploymentStrategy) {
|
||||
if strategy.RollingStyle != PartitionRollingStyle {
|
||||
return
|
||||
}
|
||||
if strategy.RollingUpdate == nil {
|
||||
strategy.RollingUpdate = &apps.RollingUpdateDeployment{}
|
||||
}
|
||||
if strategy.RollingUpdate.MaxUnavailable == nil {
|
||||
// Set MaxUnavailable as 25% by default
|
||||
maxUnavailable := intstr.FromString("25%")
|
||||
strategy.RollingUpdate.MaxUnavailable = &maxUnavailable
|
||||
}
|
||||
if strategy.RollingUpdate.MaxSurge == nil {
|
||||
// Set MaxSurge as 25% by default
|
||||
maxSurge := intstr.FromString("25%")
|
||||
strategy.RollingUpdate.MaxUnavailable = &maxSurge
|
||||
}
|
||||
|
||||
// Cannot allow maxSurge==0 && MaxUnavailable==0, otherwise, no pod can be updated when rolling update.
|
||||
maxSurge, _ := intstr.GetScaledValueFromIntOrPercent(strategy.RollingUpdate.MaxSurge, 100, true)
|
||||
maxUnavailable, _ := intstr.GetScaledValueFromIntOrPercent(strategy.RollingUpdate.MaxUnavailable, 100, true)
|
||||
if maxSurge == 0 && maxUnavailable == 0 {
|
||||
strategy.RollingUpdate = &apps.RollingUpdateDeployment{
|
||||
MaxSurge: &intstr.IntOrString{Type: intstr.Int, IntVal: 0},
|
||||
MaxUnavailable: &intstr.IntOrString{Type: intstr.Int, IntVal: 1},
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
Copyright 2023 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 v1beta1 contains API Schema definitions for the apps v1beta1 API group
|
||||
// +kubebuilder:object:generate=true
|
||||
// +groupName=rollouts.kruise.io
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"sigs.k8s.io/controller-runtime/pkg/scheme"
|
||||
)
|
||||
|
||||
var (
|
||||
// GroupVersion is group version used to register these objects
|
||||
GroupVersion = schema.GroupVersion{Group: "rollouts.kruise.io", Version: "v1beta1"}
|
||||
|
||||
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
|
||||
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
|
||||
|
||||
// AddToScheme adds the types in this group-version to the given scheme.
|
||||
AddToScheme = SchemeBuilder.AddToScheme
|
||||
|
||||
SchemeGroupVersion = GroupVersion
|
||||
)
|
||||
|
||||
// Resource is required by pkg/client/listers/...
|
||||
func Resource(resource string) schema.GroupResource {
|
||||
return SchemeGroupVersion.WithResource(resource).GroupResource()
|
||||
}
|
|
@ -0,0 +1,622 @@
|
|||
/*
|
||||
Copyright 2023 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 v1beta1
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
apps "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1"
|
||||
)
|
||||
|
||||
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
|
||||
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
|
||||
|
||||
const (
|
||||
// RolloutIDLabel is set to workload labels.
|
||||
// RolloutIDLabel is designed to distinguish each workload revision publications.
|
||||
// The value of RolloutIDLabel corresponds Rollout.Spec.RolloutID.
|
||||
RolloutIDLabel = "rollouts.kruise.io/rollout-id"
|
||||
|
||||
// RolloutBatchIDLabel is patched in pod labels.
|
||||
// RolloutBatchIDLabel is the label key of batch id that will be patched to pods during rollout.
|
||||
// Only when RolloutIDLabel is set, RolloutBatchIDLabel will be patched.
|
||||
// Users can use RolloutIDLabel and RolloutBatchIDLabel to select the pods that are upgraded in some certain batch and release.
|
||||
RolloutBatchIDLabel = "rollouts.kruise.io/rollout-batch-id"
|
||||
|
||||
// RollbackInBatchAnnotation is set to rollout annotations.
|
||||
// RollbackInBatchAnnotation allow use disable quick rollback, and will roll back in batch style.
|
||||
RollbackInBatchAnnotation = "rollouts.kruise.io/rollback-in-batch"
|
||||
)
|
||||
|
||||
// RolloutSpec defines the desired state of Rollout
|
||||
type RolloutSpec struct {
|
||||
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
|
||||
// Important: Run "make" to regenerate code after modifying this file
|
||||
// WorkloadRef contains enough information to let you identify a workload for Rollout
|
||||
// Batch release of the bypass
|
||||
WorkloadRef ObjectRef `json:"workloadRef"`
|
||||
// rollout strategy
|
||||
Strategy RolloutStrategy `json:"strategy"`
|
||||
// if a rollout disabled, then the rollout would not watch changes of workload
|
||||
//+kubebuilder:validation:Optional
|
||||
//+kubebuilder:default=false
|
||||
Disabled bool `json:"disabled"`
|
||||
}
|
||||
|
||||
// ObjectRef holds a references to the Kubernetes object
|
||||
type ObjectRef struct {
|
||||
// API Version of the referent
|
||||
APIVersion string `json:"apiVersion"`
|
||||
// Kind of the referent
|
||||
Kind string `json:"kind"`
|
||||
// Name of the referent
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// RolloutStrategy defines strategy to apply during next rollout
|
||||
type RolloutStrategy struct {
|
||||
// Paused indicates that the Rollout is paused.
|
||||
// Default value is false
|
||||
Paused bool `json:"paused,omitempty"`
|
||||
// +optional
|
||||
Canary *CanaryStrategy `json:"canary,omitempty"`
|
||||
// +optional
|
||||
BlueGreen *BlueGreenStrategy `json:"blueGreen,omitempty" protobuf:"bytes,1,opt,name=blueGreen"`
|
||||
}
|
||||
|
||||
// Get the rolling style based on the strategy
|
||||
func (r *RolloutStrategy) GetRollingStyle() RollingStyleType {
|
||||
if r.BlueGreen != nil {
|
||||
return BlueGreenRollingStyle
|
||||
}
|
||||
//NOTE - even EnableExtraWorkloadForCanary is true, as long as it is not Deployment,
|
||||
//we won't do canary release. BatchRelease will treat it as Partiton release
|
||||
if r.Canary.EnableExtraWorkloadForCanary {
|
||||
return CanaryRollingStyle
|
||||
}
|
||||
return PartitionRollingStyle
|
||||
}
|
||||
|
||||
// using single field EnableExtraWorkloadForCanary to distinguish partition-style from canary-style
|
||||
// is not enough, for example, a v1alaph1 Rollout can be converted to v1beta1 Rollout
|
||||
// with EnableExtraWorkloadForCanary set as true, even the objectRef is cloneset (which doesn't support canary release)
|
||||
func IsRealPartition(rollout *Rollout) bool {
|
||||
if rollout.Spec.Strategy.IsEmptyRelease() {
|
||||
return false
|
||||
}
|
||||
estimation := rollout.Spec.Strategy.GetRollingStyle()
|
||||
if estimation == BlueGreenRollingStyle {
|
||||
return false
|
||||
}
|
||||
targetRef := rollout.Spec.WorkloadRef
|
||||
if targetRef.APIVersion == apps.SchemeGroupVersion.String() && targetRef.Kind == reflect.TypeOf(apps.Deployment{}).Name() &&
|
||||
estimation == CanaryRollingStyle {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// r.GetRollingStyle() == BlueGreenRollingStyle
|
||||
func (r *RolloutStrategy) IsBlueGreenRelease() bool {
|
||||
return r.GetRollingStyle() == BlueGreenRollingStyle
|
||||
}
|
||||
|
||||
// r.GetRollingStyle() == CanaryRollingStyle || r.GetRollingStyle() == PartitionRollingStyle
|
||||
func (r *RolloutStrategy) IsCanaryStragegy() bool {
|
||||
return r.GetRollingStyle() == CanaryRollingStyle || r.GetRollingStyle() == PartitionRollingStyle
|
||||
}
|
||||
|
||||
func (r *RolloutStrategy) IsEmptyRelease() bool {
|
||||
return r.BlueGreen == nil && r.Canary == nil
|
||||
}
|
||||
|
||||
// Get the steps based on the rolling style
|
||||
func (r *RolloutStrategy) GetSteps() []CanaryStep {
|
||||
switch r.GetRollingStyle() {
|
||||
case BlueGreenRollingStyle:
|
||||
return r.BlueGreen.Steps
|
||||
case CanaryRollingStyle, PartitionRollingStyle:
|
||||
return r.Canary.Steps
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Get the traffic routing based on the rolling style
|
||||
func (r *RolloutStrategy) GetTrafficRouting() []TrafficRoutingRef {
|
||||
switch r.GetRollingStyle() {
|
||||
case BlueGreenRollingStyle:
|
||||
return r.BlueGreen.TrafficRoutings
|
||||
case CanaryRollingStyle, PartitionRollingStyle:
|
||||
return r.Canary.TrafficRoutings
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Check if there are traffic routings
|
||||
func (r *RolloutStrategy) HasTrafficRoutings() bool {
|
||||
return len(r.GetTrafficRouting()) > 0
|
||||
}
|
||||
|
||||
// Check the value of DisableGenerateCanaryService
|
||||
func (r *RolloutStrategy) DisableGenerateCanaryService() bool {
|
||||
switch r.GetRollingStyle() {
|
||||
case BlueGreenRollingStyle:
|
||||
return r.BlueGreen.DisableGenerateCanaryService
|
||||
case CanaryRollingStyle, PartitionRollingStyle:
|
||||
return r.Canary.DisableGenerateCanaryService
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// BlueGreenStrategy defines parameters for Blue Green Release
|
||||
type BlueGreenStrategy struct {
|
||||
// Steps define the order of phases to execute release in batches(20%, 40%, 60%, 80%, 100%)
|
||||
// +kubebuilder:validation:MaxItems=50
|
||||
// +optional
|
||||
Steps []CanaryStep `json:"steps,omitempty"`
|
||||
// TrafficRoutings support ingress, gateway api and custom network resource(e.g. istio, apisix) to enable more fine-grained traffic routing
|
||||
// and current only support one TrafficRouting
|
||||
TrafficRoutings []TrafficRoutingRef `json:"trafficRoutings,omitempty"`
|
||||
// FailureThreshold indicates how many failed pods can be tolerated in all upgraded pods.
|
||||
// Only when FailureThreshold are satisfied, Rollout can enter ready state.
|
||||
// If FailureThreshold is nil, Rollout will use the MaxUnavailable of workload as its
|
||||
// FailureThreshold.
|
||||
// Defaults to nil.
|
||||
FailureThreshold *intstr.IntOrString `json:"failureThreshold,omitempty"`
|
||||
// TrafficRoutingRef is TrafficRouting's Name
|
||||
TrafficRoutingRef string `json:"trafficRoutingRef,omitempty"`
|
||||
// canary service will not be generated if DisableGenerateCanaryService is true
|
||||
DisableGenerateCanaryService bool `json:"disableGenerateCanaryService,omitempty"`
|
||||
}
|
||||
|
||||
// CanaryStrategy defines parameters for a Replica Based Canary
|
||||
type CanaryStrategy struct {
|
||||
// Steps define the order of phases to execute release in batches(20%, 40%, 60%, 80%, 100%)
|
||||
// +kubebuilder:validation:MaxItems=50
|
||||
// +optional
|
||||
Steps []CanaryStep `json:"steps,omitempty"`
|
||||
// TrafficRoutings support ingress, gateway api and custom network resource(e.g. istio, apisix) to enable more fine-grained traffic routing
|
||||
// and current only support one TrafficRouting
|
||||
TrafficRoutings []TrafficRoutingRef `json:"trafficRoutings,omitempty"`
|
||||
// FailureThreshold indicates how many failed pods can be tolerated in all upgraded pods.
|
||||
// Only when FailureThreshold are satisfied, Rollout can enter ready state.
|
||||
// If FailureThreshold is nil, Rollout will use the MaxUnavailable of workload as its
|
||||
// FailureThreshold.
|
||||
// Defaults to nil.
|
||||
FailureThreshold *intstr.IntOrString `json:"failureThreshold,omitempty"`
|
||||
// PatchPodTemplateMetadata indicates patch configuration(e.g. labels, annotations) to the canary deployment podTemplateSpec.metadata
|
||||
// only support for canary deployment
|
||||
// +optional
|
||||
PatchPodTemplateMetadata *PatchPodTemplateMetadata `json:"patchPodTemplateMetadata,omitempty"`
|
||||
// If true, then it will create new deployment for canary, such as: workload-demo-canary.
|
||||
// When user verifies that the canary version is ready, we will remove the canary deployment and release the deployment workload-demo in full.
|
||||
// Current only support k8s native deployment
|
||||
EnableExtraWorkloadForCanary bool `json:"enableExtraWorkloadForCanary,omitempty"`
|
||||
// TrafficRoutingRef is TrafficRouting's Name
|
||||
TrafficRoutingRef string `json:"trafficRoutingRef,omitempty"`
|
||||
// canary service will not be generated if DisableGenerateCanaryService is true
|
||||
DisableGenerateCanaryService bool `json:"disableGenerateCanaryService,omitempty"`
|
||||
}
|
||||
|
||||
type PatchPodTemplateMetadata struct {
|
||||
// annotations
|
||||
Annotations map[string]string `json:"annotations,omitempty"`
|
||||
// labels
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
}
|
||||
|
||||
// CanaryStep defines a step of a canary workload.
|
||||
type CanaryStep struct {
|
||||
TrafficRoutingStrategy `json:",inline"`
|
||||
// Replicas is the number of expected canary pods in this batch
|
||||
// it can be an absolute number (ex: 5) or a percentage of total pods.
|
||||
Replicas *intstr.IntOrString `json:"replicas,omitempty"`
|
||||
// Pause defines a pause stage for a rollout, manual or auto
|
||||
// +optional
|
||||
Pause RolloutPause `json:"pause,omitempty"`
|
||||
}
|
||||
|
||||
type TrafficRoutingStrategy struct {
|
||||
// Traffic indicate how many percentage of traffic the canary pods should receive
|
||||
// Value is of string type and is a percentage, e.g. 5%.
|
||||
// +optional
|
||||
Traffic *string `json:"traffic,omitempty"`
|
||||
// Set overwrites the request with the given header (name, value)
|
||||
// before the action.
|
||||
//
|
||||
// Input:
|
||||
// GET /foo HTTP/1.1
|
||||
// my-header: foo
|
||||
//
|
||||
// requestHeaderModifier:
|
||||
// set:
|
||||
// - name: "my-header"
|
||||
// value: "bar"
|
||||
//
|
||||
// Output:
|
||||
// GET /foo HTTP/1.1
|
||||
// my-header: bar
|
||||
//
|
||||
// +optional
|
||||
RequestHeaderModifier *gatewayv1beta1.HTTPHeaderFilter `json:"requestHeaderModifier,omitempty"`
|
||||
// Matches define conditions used for matching incoming HTTP requests to the canary service.
|
||||
// Each match is independent, i.e. this rule will be matched as long as **any** one of the matches is satisfied.
|
||||
//
|
||||
// It cannot support Traffic (weight-based routing) and Matches simultaneously, if both are configured.
|
||||
// In such cases, Matches takes precedence.
|
||||
// +kubebuilder:validation:MaxItems=16
|
||||
Matches []HttpRouteMatch `json:"matches,omitempty"`
|
||||
}
|
||||
|
||||
type HttpRouteMatch struct {
|
||||
// Path specifies a HTTP request path matcher.
|
||||
// Supported list:
|
||||
// - Istio: https://istio.io/latest/docs/reference/config/networking/virtual-service/#HTTPMatchRequest
|
||||
// - GatewayAPI: If path is defined, the whole HttpRouteMatch will be used as a standalone matcher
|
||||
//
|
||||
// +optional
|
||||
Path *gatewayv1beta1.HTTPPathMatch `json:"path,omitempty"`
|
||||
|
||||
// Headers specifies HTTP request header matchers. Multiple match values are
|
||||
// ANDed together, meaning, a request must match all the specified headers
|
||||
// to select the route.
|
||||
//
|
||||
// +listType=map
|
||||
// +listMapKey=name
|
||||
// +optional
|
||||
// +kubebuilder:validation:MaxItems=16
|
||||
Headers []gatewayv1beta1.HTTPHeaderMatch `json:"headers,omitempty"`
|
||||
|
||||
// QueryParams specifies HTTP query parameter matchers. Multiple match
|
||||
// values are ANDed together, meaning, a request must match all the
|
||||
// specified query parameters to select the route.
|
||||
// Supported list:
|
||||
// - Istio: https://istio.io/latest/docs/reference/config/networking/virtual-service/#HTTPMatchRequest
|
||||
// - MSE Ingress: https://help.aliyun.com/zh/ack/ack-managed-and-ack-dedicated/user-guide/annotations-supported-by-mse-ingress-gateways-1
|
||||
// Header/Cookie > QueryParams
|
||||
// - Gateway API
|
||||
//
|
||||
// +listType=map
|
||||
// +listMapKey=name
|
||||
// +optional
|
||||
// +kubebuilder:validation:MaxItems=16
|
||||
QueryParams []gatewayv1beta1.HTTPQueryParamMatch `json:"queryParams,omitempty"`
|
||||
}
|
||||
|
||||
// RolloutPause defines a pause stage for a rollout
|
||||
type RolloutPause struct {
|
||||
// Duration the amount of time to wait before moving to the next step.
|
||||
// +optional
|
||||
Duration *int32 `json:"duration,omitempty"`
|
||||
}
|
||||
|
||||
// RolloutStatus defines the observed state of Rollout
|
||||
type RolloutStatus struct {
|
||||
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
|
||||
// Important: Run "make" to regenerate code after modifying this file
|
||||
|
||||
// observedGeneration is the most recent generation observed for this Rollout.
|
||||
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
|
||||
// Canary describes the state of the canary rollout
|
||||
// +optional
|
||||
CanaryStatus *CanaryStatus `json:"canaryStatus,omitempty"`
|
||||
// BlueGreen describes the state of the blueGreen rollout
|
||||
// +optional
|
||||
BlueGreenStatus *BlueGreenStatus `json:"blueGreenStatus,omitempty"`
|
||||
// Conditions a list of conditions a rollout can have.
|
||||
// +optional
|
||||
Conditions []RolloutCondition `json:"conditions,omitempty"`
|
||||
// +optional
|
||||
//BlueGreenStatus *BlueGreenStatus `json:"blueGreenStatus,omitempty"`
|
||||
// Phase is the rollout phase.
|
||||
Phase RolloutPhase `json:"phase,omitempty"`
|
||||
// Message provides details on why the rollout is in its current phase
|
||||
Message string `json:"message,omitempty"`
|
||||
// These two values will be synchronized with the same fileds in CanaryStatus or BlueGreeenStatus
|
||||
// mainly used to provide info for kubectl get command
|
||||
CurrentStepIndex int32 `json:"currentStepIndex"`
|
||||
CurrentStepState CanaryStepState `json:"currentStepState"`
|
||||
}
|
||||
|
||||
// RolloutCondition describes the state of a rollout at a certain point.
|
||||
type RolloutCondition struct {
|
||||
// Type of rollout condition.
|
||||
Type RolloutConditionType `json:"type"`
|
||||
// Phase of the condition, one of True, False, Unknown.
|
||||
Status corev1.ConditionStatus `json:"status"`
|
||||
// The last time this condition was updated.
|
||||
LastUpdateTime metav1.Time `json:"lastUpdateTime,omitempty"`
|
||||
// Last time the condition transitioned from one status to another.
|
||||
LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"`
|
||||
// The reason for the condition's last transition.
|
||||
Reason string `json:"reason"`
|
||||
// A human readable message indicating details about the transition.
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// RolloutConditionType defines the conditions of Rollout
|
||||
type RolloutConditionType string
|
||||
|
||||
// These are valid conditions of a rollout.
|
||||
//
|
||||
//goland:noinspection GoUnusedConst
|
||||
const (
|
||||
// RolloutConditionProgressing means the rollout is progressing. Progress for a rollout is
|
||||
// considered when a new replica set is created or adopted, when pods scale
|
||||
// up or old pods scale down, or when the services are updated. Progress is not estimated
|
||||
// for paused rollouts.
|
||||
RolloutConditionProgressing RolloutConditionType = "Progressing"
|
||||
// Progressing Reason
|
||||
ProgressingReasonInitializing = "Initializing"
|
||||
ProgressingReasonInRolling = "InRolling"
|
||||
ProgressingReasonFinalising = "Finalising"
|
||||
ProgressingReasonCompleted = "Completed"
|
||||
ProgressingReasonCancelling = "Cancelling"
|
||||
ProgressingReasonPaused = "Paused"
|
||||
|
||||
// RolloutConditionSucceeded indicates whether rollout is succeeded or failed.
|
||||
RolloutConditionSucceeded RolloutConditionType = "Succeeded"
|
||||
|
||||
// Terminating condition
|
||||
RolloutConditionTerminating RolloutConditionType = "Terminating"
|
||||
// Terminating Reason
|
||||
TerminatingReasonInTerminating = "InTerminating"
|
||||
TerminatingReasonCompleted = "Completed"
|
||||
|
||||
// Finalise Reason
|
||||
// Finalise when the last batch is released and all pods will update to new version
|
||||
FinaliseReasonSuccess = "Success"
|
||||
// Finalise when rollback detected
|
||||
FinaliseReasonRollback = "Rollback"
|
||||
// Finalise when Continuous Release detected
|
||||
FinaliseReasonContinuous = "Continuous"
|
||||
// Finalise when Rollout is disabling
|
||||
FinaliseReasonDisalbed = "RolloutDisabled"
|
||||
// Finalise when Rollout is deleting
|
||||
FinaliseReasonDelete = "RolloutDeleting"
|
||||
)
|
||||
|
||||
// fields in CommonStatus are shared between canary status and bluegreen status
|
||||
// if a field is accessed in strategy-agnostic way, e.g. accessed from rollout_progressing.go, or rollout_status.go
|
||||
// then it can be put into CommonStatus
|
||||
// if a field is only accessed in strategy-specific way, e.g. accessed from rollout_canary.go or rollout_bluegreen.go
|
||||
// then it should stay behind with CanaryStatus or BlueGreenStatus
|
||||
type CommonStatus struct {
|
||||
// observedWorkloadGeneration is the most recent generation observed for this Rollout ref workload generation.
|
||||
ObservedWorkloadGeneration int64 `json:"observedWorkloadGeneration,omitempty"`
|
||||
// ObservedRolloutID will record the newest spec.RolloutID if status.canaryRevision equals to workload.updateRevision
|
||||
ObservedRolloutID string `json:"observedRolloutID,omitempty"`
|
||||
// RolloutHash from rollout.spec object
|
||||
RolloutHash string `json:"rolloutHash,omitempty"`
|
||||
// StableRevision indicates the revision of stable pods
|
||||
StableRevision string `json:"stableRevision,omitempty"`
|
||||
// pod template hash is used as service selector label
|
||||
PodTemplateHash string `json:"podTemplateHash"`
|
||||
// CurrentStepIndex defines the current step of the rollout is on.
|
||||
// +optional
|
||||
CurrentStepIndex int32 `json:"currentStepIndex"`
|
||||
// NextStepIndex defines the next step of the rollout is on.
|
||||
// In normal case, NextStepIndex is equal to CurrentStepIndex + 1
|
||||
// If the current step is the last step, NextStepIndex is equal to -1
|
||||
// Before the release, NextStepIndex is also equal to -1
|
||||
// 0 is not used and won't appear in any case
|
||||
// It is allowed to patch NextStepIndex by design,
|
||||
// e.g. if CurrentStepIndex is 2, user can patch NextStepIndex to 3 (if exists) to
|
||||
// achieve batch jump, or patch NextStepIndex to 1 to implement a re-execution of step 1
|
||||
// Patching it with a non-positive value is useless and meaningless, which will be corrected
|
||||
// in the next reconciliation
|
||||
NextStepIndex int32 `json:"nextStepIndex"`
|
||||
// FinalisingStep the step of finalising
|
||||
FinalisingStep FinalisingStepType `json:"finalisingStep"`
|
||||
CurrentStepState CanaryStepState `json:"currentStepState"`
|
||||
Message string `json:"message,omitempty"`
|
||||
LastUpdateTime *metav1.Time `json:"lastUpdateTime,omitempty"`
|
||||
}
|
||||
|
||||
// CanaryStatus status fields that only pertain to the canary rollout
|
||||
type CanaryStatus struct {
|
||||
// must be inline
|
||||
CommonStatus `json:",inline"`
|
||||
// CanaryRevision is calculated by rollout based on podTemplateHash, and the internal logic flow uses
|
||||
// It may be different from rs podTemplateHash in different k8s versions, so it cannot be used as service selector label
|
||||
CanaryRevision string `json:"canaryRevision"`
|
||||
// CanaryReplicas the numbers of canary revision pods
|
||||
CanaryReplicas int32 `json:"canaryReplicas"`
|
||||
// CanaryReadyReplicas the numbers of ready canary revision pods
|
||||
CanaryReadyReplicas int32 `json:"canaryReadyReplicas"`
|
||||
}
|
||||
|
||||
// BlueGreenStatus status fields that only pertain to the blueGreen rollout
|
||||
type BlueGreenStatus struct {
|
||||
CommonStatus `json:",inline"`
|
||||
// UpdatedRevision is calculated by rollout based on podTemplateHash, and the internal logic flow uses
|
||||
// It may be different from rs podTemplateHash in different k8s versions, so it cannot be used as service selector label
|
||||
UpdatedRevision string `json:"updatedRevision"`
|
||||
// UpdatedReplicas the numbers of updated pods
|
||||
UpdatedReplicas int32 `json:"updatedReplicas"`
|
||||
// UpdatedReadyReplicas the numbers of updated ready pods
|
||||
UpdatedReadyReplicas int32 `json:"updatedReadyReplicas"`
|
||||
}
|
||||
|
||||
// GetSubStatus returns the ethier canary or bluegreen status
|
||||
func (r *RolloutStatus) GetSubStatus() *CommonStatus {
|
||||
if r.CanaryStatus == nil && r.BlueGreenStatus == nil {
|
||||
return nil
|
||||
}
|
||||
if r.CanaryStatus != nil {
|
||||
return &r.CanaryStatus.CommonStatus
|
||||
}
|
||||
return &r.BlueGreenStatus.CommonStatus
|
||||
}
|
||||
|
||||
func (r *RolloutStatus) IsSubStatusEmpty() bool {
|
||||
return r.CanaryStatus == nil && r.BlueGreenStatus == nil
|
||||
}
|
||||
|
||||
func (r *RolloutStatus) Clear() {
|
||||
r.CanaryStatus = nil
|
||||
r.BlueGreenStatus = nil
|
||||
}
|
||||
|
||||
//TODO - the following functions seem awkward, is there better way for our case?
|
||||
|
||||
func (r *RolloutStatus) GetCanaryRevision() string {
|
||||
if r.CanaryStatus != nil {
|
||||
return r.CanaryStatus.CanaryRevision
|
||||
}
|
||||
if r.BlueGreenStatus != nil {
|
||||
return r.BlueGreenStatus.UpdatedRevision
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (r *RolloutStatus) SetCanaryRevision(revision string) {
|
||||
if r.CanaryStatus != nil {
|
||||
r.CanaryStatus.CanaryRevision = revision
|
||||
}
|
||||
if r.BlueGreenStatus != nil {
|
||||
r.BlueGreenStatus.UpdatedRevision = revision
|
||||
}
|
||||
}
|
||||
|
||||
func (r *RolloutStatus) GetCanaryReplicas() int32 {
|
||||
if r.CanaryStatus != nil {
|
||||
return r.CanaryStatus.CanaryReplicas
|
||||
}
|
||||
return r.BlueGreenStatus.UpdatedReplicas
|
||||
}
|
||||
|
||||
func (r *RolloutStatus) SetCanaryReplicas(replicas int32) {
|
||||
if r.CanaryStatus != nil {
|
||||
r.CanaryStatus.CanaryReplicas = replicas
|
||||
}
|
||||
if r.BlueGreenStatus != nil {
|
||||
r.BlueGreenStatus.UpdatedReplicas = replicas
|
||||
}
|
||||
}
|
||||
|
||||
func (r *RolloutStatus) GetCanaryReadyReplicas() int32 {
|
||||
if r.CanaryStatus != nil {
|
||||
return r.CanaryStatus.CanaryReadyReplicas
|
||||
}
|
||||
return r.BlueGreenStatus.UpdatedReadyReplicas
|
||||
}
|
||||
|
||||
func (r *RolloutStatus) SetCanaryReadyReplicas(replicas int32) {
|
||||
if r.CanaryStatus != nil {
|
||||
r.CanaryStatus.CanaryReadyReplicas = replicas
|
||||
}
|
||||
if r.BlueGreenStatus != nil {
|
||||
r.BlueGreenStatus.UpdatedReadyReplicas = replicas
|
||||
}
|
||||
}
|
||||
|
||||
type CanaryStepState string
|
||||
|
||||
const (
|
||||
// the first step, handle some special cases before step upgrade, to prevent traffic loss
|
||||
CanaryStepStateInit CanaryStepState = "BeforeStepUpgrade"
|
||||
CanaryStepStateUpgrade CanaryStepState = "StepUpgrade"
|
||||
CanaryStepStateTrafficRouting CanaryStepState = "StepTrafficRouting"
|
||||
CanaryStepStateMetricsAnalysis CanaryStepState = "StepMetricsAnalysis"
|
||||
CanaryStepStatePaused CanaryStepState = "StepPaused"
|
||||
CanaryStepStateReady CanaryStepState = "StepReady"
|
||||
CanaryStepStateCompleted CanaryStepState = "Completed"
|
||||
)
|
||||
|
||||
// RolloutPhase are a set of phases that this rollout
|
||||
type RolloutPhase string
|
||||
|
||||
const (
|
||||
// RolloutPhaseInitial indicates a rollout is Initial
|
||||
RolloutPhaseInitial RolloutPhase = "Initial"
|
||||
// RolloutPhaseHealthy indicates a rollout is healthy
|
||||
RolloutPhaseHealthy RolloutPhase = "Healthy"
|
||||
// RolloutPhaseProgressing indicates a rollout is not yet healthy but still making progress towards a healthy state
|
||||
RolloutPhaseProgressing RolloutPhase = "Progressing"
|
||||
// RolloutPhaseTerminating indicates a rollout is terminated
|
||||
RolloutPhaseTerminating RolloutPhase = "Terminating"
|
||||
// RolloutPhaseDisabled indicates a rollout is disabled
|
||||
RolloutPhaseDisabled RolloutPhase = "Disabled"
|
||||
// RolloutPhaseDisabling indicates a rollout is disabling and releasing resources
|
||||
RolloutPhaseDisabling RolloutPhase = "Disabling"
|
||||
)
|
||||
|
||||
type FinalisingStepType string
|
||||
|
||||
//goland:noinspection GoUnusedConst
|
||||
const (
|
||||
// Route all traffic to new version (for bluegreen)
|
||||
FinalisingStepRouteTrafficToNew FinalisingStepType = "FinalisingStepRouteTrafficToNew"
|
||||
// Restore the GatewayAPI/Ingress/Istio
|
||||
FinalisingStepRouteTrafficToStable FinalisingStepType = "FinalisingStepRouteTrafficToStable"
|
||||
// Restore the stable Service, i.e. remove corresponding selector
|
||||
FinalisingStepRestoreStableService FinalisingStepType = "RestoreStableService"
|
||||
// Remove the Canary Service
|
||||
FinalisingStepRemoveCanaryService FinalisingStepType = "RemoveCanaryService"
|
||||
|
||||
// Patch Batch Release to scale down (exception: the canary Deployment will be
|
||||
// scaled down in FinalisingStepTypeDeleteBR step)
|
||||
// For Both BlueGreenStrategy and CanaryStrategy:
|
||||
// set workload.pause=false, set workload.partition=0
|
||||
FinalisingStepResumeWorkload FinalisingStepType = "ResumeWorkload"
|
||||
// Delete Batch Release
|
||||
FinalisingStepReleaseWorkloadControl FinalisingStepType = "ReleaseWorkloadControl"
|
||||
// All needed work done
|
||||
FinalisingStepTypeEnd FinalisingStepType = "END"
|
||||
// Only for debugging use
|
||||
FinalisingStepWaitEndless FinalisingStepType = "WaitEndless"
|
||||
)
|
||||
|
||||
// +genclient
|
||||
//+kubebuilder:object:root=true
|
||||
//+kubebuilder:subresource:status
|
||||
// +kubebuilder:storageversion
|
||||
// +kubebuilder:printcolumn:name="STATUS",type="string",JSONPath=".status.phase",description="The rollout status phase"
|
||||
// +kubebuilder:printcolumn:name="CANARY_STEP",type="integer",JSONPath=".status.currentStepIndex",description="The rollout canary status step"
|
||||
// +kubebuilder:printcolumn:name="CANARY_STATE",type="string",JSONPath=".status.currentStepState",description="The rollout canary status step state"
|
||||
// +kubebuilder:printcolumn:name="MESSAGE",type="string",JSONPath=".status.message",description="The rollout canary status message"
|
||||
// +kubebuilder:printcolumn:name="AGE",type=date,JSONPath=".metadata.creationTimestamp"
|
||||
|
||||
// Rollout is the Schema for the rollouts API
|
||||
type Rollout struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
Spec RolloutSpec `json:"spec,omitempty"`
|
||||
Status RolloutStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
//+kubebuilder:object:root=true
|
||||
|
||||
// RolloutList contains a list of Rollout
|
||||
type RolloutList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata,omitempty"`
|
||||
Items []Rollout `json:"items"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
SchemeBuilder.Register(&Rollout{}, &RolloutList{})
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
Copyright 2023 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 v1beta1
|
||||
|
||||
// TrafficRoutingRef hosts all the different configuration for supported service meshes to enable more fine-grained traffic routing
|
||||
type TrafficRoutingRef struct {
|
||||
// Service holds the name of a service which selects pods with stable version and don't select any pods with canary version.
|
||||
Service string `json:"service"`
|
||||
// Optional duration in seconds the traffic provider(e.g. nginx ingress controller) consumes the service, ingress configuration changes gracefully.
|
||||
// +kubebuilder:default=3
|
||||
GracePeriodSeconds int32 `json:"gracePeriodSeconds,omitempty"`
|
||||
// Ingress holds Ingress specific configuration to route traffic, e.g. Nginx, Alb.
|
||||
Ingress *IngressTrafficRouting `json:"ingress,omitempty"`
|
||||
// Gateway holds Gateway specific configuration to route traffic
|
||||
// Gateway configuration only supports >= v0.4.0 (v1alpha2).
|
||||
Gateway *GatewayTrafficRouting `json:"gateway,omitempty"`
|
||||
// CustomNetworkRefs hold a list of custom providers to route traffic
|
||||
CustomNetworkRefs []ObjectRef `json:"customNetworkRefs,omitempty"`
|
||||
}
|
||||
|
||||
// IngressTrafficRouting configuration for ingress controller to control traffic routing
|
||||
type IngressTrafficRouting struct {
|
||||
// ClassType refers to the type of `Ingress`.
|
||||
// current support nginx, aliyun-alb. default is nginx.
|
||||
// +optional
|
||||
ClassType string `json:"classType,omitempty"`
|
||||
// Name refers to the name of an `Ingress` resource in the same namespace as the `Rollout`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// GatewayTrafficRouting configuration for gateway api
|
||||
type GatewayTrafficRouting struct {
|
||||
// HTTPRouteName refers to the name of an `HTTPRoute` resource in the same namespace as the `Rollout`
|
||||
HTTPRouteName *string `json:"httpRouteName,omitempty"`
|
||||
// TCPRouteName *string `json:"tcpRouteName,omitempty"`
|
||||
// UDPRouteName *string `json:"udpRouteName,omitempty"`
|
||||
}
|
|
@ -0,0 +1,734 @@
|
|||
//go:build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright 2023 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.
|
||||
*/
|
||||
|
||||
// Code generated by controller-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
"k8s.io/api/apps/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
apisv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *BatchRelease) DeepCopyInto(out *BatchRelease) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
in.Spec.DeepCopyInto(&out.Spec)
|
||||
in.Status.DeepCopyInto(&out.Status)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BatchRelease.
|
||||
func (in *BatchRelease) DeepCopy() *BatchRelease {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(BatchRelease)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *BatchRelease) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *BatchReleaseCanaryStatus) DeepCopyInto(out *BatchReleaseCanaryStatus) {
|
||||
*out = *in
|
||||
if in.BatchReadyTime != nil {
|
||||
in, out := &in.BatchReadyTime, &out.BatchReadyTime
|
||||
*out = (*in).DeepCopy()
|
||||
}
|
||||
if in.NoNeedUpdateReplicas != nil {
|
||||
in, out := &in.NoNeedUpdateReplicas, &out.NoNeedUpdateReplicas
|
||||
*out = new(int32)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BatchReleaseCanaryStatus.
|
||||
func (in *BatchReleaseCanaryStatus) DeepCopy() *BatchReleaseCanaryStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(BatchReleaseCanaryStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *BatchReleaseList) DeepCopyInto(out *BatchReleaseList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]BatchRelease, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BatchReleaseList.
|
||||
func (in *BatchReleaseList) DeepCopy() *BatchReleaseList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(BatchReleaseList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *BatchReleaseList) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *BatchReleaseSpec) DeepCopyInto(out *BatchReleaseSpec) {
|
||||
*out = *in
|
||||
out.WorkloadRef = in.WorkloadRef
|
||||
in.ReleasePlan.DeepCopyInto(&out.ReleasePlan)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BatchReleaseSpec.
|
||||
func (in *BatchReleaseSpec) DeepCopy() *BatchReleaseSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(BatchReleaseSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *BatchReleaseStatus) DeepCopyInto(out *BatchReleaseStatus) {
|
||||
*out = *in
|
||||
if in.Conditions != nil {
|
||||
in, out := &in.Conditions, &out.Conditions
|
||||
*out = make([]RolloutCondition, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
in.CanaryStatus.DeepCopyInto(&out.CanaryStatus)
|
||||
if in.CollisionCount != nil {
|
||||
in, out := &in.CollisionCount, &out.CollisionCount
|
||||
*out = new(int32)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BatchReleaseStatus.
|
||||
func (in *BatchReleaseStatus) DeepCopy() *BatchReleaseStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(BatchReleaseStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *BlueGreenStatus) DeepCopyInto(out *BlueGreenStatus) {
|
||||
*out = *in
|
||||
in.CommonStatus.DeepCopyInto(&out.CommonStatus)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BlueGreenStatus.
|
||||
func (in *BlueGreenStatus) DeepCopy() *BlueGreenStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(BlueGreenStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *BlueGreenStrategy) DeepCopyInto(out *BlueGreenStrategy) {
|
||||
*out = *in
|
||||
if in.Steps != nil {
|
||||
in, out := &in.Steps, &out.Steps
|
||||
*out = make([]CanaryStep, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.TrafficRoutings != nil {
|
||||
in, out := &in.TrafficRoutings, &out.TrafficRoutings
|
||||
*out = make([]TrafficRoutingRef, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.FailureThreshold != nil {
|
||||
in, out := &in.FailureThreshold, &out.FailureThreshold
|
||||
*out = new(intstr.IntOrString)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BlueGreenStrategy.
|
||||
func (in *BlueGreenStrategy) DeepCopy() *BlueGreenStrategy {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(BlueGreenStrategy)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CanaryStatus) DeepCopyInto(out *CanaryStatus) {
|
||||
*out = *in
|
||||
in.CommonStatus.DeepCopyInto(&out.CommonStatus)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CanaryStatus.
|
||||
func (in *CanaryStatus) DeepCopy() *CanaryStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CanaryStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CanaryStep) DeepCopyInto(out *CanaryStep) {
|
||||
*out = *in
|
||||
in.TrafficRoutingStrategy.DeepCopyInto(&out.TrafficRoutingStrategy)
|
||||
if in.Replicas != nil {
|
||||
in, out := &in.Replicas, &out.Replicas
|
||||
*out = new(intstr.IntOrString)
|
||||
**out = **in
|
||||
}
|
||||
in.Pause.DeepCopyInto(&out.Pause)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CanaryStep.
|
||||
func (in *CanaryStep) DeepCopy() *CanaryStep {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CanaryStep)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CanaryStrategy) DeepCopyInto(out *CanaryStrategy) {
|
||||
*out = *in
|
||||
if in.Steps != nil {
|
||||
in, out := &in.Steps, &out.Steps
|
||||
*out = make([]CanaryStep, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.TrafficRoutings != nil {
|
||||
in, out := &in.TrafficRoutings, &out.TrafficRoutings
|
||||
*out = make([]TrafficRoutingRef, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.FailureThreshold != nil {
|
||||
in, out := &in.FailureThreshold, &out.FailureThreshold
|
||||
*out = new(intstr.IntOrString)
|
||||
**out = **in
|
||||
}
|
||||
if in.PatchPodTemplateMetadata != nil {
|
||||
in, out := &in.PatchPodTemplateMetadata, &out.PatchPodTemplateMetadata
|
||||
*out = new(PatchPodTemplateMetadata)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CanaryStrategy.
|
||||
func (in *CanaryStrategy) DeepCopy() *CanaryStrategy {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CanaryStrategy)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CommonStatus) DeepCopyInto(out *CommonStatus) {
|
||||
*out = *in
|
||||
if in.LastUpdateTime != nil {
|
||||
in, out := &in.LastUpdateTime, &out.LastUpdateTime
|
||||
*out = (*in).DeepCopy()
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommonStatus.
|
||||
func (in *CommonStatus) DeepCopy() *CommonStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CommonStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *DeploymentExtraStatus) DeepCopyInto(out *DeploymentExtraStatus) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeploymentExtraStatus.
|
||||
func (in *DeploymentExtraStatus) DeepCopy() *DeploymentExtraStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(DeploymentExtraStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *DeploymentStrategy) DeepCopyInto(out *DeploymentStrategy) {
|
||||
*out = *in
|
||||
if in.RollingUpdate != nil {
|
||||
in, out := &in.RollingUpdate, &out.RollingUpdate
|
||||
*out = new(v1.RollingUpdateDeployment)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
out.Partition = in.Partition
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeploymentStrategy.
|
||||
func (in *DeploymentStrategy) DeepCopy() *DeploymentStrategy {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(DeploymentStrategy)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *GatewayTrafficRouting) DeepCopyInto(out *GatewayTrafficRouting) {
|
||||
*out = *in
|
||||
if in.HTTPRouteName != nil {
|
||||
in, out := &in.HTTPRouteName, &out.HTTPRouteName
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayTrafficRouting.
|
||||
func (in *GatewayTrafficRouting) DeepCopy() *GatewayTrafficRouting {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(GatewayTrafficRouting)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *HttpRouteMatch) DeepCopyInto(out *HttpRouteMatch) {
|
||||
*out = *in
|
||||
if in.Path != nil {
|
||||
in, out := &in.Path, &out.Path
|
||||
*out = new(apisv1beta1.HTTPPathMatch)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.Headers != nil {
|
||||
in, out := &in.Headers, &out.Headers
|
||||
*out = make([]apisv1beta1.HTTPHeaderMatch, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.QueryParams != nil {
|
||||
in, out := &in.QueryParams, &out.QueryParams
|
||||
*out = make([]apisv1beta1.HTTPQueryParamMatch, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HttpRouteMatch.
|
||||
func (in *HttpRouteMatch) DeepCopy() *HttpRouteMatch {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(HttpRouteMatch)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *IngressTrafficRouting) DeepCopyInto(out *IngressTrafficRouting) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IngressTrafficRouting.
|
||||
func (in *IngressTrafficRouting) DeepCopy() *IngressTrafficRouting {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(IngressTrafficRouting)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ObjectRef) DeepCopyInto(out *ObjectRef) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectRef.
|
||||
func (in *ObjectRef) DeepCopy() *ObjectRef {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ObjectRef)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *PatchPodTemplateMetadata) DeepCopyInto(out *PatchPodTemplateMetadata) {
|
||||
*out = *in
|
||||
if in.Annotations != nil {
|
||||
in, out := &in.Annotations, &out.Annotations
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
if in.Labels != nil {
|
||||
in, out := &in.Labels, &out.Labels
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PatchPodTemplateMetadata.
|
||||
func (in *PatchPodTemplateMetadata) DeepCopy() *PatchPodTemplateMetadata {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(PatchPodTemplateMetadata)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ReleaseBatch) DeepCopyInto(out *ReleaseBatch) {
|
||||
*out = *in
|
||||
out.CanaryReplicas = in.CanaryReplicas
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReleaseBatch.
|
||||
func (in *ReleaseBatch) DeepCopy() *ReleaseBatch {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ReleaseBatch)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ReleasePlan) DeepCopyInto(out *ReleasePlan) {
|
||||
*out = *in
|
||||
if in.Batches != nil {
|
||||
in, out := &in.Batches, &out.Batches
|
||||
*out = make([]ReleaseBatch, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.BatchPartition != nil {
|
||||
in, out := &in.BatchPartition, &out.BatchPartition
|
||||
*out = new(int32)
|
||||
**out = **in
|
||||
}
|
||||
if in.FailureThreshold != nil {
|
||||
in, out := &in.FailureThreshold, &out.FailureThreshold
|
||||
*out = new(intstr.IntOrString)
|
||||
**out = **in
|
||||
}
|
||||
if in.PatchPodTemplateMetadata != nil {
|
||||
in, out := &in.PatchPodTemplateMetadata, &out.PatchPodTemplateMetadata
|
||||
*out = new(PatchPodTemplateMetadata)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReleasePlan.
|
||||
func (in *ReleasePlan) DeepCopy() *ReleasePlan {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ReleasePlan)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Rollout) DeepCopyInto(out *Rollout) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
in.Spec.DeepCopyInto(&out.Spec)
|
||||
in.Status.DeepCopyInto(&out.Status)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Rollout.
|
||||
func (in *Rollout) DeepCopy() *Rollout {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Rollout)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *Rollout) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *RolloutCondition) DeepCopyInto(out *RolloutCondition) {
|
||||
*out = *in
|
||||
in.LastUpdateTime.DeepCopyInto(&out.LastUpdateTime)
|
||||
in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RolloutCondition.
|
||||
func (in *RolloutCondition) DeepCopy() *RolloutCondition {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(RolloutCondition)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *RolloutList) DeepCopyInto(out *RolloutList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]Rollout, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RolloutList.
|
||||
func (in *RolloutList) DeepCopy() *RolloutList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(RolloutList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *RolloutList) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *RolloutPause) DeepCopyInto(out *RolloutPause) {
|
||||
*out = *in
|
||||
if in.Duration != nil {
|
||||
in, out := &in.Duration, &out.Duration
|
||||
*out = new(int32)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RolloutPause.
|
||||
func (in *RolloutPause) DeepCopy() *RolloutPause {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(RolloutPause)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *RolloutSpec) DeepCopyInto(out *RolloutSpec) {
|
||||
*out = *in
|
||||
out.WorkloadRef = in.WorkloadRef
|
||||
in.Strategy.DeepCopyInto(&out.Strategy)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RolloutSpec.
|
||||
func (in *RolloutSpec) DeepCopy() *RolloutSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(RolloutSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *RolloutStatus) DeepCopyInto(out *RolloutStatus) {
|
||||
*out = *in
|
||||
if in.CanaryStatus != nil {
|
||||
in, out := &in.CanaryStatus, &out.CanaryStatus
|
||||
*out = new(CanaryStatus)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.BlueGreenStatus != nil {
|
||||
in, out := &in.BlueGreenStatus, &out.BlueGreenStatus
|
||||
*out = new(BlueGreenStatus)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.Conditions != nil {
|
||||
in, out := &in.Conditions, &out.Conditions
|
||||
*out = make([]RolloutCondition, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RolloutStatus.
|
||||
func (in *RolloutStatus) DeepCopy() *RolloutStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(RolloutStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *RolloutStrategy) DeepCopyInto(out *RolloutStrategy) {
|
||||
*out = *in
|
||||
if in.Canary != nil {
|
||||
in, out := &in.Canary, &out.Canary
|
||||
*out = new(CanaryStrategy)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.BlueGreen != nil {
|
||||
in, out := &in.BlueGreen, &out.BlueGreen
|
||||
*out = new(BlueGreenStrategy)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RolloutStrategy.
|
||||
func (in *RolloutStrategy) DeepCopy() *RolloutStrategy {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(RolloutStrategy)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TrafficRoutingRef) DeepCopyInto(out *TrafficRoutingRef) {
|
||||
*out = *in
|
||||
if in.Ingress != nil {
|
||||
in, out := &in.Ingress, &out.Ingress
|
||||
*out = new(IngressTrafficRouting)
|
||||
**out = **in
|
||||
}
|
||||
if in.Gateway != nil {
|
||||
in, out := &in.Gateway, &out.Gateway
|
||||
*out = new(GatewayTrafficRouting)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.CustomNetworkRefs != nil {
|
||||
in, out := &in.CustomNetworkRefs, &out.CustomNetworkRefs
|
||||
*out = make([]ObjectRef, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficRoutingRef.
|
||||
func (in *TrafficRoutingRef) DeepCopy() *TrafficRoutingRef {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TrafficRoutingRef)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TrafficRoutingStrategy) DeepCopyInto(out *TrafficRoutingStrategy) {
|
||||
*out = *in
|
||||
if in.Traffic != nil {
|
||||
in, out := &in.Traffic, &out.Traffic
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
if in.RequestHeaderModifier != nil {
|
||||
in, out := &in.RequestHeaderModifier, &out.RequestHeaderModifier
|
||||
*out = new(apisv1beta1.HTTPHeaderFilter)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.Matches != nil {
|
||||
in, out := &in.Matches, &out.Matches
|
||||
*out = make([]HttpRouteMatch, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficRoutingStrategy.
|
||||
func (in *TrafficRoutingStrategy) DeepCopy() *TrafficRoutingStrategy {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TrafficRoutingStrategy)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
|
@ -1,11 +1,9 @@
|
|||
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.7.0
|
||||
creationTimestamp: null
|
||||
controller-gen.kubebuilder.io/version: v0.14.0
|
||||
name: batchreleases.rollouts.kruise.io
|
||||
spec:
|
||||
group: rollouts.kruise.io
|
||||
|
@ -37,14 +35,19 @@ spec:
|
|||
openAPIV3Schema:
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
of an object. Servers should convert recognized schemas to the latest
|
||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
description: |-
|
||||
APIVersion defines the versioned schema of this representation of an object.
|
||||
Servers should convert recognized schemas to the latest internal value, and
|
||||
may reject unrecognized values.
|
||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource this
|
||||
object represents. Servers may infer this from the endpoint the client
|
||||
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
description: |-
|
||||
Kind is a string value representing the REST resource this object represents.
|
||||
Servers may infer this from the endpoint the client submits requests to.
|
||||
Cannot be updated.
|
||||
In CamelCase.
|
||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
|
@ -56,20 +59,23 @@ spec:
|
|||
description: ReleasePlan is the details on how to rollout the resources
|
||||
properties:
|
||||
batchPartition:
|
||||
description: All pods in the batches up to the batchPartition
|
||||
(included) will have the target resource specification while
|
||||
the rest still is the stable revision. This is designed for
|
||||
the operators to manually rollout. Default is nil, which means
|
||||
no partition and will release all batches. BatchPartition start
|
||||
from 0.
|
||||
description: |-
|
||||
All pods in the batches up to the batchPartition (included) will have
|
||||
the target resource specification while the rest still is the stable revision.
|
||||
This is designed for the operators to manually rollout.
|
||||
Default is nil, which means no partition and will release all batches.
|
||||
BatchPartition start from 0.
|
||||
format: int32
|
||||
type: integer
|
||||
batches:
|
||||
description: 'Batches is the details on each batch of the ReleasePlan.
|
||||
Users can specify their batch plan in this field, such as: batches:
|
||||
- canaryReplicas: 1 # batches 0 - canaryReplicas: 2 # batches
|
||||
1 - canaryReplicas: 5 # batches 2 Not that these canaryReplicas
|
||||
should be a non-decreasing sequence.'
|
||||
description: |-
|
||||
Batches is the details on each batch of the ReleasePlan.
|
||||
Users can specify their batch plan in this field, such as:
|
||||
batches:
|
||||
- canaryReplicas: 1 # batches 0
|
||||
- canaryReplicas: 2 # batches 1
|
||||
- canaryReplicas: 5 # batches 2
|
||||
Not that these canaryReplicas should be a non-decreasing sequence.
|
||||
items:
|
||||
description: ReleaseBatch is used to describe how each batch
|
||||
release should be
|
||||
|
@ -78,33 +84,44 @@ spec:
|
|||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: 'CanaryReplicas is the number of upgraded pods
|
||||
that should have in this batch. it can be an absolute
|
||||
number (ex: 5) or a percentage of workload replicas. batches[i].canaryReplicas
|
||||
should less than or equal to batches[j].canaryReplicas
|
||||
if i < j.'
|
||||
description: |-
|
||||
CanaryReplicas is the number of upgraded pods that should have in this batch.
|
||||
it can be an absolute number (ex: 5) or a percentage of workload replicas.
|
||||
batches[i].canaryReplicas should less than or equal to batches[j].canaryReplicas if i < j.
|
||||
x-kubernetes-int-or-string: true
|
||||
required:
|
||||
- canaryReplicas
|
||||
type: object
|
||||
type: array
|
||||
enableExtraWorkloadForCanary:
|
||||
description: |-
|
||||
EnableExtraWorkloadForCanary indicates whether to create extra workload for canary
|
||||
True corresponds to RollingStyle "Canary".
|
||||
False corresponds to RollingStyle "Partiton".
|
||||
Ignored in BlueGreen-style.
|
||||
This field is about to deprecate, use RollingStyle instead.
|
||||
If both of them are set, controller will only consider this
|
||||
filed when RollingStyle is empty
|
||||
type: boolean
|
||||
failureThreshold:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: FailureThreshold indicates how many failed pods can
|
||||
be tolerated in all upgraded pods. Only when FailureThreshold
|
||||
are satisfied, Rollout can enter ready state. If FailureThreshold
|
||||
is nil, Rollout will use the MaxUnavailable of workload as its
|
||||
FailureThreshold. Defaults to nil.
|
||||
description: |-
|
||||
FailureThreshold indicates how many failed pods can be tolerated in all upgraded pods.
|
||||
Only when FailureThreshold are satisfied, Rollout can enter ready state.
|
||||
If FailureThreshold is nil, Rollout will use the MaxUnavailable of workload as its
|
||||
FailureThreshold.
|
||||
Defaults to nil.
|
||||
x-kubernetes-int-or-string: true
|
||||
finalizingPolicy:
|
||||
description: FinalizingPolicy define the behavior of controller
|
||||
when phase enter Finalizing Defaults to "Immediate"
|
||||
description: |-
|
||||
FinalizingPolicy define the behavior of controller when phase enter Finalizing
|
||||
Defaults to "Immediate"
|
||||
type: string
|
||||
patchPodTemplateMetadata:
|
||||
description: PatchPodTemplateMetadata indicates patch configuration(e.g.
|
||||
labels, annotations) to the canary deployment podTemplateSpec.metadata
|
||||
description: |-
|
||||
PatchPodTemplateMetadata indicates patch configuration(e.g. labels, annotations) to the canary deployment podTemplateSpec.metadata
|
||||
only support for canary deployment
|
||||
properties:
|
||||
annotations:
|
||||
|
@ -118,17 +135,23 @@ spec:
|
|||
description: labels
|
||||
type: object
|
||||
type: object
|
||||
rollingStyle:
|
||||
description: RollingStyle can be "Canary", "Partiton" or "BlueGreen"
|
||||
type: string
|
||||
rolloutID:
|
||||
description: RolloutID indicates an id for each rollout progress
|
||||
type: string
|
||||
required:
|
||||
- enableExtraWorkloadForCanary
|
||||
type: object
|
||||
targetReference:
|
||||
description: TargetRef contains the GVK and name of the workload that
|
||||
we need to upgrade to.
|
||||
properties:
|
||||
workloadRef:
|
||||
description: WorkloadRef contains enough information to let you
|
||||
identify a workload for Rollout Batch release of the bypass
|
||||
description: |-
|
||||
WorkloadRef contains enough information to let you identify a workload for Rollout
|
||||
Batch release of the bypass
|
||||
properties:
|
||||
apiVersion:
|
||||
description: API Version of the referent
|
||||
|
@ -157,10 +180,10 @@ spec:
|
|||
description: CanaryStatus describes the state of the canary rollout.
|
||||
properties:
|
||||
batchReadyTime:
|
||||
description: BatchReadyTime is the ready timestamp of the current
|
||||
batch or the last batch. This field is updated once a batch
|
||||
ready, and the batches[x].pausedSeconds relies on this field
|
||||
to calculate the real-time duration.
|
||||
description: |-
|
||||
BatchReadyTime is the ready timestamp of the current batch or the last batch.
|
||||
This field is updated once a batch ready, and the batches[x].pausedSeconds
|
||||
relies on this field to calculate the real-time duration.
|
||||
format: date-time
|
||||
type: string
|
||||
batchState:
|
||||
|
@ -190,9 +213,10 @@ spec:
|
|||
- currentBatch
|
||||
type: object
|
||||
collisionCount:
|
||||
description: Count of hash collisions for creating canary Deployment.
|
||||
The controller uses this field as a collision avoidance mechanism
|
||||
when it needs to create the name for the newest canary Deployment.
|
||||
description: |-
|
||||
Count of hash collisions for creating canary Deployment. The controller uses this
|
||||
field as a collision avoidance mechanism when it needs to create the name for the
|
||||
newest canary Deployment.
|
||||
format: int32
|
||||
type: integer
|
||||
conditions:
|
||||
|
@ -232,10 +256,10 @@ spec:
|
|||
type: object
|
||||
type: array
|
||||
observedGeneration:
|
||||
description: ObservedGeneration is the most recent generation observed
|
||||
for this BatchRelease. It corresponds to this BatchRelease's generation,
|
||||
which is updated on mutation by the API Server, and only if BatchRelease
|
||||
Spec was changed, its generation will increase 1.
|
||||
description: |-
|
||||
ObservedGeneration is the most recent generation observed for this BatchRelease.
|
||||
It corresponds to this BatchRelease's generation, which is updated on mutation
|
||||
by the API Server, and only if BatchRelease Spec was changed, its generation will increase 1.
|
||||
format: int64
|
||||
type: integer
|
||||
observedReleasePlanHash:
|
||||
|
@ -243,21 +267,304 @@ spec:
|
|||
spec.releasePlan.
|
||||
type: string
|
||||
observedRolloutID:
|
||||
description: ObservedRolloutID is the most recent rollout-id observed
|
||||
for this BatchRelease. If RolloutID was changed, we will restart
|
||||
to roll out from batch 0, to ensure the batch-id and rollout-id
|
||||
labels of Pods are correct.
|
||||
description: |-
|
||||
ObservedRolloutID is the most recent rollout-id observed for this BatchRelease.
|
||||
If RolloutID was changed, we will restart to roll out from batch 0,
|
||||
to ensure the batch-id and rollout-id labels of Pods are correct.
|
||||
type: string
|
||||
observedWorkloadReplicas:
|
||||
description: ObservedWorkloadReplicas is observed replicas of target
|
||||
referenced workload. This field is designed to deal with scaling
|
||||
event during rollout, if this field changed, it means that the workload
|
||||
is scaling during rollout.
|
||||
description: |-
|
||||
ObservedWorkloadReplicas is observed replicas of target referenced workload.
|
||||
This field is designed to deal with scaling event during rollout, if this field changed,
|
||||
it means that the workload is scaling during rollout.
|
||||
format: int32
|
||||
type: integer
|
||||
phase:
|
||||
description: Phase is the release plan phase, which indicates the
|
||||
current state of release plan state machine in BatchRelease controller.
|
||||
description: |-
|
||||
Phase is the release plan phase, which indicates the current state of release
|
||||
plan state machine in BatchRelease controller.
|
||||
type: string
|
||||
stableRevision:
|
||||
description: StableRevision is the pod-template-hash of stable revision
|
||||
pod template.
|
||||
type: string
|
||||
updateRevision:
|
||||
description: UpdateRevision is the pod-template-hash of update revision
|
||||
pod template.
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
storage: false
|
||||
subresources:
|
||||
status: {}
|
||||
- additionalPrinterColumns:
|
||||
- jsonPath: .spec.targetReference.workloadRef.kind
|
||||
name: KIND
|
||||
type: string
|
||||
- jsonPath: .status.phase
|
||||
name: PHASE
|
||||
type: string
|
||||
- jsonPath: .status.canaryStatus.currentBatch
|
||||
name: BATCH
|
||||
type: integer
|
||||
- jsonPath: .status.canaryStatus.batchState
|
||||
name: BATCH-STATE
|
||||
type: string
|
||||
- jsonPath: .metadata.creationTimestamp
|
||||
name: AGE
|
||||
type: date
|
||||
name: v1beta1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
properties:
|
||||
apiVersion:
|
||||
description: |-
|
||||
APIVersion defines the versioned schema of this representation of an object.
|
||||
Servers should convert recognized schemas to the latest internal value, and
|
||||
may reject unrecognized values.
|
||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
|
||||
type: string
|
||||
kind:
|
||||
description: |-
|
||||
Kind is a string value representing the REST resource this object represents.
|
||||
Servers may infer this from the endpoint the client submits requests to.
|
||||
Cannot be updated.
|
||||
In CamelCase.
|
||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: BatchReleaseSpec defines how to describe an update between
|
||||
different compRevision
|
||||
properties:
|
||||
releasePlan:
|
||||
description: ReleasePlan is the details on how to rollout the resources
|
||||
properties:
|
||||
batchPartition:
|
||||
description: |-
|
||||
All pods in the batches up to the batchPartition (included) will have
|
||||
the target resource specification while the rest still is the stable revision.
|
||||
This is designed for the operators to manually rollout.
|
||||
Default is nil, which means no partition and will release all batches.
|
||||
BatchPartition start from 0.
|
||||
format: int32
|
||||
type: integer
|
||||
batches:
|
||||
description: |-
|
||||
Batches is the details on each batch of the ReleasePlan.
|
||||
Users can specify their batch plan in this field, such as:
|
||||
batches:
|
||||
- canaryReplicas: 1 # batches 0
|
||||
- canaryReplicas: 2 # batches 1
|
||||
- canaryReplicas: 5 # batches 2
|
||||
Not that these canaryReplicas should be a non-decreasing sequence.
|
||||
items:
|
||||
description: ReleaseBatch is used to describe how each batch
|
||||
release should be
|
||||
properties:
|
||||
canaryReplicas:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: |-
|
||||
CanaryReplicas is the number of upgraded pods that should have in this batch.
|
||||
it can be an absolute number (ex: 5) or a percentage of workload replicas.
|
||||
batches[i].canaryReplicas should less than or equal to batches[j].canaryReplicas if i < j.
|
||||
x-kubernetes-int-or-string: true
|
||||
required:
|
||||
- canaryReplicas
|
||||
type: object
|
||||
type: array
|
||||
enableExtraWorkloadForCanary:
|
||||
description: |-
|
||||
EnableExtraWorkloadForCanary indicates whether to create extra workload for canary
|
||||
True corresponds to RollingStyle "Canary".
|
||||
False corresponds to RollingStyle "Partiton".
|
||||
Ignored in BlueGreen-style.
|
||||
This field is about to deprecate, use RollingStyle instead.
|
||||
If both of them are set, controller will only consider this
|
||||
filed when RollingStyle is empty
|
||||
type: boolean
|
||||
failureThreshold:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: |-
|
||||
FailureThreshold indicates how many failed pods can be tolerated in all upgraded pods.
|
||||
Only when FailureThreshold are satisfied, Rollout can enter ready state.
|
||||
If FailureThreshold is nil, Rollout will use the MaxUnavailable of workload as its
|
||||
FailureThreshold.
|
||||
Defaults to nil.
|
||||
x-kubernetes-int-or-string: true
|
||||
finalizingPolicy:
|
||||
description: |-
|
||||
FinalizingPolicy define the behavior of controller when phase enter Finalizing
|
||||
Defaults to "Immediate"
|
||||
type: string
|
||||
patchPodTemplateMetadata:
|
||||
description: |-
|
||||
PatchPodTemplateMetadata indicates patch configuration(e.g. labels, annotations) to the canary deployment podTemplateSpec.metadata
|
||||
only support for canary deployment
|
||||
properties:
|
||||
annotations:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: annotations
|
||||
type: object
|
||||
labels:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: labels
|
||||
type: object
|
||||
type: object
|
||||
rollingStyle:
|
||||
description: RollingStyle can be "Canary", "Partiton" or "BlueGreen"
|
||||
type: string
|
||||
rolloutID:
|
||||
description: RolloutID indicates an id for each rollout progress
|
||||
type: string
|
||||
required:
|
||||
- enableExtraWorkloadForCanary
|
||||
type: object
|
||||
workloadRef:
|
||||
description: |-
|
||||
WorkloadRef contains enough information to let you identify a workload for Rollout
|
||||
Batch release of the bypass
|
||||
properties:
|
||||
apiVersion:
|
||||
description: API Version of the referent
|
||||
type: string
|
||||
kind:
|
||||
description: Kind of the referent
|
||||
type: string
|
||||
name:
|
||||
description: Name of the referent
|
||||
type: string
|
||||
required:
|
||||
- apiVersion
|
||||
- kind
|
||||
- name
|
||||
type: object
|
||||
required:
|
||||
- releasePlan
|
||||
type: object
|
||||
status:
|
||||
description: BatchReleaseStatus defines the observed state of a release
|
||||
plan
|
||||
properties:
|
||||
canaryStatus:
|
||||
description: CanaryStatus describes the state of the canary rollout.
|
||||
properties:
|
||||
batchReadyTime:
|
||||
description: |-
|
||||
BatchReadyTime is the ready timestamp of the current batch or the last batch.
|
||||
This field is updated once a batch ready, and the batches[x].pausedSeconds
|
||||
relies on this field to calculate the real-time duration.
|
||||
format: date-time
|
||||
type: string
|
||||
batchState:
|
||||
description: CurrentBatchState indicates the release state of
|
||||
the current batch.
|
||||
type: string
|
||||
currentBatch:
|
||||
description: The current batch the rollout is working on/blocked,
|
||||
it starts from 0
|
||||
format: int32
|
||||
type: integer
|
||||
noNeedUpdateReplicas:
|
||||
description: the number of pods that no need to rollback in rollback
|
||||
scene.
|
||||
format: int32
|
||||
type: integer
|
||||
updatedReadyReplicas:
|
||||
description: UpdatedReadyReplicas is the number upgraded Pods
|
||||
that have a Ready Condition.
|
||||
format: int32
|
||||
type: integer
|
||||
updatedReplicas:
|
||||
description: UpdatedReplicas is the number of upgraded Pods.
|
||||
format: int32
|
||||
type: integer
|
||||
required:
|
||||
- currentBatch
|
||||
type: object
|
||||
collisionCount:
|
||||
description: |-
|
||||
Count of hash collisions for creating canary Deployment. The controller uses this
|
||||
field as a collision avoidance mechanism when it needs to create the name for the
|
||||
newest canary Deployment.
|
||||
format: int32
|
||||
type: integer
|
||||
conditions:
|
||||
description: Conditions represents the observed process state of each
|
||||
phase during executing the release plan.
|
||||
items:
|
||||
description: RolloutCondition describes the state of a rollout at
|
||||
a certain point.
|
||||
properties:
|
||||
lastTransitionTime:
|
||||
description: Last time the condition transitioned from one status
|
||||
to another.
|
||||
format: date-time
|
||||
type: string
|
||||
lastUpdateTime:
|
||||
description: The last time this condition was updated.
|
||||
format: date-time
|
||||
type: string
|
||||
message:
|
||||
description: A human readable message indicating details about
|
||||
the transition.
|
||||
type: string
|
||||
reason:
|
||||
description: The reason for the condition's last transition.
|
||||
type: string
|
||||
status:
|
||||
description: Phase of the condition, one of True, False, Unknown.
|
||||
type: string
|
||||
type:
|
||||
description: Type of rollout condition.
|
||||
type: string
|
||||
required:
|
||||
- message
|
||||
- reason
|
||||
- status
|
||||
- type
|
||||
type: object
|
||||
type: array
|
||||
message:
|
||||
description: Message provides details on why the rollout is in its
|
||||
current phase
|
||||
type: string
|
||||
observedGeneration:
|
||||
description: |-
|
||||
ObservedGeneration is the most recent generation observed for this BatchRelease.
|
||||
It corresponds to this BatchRelease's generation, which is updated on mutation
|
||||
by the API Server, and only if BatchRelease Spec was changed, its generation will increase 1.
|
||||
format: int64
|
||||
type: integer
|
||||
observedReleasePlanHash:
|
||||
description: ObservedReleasePlanHash is a hash code of observed itself
|
||||
spec.releasePlan.
|
||||
type: string
|
||||
observedRolloutID:
|
||||
description: |-
|
||||
ObservedRolloutID is the most recent rollout-id observed for this BatchRelease.
|
||||
If RolloutID was changed, we will restart to roll out from batch 0,
|
||||
to ensure the batch-id and rollout-id labels of Pods are correct.
|
||||
type: string
|
||||
observedWorkloadReplicas:
|
||||
description: |-
|
||||
ObservedWorkloadReplicas is observed replicas of target referenced workload.
|
||||
This field is designed to deal with scaling event during rollout, if this field changed,
|
||||
it means that the workload is scaling during rollout.
|
||||
format: int32
|
||||
type: integer
|
||||
phase:
|
||||
description: |-
|
||||
Phase is the release plan phase, which indicates the current state of release
|
||||
plan state machine in BatchRelease controller.
|
||||
type: string
|
||||
stableRevision:
|
||||
description: StableRevision is the pod-template-hash of stable revision
|
||||
|
@ -273,9 +580,3 @@ spec:
|
|||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.7.0
|
||||
creationTimestamp: null
|
||||
controller-gen.kubebuilder.io/version: v0.14.0
|
||||
name: rollouthistories.rollouts.kruise.io
|
||||
spec:
|
||||
group: rollouts.kruise.io
|
||||
|
@ -22,14 +20,19 @@ spec:
|
|||
description: RolloutHistory is the Schema for the rollouthistories API
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
of an object. Servers should convert recognized schemas to the latest
|
||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
description: |-
|
||||
APIVersion defines the versioned schema of this representation of an object.
|
||||
Servers should convert recognized schemas to the latest internal value, and
|
||||
may reject unrecognized values.
|
||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource this
|
||||
object represents. Servers may infer this from the endpoint the client
|
||||
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
description: |-
|
||||
Kind is a string value representing the REST resource this object represents.
|
||||
Servers may infer this from the endpoint the client submits requests to.
|
||||
Cannot be updated.
|
||||
In CamelCase.
|
||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
|
@ -48,8 +51,9 @@ spec:
|
|||
name, workload name, ingress name, etc.
|
||||
type: string
|
||||
rolloutID:
|
||||
description: RolloutID indicates the new rollout if there is no
|
||||
new RolloutID this time, ignore it and not execute RolloutHistory
|
||||
description: |-
|
||||
RolloutID indicates the new rollout
|
||||
if there is no new RolloutID this time, ignore it and not execute RolloutHistory
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
|
@ -105,19 +109,22 @@ spec:
|
|||
as cloneset, deployment, advanced statefulset
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this
|
||||
representation of an object. Servers should convert recognized
|
||||
schemas to the latest internal value, and may reject unrecognized
|
||||
values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
description: |-
|
||||
APIVersion defines the versioned schema of this representation of an object.
|
||||
Servers should convert recognized schemas to the latest internal value, and
|
||||
may reject unrecognized values.
|
||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
|
||||
type: string
|
||||
data:
|
||||
description: Data indecates the spec of object ref
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource
|
||||
this object represents. Servers may infer this from the endpoint
|
||||
the client submits requests to. Cannot be updated. In CamelCase.
|
||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
description: |-
|
||||
Kind is a string value representing the REST resource this object represents.
|
||||
Servers may infer this from the endpoint the client submits requests to.
|
||||
Cannot be updated.
|
||||
In CamelCase.
|
||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||
type: string
|
||||
name:
|
||||
description: Name indicates the name of object ref, such as rollout
|
||||
|
@ -168,9 +175,3 @@ spec:
|
|||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,11 +1,9 @@
|
|||
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.7.0
|
||||
creationTimestamp: null
|
||||
controller-gen.kubebuilder.io/version: v0.14.0
|
||||
name: trafficroutings.rollouts.kruise.io
|
||||
spec:
|
||||
group: rollouts.kruise.io
|
||||
|
@ -34,14 +32,19 @@ spec:
|
|||
description: TrafficRouting is the Schema for the TrafficRoutings API
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
of an object. Servers should convert recognized schemas to the latest
|
||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
description: |-
|
||||
APIVersion defines the versioned schema of this representation of an object.
|
||||
Servers should convert recognized schemas to the latest internal value, and
|
||||
may reject unrecognized values.
|
||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource this
|
||||
object represents. Servers may infer this from the endpoint the client
|
||||
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
description: |-
|
||||
Kind is a string value representing the REST resource this object represents.
|
||||
Servers may infer this from the endpoint the client submits requests to.
|
||||
Cannot be updated.
|
||||
In CamelCase.
|
||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
|
@ -54,10 +57,27 @@ spec:
|
|||
for supported service meshes to enable more fine-grained traffic
|
||||
routing
|
||||
properties:
|
||||
customNetworkRefs:
|
||||
description: CustomNetworkRefs hold a list of custom providers
|
||||
to route traffic
|
||||
items:
|
||||
properties:
|
||||
apiVersion:
|
||||
type: string
|
||||
kind:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
required:
|
||||
- apiVersion
|
||||
- kind
|
||||
- name
|
||||
type: object
|
||||
type: array
|
||||
gateway:
|
||||
description: Gateway holds Gateway specific configuration to
|
||||
route traffic Gateway configuration only supports >= v0.4.0
|
||||
(v1alpha2).
|
||||
description: |-
|
||||
Gateway holds Gateway specific configuration to route traffic
|
||||
Gateway configuration only supports >= v0.4.0 (v1alpha2).
|
||||
properties:
|
||||
httpRouteName:
|
||||
description: HTTPRouteName refers to the name of an `HTTPRoute`
|
||||
|
@ -65,6 +85,7 @@ spec:
|
|||
type: string
|
||||
type: object
|
||||
gracePeriodSeconds:
|
||||
default: 3
|
||||
description: Optional duration in seconds the traffic provider(e.g.
|
||||
nginx ingress controller) consumes the service, ingress configuration
|
||||
changes gracefully.
|
||||
|
@ -75,7 +96,8 @@ spec:
|
|||
route traffic, e.g. Nginx, Alb.
|
||||
properties:
|
||||
classType:
|
||||
description: ClassType refers to the type of `Ingress`.
|
||||
description: |-
|
||||
ClassType refers to the type of `Ingress`.
|
||||
current support nginx, aliyun-alb. default is nginx.
|
||||
type: string
|
||||
name:
|
||||
|
@ -98,52 +120,61 @@ spec:
|
|||
description: trafficrouting strategy
|
||||
properties:
|
||||
matches:
|
||||
description: Matches define conditions used for matching the incoming
|
||||
HTTP requests to canary service. Each match is independent,
|
||||
i.e. this rule will be matched if **any** one of the matches
|
||||
is satisfied. If Gateway API, current only support one match.
|
||||
And cannot support both weight and matches, if both are configured,
|
||||
then matches takes precedence.
|
||||
description: |-
|
||||
Matches define conditions used for matching the incoming HTTP requests to canary service.
|
||||
Each match is independent, i.e. this rule will be matched if **any** one of the matches is satisfied.
|
||||
If Gateway API, current only support one match.
|
||||
And cannot support both weight and matches, if both are configured, then matches takes precedence.
|
||||
items:
|
||||
properties:
|
||||
headers:
|
||||
description: Headers specifies HTTP request header matchers.
|
||||
Multiple match values are ANDed together, meaning, a request
|
||||
must match all the specified headers to select the route.
|
||||
description: |-
|
||||
Headers specifies HTTP request header matchers. Multiple match values are
|
||||
ANDed together, meaning, a request must match all the specified headers
|
||||
to select the route.
|
||||
items:
|
||||
description: HTTPHeaderMatch describes how to select a
|
||||
HTTP route by matching HTTP request headers.
|
||||
description: |-
|
||||
HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request
|
||||
headers.
|
||||
properties:
|
||||
name:
|
||||
description: "Name is the name of the HTTP Header
|
||||
to be matched. Name matching MUST be case insensitive.
|
||||
(See https://tools.ietf.org/html/rfc7230#section-3.2).
|
||||
\n If multiple entries specify equivalent header
|
||||
names, only the first entry with an equivalent name
|
||||
MUST be considered for a match. Subsequent entries
|
||||
with an equivalent header name MUST be ignored.
|
||||
Due to the case-insensitivity of header names, \"foo\"
|
||||
and \"Foo\" are considered equivalent. \n When a
|
||||
header is repeated in an HTTP request, it is implementation-specific
|
||||
behavior as to how this is represented. Generally,
|
||||
proxies should follow the guidance from the RFC:
|
||||
https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2
|
||||
regarding processing a repeated header, with special
|
||||
handling for \"Set-Cookie\"."
|
||||
description: |-
|
||||
Name is the name of the HTTP Header to be matched. Name matching MUST be
|
||||
case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2).
|
||||
|
||||
|
||||
If multiple entries specify equivalent header names, only the first
|
||||
entry with an equivalent name MUST be considered for a match. Subsequent
|
||||
entries with an equivalent header name MUST be ignored. Due to the
|
||||
case-insensitivity of header names, "foo" and "Foo" are considered
|
||||
equivalent.
|
||||
|
||||
|
||||
When a header is repeated in an HTTP request, it is
|
||||
implementation-specific behavior as to how this is represented.
|
||||
Generally, proxies should follow the guidance from the RFC:
|
||||
https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding
|
||||
processing a repeated header, with special handling for "Set-Cookie".
|
||||
maxLength: 256
|
||||
minLength: 1
|
||||
pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$
|
||||
type: string
|
||||
type:
|
||||
default: Exact
|
||||
description: "Type specifies how to match against
|
||||
the value of the header. \n Support: Core (Exact)
|
||||
\n Support: Custom (RegularExpression) \n Since
|
||||
RegularExpression HeaderMatchType has custom conformance,
|
||||
implementations can support POSIX, PCRE or any other
|
||||
dialects of regular expressions. Please read the
|
||||
implementation's documentation to determine the
|
||||
supported dialect."
|
||||
description: |-
|
||||
Type specifies how to match against the value of the header.
|
||||
|
||||
|
||||
Support: Core (Exact)
|
||||
|
||||
|
||||
Support: Implementation-specific (RegularExpression)
|
||||
|
||||
|
||||
Since RegularExpression HeaderMatchType has implementation-specific
|
||||
conformance, implementations can support POSIX, PCRE or any other dialects
|
||||
of regular expressions. Please read the implementation's documentation to
|
||||
determine the supported dialect.
|
||||
enum:
|
||||
- Exact
|
||||
- RegularExpression
|
||||
|
@ -163,33 +194,62 @@ spec:
|
|||
type: object
|
||||
type: array
|
||||
requestHeaderModifier:
|
||||
description: "Set overwrites the request with the given header
|
||||
(name, value) before the action. \n Input: GET /foo HTTP/1.1
|
||||
\ my-header: foo \n requestHeaderModifier: set: - name:
|
||||
\"my-header\" value: \"bar\" \n Output: GET /foo HTTP/1.1
|
||||
\ my-header: bar"
|
||||
description: |-
|
||||
Set overwrites the request with the given header (name, value)
|
||||
before the action.
|
||||
|
||||
|
||||
Input:
|
||||
GET /foo HTTP/1.1
|
||||
my-header: foo
|
||||
|
||||
|
||||
requestHeaderModifier:
|
||||
set:
|
||||
- name: "my-header"
|
||||
value: "bar"
|
||||
|
||||
|
||||
Output:
|
||||
GET /foo HTTP/1.1
|
||||
my-header: bar
|
||||
properties:
|
||||
add:
|
||||
description: "Add adds the given header(s) (name, value) to
|
||||
the request before the action. It appends to any existing
|
||||
values associated with the header name. \n Input: GET
|
||||
/foo HTTP/1.1 my-header: foo \n Config: add: - name:
|
||||
\"my-header\" value: \"bar\" \n Output: GET /foo HTTP/1.1
|
||||
\ my-header: foo my-header: bar"
|
||||
description: |-
|
||||
Add adds the given header(s) (name, value) to the request
|
||||
before the action. It appends to any existing values associated
|
||||
with the header name.
|
||||
|
||||
|
||||
Input:
|
||||
GET /foo HTTP/1.1
|
||||
my-header: foo
|
||||
|
||||
|
||||
Config:
|
||||
add:
|
||||
- name: "my-header"
|
||||
value: "bar,baz"
|
||||
|
||||
|
||||
Output:
|
||||
GET /foo HTTP/1.1
|
||||
my-header: foo,bar,baz
|
||||
items:
|
||||
description: HTTPHeader represents an HTTP Header name and
|
||||
value as defined by RFC 7230.
|
||||
properties:
|
||||
name:
|
||||
description: "Name is the name of the HTTP Header to
|
||||
be matched. Name matching MUST be case insensitive.
|
||||
(See https://tools.ietf.org/html/rfc7230#section-3.2).
|
||||
\n If multiple entries specify equivalent header names,
|
||||
the first entry with an equivalent name MUST be considered
|
||||
for a match. Subsequent entries with an equivalent
|
||||
header name MUST be ignored. Due to the case-insensitivity
|
||||
of header names, \"foo\" and \"Foo\" are considered
|
||||
equivalent."
|
||||
description: |-
|
||||
Name is the name of the HTTP Header to be matched. Name matching MUST be
|
||||
case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2).
|
||||
|
||||
|
||||
If multiple entries specify equivalent header names, the first entry with
|
||||
an equivalent name MUST be considered for a match. Subsequent entries
|
||||
with an equivalent header name MUST be ignored. Due to the
|
||||
case-insensitivity of header names, "foo" and "Foo" are considered
|
||||
equivalent.
|
||||
maxLength: 256
|
||||
minLength: 1
|
||||
pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$
|
||||
|
@ -210,38 +270,67 @@ spec:
|
|||
- name
|
||||
x-kubernetes-list-type: map
|
||||
remove:
|
||||
description: "Remove the given header(s) from the HTTP request
|
||||
before the action. The value of Remove is a list of HTTP
|
||||
header names. Note that the header names are case-insensitive
|
||||
(see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2).
|
||||
\n Input: GET /foo HTTP/1.1 my-header1: foo my-header2:
|
||||
bar my-header3: baz \n Config: remove: [\"my-header1\",
|
||||
\"my-header3\"] \n Output: GET /foo HTTP/1.1 my-header2:
|
||||
bar"
|
||||
description: |-
|
||||
Remove the given header(s) from the HTTP request before the action. The
|
||||
value of Remove is a list of HTTP header names. Note that the header
|
||||
names are case-insensitive (see
|
||||
https://datatracker.ietf.org/doc/html/rfc2616#section-4.2).
|
||||
|
||||
|
||||
Input:
|
||||
GET /foo HTTP/1.1
|
||||
my-header1: foo
|
||||
my-header2: bar
|
||||
my-header3: baz
|
||||
|
||||
|
||||
Config:
|
||||
remove: ["my-header1", "my-header3"]
|
||||
|
||||
|
||||
Output:
|
||||
GET /foo HTTP/1.1
|
||||
my-header2: bar
|
||||
items:
|
||||
type: string
|
||||
maxItems: 16
|
||||
type: array
|
||||
x-kubernetes-list-type: set
|
||||
set:
|
||||
description: "Set overwrites the request with the given header
|
||||
(name, value) before the action. \n Input: GET /foo HTTP/1.1
|
||||
\ my-header: foo \n Config: set: - name: \"my-header\"
|
||||
\ value: \"bar\" \n Output: GET /foo HTTP/1.1 my-header:
|
||||
bar"
|
||||
description: |-
|
||||
Set overwrites the request with the given header (name, value)
|
||||
before the action.
|
||||
|
||||
|
||||
Input:
|
||||
GET /foo HTTP/1.1
|
||||
my-header: foo
|
||||
|
||||
|
||||
Config:
|
||||
set:
|
||||
- name: "my-header"
|
||||
value: "bar"
|
||||
|
||||
|
||||
Output:
|
||||
GET /foo HTTP/1.1
|
||||
my-header: bar
|
||||
items:
|
||||
description: HTTPHeader represents an HTTP Header name and
|
||||
value as defined by RFC 7230.
|
||||
properties:
|
||||
name:
|
||||
description: "Name is the name of the HTTP Header to
|
||||
be matched. Name matching MUST be case insensitive.
|
||||
(See https://tools.ietf.org/html/rfc7230#section-3.2).
|
||||
\n If multiple entries specify equivalent header names,
|
||||
the first entry with an equivalent name MUST be considered
|
||||
for a match. Subsequent entries with an equivalent
|
||||
header name MUST be ignored. Due to the case-insensitivity
|
||||
of header names, \"foo\" and \"Foo\" are considered
|
||||
equivalent."
|
||||
description: |-
|
||||
Name is the name of the HTTP Header to be matched. Name matching MUST be
|
||||
case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2).
|
||||
|
||||
|
||||
If multiple entries specify equivalent header names, the first entry with
|
||||
an equivalent name MUST be considered for a match. Subsequent entries
|
||||
with an equivalent header name MUST be ignored. Due to the
|
||||
case-insensitivity of header names, "foo" and "Foo" are considered
|
||||
equivalent.
|
||||
maxLength: 256
|
||||
minLength: 1
|
||||
pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$
|
||||
|
@ -292,9 +381,3 @@ spec:
|
|||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
|
|
|
@ -11,8 +11,8 @@ resources:
|
|||
patchesStrategicMerge:
|
||||
# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix.
|
||||
# patches here are for enabling the conversion webhook for each CRD
|
||||
#- patches/webhook_in_rollouts.yaml
|
||||
#- patches/webhook_in_batchreleases.yaml
|
||||
- patches/webhook_in_rollouts.yaml
|
||||
- patches/webhook_in_batchreleases.yaml
|
||||
#+kubebuilder:scaffold:crdkustomizewebhookpatch
|
||||
|
||||
# [CERTMANAGER] To enable webhook, uncomment all the sections with [CERTMANAGER] prefix.
|
||||
|
|
|
@ -13,4 +13,4 @@ spec:
|
|||
name: webhook-service
|
||||
path: /convert
|
||||
conversionReviewVersions:
|
||||
- v1
|
||||
- v1beta1
|
||||
|
|
|
@ -13,4 +13,4 @@ spec:
|
|||
name: webhook-service
|
||||
path: /convert
|
||||
conversionReviewVersions:
|
||||
- v1
|
||||
- v1beta1
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
name: manager-role
|
||||
rules:
|
||||
- apiGroups:
|
||||
|
@ -162,6 +160,16 @@ rules:
|
|||
- get
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- autoscaling
|
||||
resources:
|
||||
- horizontalpodautoscalers
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
|
@ -196,18 +204,6 @@ rules:
|
|||
- get
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- secrets
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
|
@ -248,6 +244,17 @@ rules:
|
|||
- get
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- networking.istio.io
|
||||
resources:
|
||||
- destinationrules
|
||||
- virtualservices
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- networking.k8s.io
|
||||
resources:
|
||||
|
@ -365,3 +372,22 @@ rules:
|
|||
- get
|
||||
- patch
|
||||
- update
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: manager-role
|
||||
namespace: system
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- secrets
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
|
|
|
@ -10,3 +10,17 @@ subjects:
|
|||
- kind: ServiceAccount
|
||||
name: controller-manager
|
||||
namespace: system
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: manager-rolebinding
|
||||
namespace: system
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: manager-role
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: controller-manager
|
||||
namespace: system
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
|
||||
---
|
||||
apiVersion: admissionregistration.k8s.io/v1
|
||||
kind: MutatingWebhookConfiguration
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
name: mutating-webhook-configuration
|
||||
webhooks:
|
||||
- admissionReviewVersions:
|
||||
|
@ -66,48 +64,6 @@ webhooks:
|
|||
resources:
|
||||
- deployments
|
||||
sideEffects: None
|
||||
- admissionReviewVersions:
|
||||
- v1
|
||||
- v1beta1
|
||||
clientConfig:
|
||||
service:
|
||||
name: webhook-service
|
||||
namespace: system
|
||||
path: /mutate-apps-v1-statefulset
|
||||
failurePolicy: Fail
|
||||
name: mstatefulset.kb.io
|
||||
rules:
|
||||
- apiGroups:
|
||||
- apps
|
||||
apiVersions:
|
||||
- v1
|
||||
operations:
|
||||
- UPDATE
|
||||
resources:
|
||||
- statefulsets
|
||||
sideEffects: None
|
||||
- admissionReviewVersions:
|
||||
- v1
|
||||
- v1beta1
|
||||
clientConfig:
|
||||
service:
|
||||
name: webhook-service
|
||||
namespace: system
|
||||
path: /mutate-apps-kruise-io-statefulset
|
||||
failurePolicy: Fail
|
||||
name: madvancedstatefulset.kb.io
|
||||
rules:
|
||||
- apiGroups:
|
||||
- apps.kruise.io
|
||||
apiVersions:
|
||||
- v1alpha1
|
||||
- v1beta1
|
||||
operations:
|
||||
- CREATE
|
||||
- UPDATE
|
||||
resources:
|
||||
- statefulsets
|
||||
sideEffects: None
|
||||
- admissionReviewVersions:
|
||||
- v1
|
||||
- v1beta1
|
||||
|
@ -129,12 +85,10 @@ webhooks:
|
|||
resources:
|
||||
- '*'
|
||||
sideEffects: None
|
||||
|
||||
---
|
||||
apiVersion: admissionregistration.k8s.io/v1
|
||||
kind: ValidatingWebhookConfiguration
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
name: validating-webhook-configuration
|
||||
webhooks:
|
||||
- admissionReviewVersions:
|
||||
|
@ -152,6 +106,7 @@ webhooks:
|
|||
- rollouts.kruise.io
|
||||
apiVersions:
|
||||
- v1alpha1
|
||||
- v1beta1
|
||||
operations:
|
||||
- CREATE
|
||||
- UPDATE
|
||||
|
|
|
@ -18,16 +18,16 @@ webhooks:
|
|||
matchExpressions:
|
||||
- key: rollouts.kruise.io/workload-type
|
||||
operator: Exists
|
||||
- name: mstatefulset.kb.io
|
||||
objectSelector:
|
||||
matchExpressions:
|
||||
- key: rollouts.kruise.io/workload-type
|
||||
operator: Exists
|
||||
- name: madvancedstatefulset.kb.io
|
||||
objectSelector:
|
||||
matchExpressions:
|
||||
- key: rollouts.kruise.io/workload-type
|
||||
operator: Exists
|
||||
# - name: mstatefulset.kb.io
|
||||
# objectSelector:
|
||||
# matchExpressions:
|
||||
# - key: rollouts.kruise.io/workload-type
|
||||
# operator: Exists
|
||||
# - name: madvancedstatefulset.kb.io
|
||||
# objectSelector:
|
||||
# matchExpressions:
|
||||
# - key: rollouts.kruise.io/workload-type
|
||||
# operator: Exists
|
||||
- name: mdeployment.kb.io
|
||||
objectSelector:
|
||||
matchExpressions:
|
||||
|
|
|
@ -0,0 +1,224 @@
|
|||
---
|
||||
title: v1beta1-apis-proposal
|
||||
|
||||
authors:
|
||||
- "@zmberg"
|
||||
|
||||
creation-date: 2023-11-07
|
||||
|
||||
---
|
||||
|
||||
## Motivation
|
||||
|
||||
The Kruise Rollout project has been stable for a year, recently we plan to upgrade the apis from v1alpha1 to v1beta1 and optimize some of the fields in response to past questions and community feedback,
|
||||
this proposal will organize the v1beta1 apis and discuss it with the community.
|
||||
|
||||
## Proposal
|
||||
To make it easier to understand, I'm going to introduce the v1beta1 field from 6 scenario.
|
||||
|
||||
### Canary Release
|
||||
```
|
||||
apiVersion: rollouts.kruise.io/v1beta1
|
||||
kind: Rollout
|
||||
metadata:
|
||||
name: rollouts-demo
|
||||
spec:
|
||||
workloadRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: workload-demo
|
||||
strategy:
|
||||
canary:
|
||||
# If true, then it will create new deployment for canary, such as: workload-demo-canary.
|
||||
# When user verifies that the canary version is OK, we will remove the canary deployment and release the deployment workload-demo in full.
|
||||
# Current only support k8s native deployment
|
||||
enableExtraWorkloadForCanary: true
|
||||
steps:
|
||||
- trafficWeight: 20%
|
||||
desiredReplicas: 2
|
||||
trafficRoutings:
|
||||
- service: service-demo
|
||||
ingress:
|
||||
classType: nginx
|
||||
name: ingress-demo
|
||||
```
|
||||
|
||||
### A/B Testing Release
|
||||
```
|
||||
apiVersion: rollouts.kruise.io/v1beta1
|
||||
kind: Rollout
|
||||
metadata:
|
||||
name: rollouts-demo
|
||||
spec:
|
||||
workloadRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: workload-demo
|
||||
strategy:
|
||||
canary:
|
||||
enableExtraWorkloadForCanary: true
|
||||
steps:
|
||||
- desiredReplicas: 2
|
||||
trafficMatches:
|
||||
- headers:
|
||||
- name: user-agent
|
||||
type: Exact
|
||||
value: pc
|
||||
trafficRoutings:
|
||||
- service: service-demo
|
||||
ingress:
|
||||
classType: nginx
|
||||
name: ingress-demo
|
||||
```
|
||||
|
||||
### Only Batch Release
|
||||
```
|
||||
apiVersion: rollouts.kruise.io/v1beta1
|
||||
kind: Rollout
|
||||
metadata:
|
||||
name: rollouts-demo
|
||||
spec:
|
||||
workloadRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: workload-demo
|
||||
strategy:
|
||||
canary:
|
||||
steps:
|
||||
- desiredReplicas: 1
|
||||
- desiredReplicas: 10%
|
||||
# After desiredReplicas Pods are ready, sleep 60 and continue to release later batches.
|
||||
# If you don't configure it, manual confirmation is required by default.
|
||||
pause: {duration: 60}
|
||||
- desiredReplicas: 30%
|
||||
pause: {duration: 60}
|
||||
- desiredReplicas: 60%
|
||||
pause: {duration: 60}
|
||||
- desiredReplicas: 100%
|
||||
pause: {duration: 60}
|
||||
```
|
||||
|
||||
### Batch Release + Traffic Weight
|
||||
```
|
||||
apiVersion: rollouts.kruise.io/v1beta1
|
||||
kind: Rollout
|
||||
metadata:
|
||||
name: rollouts-demo
|
||||
spec:
|
||||
workloadRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: workload-demo
|
||||
strategy:
|
||||
canary:
|
||||
steps:
|
||||
- trafficWeight: 5%
|
||||
desiredReplicas: 2
|
||||
- desiredReplicas: 30%
|
||||
- desiredReplicas: 60%
|
||||
- desiredReplicas: 100%
|
||||
trafficRoutings:
|
||||
- service: service-demo
|
||||
ingress:
|
||||
classType: nginx
|
||||
name: ingress-demo
|
||||
```
|
||||
### Batch Release + Traffic A/B Testing
|
||||
```
|
||||
apiVersion: rollouts.kruise.io/v1beta1
|
||||
kind: Rollout
|
||||
metadata:
|
||||
name: rollouts-demo
|
||||
spec:
|
||||
workloadRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: workload-demo
|
||||
strategy:
|
||||
canary:
|
||||
steps:
|
||||
- trafficMatches:
|
||||
- headers:
|
||||
- name: user-agent
|
||||
type: Exact
|
||||
value: pc
|
||||
desiredReplicas: 2
|
||||
- desiredReplicas: 30%
|
||||
- desiredReplicas: 60%
|
||||
- desiredReplicas: 100%
|
||||
trafficRoutings:
|
||||
- service: service-demo
|
||||
ingress:
|
||||
classType: nginx
|
||||
name: ingress-demo
|
||||
```
|
||||
### End-to-End progressive delivery for microservice application
|
||||
```
|
||||
apiVersion: rollouts.kruise.io/v1alpha1
|
||||
kind: TrafficRouting
|
||||
metadata:
|
||||
name: mse-traffic
|
||||
spec:
|
||||
objectRef:
|
||||
- service: spring-cloud-a
|
||||
ingress:
|
||||
classType: mse
|
||||
name: spring-cloud-a
|
||||
strategy:
|
||||
matches:
|
||||
- headers:
|
||||
- type: Exact
|
||||
name: User-Agent
|
||||
value: xiaoming
|
||||
# http request via ingress, and add header[x-mse-tag]=gray
|
||||
# for mse or istio routing the gray traffic to gray application
|
||||
requestHeaderModifier:
|
||||
set:
|
||||
- name: x-mse-tag
|
||||
value: gray
|
||||
---
|
||||
apiVersion: rollouts.kruise.io/v1alpha1
|
||||
kind: Rollout
|
||||
metadata:
|
||||
name: rollout-a
|
||||
spec:
|
||||
workloadRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: spring-cloud-a
|
||||
strategy:
|
||||
canary:
|
||||
enableExtraWorkloadForCanary: true
|
||||
# Type TrafficRouting's name
|
||||
trafficRoutingRef: mse-traffic
|
||||
steps:
|
||||
- desiredReplicas: 1
|
||||
# patch pod template metadata to canary workload
|
||||
# current only support deployment, and when enableExtraWorkloadForCanary=true
|
||||
patchPodTemplateMetadata:
|
||||
labels:
|
||||
alicloud.service.tag: gray
|
||||
opensergo.io/canary-gray: gray
|
||||
---
|
||||
apiVersion: rollouts.kruise.io/v1alpha1
|
||||
kind: Rollout
|
||||
metadata:
|
||||
name: rollout-a
|
||||
spec:
|
||||
workloadRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: spring-cloud-a
|
||||
strategy:
|
||||
canary:
|
||||
enableExtraWorkloadForCanary: true
|
||||
# Type TrafficRouting's name
|
||||
trafficRoutingRef: mse-traffic
|
||||
steps:
|
||||
- desiredReplicas: 1
|
||||
# patch pod template metadata to canary workload
|
||||
patchPodTemplateMetadata:
|
||||
labels:
|
||||
alicloud.service.tag: gray
|
||||
opensergo.io/canary-gray: gray
|
||||
```
|
114
go.mod
114
go.mod
|
@ -1,81 +1,81 @@
|
|||
module github.com/openkruise/rollouts
|
||||
|
||||
go 1.18
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/evanphx/json-patch v4.11.0+incompatible
|
||||
github.com/evanphx/json-patch v5.6.0+incompatible
|
||||
github.com/onsi/ginkgo v1.16.5
|
||||
github.com/onsi/gomega v1.17.0
|
||||
github.com/openkruise/kruise-api v1.3.0
|
||||
github.com/onsi/gomega v1.27.10
|
||||
github.com/openkruise/kruise-api v1.7.0
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/stretchr/testify v1.9.0
|
||||
github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64
|
||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac
|
||||
golang.org/x/time v0.3.0
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
k8s.io/api v0.22.6
|
||||
k8s.io/apiextensions-apiserver v0.22.6
|
||||
k8s.io/apimachinery v0.22.6
|
||||
k8s.io/apiserver v0.22.6
|
||||
k8s.io/client-go v0.22.6
|
||||
k8s.io/component-base v0.22.6
|
||||
k8s.io/klog/v2 v2.10.0
|
||||
k8s.io/utils v0.0.0-20210820185131-d34e5cb4466e
|
||||
k8s.io/api v0.28.9
|
||||
k8s.io/apiextensions-apiserver v0.28.9
|
||||
k8s.io/apimachinery v0.28.9
|
||||
k8s.io/apiserver v0.28.9
|
||||
k8s.io/client-go v0.28.9
|
||||
k8s.io/component-base v0.28.9
|
||||
k8s.io/klog/v2 v2.120.1
|
||||
k8s.io/utils v0.0.0-20230726121419-3b25d923346b
|
||||
layeh.com/gopher-json v0.0.0-20201124131017-552bb3c4c3bf
|
||||
sigs.k8s.io/controller-runtime v0.10.3
|
||||
sigs.k8s.io/gateway-api v0.4.3
|
||||
sigs.k8s.io/yaml v1.2.0
|
||||
sigs.k8s.io/controller-runtime v0.16.6
|
||||
sigs.k8s.io/gateway-api v0.8.1
|
||||
sigs.k8s.io/yaml v1.4.0
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.81.0 // indirect
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||
github.com/Azure/go-autorest/autorest v0.11.18 // indirect
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.13 // indirect
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/blang/semver v3.5.1+incompatible // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.1 // indirect
|
||||
github.com/form3tech-oss/jwt-go v3.2.3+incompatible // indirect
|
||||
github.com/fsnotify/fsnotify v1.4.9 // indirect
|
||||
github.com/go-logr/logr v0.4.0 // indirect
|
||||
github.com/go-logr/zapr v0.4.0 // indirect
|
||||
github.com/blang/semver/v4 v4.0.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
|
||||
github.com/evanphx/json-patch/v5 v5.6.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/go-logr/logr v1.4.1 // indirect
|
||||
github.com/go-logr/zapr v1.2.4 // 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/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/google/go-cmp v0.5.6 // indirect
|
||||
github.com/google/gofuzz v1.1.0 // indirect
|
||||
github.com/google/uuid v1.1.2 // indirect
|
||||
github.com/googleapis/gnostic v0.5.5 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // 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/uuid v1.6.0 // indirect
|
||||
github.com/imdario/mergo v0.3.12 // indirect
|
||||
github.com/json-iterator/go v1.1.11 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.1 // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/nxadm/tail v1.4.8 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/client_golang v1.11.0 // indirect
|
||||
github.com/prometheus/client_model v0.2.0 // indirect
|
||||
github.com/prometheus/common v0.26.0 // indirect
|
||||
github.com/prometheus/procfs v0.6.0 // indirect
|
||||
go.uber.org/atomic v1.7.0 // indirect
|
||||
go.uber.org/multierr v1.6.0 // indirect
|
||||
go.uber.org/zap v1.19.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 // indirect
|
||||
golang.org/x/net v0.0.0-20211209124913-491a49abca63 // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602 // indirect
|
||||
golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2 // indirect
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect
|
||||
golang.org/x/text v0.3.6 // indirect
|
||||
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/protobuf v1.26.0 // indirect
|
||||
github.com/prometheus/client_golang v1.16.0 // indirect
|
||||
github.com/prometheus/client_model v0.4.0 // indirect
|
||||
github.com/prometheus/common v0.44.0 // indirect
|
||||
github.com/prometheus/procfs v0.10.1 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.25.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect
|
||||
golang.org/x/net v0.24.0 // indirect
|
||||
golang.org/x/oauth2 v0.17.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
|
||||
gomodules.xyz/jsonpatch/v2 v2.4.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/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
|
||||
)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
Copyright 2023 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.
|
||||
|
|
|
@ -0,0 +1,242 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
lua "github.com/yuin/gopher-lua"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
utilpointer "k8s.io/utils/pointer"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"github.com/openkruise/rollouts/api/v1alpha1"
|
||||
"github.com/openkruise/rollouts/api/v1beta1"
|
||||
custom "github.com/openkruise/rollouts/pkg/trafficrouting/network/customNetworkProvider"
|
||||
"github.com/openkruise/rollouts/pkg/util/luamanager"
|
||||
)
|
||||
|
||||
type TestCase struct {
|
||||
Rollout *v1beta1.Rollout `json:"rollout,omitempty"`
|
||||
TrafficRouting *v1alpha1.TrafficRouting `json:"trafficRouting,omitempty"`
|
||||
Original *unstructured.Unstructured `json:"original,omitempty"`
|
||||
Expected []*unstructured.Unstructured `json:"expected,omitempty"`
|
||||
}
|
||||
|
||||
// this function aims to convert testdata to lua object for debugging
|
||||
// run `go run lua.go`, then this program will get all testdata and convert them into lua objects
|
||||
// copy the generated objects to lua scripts and then you can start debugging your lua scripts
|
||||
func main() {
|
||||
err := convertTestCaseToLuaObject()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
func convertTestCaseToLuaObject() error {
|
||||
err := filepath.Walk("./", func(path string, f os.FileInfo, err error) error {
|
||||
if !strings.Contains(path, "trafficRouting.lua") {
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to walk path: %s", err.Error())
|
||||
}
|
||||
dir := filepath.Dir(path)
|
||||
if _, err := os.Stat(filepath.Join(dir, "testdata")); err != nil {
|
||||
fmt.Printf("testdata not found in %s\n", dir)
|
||||
return nil
|
||||
}
|
||||
err = filepath.Walk(filepath.Join(dir, "testdata"), func(path string, info os.FileInfo, err error) error {
|
||||
if !info.IsDir() && filepath.Ext(path) == ".yaml" || filepath.Ext(path) == ".yml" {
|
||||
fmt.Printf("--- walking path: %s ---\n", path)
|
||||
err = objectToTable(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to convert object to table: %s", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to walk path: %s", err.Error())
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to walk path: %s", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// convert a testcase object to lua table for debug
|
||||
func objectToTable(path string) error {
|
||||
dir, file := filepath.Split(path)
|
||||
testCase, err := getLuaTestCase(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get lua testcase: %s", err)
|
||||
}
|
||||
uList := make(map[string]interface{})
|
||||
rollout := testCase.Rollout
|
||||
trafficRouting := testCase.TrafficRouting
|
||||
if rollout != nil {
|
||||
steps := rollout.Spec.Strategy.GetSteps()
|
||||
for i, step := range steps {
|
||||
var weight *int32
|
||||
if step.TrafficRoutingStrategy.Traffic != nil {
|
||||
is := intstr.FromString(*step.TrafficRoutingStrategy.Traffic)
|
||||
weightInt, _ := intstr.GetScaledValueFromIntOrPercent(&is, 100, true)
|
||||
weight = utilpointer.Int32(int32(weightInt))
|
||||
} else {
|
||||
weight = utilpointer.Int32(-1)
|
||||
}
|
||||
var canaryService string
|
||||
stableService := rollout.Spec.Strategy.GetTrafficRouting()[0].Service
|
||||
canaryService = fmt.Sprintf("%s-canary", stableService)
|
||||
data := &custom.LuaData{
|
||||
Data: custom.Data{
|
||||
Labels: testCase.Original.GetLabels(),
|
||||
Annotations: testCase.Original.GetAnnotations(),
|
||||
Spec: testCase.Original.Object["spec"],
|
||||
},
|
||||
Matches: step.TrafficRoutingStrategy.Matches,
|
||||
CanaryWeight: *weight,
|
||||
StableWeight: 100 - *weight,
|
||||
CanaryService: canaryService,
|
||||
StableService: stableService,
|
||||
RequestHeaderModifier: step.TrafficRoutingStrategy.RequestHeaderModifier,
|
||||
}
|
||||
uList[fmt.Sprintf("step_%d", i)] = data
|
||||
}
|
||||
} else if trafficRouting != nil {
|
||||
weight := trafficRouting.Spec.Strategy.Weight
|
||||
if weight == nil {
|
||||
weight = utilpointer.Int32(-1)
|
||||
}
|
||||
var canaryService string
|
||||
stableService := trafficRouting.Spec.ObjectRef[0].Service
|
||||
canaryService = stableService
|
||||
matches := make([]v1beta1.HttpRouteMatch, 0)
|
||||
for _, match := range trafficRouting.Spec.Strategy.Matches {
|
||||
obj := v1beta1.HttpRouteMatch{}
|
||||
obj.Headers = match.Headers
|
||||
matches = append(matches, obj)
|
||||
}
|
||||
data := &custom.LuaData{
|
||||
Data: custom.Data{
|
||||
Labels: testCase.Original.GetLabels(),
|
||||
Annotations: testCase.Original.GetAnnotations(),
|
||||
Spec: testCase.Original.Object["spec"],
|
||||
},
|
||||
Matches: matches,
|
||||
CanaryWeight: *weight,
|
||||
StableWeight: 100 - *weight,
|
||||
CanaryService: canaryService,
|
||||
StableService: stableService,
|
||||
RequestHeaderModifier: trafficRouting.Spec.Strategy.RequestHeaderModifier,
|
||||
}
|
||||
uList["steps_0"] = data
|
||||
} else {
|
||||
return fmt.Errorf("neither rollout nor trafficRouting defined in test case: %s", path)
|
||||
}
|
||||
|
||||
objStr, err := executeLua(uList)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to execute lua: %s", err.Error())
|
||||
}
|
||||
filePath := fmt.Sprintf("%s%s_obj.lua", dir, strings.Split(file, ".")[0])
|
||||
fileStream, err := os.OpenFile(filePath, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0666)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open file: %s", err)
|
||||
}
|
||||
defer fileStream.Close()
|
||||
header := "-- THIS IS GENERATED BY CONVERT_TEST_CASE_TO_LUA_OBJECT.GO FOR DEBUGGING --\n"
|
||||
_, err = io.WriteString(fileStream, header+objStr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to WriteString %s", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getLuaTestCase(path string) (*TestCase, error) {
|
||||
yamlFile, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
luaTestCase := &TestCase{}
|
||||
err = yaml.Unmarshal(yamlFile, luaTestCase)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return luaTestCase, nil
|
||||
}
|
||||
|
||||
func executeLua(steps map[string]interface{}) (string, error) {
|
||||
luaManager := &luamanager.LuaManager{}
|
||||
unObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&steps)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to convert to unstructured: %s", err)
|
||||
}
|
||||
u := &unstructured.Unstructured{Object: unObj}
|
||||
script := `
|
||||
function serialize(obj, isKey)
|
||||
local lua = ""
|
||||
local t = type(obj)
|
||||
if t == "number" then
|
||||
lua = lua .. obj
|
||||
elseif t == "boolean" then
|
||||
lua = lua .. tostring(obj)
|
||||
elseif t == "string" then
|
||||
if isKey then
|
||||
lua = lua .. string.format("%s", obj)
|
||||
else
|
||||
lua = lua .. string.format("%q", obj)
|
||||
end
|
||||
elseif t == "table" then
|
||||
lua = lua .. "{"
|
||||
for k, v in pairs(obj) do
|
||||
if type(k) == "string" then
|
||||
lua = lua .. serialize(k, true) .. "=" .. serialize(v, false) .. ","
|
||||
else
|
||||
lua = lua .. serialize(v, false) .. ","
|
||||
end
|
||||
end
|
||||
local metatable = getmetatable(obj)
|
||||
if metatable ~= nil and type(metatable.__index) == "table" then
|
||||
for k, v in pairs(metatable.__index) do
|
||||
if type(k) == "string" then
|
||||
lua = lua .. serialize(k, true) .. "=" .. serialize(v, false) .. ","
|
||||
else
|
||||
lua = lua .. serialize(v, false) .. ","
|
||||
end
|
||||
end
|
||||
end
|
||||
lua = lua .. "}"
|
||||
elseif t == "nil" then
|
||||
return nil
|
||||
else
|
||||
error("can not serialize a " .. t .. " type.")
|
||||
end
|
||||
return lua
|
||||
end
|
||||
|
||||
function table2string(tablevalue)
|
||||
local stringtable = "steps=" .. serialize(tablevalue)
|
||||
print(stringtable)
|
||||
return stringtable
|
||||
end
|
||||
return table2string(obj)
|
||||
`
|
||||
l, err := luaManager.RunLuaScript(u, script)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to run lua script: %s", err)
|
||||
}
|
||||
returnValue := l.Get(-1)
|
||||
if returnValue.Type() == lua.LTString {
|
||||
return returnValue.String(), nil
|
||||
} else {
|
||||
return "", fmt.Errorf("unexpected lua output type")
|
||||
}
|
||||
}
|
49
lua_configuration/networking.istio.io/DestinationRule/testdata/traffic_routing_with_a_match.yaml
vendored
Normal file
49
lua_configuration/networking.istio.io/DestinationRule/testdata/traffic_routing_with_a_match.yaml
vendored
Normal file
|
@ -0,0 +1,49 @@
|
|||
trafficRouting:
|
||||
apiVersion: rollouts.kruise.io/v1alpha1
|
||||
kind: TrafficRouting
|
||||
metadata:
|
||||
name: tr-demo
|
||||
spec:
|
||||
strategy:
|
||||
matches:
|
||||
- headers:
|
||||
- type: Exact
|
||||
name: version
|
||||
value: canary
|
||||
objectRef:
|
||||
- service: svc-demo
|
||||
customNetworkRefs:
|
||||
- apiVersion: networking.istio.io/v1beta1
|
||||
kind: DestinationRule
|
||||
name: ds-demo
|
||||
original:
|
||||
apiVersion: networking.istio.io/v1beta1
|
||||
kind: DestinationRule
|
||||
metadata:
|
||||
name: ds-demo
|
||||
spec:
|
||||
host: svc-demo
|
||||
trafficPolicy:
|
||||
loadBalancer:
|
||||
simple: ROUND_ROBIN
|
||||
subsets:
|
||||
- labels:
|
||||
version: base
|
||||
name: version-base
|
||||
expected:
|
||||
- apiVersion: networking.istio.io/v1beta1
|
||||
kind: DestinationRule
|
||||
metadata:
|
||||
name: ds-demo
|
||||
spec:
|
||||
host: svc-demo
|
||||
trafficPolicy:
|
||||
loadBalancer:
|
||||
simple: ROUND_ROBIN
|
||||
subsets:
|
||||
- labels:
|
||||
version: base
|
||||
name: version-base
|
||||
- labels:
|
||||
istio.service.tag: gray
|
||||
name: canary
|
|
@ -0,0 +1,8 @@
|
|||
local spec = obj.data.spec
|
||||
local canary = {}
|
||||
canary.labels = {}
|
||||
canary.name = "canary"
|
||||
local podLabelKey = "istio.service.tag"
|
||||
canary.labels[podLabelKey] = "gray"
|
||||
table.insert(spec.subsets, canary)
|
||||
return obj.data
|
126
lua_configuration/networking.istio.io/VirtualService/testdata/rollout_with_three_steps.yaml
vendored
Normal file
126
lua_configuration/networking.istio.io/VirtualService/testdata/rollout_with_three_steps.yaml
vendored
Normal file
|
@ -0,0 +1,126 @@
|
|||
rollout:
|
||||
apiVersion: rollouts.kruise.io/v1beta1
|
||||
kind: Rollout
|
||||
metadata:
|
||||
name: rollouts-demo
|
||||
spec:
|
||||
workloadRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: deploy-demo
|
||||
strategy:
|
||||
canary:
|
||||
steps:
|
||||
- matches:
|
||||
- headers:
|
||||
- type: Exact
|
||||
name: user-agent
|
||||
value: pc
|
||||
- type: RegularExpression
|
||||
name: name
|
||||
value: ".*demo"
|
||||
requestHeaderModifier:
|
||||
set:
|
||||
- name: "header-foo"
|
||||
value: "bar"
|
||||
- matches:
|
||||
- headers:
|
||||
- type: Exact
|
||||
name: user-agent
|
||||
value: pc
|
||||
- headers:
|
||||
- type: RegularExpression
|
||||
name: name
|
||||
value: ".*demo"
|
||||
- traffic: "50%"
|
||||
trafficRoutings:
|
||||
- service: svc-demo
|
||||
customNetworkRefs:
|
||||
- apiVersion: networking.istio.io/v1alpha3
|
||||
kind: VirtualService
|
||||
name: vs-demo
|
||||
original:
|
||||
apiVersion: networking.istio.io/v1alpha3
|
||||
kind: VirtualService
|
||||
metadata:
|
||||
name: vs-demo
|
||||
spec:
|
||||
hosts:
|
||||
- "*"
|
||||
gateways:
|
||||
- nginx-gateway
|
||||
http:
|
||||
- route:
|
||||
- destination:
|
||||
host: svc-demo
|
||||
expected:
|
||||
- apiVersion: networking.istio.io/v1alpha3
|
||||
kind: VirtualService
|
||||
metadata:
|
||||
name: vs-demo
|
||||
spec:
|
||||
hosts:
|
||||
- "*"
|
||||
gateways:
|
||||
- nginx-gateway
|
||||
http:
|
||||
- match:
|
||||
- headers:
|
||||
user-agent:
|
||||
exact: pc
|
||||
name:
|
||||
regex: .*demo
|
||||
headers:
|
||||
request:
|
||||
set:
|
||||
header-foo: bar
|
||||
route:
|
||||
- destination:
|
||||
host: svc-demo-canary
|
||||
- route:
|
||||
- destination:
|
||||
host: svc-demo
|
||||
- apiVersion: networking.istio.io/v1alpha3
|
||||
kind: VirtualService
|
||||
metadata:
|
||||
name: vs-demo
|
||||
spec:
|
||||
hosts:
|
||||
- "*"
|
||||
gateways:
|
||||
- nginx-gateway
|
||||
http:
|
||||
- match:
|
||||
- headers:
|
||||
name:
|
||||
regex: .*demo
|
||||
route:
|
||||
- destination:
|
||||
host: svc-demo-canary
|
||||
- match:
|
||||
- headers:
|
||||
user-agent:
|
||||
exact: pc
|
||||
route:
|
||||
- destination:
|
||||
host: svc-demo-canary
|
||||
- route:
|
||||
- destination:
|
||||
host: svc-demo
|
||||
- apiVersion: networking.istio.io/v1alpha3
|
||||
kind: VirtualService
|
||||
metadata:
|
||||
name: vs-demo
|
||||
spec:
|
||||
hosts:
|
||||
- "*"
|
||||
gateways:
|
||||
- nginx-gateway
|
||||
http:
|
||||
- route:
|
||||
- destination:
|
||||
host: svc-demo
|
||||
weight: 50
|
||||
- destination:
|
||||
host: svc-demo-canary
|
||||
weight: 50
|
69
lua_configuration/networking.istio.io/VirtualService/testdata/traffic_routing_with_a_match.yaml
vendored
Normal file
69
lua_configuration/networking.istio.io/VirtualService/testdata/traffic_routing_with_a_match.yaml
vendored
Normal file
|
@ -0,0 +1,69 @@
|
|||
trafficRouting:
|
||||
apiVersion: rollouts.kruise.io/v1alpha1
|
||||
kind: TrafficRouting
|
||||
metadata:
|
||||
name: tr-demo
|
||||
spec:
|
||||
strategy:
|
||||
matches:
|
||||
- headers:
|
||||
- type: Exact
|
||||
name: user-agent
|
||||
value: pc
|
||||
- type: RegularExpression
|
||||
name: name
|
||||
value: ".*demo"
|
||||
requestHeaderModifier:
|
||||
set:
|
||||
- name: "header-foo"
|
||||
value: "bar"
|
||||
objectRef:
|
||||
- service: svc-demo
|
||||
customNetworkRefs:
|
||||
- apiVersion: networking.istio.io/v1alpha3
|
||||
kind: VirtualService
|
||||
name: vs-demo
|
||||
original:
|
||||
apiVersion: networking.istio.io/v1alpha3
|
||||
kind: VirtualService
|
||||
metadata:
|
||||
name: vs-demo
|
||||
spec:
|
||||
hosts:
|
||||
- "*"
|
||||
gateways:
|
||||
- nginx-gateway
|
||||
http:
|
||||
- route:
|
||||
- destination:
|
||||
host: svc-demo
|
||||
subset: base
|
||||
expected:
|
||||
- apiVersion: networking.istio.io/v1alpha3
|
||||
kind: VirtualService
|
||||
metadata:
|
||||
name: vs-demo
|
||||
spec:
|
||||
hosts:
|
||||
- "*"
|
||||
gateways:
|
||||
- nginx-gateway
|
||||
http:
|
||||
- match:
|
||||
- headers:
|
||||
user-agent:
|
||||
exact: pc
|
||||
name:
|
||||
regex: .*demo
|
||||
headers:
|
||||
request:
|
||||
set:
|
||||
header-foo: bar
|
||||
route:
|
||||
- destination:
|
||||
host: svc-demo
|
||||
subset: canary
|
||||
- route:
|
||||
- destination:
|
||||
host: svc-demo
|
||||
subset: base
|
80
lua_configuration/networking.istio.io/VirtualService/testdata/traffic_routing_with_matches.yaml
vendored
Normal file
80
lua_configuration/networking.istio.io/VirtualService/testdata/traffic_routing_with_matches.yaml
vendored
Normal file
|
@ -0,0 +1,80 @@
|
|||
trafficRouting:
|
||||
apiVersion: rollouts.kruise.io/v1alpha1
|
||||
kind: TrafficRouting
|
||||
metadata:
|
||||
name: tr-demo
|
||||
spec:
|
||||
strategy:
|
||||
matches:
|
||||
- headers:
|
||||
- type: Exact
|
||||
name: user-agent
|
||||
value: pc
|
||||
- headers:
|
||||
- type: RegularExpression
|
||||
name: name
|
||||
value: ".*demo"
|
||||
requestHeaderModifier:
|
||||
set:
|
||||
- name: "header-foo"
|
||||
value: "bar"
|
||||
objectRef:
|
||||
- service: svc-demo
|
||||
customNetworkRefs:
|
||||
- apiVersion: networking.istio.io/v1alpha3
|
||||
kind: VirtualService
|
||||
name: vs-demo
|
||||
original:
|
||||
apiVersion: networking.istio.io/v1alpha3
|
||||
kind: VirtualService
|
||||
metadata:
|
||||
name: vs-demo
|
||||
spec:
|
||||
hosts:
|
||||
- "*"
|
||||
gateways:
|
||||
- nginx-gateway
|
||||
http:
|
||||
- route:
|
||||
- destination:
|
||||
host: svc-demo
|
||||
subset: base
|
||||
expected:
|
||||
- apiVersion: networking.istio.io/v1alpha3
|
||||
kind: VirtualService
|
||||
metadata:
|
||||
name: vs-demo
|
||||
spec:
|
||||
hosts:
|
||||
- "*"
|
||||
gateways:
|
||||
- nginx-gateway
|
||||
http:
|
||||
- match:
|
||||
- headers:
|
||||
name:
|
||||
regex: .*demo
|
||||
headers:
|
||||
request:
|
||||
set:
|
||||
header-foo: bar
|
||||
route:
|
||||
- destination:
|
||||
host: svc-demo
|
||||
subset: canary
|
||||
- match:
|
||||
- headers:
|
||||
user-agent:
|
||||
exact: pc
|
||||
headers:
|
||||
request:
|
||||
set:
|
||||
header-foo: bar
|
||||
route:
|
||||
- destination:
|
||||
host: svc-demo
|
||||
subset: canary
|
||||
- route:
|
||||
- destination:
|
||||
host: svc-demo
|
||||
subset: base
|
50
lua_configuration/networking.istio.io/VirtualService/testdata/traffic_routing_with_weight.yaml
vendored
Normal file
50
lua_configuration/networking.istio.io/VirtualService/testdata/traffic_routing_with_weight.yaml
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
trafficRouting:
|
||||
apiVersion: rollouts.kruise.io/v1alpha1
|
||||
kind: TrafficRouting
|
||||
metadata:
|
||||
name: tr-demo
|
||||
spec:
|
||||
strategy:
|
||||
weight: 50
|
||||
objectRef:
|
||||
- service: svc-demo
|
||||
customNetworkRefs:
|
||||
- apiVersion: networking.istio.io/v1alpha3
|
||||
kind: VirtualService
|
||||
name: vs-demo
|
||||
original:
|
||||
apiVersion: networking.istio.io/v1alpha3
|
||||
kind: VirtualService
|
||||
metadata:
|
||||
name: vs-demo
|
||||
spec:
|
||||
hosts:
|
||||
- "*"
|
||||
gateways:
|
||||
- nginx-gateway
|
||||
http:
|
||||
- route:
|
||||
- destination:
|
||||
host: svc-demo
|
||||
subset: base
|
||||
expected:
|
||||
- apiVersion: networking.istio.io/v1alpha3
|
||||
kind: VirtualService
|
||||
metadata:
|
||||
name: nginx-vs
|
||||
namespace: demo
|
||||
spec:
|
||||
hosts:
|
||||
- "*"
|
||||
gateways:
|
||||
- nginx-gateway
|
||||
http:
|
||||
- route:
|
||||
- destination:
|
||||
host: svc-demo
|
||||
subset: base
|
||||
weight: 50
|
||||
- destination:
|
||||
host: svc-demo
|
||||
subset: canary
|
||||
weight: 50
|
|
@ -0,0 +1,156 @@
|
|||
spec = obj.data.spec
|
||||
|
||||
if obj.canaryWeight == -1 then
|
||||
obj.canaryWeight = 100
|
||||
obj.stableWeight = 0
|
||||
end
|
||||
|
||||
function GetHost(destination)
|
||||
local host = destination.destination.host
|
||||
dot_position = string.find(host, ".", 1, true)
|
||||
if (dot_position) then
|
||||
host = string.sub(host, 1, dot_position - 1)
|
||||
end
|
||||
return host
|
||||
end
|
||||
|
||||
-- find routes of VirtualService with stableService
|
||||
function GetRulesToPatch(spec, stableService, protocol)
|
||||
local matchedRoutes = {}
|
||||
if (spec[protocol] ~= nil) then
|
||||
for _, rule in ipairs(spec[protocol]) do
|
||||
-- skip routes contain matches
|
||||
if (rule.match == nil) then
|
||||
for _, route in ipairs(rule.route) do
|
||||
if GetHost(route) == stableService then
|
||||
table.insert(matchedRoutes, rule)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return matchedRoutes
|
||||
end
|
||||
|
||||
function CalculateWeight(route, stableWeight, n)
|
||||
local weight
|
||||
if (route.weight) then
|
||||
weight = math.floor(route.weight * stableWeight / 100)
|
||||
else
|
||||
weight = math.floor(stableWeight / n)
|
||||
end
|
||||
return weight
|
||||
end
|
||||
|
||||
-- generate routes with matches, insert a rule before other rules, only support http headers, cookies etc.
|
||||
function GenerateRoutesWithMatches(spec, matches, stableService, canaryService, requestHeaderModifier)
|
||||
for _, match in ipairs(matches) do
|
||||
local route = {}
|
||||
route["match"] = {}
|
||||
|
||||
local vsMatch = {}
|
||||
for key, value in pairs(match) do
|
||||
if key == "path" then
|
||||
vsMatch["uri"] = {}
|
||||
local rule = value
|
||||
if rule["type"] == "RegularExpression" then
|
||||
matchType = "regex"
|
||||
elseif rule["type"] == "Exact" then
|
||||
matchType = "exact"
|
||||
elseif rule["type"] == "PathPrefix" then
|
||||
matchType = "prefix"
|
||||
end
|
||||
vsMatch["uri"][matchType] = rule.value
|
||||
else
|
||||
vsMatch[key] = {}
|
||||
for _, rule in ipairs(value) do
|
||||
if rule["type"] == "RegularExpression" then
|
||||
matchType = "regex"
|
||||
elseif rule["type"] == "Exact" then
|
||||
matchType = "exact"
|
||||
elseif rule["type"] == "Prefix" then
|
||||
matchType = "prefix"
|
||||
end
|
||||
if key == "headers" or key == "queryParams" then
|
||||
vsMatch[key][rule["name"]] = {}
|
||||
vsMatch[key][rule["name"]][matchType] = rule.value
|
||||
else
|
||||
vsMatch[key][matchType] = rule.value
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
table.insert(route["match"], vsMatch)
|
||||
if requestHeaderModifier then
|
||||
route["headers"] = {}
|
||||
route["headers"]["request"] = {}
|
||||
for action, headers in pairs(requestHeaderModifier) do
|
||||
if action == "set" or action == "add" then
|
||||
route["headers"]["request"][action] = {}
|
||||
for _, header in ipairs(headers) do
|
||||
route["headers"]["request"][action][header["name"]] = header["value"]
|
||||
end
|
||||
elseif action == "remove" then
|
||||
route["headers"]["request"]["remove"] = {}
|
||||
for _, rHeader in ipairs(headers) do
|
||||
table.insert(route["headers"]["request"]["remove"], rHeader)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
route.route = {
|
||||
{
|
||||
destination = {}
|
||||
}
|
||||
}
|
||||
-- stableService == canaryService indicates DestinationRule exists and subset is set to be canary by default
|
||||
if stableService == canaryService then
|
||||
route.route[1].destination.host = stableService
|
||||
route.route[1].destination.subset = "canary"
|
||||
else
|
||||
route.route[1].destination.host = canaryService
|
||||
end
|
||||
table.insert(spec.http, 1, route)
|
||||
end
|
||||
end
|
||||
|
||||
-- generate routes without matches, change every rule whose host is stableService
|
||||
function GenerateRoutes(spec, stableService, canaryService, stableWeight, canaryWeight, protocol)
|
||||
local matchedRules = GetRulesToPatch(spec, stableService, protocol)
|
||||
for _, rule in ipairs(matchedRules) do
|
||||
local canary
|
||||
if stableService ~= canaryService then
|
||||
canary = {
|
||||
destination = {
|
||||
host = canaryService,
|
||||
},
|
||||
weight = canaryWeight,
|
||||
}
|
||||
else
|
||||
canary = {
|
||||
destination = {
|
||||
host = stableService,
|
||||
subset = "canary",
|
||||
},
|
||||
weight = canaryWeight,
|
||||
}
|
||||
end
|
||||
|
||||
-- incase there are multiple versions traffic already, do a for-loop
|
||||
for _, route in ipairs(rule.route) do
|
||||
-- update stable service weight
|
||||
route.weight = CalculateWeight(route, stableWeight, #rule.route)
|
||||
end
|
||||
table.insert(rule.route, canary)
|
||||
end
|
||||
end
|
||||
|
||||
if (obj.matches and next(obj.matches) ~= nil)
|
||||
then
|
||||
GenerateRoutesWithMatches(spec, obj.matches, obj.stableService, obj.canaryService, obj.requestHeaderModifier)
|
||||
else
|
||||
GenerateRoutes(spec, obj.stableService, obj.canaryService, obj.stableWeight, obj.canaryWeight, "http")
|
||||
GenerateRoutes(spec, obj.stableService, obj.canaryService, obj.stableWeight, obj.canaryWeight, "tcp")
|
||||
GenerateRoutes(spec, obj.stableService, obj.canaryService, obj.stableWeight, obj.canaryWeight, "tls")
|
||||
end
|
||||
return obj.data
|
|
@ -10,6 +10,10 @@ annotations["nginx.ingress.kubernetes.io/canary-by-cookie"] = nil
|
|||
annotations["nginx.ingress.kubernetes.io/canary-by-header"] = nil
|
||||
annotations["nginx.ingress.kubernetes.io/canary-by-header-pattern"] = nil
|
||||
annotations["nginx.ingress.kubernetes.io/canary-by-header-value"] = nil
|
||||
-- MSE extended annotations
|
||||
annotations["mse.ingress.kubernetes.io/canary-by-query"] = nil
|
||||
annotations["mse.ingress.kubernetes.io/canary-by-query-pattern"] = nil
|
||||
annotations["mse.ingress.kubernetes.io/canary-by-query-value"] = nil
|
||||
annotations["nginx.ingress.kubernetes.io/canary-weight"] = nil
|
||||
if ( obj.weight ~= "-1" )
|
||||
then
|
||||
|
@ -33,18 +37,30 @@ then
|
|||
return annotations
|
||||
end
|
||||
for _,match in ipairs(obj.matches) do
|
||||
header = match.headers[1]
|
||||
if ( header.name == "canary-by-cookie" )
|
||||
then
|
||||
annotations["nginx.ingress.kubernetes.io/canary-by-cookie"] = header.value
|
||||
else
|
||||
annotations["nginx.ingress.kubernetes.io/canary-by-header"] = header.name
|
||||
if ( header.type == "RegularExpression" )
|
||||
if match.headers and next(match.headers) ~= nil then
|
||||
header = match.headers[1]
|
||||
if ( header.name == "canary-by-cookie" )
|
||||
then
|
||||
annotations["nginx.ingress.kubernetes.io/canary-by-header-pattern"] = header.value
|
||||
annotations["nginx.ingress.kubernetes.io/canary-by-cookie"] = header.value
|
||||
else
|
||||
annotations["nginx.ingress.kubernetes.io/canary-by-header-value"] = header.value
|
||||
annotations["nginx.ingress.kubernetes.io/canary-by-header"] = header.name
|
||||
if ( header.type == "RegularExpression" )
|
||||
then
|
||||
annotations["nginx.ingress.kubernetes.io/canary-by-header-pattern"] = header.value
|
||||
else
|
||||
annotations["nginx.ingress.kubernetes.io/canary-by-header-value"] = header.value
|
||||
end
|
||||
end
|
||||
end
|
||||
if match.queryParams and next(match.queryParams) ~= nil then
|
||||
queryParam = match.queryParams[1]
|
||||
annotations["nginx.ingress.kubernetes.io/canary-by-query"] = queryParam.name
|
||||
if ( queryParam.type == "RegularExpression" )
|
||||
then
|
||||
annotations["nginx.ingress.kubernetes.io/canary-by-query-pattern"] = queryParam.value
|
||||
else
|
||||
annotations["nginx.ingress.kubernetes.io/canary-by-query-value"] = queryParam.value
|
||||
end
|
||||
end
|
||||
end
|
||||
return annotations
|
||||
return annotations
|
|
@ -26,19 +26,21 @@ end
|
|||
-- headers & cookie apis
|
||||
-- traverse matches
|
||||
for _,match in ipairs(obj.matches) do
|
||||
local header = match.headers[1]
|
||||
-- cookie
|
||||
if ( header.name == "canary-by-cookie" )
|
||||
then
|
||||
annotations["nginx.ingress.kubernetes.io/canary-by-cookie"] = header.value
|
||||
else
|
||||
annotations["nginx.ingress.kubernetes.io/canary-by-header"] = header.name
|
||||
-- if regular expression
|
||||
if ( header.type == "RegularExpression" )
|
||||
if match.headers and next(match.headers) ~= nil then
|
||||
local header = match.headers[1]
|
||||
-- cookie
|
||||
if ( header.name == "canary-by-cookie" )
|
||||
then
|
||||
annotations["nginx.ingress.kubernetes.io/canary-by-header-pattern"] = header.value
|
||||
annotations["nginx.ingress.kubernetes.io/canary-by-cookie"] = header.value
|
||||
else
|
||||
annotations["nginx.ingress.kubernetes.io/canary-by-header-value"] = header.value
|
||||
annotations["nginx.ingress.kubernetes.io/canary-by-header"] = header.name
|
||||
-- if regular expression
|
||||
if ( header.type == "RegularExpression" )
|
||||
then
|
||||
annotations["nginx.ingress.kubernetes.io/canary-by-header-pattern"] = header.value
|
||||
else
|
||||
annotations["nginx.ingress.kubernetes.io/canary-by-header-value"] = header.value
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
43
main.go
43
main.go
|
@ -20,17 +20,10 @@ import (
|
|||
"flag"
|
||||
"os"
|
||||
|
||||
webhookutil "github.com/openkruise/rollouts/pkg/webhook/util"
|
||||
|
||||
kruisev1aplphal1 "github.com/openkruise/kruise-api/apps/v1alpha1"
|
||||
kruisev1beta1 "github.com/openkruise/kruise-api/apps/v1beta1"
|
||||
rolloutsv1alpha1 "github.com/openkruise/rollouts/api/v1alpha1"
|
||||
br "github.com/openkruise/rollouts/pkg/controller/batchrelease"
|
||||
"github.com/openkruise/rollouts/pkg/controller/deployment"
|
||||
"github.com/openkruise/rollouts/pkg/controller/rollout"
|
||||
"github.com/openkruise/rollouts/pkg/controller/rollouthistory"
|
||||
"github.com/openkruise/rollouts/pkg/controller/trafficrouting"
|
||||
utilclient "github.com/openkruise/rollouts/pkg/util/client"
|
||||
utilfeature "github.com/openkruise/rollouts/pkg/util/feature"
|
||||
"github.com/openkruise/rollouts/pkg/webhook"
|
||||
"github.com/spf13/pflag"
|
||||
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
@ -40,7 +33,19 @@ import (
|
|||
"k8s.io/klog/v2/klogr"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/healthz"
|
||||
gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
|
||||
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
|
||||
ctrlwebhook "sigs.k8s.io/controller-runtime/pkg/webhook"
|
||||
gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1"
|
||||
|
||||
rolloutapi "github.com/openkruise/rollouts/api"
|
||||
br "github.com/openkruise/rollouts/pkg/controller/batchrelease"
|
||||
"github.com/openkruise/rollouts/pkg/controller/deployment"
|
||||
"github.com/openkruise/rollouts/pkg/controller/rollout"
|
||||
"github.com/openkruise/rollouts/pkg/controller/rollouthistory"
|
||||
"github.com/openkruise/rollouts/pkg/controller/trafficrouting"
|
||||
utilclient "github.com/openkruise/rollouts/pkg/util/client"
|
||||
utilfeature "github.com/openkruise/rollouts/pkg/util/feature"
|
||||
"github.com/openkruise/rollouts/pkg/webhook"
|
||||
|
||||
// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
|
||||
// to ensure that exec-entrypoint and run can make use of them.
|
||||
|
@ -57,8 +62,8 @@ func init() {
|
|||
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
|
||||
utilruntime.Must(kruisev1aplphal1.AddToScheme(scheme))
|
||||
utilruntime.Must(kruisev1beta1.AddToScheme(scheme))
|
||||
utilruntime.Must(rolloutsv1alpha1.AddToScheme(scheme))
|
||||
utilruntime.Must(gatewayv1alpha2.AddToScheme(scheme))
|
||||
utilruntime.Must(rolloutapi.AddToScheme(scheme))
|
||||
utilruntime.Must(gatewayv1beta1.AddToScheme(scheme))
|
||||
utilruntime.Must(admissionregistrationv1.AddToScheme(scheme))
|
||||
//+kubebuilder:scaffold:scheme
|
||||
}
|
||||
|
@ -89,13 +94,19 @@ func main() {
|
|||
}
|
||||
|
||||
mgr, err := ctrl.NewManager(cfg, ctrl.Options{
|
||||
Scheme: scheme,
|
||||
MetricsBindAddress: metricsAddr,
|
||||
Port: 9443,
|
||||
Scheme: scheme,
|
||||
Metrics: metricsserver.Options{
|
||||
BindAddress: metricsAddr,
|
||||
},
|
||||
WebhookServer: ctrlwebhook.NewServer(ctrlwebhook.Options{
|
||||
Host: "0.0.0.0",
|
||||
Port: webhookutil.GetPort(),
|
||||
CertDir: webhookutil.GetCertDir(),
|
||||
}),
|
||||
HealthProbeBindAddress: probeAddr,
|
||||
LeaderElection: enableLeaderElection,
|
||||
LeaderElectionID: "71ddec2c.kruise.io",
|
||||
NewClient: utilclient.NewClient,
|
||||
NewCache: utilclient.NewCache,
|
||||
})
|
||||
if err != nil {
|
||||
setupLog.Error(err, "unable to start manager")
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package versioned
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package has the automatically generated clientset.
|
||||
package versioned
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package has the automatically generated fake clientset.
|
||||
package fake
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package contains the scheme of the automatically generated clientset.
|
||||
package scheme
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package scheme
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package has the automatically generated typed clients.
|
||||
package v1beta1
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// Package fake has the automatically generated clients.
|
||||
package fake
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
|
@ -24,8 +24,8 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/openkruise/rollouts/api/v1alpha1"
|
||||
"github.com/openkruise/rollouts/pkg/util"
|
||||
"sigs.k8s.io/controller-runtime/pkg/cache"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
@ -43,6 +43,9 @@ import (
|
|||
"sigs.k8s.io/controller-runtime/pkg/predicate"
|
||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||
"sigs.k8s.io/controller-runtime/pkg/source"
|
||||
|
||||
"github.com/openkruise/rollouts/api/v1beta1"
|
||||
"github.com/openkruise/rollouts/pkg/util"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -80,6 +83,7 @@ func newReconciler(mgr manager.Manager) reconcile.Reconciler {
|
|||
Client: cli,
|
||||
Scheme: mgr.GetScheme(),
|
||||
recorder: recorder,
|
||||
cache: mgr.GetCache(),
|
||||
executor: NewReleasePlanExecutor(cli, recorder),
|
||||
}
|
||||
}
|
||||
|
@ -94,10 +98,10 @@ func add(mgr manager.Manager, r reconcile.Reconciler) error {
|
|||
}
|
||||
|
||||
// Watch for changes to BatchRelease
|
||||
err = c.Watch(&source.Kind{Type: &v1alpha1.BatchRelease{}}, &handler.EnqueueRequestForObject{}, predicate.Funcs{
|
||||
err = c.Watch(source.Kind(mgr.GetCache(), &v1beta1.BatchRelease{}), &handler.EnqueueRequestForObject{}, predicate.Funcs{
|
||||
UpdateFunc: func(e event.UpdateEvent) bool {
|
||||
oldObject := e.ObjectOld.(*v1alpha1.BatchRelease)
|
||||
newObject := e.ObjectNew.(*v1alpha1.BatchRelease)
|
||||
oldObject := e.ObjectOld.(*v1beta1.BatchRelease)
|
||||
newObject := e.ObjectNew.(*v1beta1.BatchRelease)
|
||||
if oldObject.Generation != newObject.Generation || newObject.DeletionTimestamp != nil {
|
||||
klog.V(3).Infof("Observed updated Spec for BatchRelease: %s/%s", newObject.Namespace, newObject.Name)
|
||||
return true
|
||||
|
@ -113,14 +117,14 @@ func add(mgr manager.Manager, r reconcile.Reconciler) error {
|
|||
return err
|
||||
}
|
||||
|
||||
err = c.Watch(&source.Kind{Type: &corev1.Pod{}}, &podEventHandler{Reader: mgr.GetCache()})
|
||||
err = c.Watch(source.Kind(mgr.GetCache(), &corev1.Pod{}), &podEventHandler{Reader: mgr.GetCache()})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
runtimeController = c
|
||||
workloadHandler = &workloadEventHandler{Reader: mgr.GetCache()}
|
||||
return util.AddWorkloadWatcher(c, workloadHandler)
|
||||
return util.AddWorkloadWatcher(mgr.GetCache(), c, workloadHandler)
|
||||
}
|
||||
|
||||
var _ reconcile.Reconciler = &BatchReleaseReconciler{}
|
||||
|
@ -128,6 +132,7 @@ var _ reconcile.Reconciler = &BatchReleaseReconciler{}
|
|||
// BatchReleaseReconciler reconciles a BatchRelease object
|
||||
type BatchReleaseReconciler struct {
|
||||
client.Client
|
||||
cache cache.Cache
|
||||
Scheme *runtime.Scheme
|
||||
recorder record.EventRecorder
|
||||
executor *Executor
|
||||
|
@ -148,11 +153,12 @@ type BatchReleaseReconciler struct {
|
|||
// +kubebuilder:rbac:groups=apps.kruise.io,resources=statefulsets/status,verbs=get;update;patch
|
||||
// +kubebuilder:rbac:groups=apps.kruise.io,resources=daemonsets,verbs=get;list;watch;update;patch
|
||||
// +kubebuilder:rbac:groups=apps.kruise.io,resources=daemonsets/status,verbs=get;update;patch
|
||||
// +kubebuilder:rbac:groups=autoscaling,resources=horizontalpodautoscalers,verbs=get;list;watch;update;patch
|
||||
|
||||
// Reconcile reads that state of the cluster for a Rollout object and makes changes based on the state read
|
||||
// and what is in the Rollout.Spec
|
||||
func (r *BatchReleaseReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
|
||||
release := new(v1alpha1.BatchRelease)
|
||||
release := new(v1beta1.BatchRelease)
|
||||
err := r.Get(context.TODO(), req.NamespacedName, release)
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
|
@ -167,11 +173,11 @@ func (r *BatchReleaseReconciler) Reconcile(ctx context.Context, req ctrl.Request
|
|||
klog.Infof("Begin to reconcile BatchRelease(%v/%v), release-phase: %v", release.Namespace, release.Name, release.Status.Phase)
|
||||
|
||||
// If workload watcher does not exist, then add the watcher dynamically
|
||||
workloadRef := release.Spec.TargetRef.WorkloadRef
|
||||
workloadGVK := util.GetGVKFrom(workloadRef)
|
||||
workloadRef := release.Spec.WorkloadRef
|
||||
workloadGVK := util.GetGVKFrom(&workloadRef)
|
||||
_, exists := watchedWorkload.Load(workloadGVK.String())
|
||||
if workloadRef != nil && !exists {
|
||||
succeeded, err := util.AddWatcherDynamically(runtimeController, workloadHandler, workloadGVK)
|
||||
if !exists {
|
||||
succeeded, err := util.AddWatcherDynamically(r.cache, runtimeController, workloadHandler, workloadGVK)
|
||||
if err != nil {
|
||||
return ctrl.Result{}, err
|
||||
} else if succeeded {
|
||||
|
@ -216,7 +222,7 @@ func (r *BatchReleaseReconciler) Reconcile(ctx context.Context, req ctrl.Request
|
|||
}
|
||||
|
||||
// updateStatus update BatchRelease status to newStatus
|
||||
func (r *BatchReleaseReconciler) updateStatus(release *v1alpha1.BatchRelease, newStatus *v1alpha1.BatchReleaseStatus) error {
|
||||
func (r *BatchReleaseReconciler) updateStatus(release *v1beta1.BatchRelease, newStatus *v1beta1.BatchReleaseStatus) error {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
|
@ -234,7 +240,7 @@ func (r *BatchReleaseReconciler) updateStatus(release *v1alpha1.BatchRelease, ne
|
|||
objectKey := client.ObjectKeyFromObject(release)
|
||||
if !reflect.DeepEqual(release.Status, *newStatus) {
|
||||
err = retry.RetryOnConflict(retry.DefaultBackoff, func() error {
|
||||
clone := &v1alpha1.BatchRelease{}
|
||||
clone := &v1beta1.BatchRelease{}
|
||||
getErr := r.Get(context.TODO(), objectKey, clone)
|
||||
if getErr != nil {
|
||||
return getErr
|
||||
|
@ -247,7 +253,7 @@ func (r *BatchReleaseReconciler) updateStatus(release *v1alpha1.BatchRelease, ne
|
|||
}
|
||||
|
||||
// handleFinalizer will remove finalizer in finalized phase and add finalizer in the other phases.
|
||||
func (r *BatchReleaseReconciler) handleFinalizer(release *v1alpha1.BatchRelease) (bool, error) {
|
||||
func (r *BatchReleaseReconciler) handleFinalizer(release *v1beta1.BatchRelease) (bool, error) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
|
@ -257,7 +263,7 @@ func (r *BatchReleaseReconciler) handleFinalizer(release *v1alpha1.BatchRelease)
|
|||
|
||||
// remove the release finalizer if it needs
|
||||
if !release.DeletionTimestamp.IsZero() &&
|
||||
release.Status.Phase == v1alpha1.RolloutPhaseCompleted &&
|
||||
release.Status.Phase == v1beta1.RolloutPhaseCompleted &&
|
||||
controllerutil.ContainsFinalizer(release, ReleaseFinalizer) {
|
||||
err = util.UpdateFinalizer(r.Client, release, util.RemoveFinalizerOpType, ReleaseFinalizer)
|
||||
if client.IgnoreNotFound(err) != nil {
|
||||
|
|
|
@ -27,8 +27,6 @@ import (
|
|||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
kruiseappsv1alpha1 "github.com/openkruise/kruise-api/apps/v1alpha1"
|
||||
"github.com/openkruise/rollouts/api/v1alpha1"
|
||||
"github.com/openkruise/rollouts/pkg/util"
|
||||
apps "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
@ -43,15 +41,19 @@ import (
|
|||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client/fake"
|
||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||
|
||||
rolloutapi "github.com/openkruise/rollouts/api"
|
||||
"github.com/openkruise/rollouts/api/v1beta1"
|
||||
"github.com/openkruise/rollouts/pkg/util"
|
||||
)
|
||||
|
||||
const TIME_LAYOUT = "2006-01-02 15:04:05"
|
||||
|
||||
var (
|
||||
scheme *runtime.Scheme
|
||||
releaseDeploy = &v1alpha1.BatchRelease{
|
||||
releaseDeploy = &v1beta1.BatchRelease{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: v1alpha1.GroupVersion.String(),
|
||||
APIVersion: v1beta1.GroupVersion.String(),
|
||||
Kind: "BatchRelease",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
|
@ -59,17 +61,16 @@ var (
|
|||
Namespace: "application",
|
||||
UID: types.UID("87076677"),
|
||||
},
|
||||
Spec: v1alpha1.BatchReleaseSpec{
|
||||
TargetRef: v1alpha1.ObjectRef{
|
||||
WorkloadRef: &v1alpha1.WorkloadRef{
|
||||
APIVersion: "apps/v1",
|
||||
Kind: "Deployment",
|
||||
Name: "sample",
|
||||
},
|
||||
Spec: v1beta1.BatchReleaseSpec{
|
||||
WorkloadRef: v1beta1.ObjectRef{
|
||||
APIVersion: "apps/v1",
|
||||
Kind: "Deployment",
|
||||
Name: "sample",
|
||||
},
|
||||
ReleasePlan: v1alpha1.ReleasePlan{
|
||||
ReleasePlan: v1beta1.ReleasePlan{
|
||||
RollingStyle: v1beta1.CanaryRollingStyle,
|
||||
BatchPartition: pointer.Int32(0),
|
||||
Batches: []v1alpha1.ReleaseBatch{
|
||||
Batches: []v1beta1.ReleaseBatch{
|
||||
{
|
||||
CanaryReplicas: intstr.FromString("10%"),
|
||||
},
|
||||
|
@ -100,7 +101,7 @@ var (
|
|||
},
|
||||
},
|
||||
Spec: apps.DeploymentSpec{
|
||||
Replicas: pointer.Int32Ptr(100),
|
||||
Replicas: pointer.Int32(100),
|
||||
Strategy: apps.DeploymentStrategy{
|
||||
Type: apps.RollingUpdateDeploymentStrategyType,
|
||||
RollingUpdate: &apps.RollingUpdateDeployment{
|
||||
|
@ -129,9 +130,9 @@ var (
|
|||
)
|
||||
|
||||
var (
|
||||
releaseClone = &v1alpha1.BatchRelease{
|
||||
releaseClone = &v1beta1.BatchRelease{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: v1alpha1.GroupVersion.String(),
|
||||
APIVersion: v1beta1.GroupVersion.String(),
|
||||
Kind: "BatchRelease",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
|
@ -139,17 +140,16 @@ var (
|
|||
Namespace: "application",
|
||||
UID: types.UID("87076677"),
|
||||
},
|
||||
Spec: v1alpha1.BatchReleaseSpec{
|
||||
TargetRef: v1alpha1.ObjectRef{
|
||||
WorkloadRef: &v1alpha1.WorkloadRef{
|
||||
APIVersion: "apps.kruise.io/v1alpha1",
|
||||
Kind: "CloneSet",
|
||||
Name: "sample",
|
||||
},
|
||||
Spec: v1beta1.BatchReleaseSpec{
|
||||
WorkloadRef: v1beta1.ObjectRef{
|
||||
APIVersion: "apps.kruise.io/v1alpha1",
|
||||
Kind: "CloneSet",
|
||||
Name: "sample",
|
||||
},
|
||||
ReleasePlan: v1alpha1.ReleasePlan{
|
||||
BatchPartition: pointer.Int32Ptr(0),
|
||||
Batches: []v1alpha1.ReleaseBatch{
|
||||
ReleasePlan: v1beta1.ReleasePlan{
|
||||
BatchPartition: pointer.Int32(0),
|
||||
RollingStyle: v1beta1.PartitionRollingStyle,
|
||||
Batches: []v1beta1.ReleaseBatch{
|
||||
{
|
||||
CanaryReplicas: intstr.FromString("10%"),
|
||||
},
|
||||
|
@ -179,7 +179,7 @@ var (
|
|||
},
|
||||
},
|
||||
Spec: kruiseappsv1alpha1.CloneSetSpec{
|
||||
Replicas: pointer.Int32Ptr(100),
|
||||
Replicas: pointer.Int32(100),
|
||||
UpdateStrategy: kruiseappsv1alpha1.CloneSetUpdateStrategy{
|
||||
Partition: &intstr.IntOrString{Type: intstr.Int, IntVal: int32(1)},
|
||||
MaxSurge: &intstr.IntOrString{Type: intstr.Int, IntVal: int32(2)},
|
||||
|
@ -209,7 +209,7 @@ var (
|
|||
func init() {
|
||||
scheme = runtime.NewScheme()
|
||||
apimachineryruntime.Must(apps.AddToScheme(scheme))
|
||||
apimachineryruntime.Must(v1alpha1.AddToScheme(scheme))
|
||||
apimachineryruntime.Must(rolloutapi.AddToScheme(scheme))
|
||||
apimachineryruntime.Must(kruiseappsv1alpha1.AddToScheme(scheme))
|
||||
|
||||
controlInfo, _ := json.Marshal(metav1.NewControllerRef(releaseDeploy, releaseDeploy.GroupVersionKind()))
|
||||
|
@ -232,13 +232,13 @@ func TestReconcile_CloneSet(t *testing.T) {
|
|||
GetRelease func() client.Object
|
||||
GetCloneSet func() []client.Object
|
||||
ExpectedBatch int32
|
||||
ExpectedPhase v1alpha1.RolloutPhase
|
||||
ExpectedState v1alpha1.BatchReleaseBatchStateType
|
||||
ExpectedPhase v1beta1.RolloutPhase
|
||||
ExpectedState v1beta1.BatchReleaseBatchStateType
|
||||
}{
|
||||
{
|
||||
Name: "Preparing, Input-Phase=Preparing, Output-Phase=Progressing",
|
||||
GetRelease: func() client.Object {
|
||||
release := setPhase(releaseClone, v1alpha1.RolloutPhasePreparing)
|
||||
release := setPhase(releaseClone, v1beta1.RolloutPhasePreparing)
|
||||
stableTemplate := stableClone.Spec.Template.DeepCopy()
|
||||
canaryTemplate := stableClone.Spec.Template.DeepCopy()
|
||||
stableTemplate.Spec.Containers = containers("v1")
|
||||
|
@ -254,12 +254,12 @@ func TestReconcile_CloneSet(t *testing.T) {
|
|||
canary,
|
||||
}
|
||||
},
|
||||
ExpectedPhase: v1alpha1.RolloutPhaseProgressing,
|
||||
ExpectedPhase: v1beta1.RolloutPhaseProgressing,
|
||||
},
|
||||
{
|
||||
Name: "Progressing, stage=0, Input-State=Upgrade, Output-State=Verify",
|
||||
GetRelease: func() client.Object {
|
||||
release := setState(releaseClone, v1alpha1.UpgradingBatchState)
|
||||
release := setState(releaseClone, v1beta1.UpgradingBatchState)
|
||||
stableTemplate := stableClone.Spec.Template.DeepCopy()
|
||||
canaryTemplate := stableClone.Spec.Template.DeepCopy()
|
||||
stableTemplate.Spec.Containers = containers("v1")
|
||||
|
@ -275,13 +275,13 @@ func TestReconcile_CloneSet(t *testing.T) {
|
|||
canary,
|
||||
}
|
||||
},
|
||||
ExpectedPhase: v1alpha1.RolloutPhaseProgressing,
|
||||
ExpectedState: v1alpha1.VerifyingBatchState,
|
||||
ExpectedPhase: v1beta1.RolloutPhaseProgressing,
|
||||
ExpectedState: v1beta1.VerifyingBatchState,
|
||||
},
|
||||
{
|
||||
Name: "Progressing, stage=0, Input-State=Upgrade, Output-State=Verify",
|
||||
GetRelease: func() client.Object {
|
||||
release := setState(releaseClone, v1alpha1.UpgradingBatchState)
|
||||
release := setState(releaseClone, v1beta1.UpgradingBatchState)
|
||||
stableTemplate := stableClone.Spec.Template.DeepCopy()
|
||||
canaryTemplate := stableClone.Spec.Template.DeepCopy()
|
||||
stableTemplate.Spec.Containers = containers("v1")
|
||||
|
@ -297,13 +297,13 @@ func TestReconcile_CloneSet(t *testing.T) {
|
|||
canary,
|
||||
}
|
||||
},
|
||||
ExpectedPhase: v1alpha1.RolloutPhaseProgressing,
|
||||
ExpectedState: v1alpha1.VerifyingBatchState,
|
||||
ExpectedPhase: v1beta1.RolloutPhaseProgressing,
|
||||
ExpectedState: v1beta1.VerifyingBatchState,
|
||||
},
|
||||
{
|
||||
Name: "Progressing, stage=0, Input-State=Verify, Output-State=BatchReady",
|
||||
GetRelease: func() client.Object {
|
||||
release := setState(releaseClone, v1alpha1.VerifyingBatchState)
|
||||
release := setState(releaseClone, v1beta1.VerifyingBatchState)
|
||||
stableTemplate := stableClone.Spec.Template.DeepCopy()
|
||||
canaryTemplate := stableClone.Spec.Template.DeepCopy()
|
||||
stableTemplate.Spec.Containers = containers("v1")
|
||||
|
@ -321,13 +321,13 @@ func TestReconcile_CloneSet(t *testing.T) {
|
|||
canary,
|
||||
}
|
||||
},
|
||||
ExpectedPhase: v1alpha1.RolloutPhaseProgressing,
|
||||
ExpectedState: v1alpha1.ReadyBatchState,
|
||||
ExpectedPhase: v1beta1.RolloutPhaseProgressing,
|
||||
ExpectedState: v1beta1.ReadyBatchState,
|
||||
},
|
||||
{
|
||||
Name: "Progressing, stage=0->1, Input-State=BatchReady, Output-State=Upgrade",
|
||||
GetRelease: func() client.Object {
|
||||
release := setState(releaseClone, v1alpha1.ReadyBatchState)
|
||||
release := setState(releaseClone, v1beta1.ReadyBatchState)
|
||||
release.Status.CanaryStatus.BatchReadyTime = getOldTime()
|
||||
stableTemplate := stableClone.Spec.Template.DeepCopy()
|
||||
canaryTemplate := stableClone.Spec.Template.DeepCopy()
|
||||
|
@ -347,14 +347,14 @@ func TestReconcile_CloneSet(t *testing.T) {
|
|||
canary,
|
||||
}
|
||||
},
|
||||
ExpectedPhase: v1alpha1.RolloutPhaseProgressing,
|
||||
ExpectedState: v1alpha1.UpgradingBatchState,
|
||||
ExpectedPhase: v1beta1.RolloutPhaseProgressing,
|
||||
ExpectedState: v1beta1.UpgradingBatchState,
|
||||
ExpectedBatch: 1,
|
||||
},
|
||||
{
|
||||
Name: "Progressing, stage=0->1, Input-State=BatchReady, Output-State=BatchReady",
|
||||
GetRelease: func() client.Object {
|
||||
release := setState(releaseClone, v1alpha1.ReadyBatchState)
|
||||
release := setState(releaseClone, v1beta1.ReadyBatchState)
|
||||
now := metav1.Now()
|
||||
release.Status.CanaryStatus.BatchReadyTime = &now
|
||||
stableTemplate := stableClone.Spec.Template.DeepCopy()
|
||||
|
@ -374,13 +374,13 @@ func TestReconcile_CloneSet(t *testing.T) {
|
|||
canary,
|
||||
}
|
||||
},
|
||||
ExpectedPhase: v1alpha1.RolloutPhaseProgressing,
|
||||
ExpectedState: v1alpha1.ReadyBatchState,
|
||||
ExpectedPhase: v1beta1.RolloutPhaseProgressing,
|
||||
ExpectedState: v1beta1.ReadyBatchState,
|
||||
},
|
||||
{
|
||||
Name: "Special Case: Scaling, Input-State=BatchReady, Output-State=Upgrade",
|
||||
GetRelease: func() client.Object {
|
||||
release := setState(releaseClone, v1alpha1.ReadyBatchState)
|
||||
release := setState(releaseClone, v1beta1.ReadyBatchState)
|
||||
now := metav1.Now()
|
||||
release.Status.CanaryStatus.BatchReadyTime = &now
|
||||
stableTemplate := stableClone.Spec.Template.DeepCopy()
|
||||
|
@ -395,19 +395,19 @@ func TestReconcile_CloneSet(t *testing.T) {
|
|||
},
|
||||
GetCloneSet: func() []client.Object {
|
||||
stable := getStableWithReady(stableClone, "v2").(*kruiseappsv1alpha1.CloneSet)
|
||||
stable.Spec.Replicas = pointer.Int32Ptr(200)
|
||||
stable.Spec.Replicas = pointer.Int32(200)
|
||||
canary := getCanaryWithStage(stable, "v2", 0, true)
|
||||
return []client.Object{
|
||||
canary,
|
||||
}
|
||||
},
|
||||
ExpectedPhase: v1alpha1.RolloutPhaseProgressing,
|
||||
ExpectedState: v1alpha1.UpgradingBatchState,
|
||||
ExpectedPhase: v1beta1.RolloutPhaseProgressing,
|
||||
ExpectedState: v1beta1.UpgradingBatchState,
|
||||
},
|
||||
{
|
||||
Name: `Special Case: RollBack, Input-Phase=Progressing, Output-Phase=Progressing`,
|
||||
GetRelease: func() client.Object {
|
||||
release := setState(releaseClone, v1alpha1.ReadyBatchState)
|
||||
release := setState(releaseClone, v1beta1.ReadyBatchState)
|
||||
now := metav1.Now()
|
||||
release.Status.CanaryStatus.BatchReadyTime = &now
|
||||
stableTemplate := stableClone.Spec.Template.DeepCopy()
|
||||
|
@ -431,13 +431,13 @@ func TestReconcile_CloneSet(t *testing.T) {
|
|||
canary,
|
||||
}
|
||||
},
|
||||
ExpectedPhase: v1alpha1.RolloutPhaseProgressing,
|
||||
ExpectedState: v1alpha1.ReadyBatchState,
|
||||
ExpectedPhase: v1beta1.RolloutPhaseProgressing,
|
||||
ExpectedState: v1beta1.ReadyBatchState,
|
||||
},
|
||||
{
|
||||
Name: `Special Case: Deletion, Input-Phase=Progressing, Output-Phase=Finalizing`,
|
||||
GetRelease: func() client.Object {
|
||||
release := setState(releaseClone, v1alpha1.ReadyBatchState)
|
||||
release := setState(releaseClone, v1beta1.ReadyBatchState)
|
||||
now := metav1.Now()
|
||||
release.Status.CanaryStatus.BatchReadyTime = &now
|
||||
stableTemplate := stableClone.Spec.Template.DeepCopy()
|
||||
|
@ -459,13 +459,13 @@ func TestReconcile_CloneSet(t *testing.T) {
|
|||
canary,
|
||||
}
|
||||
},
|
||||
ExpectedPhase: v1alpha1.RolloutPhaseFinalizing,
|
||||
ExpectedState: v1alpha1.ReadyBatchState,
|
||||
ExpectedPhase: v1beta1.RolloutPhaseFinalizing,
|
||||
ExpectedState: v1beta1.ReadyBatchState,
|
||||
},
|
||||
{
|
||||
Name: `Special Case: Continuous Release, Input-Phase=Progressing, Output-Phase=Progressing`,
|
||||
GetRelease: func() client.Object {
|
||||
release := setState(releaseClone, v1alpha1.ReadyBatchState)
|
||||
release := setState(releaseClone, v1beta1.ReadyBatchState)
|
||||
now := metav1.Now()
|
||||
release.Status.CanaryStatus.BatchReadyTime = &now
|
||||
stableTemplate := stableClone.Spec.Template.DeepCopy()
|
||||
|
@ -476,7 +476,7 @@ func TestReconcile_CloneSet(t *testing.T) {
|
|||
release.Status.UpdateRevision = util.ComputeHash(canaryTemplate, nil)
|
||||
release.Status.CanaryStatus.UpdatedReplicas = 10
|
||||
release.Status.CanaryStatus.UpdatedReadyReplicas = 10
|
||||
release.Spec.ReleasePlan.BatchPartition = pointer.Int32Ptr(1)
|
||||
release.Spec.ReleasePlan.BatchPartition = pointer.Int32(1)
|
||||
release.Status.ObservedReleasePlanHash = util.HashReleasePlanBatches(&release.Spec.ReleasePlan)
|
||||
return release
|
||||
},
|
||||
|
@ -493,13 +493,13 @@ func TestReconcile_CloneSet(t *testing.T) {
|
|||
canary,
|
||||
}
|
||||
},
|
||||
ExpectedPhase: v1alpha1.RolloutPhaseProgressing,
|
||||
ExpectedState: v1alpha1.ReadyBatchState,
|
||||
ExpectedPhase: v1beta1.RolloutPhaseProgressing,
|
||||
ExpectedState: v1beta1.ReadyBatchState,
|
||||
},
|
||||
{
|
||||
Name: `Special Case: BatchPartition=nil, Input-Phase=Progressing, Output-Phase=Finalizing`,
|
||||
GetRelease: func() client.Object {
|
||||
release := setState(releaseClone, v1alpha1.ReadyBatchState)
|
||||
release := setState(releaseClone, v1beta1.ReadyBatchState)
|
||||
now := metav1.Now()
|
||||
release.Status.CanaryStatus.BatchReadyTime = &now
|
||||
stableTemplate := stableClone.Spec.Template.DeepCopy()
|
||||
|
@ -521,8 +521,8 @@ func TestReconcile_CloneSet(t *testing.T) {
|
|||
canary,
|
||||
}
|
||||
},
|
||||
ExpectedPhase: v1alpha1.RolloutPhaseFinalizing,
|
||||
ExpectedState: v1alpha1.ReadyBatchState,
|
||||
ExpectedPhase: v1beta1.RolloutPhaseFinalizing,
|
||||
ExpectedState: v1beta1.ReadyBatchState,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -531,7 +531,11 @@ func TestReconcile_CloneSet(t *testing.T) {
|
|||
release := cs.GetRelease()
|
||||
clonesets := cs.GetCloneSet()
|
||||
rec := record.NewFakeRecorder(100)
|
||||
cli := fake.NewClientBuilder().WithScheme(scheme).WithObjects(release).WithObjects(clonesets...).Build()
|
||||
cli := fake.NewClientBuilder().WithScheme(scheme).
|
||||
WithObjects(release).
|
||||
WithObjects(clonesets...).
|
||||
WithStatusSubresource(&v1beta1.BatchRelease{}).
|
||||
Build()
|
||||
reconciler := &BatchReleaseReconciler{
|
||||
Client: cli,
|
||||
recorder: rec,
|
||||
|
@ -545,7 +549,7 @@ func TestReconcile_CloneSet(t *testing.T) {
|
|||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(result.RequeueAfter).Should(BeNumerically(">=", int64(0)))
|
||||
|
||||
newRelease := v1alpha1.BatchRelease{}
|
||||
newRelease := v1beta1.BatchRelease{}
|
||||
err = cli.Get(context.TODO(), key, &newRelease)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(newRelease.Status.Phase).Should(Equal(cs.ExpectedPhase))
|
||||
|
@ -563,14 +567,14 @@ func TestReconcile_Deployment(t *testing.T) {
|
|||
GetRelease func() client.Object
|
||||
GetDeployments func() []client.Object
|
||||
ExpectedBatch int32
|
||||
ExpectedPhase v1alpha1.RolloutPhase
|
||||
ExpectedState v1alpha1.BatchReleaseBatchStateType
|
||||
ExpectedPhase v1beta1.RolloutPhase
|
||||
ExpectedState v1beta1.BatchReleaseBatchStateType
|
||||
}{
|
||||
// Following cases of Linear Transaction on State Machine
|
||||
{
|
||||
Name: "IfNeedProgress=true, Input-Phase=Healthy, Output-Phase=Progressing",
|
||||
GetRelease: func() client.Object {
|
||||
return setPhase(releaseDeploy, v1alpha1.RolloutPhaseHealthy)
|
||||
return setPhase(releaseDeploy, v1beta1.RolloutPhaseHealthy)
|
||||
},
|
||||
GetDeployments: func() []client.Object {
|
||||
stable := getStableWithReady(stableDeploy, "v2").(*apps.Deployment)
|
||||
|
@ -579,12 +583,12 @@ func TestReconcile_Deployment(t *testing.T) {
|
|||
stable, canary,
|
||||
}
|
||||
},
|
||||
ExpectedPhase: v1alpha1.RolloutPhaseProgressing,
|
||||
ExpectedPhase: v1beta1.RolloutPhaseProgressing,
|
||||
},
|
||||
{
|
||||
Name: "Preparing, Input-Phase=Preparing, Output-Phase=Progressing",
|
||||
GetRelease: func() client.Object {
|
||||
return setPhase(releaseDeploy, v1alpha1.RolloutPhasePreparing)
|
||||
return setPhase(releaseDeploy, v1beta1.RolloutPhasePreparing)
|
||||
},
|
||||
GetDeployments: func() []client.Object {
|
||||
stable := getStableWithReady(stableDeploy, "v2")
|
||||
|
@ -593,12 +597,12 @@ func TestReconcile_Deployment(t *testing.T) {
|
|||
stable, canary,
|
||||
}
|
||||
},
|
||||
ExpectedPhase: v1alpha1.RolloutPhaseProgressing,
|
||||
ExpectedPhase: v1beta1.RolloutPhaseProgressing,
|
||||
},
|
||||
{
|
||||
Name: "Progressing, stage=0, Input-State=Upgrade, Output-State=Verify",
|
||||
GetRelease: func() client.Object {
|
||||
return setState(releaseDeploy, v1alpha1.UpgradingBatchState)
|
||||
return setState(releaseDeploy, v1beta1.UpgradingBatchState)
|
||||
},
|
||||
GetDeployments: func() []client.Object {
|
||||
stable := getStableWithReady(stableDeploy, "v2")
|
||||
|
@ -607,8 +611,8 @@ func TestReconcile_Deployment(t *testing.T) {
|
|||
stable, canary,
|
||||
}
|
||||
},
|
||||
ExpectedPhase: v1alpha1.RolloutPhaseProgressing,
|
||||
ExpectedState: v1alpha1.VerifyingBatchState,
|
||||
ExpectedPhase: v1beta1.RolloutPhaseProgressing,
|
||||
ExpectedState: v1beta1.VerifyingBatchState,
|
||||
},
|
||||
{
|
||||
Name: "Progressing, stage=0, Input-State=Verify, Output-State=Upgrade",
|
||||
|
@ -616,7 +620,7 @@ func TestReconcile_Deployment(t *testing.T) {
|
|||
release := releaseDeploy.DeepCopy()
|
||||
release.Status.CanaryStatus.UpdatedReplicas = 5
|
||||
release.Status.CanaryStatus.UpdatedReadyReplicas = 5
|
||||
return setState(release, v1alpha1.VerifyingBatchState)
|
||||
return setState(release, v1beta1.VerifyingBatchState)
|
||||
},
|
||||
GetDeployments: func() []client.Object {
|
||||
stable := getStableWithReady(stableDeploy, "v2")
|
||||
|
@ -625,8 +629,8 @@ func TestReconcile_Deployment(t *testing.T) {
|
|||
stable, canary,
|
||||
}
|
||||
},
|
||||
ExpectedPhase: v1alpha1.RolloutPhaseProgressing,
|
||||
ExpectedState: v1alpha1.UpgradingBatchState,
|
||||
ExpectedPhase: v1beta1.RolloutPhaseProgressing,
|
||||
ExpectedState: v1beta1.UpgradingBatchState,
|
||||
},
|
||||
{
|
||||
Name: "Progressing, stage=0, Input-State=Verify, Output-State=BatchReady",
|
||||
|
@ -634,7 +638,7 @@ func TestReconcile_Deployment(t *testing.T) {
|
|||
release := releaseDeploy.DeepCopy()
|
||||
release.Status.CanaryStatus.UpdatedReplicas = 10
|
||||
release.Status.CanaryStatus.UpdatedReadyReplicas = 10
|
||||
return setState(release, v1alpha1.VerifyingBatchState)
|
||||
return setState(release, v1beta1.VerifyingBatchState)
|
||||
},
|
||||
GetDeployments: func() []client.Object {
|
||||
stable := getStableWithReady(stableDeploy, "v2")
|
||||
|
@ -643,8 +647,8 @@ func TestReconcile_Deployment(t *testing.T) {
|
|||
stable, canary,
|
||||
}
|
||||
},
|
||||
ExpectedPhase: v1alpha1.RolloutPhaseProgressing,
|
||||
ExpectedState: v1alpha1.ReadyBatchState,
|
||||
ExpectedPhase: v1beta1.RolloutPhaseProgressing,
|
||||
ExpectedState: v1beta1.ReadyBatchState,
|
||||
},
|
||||
{
|
||||
Name: "Progressing, stage=0->1, Input-State=BatchReady, Output-State=Upgrade",
|
||||
|
@ -652,8 +656,8 @@ func TestReconcile_Deployment(t *testing.T) {
|
|||
release := releaseDeploy.DeepCopy()
|
||||
release.Status.CanaryStatus.UpdatedReplicas = 10
|
||||
release.Status.CanaryStatus.UpdatedReadyReplicas = 10
|
||||
release.Spec.ReleasePlan.BatchPartition = pointer.Int32Ptr(1)
|
||||
return setState(release, v1alpha1.ReadyBatchState)
|
||||
release.Spec.ReleasePlan.BatchPartition = pointer.Int32(1)
|
||||
return setState(release, v1beta1.ReadyBatchState)
|
||||
},
|
||||
GetDeployments: func() []client.Object {
|
||||
stable := getStableWithReady(stableDeploy, "v2")
|
||||
|
@ -662,8 +666,8 @@ func TestReconcile_Deployment(t *testing.T) {
|
|||
stable, canary,
|
||||
}
|
||||
},
|
||||
ExpectedPhase: v1alpha1.RolloutPhaseProgressing,
|
||||
ExpectedState: v1alpha1.UpgradingBatchState,
|
||||
ExpectedPhase: v1beta1.RolloutPhaseProgressing,
|
||||
ExpectedState: v1beta1.UpgradingBatchState,
|
||||
ExpectedBatch: 1,
|
||||
},
|
||||
{
|
||||
|
@ -672,7 +676,7 @@ func TestReconcile_Deployment(t *testing.T) {
|
|||
release := releaseDeploy.DeepCopy()
|
||||
release.Status.CanaryStatus.UpdatedReplicas = 10
|
||||
release.Status.CanaryStatus.UpdatedReadyReplicas = 10
|
||||
release = setState(release, v1alpha1.ReadyBatchState)
|
||||
release = setState(release, v1beta1.ReadyBatchState)
|
||||
return release
|
||||
},
|
||||
GetDeployments: func() []client.Object {
|
||||
|
@ -682,32 +686,32 @@ func TestReconcile_Deployment(t *testing.T) {
|
|||
stable, canary,
|
||||
}
|
||||
},
|
||||
ExpectedPhase: v1alpha1.RolloutPhaseProgressing,
|
||||
ExpectedState: v1alpha1.ReadyBatchState,
|
||||
ExpectedPhase: v1beta1.RolloutPhaseProgressing,
|
||||
ExpectedState: v1beta1.ReadyBatchState,
|
||||
},
|
||||
{
|
||||
Name: "Special Case: Scaling, Input-State=BatchReady, Output-State=Upgrade",
|
||||
GetRelease: func() client.Object {
|
||||
release := setState(releaseDeploy, v1alpha1.ReadyBatchState)
|
||||
release := setState(releaseDeploy, v1beta1.ReadyBatchState)
|
||||
now := metav1.Now()
|
||||
release.Status.CanaryStatus.BatchReadyTime = &now
|
||||
return release
|
||||
},
|
||||
GetDeployments: func() []client.Object {
|
||||
stable := getStableWithReady(stableDeploy, "v2").(*apps.Deployment)
|
||||
stable.Spec.Replicas = pointer.Int32Ptr(200)
|
||||
stable.Spec.Replicas = pointer.Int32(200)
|
||||
canary := getCanaryWithStage(stable, "v2", 0, true)
|
||||
return []client.Object{
|
||||
stable, canary,
|
||||
}
|
||||
},
|
||||
ExpectedPhase: v1alpha1.RolloutPhaseProgressing,
|
||||
ExpectedState: v1alpha1.UpgradingBatchState,
|
||||
ExpectedPhase: v1beta1.RolloutPhaseProgressing,
|
||||
ExpectedState: v1beta1.UpgradingBatchState,
|
||||
},
|
||||
{
|
||||
Name: `Special Case: RollBack, Input-Phase=Progressing, Output-Phase=Progressing`,
|
||||
GetRelease: func() client.Object {
|
||||
release := setState(releaseDeploy, v1alpha1.ReadyBatchState)
|
||||
release := setState(releaseDeploy, v1beta1.ReadyBatchState)
|
||||
now := metav1.Now()
|
||||
release.Status.CanaryStatus.BatchReadyTime = &now
|
||||
stableTemplate := stableDeploy.Spec.Template.DeepCopy()
|
||||
|
@ -725,13 +729,13 @@ func TestReconcile_Deployment(t *testing.T) {
|
|||
stable, canary,
|
||||
}
|
||||
},
|
||||
ExpectedPhase: v1alpha1.RolloutPhaseProgressing,
|
||||
ExpectedState: v1alpha1.ReadyBatchState,
|
||||
ExpectedPhase: v1beta1.RolloutPhaseProgressing,
|
||||
ExpectedState: v1beta1.ReadyBatchState,
|
||||
},
|
||||
{
|
||||
Name: `Special Case: Deletion, Input-Phase=Progressing, Output-Phase=Finalizing`,
|
||||
GetRelease: func() client.Object {
|
||||
release := setState(releaseDeploy, v1alpha1.ReadyBatchState)
|
||||
release := setState(releaseDeploy, v1beta1.ReadyBatchState)
|
||||
now := metav1.Now()
|
||||
release.Status.CanaryStatus.BatchReadyTime = &now
|
||||
stableTemplate := stableDeploy.Spec.Template.DeepCopy()
|
||||
|
@ -751,13 +755,13 @@ func TestReconcile_Deployment(t *testing.T) {
|
|||
stable, canary,
|
||||
}
|
||||
},
|
||||
ExpectedPhase: v1alpha1.RolloutPhaseFinalizing,
|
||||
ExpectedState: v1alpha1.ReadyBatchState,
|
||||
ExpectedPhase: v1beta1.RolloutPhaseFinalizing,
|
||||
ExpectedState: v1beta1.ReadyBatchState,
|
||||
},
|
||||
{
|
||||
Name: `Special Case: Continuous Release, Input-Phase=Progressing, Output-Phase=Progressing`,
|
||||
GetRelease: func() client.Object {
|
||||
release := setState(releaseDeploy, v1alpha1.ReadyBatchState)
|
||||
release := setState(releaseDeploy, v1beta1.ReadyBatchState)
|
||||
now := metav1.Now()
|
||||
release.Status.CanaryStatus.BatchReadyTime = &now
|
||||
stableTemplate := stableDeploy.Spec.Template.DeepCopy()
|
||||
|
@ -775,8 +779,8 @@ func TestReconcile_Deployment(t *testing.T) {
|
|||
stable, canary,
|
||||
}
|
||||
},
|
||||
ExpectedState: v1alpha1.ReadyBatchState,
|
||||
ExpectedPhase: v1alpha1.RolloutPhaseProgressing,
|
||||
ExpectedState: v1beta1.ReadyBatchState,
|
||||
ExpectedPhase: v1beta1.RolloutPhaseProgressing,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -795,6 +799,8 @@ func TestReconcile_Deployment(t *testing.T) {
|
|||
cliBuilder = cliBuilder.WithObjects(makeCanaryReplicaSets(deployments[1:]...)...)
|
||||
}
|
||||
|
||||
cliBuilder.WithStatusSubresource(&v1beta1.BatchRelease{})
|
||||
|
||||
cli := cliBuilder.Build()
|
||||
reconciler := &BatchReleaseReconciler{
|
||||
Client: cli,
|
||||
|
@ -808,7 +814,7 @@ func TestReconcile_Deployment(t *testing.T) {
|
|||
result, _ := reconciler.Reconcile(context.TODO(), request)
|
||||
Expect(result.RequeueAfter).Should(BeNumerically(">=", int64(0)))
|
||||
|
||||
newRelease := v1alpha1.BatchRelease{}
|
||||
newRelease := v1beta1.BatchRelease{}
|
||||
err := cli.Get(context.TODO(), key, &newRelease)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(newRelease.Status.Phase).Should(Equal(cs.ExpectedPhase))
|
||||
|
@ -827,7 +833,7 @@ func containers(version string) []corev1.Container {
|
|||
}
|
||||
}
|
||||
|
||||
func setPhase(release *v1alpha1.BatchRelease, phase v1alpha1.RolloutPhase) *v1alpha1.BatchRelease {
|
||||
func setPhase(release *v1beta1.BatchRelease, phase v1beta1.RolloutPhase) *v1beta1.BatchRelease {
|
||||
r := release.DeepCopy()
|
||||
r.Status.Phase = phase
|
||||
r.Status.ObservedWorkloadReplicas = 100
|
||||
|
@ -835,9 +841,9 @@ func setPhase(release *v1alpha1.BatchRelease, phase v1alpha1.RolloutPhase) *v1al
|
|||
return r
|
||||
}
|
||||
|
||||
func setState(release *v1alpha1.BatchRelease, state v1alpha1.BatchReleaseBatchStateType) *v1alpha1.BatchRelease {
|
||||
func setState(release *v1beta1.BatchRelease, state v1beta1.BatchReleaseBatchStateType) *v1beta1.BatchRelease {
|
||||
r := release.DeepCopy()
|
||||
r.Status.Phase = v1alpha1.RolloutPhaseProgressing
|
||||
r.Status.Phase = v1beta1.RolloutPhaseProgressing
|
||||
r.Status.CanaryStatus.CurrentBatchState = state
|
||||
r.Status.ObservedWorkloadReplicas = 100
|
||||
r.Status.ObservedReleasePlanHash = util.HashReleasePlanBatches(&release.Spec.ReleasePlan)
|
||||
|
@ -892,7 +898,7 @@ func getCanaryWithStage(workload client.Object, version string, stage int, ready
|
|||
d.ResourceVersion = strconv.Itoa(rand.Intn(100000000000))
|
||||
d.Labels[util.CanaryDeploymentLabel] = "87076677"
|
||||
d.Finalizers = []string{util.CanaryDeploymentFinalizer}
|
||||
d.Spec.Replicas = pointer.Int32Ptr(int32(stageReplicas))
|
||||
d.Spec.Replicas = pointer.Int32(int32(stageReplicas))
|
||||
d.Spec.Template.Spec.Containers = containers(version)
|
||||
d.Status.Replicas = int32(stageReplicas)
|
||||
d.Status.ReadyReplicas = int32(stageReplicas)
|
||||
|
|
|
@ -23,10 +23,6 @@ import (
|
|||
|
||||
kruiseappsv1alpha1 "github.com/openkruise/kruise-api/apps/v1alpha1"
|
||||
kruiseappsv1beta1 "github.com/openkruise/kruise-api/apps/v1beta1"
|
||||
"github.com/openkruise/rollouts/api/v1alpha1"
|
||||
"github.com/openkruise/rollouts/pkg/util"
|
||||
utilclient "github.com/openkruise/rollouts/pkg/util/client"
|
||||
expectations "github.com/openkruise/rollouts/pkg/util/expectation"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
@ -39,6 +35,11 @@ import (
|
|||
"sigs.k8s.io/controller-runtime/pkg/event"
|
||||
"sigs.k8s.io/controller-runtime/pkg/handler"
|
||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||
|
||||
"github.com/openkruise/rollouts/api/v1beta1"
|
||||
"github.com/openkruise/rollouts/pkg/util"
|
||||
utilclient "github.com/openkruise/rollouts/pkg/util/client"
|
||||
expectations "github.com/openkruise/rollouts/pkg/util/expectation"
|
||||
)
|
||||
|
||||
type EventAction string
|
||||
|
@ -55,7 +56,7 @@ type podEventHandler struct {
|
|||
client.Reader
|
||||
}
|
||||
|
||||
func (p podEventHandler) Create(evt event.CreateEvent, q workqueue.RateLimitingInterface) {
|
||||
func (p podEventHandler) Create(ctx context.Context, evt event.CreateEvent, q workqueue.RateLimitingInterface) {
|
||||
pod, ok := evt.Object.(*corev1.Pod)
|
||||
if !ok {
|
||||
return
|
||||
|
@ -63,13 +64,13 @@ func (p podEventHandler) Create(evt event.CreateEvent, q workqueue.RateLimitingI
|
|||
p.enqueue(pod, q)
|
||||
}
|
||||
|
||||
func (p podEventHandler) Generic(evt event.GenericEvent, q workqueue.RateLimitingInterface) {
|
||||
func (p podEventHandler) Generic(ctx context.Context, evt event.GenericEvent, q workqueue.RateLimitingInterface) {
|
||||
}
|
||||
|
||||
func (p podEventHandler) Delete(evt event.DeleteEvent, q workqueue.RateLimitingInterface) {
|
||||
func (p podEventHandler) Delete(ctx context.Context, evt event.DeleteEvent, q workqueue.RateLimitingInterface) {
|
||||
}
|
||||
|
||||
func (p podEventHandler) Update(evt event.UpdateEvent, q workqueue.RateLimitingInterface) {
|
||||
func (p podEventHandler) Update(ctx context.Context, evt event.UpdateEvent, q workqueue.RateLimitingInterface) {
|
||||
oldPod, oldOK := evt.ObjectOld.(*corev1.Pod)
|
||||
newPod, newOK := evt.ObjectNew.(*corev1.Pod)
|
||||
if !oldOK || !newOK {
|
||||
|
@ -121,12 +122,12 @@ type workloadEventHandler struct {
|
|||
client.Reader
|
||||
}
|
||||
|
||||
func (w workloadEventHandler) Create(evt event.CreateEvent, q workqueue.RateLimitingInterface) {
|
||||
func (w workloadEventHandler) Create(ctx context.Context, evt event.CreateEvent, q workqueue.RateLimitingInterface) {
|
||||
expectationObserved(evt.Object)
|
||||
w.handleWorkload(q, evt.Object, CreateEventAction)
|
||||
}
|
||||
|
||||
func (w workloadEventHandler) Update(evt event.UpdateEvent, q workqueue.RateLimitingInterface) {
|
||||
func (w workloadEventHandler) Update(ctx context.Context, evt event.UpdateEvent, q workqueue.RateLimitingInterface) {
|
||||
var gvk schema.GroupVersionKind
|
||||
switch obj := evt.ObjectNew.(type) {
|
||||
case *kruiseappsv1alpha1.CloneSet:
|
||||
|
@ -145,8 +146,8 @@ func (w workloadEventHandler) Update(evt event.UpdateEvent, q workqueue.RateLimi
|
|||
return
|
||||
}
|
||||
|
||||
oldObject := evt.ObjectNew
|
||||
newObject := evt.ObjectOld
|
||||
newObject := evt.ObjectNew
|
||||
oldObject := evt.ObjectOld
|
||||
expectationObserved(newObject)
|
||||
if newObject.GetResourceVersion() == oldObject.GetResourceVersion() {
|
||||
return
|
||||
|
@ -172,11 +173,11 @@ func (w workloadEventHandler) Update(evt event.UpdateEvent, q workqueue.RateLimi
|
|||
}
|
||||
}
|
||||
|
||||
func (w workloadEventHandler) Delete(evt event.DeleteEvent, q workqueue.RateLimitingInterface) {
|
||||
func (w workloadEventHandler) Delete(ctx context.Context, evt event.DeleteEvent, q workqueue.RateLimitingInterface) {
|
||||
w.handleWorkload(q, evt.Object, DeleteEventAction)
|
||||
}
|
||||
|
||||
func (w workloadEventHandler) Generic(evt event.GenericEvent, q workqueue.RateLimitingInterface) {
|
||||
func (w workloadEventHandler) Generic(ctx context.Context, evt event.GenericEvent, q workqueue.RateLimitingInterface) {
|
||||
}
|
||||
|
||||
func (w *workloadEventHandler) handleWorkload(q workqueue.RateLimitingInterface, obj client.Object, action EventAction) {
|
||||
|
@ -224,14 +225,14 @@ func getBatchRelease(c client.Reader, workloadNamespaceName types.NamespacedName
|
|||
klog.Errorf("Failed to unmarshal controller info annotations for %v(%v)", gvk, workloadNamespaceName)
|
||||
}
|
||||
|
||||
if br.APIVersion == v1alpha1.GroupVersion.String() && br.Kind == "BatchRelease" {
|
||||
if br.APIVersion == v1beta1.GroupVersion.String() && br.Kind == "BatchRelease" {
|
||||
klog.V(3).Infof("%s (%v) is managed by BatchRelease (%s), append queue and will reconcile BatchRelease", gvk.Kind, workloadNamespaceName, br.Name)
|
||||
nsn = types.NamespacedName{Namespace: workloadNamespaceName.Namespace, Name: br.Name}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
brList := &v1alpha1.BatchReleaseList{}
|
||||
brList := &v1beta1.BatchReleaseList{}
|
||||
namespace := workloadNamespaceName.Namespace
|
||||
if err = c.List(context.TODO(), brList, client.InNamespace(namespace), utilclient.DisableDeepCopy); err != nil {
|
||||
klog.Errorf("List BatchRelease failed: %s", err.Error())
|
||||
|
@ -240,14 +241,14 @@ func getBatchRelease(c client.Reader, workloadNamespaceName types.NamespacedName
|
|||
|
||||
for i := range brList.Items {
|
||||
br := &brList.Items[i]
|
||||
targetRef := br.Spec.TargetRef
|
||||
targetGV, err := schema.ParseGroupVersion(targetRef.WorkloadRef.APIVersion)
|
||||
targetRef := br.Spec.WorkloadRef
|
||||
targetGV, err := schema.ParseGroupVersion(targetRef.APIVersion)
|
||||
if err != nil {
|
||||
klog.Errorf("Failed to parse targetRef's group version: %s for BatchRelease(%v)", targetRef.WorkloadRef.APIVersion, client.ObjectKeyFromObject(br))
|
||||
klog.Errorf("Failed to parse targetRef's group version: %s for BatchRelease(%v)", targetRef.APIVersion, client.ObjectKeyFromObject(br))
|
||||
continue
|
||||
}
|
||||
|
||||
if targetRef.WorkloadRef.Kind == gvk.Kind && targetGV.Group == gvk.Group && targetRef.WorkloadRef.Name == workloadNamespaceName.Name {
|
||||
if targetRef.Kind == gvk.Kind && targetGV.Group == gvk.Group && targetRef.Name == workloadNamespaceName.Name {
|
||||
nsn = client.ObjectKeyFromObject(br)
|
||||
}
|
||||
}
|
||||
|
@ -269,7 +270,7 @@ func getControllerKey(object client.Object) *string {
|
|||
if owner == nil {
|
||||
return nil
|
||||
}
|
||||
if owner.APIVersion == v1alpha1.GroupVersion.String() {
|
||||
if owner.Kind == "BatchRelease" {
|
||||
key := types.NamespacedName{Namespace: object.GetNamespace(), Name: owner.Name}.String()
|
||||
return &key
|
||||
}
|
||||
|
|
|
@ -17,14 +17,13 @@ limitations under the License.
|
|||
package batchrelease
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/openkruise/rollouts/api/v1alpha1"
|
||||
"github.com/openkruise/rollouts/pkg/util"
|
||||
apps "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
@ -34,6 +33,9 @@ import (
|
|||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client/fake"
|
||||
"sigs.k8s.io/controller-runtime/pkg/event"
|
||||
|
||||
"github.com/openkruise/rollouts/api/v1beta1"
|
||||
"github.com/openkruise/rollouts/pkg/util"
|
||||
)
|
||||
|
||||
func TestWorkloadEventHandler_Update(t *testing.T) {
|
||||
|
@ -91,14 +93,14 @@ func TestWorkloadEventHandler_Update(t *testing.T) {
|
|||
oldObject := getStableWithReady(stableDeploy, "v2").(*apps.Deployment)
|
||||
oldObject.SetGeneration(2)
|
||||
oldObject.Status.ObservedGeneration = 2
|
||||
oldObject.Spec.Replicas = pointer.Int32Ptr(1000)
|
||||
oldObject.Spec.Replicas = pointer.Int32(1000)
|
||||
return oldObject
|
||||
},
|
||||
GetNewWorkload: func() client.Object {
|
||||
newObject := getStableWithReady(stableDeploy, "v2").(*apps.Deployment)
|
||||
newObject.SetGeneration(2)
|
||||
newObject.Status.ObservedGeneration = 2
|
||||
newObject.Spec.Replicas = pointer.Int32Ptr(1000)
|
||||
newObject.Spec.Replicas = pointer.Int32(1000)
|
||||
newObject.Status.Replicas = 1000
|
||||
return newObject
|
||||
},
|
||||
|
@ -137,7 +139,7 @@ func TestWorkloadEventHandler_Update(t *testing.T) {
|
|||
ObjectOld: oldObject,
|
||||
ObjectNew: newObject,
|
||||
}
|
||||
handler.Update(updateEvt, updateQ)
|
||||
handler.Update(context.TODO(), updateEvt, updateQ)
|
||||
Expect(updateQ.Len()).Should(Equal(cs.ExpectedQueueLen))
|
||||
})
|
||||
}
|
||||
|
@ -172,7 +174,7 @@ func TestWorkloadEventHandler_Create(t *testing.T) {
|
|||
GetNewWorkload: func() client.Object {
|
||||
object := getStableWithReady(stableDeploy, "v2").(*apps.Deployment)
|
||||
controlInfo, _ := json.Marshal(&metav1.OwnerReference{
|
||||
APIVersion: v1alpha1.GroupVersion.String(),
|
||||
APIVersion: v1beta1.GroupVersion.String(),
|
||||
Kind: "Rollout",
|
||||
Name: "whatever",
|
||||
})
|
||||
|
@ -193,7 +195,7 @@ func TestWorkloadEventHandler_Create(t *testing.T) {
|
|||
createEvt := event.CreateEvent{
|
||||
Object: newObject,
|
||||
}
|
||||
handler.Create(createEvt, createQ)
|
||||
handler.Create(context.TODO(), createEvt, createQ)
|
||||
Expect(createQ.Len()).Should(Equal(cs.ExpectedQueueLen))
|
||||
})
|
||||
}
|
||||
|
@ -228,7 +230,7 @@ func TestWorkloadEventHandler_Delete(t *testing.T) {
|
|||
GetNewWorkload: func() client.Object {
|
||||
object := getStableWithReady(stableDeploy, "v2").(*apps.Deployment)
|
||||
controlInfo, _ := json.Marshal(&metav1.OwnerReference{
|
||||
APIVersion: v1alpha1.GroupVersion.String(),
|
||||
APIVersion: v1beta1.GroupVersion.String(),
|
||||
Kind: "Rollout",
|
||||
Name: "whatever",
|
||||
})
|
||||
|
@ -249,7 +251,7 @@ func TestWorkloadEventHandler_Delete(t *testing.T) {
|
|||
deleteEvt := event.DeleteEvent{
|
||||
Object: newObject,
|
||||
}
|
||||
handler.Delete(deleteEvt, deleteQ)
|
||||
handler.Delete(context.TODO(), deleteEvt, deleteQ)
|
||||
Expect(deleteQ.Len()).Should(Equal(cs.ExpectedQueueLen))
|
||||
})
|
||||
}
|
||||
|
@ -399,7 +401,7 @@ func TestPodEventHandler_Update(t *testing.T) {
|
|||
ObjectOld: oldObject,
|
||||
ObjectNew: newObject,
|
||||
}
|
||||
handler.Update(updateEvt, updateQ)
|
||||
handler.Update(context.TODO(), updateEvt, updateQ)
|
||||
Expect(updateQ.Len()).Should(Equal(cs.ExpectedQueueLen))
|
||||
})
|
||||
}
|
||||
|
@ -466,7 +468,7 @@ func TestPodEventHandler_Create(t *testing.T) {
|
|||
createEvt := event.CreateEvent{
|
||||
Object: newObject,
|
||||
}
|
||||
handler.Create(createEvt, createQ)
|
||||
handler.Create(context.TODO(), createEvt, createQ)
|
||||
Expect(createQ.Len()).Should(Equal(cs.ExpectedQueueLen))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -19,20 +19,9 @@ package batchrelease
|
|||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
appsv1alpha1 "github.com/openkruise/kruise-api/apps/v1alpha1"
|
||||
"github.com/openkruise/rollouts/api/v1alpha1"
|
||||
"github.com/openkruise/rollouts/pkg/controller/batchrelease/control"
|
||||
"github.com/openkruise/rollouts/pkg/controller/batchrelease/control/canarystyle"
|
||||
canarydeployment "github.com/openkruise/rollouts/pkg/controller/batchrelease/control/canarystyle/deployment"
|
||||
"github.com/openkruise/rollouts/pkg/controller/batchrelease/control/partitionstyle"
|
||||
"github.com/openkruise/rollouts/pkg/controller/batchrelease/control/partitionstyle/cloneset"
|
||||
"github.com/openkruise/rollouts/pkg/controller/batchrelease/control/partitionstyle/daemonset"
|
||||
partitiondeployment "github.com/openkruise/rollouts/pkg/controller/batchrelease/control/partitionstyle/deployment"
|
||||
"github.com/openkruise/rollouts/pkg/controller/batchrelease/control/partitionstyle/statefulset"
|
||||
"github.com/openkruise/rollouts/pkg/util"
|
||||
apps "k8s.io/api/apps/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
@ -42,6 +31,21 @@ import (
|
|||
"k8s.io/klog/v2"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||
|
||||
"github.com/openkruise/rollouts/api/v1beta1"
|
||||
"github.com/openkruise/rollouts/pkg/controller/batchrelease/control"
|
||||
"github.com/openkruise/rollouts/pkg/controller/batchrelease/control/bluegreenstyle"
|
||||
bgcloneset "github.com/openkruise/rollouts/pkg/controller/batchrelease/control/bluegreenstyle/cloneset"
|
||||
bgdeplopyment "github.com/openkruise/rollouts/pkg/controller/batchrelease/control/bluegreenstyle/deployment"
|
||||
"github.com/openkruise/rollouts/pkg/controller/batchrelease/control/canarystyle"
|
||||
canarydeployment "github.com/openkruise/rollouts/pkg/controller/batchrelease/control/canarystyle/deployment"
|
||||
"github.com/openkruise/rollouts/pkg/controller/batchrelease/control/partitionstyle"
|
||||
"github.com/openkruise/rollouts/pkg/controller/batchrelease/control/partitionstyle/cloneset"
|
||||
"github.com/openkruise/rollouts/pkg/controller/batchrelease/control/partitionstyle/daemonset"
|
||||
partitiondeployment "github.com/openkruise/rollouts/pkg/controller/batchrelease/control/partitionstyle/deployment"
|
||||
"github.com/openkruise/rollouts/pkg/controller/batchrelease/control/partitionstyle/statefulset"
|
||||
"github.com/openkruise/rollouts/pkg/util"
|
||||
"github.com/openkruise/rollouts/pkg/util/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -63,7 +67,7 @@ func NewReleasePlanExecutor(cli client.Client, recorder record.EventRecorder) *E
|
|||
}
|
||||
|
||||
// Do execute the release plan
|
||||
func (r *Executor) Do(release *v1alpha1.BatchRelease) (reconcile.Result, *v1alpha1.BatchReleaseStatus, error) {
|
||||
func (r *Executor) Do(release *v1beta1.BatchRelease) (reconcile.Result, *v1beta1.BatchReleaseStatus, error) {
|
||||
klog.InfoS("Starting one round of reconciling release plan",
|
||||
"BatchRelease", client.ObjectKeyFromObject(release),
|
||||
"phase", release.Status.Phase,
|
||||
|
@ -84,7 +88,7 @@ func (r *Executor) Do(release *v1alpha1.BatchRelease) (reconcile.Result, *v1alph
|
|||
return r.executeBatchReleasePlan(release, newStatus, workloadController)
|
||||
}
|
||||
|
||||
func (r *Executor) executeBatchReleasePlan(release *v1alpha1.BatchRelease, newStatus *v1alpha1.BatchReleaseStatus, workloadController control.Interface) (reconcile.Result, *v1alpha1.BatchReleaseStatus, error) {
|
||||
func (r *Executor) executeBatchReleasePlan(release *v1beta1.BatchRelease, newStatus *v1beta1.BatchReleaseStatus, workloadController control.Interface) (reconcile.Result, *v1beta1.BatchReleaseStatus, error) {
|
||||
var err error
|
||||
result := reconcile.Result{}
|
||||
|
||||
|
@ -93,42 +97,42 @@ func (r *Executor) executeBatchReleasePlan(release *v1alpha1.BatchRelease, newSt
|
|||
switch newStatus.Phase {
|
||||
default:
|
||||
// for compatibility. if it is an unknown phase, should start from beginning.
|
||||
newStatus.Phase = v1alpha1.RolloutPhasePreparing
|
||||
newStatus.Phase = v1beta1.RolloutPhasePreparing
|
||||
fallthrough
|
||||
|
||||
case v1alpha1.RolloutPhasePreparing:
|
||||
case v1beta1.RolloutPhasePreparing:
|
||||
// prepare and initialize something before progressing in this state.
|
||||
err = workloadController.Initialize()
|
||||
switch {
|
||||
case err == nil:
|
||||
newStatus.Phase = v1alpha1.RolloutPhaseProgressing
|
||||
newStatus.Phase = v1beta1.RolloutPhaseProgressing
|
||||
result = reconcile.Result{RequeueAfter: DefaultDuration}
|
||||
default:
|
||||
klog.Warningf("Failed to initialize %v, err %v", klog.KObj(release), err)
|
||||
}
|
||||
|
||||
case v1alpha1.RolloutPhaseProgressing:
|
||||
case v1beta1.RolloutPhaseProgressing:
|
||||
// progress the release plan in this state.
|
||||
result, err = r.progressBatches(release, newStatus, workloadController)
|
||||
|
||||
case v1alpha1.RolloutPhaseFinalizing:
|
||||
case v1beta1.RolloutPhaseFinalizing:
|
||||
err = workloadController.Finalize()
|
||||
switch {
|
||||
case err == nil:
|
||||
newStatus.Phase = v1alpha1.RolloutPhaseCompleted
|
||||
newStatus.Phase = v1beta1.RolloutPhaseCompleted
|
||||
default:
|
||||
klog.Warningf("Failed to finalize %v, err %v", klog.KObj(release), err)
|
||||
}
|
||||
|
||||
case v1alpha1.RolloutPhaseCompleted:
|
||||
// this state indicates that the plan is executed/cancelled successfully, should do nothing in these states.
|
||||
case v1beta1.RolloutPhaseCompleted:
|
||||
// this state indicates that the plan is executed/canceled successfully, should do nothing in these states.
|
||||
}
|
||||
|
||||
return result, newStatus, err
|
||||
}
|
||||
|
||||
// reconcile logic when we are in the middle of release, we have to go through finalizing state before succeed or fail
|
||||
func (r *Executor) progressBatches(release *v1alpha1.BatchRelease, newStatus *v1alpha1.BatchReleaseStatus, workloadController control.Interface) (reconcile.Result, error) {
|
||||
func (r *Executor) progressBatches(release *v1beta1.BatchRelease, newStatus *v1beta1.BatchReleaseStatus, workloadController control.Interface) (reconcile.Result, error) {
|
||||
var err error
|
||||
result := reconcile.Result{}
|
||||
|
||||
|
@ -137,43 +141,47 @@ func (r *Executor) progressBatches(release *v1alpha1.BatchRelease, newStatus *v1
|
|||
switch newStatus.CanaryStatus.CurrentBatchState {
|
||||
default:
|
||||
// for compatibility. if it is an unknown state, should start from beginning.
|
||||
newStatus.CanaryStatus.CurrentBatchState = v1alpha1.UpgradingBatchState
|
||||
newStatus.CanaryStatus.CurrentBatchState = v1beta1.UpgradingBatchState
|
||||
fallthrough
|
||||
|
||||
case v1alpha1.UpgradingBatchState:
|
||||
case v1beta1.UpgradingBatchState:
|
||||
// modify workload replicas/partition based on release plan in this state.
|
||||
err = workloadController.UpgradeBatch()
|
||||
switch {
|
||||
case err == nil:
|
||||
result = reconcile.Result{RequeueAfter: DefaultDuration}
|
||||
newStatus.CanaryStatus.CurrentBatchState = v1alpha1.VerifyingBatchState
|
||||
removeProgressingCondition(newStatus)
|
||||
newStatus.CanaryStatus.CurrentBatchState = v1beta1.VerifyingBatchState
|
||||
case errors.IsBadRequest(err):
|
||||
progressingStateTransition(newStatus, v1.ConditionTrue, v1beta1.ProgressingReasonInRolling, err.Error())
|
||||
fallthrough
|
||||
default:
|
||||
klog.Warningf("Failed to upgrade %v, err %v", klog.KObj(release), err)
|
||||
}
|
||||
|
||||
case v1alpha1.VerifyingBatchState:
|
||||
case v1beta1.VerifyingBatchState:
|
||||
// replicas/partition has been modified, should wait pod ready in this state.
|
||||
err = workloadController.CheckBatchReady()
|
||||
err = workloadController.EnsureBatchPodsReadyAndLabeled()
|
||||
switch {
|
||||
case err != nil:
|
||||
// should go to upgrade state to do again to avoid dead wait.
|
||||
newStatus.CanaryStatus.CurrentBatchState = v1alpha1.UpgradingBatchState
|
||||
newStatus.CanaryStatus.CurrentBatchState = v1beta1.UpgradingBatchState
|
||||
klog.Warningf("%v current batch is not ready, err %v", klog.KObj(release), err)
|
||||
default:
|
||||
now := metav1.Now()
|
||||
newStatus.CanaryStatus.BatchReadyTime = &now
|
||||
result = reconcile.Result{RequeueAfter: DefaultDuration}
|
||||
newStatus.CanaryStatus.CurrentBatchState = v1alpha1.ReadyBatchState
|
||||
newStatus.CanaryStatus.CurrentBatchState = v1beta1.ReadyBatchState
|
||||
}
|
||||
|
||||
case v1alpha1.ReadyBatchState:
|
||||
case v1beta1.ReadyBatchState:
|
||||
// replicas/partition may be modified even though ready, should recheck in this state.
|
||||
err = workloadController.CheckBatchReady()
|
||||
err = workloadController.EnsureBatchPodsReadyAndLabeled()
|
||||
switch {
|
||||
case err != nil:
|
||||
// if the batch ready condition changed due to some reasons, just recalculate the current batch.
|
||||
newStatus.CanaryStatus.BatchReadyTime = nil
|
||||
newStatus.CanaryStatus.CurrentBatchState = v1alpha1.UpgradingBatchState
|
||||
newStatus.CanaryStatus.CurrentBatchState = v1beta1.UpgradingBatchState
|
||||
klog.Warningf("%v current batch is not ready, err %v", klog.KObj(release), err)
|
||||
case !isPartitioned(release):
|
||||
r.moveToNextBatch(release, newStatus)
|
||||
|
@ -185,12 +193,8 @@ func (r *Executor) progressBatches(release *v1alpha1.BatchRelease, newStatus *v1
|
|||
}
|
||||
|
||||
// GetWorkloadController pick the right workload controller to work on the workload
|
||||
func (r *Executor) getReleaseController(release *v1alpha1.BatchRelease, newStatus *v1alpha1.BatchReleaseStatus) (control.Interface, error) {
|
||||
targetRef := release.Spec.TargetRef.WorkloadRef
|
||||
if targetRef == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (r *Executor) getReleaseController(release *v1beta1.BatchRelease, newStatus *v1beta1.BatchReleaseStatus) (control.Interface, error) {
|
||||
targetRef := release.Spec.WorkloadRef
|
||||
gvk := schema.FromAPIVersionAndKind(targetRef.APIVersion, targetRef.Kind)
|
||||
if !util.IsSupportedWorkload(gvk) {
|
||||
message := fmt.Sprintf("the workload type '%v' is not supported", gvk)
|
||||
|
@ -202,28 +206,43 @@ func (r *Executor) getReleaseController(release *v1alpha1.BatchRelease, newStatu
|
|||
Namespace: release.Namespace,
|
||||
Name: targetRef.Name,
|
||||
}
|
||||
rollingStyle := release.Spec.ReleasePlan.RollingStyle
|
||||
if len(rollingStyle) == 0 && release.Spec.ReleasePlan.EnableExtraWorkloadForCanary {
|
||||
rollingStyle = v1beta1.CanaryRollingStyle
|
||||
}
|
||||
klog.Infof("BatchRelease(%v) using %s-style release controller for this batch release", klog.KObj(release), rollingStyle)
|
||||
switch rollingStyle {
|
||||
case v1beta1.BlueGreenRollingStyle:
|
||||
if targetRef.APIVersion == appsv1alpha1.GroupVersion.String() && targetRef.Kind == reflect.TypeOf(appsv1alpha1.CloneSet{}).Name() {
|
||||
klog.InfoS("Using CloneSet bluegreen-style release controller for this batch release", "workload name", targetKey.Name, "namespace", targetKey.Namespace)
|
||||
return bluegreenstyle.NewControlPlane(bgcloneset.NewController, r.client, r.recorder, release, newStatus, targetKey, gvk), nil
|
||||
}
|
||||
if targetRef.APIVersion == apps.SchemeGroupVersion.String() && targetRef.Kind == reflect.TypeOf(apps.Deployment{}).Name() {
|
||||
klog.InfoS("Using Deployment bluegreen-style release controller for this batch release", "workload name", targetKey.Name, "namespace", targetKey.Namespace)
|
||||
return bluegreenstyle.NewControlPlane(bgdeplopyment.NewController, r.client, r.recorder, release, newStatus, targetKey, gvk), nil
|
||||
}
|
||||
|
||||
switch targetRef.APIVersion {
|
||||
case appsv1alpha1.GroupVersion.String():
|
||||
if targetRef.Kind == reflect.TypeOf(appsv1alpha1.CloneSet{}).Name() {
|
||||
case v1beta1.CanaryRollingStyle:
|
||||
if targetRef.APIVersion == apps.SchemeGroupVersion.String() && targetRef.Kind == reflect.TypeOf(apps.Deployment{}).Name() {
|
||||
klog.InfoS("Using Deployment canary-style release controller for this batch release", "workload name", targetKey.Name, "namespace", targetKey.Namespace)
|
||||
return canarystyle.NewControlPlane(canarydeployment.NewController, r.client, r.recorder, release, newStatus, targetKey), nil
|
||||
}
|
||||
fallthrough
|
||||
|
||||
case v1beta1.PartitionRollingStyle, "":
|
||||
if targetRef.APIVersion == appsv1alpha1.GroupVersion.String() && targetRef.Kind == reflect.TypeOf(appsv1alpha1.CloneSet{}).Name() {
|
||||
klog.InfoS("Using CloneSet partition-style release controller for this batch release", "workload name", targetKey.Name, "namespace", targetKey.Namespace)
|
||||
return partitionstyle.NewControlPlane(cloneset.NewController, r.client, r.recorder, release, newStatus, targetKey, gvk), nil
|
||||
}
|
||||
if targetRef.Kind == reflect.TypeOf(appsv1alpha1.DaemonSet{}).Name() {
|
||||
if targetRef.APIVersion == appsv1alpha1.GroupVersion.String() && targetRef.Kind == reflect.TypeOf(appsv1alpha1.DaemonSet{}).Name() {
|
||||
klog.InfoS("Using DaemonSet partition-style release controller for this batch release", "workload name", targetKey.Name, "namespace", targetKey.Namespace)
|
||||
return partitionstyle.NewControlPlane(daemonset.NewController, r.client, r.recorder, release, newStatus, targetKey, gvk), nil
|
||||
}
|
||||
|
||||
case apps.SchemeGroupVersion.String():
|
||||
if targetRef.Kind == reflect.TypeOf(apps.Deployment{}).Name() {
|
||||
if strings.EqualFold(release.Annotations[v1alpha1.RolloutStyleAnnotation], string(v1alpha1.PartitionRollingStyle)) {
|
||||
klog.InfoS("Using Deployment partition-style release controller for this batch release", "workload name", targetKey.Name, "namespace", targetKey.Namespace)
|
||||
return partitionstyle.NewControlPlane(partitiondeployment.NewController, r.client, r.recorder, release, newStatus, targetKey, gvk), nil
|
||||
} else {
|
||||
klog.InfoS("Using Deployment canary-style release controller for this batch release", "workload name", targetKey.Name, "namespace", targetKey.Namespace)
|
||||
return canarystyle.NewControlPlane(canarydeployment.NewController, r.client, r.recorder, release, newStatus, targetKey), nil
|
||||
}
|
||||
if targetRef.APIVersion == apps.SchemeGroupVersion.String() && targetRef.Kind == reflect.TypeOf(apps.Deployment{}).Name() {
|
||||
klog.InfoS("Using Deployment partition-style release controller for this batch release", "workload name", targetKey.Name, "namespace", targetKey.Namespace)
|
||||
return partitionstyle.NewControlPlane(partitiondeployment.NewController, r.client, r.recorder, release, newStatus, targetKey, gvk), nil
|
||||
}
|
||||
klog.Info("Partition, but use StatefulSet-Like partition-style release controller for this batch release")
|
||||
}
|
||||
|
||||
// try to use StatefulSet-like rollout controller by default
|
||||
|
@ -231,7 +250,7 @@ func (r *Executor) getReleaseController(release *v1alpha1.BatchRelease, newStatu
|
|||
return partitionstyle.NewControlPlane(statefulset.NewController, r.client, r.recorder, release, newStatus, targetKey, gvk), nil
|
||||
}
|
||||
|
||||
func (r *Executor) moveToNextBatch(release *v1alpha1.BatchRelease, status *v1alpha1.BatchReleaseStatus) {
|
||||
func (r *Executor) moveToNextBatch(release *v1beta1.BatchRelease, status *v1beta1.BatchReleaseStatus) {
|
||||
currentBatch := int(status.CanaryStatus.CurrentBatch)
|
||||
if currentBatch >= len(release.Spec.ReleasePlan.Batches)-1 {
|
||||
klog.V(3).Infof("BatchRelease(%v) finished all batch, release current batch: %v", klog.KObj(release), status.CanaryStatus.CurrentBatch)
|
||||
|
@ -239,11 +258,31 @@ func (r *Executor) moveToNextBatch(release *v1alpha1.BatchRelease, status *v1alp
|
|||
if release.Spec.ReleasePlan.BatchPartition == nil || *release.Spec.ReleasePlan.BatchPartition > status.CanaryStatus.CurrentBatch {
|
||||
status.CanaryStatus.CurrentBatch++
|
||||
}
|
||||
status.CanaryStatus.CurrentBatchState = v1alpha1.UpgradingBatchState
|
||||
status.CanaryStatus.CurrentBatchState = v1beta1.UpgradingBatchState
|
||||
klog.V(3).Infof("BatchRelease(%v) finished one batch, release current batch: %v", klog.KObj(release), status.CanaryStatus.CurrentBatch)
|
||||
}
|
||||
|
||||
func isPartitioned(release *v1alpha1.BatchRelease) bool {
|
||||
func isPartitioned(release *v1beta1.BatchRelease) bool {
|
||||
return release.Spec.ReleasePlan.BatchPartition != nil &&
|
||||
*release.Spec.ReleasePlan.BatchPartition <= release.Status.CanaryStatus.CurrentBatch
|
||||
}
|
||||
|
||||
func progressingStateTransition(status *v1beta1.BatchReleaseStatus, condStatus v1.ConditionStatus, reason, message string) {
|
||||
cond := util.GetBatchReleaseCondition(*status, v1beta1.RolloutConditionProgressing)
|
||||
if cond == nil {
|
||||
cond = util.NewRolloutCondition(v1beta1.RolloutConditionProgressing, condStatus, reason, message)
|
||||
} else {
|
||||
cond.Status = condStatus
|
||||
cond.Reason = reason
|
||||
if message != "" {
|
||||
cond.Message = message
|
||||
}
|
||||
}
|
||||
util.SetBatchReleaseCondition(status, *cond)
|
||||
status.Message = cond.Message
|
||||
}
|
||||
|
||||
func removeProgressingCondition(status *v1beta1.BatchReleaseStatus) {
|
||||
util.RemoveBatchReleaseCondition(status, v1beta1.RolloutConditionProgressing)
|
||||
status.Message = ""
|
||||
}
|
||||
|
|
|
@ -19,17 +19,19 @@ package batchrelease
|
|||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/openkruise/rollouts/api/v1alpha1"
|
||||
"github.com/openkruise/rollouts/pkg/controller/batchrelease/control"
|
||||
"github.com/openkruise/rollouts/pkg/util"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/klog/v2"
|
||||
"k8s.io/utils/integer"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||
|
||||
"github.com/openkruise/rollouts/api/v1alpha1"
|
||||
"github.com/openkruise/rollouts/api/v1beta1"
|
||||
"github.com/openkruise/rollouts/pkg/controller/batchrelease/control"
|
||||
"github.com/openkruise/rollouts/pkg/util"
|
||||
)
|
||||
|
||||
func (r *Executor) syncStatusBeforeExecuting(release *v1alpha1.BatchRelease, newStatus *v1alpha1.BatchReleaseStatus, controller control.Interface) (bool, reconcile.Result, error) {
|
||||
func (r *Executor) syncStatusBeforeExecuting(release *v1beta1.BatchRelease, newStatus *v1beta1.BatchReleaseStatus, controller control.Interface) (bool, reconcile.Result, error) {
|
||||
var err error
|
||||
var message string
|
||||
var needRetry bool
|
||||
|
@ -45,7 +47,7 @@ func (r *Executor) syncStatusBeforeExecuting(release *v1alpha1.BatchRelease, new
|
|||
*************************************************************************/
|
||||
//The following special cases are about the **batch release plan**, include:
|
||||
// (1). Plan has been terminated
|
||||
// (2). Plan is deleted or cancelled
|
||||
// (2). Plan is deleted or canceled
|
||||
// (3). Plan is changed during rollout
|
||||
// (4). Plan status is unexpected/unhealthy
|
||||
case isPlanCompleted(release):
|
||||
|
@ -54,7 +56,7 @@ func (r *Executor) syncStatusBeforeExecuting(release *v1alpha1.BatchRelease, new
|
|||
|
||||
case isPlanFinalizing(release):
|
||||
// handle the case that the plan is deleted or is terminating
|
||||
message = "release plan is deleted or cancelled, then finalize"
|
||||
message = "release plan is deleted or canceled, then finalize"
|
||||
signalFinalizing(newStatus)
|
||||
|
||||
case isPlanChanged(release):
|
||||
|
@ -145,7 +147,7 @@ func (r *Executor) syncStatusBeforeExecuting(release *v1alpha1.BatchRelease, new
|
|||
return needStopThisRound, result, err
|
||||
}
|
||||
|
||||
func refreshStatus(release *v1alpha1.BatchRelease, newStatus *v1alpha1.BatchReleaseStatus, workloadInfo *util.WorkloadInfo) {
|
||||
func refreshStatus(release *v1beta1.BatchRelease, newStatus *v1beta1.BatchReleaseStatus, workloadInfo *util.WorkloadInfo) {
|
||||
// refresh workload info for status
|
||||
if workloadInfo != nil {
|
||||
newStatus.CanaryStatus.UpdatedReplicas = workloadInfo.Status.UpdatedReplicas
|
||||
|
@ -154,78 +156,79 @@ func refreshStatus(release *v1alpha1.BatchRelease, newStatus *v1alpha1.BatchRele
|
|||
if len(newStatus.ObservedReleasePlanHash) == 0 {
|
||||
newStatus.ObservedReleasePlanHash = util.HashReleasePlanBatches(&release.Spec.ReleasePlan)
|
||||
}
|
||||
newStatus.ObservedRolloutID = release.Spec.ReleasePlan.RolloutID
|
||||
}
|
||||
|
||||
func isPlanFinalizing(release *v1alpha1.BatchRelease) bool {
|
||||
if release.DeletionTimestamp != nil || release.Status.Phase == v1alpha1.RolloutPhaseFinalizing {
|
||||
func isPlanFinalizing(release *v1beta1.BatchRelease) bool {
|
||||
if release.DeletionTimestamp != nil || release.Status.Phase == v1beta1.RolloutPhaseFinalizing {
|
||||
return true
|
||||
}
|
||||
return release.Spec.ReleasePlan.BatchPartition == nil
|
||||
}
|
||||
|
||||
func isPlanCompleted(release *v1alpha1.BatchRelease) bool {
|
||||
return release.Status.Phase == v1alpha1.RolloutPhaseCompleted
|
||||
func isPlanCompleted(release *v1beta1.BatchRelease) bool {
|
||||
return release.Status.Phase == v1beta1.RolloutPhaseCompleted
|
||||
}
|
||||
|
||||
func isPlanChanged(release *v1alpha1.BatchRelease) bool {
|
||||
return release.Status.ObservedReleasePlanHash != util.HashReleasePlanBatches(&release.Spec.ReleasePlan) && release.Status.Phase == v1alpha1.RolloutPhaseProgressing
|
||||
func isPlanChanged(release *v1beta1.BatchRelease) bool {
|
||||
return release.Status.ObservedReleasePlanHash != util.HashReleasePlanBatches(&release.Spec.ReleasePlan) && release.Status.Phase == v1beta1.RolloutPhaseProgressing
|
||||
}
|
||||
|
||||
func isPlanUnhealthy(release *v1alpha1.BatchRelease) bool {
|
||||
return int(release.Status.CanaryStatus.CurrentBatch) >= len(release.Spec.ReleasePlan.Batches) && release.Status.Phase == v1alpha1.RolloutPhaseProgressing
|
||||
func isPlanUnhealthy(release *v1beta1.BatchRelease) bool {
|
||||
return int(release.Status.CanaryStatus.CurrentBatch) >= len(release.Spec.ReleasePlan.Batches) && release.Status.Phase == v1beta1.RolloutPhaseProgressing
|
||||
}
|
||||
|
||||
func isGetWorkloadInfoError(err error) bool {
|
||||
return err != nil && !errors.IsNotFound(err)
|
||||
}
|
||||
|
||||
func isWorkloadGone(event control.WorkloadEventType, release *v1alpha1.BatchRelease) bool {
|
||||
return event == control.WorkloadHasGone && release.Status.Phase != v1alpha1.RolloutPhaseInitial && release.Status.Phase != ""
|
||||
func isWorkloadGone(event control.WorkloadEventType, release *v1beta1.BatchRelease) bool {
|
||||
return event == control.WorkloadHasGone && release.Status.Phase != v1beta1.RolloutPhaseInitial && release.Status.Phase != ""
|
||||
}
|
||||
|
||||
func isWorkloadScaling(event control.WorkloadEventType, release *v1alpha1.BatchRelease) bool {
|
||||
return event == control.WorkloadReplicasChanged && release.Status.Phase == v1alpha1.RolloutPhaseProgressing
|
||||
func isWorkloadScaling(event control.WorkloadEventType, release *v1beta1.BatchRelease) bool {
|
||||
return event == control.WorkloadReplicasChanged && release.Status.Phase == v1beta1.RolloutPhaseProgressing
|
||||
}
|
||||
|
||||
func isWorkloadRevisionChanged(event control.WorkloadEventType, release *v1alpha1.BatchRelease) bool {
|
||||
return event == control.WorkloadPodTemplateChanged && release.Status.Phase == v1alpha1.RolloutPhaseProgressing
|
||||
func isWorkloadRevisionChanged(event control.WorkloadEventType, release *v1beta1.BatchRelease) bool {
|
||||
return event == control.WorkloadPodTemplateChanged && release.Status.Phase == v1beta1.RolloutPhaseProgressing
|
||||
}
|
||||
|
||||
func isWorkloadRollbackInBatch(event control.WorkloadEventType, release *v1alpha1.BatchRelease) bool {
|
||||
func isWorkloadRollbackInBatch(event control.WorkloadEventType, release *v1beta1.BatchRelease) bool {
|
||||
return (event == control.WorkloadRollbackInBatch || release.Annotations[v1alpha1.RollbackInBatchAnnotation] != "") &&
|
||||
release.Status.CanaryStatus.NoNeedUpdateReplicas == nil && release.Status.Phase == v1alpha1.RolloutPhaseProgressing
|
||||
release.Status.CanaryStatus.NoNeedUpdateReplicas == nil && release.Status.Phase == v1beta1.RolloutPhaseProgressing
|
||||
}
|
||||
|
||||
func isWorkloadUnstable(event control.WorkloadEventType, _ *v1alpha1.BatchRelease) bool {
|
||||
func isWorkloadUnstable(event control.WorkloadEventType, _ *v1beta1.BatchRelease) bool {
|
||||
return event == control.WorkloadStillReconciling
|
||||
}
|
||||
|
||||
func isRollbackInBatchSatisfied(workloadInfo *util.WorkloadInfo, release *v1alpha1.BatchRelease) bool {
|
||||
func isRollbackInBatchSatisfied(workloadInfo *util.WorkloadInfo, release *v1beta1.BatchRelease) bool {
|
||||
return workloadInfo.Status.StableRevision == workloadInfo.Status.UpdateRevision && release.Annotations[v1alpha1.RollbackInBatchAnnotation] != ""
|
||||
}
|
||||
|
||||
func signalRePrepareRollback(newStatus *v1alpha1.BatchReleaseStatus) {
|
||||
newStatus.Phase = v1alpha1.RolloutPhasePreparing
|
||||
func signalRePrepareRollback(newStatus *v1beta1.BatchReleaseStatus) {
|
||||
newStatus.Phase = v1beta1.RolloutPhasePreparing
|
||||
newStatus.CanaryStatus.BatchReadyTime = nil
|
||||
newStatus.CanaryStatus.CurrentBatchState = v1alpha1.UpgradingBatchState
|
||||
newStatus.CanaryStatus.CurrentBatchState = v1beta1.UpgradingBatchState
|
||||
}
|
||||
|
||||
func signalRestartBatch(status *v1alpha1.BatchReleaseStatus) {
|
||||
func signalRestartBatch(status *v1beta1.BatchReleaseStatus) {
|
||||
status.CanaryStatus.BatchReadyTime = nil
|
||||
status.CanaryStatus.CurrentBatchState = v1alpha1.UpgradingBatchState
|
||||
status.CanaryStatus.CurrentBatchState = v1beta1.UpgradingBatchState
|
||||
}
|
||||
|
||||
func signalRestartAll(status *v1alpha1.BatchReleaseStatus) {
|
||||
emptyStatus := v1alpha1.BatchReleaseStatus{}
|
||||
func signalRestartAll(status *v1beta1.BatchReleaseStatus) {
|
||||
emptyStatus := v1beta1.BatchReleaseStatus{}
|
||||
resetStatus(&emptyStatus)
|
||||
*status = emptyStatus
|
||||
}
|
||||
|
||||
func signalFinalizing(status *v1alpha1.BatchReleaseStatus) {
|
||||
status.Phase = v1alpha1.RolloutPhaseFinalizing
|
||||
func signalFinalizing(status *v1beta1.BatchReleaseStatus) {
|
||||
status.Phase = v1beta1.RolloutPhaseFinalizing
|
||||
}
|
||||
|
||||
func signalRecalculate(release *v1alpha1.BatchRelease, newStatus *v1alpha1.BatchReleaseStatus) {
|
||||
func signalRecalculate(release *v1beta1.BatchRelease, newStatus *v1beta1.BatchReleaseStatus) {
|
||||
// When BatchRelease plan was changed, rollout controller will update this batchRelease cr,
|
||||
// and rollout controller will set BatchPartition as its expected current batch index.
|
||||
currentBatch := int32(0)
|
||||
|
@ -242,11 +245,11 @@ func signalRecalculate(release *v1alpha1.BatchRelease, newStatus *v1alpha1.Batch
|
|||
newStatus.CanaryStatus.BatchReadyTime = nil
|
||||
newStatus.CanaryStatus.CurrentBatch = currentBatch
|
||||
newStatus.ObservedRolloutID = release.Spec.ReleasePlan.RolloutID
|
||||
newStatus.CanaryStatus.CurrentBatchState = v1alpha1.UpgradingBatchState
|
||||
newStatus.CanaryStatus.CurrentBatchState = v1beta1.UpgradingBatchState
|
||||
newStatus.ObservedReleasePlanHash = util.HashReleasePlanBatches(&release.Spec.ReleasePlan)
|
||||
}
|
||||
|
||||
func getInitializedStatus(status *v1alpha1.BatchReleaseStatus) *v1alpha1.BatchReleaseStatus {
|
||||
func getInitializedStatus(status *v1beta1.BatchReleaseStatus) *v1beta1.BatchReleaseStatus {
|
||||
newStatus := status.DeepCopy()
|
||||
if len(status.Phase) == 0 {
|
||||
resetStatus(newStatus)
|
||||
|
@ -254,11 +257,11 @@ func getInitializedStatus(status *v1alpha1.BatchReleaseStatus) *v1alpha1.BatchRe
|
|||
return newStatus
|
||||
}
|
||||
|
||||
func resetStatus(status *v1alpha1.BatchReleaseStatus) {
|
||||
status.Phase = v1alpha1.RolloutPhasePreparing
|
||||
func resetStatus(status *v1beta1.BatchReleaseStatus) {
|
||||
status.Phase = v1beta1.RolloutPhasePreparing
|
||||
status.StableRevision = ""
|
||||
status.UpdateRevision = ""
|
||||
status.ObservedReleasePlanHash = ""
|
||||
status.ObservedWorkloadReplicas = -1
|
||||
status.CanaryStatus = v1alpha1.BatchReleaseCanaryStatus{}
|
||||
status.CanaryStatus = v1beta1.BatchReleaseCanaryStatus{}
|
||||
}
|
||||
|
|
|
@ -20,10 +20,11 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/openkruise/rollouts/api/v1alpha1"
|
||||
"github.com/openkruise/rollouts/pkg/util"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
|
||||
"github.com/openkruise/rollouts/api/v1beta1"
|
||||
"github.com/openkruise/rollouts/pkg/util"
|
||||
)
|
||||
|
||||
type BatchContext struct {
|
||||
|
@ -61,6 +62,9 @@ type BatchContext struct {
|
|||
Pods []*corev1.Pod `json:"-"`
|
||||
// filter or sort pods before patch label
|
||||
FilterFunc FilterFuncType `json:"-"`
|
||||
// the next two fields are only used for bluegreen style
|
||||
CurrentSurge intstr.IntOrString `json:"currentSurge,omitempty"`
|
||||
DesiredSurge intstr.IntOrString `json:"desiredSurge,omitempty"`
|
||||
}
|
||||
|
||||
type FilterFuncType func(pods []*corev1.Pod, ctx *BatchContext) []*corev1.Pod
|
||||
|
@ -73,20 +77,20 @@ func (bc *BatchContext) Log() string {
|
|||
// IsBatchReady return nil if the batch is ready
|
||||
func (bc *BatchContext) IsBatchReady() error {
|
||||
if bc.UpdatedReplicas < bc.DesiredUpdatedReplicas {
|
||||
return fmt.Errorf("current batch not ready: updated replicas not satified")
|
||||
return fmt.Errorf("current batch not ready: updated replicas not satisfied, UpdatedReplicas %d < DesiredUpdatedReplicas %d", bc.UpdatedReplicas, bc.DesiredUpdatedReplicas)
|
||||
}
|
||||
|
||||
unavailableToleration := allowedUnavailable(bc.FailureThreshold, bc.UpdatedReplicas)
|
||||
if unavailableToleration+bc.UpdatedReadyReplicas < bc.DesiredUpdatedReplicas {
|
||||
return fmt.Errorf("current batch not ready: updated ready replicas not satified")
|
||||
return fmt.Errorf("current batch not ready: updated ready replicas not satisfied, allowedUnavailable + UpdatedReadyReplicas %d < DesiredUpdatedReplicas %d", unavailableToleration+bc.UpdatedReadyReplicas, bc.DesiredUpdatedReplicas)
|
||||
}
|
||||
|
||||
if bc.DesiredUpdatedReplicas > 0 && bc.UpdatedReadyReplicas == 0 {
|
||||
return fmt.Errorf("current batch not ready: no updated ready replicas")
|
||||
return fmt.Errorf("current batch not ready: no updated ready replicas, DesiredUpdatedReplicas %d > 0 and UpdatedReadyReplicas %d = 0", bc.DesiredUpdatedReplicas, bc.UpdatedReadyReplicas)
|
||||
}
|
||||
|
||||
if !batchLabelSatisfied(bc.Pods, bc.RolloutID, bc.PlannedUpdatedReplicas) {
|
||||
return fmt.Errorf("current batch not ready: pods with batch label not satified")
|
||||
return fmt.Errorf("current batch not ready: pods with batch label not satisfied, RolloutID %s, PlannedUpdatedReplicas %d", bc.RolloutID, bc.PlannedUpdatedReplicas)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -100,7 +104,7 @@ func batchLabelSatisfied(pods []*corev1.Pod, rolloutID string, targetCount int32
|
|||
if !pod.DeletionTimestamp.IsZero() {
|
||||
return false
|
||||
}
|
||||
return pod.Labels[v1alpha1.RolloutIDLabel] == rolloutID
|
||||
return pod.Labels[v1beta1.RolloutIDLabel] == rolloutID
|
||||
})
|
||||
return patchedCount >= int(targetCount)
|
||||
}
|
||||
|
|
|
@ -22,12 +22,13 @@ import (
|
|||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/openkruise/rollouts/api/v1alpha1"
|
||||
"github.com/openkruise/rollouts/pkg/util"
|
||||
apps "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
|
||||
"github.com/openkruise/rollouts/api/v1beta1"
|
||||
"github.com/openkruise/rollouts/pkg/util"
|
||||
)
|
||||
|
||||
func TestIsBatchReady(t *testing.T) {
|
||||
|
@ -36,14 +37,14 @@ func TestIsBatchReady(t *testing.T) {
|
|||
p := func(f intstr.IntOrString) *intstr.IntOrString {
|
||||
return &f
|
||||
}
|
||||
r := func(f *intstr.IntOrString, id, revision string) *v1alpha1.BatchRelease {
|
||||
return &v1alpha1.BatchRelease{
|
||||
Spec: v1alpha1.BatchReleaseSpec{ReleasePlan: v1alpha1.ReleasePlan{RolloutID: id, FailureThreshold: f}},
|
||||
Status: v1alpha1.BatchReleaseStatus{UpdateRevision: revision},
|
||||
r := func(f *intstr.IntOrString, id, revision string) *v1beta1.BatchRelease {
|
||||
return &v1beta1.BatchRelease{
|
||||
Spec: v1beta1.BatchReleaseSpec{ReleasePlan: v1beta1.ReleasePlan{RolloutID: id, FailureThreshold: f}},
|
||||
Status: v1beta1.BatchReleaseStatus{UpdateRevision: revision},
|
||||
}
|
||||
}
|
||||
cases := map[string]struct {
|
||||
release *v1alpha1.BatchRelease
|
||||
release *v1beta1.BatchRelease
|
||||
pods []*corev1.Pod
|
||||
maxUnavailable *intstr.IntOrString
|
||||
labelDesired int32
|
||||
|
@ -151,11 +152,11 @@ func TestIsBatchReady(t *testing.T) {
|
|||
func generatePods(updatedReplicas, noNeedRollbackReplicas int) []*corev1.Pod {
|
||||
podsNoNeed := generatePodsWith(map[string]string{
|
||||
util.NoNeedUpdatePodLabel: "0x1",
|
||||
v1alpha1.RolloutIDLabel: "1",
|
||||
v1beta1.RolloutIDLabel: "1",
|
||||
apps.ControllerRevisionHashLabelKey: "version-1",
|
||||
}, noNeedRollbackReplicas, 0)
|
||||
return append(generatePodsWith(map[string]string{
|
||||
v1alpha1.RolloutIDLabel: "1",
|
||||
v1beta1.RolloutIDLabel: "1",
|
||||
apps.ControllerRevisionHashLabelKey: "version-1",
|
||||
}, updatedReplicas-noNeedRollbackReplicas, noNeedRollbackReplicas), podsNoNeed...)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
Copyright 2022 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 control
|
||||
|
||||
import "k8s.io/apimachinery/pkg/util/intstr"
|
||||
|
||||
// OriginalDeploymentStrategy stores part of the fileds of a workload,
|
||||
// so that it can be restored when finalizing.
|
||||
// It is only used for BlueGreen Release
|
||||
// Similar to DeploymentStrategy, it is an annotation used in workload
|
||||
// However, unlike DeploymentStrategy, it is only used to store and restore the user's strategy
|
||||
type OriginalDeploymentStrategy struct {
|
||||
// +optional
|
||||
MaxUnavailable *intstr.IntOrString `json:"maxUnavailable,omitempty" protobuf:"bytes,1,opt,name=maxUnavailable"`
|
||||
// +optional
|
||||
MaxSurge *intstr.IntOrString `json:"maxSurge,omitempty" protobuf:"bytes,2,opt,name=maxSurge"`
|
||||
// Minimum number of seconds for which a newly created pod should be ready
|
||||
// without any of its container crashing, for it to be considered available.
|
||||
// Defaults to 0 (pod will be considered available as soon as it is ready)
|
||||
// +optional
|
||||
MinReadySeconds int32 `json:"minReadySeconds,omitempty" protobuf:"varint,5,opt,name=minReadySeconds"`
|
||||
// The maximum time in seconds for a deployment to make progress before it
|
||||
// is considered to be failed. The deployment controller will continue to
|
||||
// process failed deployments and a condition with a ProgressDeadlineExceeded
|
||||
// reason will be surfaced in the deployment status. Note that progress will
|
||||
// not be estimated during the time a deployment is paused. Defaults to 600s.
|
||||
ProgressDeadlineSeconds *int32 `json:"progressDeadlineSeconds,omitempty" protobuf:"varint,9,opt,name=progressDeadlineSeconds"`
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue