mirror of
https://github.com/kubevela/kubevela.git
synced 2026-02-25 23:33:58 +00:00
Compare commits
60 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
18d93039c9 | ||
|
|
8ffd80e4a7 | ||
|
|
735075f5a6 | ||
|
|
52d1a4364b | ||
|
|
1b7f9aae65 | ||
|
|
e94519b788 | ||
|
|
18d755ed72 | ||
|
|
c15d0e4e0f | ||
|
|
82ce9daf38 | ||
|
|
6eef47c5e0 | ||
|
|
7728de933b | ||
|
|
5ceb193ebe | ||
|
|
186ab37547 | ||
|
|
5a98541e8e | ||
|
|
d599e63ec9 | ||
|
|
055a50fad8 | ||
|
|
7921475af2 | ||
|
|
caf09b81b0 | ||
|
|
4c525f8e5d | ||
|
|
bdf71bb290 | ||
|
|
5873ba4c47 | ||
|
|
9ded3c9d3e | ||
|
|
56c2827669 | ||
|
|
b6a7d8621f | ||
|
|
b80f673f69 | ||
|
|
e14dd09872 | ||
|
|
e31bacbb05 | ||
|
|
e602c0420b | ||
|
|
68e3c7cfc7 | ||
|
|
a5b8cfc9fb | ||
|
|
fce308d234 | ||
|
|
3c9f359e60 | ||
|
|
e5b0149ce5 | ||
|
|
83fd9edcfe | ||
|
|
f986073273 | ||
|
|
17872f9705 | ||
|
|
e463dbf1fb | ||
|
|
44142c4c70 | ||
|
|
e460638799 | ||
|
|
58ca3a820d | ||
|
|
63b31be38e | ||
|
|
06f10d4026 | ||
|
|
7a2b18b78a | ||
|
|
52ee87df16 | ||
|
|
3177d26fc4 | ||
|
|
3df1776b37 | ||
|
|
a6434c3efa | ||
|
|
766594d625 | ||
|
|
f7bd17edd7 | ||
|
|
5213e54466 | ||
|
|
939556a698 | ||
|
|
c8d89a1856 | ||
|
|
891429c5f5 | ||
|
|
8b6dbd781f | ||
|
|
7916e874c5 | ||
|
|
8f78189a79 | ||
|
|
6d979cfcab | ||
|
|
491127daec | ||
|
|
1829cf4e40 | ||
|
|
b0facbeaab |
71
.github/workflows/apiserver-test.yaml
vendored
71
.github/workflows/apiserver-test.yaml
vendored
@@ -19,9 +19,8 @@ env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.17'
|
||||
GOLANGCI_VERSION: 'v1.38'
|
||||
KIND_VERSION: 'v0.7.0'
|
||||
KIND_IMAGE_VERSION: '[\"v1.20.7\"]'
|
||||
KIND_IMAGE_VERSIONS: '[\"v1.18.20\",\"v1.20.7\",\"v1.22.7\"]'
|
||||
K3D_IMAGE_VERSION: '[\"v1.20\",\"v1.24\"]'
|
||||
K3D_IMAGE_VERSIONS: '[\"v1.20\",\"v1.24\"]'
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -48,9 +47,9 @@ jobs:
|
||||
run: |
|
||||
if [[ "${{ github.ref }}" == refs/tags/v* ]]; then
|
||||
echo "pushing tag: ${{ github.ref_name }}"
|
||||
echo "::set-output name=matrix::${{ env.KIND_IMAGE_VERSIONS }}"
|
||||
echo "::set-output name=matrix::${{ env.K3D_IMAGE_VERSIONS }}"
|
||||
else
|
||||
echo "::set-output name=matrix::${{ env.KIND_IMAGE_VERSION }}"
|
||||
echo "::set-output name=matrix::${{ env.K3D_IMAGE_VERSION }}"
|
||||
fi
|
||||
|
||||
apiserver-unit-tests:
|
||||
@@ -105,12 +104,15 @@ jobs:
|
||||
name: codecov-umbrella
|
||||
|
||||
apiserver-e2e-tests:
|
||||
runs-on: aliyun
|
||||
runs-on: aliyun-legacy
|
||||
needs: [ detect-noop,set-k8s-matrix ]
|
||||
if: needs.detect-noop.outputs.noop != 'true'
|
||||
strategy:
|
||||
matrix:
|
||||
k8s-version: ${{ fromJson(needs.set-k8s-matrix.outputs.matrix) }}
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}-${{ matrix.k8s-version }}
|
||||
cancel-in-progress: true
|
||||
|
||||
steps:
|
||||
- name: Set up Go
|
||||
@@ -128,35 +130,50 @@ jobs:
|
||||
run: |
|
||||
go get -v -t -d ./...
|
||||
|
||||
- name: Setup Kind
|
||||
uses: engineerd/setup-kind@v0.5.0
|
||||
- name: Tear down K3d if exist
|
||||
run: |
|
||||
k3d cluster delete || true
|
||||
k3d cluster delete worker || true
|
||||
|
||||
- name: Calculate K3d args
|
||||
run: |
|
||||
EGRESS_ARG=""
|
||||
if [[ "${{ matrix.k8s-version }}" == v1.24 ]]; then
|
||||
EGRESS_ARG="--k3s-arg --egress-selector-mode=disabled@server:0"
|
||||
fi
|
||||
echo "EGRESS_ARG=${EGRESS_ARG}" >> $GITHUB_ENV
|
||||
|
||||
- name: Setup K3d (Hub)
|
||||
uses: nolar/setup-k3d-k3s@v1.0.8
|
||||
with:
|
||||
version: ${{ env.KIND_VERSION }}
|
||||
skipClusterCreation: true
|
||||
version: ${{ matrix.k8s-version }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
k3d-args: ${{ env.EGRESS_ARG }}
|
||||
|
||||
- name: Setup Kind Cluster (Worker)
|
||||
|
||||
- name: Setup K3d (Worker)
|
||||
uses: nolar/setup-k3d-k3s@v1.0.8
|
||||
with:
|
||||
version: ${{ matrix.k8s-version }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
k3d-name: worker
|
||||
k3d-args: --kubeconfig-update-default=false --network=k3d-k3s-default ${{ env.EGRESS_ARG }}
|
||||
|
||||
|
||||
- name: Kind Cluster (Worker)
|
||||
run: |
|
||||
kind delete cluster --name worker
|
||||
kind create cluster --image kindest/node:${{ matrix.k8s-version }} --name worker
|
||||
kubectl version
|
||||
kubectl cluster-info
|
||||
kind get kubeconfig --name worker --internal > /tmp/worker.kubeconfig
|
||||
kind get kubeconfig --name worker > /tmp/worker.client.kubeconfig
|
||||
internal_ip=$(docker network inspect k3d-k3s-default|jq ".[0].Containers"| jq -r '.[]| select(.Name=="k3d-worker-server-0")|.IPv4Address' | cut -d/ -f1)
|
||||
k3d kubeconfig get worker > /tmp/worker.client.kubeconfig
|
||||
cp /tmp/worker.client.kubeconfig /tmp/worker.kubeconfig
|
||||
sed -i "s/0.0.0.0:[0-9]\+/$internal_ip:6443/" /tmp/worker.kubeconfig
|
||||
|
||||
- name: Setup Kind Cluster (Hub)
|
||||
run: |
|
||||
kind delete cluster
|
||||
kind create cluster --image kindest/node:${{ matrix.k8s-version }}
|
||||
kubectl version
|
||||
kubectl cluster-info
|
||||
|
||||
- name: Load Image to kind cluster
|
||||
run: make kind-load
|
||||
- name: Load image to k3d cluster
|
||||
run: make image-load
|
||||
|
||||
- name: Cleanup for e2e tests
|
||||
run: |
|
||||
make e2e-cleanup
|
||||
make vela-cli
|
||||
make e2e-cleanup
|
||||
make e2e-setup-core
|
||||
bin/vela addon enable fluxcd
|
||||
timeout 600s bash -c -- 'while true; do kubectl get ns flux-system; if [ $? -eq 0 ] ; then break; else sleep 5; fi;done'
|
||||
|
||||
70
.github/workflows/e2e-multicluster-test.yml
vendored
70
.github/workflows/e2e-multicluster-test.yml
vendored
@@ -17,9 +17,8 @@ env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.17'
|
||||
GOLANGCI_VERSION: 'v1.38'
|
||||
KIND_VERSION: 'v0.7.0'
|
||||
KIND_IMAGE_VERSION: '[\"v1.20.7\"]'
|
||||
KIND_IMAGE_VERSIONS: '[\"v1.18.20\",\"v1.20.7\",\"v1.22.7\"]'
|
||||
K3D_IMAGE_VERSION: '[\"v1.20\",\"v1.24\"]'
|
||||
K3D_IMAGE_VERSIONS: '[\"v1.20\",\"v1.24\"]'
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -46,19 +45,22 @@ jobs:
|
||||
run: |
|
||||
if [[ "${{ github.ref }}" == refs/tags/v* ]]; then
|
||||
echo "pushing tag: ${{ github.ref_name }}"
|
||||
echo "::set-output name=matrix::${{ env.KIND_IMAGE_VERSIONS }}"
|
||||
echo "::set-output name=matrix::${{ env.K3D_IMAGE_VERSIONS }}"
|
||||
else
|
||||
echo "::set-output name=matrix::${{ env.KIND_IMAGE_VERSION }}"
|
||||
echo "::set-output name=matrix::${{ env.K3D_IMAGE_VERSION }}"
|
||||
fi
|
||||
|
||||
|
||||
e2e-multi-cluster-tests:
|
||||
runs-on: aliyun
|
||||
runs-on: aliyun-legacy
|
||||
needs: [ detect-noop,set-k8s-matrix ]
|
||||
if: needs.detect-noop.outputs.noop != 'true'
|
||||
strategy:
|
||||
matrix:
|
||||
k8s-version: ${{ fromJson(needs.set-k8s-matrix.outputs.matrix) }}
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}-${{ matrix.k8s-version }}
|
||||
cancel-in-progress: true
|
||||
|
||||
|
||||
steps:
|
||||
@@ -74,37 +76,49 @@ jobs:
|
||||
run: |
|
||||
go get -v -t -d ./...
|
||||
|
||||
- name: Setup Kind
|
||||
uses: engineerd/setup-kind@v0.5.0
|
||||
- name: Tear down K3d if exist
|
||||
run: |
|
||||
k3d cluster delete || true
|
||||
k3d cluster delete worker || true
|
||||
|
||||
- name: Calculate K3d args
|
||||
run: |
|
||||
EGRESS_ARG=""
|
||||
if [[ "${{ matrix.k8s-version }}" == v1.24 ]]; then
|
||||
EGRESS_ARG="--k3s-arg --egress-selector-mode=disabled@server:0"
|
||||
fi
|
||||
echo "EGRESS_ARG=${EGRESS_ARG}" >> $GITHUB_ENV
|
||||
|
||||
- name: Setup K3d (Hub)
|
||||
uses: nolar/setup-k3d-k3s@v1.0.8
|
||||
with:
|
||||
version: ${{ env.KIND_VERSION }}
|
||||
skipClusterCreation: true
|
||||
version: ${{ matrix.k8s-version }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
k3d-args: ${{ env.EGRESS_ARG }}
|
||||
|
||||
- name: Setup Kind Cluster (Worker)
|
||||
- name: Setup K3d (Worker)
|
||||
uses: nolar/setup-k3d-k3s@v1.0.8
|
||||
with:
|
||||
version: ${{ matrix.k8s-version }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
k3d-name: worker
|
||||
k3d-args: --kubeconfig-update-default=false --network=k3d-k3s-default ${{ env.EGRESS_ARG }}
|
||||
|
||||
- name: Generating internal worker kubeconfig
|
||||
run: |
|
||||
kind delete cluster --name worker
|
||||
kind create cluster --image kindest/node:${{ matrix.k8s-version }} --name worker
|
||||
kubectl version
|
||||
kubectl cluster-info
|
||||
kind get kubeconfig --name worker --internal > /tmp/worker.kubeconfig
|
||||
kind get kubeconfig --name worker > /tmp/worker.client.kubeconfig
|
||||
internal_ip=$(docker network inspect k3d-k3s-default|jq ".[0].Containers"| jq -r '.[]| select(.Name=="k3d-worker-server-0")|.IPv4Address' | cut -d/ -f1)
|
||||
k3d kubeconfig get worker > /tmp/worker.client.kubeconfig
|
||||
cp /tmp/worker.client.kubeconfig /tmp/worker.kubeconfig
|
||||
sed -i "s/0.0.0.0:[0-9]\+/$internal_ip:6443/" /tmp/worker.kubeconfig
|
||||
|
||||
- name: Setup Kind Cluster (Hub)
|
||||
run: |
|
||||
kind delete cluster
|
||||
kind create cluster --image kindest/node:${{ matrix.k8s-version }}
|
||||
kubectl version
|
||||
kubectl cluster-info
|
||||
|
||||
- name: Load Image to kind cluster (Hub)
|
||||
run: make kind-load
|
||||
- name: Load image to k3d cluster (hub and worker)
|
||||
run: make image-load image-load-runtime-cluster
|
||||
|
||||
- name: Cleanup for e2e tests
|
||||
run: |
|
||||
make e2e-cleanup
|
||||
make vela-cli
|
||||
make e2e-cleanup
|
||||
make e2e-setup-core-auth
|
||||
make
|
||||
make setup-runtime-e2e-cluster
|
||||
|
||||
- name: Run e2e multicluster tests
|
||||
|
||||
55
.github/workflows/e2e-rollout-test.yml
vendored
55
.github/workflows/e2e-rollout-test.yml
vendored
@@ -17,9 +17,8 @@ env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.17'
|
||||
GOLANGCI_VERSION: 'v1.38'
|
||||
KIND_VERSION: 'v0.7.0'
|
||||
KIND_IMAGE_VERSION: '[\"v1.20.7\"]'
|
||||
KIND_IMAGE_VERSIONS: '[\"v1.18.20\",\"v1.20.7\",\"v1.22.7\"]'
|
||||
K3D_IMAGE_VERSION: '[\"v1.20\",\"v1.24\"]'
|
||||
K3D_IMAGE_VERSIONS: '[\"v1.20\",\"v1.24\"]'
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -46,18 +45,22 @@ jobs:
|
||||
run: |
|
||||
if [[ "${{ github.ref }}" == refs/tags/v* ]]; then
|
||||
echo "pushing tag: ${{ github.ref_name }}"
|
||||
echo "::set-output name=matrix::${{ env.KIND_IMAGE_VERSIONS }}"
|
||||
echo "::set-output name=matrix::${{ env.K3D_IMAGE_VERSIONS }}"
|
||||
else
|
||||
echo "::set-output name=matrix::${{ env.KIND_IMAGE_VERSION }}"
|
||||
echo "::set-output name=matrix::${{ env.K3D_IMAGE_VERSION }}"
|
||||
fi
|
||||
|
||||
e2e-rollout-tests:
|
||||
runs-on: aliyun
|
||||
runs-on: aliyun-legacy
|
||||
needs: [ detect-noop,set-k8s-matrix ]
|
||||
if: needs.detect-noop.outputs.noop != 'true'
|
||||
strategy:
|
||||
matrix:
|
||||
k8s-version: ${{ fromJson(needs.set-k8s-matrix.outputs.matrix) }}
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}-${{ matrix.k8s-version }}
|
||||
cancel-in-progress: true
|
||||
|
||||
|
||||
steps:
|
||||
- name: Check out code into the Go module directory
|
||||
@@ -72,33 +75,35 @@ jobs:
|
||||
run: |
|
||||
go get -v -t -d ./...
|
||||
|
||||
- name: Setup Kind
|
||||
uses: engineerd/setup-kind@v0.5.0
|
||||
with:
|
||||
version: ${{ env.KIND_VERSION }}
|
||||
skipClusterCreation: true
|
||||
|
||||
- name: Setup Kind Cluster
|
||||
- name: Tear down K3d if exist
|
||||
run: |
|
||||
kind delete cluster
|
||||
kind create cluster --image kindest/node:${{ matrix.k8s-version }}
|
||||
kubectl version
|
||||
kubectl cluster-info
|
||||
k3d cluster delete || true
|
||||
k3d cluster delete worker || true
|
||||
|
||||
- name: Load Image to kind cluster
|
||||
run: make kind-load
|
||||
- name: Calculate K3d args
|
||||
run: |
|
||||
EGRESS_ARG=""
|
||||
if [[ "${{ matrix.k8s-version }}" == v1.24 ]]; then
|
||||
EGRESS_ARG="--k3s-arg --egress-selector-mode=disabled@server:0"
|
||||
fi
|
||||
echo "EGRESS_ARG=${EGRESS_ARG}" >> $GITHUB_ENV
|
||||
|
||||
- name: Run Make
|
||||
run: make
|
||||
- name: Setup K3d
|
||||
uses: nolar/setup-k3d-k3s@v1.0.8
|
||||
with:
|
||||
version: ${{ matrix.k8s-version }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
k3d-args: ${{ env.EGRESS_ARG }}
|
||||
|
||||
- name: Run Make Manager
|
||||
run: make manager
|
||||
- name: Load image to k3d cluster
|
||||
run: make image-load image-load-runtime-cluster
|
||||
|
||||
- name: Prepare for e2e tests
|
||||
run: |
|
||||
make vela-cli
|
||||
make e2e-cleanup
|
||||
make e2e-setup
|
||||
helm lint ./charts/vela-core
|
||||
make e2e-setup-core
|
||||
make setup-runtime-e2e-cluster
|
||||
helm test -n vela-system kubevela --timeout 5m
|
||||
|
||||
- name: Run e2e tests
|
||||
|
||||
54
.github/workflows/e2e-test.yml
vendored
54
.github/workflows/e2e-test.yml
vendored
@@ -17,9 +17,8 @@ env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.17'
|
||||
GOLANGCI_VERSION: 'v1.38'
|
||||
KIND_VERSION: 'v0.7.0'
|
||||
KIND_IMAGE_VERSION: '[\"v1.20.7\"]'
|
||||
KIND_IMAGE_VERSIONS: '[\"v1.18.20\",\"v1.20.7\",\"v1.22.7\"]'
|
||||
K3D_IMAGE_VERSION: '[\"v1.20\",\"v1.24\"]'
|
||||
K3D_IMAGE_VERSIONS: '[\"v1.20\",\"v1.24\"]'
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -46,18 +45,22 @@ jobs:
|
||||
run: |
|
||||
if [[ "${{ github.ref }}" == refs/tags/v* ]]; then
|
||||
echo "pushing tag: ${{ github.ref_name }}"
|
||||
echo "::set-output name=matrix::${{ env.KIND_IMAGE_VERSIONS }}"
|
||||
echo "::set-output name=matrix::${{ env.K3D_IMAGE_VERSIONS }}"
|
||||
else
|
||||
echo "::set-output name=matrix::${{ env.KIND_IMAGE_VERSION }}"
|
||||
echo "::set-output name=matrix::${{ env.K3D_IMAGE_VERSION }}"
|
||||
fi
|
||||
|
||||
e2e-tests:
|
||||
runs-on: aliyun
|
||||
runs-on: aliyun-legacy
|
||||
needs: [ detect-noop,set-k8s-matrix ]
|
||||
if: needs.detect-noop.outputs.noop != 'true'
|
||||
strategy:
|
||||
matrix:
|
||||
k8s-version: ${{ fromJson(needs.set-k8s-matrix.outputs.matrix) }}
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}-${{ matrix.k8s-version }}
|
||||
cancel-in-progress: true
|
||||
|
||||
|
||||
steps:
|
||||
- name: Check out code into the Go module directory
|
||||
@@ -72,33 +75,36 @@ jobs:
|
||||
run: |
|
||||
go get -v -t -d ./...
|
||||
|
||||
- name: Setup Kind
|
||||
uses: engineerd/setup-kind@v0.5.0
|
||||
with:
|
||||
version: ${{ env.KIND_VERSION }}
|
||||
skipClusterCreation: true
|
||||
|
||||
- name: Setup Kind Cluster
|
||||
- name: Tear down K3d if exist
|
||||
run: |
|
||||
kind delete cluster
|
||||
kind create cluster --image kindest/node:${{ matrix.k8s-version }}
|
||||
kubectl version
|
||||
kubectl cluster-info
|
||||
k3d cluster delete || true
|
||||
k3d cluster delete worker || true
|
||||
|
||||
- name: Load Image to kind cluster
|
||||
run: make kind-load
|
||||
- name: Calculate K3d args
|
||||
run: |
|
||||
EGRESS_ARG=""
|
||||
if [[ "${{ matrix.k8s-version }}" == v1.24 ]]; then
|
||||
EGRESS_ARG="--k3s-arg --egress-selector-mode=disabled@server:0"
|
||||
fi
|
||||
echo "EGRESS_ARG=${EGRESS_ARG}" >> $GITHUB_ENV
|
||||
|
||||
- name: Setup K3d
|
||||
uses: nolar/setup-k3d-k3s@v1.0.8
|
||||
with:
|
||||
version: ${{ matrix.k8s-version }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
k3d-args: ${{ env.EGRESS_ARG }}
|
||||
|
||||
- name: Load image to k3d cluster
|
||||
run: make image-load
|
||||
|
||||
- name: Run Make
|
||||
run: make
|
||||
|
||||
- name: Run Make Manager
|
||||
run: make manager
|
||||
|
||||
- name: Prepare for e2e tests
|
||||
run: |
|
||||
make e2e-cleanup
|
||||
make e2e-setup
|
||||
helm lint ./charts/vela-core
|
||||
make e2e-setup-core
|
||||
helm test -n vela-system kubevela --timeout 5m
|
||||
|
||||
- name: Run api e2e tests
|
||||
|
||||
3
.github/workflows/go.yml
vendored
3
.github/workflows/go.yml
vendored
@@ -15,7 +15,6 @@ env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.17'
|
||||
GOLANGCI_VERSION: 'v1.38'
|
||||
KIND_VERSION: 'v0.7.0'
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -98,7 +97,7 @@ jobs:
|
||||
version: ${{ env.GOLANGCI_VERSION }}
|
||||
|
||||
check-diff:
|
||||
runs-on: aliyun
|
||||
runs-on: aliyun-legacy
|
||||
needs: detect-noop
|
||||
if: needs.detect-noop.outputs.noop != 'true'
|
||||
|
||||
|
||||
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@@ -150,11 +150,15 @@ jobs:
|
||||
- name: Display structure of downloaded files
|
||||
run: ls -R
|
||||
working-directory: cli-artifacts
|
||||
- name: Get version
|
||||
run: echo "VELA_VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
|
||||
- shell: bash
|
||||
working-directory: cli-artifacts
|
||||
run: |
|
||||
for file in *
|
||||
do
|
||||
sed -i "s/\/vela/-${{ env.VELA_VERSION }}/g" ${file}
|
||||
sed -i "s/\/kubectl-vela/-${{ env.VELA_VERSION }}/g" ${file}
|
||||
cat ${file} >> sha256sums.txt
|
||||
done
|
||||
- name: Upload Checksums
|
||||
|
||||
2
.github/workflows/timed-task.yml
vendored
2
.github/workflows/timed-task.yml
vendored
@@ -4,7 +4,7 @@ on:
|
||||
- cron: '* * * * *'
|
||||
jobs:
|
||||
clean-image:
|
||||
runs-on: aliyun
|
||||
runs-on: aliyun-legacy
|
||||
steps:
|
||||
- name: Cleanup image
|
||||
run: docker image prune -f
|
||||
8
.github/workflows/unit-test.yml
vendored
8
.github/workflows/unit-test.yml
vendored
@@ -15,7 +15,6 @@ env:
|
||||
# Common versions
|
||||
GO_VERSION: '1.17'
|
||||
GOLANGCI_VERSION: 'v1.38'
|
||||
KIND_VERSION: 'v0.7.0'
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -61,10 +60,11 @@ jobs:
|
||||
run: |
|
||||
sudo apt-get install -y golang-ginkgo-dev
|
||||
|
||||
- name: Setup Kind Cluster
|
||||
uses: engineerd/setup-kind@v0.5.0
|
||||
- name: Setup K3d
|
||||
uses: nolar/setup-k3d-k3s@v1.0.8
|
||||
with:
|
||||
version: ${{ env.KIND_VERSION }}
|
||||
version: v1.20
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: install Kubebuilder
|
||||
uses: RyanSiu1995/kubebuilder-action@v1.2
|
||||
|
||||
12
Makefile
12
Makefile
@@ -82,17 +82,17 @@ endif
|
||||
|
||||
|
||||
|
||||
# load docker image to the kind cluster
|
||||
kind-load: kind-load-runtime-cluster
|
||||
# load docker image to the k3d cluster
|
||||
image-load:
|
||||
docker build -t $(VELA_CORE_TEST_IMAGE) -f Dockerfile.e2e .
|
||||
kind load docker-image $(VELA_CORE_TEST_IMAGE) || { echo >&2 "kind not installed or error loading image: $(VELA_CORE_TEST_IMAGE)"; exit 1; }
|
||||
k3d image import $(VELA_CORE_TEST_IMAGE) || { echo >&2 "kind not installed or error loading image: $(VELA_CORE_TEST_IMAGE)"; exit 1; }
|
||||
|
||||
kind-load-runtime-cluster:
|
||||
image-load-runtime-cluster:
|
||||
/bin/sh hack/e2e/build_runtime_rollout.sh
|
||||
docker build -t $(VELA_RUNTIME_ROLLOUT_TEST_IMAGE) -f runtime/rollout/e2e/Dockerfile.e2e runtime/rollout/e2e/
|
||||
rm -rf runtime/rollout/e2e/tmp
|
||||
kind load docker-image $(VELA_RUNTIME_ROLLOUT_TEST_IMAGE) || { echo >&2 "kind not installed or error loading image: $(VELA_RUNTIME_ROLLOUT_TEST_IMAGE)"; exit 1; }
|
||||
kind load docker-image $(VELA_RUNTIME_ROLLOUT_TEST_IMAGE) --name=$(RUNTIME_CLUSTER_NAME) || { echo >&2 "kind not installed or error loading image: $(VELA_RUNTIME_ROLLOUT_TEST_IMAGE)"; exit 1; }
|
||||
k3d image import $(VELA_RUNTIME_ROLLOUT_TEST_IMAGE) || { echo >&2 "kind not installed or error loading image: $(VELA_RUNTIME_ROLLOUT_TEST_IMAGE)"; exit 1; }
|
||||
k3d cluster get $(RUNTIME_CLUSTER_NAME) && k3d image import $(VELA_RUNTIME_ROLLOUT_TEST_IMAGE) --cluster=$(RUNTIME_CLUSTER_NAME) || echo "no worker cluster"
|
||||
|
||||
# Run tests
|
||||
core-test: fmt vet manifests
|
||||
|
||||
@@ -53,15 +53,7 @@ func (in ApplyOncePolicySpec) FindStrategy(manifest *unstructured.Unstructured)
|
||||
return nil
|
||||
}
|
||||
for _, rule := range in.Rules {
|
||||
match := func(src []string, val string) (found bool) {
|
||||
for _, _val := range src {
|
||||
found = found || _val == val
|
||||
}
|
||||
return val != "" && found
|
||||
}
|
||||
if (match(rule.Selector.CompNames, manifest.GetName()) && match(rule.Selector.ResourceTypes, manifest.GetKind())) ||
|
||||
(rule.Selector.CompNames == nil && match(rule.Selector.ResourceTypes, manifest.GetKind()) ||
|
||||
(rule.Selector.ResourceTypes == nil && match(rule.Selector.CompNames, manifest.GetName()))) {
|
||||
if rule.Selector.Match(manifest) {
|
||||
return rule.Strategy
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package v1alpha1
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/utils/pointer"
|
||||
"k8s.io/utils/strings/slices"
|
||||
|
||||
"github.com/oam-dev/kubevela/pkg/oam"
|
||||
@@ -57,10 +58,7 @@ type GarbageCollectPolicyRule struct {
|
||||
}
|
||||
|
||||
// ResourcePolicyRuleSelector select the targets of the rule
|
||||
// 1) for GarbageCollectPolicyRule
|
||||
// if both traitTypes, oamTypes and componentTypes are specified, combination logic is OR
|
||||
// if one resource is specified with conflict strategies, strategy as component go first.
|
||||
// 2) for ApplyOncePolicyRule only CompNames and ResourceTypes are used
|
||||
// if multiple conditions are specified, combination logic is AND
|
||||
type ResourcePolicyRuleSelector struct {
|
||||
CompNames []string `json:"componentNames,omitempty"`
|
||||
CompTypes []string `json:"componentTypes,omitempty"`
|
||||
@@ -71,6 +69,8 @@ type ResourcePolicyRuleSelector struct {
|
||||
}
|
||||
|
||||
// Match check if current rule selector match the target resource
|
||||
// If at least one condition is matched and no other condition failed (could be empty), return true
|
||||
// Otherwise, return false
|
||||
func (in *ResourcePolicyRuleSelector) Match(manifest *unstructured.Unstructured) bool {
|
||||
var compName, compType, oamType, traitType, resourceType, resourceName string
|
||||
if labels := manifest.GetLabels(); labels != nil {
|
||||
@@ -81,15 +81,33 @@ func (in *ResourcePolicyRuleSelector) Match(manifest *unstructured.Unstructured)
|
||||
}
|
||||
resourceType = manifest.GetKind()
|
||||
resourceName = manifest.GetName()
|
||||
match := func(src []string, val string) (found bool) {
|
||||
return val != "" && slices.Contains(src, val)
|
||||
match := func(src []string, val string) (found *bool) {
|
||||
if len(src) == 0 {
|
||||
return nil
|
||||
}
|
||||
return pointer.Bool(val != "" && slices.Contains(src, val))
|
||||
}
|
||||
return match(in.CompNames, compName) ||
|
||||
match(in.CompTypes, compType) ||
|
||||
match(in.OAMResourceTypes, oamType) ||
|
||||
match(in.TraitTypes, traitType) ||
|
||||
match(in.ResourceTypes, resourceType) ||
|
||||
match(in.ResourceNames, resourceName)
|
||||
conditions := []*bool{
|
||||
match(in.CompNames, compName),
|
||||
match(in.CompTypes, compType),
|
||||
match(in.OAMResourceTypes, oamType),
|
||||
match(in.TraitTypes, traitType),
|
||||
match(in.ResourceTypes, resourceType),
|
||||
match(in.ResourceNames, resourceName),
|
||||
}
|
||||
hasMatched := false
|
||||
for _, cond := range conditions {
|
||||
// if any non-empty condition failed, return false
|
||||
if cond != nil && !*cond {
|
||||
return false
|
||||
}
|
||||
// if condition succeed, record it
|
||||
if cond != nil && *cond {
|
||||
hasMatched = true
|
||||
}
|
||||
}
|
||||
// if at least one condition is met, return true
|
||||
return hasMatched
|
||||
}
|
||||
|
||||
// GarbageCollectStrategy the strategy for target resource to recycle
|
||||
|
||||
@@ -123,12 +123,13 @@ func (in ManagedResource) NamespacedName() types.NamespacedName {
|
||||
|
||||
// ResourceKey computes the key for managed resource, resources with the same key points to the same resource
|
||||
func (in ManagedResource) ResourceKey() string {
|
||||
gv, kind := in.GroupVersionKind().ToAPIVersionAndKind()
|
||||
group := in.GroupVersionKind().Group
|
||||
kind := in.GroupVersionKind().Kind
|
||||
cluster := in.Cluster
|
||||
if cluster == "" {
|
||||
cluster = velatypes.ClusterLocalName
|
||||
}
|
||||
return strings.Join([]string{gv, kind, cluster, in.Namespace, in.Name}, "/")
|
||||
return strings.Join([]string{group, kind, cluster, in.Namespace, in.Name}, "/")
|
||||
}
|
||||
|
||||
// ComponentKey computes the key for the component which managed resource belongs to
|
||||
|
||||
@@ -125,7 +125,7 @@ func TestManagedResourceKeys(t *testing.T) {
|
||||
},
|
||||
}
|
||||
r.Equal("namespace/name", input.NamespacedName().String())
|
||||
r.Equal("apps/v1/Deployment/cluster/namespace/name", input.ResourceKey())
|
||||
r.Equal("apps/Deployment/cluster/namespace/name", input.ResourceKey())
|
||||
r.Equal("env/component", input.ComponentKey())
|
||||
r.Equal("Deployment name (Cluster: cluster, Namespace: namespace)", input.DisplayName())
|
||||
var deploy1, deploy2 v12.Deployment
|
||||
|
||||
@@ -5,8 +5,6 @@ kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Add annotations on your workload. if it generates pod, add same annotations for generated pods.
|
||||
labels:
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: annotations
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
|
||||
@@ -5,8 +5,6 @@ kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Add command on K8s pod for your workload which follows the pod spec in path 'spec.template'
|
||||
labels:
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: command
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
|
||||
@@ -5,8 +5,6 @@ kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Set the image of the container.
|
||||
labels:
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: container-image
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
|
||||
@@ -5,8 +5,6 @@ kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Automatically scale the component based on CPU usage.
|
||||
labels:
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: cpuscaler
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
|
||||
@@ -5,8 +5,6 @@ kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Add env on K8s pod for your workload which follows the pod spec in path 'spec.template'
|
||||
labels:
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: env
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
|
||||
@@ -5,8 +5,6 @@ kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Expose port to enable web traffic for your component.
|
||||
labels:
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: expose
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
|
||||
@@ -104,7 +104,7 @@ spec:
|
||||
message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host + ", IP: " + igs[0].ip
|
||||
}
|
||||
if igs[0].host == _|_ {
|
||||
message: "Host not specified, visit the cluster or load balancer in front of the cluster"
|
||||
message: "Host not specified, visit the cluster or load balancer in front of the cluster with IP: " + igs[0].ip
|
||||
}
|
||||
}
|
||||
if igs[0].ip == _|_ {
|
||||
|
||||
@@ -5,8 +5,6 @@ kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Add host aliases on K8s pod for your workload which follows the pod spec in path 'spec.template'.
|
||||
labels:
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: hostalias
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
# Code generated by KubeVela templates. DO NOT EDIT. Please edit the original cue file.
|
||||
# Definition source cue file: vela-templates/definitions/internal/import-grafana-dashboard.cue
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Import dashboards to Grafana
|
||||
labels:
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: import-grafana-dashboard
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads: []
|
||||
conflictsWith: []
|
||||
podDisruptive: false
|
||||
schematic:
|
||||
cue:
|
||||
template: |
|
||||
outputs: registerdatasource: {
|
||||
apiVersion: "grafana.extension.oam.dev/v1alpha1"
|
||||
kind: "ImportDashboard"
|
||||
spec: {
|
||||
grafana: {
|
||||
service: parameter.grafanaServiceName
|
||||
namespace: parameter.grafanaServiceNamespace
|
||||
credentialSecret: parameter.credentialSecret
|
||||
credentialSecretNamespace: parameter.credentialSecretNamespace
|
||||
}
|
||||
urls: parameter.urls
|
||||
}
|
||||
}
|
||||
parameter: {
|
||||
grafanaServiceName: string
|
||||
grafanaServiceNamespace: *"default" | string
|
||||
credentialSecret: string
|
||||
credentialSecretNamespace: *"default" | string
|
||||
urls: [...string]
|
||||
|
||||
}
|
||||
workloadRefPath: ""
|
||||
|
||||
@@ -5,8 +5,6 @@ kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: add an init container and use shared volume with pod
|
||||
labels:
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: init-container
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
@@ -30,8 +28,9 @@ spec:
|
||||
}]
|
||||
}]
|
||||
initContainers: [{
|
||||
name: parameter.name
|
||||
image: parameter.image
|
||||
name: parameter.name
|
||||
image: parameter.image
|
||||
imagePullPolicy: parameter.imagePullPolicy
|
||||
if parameter.cmd != _|_ {
|
||||
command: parameter.cmd
|
||||
}
|
||||
@@ -61,6 +60,9 @@ spec:
|
||||
// +usage=Specify the image of init container
|
||||
image: string
|
||||
|
||||
// +usage=Specify image pull policy for your service
|
||||
imagePullPolicy: *"IfNotPresent" | "Always" | "Never"
|
||||
|
||||
// +usage=Specify the commands run in the init container
|
||||
cmd?: [...string]
|
||||
|
||||
|
||||
@@ -5,8 +5,6 @@ kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Add labels on your workload. if it generates pod, add same label for generated pods.
|
||||
labels:
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: labels
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
|
||||
@@ -5,8 +5,6 @@ kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Add lifecycle hooks for every container of K8s pod for your workload which follows the pod spec in path 'spec.template'.
|
||||
labels:
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: lifecycle
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
# Code generated by KubeVela templates. DO NOT EDIT. Please edit the original cue file.
|
||||
# Definition source cue file: vela-templates/definitions/internal/register-grafana-datasource.cue
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Add a datasource to Grafana
|
||||
labels:
|
||||
custom.definition.oam.dev/deprecated: "true"
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: register-grafana-datasource
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads: []
|
||||
conflictsWith: []
|
||||
podDisruptive: false
|
||||
schematic:
|
||||
cue:
|
||||
template: |
|
||||
outputs: registerdatasource: {
|
||||
apiVersion: "grafana.extension.oam.dev/v1alpha1"
|
||||
kind: "DatasourceRegistration"
|
||||
spec: {
|
||||
grafana: {
|
||||
service: parameter.grafanaServiceName
|
||||
namespace: parameter.grafanaServiceNamespace
|
||||
credentialSecret: parameter.credentialSecret
|
||||
credentialSecretNamespace: parameter.credentialSecretNamespace
|
||||
}
|
||||
datasource: {
|
||||
name: parameter.name
|
||||
type: parameter.type
|
||||
access: parameter.access
|
||||
service: parameter.service
|
||||
namespace: parameter.namespace
|
||||
}
|
||||
}
|
||||
}
|
||||
parameter: {
|
||||
grafanaServiceName: string
|
||||
grafanaServiceNamespace: *"default" | string
|
||||
credentialSecret: string
|
||||
credentialSecretNamespace: string
|
||||
name: string
|
||||
type: string
|
||||
access: *"proxy" | string
|
||||
service: string
|
||||
namespace: *"default" | string
|
||||
}
|
||||
workloadRefPath: ""
|
||||
|
||||
@@ -5,8 +5,6 @@ kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Add resource requests and limits on K8s pod for your workload which follows the pod spec in path 'spec.template.'
|
||||
labels:
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: resource
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# Code generated by KubeVela templates. DO NOT EDIT. Please edit the original cue file.
|
||||
# Definition source cue file: vela-templates/definitions/internal/shared-resource.cue
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: PolicyDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Configure the resources to be sharable across applications.
|
||||
name: shared-resource
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
schematic:
|
||||
cue:
|
||||
template: |
|
||||
#SharedResourcePolicyRule: {
|
||||
// +usage=Specify how to select the targets of the rule
|
||||
selector: [...#ResourcePolicyRuleSelector]
|
||||
}
|
||||
#ResourcePolicyRuleSelector: {
|
||||
// +usage=Select resources by component names
|
||||
componentNames?: [...string]
|
||||
// +usage=Select resources by component types
|
||||
componentTypes?: [...string]
|
||||
// +usage=Select resources by oamTypes (COMPONENT or TRAIT)
|
||||
oamTypes?: [...string]
|
||||
// +usage=Select resources by trait types
|
||||
traitTypes?: [...string]
|
||||
// +usage=Select resources by resource types (like Deployment)
|
||||
resourceTypes?: [...string]
|
||||
// +usage=Select resources by their names
|
||||
resourceNames?: [...string]
|
||||
}
|
||||
parameter: {
|
||||
// +usage=Specify the list of rules to control shared-resource strategy at resource level.
|
||||
// The selected resource will be sharable across applications. (That means multiple applications
|
||||
// can all read it without conflict, but only the first one can write it)
|
||||
rules?: [...#SharedResourcePolicyRule]
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Inject a sidecar container to K8s pod for your workload which follows the pod spec in path 'spec.template'.
|
||||
labels:
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: sidecar
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
|
||||
@@ -13,7 +13,7 @@ spec:
|
||||
template: |
|
||||
parameter: {
|
||||
// +usage=Specify the names of the clusters to select.
|
||||
cluster?: [...string]
|
||||
clusters?: [...string]
|
||||
// +usage=Specify the label selector for clusters
|
||||
clusterLabelSelector?: [string]: string
|
||||
// +usage=Deprecated: Use clusterLabelSelector instead.
|
||||
|
||||
@@ -306,6 +306,9 @@ spec:
|
||||
if v.name == _|_ {
|
||||
name: "port-" + strconv.FormatInt(v.port, 10)
|
||||
}
|
||||
if v.nodePort != _|_ && parameter.exposeType == "NodePort" {
|
||||
nodePort: v.nodePort
|
||||
}
|
||||
},
|
||||
]
|
||||
outputs: {
|
||||
@@ -354,6 +357,8 @@ spec:
|
||||
protocol: *"TCP" | "UDP" | "SCTP"
|
||||
// +usage=Specify if the port should be exposed
|
||||
expose: *false | bool
|
||||
// +usage=exposed node port. Only Valid when exposeType is NodePort
|
||||
nodePort?: int
|
||||
}]
|
||||
|
||||
// +ignore
|
||||
|
||||
@@ -33,7 +33,7 @@ kind: ClusterRole
|
||||
metadata:
|
||||
name: {{ include "kubevela.fullname" . }}:manager
|
||||
rules:
|
||||
- apiGroups: ["core.oam.dev", "terraform.core.oam.dev", "prism.oam.dev"]
|
||||
- apiGroups: ["core.oam.dev", "terraform.core.oam.dev", "prism.oam.dev", "standard.oam.dev"]
|
||||
resources: ["*"]
|
||||
verbs: ["*"]
|
||||
- apiGroups: ["cluster.open-cluster-management.io"]
|
||||
|
||||
@@ -13,12 +13,6 @@ spec:
|
||||
properties:
|
||||
image: {{ .Values.imageRegistry }}{{ .Values.test.app.repository }}:{{ .Values.test.app.tag }}
|
||||
port: 8000
|
||||
traits:
|
||||
- type: ingress
|
||||
properties:
|
||||
domain: testsvc.example.com
|
||||
http:
|
||||
"/": 8000
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
@@ -52,13 +46,5 @@ spec:
|
||||
kubectl -n {{ include "systemDefinitionNamespace" . }} wait --for=condition=available deployments helm-test-express-server --timeout 3m
|
||||
echo "deployment being available"
|
||||
|
||||
# wait for ingress being created
|
||||
while ! [ `kubectl -n {{ include "systemDefinitionNamespace" . }} get ing helm-test-express-server | grep -v NAME | wc -l` = 1 ]; do
|
||||
echo "waiting for ingress being created"
|
||||
sleep 1
|
||||
done
|
||||
|
||||
|
||||
|
||||
echo "Application and its components are created"
|
||||
restartPolicy: Never
|
||||
|
||||
@@ -5,8 +5,6 @@ kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Add annotations on your workload. if it generates pod, add same annotations for generated pods.
|
||||
labels:
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: annotations
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
|
||||
@@ -5,8 +5,6 @@ kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Add command on K8s pod for your workload which follows the pod spec in path 'spec.template'
|
||||
labels:
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: command
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
|
||||
@@ -5,8 +5,6 @@ kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Set the image of the container.
|
||||
labels:
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: container-image
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
|
||||
@@ -5,8 +5,6 @@ kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Automatically scale the component based on CPU usage.
|
||||
labels:
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: cpuscaler
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
|
||||
@@ -5,8 +5,6 @@ kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Add env on K8s pod for your workload which follows the pod spec in path 'spec.template'
|
||||
labels:
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: env
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
|
||||
@@ -5,8 +5,6 @@ kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Expose port to enable web traffic for your component.
|
||||
labels:
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: expose
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
|
||||
@@ -104,7 +104,7 @@ spec:
|
||||
message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host + ", IP: " + igs[0].ip
|
||||
}
|
||||
if igs[0].host == _|_ {
|
||||
message: "Host not specified, visit the cluster or load balancer in front of the cluster"
|
||||
message: "Host not specified, visit the cluster or load balancer in front of the cluster with IP: " + igs[0].ip
|
||||
}
|
||||
}
|
||||
if igs[0].ip == _|_ {
|
||||
|
||||
@@ -5,8 +5,6 @@ kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Add host aliases on K8s pod for your workload which follows the pod spec in path 'spec.template'.
|
||||
labels:
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: hostalias
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
|
||||
@@ -5,8 +5,6 @@ kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: add an init container and use shared volume with pod
|
||||
labels:
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: init-container
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
@@ -30,8 +28,9 @@ spec:
|
||||
}]
|
||||
}]
|
||||
initContainers: [{
|
||||
name: parameter.name
|
||||
image: parameter.image
|
||||
name: parameter.name
|
||||
image: parameter.image
|
||||
imagePullPolicy: parameter.imagePullPolicy
|
||||
if parameter.cmd != _|_ {
|
||||
command: parameter.cmd
|
||||
}
|
||||
@@ -61,6 +60,9 @@ spec:
|
||||
// +usage=Specify the image of init container
|
||||
image: string
|
||||
|
||||
// +usage=Specify image pull policy for your service
|
||||
imagePullPolicy: *"IfNotPresent" | "Always" | "Never"
|
||||
|
||||
// +usage=Specify the commands run in the init container
|
||||
cmd?: [...string]
|
||||
|
||||
|
||||
@@ -5,8 +5,6 @@ kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Add labels on your workload. if it generates pod, add same label for generated pods.
|
||||
labels:
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: labels
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
|
||||
@@ -5,8 +5,6 @@ kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Add lifecycle hooks for every container of K8s pod for your workload which follows the pod spec in path 'spec.template'.
|
||||
labels:
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: lifecycle
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
|
||||
@@ -5,8 +5,6 @@ kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Add resource requests and limits on K8s pod for your workload which follows the pod spec in path 'spec.template.'
|
||||
labels:
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: resource
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# Code generated by KubeVela templates. DO NOT EDIT. Please edit the original cue file.
|
||||
# Definition source cue file: vela-templates/definitions/internal/shared-resource.cue
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: PolicyDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Configure the resources to be sharable across applications.
|
||||
name: shared-resource
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
schematic:
|
||||
cue:
|
||||
template: |
|
||||
#SharedResourcePolicyRule: {
|
||||
// +usage=Specify how to select the targets of the rule
|
||||
selector: [...#ResourcePolicyRuleSelector]
|
||||
}
|
||||
#ResourcePolicyRuleSelector: {
|
||||
// +usage=Select resources by component names
|
||||
componentNames?: [...string]
|
||||
// +usage=Select resources by component types
|
||||
componentTypes?: [...string]
|
||||
// +usage=Select resources by oamTypes (COMPONENT or TRAIT)
|
||||
oamTypes?: [...string]
|
||||
// +usage=Select resources by trait types
|
||||
traitTypes?: [...string]
|
||||
// +usage=Select resources by resource types (like Deployment)
|
||||
resourceTypes?: [...string]
|
||||
// +usage=Select resources by their names
|
||||
resourceNames?: [...string]
|
||||
}
|
||||
parameter: {
|
||||
// +usage=Specify the list of rules to control shared-resource strategy at resource level.
|
||||
// The selected resource will be sharable across applications. (That means multiple applications
|
||||
// can all read it without conflict, but only the first one can write it)
|
||||
rules?: [...#SharedResourcePolicyRule]
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Inject a sidecar container to K8s pod for your workload which follows the pod spec in path 'spec.template'.
|
||||
labels:
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: sidecar
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
|
||||
@@ -13,7 +13,7 @@ spec:
|
||||
template: |
|
||||
parameter: {
|
||||
// +usage=Specify the names of the clusters to select.
|
||||
cluster?: [...string]
|
||||
clusters?: [...string]
|
||||
// +usage=Specify the label selector for clusters
|
||||
clusterLabelSelector?: [string]: string
|
||||
// +usage=Deprecated: Use clusterLabelSelector instead.
|
||||
|
||||
@@ -306,6 +306,9 @@ spec:
|
||||
if v.name == _|_ {
|
||||
name: "port-" + strconv.FormatInt(v.port, 10)
|
||||
}
|
||||
if v.nodePort != _|_ && parameter.exposeType == "NodePort" {
|
||||
nodePort: v.nodePort
|
||||
}
|
||||
},
|
||||
]
|
||||
outputs: {
|
||||
@@ -354,6 +357,8 @@ spec:
|
||||
protocol: *"TCP" | "UDP" | "SCTP"
|
||||
// +usage=Specify if the port should be exposed
|
||||
expose: *false | bool
|
||||
// +usage=exposed node port. Only Valid when exposeType is NodePort
|
||||
nodePort?: int
|
||||
}]
|
||||
|
||||
// +ignore
|
||||
|
||||
@@ -36,7 +36,7 @@ kind: ClusterRole
|
||||
metadata:
|
||||
name: {{ include "kubevela.fullname" . }}:manager
|
||||
rules:
|
||||
- apiGroups: ["core.oam.dev", "terraform.core.oam.dev", "prism.oam.dev"]
|
||||
- apiGroups: ["core.oam.dev", "terraform.core.oam.dev", "prism.oam.dev", "standard.oam.dev"]
|
||||
resources: ["*"]
|
||||
verbs: ["*"]
|
||||
- apiGroups: ["cluster.open-cluster-management.io"]
|
||||
|
||||
@@ -35,6 +35,7 @@ import (
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/config"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/utils/log"
|
||||
"github.com/oam-dev/kubevela/pkg/features"
|
||||
"github.com/oam-dev/kubevela/pkg/utils"
|
||||
"github.com/oam-dev/kubevela/version"
|
||||
)
|
||||
|
||||
@@ -50,6 +51,7 @@ func main() {
|
||||
flag.DurationVar(&s.serverConfig.LeaderConfig.Duration, "duration", time.Second*5, "the lease lock resource name")
|
||||
flag.DurationVar(&s.serverConfig.AddonCacheTime, "addon-cache-duration", time.Minute*10, "how long between two addon cache operation")
|
||||
flag.BoolVar(&s.serverConfig.DisableStatisticCronJob, "disable-statistic-cronJob", false, "close the system statistic info calculating cronJob")
|
||||
flag.StringVar(&s.serverConfig.PprofAddr, "pprof-addr", "", "The address for pprof to use while exporting profiling results. The default value is empty which means do not expose it. Set it to address like :6666 to expose it.")
|
||||
flag.Float64Var(&s.serverConfig.KubeQPS, "kube-api-qps", 100, "the qps for kube clients. Low qps may lead to low throughput. High qps may give stress to api-server.")
|
||||
flag.IntVar(&s.serverConfig.KubeBurst, "kube-api-burst", 300, "the burst for kube clients. Recommend setting it qps*3.")
|
||||
features.APIServerMutableFeatureGate.AddFlag(flag.CommandLine)
|
||||
@@ -90,6 +92,11 @@ func main() {
|
||||
errChan := make(chan error)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
if s.serverConfig.PprofAddr != "" {
|
||||
go utils.EnablePprof(s.serverConfig.PprofAddr, errChan)
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := s.run(ctx, errChan); err != nil {
|
||||
errChan <- fmt.Errorf("failed to run apiserver: %w", err)
|
||||
|
||||
@@ -19,10 +19,9 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
goflag "flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/pprof"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
@@ -52,6 +51,7 @@ import (
|
||||
"github.com/oam-dev/kubevela/pkg/oam"
|
||||
"github.com/oam-dev/kubevela/pkg/oam/discoverymapper"
|
||||
"github.com/oam-dev/kubevela/pkg/resourcekeeper"
|
||||
pkgutils "github.com/oam-dev/kubevela/pkg/utils"
|
||||
"github.com/oam-dev/kubevela/pkg/utils/common"
|
||||
"github.com/oam-dev/kubevela/pkg/utils/system"
|
||||
"github.com/oam-dev/kubevela/pkg/utils/util"
|
||||
@@ -139,6 +139,7 @@ func main() {
|
||||
flag.DurationVar(&clusterMetricsInterval, "cluster-metrics-interval", 15*time.Second, "The interval that ClusterMetricsMgr will collect metrics from clusters, default value is 15 seconds.")
|
||||
flag.BoolVar(&controllerArgs.EnableCompatibility, "enable-asi-compatibility", false, "enable compatibility for asi")
|
||||
flag.BoolVar(&controllerArgs.IgnoreAppWithoutControllerRequirement, "ignore-app-without-controller-version", false, "If true, application controller will not process the app without 'app.oam.dev/controller-version-require' annotation")
|
||||
flag.BoolVar(&controllerArgs.IgnoreDefinitionWithoutControllerRequirement, "ignore-definition-without-controller-version", false, "If true, trait/component/workflowstep definition controller will not process the definition without 'definition.oam.dev/controller-version-require' annotation")
|
||||
standardcontroller.AddOptimizeFlags()
|
||||
standardcontroller.AddAdmissionFlags()
|
||||
flag.IntVar(&resourcekeeper.MaxDispatchConcurrent, "max-dispatch-concurrent", 10, "Set the max dispatch concurrent number, default is 10")
|
||||
@@ -147,45 +148,17 @@ func main() {
|
||||
flag.IntVar(&wfTypes.MaxWorkflowStepErrorRetryTimes, "max-workflow-step-error-retry-times", 10, "Set the max workflow step error retry times, default is 10")
|
||||
utilfeature.DefaultMutableFeatureGate.AddFlag(flag.CommandLine)
|
||||
|
||||
flag.Parse()
|
||||
// setup logging
|
||||
klog.InitFlags(nil)
|
||||
flag.CommandLine.AddGoFlagSet(goflag.CommandLine)
|
||||
flag.Parse()
|
||||
if logDebug {
|
||||
_ = flag.Set("v", strconv.Itoa(int(commonconfig.LogDebug)))
|
||||
}
|
||||
|
||||
if pprofAddr != "" {
|
||||
// Start pprof server if enabled
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/debug/pprof/", pprof.Index)
|
||||
mux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
|
||||
mux.HandleFunc("/debug/pprof/profile", pprof.Profile)
|
||||
mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
|
||||
mux.HandleFunc("/debug/pprof/trace", pprof.Trace)
|
||||
pprofServer := http.Server{
|
||||
Addr: pprofAddr,
|
||||
Handler: mux,
|
||||
}
|
||||
klog.InfoS("Starting debug HTTP server", "addr", pprofServer.Addr)
|
||||
|
||||
go func() {
|
||||
go func() {
|
||||
ctx := context.Background()
|
||||
<-ctx.Done()
|
||||
|
||||
ctx, cancelFunc := context.WithTimeout(context.Background(), 60*time.Minute)
|
||||
defer cancelFunc()
|
||||
|
||||
if err := pprofServer.Shutdown(ctx); err != nil {
|
||||
klog.Error(err, "Failed to shutdown debug HTTP server")
|
||||
}
|
||||
}()
|
||||
|
||||
if err := pprofServer.ListenAndServe(); !errors.Is(http.ErrServerClosed, err) {
|
||||
klog.Error(err, "Failed to start debug HTTP server")
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
go pkgutils.EnablePprof(pprofAddr, nil)
|
||||
}
|
||||
|
||||
if logFilePath != "" {
|
||||
|
||||
@@ -76,17 +76,19 @@ func ApplyMockServerConfig() error {
|
||||
} else {
|
||||
cm.ResourceVersion = originCm.ResourceVersion
|
||||
if err = k8sClient.Update(ctx, &cm); err != nil {
|
||||
fmt.Println("print errr------")
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := k8sClient.Create(ctx, &v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "test-vela"}}); err != nil {
|
||||
return err
|
||||
if !apierrors.IsAlreadyExists(err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
otherRegistry.SetNamespace("test-vela")
|
||||
if err := k8sClient.Create(ctx, otherRegistry); err != nil {
|
||||
return err
|
||||
if !apierrors.IsAlreadyExists(err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ var (
|
||||
func main() {
|
||||
err := utils.ApplyMockServerConfig()
|
||||
if err != nil {
|
||||
log.Fatal("Apply mock server config to ConfigMap fail")
|
||||
log.Fatal(err)
|
||||
}
|
||||
http.HandleFunc("/", ossHandler)
|
||||
http.HandleFunc("/helm/", helmHandler)
|
||||
|
||||
@@ -294,7 +294,7 @@ var VelaQLPodListContext = func(context string, velaQL string) bool {
|
||||
gomega.Expect(v.Status.Phase).To(gomega.ContainSubstring("Running"))
|
||||
}
|
||||
if v.Status.NodeName != "" {
|
||||
gomega.Expect(v.Status.NodeName).To(gomega.ContainSubstring("kind-control-plane"))
|
||||
gomega.Expect(v.Status.NodeName).To(gomega.ContainSubstring("k3d-k3s-default-server-0"))
|
||||
}
|
||||
if v.Metadata.Namespace != "" {
|
||||
gomega.Expect(v.Metadata.Namespace).To(gomega.ContainSubstring("default"))
|
||||
|
||||
@@ -186,4 +186,14 @@ var (
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
ShowCapabilityReferenceMarkdown = func(context string, capabilityName string) bool {
|
||||
return ginkgo.Context(context, func() {
|
||||
ginkgo.It("should show capability reference in markdown", func() {
|
||||
cli := fmt.Sprintf("vela show %s --format=markdown", capabilityName)
|
||||
_, err := Exec(cli)
|
||||
gomega.Expect(err).Should(gomega.BeNil())
|
||||
})
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
Copyright 2021 The KubeVela 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 e2e
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/oam-dev/kubevela/e2e"
|
||||
|
||||
"github.com/onsi/ginkgo"
|
||||
"github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
var _ = ginkgo.BeforeSuite(func() {
|
||||
e2e.BeforeSuit()
|
||||
}, 30)
|
||||
|
||||
func TestApplication(t *testing.T) {
|
||||
gomega.RegisterFailHandler(ginkgo.Fail)
|
||||
ginkgo.RunSpecs(t, "Setup Suite")
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
Copyright 2021 The KubeVela 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 e2e
|
||||
|
||||
import (
|
||||
"github.com/onsi/ginkgo"
|
||||
)
|
||||
|
||||
var _ = ginkgo.Describe("Setup", func() {
|
||||
|
||||
})
|
||||
@@ -28,6 +28,7 @@ var _ = ginkgo.Describe("Trait", func() {
|
||||
|
||||
var _ = ginkgo.Describe("Test vela show", func() {
|
||||
e2e.ShowCapabilityReference("show ingress", "ingress")
|
||||
e2e.ShowCapabilityReferenceMarkdown("show ingress markdown", "ingress")
|
||||
|
||||
env := "namespace-xxxfwrr23erfm"
|
||||
e2e.EnvInitWithNamespaceOptionContext("env init", env, env)
|
||||
|
||||
@@ -37,6 +37,7 @@ var _ = Describe("Workload", func() {
|
||||
|
||||
var _ = Describe("Test vela show", func() {
|
||||
e2e.ShowCapabilityReference("show webservice", "webservice")
|
||||
e2e.ShowCapabilityReferenceMarkdown("show webservice markdown", "webservice")
|
||||
|
||||
env := "namespace-xxxfwrr23erfm"
|
||||
e2e.EnvInitWithNamespaceOptionContext("env init", env, env)
|
||||
|
||||
4
go.mod
4
go.mod
@@ -118,7 +118,7 @@ require (
|
||||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect
|
||||
github.com/openkruise/rollouts v0.1.1-0.20220622054609-149e5a48da5e
|
||||
github.com/xanzy/ssh-agent v0.3.0 // indirect
|
||||
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e // indirect
|
||||
golang.org/x/net v0.0.0-20220906165146-f3363e06e74c // indirect
|
||||
golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect
|
||||
google.golang.org/protobuf v1.28.0 // indirect
|
||||
sigs.k8s.io/gateway-api v0.4.3
|
||||
@@ -296,7 +296,7 @@ require (
|
||||
go.uber.org/multierr v1.6.0 // indirect
|
||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
|
||||
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f // indirect
|
||||
golang.org/x/sys v0.0.0-20220624220833-87e55d714810 // indirect
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
|
||||
8
go.sum
8
go.sum
@@ -2410,8 +2410,8 @@ golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220516155154-20f960328961/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e h1:TsQ7F31D3bUCLeqPT0u+yjp1guoArKaNKmCr22PYgTQ=
|
||||
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20220906165146-f3363e06e74c h1:yKufUcDwucU5urd+50/Opbt4AYpqthk7wHpHok8f1lo=
|
||||
golang.org/x/net v0.0.0-20220906165146-f3363e06e74c/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@@ -2608,8 +2608,8 @@ golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220624220833-87e55d714810 h1:rHZQSjJdAI4Xf5Qzeh2bBc5YJIkPFVM6oDtMFYmgws0=
|
||||
golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg=
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
. ./hack/e2e/end_e2e_core.sh
|
||||
|
||||
OAM_CONTAINER_ID=$(docker exec kind-control-plane crictl ps | grep oam-runtime | grep --regexp '^.............' -o)
|
||||
OAM_DOCKER_DIR=$(docker exec kind-control-plane crictl inspect --output go-template --template '{{range .info.runtimeSpec.mounts}}{{if (eq .destination "/workspace/data")}}{{.source}}{{end}}{{end}}' "${OAM_CONTAINER_ID}")
|
||||
OAM_CONTAINER_ID=$(docker exec k3d-k3s-default-server-0 crictl ps | grep oam-runtime | grep --regexp '^.............' -o)
|
||||
OAM_DOCKER_DIR=$(docker exec k3d-k3s-default-server-0 crictl inspect --output go-template --template '{{range .info.runtimeSpec.mounts}}{{if (eq .destination "/workspace/data")}}{{.source}}{{end}}{{end}}' "${OAM_CONTAINER_ID}")
|
||||
echo "${OAM_CONTAINER_ID}"
|
||||
echo "${OAM_DOCKER_DIR}"
|
||||
|
||||
docker exec kind-control-plane crictl exec "${OAM_CONTAINER_ID}" kill -2 1
|
||||
docker exec k3d-k3s-default-server-0 crictl exec "${OAM_CONTAINER_ID}" kill -2 1
|
||||
|
||||
file=$OAM_DOCKER_DIR/e2e-profile.out
|
||||
echo "$file"
|
||||
n=1
|
||||
while [ $n -le 60 ];do
|
||||
if_exist=$(docker exec kind-control-plane sh -c "test -f $file && echo 'ok'")
|
||||
if_exist=$(docker exec k3d-k3s-default-server-0 sh -c "test -f $file && echo 'ok'")
|
||||
echo "$if_exist"
|
||||
if [ -n "$if_exist" ];then
|
||||
docker exec kind-control-plane cat "$file" > /tmp/oam-e2e-profile.out
|
||||
docker exec k3d-k3s-default-server-0 cat "$file" > /tmp/oam-e2e-profile.out
|
||||
break
|
||||
fi
|
||||
echo file not generated yet
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
CONTAINER_ID=$(docker exec kind-control-plane crictl ps | grep 'kubevela\s' | grep --regexp '^.............' -o)
|
||||
DOCKER_DIR=$(docker exec kind-control-plane crictl inspect --output go-template --template '{{range .info.runtimeSpec.mounts}}{{if (eq .destination "/workspace/data")}}{{.source}}{{end}}{{end}}' "${CONTAINER_ID}")
|
||||
CONTAINER_ID=$(docker exec k3d-k3s-default-server-0 crictl ps | grep 'kubevela\s' | grep --regexp '^.............' -o)
|
||||
DOCKER_DIR=$(docker exec k3d-k3s-default-server-0 crictl inspect --output go-template --template '{{range .info.runtimeSpec.mounts}}{{if (eq .destination "/workspace/data")}}{{.source}}{{end}}{{end}}' "${CONTAINER_ID}")
|
||||
echo "${CONTAINER_ID}"
|
||||
echo "${DOCKER_DIR}"
|
||||
|
||||
docker exec kind-control-plane crictl exec "${CONTAINER_ID}" kill -2 1
|
||||
docker exec k3d-k3s-default-server-0 crictl exec "${CONTAINER_ID}" kill -2 1
|
||||
|
||||
file=$DOCKER_DIR/e2e-profile.out
|
||||
echo "$file"
|
||||
n=1
|
||||
while [ $n -le 60 ];do
|
||||
if_exist=$(docker exec kind-control-plane sh -c "test -f $file && echo 'ok'")
|
||||
if_exist=$(docker exec k3d-k3s-default-server-0 sh -c "test -f $file && echo 'ok'")
|
||||
echo "$if_exist"
|
||||
if [ -n "$if_exist" ];then
|
||||
docker exec kind-control-plane cat "$file" > /tmp/e2e-profile.out
|
||||
docker exec k3d-k3s-default-server-0 cat "$file" > /tmp/e2e-profile.out
|
||||
break
|
||||
fi
|
||||
echo file not generated yet
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
template: {
|
||||
patch: spec: template: spec: {
|
||||
tolerations: [{
|
||||
key: "node.kubernetes.io/network-unavailable"
|
||||
key: "node.kubernetes.io/network-unavailable"
|
||||
operator: "Exists"
|
||||
effect: "NoSchedule"
|
||||
effect: "NoSchedule"
|
||||
}]
|
||||
}
|
||||
parameter: {}
|
||||
|
||||
@@ -80,7 +80,7 @@ ifeq (, $(shell which readme-generator))
|
||||
@{ \
|
||||
set -e ;\
|
||||
echo 'installing readme-generator-for-helm' ;\
|
||||
npm install -g readme-generator-for-helm ;\
|
||||
npm install -g @bitnami/readme-generator-for-helm ;\
|
||||
}
|
||||
else
|
||||
@$(OK) readme-generator-for-helm is already installed
|
||||
|
||||
@@ -5,11 +5,18 @@ e2e-setup-core-pre-hook:
|
||||
.PHONY: e2e-setup-core-post-hook
|
||||
e2e-setup-core-post-hook:
|
||||
kubectl wait --for=condition=Available deployment/kubevela-vela-core -n vela-system --timeout=180s
|
||||
helm upgrade --install --namespace vela-system --wait oam-rollout --set image.repository=vela-runtime-rollout-test --set image.tag=$(GIT_COMMIT) ./runtime/rollout/charts
|
||||
helm install kruise https://github.com/openkruise/charts/releases/download/kruise-1.1.0/kruise-1.1.0.tgz --set featureGates="PreDownloadImageForInPlaceUpdate=true" --set daemon.socketLocation=/run/k3s/containerd/
|
||||
go run ./e2e/addon/mock &
|
||||
sleep 15
|
||||
bin/vela addon enable ./e2e/addon/mock/testdata/fluxcd
|
||||
bin/vela addon enable ./e2e/addon/mock/testdata/rollout
|
||||
bin/vela addon enable ./e2e/addon/mock/testdata/terraform
|
||||
bin/vela addon enable ./e2e/addon/mock/testdata/terraform-alibaba ALICLOUD_ACCESS_KEY=xxx ALICLOUD_SECRET_KEY=yyy ALICLOUD_REGION=cn-beijing
|
||||
|
||||
timeout 600s bash -c -- 'while true; do kubectl get ns flux-system; if [ $$? -eq 0 ] ; then break; else sleep 5; fi;done'
|
||||
kubectl wait --for=condition=Ready pod -l app.kubernetes.io/name=vela-core,app.kubernetes.io/instance=kubevela -n vela-system --timeout=600s
|
||||
kubectl wait --for=condition=Ready pod -l app=source-controller -n flux-system --timeout=600s
|
||||
kubectl wait --for=condition=Ready pod -l app=helm-controller -n flux-system --timeout=600s
|
||||
|
||||
.PHONY: e2e-setup-core-wo-auth
|
||||
e2e-setup-core-wo-auth:
|
||||
@@ -27,28 +34,26 @@ e2e-setup-core-auth: e2e-setup-core-pre-hook e2e-setup-core-w-auth e2e-setup-cor
|
||||
|
||||
.PHONY: setup-runtime-e2e-cluster
|
||||
setup-runtime-e2e-cluster:
|
||||
helm upgrade --install --create-namespace --namespace vela-system --kubeconfig=$(RUNTIME_CLUSTER_CONFIG) --set image.pullPolicy=IfNotPresent --set image.repository=vela-runtime-rollout-test --set image.tag=$(GIT_COMMIT) --wait vela-rollout ./runtime/rollout/charts
|
||||
helm upgrade --install \
|
||||
--namespace vela-system \
|
||||
--wait oam-rollout \
|
||||
--set image.repository=vela-runtime-rollout-test \
|
||||
--set image.tag=$(GIT_COMMIT) \
|
||||
./runtime/rollout/charts
|
||||
|
||||
.PHONY: e2e-setup
|
||||
e2e-setup:
|
||||
helm install kruise https://github.com/openkruise/charts/releases/download/kruise-1.1.0/kruise-1.1.0.tgz --set featureGates="PreDownloadImageForInPlaceUpdate=true"
|
||||
sh ./hack/e2e/modify_charts.sh
|
||||
helm upgrade --install --create-namespace --namespace vela-system --set image.pullPolicy=IfNotPresent --set image.repository=vela-core-test --set applicationRevisionLimit=5 --set dependCheckWait=10s --set image.tag=$(GIT_COMMIT) --wait kubevela ./charts/vela-core
|
||||
helm upgrade --install --namespace vela-system --wait oam-rollout --set image.repository=vela-runtime-rollout-test --set image.tag=$(GIT_COMMIT) ./runtime/rollout/charts
|
||||
k3d cluster get $(RUNTIME_CLUSTER_NAME) && \
|
||||
helm upgrade --install \
|
||||
--create-namespace \
|
||||
--namespace vela-system \
|
||||
--kubeconfig=$(RUNTIME_CLUSTER_CONFIG) \
|
||||
--set image.pullPolicy=IfNotPresent \
|
||||
--set image.repository=vela-runtime-rollout-test \
|
||||
--set image.tag=$(GIT_COMMIT) \
|
||||
--wait vela-rollout \
|
||||
./runtime/rollout/charts || \
|
||||
echo "no worker cluster" \
|
||||
|
||||
go run ./e2e/addon/mock &
|
||||
sleep 15
|
||||
bin/vela addon enable ./e2e/addon/mock/testdata/fluxcd
|
||||
bin/vela addon enable ./e2e/addon/mock/testdata/terraform
|
||||
bin/vela addon enable ./e2e/addon/mock/testdata/terraform-alibaba ALICLOUD_ACCESS_KEY=xxx ALICLOUD_SECRET_KEY=yyy ALICLOUD_REGION=cn-beijing
|
||||
bin/vela addon enable ./e2e/addon/mock/testdata/rollout
|
||||
ginkgo version
|
||||
ginkgo -v -r e2e/setup
|
||||
|
||||
timeout 600s bash -c -- 'while true; do kubectl get ns flux-system; if [ $$? -eq 0 ] ; then break; else sleep 5; fi;done'
|
||||
kubectl wait --for=condition=Ready pod -l app.kubernetes.io/name=vela-core,app.kubernetes.io/instance=kubevela -n vela-system --timeout=600s
|
||||
kubectl wait --for=condition=Ready pod -l app=source-controller -n flux-system --timeout=600s
|
||||
kubectl wait --for=condition=Ready pod -l app=helm-controller -n flux-system --timeout=600s
|
||||
|
||||
.PHONY: e2e-api-test
|
||||
e2e-api-test:
|
||||
|
||||
@@ -994,12 +994,8 @@ func (h *Installer) getAddonMeta() (map[string]SourceMeta, error) {
|
||||
|
||||
// installDependency checks if addon's dependency and install it
|
||||
func (h *Installer) installDependency(addon *InstallPackage) error {
|
||||
var app v1beta1.Application
|
||||
for _, dep := range addon.Dependencies {
|
||||
err := h.cli.Get(h.ctx, client.ObjectKey{
|
||||
Namespace: types.DefaultKubeVelaNS,
|
||||
Name: addonutil.Addon2AppName(dep.Name),
|
||||
}, &app)
|
||||
_, err := FetchAddonRelatedApp(h.ctx, h.cli, dep.Name)
|
||||
if err == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -418,9 +418,12 @@ var _ = Describe("test override defs of addon", func() {
|
||||
u := unstructured.Unstructured{Object: compUnstructured}
|
||||
u.SetAPIVersion(v1beta1.SchemeGroupVersion.String())
|
||||
u.SetKind(v1beta1.ComponentDefinitionKind)
|
||||
u.SetLabels(map[string]string{"testUpdateLabel": "test"})
|
||||
c, err := checkConflictDefs(ctx, k8sClient, []*unstructured.Unstructured{&u}, app.GetName())
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(len(c)).Should(BeEquivalentTo(1))
|
||||
// guarantee checkConflictDefs won't change source definition
|
||||
Expect(u.GetLabels()["testUpdateLabel"]).Should(BeEquivalentTo("test"))
|
||||
|
||||
u.SetName("rollout")
|
||||
c, err = checkConflictDefs(ctx, k8sClient, []*unstructured.Unstructured{&u}, app.GetName())
|
||||
|
||||
@@ -86,7 +86,6 @@ var _ = Describe("test FindWholeAddonPackagesFromRegistry", func() {
|
||||
Expect(res).To(HaveLen(1))
|
||||
Expect(res[0].Name).To(Equal("velaux"))
|
||||
Expect(res[0].InstallPackage).ToNot(BeNil())
|
||||
Expect(res[0].APISchema).ToNot(BeNil())
|
||||
})
|
||||
It("should return one valid result, matching one registry", func() {
|
||||
res, err := FindWholeAddonPackagesFromRegistry(context.Background(), k8sClient, []string{"velaux"}, []string{"KubeVela"})
|
||||
@@ -94,7 +93,6 @@ var _ = Describe("test FindWholeAddonPackagesFromRegistry", func() {
|
||||
Expect(res).To(HaveLen(1))
|
||||
Expect(res[0].Name).To(Equal("velaux"))
|
||||
Expect(res[0].InstallPackage).ToNot(BeNil())
|
||||
Expect(res[0].APISchema).ToNot(BeNil())
|
||||
})
|
||||
})
|
||||
|
||||
@@ -113,10 +111,8 @@ var _ = Describe("test FindWholeAddonPackagesFromRegistry", func() {
|
||||
Expect(res).To(HaveLen(2))
|
||||
Expect(res[0].Name).To(Equal("velaux"))
|
||||
Expect(res[0].InstallPackage).ToNot(BeNil())
|
||||
Expect(res[0].APISchema).ToNot(BeNil())
|
||||
Expect(res[1].Name).To(Equal("traefik"))
|
||||
Expect(res[1].InstallPackage).ToNot(BeNil())
|
||||
Expect(res[1].APISchema).ToNot(BeNil())
|
||||
})
|
||||
})
|
||||
|
||||
@@ -127,7 +123,6 @@ var _ = Describe("test FindWholeAddonPackagesFromRegistry", func() {
|
||||
Expect(res).To(HaveLen(1))
|
||||
Expect(res[0].Name).To(Equal("velaux"))
|
||||
Expect(res[0].InstallPackage).ToNot(BeNil())
|
||||
Expect(res[0].APISchema).ToNot(BeNil())
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -48,6 +48,7 @@ const (
|
||||
addonAllClusterPolicy = "deploy-addon-to-all-clusters"
|
||||
renderOutputCuePath = "output"
|
||||
renderAuxiliaryOutputsPath = "outputs"
|
||||
defaultCuePackageHeader = "main"
|
||||
)
|
||||
|
||||
type addonCueTemplateRender struct {
|
||||
@@ -334,6 +335,13 @@ func renderResources(addon *InstallPackage, args map[string]interface{}) ([]comm
|
||||
}
|
||||
|
||||
for _, tmpl := range addon.CUETemplates {
|
||||
isMainCueTemplate, err := checkCueFileHasPackageHeader(tmpl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if isMainCueTemplate {
|
||||
continue
|
||||
}
|
||||
comp, err := renderCompAccordingCUETemplate(tmpl, addon, args)
|
||||
if err != nil && strings.Contains(err.Error(), "var(path=output) not exist") {
|
||||
continue
|
||||
@@ -367,3 +375,14 @@ func isDeployToRuntime(addon *InstallPackage) bool {
|
||||
}
|
||||
return addon.DeployTo.RuntimeCluster || addon.DeployTo.LegacyRuntimeCluster
|
||||
}
|
||||
|
||||
func checkCueFileHasPackageHeader(cueTemplate ElementFile) (bool, error) {
|
||||
cueFile, err := parser.ParseFile(cueTemplate.Name, cueTemplate.Data, parser.ParseComments)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if cueFile.PackageName() == defaultCuePackageHeader {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
@@ -451,3 +451,99 @@ func TestRenderCueResourceError(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, len(comp), 2)
|
||||
}
|
||||
|
||||
func TestCheckCueFileHasPackageHeader(t *testing.T) {
|
||||
testCueTemplateWithPkg := `
|
||||
package main
|
||||
|
||||
kustomizeController: {
|
||||
// About this name, refer to #429 for details.
|
||||
name: "fluxcd-kustomize-controller"
|
||||
type: "webservice"
|
||||
dependsOn: ["fluxcd-ns"]
|
||||
properties: {
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
image: _base + "fluxcd/kustomize-controller:v0.26.0"
|
||||
env: [
|
||||
{
|
||||
name: "RUNTIME_NAMESPACE"
|
||||
value: _targetNamespace
|
||||
},
|
||||
]
|
||||
livenessProbe: {
|
||||
httpGet: {
|
||||
path: "/healthz"
|
||||
port: 9440
|
||||
}
|
||||
timeoutSeconds: 5
|
||||
}
|
||||
readinessProbe: {
|
||||
httpGet: {
|
||||
path: "/readyz"
|
||||
port: 9440
|
||||
}
|
||||
timeoutSeconds: 5
|
||||
}
|
||||
volumeMounts: {
|
||||
emptyDir: [
|
||||
{
|
||||
name: "temp"
|
||||
mountPath: "/tmp"
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
traits: [
|
||||
{
|
||||
type: "service-account"
|
||||
properties: {
|
||||
name: "sa-kustomize-controller"
|
||||
create: true
|
||||
privileges: _rules
|
||||
}
|
||||
},
|
||||
{
|
||||
type: "labels"
|
||||
properties: {
|
||||
"control-plane": "controller"
|
||||
// This label is kept to avoid breaking existing
|
||||
// KubeVela e2e tests (makefile e2e-setup).
|
||||
"app": "kustomize-controller"
|
||||
}
|
||||
},
|
||||
{
|
||||
type: "command"
|
||||
properties: {
|
||||
args: controllerArgs
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
`
|
||||
|
||||
testCueTemplateWithoutPkg := `
|
||||
output: {
|
||||
type: "helm"
|
||||
name: "nginx-ingress"
|
||||
properties: {
|
||||
repoType: "helm"
|
||||
url: "https://kubernetes.github.io/ingress-nginx"
|
||||
chart: "ingress-nginx"
|
||||
version: "4.2.0"
|
||||
values: {
|
||||
controller: service: type: parameter["serviceType"]
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
cueTemplate := ElementFile{Name: "test-file.cue", Data: testCueTemplateWithPkg}
|
||||
ok, err := checkCueFileHasPackageHeader(cueTemplate)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, true, ok)
|
||||
|
||||
cueTemplate = ElementFile{Name: "test-file-without-pkg.cue", Data: testCueTemplateWithoutPkg}
|
||||
ok, err = checkCueFileHasPackageHeader(cueTemplate)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, false, ok)
|
||||
}
|
||||
|
||||
@@ -448,20 +448,21 @@ func isErrorCueRenderPathNotFound(err error, path string) bool {
|
||||
func checkConflictDefs(ctx context.Context, k8sClient client.Client, defs []*unstructured.Unstructured, appName string) (map[string]string, error) {
|
||||
res := map[string]string{}
|
||||
for _, def := range defs {
|
||||
err := k8sClient.Get(ctx, client.ObjectKeyFromObject(def), def)
|
||||
checkDef := def.DeepCopy()
|
||||
err := k8sClient.Get(ctx, client.ObjectKeyFromObject(checkDef), checkDef)
|
||||
if err == nil {
|
||||
owner := metav1.GetControllerOf(def)
|
||||
owner := metav1.GetControllerOf(checkDef)
|
||||
if owner == nil || owner.Kind != v1beta1.ApplicationKind {
|
||||
res[def.GetName()] = fmt.Sprintf("definition: %s already exist and not belong to any addon \n", def.GetName())
|
||||
res[checkDef.GetName()] = fmt.Sprintf("definition: %s already exist and not belong to any addon \n", checkDef.GetName())
|
||||
continue
|
||||
}
|
||||
if owner.Name != appName {
|
||||
// if addon not belong to an addon or addon name is another one, we should put them in result
|
||||
res[def.GetName()] = fmt.Sprintf("definition: %s in this addon already exist in %s \n", def.GetName(), addon.AppName2Addon(appName))
|
||||
res[checkDef.GetName()] = fmt.Sprintf("definition: %s in this addon already exist in %s \n", checkDef.GetName(), addon.AppName2Addon(appName))
|
||||
}
|
||||
}
|
||||
if err != nil && !errors2.IsNotFound(err) {
|
||||
return nil, errors.Wrapf(err, "check definition %s", def.GetName())
|
||||
return nil, errors.Wrapf(err, "check definition %s", checkDef.GetName())
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
@@ -482,10 +483,16 @@ func produceDefConflictError(conflictDefs map[string]string) error {
|
||||
// checkBondComponentExistt will check the ready-to-apply object(def or auxiliary outputs) whether bind to a component
|
||||
// if the target component not exist, return false.
|
||||
func checkBondComponentExist(u unstructured.Unstructured, app v1beta1.Application) bool {
|
||||
comp, existKey := u.GetAnnotations()[oam.AnnotationIgnoreWithoutCompKey]
|
||||
var comp string
|
||||
var existKey bool
|
||||
comp, existKey = u.GetAnnotations()[oam.AnnotationAddonDefinitionBondCompKey]
|
||||
if !existKey {
|
||||
// if an object(def or auxiliary outputs ) binding no components return true
|
||||
return true
|
||||
// this is compatibility logic for deprecated annotation
|
||||
comp, existKey = u.GetAnnotations()[oam.AnnotationIgnoreWithoutCompKey]
|
||||
if !existKey {
|
||||
// if an object(def or auxiliary outputs ) binding no components return true
|
||||
return true
|
||||
}
|
||||
}
|
||||
for _, component := range app.Spec.Components {
|
||||
if component.Name == comp {
|
||||
|
||||
@@ -290,10 +290,13 @@ func TestMakeChart(t *testing.T) {
|
||||
|
||||
func TestCheckObjectBindingComponent(t *testing.T) {
|
||||
existingBindingDef := unstructured.Unstructured{}
|
||||
existingBindingDef.SetAnnotations(map[string]string{oam.AnnotationIgnoreWithoutCompKey: "kustomize"})
|
||||
existingBindingDef.SetAnnotations(map[string]string{oam.AnnotationAddonDefinitionBondCompKey: "kustomize"})
|
||||
|
||||
emptyAnnoDef := unstructured.Unstructured{}
|
||||
emptyAnnoDef.SetAnnotations(map[string]string{"test": "onlyForTest"})
|
||||
|
||||
legacyAnnoDef := unstructured.Unstructured{}
|
||||
legacyAnnoDef.SetAnnotations(map[string]string{oam.AnnotationIgnoreWithoutCompKey: "kustomize"})
|
||||
testCases := map[string]struct {
|
||||
object unstructured.Unstructured
|
||||
app v1beta1.Application
|
||||
@@ -311,6 +314,14 @@ func TestCheckObjectBindingComponent(t *testing.T) {
|
||||
"EmptyApp": {object: existingBindingDef,
|
||||
app: v1beta1.Application{Spec: v1beta1.ApplicationSpec{Components: []common.ApplicationComponent{}}},
|
||||
res: false},
|
||||
"LegacyApp": {object: legacyAnnoDef,
|
||||
app: v1beta1.Application{Spec: v1beta1.ApplicationSpec{Components: []common.ApplicationComponent{{Name: "kustomize"}}}},
|
||||
res: true,
|
||||
},
|
||||
"LegacyAppWithoutComp": {object: legacyAnnoDef,
|
||||
app: v1beta1.Application{Spec: v1beta1.ApplicationSpec{Components: []common.ApplicationComponent{{}}}},
|
||||
res: false,
|
||||
},
|
||||
}
|
||||
for _, s := range testCases {
|
||||
result := checkBondComponentExist(s.object, s.app)
|
||||
|
||||
@@ -46,6 +46,9 @@ type Config struct {
|
||||
|
||||
// KubeQPS the QPS of kube client
|
||||
KubeQPS float64
|
||||
|
||||
// PprofAddr the address for pprof to use while exporting profiling results.
|
||||
PprofAddr string
|
||||
}
|
||||
|
||||
type leaderConfig struct {
|
||||
|
||||
@@ -32,6 +32,7 @@ const (
|
||||
// SystemInfo systemInfo model
|
||||
type SystemInfo struct {
|
||||
BaseModel
|
||||
SignedKey string `json:"signedKey"`
|
||||
InstallID string `json:"installID"`
|
||||
EnableCollection bool `json:"enableCollection"`
|
||||
StatisticInfo StatisticInfo `json:"statisticInfo,omitempty"`
|
||||
|
||||
@@ -150,7 +150,7 @@ func (w *WorkflowRecord) Index() map[string]string {
|
||||
index["namespace"] = w.Namespace
|
||||
}
|
||||
if w.WorkflowName != "" {
|
||||
index["workflowPrimaryKey"] = w.WorkflowName
|
||||
index["workflowName"] = w.WorkflowName
|
||||
}
|
||||
if w.AppPrimaryKey != "" {
|
||||
index["appPrimaryKey"] = w.AppPrimaryKey
|
||||
|
||||
@@ -1550,6 +1550,13 @@ func (c *applicationServiceImpl) DryRunAppOrRevision(ctx context.Context, appMod
|
||||
}
|
||||
case "REVISION":
|
||||
app, _, err = c.getAppModelFromRevision(ctx, appModel.Name, dryRunReq.Version)
|
||||
originalApp := &v1beta1.Application{}
|
||||
if err := c.KubeClient.Get(ctx, types.NamespacedName{
|
||||
Name: app.Name,
|
||||
Namespace: app.Namespace,
|
||||
}, originalApp); err == nil {
|
||||
app.ResourceVersion = originalApp.ResourceVersion
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -58,7 +58,8 @@ const (
|
||||
GrantTypeRefresh = "refresh"
|
||||
)
|
||||
|
||||
var signedKey = ""
|
||||
// signedKey is the signed key of JWT
|
||||
var signedKey string
|
||||
|
||||
// AuthenticationService is the service of authentication
|
||||
type AuthenticationService interface {
|
||||
|
||||
@@ -72,7 +72,7 @@ func (u *configServiceImpl) ListConfigTypes(ctx context.Context, query string) (
|
||||
defs := &v1beta1.ComponentDefinitionList{}
|
||||
if err := u.KubeClient.List(ctx, defs, client.InNamespace(types.DefaultKubeVelaNS),
|
||||
client.MatchingLabels{
|
||||
configCatalog: types.VelaCoreConfig,
|
||||
definition.ConfigCatalog: types.VelaCoreConfig,
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -85,13 +85,13 @@ func (u *configServiceImpl) ListConfigTypes(ctx context.Context, query string) (
|
||||
if err := u.KubeClient.List(ctx, defsLegacy, client.InNamespace(types.DefaultKubeVelaNS),
|
||||
client.MatchingLabels{
|
||||
// leave here as the legacy format to test the compatibility
|
||||
definition.UserPrefix + configCatalog: types.VelaCoreConfig,
|
||||
definition.UserPrefix + definition.ConfigCatalog: types.VelaCoreConfig,
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// filter repeated config,due to new labels that exist at the same time
|
||||
for _, legacy := range defsLegacy.Items {
|
||||
if legacy.Labels[configCatalog] == types.VelaCoreConfig {
|
||||
if legacy.Labels[definition.ConfigCatalog] == types.VelaCoreConfig {
|
||||
continue
|
||||
}
|
||||
items = append(items, legacy)
|
||||
|
||||
@@ -57,8 +57,8 @@ func TestListConfigTypes(t *testing.T) {
|
||||
Name: "def1",
|
||||
Namespace: types.DefaultKubeVelaNS,
|
||||
Labels: map[string]string{
|
||||
configCatalog: types.VelaCoreConfig,
|
||||
definitionType: types.TerraformProvider,
|
||||
definition.ConfigCatalog: types.VelaCoreConfig,
|
||||
definition.DefinitionType: types.TerraformProvider,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -71,10 +71,10 @@ func TestListConfigTypes(t *testing.T) {
|
||||
Name: "def2",
|
||||
Namespace: types.DefaultKubeVelaNS,
|
||||
Annotations: map[string]string{
|
||||
definitionAlias: "Def2",
|
||||
definition.DefinitionAlias: "Def2",
|
||||
},
|
||||
Labels: map[string]string{
|
||||
configCatalog: types.VelaCoreConfig,
|
||||
definition.ConfigCatalog: types.VelaCoreConfig,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -153,10 +153,10 @@ func TestGetConfigType(t *testing.T) {
|
||||
Name: "def2",
|
||||
Namespace: types.DefaultKubeVelaNS,
|
||||
Annotations: map[string]string{
|
||||
definitionAlias: "Def2",
|
||||
definition.DefinitionAlias: "Def2",
|
||||
},
|
||||
Labels: map[string]string{
|
||||
definition.UserPrefix + configCatalog: types.VelaCoreConfig,
|
||||
definition.UserPrefix + definition.ConfigCatalog: types.VelaCoreConfig,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -63,6 +63,7 @@ func (u systemInfoServiceImpl) Get(ctx context.Context) (*model.SystemInfo, erro
|
||||
}
|
||||
return info, nil
|
||||
}
|
||||
info.SignedKey = rand.String(32)
|
||||
installID := rand.String(16)
|
||||
info.InstallID = installID
|
||||
info.EnableCollection = true
|
||||
@@ -161,7 +162,7 @@ func (u systemInfoServiceImpl) Init(ctx context.Context) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
signedKey = info.InstallID
|
||||
signedKey = info.SignedKey
|
||||
_, err = initDexConfig(ctx, u.KubeClient, "http://velaux.com")
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -18,22 +18,16 @@ package service
|
||||
|
||||
import "github.com/oam-dev/kubevela/pkg/definition"
|
||||
|
||||
const (
|
||||
definitionAlias = "alias.config.oam.dev"
|
||||
definitionType = "type.config.oam.dev"
|
||||
configCatalog = "catalog.config.oam.dev"
|
||||
)
|
||||
|
||||
// DefinitionAlias will get definitionAlias value from tags
|
||||
func DefinitionAlias(tags map[string]string) string {
|
||||
if tags == nil {
|
||||
return ""
|
||||
}
|
||||
val := tags[definitionAlias]
|
||||
val := tags[definition.DefinitionAlias]
|
||||
if val != "" {
|
||||
return val
|
||||
}
|
||||
return tags[definition.UserPrefix+definitionAlias]
|
||||
return tags[definition.UserPrefix+definition.DefinitionAlias]
|
||||
}
|
||||
|
||||
// DefinitionType will get definitionType value from tags
|
||||
@@ -41,11 +35,11 @@ func DefinitionType(tags map[string]string) string {
|
||||
if tags == nil {
|
||||
return ""
|
||||
}
|
||||
val := tags[definitionType]
|
||||
val := tags[definition.DefinitionType]
|
||||
if val != "" {
|
||||
return val
|
||||
}
|
||||
return tags[definition.UserPrefix+definitionType]
|
||||
return tags[definition.UserPrefix+definition.DefinitionType]
|
||||
}
|
||||
|
||||
// ConfigCatalog will get configCatalog value from tags
|
||||
@@ -53,9 +47,9 @@ func ConfigCatalog(tags map[string]string) string {
|
||||
if tags == nil {
|
||||
return ""
|
||||
}
|
||||
val := tags[configCatalog]
|
||||
val := tags[definition.ConfigCatalog]
|
||||
if val != "" {
|
||||
return val
|
||||
}
|
||||
return tags[definition.UserPrefix+configCatalog]
|
||||
return tags[definition.UserPrefix+definition.ConfigCatalog]
|
||||
}
|
||||
|
||||
@@ -19,20 +19,22 @@ package service
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/oam-dev/kubevela/pkg/definition"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCompatiblleTag(t *testing.T) {
|
||||
func TestCompatibleTag(t *testing.T) {
|
||||
tg := map[string]string{
|
||||
"alias.config.oam.dev": "abc",
|
||||
"type.config.oam.dev": "image-registry",
|
||||
"catalog.config.oam.dev": "cata",
|
||||
definition.DefinitionAlias: "abc",
|
||||
definition.DefinitionType: "image-registry",
|
||||
definition.ConfigCatalog: "cata",
|
||||
}
|
||||
|
||||
tgOld := map[string]string{
|
||||
"custom.definition.oam.dev/alias.config.oam.dev": "abc-2",
|
||||
"custom.definition.oam.dev/type.config.oam.dev": "image-registry-2",
|
||||
"custom.definition.oam.dev/catalog.config.oam.dev": "cata-2",
|
||||
definition.UserPrefix + definition.DefinitionAlias: "abc-2",
|
||||
definition.UserPrefix + definition.DefinitionType: "image-registry-2",
|
||||
definition.UserPrefix + definition.ConfigCatalog: "cata-2",
|
||||
}
|
||||
|
||||
assert.Equal(t, DefinitionAlias(nil), "")
|
||||
|
||||
@@ -121,23 +121,22 @@ func (w *workflowServiceImpl) DeleteWorkflowByApp(ctx context.Context, app *mode
|
||||
}
|
||||
for i := range workflows {
|
||||
workflow := workflows[i].(*model.Workflow)
|
||||
var record = model.WorkflowRecord{
|
||||
AppPrimaryKey: workflow.AppPrimaryKey,
|
||||
WorkflowName: workflow.Name,
|
||||
}
|
||||
records, err := w.Store.List(ctx, &record, &datastore.ListOptions{})
|
||||
if err != nil {
|
||||
log.Logger.Errorf("list workflow %s record failure %s", workflow.PrimaryKey(), err.Error())
|
||||
}
|
||||
for _, record := range records {
|
||||
if err := w.Store.Delete(ctx, record); err != nil {
|
||||
log.Logger.Errorf("delete workflow record %s failure %s", record.PrimaryKey(), err.Error())
|
||||
}
|
||||
}
|
||||
if err := w.Store.Delete(ctx, workflow); err != nil {
|
||||
log.Logger.Errorf("delete workflow %s failure %s", workflow.PrimaryKey(), err.Error())
|
||||
}
|
||||
}
|
||||
var record = model.WorkflowRecord{
|
||||
AppPrimaryKey: workflow.AppPrimaryKey,
|
||||
}
|
||||
records, err := w.Store.List(ctx, &record, &datastore.ListOptions{})
|
||||
if err != nil {
|
||||
log.Logger.Errorf("list workflow %s record failure %s", workflow.PrimaryKey(), err.Error())
|
||||
}
|
||||
for _, record := range records {
|
||||
if err := w.Store.Delete(ctx, record); err != nil {
|
||||
log.Logger.Errorf("delete workflow record %s failure %s", record.PrimaryKey(), err.Error())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -368,6 +367,10 @@ func (w *workflowServiceImpl) SyncWorkflowRecord(ctx context.Context) error {
|
||||
continue
|
||||
}
|
||||
|
||||
if app.Status.Workflow == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// there is a ":" in the default app revision
|
||||
recordName := strings.Replace(app.Status.Workflow.AppRevision, ":", "-", 1)
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ import (
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/domain/model"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore/mongodb"
|
||||
apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1"
|
||||
"github.com/oam-dev/kubevela/pkg/oam"
|
||||
"github.com/oam-dev/kubevela/pkg/utils/apply"
|
||||
@@ -563,6 +564,55 @@ var _ = Describe("Test workflow service functions", func() {
|
||||
Expect(record.Finished).Should(Equal("true"))
|
||||
Expect(record.Steps[1].Phase).Should(Equal(common.WorkflowStepPhaseStopped))
|
||||
})
|
||||
|
||||
It("Test deleting workflow", func() {
|
||||
By("Test deleting the workflow from the mongo")
|
||||
mongodbDriver, err := mongodb.New(context.TODO(), datastore.Config{
|
||||
URL: "mongodb://localhost:27017",
|
||||
Database: "kubevela",
|
||||
})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(mongodbDriver).ToNot(BeNil())
|
||||
|
||||
Expect(mongodbDriver.BatchAdd(context.Background(), []datastore.Entity{
|
||||
&model.Workflow{
|
||||
Name: "workflow-default",
|
||||
AppPrimaryKey: "war-app",
|
||||
},
|
||||
&model.WorkflowRecord{
|
||||
Name: "workflow-default-20220809081934217",
|
||||
WorkflowName: "workflow-default",
|
||||
AppPrimaryKey: "war-app",
|
||||
RevisionPrimaryKey: "20220809081934216",
|
||||
},
|
||||
&model.WorkflowRecord{
|
||||
WorkflowName: "workflow-default",
|
||||
AppPrimaryKey: "war-app",
|
||||
Name: "workflow-default-20220809082525833",
|
||||
RevisionPrimaryKey: "20220809082525832",
|
||||
},
|
||||
})).ToNot(HaveOccurred())
|
||||
|
||||
var record = model.WorkflowRecord{
|
||||
AppPrimaryKey: "war-app",
|
||||
WorkflowName: "workflow-default",
|
||||
}
|
||||
records, err := mongodbDriver.List(context.TODO(), &record, &datastore.ListOptions{})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(len(records)).Should(Equal(2))
|
||||
|
||||
srv := workflowServiceImpl{
|
||||
Store: mongodbDriver,
|
||||
}
|
||||
Expect(srv.DeleteWorkflowByApp(context.TODO(), &model.Application{Name: "war-app"})).ToNot(HaveOccurred())
|
||||
wc, err := mongodbDriver.Count(context.TODO(), &model.Workflow{AppPrimaryKey: "war-app"}, nil)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(int(wc)).Should(Equal(0))
|
||||
|
||||
list, err := mongodbDriver.List(context.TODO(), &model.WorkflowRecord{AppPrimaryKey: "war-app"}, nil)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(len(list)).Should(Equal(0))
|
||||
})
|
||||
})
|
||||
|
||||
var yamlStr = `apiVersion: core.oam.dev/v1beta1
|
||||
|
||||
@@ -54,9 +54,11 @@ func StoreProject(ctx context.Context, name string, ds datastore.DataStore, proj
|
||||
|
||||
// StoreAppMeta will sync application metadata from CR to datastore
|
||||
func StoreAppMeta(ctx context.Context, app *model.DataStoreApp, ds datastore.DataStore) error {
|
||||
err := ds.Get(ctx, &model.Application{Name: app.AppMeta.Name})
|
||||
oldApp := &model.Application{Name: app.AppMeta.Name}
|
||||
err := ds.Get(ctx, oldApp)
|
||||
if err == nil {
|
||||
// it means the record already exists
|
||||
app.AppMeta.CreateTime = oldApp.CreateTime
|
||||
return ds.Put(ctx, app.AppMeta)
|
||||
}
|
||||
if !errors.Is(err, datastore.ErrRecordNotExist) {
|
||||
@@ -75,6 +77,7 @@ func StoreEnv(ctx context.Context, app *model.DataStoreApp, ds datastore.DataSto
|
||||
if utils.EqualSlice(curEnv.Targets, app.Env.Targets) {
|
||||
return nil
|
||||
}
|
||||
app.Env.CreateTime = curEnv.CreateTime
|
||||
return ds.Put(ctx, app.Env)
|
||||
}
|
||||
if !errors.Is(err, datastore.ErrRecordNotExist) {
|
||||
@@ -119,9 +122,11 @@ func StoreComponents(ctx context.Context, appPrimaryKey string, expComps []*mode
|
||||
return err
|
||||
}
|
||||
var originCompNames []string
|
||||
for _, entity := range originComps {
|
||||
comp := entity.(*model.ApplicationComponent)
|
||||
var existComponentMap = make(map[string]*model.ApplicationComponent)
|
||||
for i := range originComps {
|
||||
comp := originComps[i].(*model.ApplicationComponent)
|
||||
originCompNames = append(originCompNames, comp.Name)
|
||||
existComponentMap[comp.Name] = comp
|
||||
}
|
||||
|
||||
var targetCompNames []string
|
||||
@@ -154,6 +159,9 @@ func StoreComponents(ctx context.Context, appPrimaryKey string, expComps []*mode
|
||||
if utils.StringsContain(readyToAdd, comp.Name) {
|
||||
err = ds.Add(ctx, comp)
|
||||
} else {
|
||||
if old := existComponentMap[comp.Name]; old != nil {
|
||||
comp.CreateTime = old.CreateTime
|
||||
}
|
||||
err = ds.Put(ctx, comp)
|
||||
}
|
||||
if err != nil {
|
||||
@@ -172,9 +180,11 @@ func StorePolicy(ctx context.Context, appPrimaryKey string, expPolicies []*model
|
||||
return err
|
||||
}
|
||||
var originPolicyNames []string
|
||||
for _, entity := range originPolicies {
|
||||
plc := entity.(*model.ApplicationPolicy)
|
||||
var policyMap = make(map[string]*model.ApplicationPolicy)
|
||||
for i := range originPolicies {
|
||||
plc := originPolicies[i].(*model.ApplicationPolicy)
|
||||
originPolicyNames = append(originPolicyNames, plc.Name)
|
||||
policyMap[plc.Name] = plc
|
||||
}
|
||||
|
||||
var targetPLCNames []string
|
||||
@@ -209,6 +219,9 @@ func StorePolicy(ctx context.Context, appPrimaryKey string, expPolicies []*model
|
||||
if utils.StringsContain(readyToAdd, plc.Name) {
|
||||
err = ds.Add(ctx, plc)
|
||||
} else {
|
||||
if existPolicy := policyMap[plc.Name]; existPolicy != nil {
|
||||
plc.CreateTime = existPolicy.CreateTime
|
||||
}
|
||||
err = ds.Put(ctx, plc)
|
||||
}
|
||||
if err != nil {
|
||||
@@ -221,8 +234,10 @@ func StorePolicy(ctx context.Context, appPrimaryKey string, expPolicies []*model
|
||||
|
||||
// StoreWorkflow will sync workflow application CR to datastore, it updates the only one workflow from the application with specified name
|
||||
func StoreWorkflow(ctx context.Context, dsApp *model.DataStoreApp, ds datastore.DataStore) error {
|
||||
err := ds.Get(ctx, &model.Workflow{AppPrimaryKey: dsApp.AppMeta.Name, Name: dsApp.Workflow.Name})
|
||||
old := &model.Workflow{AppPrimaryKey: dsApp.AppMeta.Name, Name: dsApp.Workflow.Name}
|
||||
err := ds.Get(ctx, old)
|
||||
if err == nil {
|
||||
dsApp.Workflow.CreateTime = old.CreateTime
|
||||
// it means the record already exists, update it
|
||||
return ds.Put(ctx, dsApp.Workflow)
|
||||
}
|
||||
@@ -254,8 +269,10 @@ func StoreApplicationRevision(ctx context.Context, dsApp *model.DataStoreApp, ds
|
||||
if dsApp.Revision == nil {
|
||||
return nil
|
||||
}
|
||||
err := ds.Get(ctx, &model.ApplicationRevision{AppPrimaryKey: dsApp.AppMeta.Name, Version: dsApp.Revision.Version})
|
||||
old := &model.ApplicationRevision{AppPrimaryKey: dsApp.AppMeta.Name, Version: dsApp.Revision.Version}
|
||||
err := ds.Get(ctx, old)
|
||||
if err == nil {
|
||||
dsApp.Revision.CreateTime = old.CreateTime
|
||||
return ds.Put(ctx, dsApp.Revision)
|
||||
}
|
||||
if !errors.Is(err, datastore.ErrRecordNotExist) {
|
||||
|
||||
@@ -18,11 +18,12 @@ package sync
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"sync"
|
||||
|
||||
"github.com/fatih/color"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/client-go/dynamic"
|
||||
dynamicInformer "k8s.io/client-go/dynamic/dynamicinformer"
|
||||
"k8s.io/client-go/rest"
|
||||
@@ -58,14 +59,17 @@ func (a *ApplicationSync) Start(ctx context.Context, errorChan chan error) {
|
||||
factory := dynamicInformer.NewFilteredDynamicSharedInformerFactory(dynamicClient, 0, v1.NamespaceAll, nil)
|
||||
informer := factory.ForResource(v1beta1.SchemeGroupVersion.WithResource("applications")).Informer()
|
||||
getApp := func(obj interface{}) *v1beta1.Application {
|
||||
app := &v1beta1.Application{}
|
||||
bs, err := json.Marshal(obj)
|
||||
if err != nil {
|
||||
log.Logger.Errorf("decode the application failure %s", err.Error())
|
||||
if app, ok := obj.(*v1beta1.Application); ok {
|
||||
return app
|
||||
}
|
||||
_ = json.Unmarshal(bs, app)
|
||||
return app
|
||||
var app v1beta1.Application
|
||||
if object, ok := obj.(*unstructured.Unstructured); ok {
|
||||
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(object.Object, &app); err != nil {
|
||||
log.Logger.Errorf("decode the application failure %s", err.Error())
|
||||
return &app
|
||||
}
|
||||
}
|
||||
return &app
|
||||
}
|
||||
cu := &CR2UX{
|
||||
ds: a.Store,
|
||||
@@ -89,6 +93,7 @@ func (a *ApplicationSync) Start(ctx context.Context, errorChan chan error) {
|
||||
if err := cu.AddOrUpdate(ctx, app.(*v1beta1.Application)); err != nil {
|
||||
log.Logger.Errorf("fail to add or update application %s", err.Error())
|
||||
}
|
||||
a.Queue.Done(app)
|
||||
}
|
||||
}()
|
||||
|
||||
|
||||
@@ -88,6 +88,7 @@ var _ = Describe("Test Worker CR sync to datastore", func() {
|
||||
|
||||
comp1 := model.ApplicationComponent{AppPrimaryKey: app1.Name, Name: "nginx"}
|
||||
Expect(ds.Get(ctx, &comp1)).Should(BeNil())
|
||||
Expect(comp1.CreateTime.IsZero()).Should(BeFalse())
|
||||
Expect(comp1.Properties).Should(BeEquivalentTo(&model.JSONStruct{"image": "nginx"}))
|
||||
|
||||
comp2 := model.ApplicationComponent{AppPrimaryKey: app1.Name, Name: "nginx2"}
|
||||
@@ -96,10 +97,12 @@ var _ = Describe("Test Worker CR sync to datastore", func() {
|
||||
|
||||
env := model.Env{Project: appNS1, Name: model.AutoGenEnvNamePrefix + appNS1}
|
||||
Expect(ds.Get(ctx, &env)).Should(BeNil())
|
||||
Expect(env.CreateTime.IsZero()).Should(BeFalse())
|
||||
Expect(len(env.Targets)).Should(Equal(2))
|
||||
|
||||
appPlc1 := model.ApplicationPolicy{AppPrimaryKey: app1.Name, Name: "topology-beijing-demo"}
|
||||
Expect(ds.Get(ctx, &appPlc1)).Should(BeNil())
|
||||
Expect(appPlc1.CreateTime.IsZero()).Should(BeFalse())
|
||||
appPlc2 := model.ApplicationPolicy{AppPrimaryKey: app1.Name, Name: "topology-local"}
|
||||
Expect(ds.Get(ctx, &appPlc2)).Should(BeNil())
|
||||
appwf1 := model.Workflow{AppPrimaryKey: app1.Name, Name: model.AutoGenWorkflowNamePrefix + app1.Name}
|
||||
|
||||
@@ -36,8 +36,10 @@ import (
|
||||
var _ = Describe("Test kubeapi datastore driver", func() {
|
||||
|
||||
It("Test add function", func() {
|
||||
err := kubeStore.Add(context.TODO(), &model.Application{Name: "kubevela-app", Description: "default"})
|
||||
app := &model.Application{Name: "kubevela-app", Description: "default"}
|
||||
err := kubeStore.Add(context.TODO(), app)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(app.CreateTime.IsZero()).Should(BeFalse())
|
||||
})
|
||||
|
||||
It("Test batch add function", func() {
|
||||
|
||||
@@ -82,8 +82,8 @@ func (c Condition) Validate() error {
|
||||
if c.JSONKey == "" {
|
||||
return fmt.Errorf("the json key of the condition can not be empty")
|
||||
}
|
||||
if c.Action != "enable" && c.Action != "disable" {
|
||||
return fmt.Errorf("the action of the condition must be enable or disable")
|
||||
if c.Action != "enable" && c.Action != "disable" && c.Action != "" {
|
||||
return fmt.Errorf("the action of the condition only supports enable, disable or leave it empty")
|
||||
}
|
||||
if c.Op != "" && !StringsContain([]string{"==", "!=", "in"}, c.Op) {
|
||||
return fmt.Errorf("the op of the condition must be `==` 、`!=` and `in`")
|
||||
|
||||
@@ -381,6 +381,9 @@ func (p *Parser) parsePoliciesFromRevision(ctx context.Context, af *Appfile) (er
|
||||
return err
|
||||
}
|
||||
for _, policy := range af.Policies {
|
||||
if policy.Properties == nil && policy.Type != v1alpha1.DebugPolicyType {
|
||||
return fmt.Errorf("policy %s named %s must not have empty properties", policy.Type, policy.Name)
|
||||
}
|
||||
switch policy.Type {
|
||||
case v1alpha1.GarbageCollectPolicyType:
|
||||
case v1alpha1.ApplyOncePolicyType:
|
||||
@@ -407,6 +410,9 @@ func (p *Parser) parsePolicies(ctx context.Context, af *Appfile) (err error) {
|
||||
return err
|
||||
}
|
||||
for _, policy := range af.Policies {
|
||||
if policy.Properties == nil && policy.Type != v1alpha1.DebugPolicyType {
|
||||
return fmt.Errorf("policy %s named %s must not have empty properties", policy.Type, policy.Name)
|
||||
}
|
||||
switch policy.Type {
|
||||
case v1alpha1.GarbageCollectPolicyType:
|
||||
case v1alpha1.ApplyOncePolicyType:
|
||||
|
||||
@@ -269,6 +269,20 @@ spec:
|
||||
image: "busybox"
|
||||
`
|
||||
|
||||
const appfileYamlEmptyPolicy = `
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: application-sample
|
||||
namespace: default
|
||||
spec:
|
||||
components: []
|
||||
policies:
|
||||
- type: garbage-collect
|
||||
name: somename
|
||||
properties:
|
||||
`
|
||||
|
||||
var _ = Describe("Test application parser", func() {
|
||||
It("Test we can parse an application to an appFile", func() {
|
||||
o := v1beta1.Application{}
|
||||
@@ -314,6 +328,14 @@ var _ = Describe("Test application parser", func() {
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
_, err = NewApplicationParser(&tclient, dm, pd).GenerateAppFile(context.TODO(), ¬found)
|
||||
Expect(err).Should(HaveOccurred())
|
||||
|
||||
By("app with empty policy")
|
||||
emptyPolicy := v1beta1.Application{}
|
||||
err = yaml.Unmarshal([]byte(appfileYamlEmptyPolicy), &emptyPolicy)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
_, err = NewApplicationParser(&tclient, dm, pd).GenerateAppFile(context.TODO(), &emptyPolicy)
|
||||
Expect(err).Should(HaveOccurred())
|
||||
Expect(err.Error()).Should(ContainSubstring("have empty properties"))
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
authenticationv1 "k8s.io/api/authentication/v1"
|
||||
certificatesv1 "k8s.io/api/certificates/v1"
|
||||
certificatesv1beta1 "k8s.io/api/certificates/v1beta1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
@@ -46,6 +47,9 @@ import (
|
||||
"github.com/oam-dev/kubevela/pkg/utils"
|
||||
)
|
||||
|
||||
// DefaultExpireTime is default expire time for both X.509 and SA token apply
|
||||
const DefaultExpireTime = time.Hour * 24 * 365
|
||||
|
||||
// KubeConfigGenerateOptions options for create KubeConfig
|
||||
type KubeConfigGenerateOptions struct {
|
||||
X509 *KubeConfigGenerateX509Options
|
||||
@@ -64,6 +68,7 @@ type KubeConfigGenerateX509Options struct {
|
||||
type KubeConfigGenerateServiceAccountOptions struct {
|
||||
ServiceAccountName string
|
||||
ServiceAccountNamespace string
|
||||
ExpireTime time.Duration
|
||||
}
|
||||
|
||||
// KubeConfigWithUserGenerateOption option for setting user in KubeConfig
|
||||
@@ -96,6 +101,7 @@ func (opt KubeConfigWithServiceAccountGenerateOption) ApplyToOptions(options *Ku
|
||||
options.ServiceAccount = &KubeConfigGenerateServiceAccountOptions{
|
||||
ServiceAccountName: opt.Name,
|
||||
ServiceAccountNamespace: opt.Namespace,
|
||||
ExpireTime: DefaultExpireTime,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,7 +134,7 @@ func newKubeConfigGenerateOptions(options ...KubeConfigGenerateOption) *KubeConf
|
||||
X509: &KubeConfigGenerateX509Options{
|
||||
User: user.Anonymous,
|
||||
Groups: []string{KubeVelaClientGroup},
|
||||
ExpireTime: time.Hour * 24 * 365,
|
||||
ExpireTime: DefaultExpireTime,
|
||||
PrivateKeyBits: 2048,
|
||||
},
|
||||
ServiceAccount: nil,
|
||||
@@ -329,30 +335,53 @@ func generateX509KubeConfigV1Beta(ctx context.Context, cli kubernetes.Interface,
|
||||
}
|
||||
|
||||
func generateServiceAccountKubeConfig(ctx context.Context, cli kubernetes.Interface, cfg *clientcmdapi.Config, writer io.Writer, opts *KubeConfigGenerateServiceAccountOptions) (*clientcmdapi.Config, error) {
|
||||
var (
|
||||
token string
|
||||
CA []byte
|
||||
)
|
||||
sa, err := cli.CoreV1().ServiceAccounts(opts.ServiceAccountNamespace).Get(ctx, opts.ServiceAccountName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, _ = fmt.Fprintf(writer, "ServiceAccount %s/%s found.\n", opts.ServiceAccountNamespace, opts.ServiceAccountName)
|
||||
if len(sa.Secrets) == 0 {
|
||||
return nil, errors.Errorf("no secret found in serviceaccount %s/%s", opts.ServiceAccountNamespace, opts.ServiceAccountName)
|
||||
_, _ = fmt.Fprintf(writer, "ServiceAccount %s/%s has no secret. Requesting token", opts.ServiceAccountNamespace, opts.ServiceAccountName)
|
||||
request := authenticationv1.TokenRequest{
|
||||
Spec: authenticationv1.TokenRequestSpec{
|
||||
Audiences: []string{},
|
||||
ExpirationSeconds: pointer.Int64(int64(opts.ExpireTime.Seconds())),
|
||||
},
|
||||
}
|
||||
tokenRequest, err := cli.CoreV1().ServiceAccounts(opts.ServiceAccountNamespace).CreateToken(ctx, opts.ServiceAccountName, &request, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to request token")
|
||||
}
|
||||
token = tokenRequest.Status.Token
|
||||
CAConfigMap, err := cli.CoreV1().ConfigMaps(sa.Namespace).Get(ctx, "kube-root-ca.crt", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get root CA secret")
|
||||
}
|
||||
CA = []byte(CAConfigMap.Data["ca.crt"])
|
||||
} else {
|
||||
secretKey := sa.Secrets[0]
|
||||
if secretKey.Namespace == "" {
|
||||
secretKey.Namespace = sa.Namespace
|
||||
}
|
||||
secret, err := cli.CoreV1().Secrets(secretKey.Namespace).Get(ctx, secretKey.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, _ = fmt.Fprintf(writer, "ServiceAccount secret %s/%s found.\n", secretKey.Namespace, secret.Name)
|
||||
if len(secret.Data["token"]) == 0 {
|
||||
return nil, errors.Errorf("no token found in secret %s/%s", secret.Namespace, secret.Name)
|
||||
}
|
||||
_, _ = fmt.Fprintf(writer, "ServiceAccount token found.\n")
|
||||
token = string(secret.Data["token"])
|
||||
CA = secret.Data["ca.crt"]
|
||||
}
|
||||
secretKey := sa.Secrets[0]
|
||||
if secretKey.Namespace == "" {
|
||||
secretKey.Namespace = sa.Namespace
|
||||
}
|
||||
secret, err := cli.CoreV1().Secrets(secretKey.Namespace).Get(ctx, secretKey.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, _ = fmt.Fprintf(writer, "ServiceAccount secret %s/%s found.\n", secretKey.Namespace, secret.Name)
|
||||
if len(secret.Data["token"]) == 0 {
|
||||
return nil, errors.Errorf("no token found in secret %s/%s", secret.Namespace, secret.Name)
|
||||
}
|
||||
_, _ = fmt.Fprintf(writer, "ServiceAccount token found.\n")
|
||||
return genKubeConfig(cfg, &clientcmdapi.AuthInfo{
|
||||
Token: string(secret.Data["token"]),
|
||||
}, secret.Data["ca.crt"])
|
||||
Token: token,
|
||||
}, CA)
|
||||
}
|
||||
|
||||
// ReadIdentityFromKubeConfig extract identity from kubeconfig
|
||||
|
||||
@@ -86,4 +86,7 @@ type Args struct {
|
||||
|
||||
// IgnoreAppWithoutControllerRequirement indicates that application controller will not process the app without 'app.oam.dev/controller-version-require' annotation.
|
||||
IgnoreAppWithoutControllerRequirement bool
|
||||
|
||||
// IgnoreDefinitionWithoutControllerRequirement indicates that trait/component/workflowstep definition controller will not process the definition without 'definition.oam.dev/controller-version-require' annotation.
|
||||
IgnoreDefinitionWithoutControllerRequirement bool
|
||||
}
|
||||
|
||||
@@ -299,6 +299,11 @@ func (r *Reconciler) gcResourceTrackers(logCtx monitorContext.Context, handler *
|
||||
}))
|
||||
defer subCtx.Commit("finish gc resourceTrackers")
|
||||
|
||||
statusUpdater := r.updateStatus
|
||||
if isPatch {
|
||||
statusUpdater = r.patchStatus
|
||||
}
|
||||
|
||||
var options []resourcekeeper.GCOption
|
||||
if !gcOutdated {
|
||||
options = append(options, resourcekeeper.DisableMarkStageGCOption{}, resourcekeeper.DisableGCComponentRevisionOption{}, resourcekeeper.DisableLegacyGCOption{})
|
||||
@@ -306,8 +311,10 @@ func (r *Reconciler) gcResourceTrackers(logCtx monitorContext.Context, handler *
|
||||
finished, waiting, err := handler.resourceKeeper.GarbageCollect(logCtx, options...)
|
||||
if err != nil {
|
||||
logCtx.Error(err, "Failed to gc resourcetrackers")
|
||||
r.Recorder.Event(handler.app, event.Warning(velatypes.ReasonFailedGC, err))
|
||||
return r.endWithNegativeCondition(logCtx, handler.app, condition.ReconcileError(err), phase)
|
||||
cond := condition.Deleting()
|
||||
cond.Message = fmt.Sprintf("error encountered during garbage collection: %s", err.Error())
|
||||
handler.app.Status.SetConditions(cond)
|
||||
return r.result(statusUpdater(logCtx, handler.app, phase)).ret()
|
||||
}
|
||||
if !finished {
|
||||
logCtx.Info("GarbageCollecting resourcetrackers unfinished")
|
||||
@@ -316,13 +323,13 @@ func (r *Reconciler) gcResourceTrackers(logCtx monitorContext.Context, handler *
|
||||
cond.Message = fmt.Sprintf("Waiting for %s to delete. (At least %d resources are deleting.)", waiting[0].DisplayName(), len(waiting))
|
||||
}
|
||||
handler.app.Status.SetConditions(cond)
|
||||
return r.result(r.patchStatus(logCtx, handler.app, phase)).requeue(baseGCBackoffWaitTime).ret()
|
||||
return r.result(statusUpdater(logCtx, handler.app, phase)).requeue(baseGCBackoffWaitTime).ret()
|
||||
}
|
||||
logCtx.Info("GarbageCollected resourcetrackers")
|
||||
if !isPatch {
|
||||
return r.result(r.updateStatus(logCtx, handler.app, common.ApplicationRunningWorkflow)).ret()
|
||||
phase = common.ApplicationRunningWorkflow
|
||||
}
|
||||
return r.result(r.patchStatus(logCtx, handler.app, phase)).ret()
|
||||
return r.result(statusUpdater(logCtx, handler.app, phase)).ret()
|
||||
}
|
||||
|
||||
type reconcileResult struct {
|
||||
|
||||
@@ -1612,6 +1612,7 @@ var _ = Describe("Test Application Controller", func() {
|
||||
Expect(err).Should(BeNil())
|
||||
rolloutTrait := &v1beta1.TraitDefinition{}
|
||||
Expect(json.Unmarshal([]byte(rolloutTdDef), rolloutTrait)).Should(BeNil())
|
||||
rolloutTrait.Spec.SkipRevisionAffect = false
|
||||
ns := corev1.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "app-with-rollout-trait",
|
||||
@@ -1673,15 +1674,13 @@ var _ = Describe("Test Application Controller", func() {
|
||||
deploy = &v1.Deployment{}
|
||||
Expect(k8sClient.Get(ctx, types.NamespacedName{Name: "myweb1", Namespace: ns.Name}, deploy)).Should(util.NotFoundMatcher{})
|
||||
|
||||
By("check update rollout trait won't generate new appRevision")
|
||||
appRevName := checkApp.Status.LatestRevision.Name
|
||||
By("check update rollout trait generate new appRevision")
|
||||
checkApp.Spec.Components[0].Traits[0].Properties = &runtime.RawExtension{Raw: []byte(`{"targetRevision":"myweb1-v3"}`)}
|
||||
Expect(k8sClient.Update(ctx, checkApp)).Should(BeNil())
|
||||
testutil.ReconcileOnce(reconciler, reconcile.Request{NamespacedName: appKey})
|
||||
testutil.ReconcileOnce(reconciler, reconcile.Request{NamespacedName: appKey})
|
||||
checkApp = &v1beta1.Application{}
|
||||
Expect(k8sClient.Get(ctx, appKey, checkApp)).Should(BeNil())
|
||||
Expect(checkApp.Status.LatestRevision.Name).Should(BeEquivalentTo(appRevName))
|
||||
checkRollout = &stdv1alpha1.Rollout{}
|
||||
Expect(k8sClient.Get(ctx, types.NamespacedName{Name: "myweb1", Namespace: ns.Name}, checkRollout)).Should(BeNil())
|
||||
Expect(checkRollout.Spec.TargetRevisionName).Should(BeEquivalentTo("myweb1-v3"))
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/go-version"
|
||||
"github.com/pkg/errors"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
@@ -233,9 +234,6 @@ func (h *AppHandler) gatherRevisionSpec(af *appfile.Appfile) (*v1beta1.Applicati
|
||||
copiedApp := h.app.DeepCopy()
|
||||
// We better to remove all object status in the appRevision
|
||||
copiedApp.Status = common.AppStatus{}
|
||||
if !metav1.HasAnnotation(h.app.ObjectMeta, oam.AnnotationPublishVersion) {
|
||||
copiedApp.Spec.Workflow = nil
|
||||
}
|
||||
appRev := &v1beta1.ApplicationRevision{
|
||||
Spec: v1beta1.ApplicationRevisionSpec{
|
||||
Application: *copiedApp,
|
||||
@@ -525,6 +523,28 @@ func deepEqualWorkflow(old, new v1alpha1.Workflow) bool {
|
||||
return apiequality.Semantic.DeepEqual(old.Steps, new.Steps)
|
||||
}
|
||||
|
||||
const velaVersionNumberToCompareWorkflow = "v1.5.7"
|
||||
|
||||
func deepEqualAppSpec(old, new *v1beta1.Application) bool {
|
||||
oldSpec, newSpec := old.Spec.DeepCopy(), new.Spec.DeepCopy()
|
||||
// legacy code: KubeVela version before v1.5.7 & v1.6.0-alpha.4 does not
|
||||
// record workflow in application spec in application revision. The comparison
|
||||
// need to bypass the equality check of workflow to prevent unintended rerun
|
||||
var curVerNum, publishVersion string
|
||||
if annotations := old.GetAnnotations(); annotations != nil {
|
||||
curVerNum = annotations[oam.AnnotationKubeVelaVersion]
|
||||
publishVersion = annotations[oam.AnnotationPublishVersion]
|
||||
}
|
||||
if publishVersion == "" && curVerNum != "" {
|
||||
cmpVer, _ := version.NewVersion(velaVersionNumberToCompareWorkflow)
|
||||
if curVer, err := version.NewVersion(curVerNum); err == nil && curVer.LessThan(cmpVer) {
|
||||
oldSpec.Workflow = nil
|
||||
newSpec.Workflow = nil
|
||||
}
|
||||
}
|
||||
return apiequality.Semantic.DeepEqual(oldSpec, newSpec)
|
||||
}
|
||||
|
||||
func deepEqualAppInRevision(old, new *v1beta1.ApplicationRevision) bool {
|
||||
if len(old.Spec.Policies) != len(new.Spec.Policies) {
|
||||
return false
|
||||
@@ -542,8 +562,10 @@ func deepEqualAppInRevision(old, new *v1beta1.ApplicationRevision) bool {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return apiequality.Semantic.DeepEqual(filterSkipAffectAppRevTrait(old.Spec.Application.Spec, old.Spec.TraitDefinitions),
|
||||
filterSkipAffectAppRevTrait(new.Spec.Application.Spec, new.Spec.TraitDefinitions))
|
||||
oldApp, newApp := old.Spec.Application.DeepCopy(), new.Spec.Application.DeepCopy()
|
||||
oldApp.Spec = filterSkipAffectAppRevTrait(oldApp.Spec, old.Spec.TraitDefinitions)
|
||||
newApp.Spec = filterSkipAffectAppRevTrait(newApp.Spec, new.Spec.TraitDefinitions)
|
||||
return deepEqualAppSpec(oldApp, newApp)
|
||||
}
|
||||
|
||||
// HandleComponentsRevision manages Component revisions
|
||||
|
||||
@@ -22,10 +22,12 @@ import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
@@ -1171,3 +1173,19 @@ status: {}
|
||||
}()).Should(BeTrue())
|
||||
})
|
||||
})
|
||||
|
||||
func TestDeepEqualAppInRevision(t *testing.T) {
|
||||
oldRev := &v1beta1.ApplicationRevision{}
|
||||
newRev := &v1beta1.ApplicationRevision{}
|
||||
newRev.Spec.Application.Spec.Workflow = &v1beta1.Workflow{
|
||||
Steps: []v1beta1.WorkflowStep{{
|
||||
Type: "deploy",
|
||||
Name: "deploy",
|
||||
}},
|
||||
}
|
||||
require.False(t, deepEqualAppInRevision(oldRev, newRev))
|
||||
metav1.SetMetaDataAnnotation(&oldRev.Spec.Application.ObjectMeta, oam.AnnotationKubeVelaVersion, "v1.6.0-alpha.5")
|
||||
require.False(t, deepEqualAppInRevision(oldRev, newRev))
|
||||
metav1.SetMetaDataAnnotation(&oldRev.Spec.Application.ObjectMeta, oam.AnnotationKubeVelaVersion, "v1.5.0")
|
||||
require.True(t, deepEqualAppInRevision(oldRev, newRev))
|
||||
}
|
||||
|
||||
@@ -43,17 +43,24 @@ import (
|
||||
"github.com/oam-dev/kubevela/pkg/oam"
|
||||
"github.com/oam-dev/kubevela/pkg/oam/discoverymapper"
|
||||
"github.com/oam-dev/kubevela/pkg/oam/util"
|
||||
"github.com/oam-dev/kubevela/version"
|
||||
)
|
||||
|
||||
// Reconciler reconciles a ComponentDefinition object
|
||||
type Reconciler struct {
|
||||
client.Client
|
||||
dm discoverymapper.DiscoveryMapper
|
||||
pd *packages.PackageDiscover
|
||||
Scheme *runtime.Scheme
|
||||
record event.Recorder
|
||||
dm discoverymapper.DiscoveryMapper
|
||||
pd *packages.PackageDiscover
|
||||
Scheme *runtime.Scheme
|
||||
record event.Recorder
|
||||
options
|
||||
}
|
||||
|
||||
type options struct {
|
||||
defRevLimit int
|
||||
concurrentReconciles int
|
||||
ignoreDefNoCtrlReq bool
|
||||
controllerVersion string
|
||||
}
|
||||
|
||||
// Reconcile is the main logic for ComponentDefinition controller
|
||||
@@ -68,6 +75,11 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
|
||||
return ctrl.Result{}, client.IgnoreNotFound(err)
|
||||
}
|
||||
|
||||
if !r.matchControllerRequirement(&componentDefinition) {
|
||||
klog.InfoS("skip componentDefinition: not match the controller requirement of componentDefinition", "componentDefinition", klog.KObj(&componentDefinition))
|
||||
return ctrl.Result{}, nil
|
||||
}
|
||||
|
||||
// refresh package discover when componentDefinition is registered
|
||||
if componentDefinition.Spec.Workload.Type != types.AutoDetectWorkloadDefinition {
|
||||
err := utils.RefreshPackageDiscover(ctx, r.Client, r.dm, r.pd, &componentDefinition)
|
||||
@@ -187,12 +199,32 @@ func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error {
|
||||
// Setup adds a controller that reconciles ComponentDefinition.
|
||||
func Setup(mgr ctrl.Manager, args oamctrl.Args) error {
|
||||
r := Reconciler{
|
||||
Client: mgr.GetClient(),
|
||||
Scheme: mgr.GetScheme(),
|
||||
dm: args.DiscoveryMapper,
|
||||
pd: args.PackageDiscover,
|
||||
defRevLimit: args.DefRevisionLimit,
|
||||
concurrentReconciles: args.ConcurrentReconciles,
|
||||
Client: mgr.GetClient(),
|
||||
Scheme: mgr.GetScheme(),
|
||||
dm: args.DiscoveryMapper,
|
||||
pd: args.PackageDiscover,
|
||||
options: parseOptions(args),
|
||||
}
|
||||
return r.SetupWithManager(mgr)
|
||||
}
|
||||
|
||||
func parseOptions(args oamctrl.Args) options {
|
||||
return options{
|
||||
defRevLimit: args.DefRevisionLimit,
|
||||
concurrentReconciles: args.ConcurrentReconciles,
|
||||
ignoreDefNoCtrlReq: args.IgnoreDefinitionWithoutControllerRequirement,
|
||||
controllerVersion: version.VelaVersion,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Reconciler) matchControllerRequirement(componentDefinition *v1beta1.ComponentDefinition) bool {
|
||||
if componentDefinition.Annotations != nil {
|
||||
if requireVersion, ok := componentDefinition.Annotations[oam.AnnotationControllerRequirement]; ok {
|
||||
return requireVersion == r.controllerVersion
|
||||
}
|
||||
}
|
||||
if r.ignoreDefNoCtrlReq {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user