mirror of
https://github.com/kubevela/kubevela.git
synced 2026-02-28 16:50:29 +00:00
Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
69
.github/workflows/apiserver-test.yaml
vendored
69
.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:
|
||||
@@ -111,6 +110,9 @@ jobs:
|
||||
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'
|
||||
|
||||
68
.github/workflows/e2e-multicluster-test.yml
vendored
68
.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,9 +45,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
|
||||
|
||||
|
||||
@@ -59,6 +58,9 @@ jobs:
|
||||
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
|
||||
|
||||
53
.github/workflows/e2e-rollout-test.yml
vendored
53
.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,9 +45,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
|
||||
|
||||
e2e-rollout-tests:
|
||||
@@ -58,6 +57,10 @@ jobs:
|
||||
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
|
||||
|
||||
52
.github/workflows/e2e-test.yml
vendored
52
.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,9 +45,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
|
||||
|
||||
e2e-tests:
|
||||
@@ -58,6 +57,10 @@ jobs:
|
||||
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
|
||||
|
||||
1
.github/workflows/go.yml
vendored
1
.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:
|
||||
|
||||
|
||||
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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -19,6 +19,7 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
goflag "flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
@@ -139,6 +140,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,9 +149,10 @@ 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)))
|
||||
}
|
||||
|
||||
@@ -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: {}
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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"))
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -90,11 +90,13 @@ var _ = BeforeSuite(func(done Done) {
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
r = Reconciler{
|
||||
Client: mgr.GetClient(),
|
||||
Scheme: mgr.GetScheme(),
|
||||
dm: dm,
|
||||
pd: pd,
|
||||
defRevLimit: defRevisionLimit,
|
||||
Client: mgr.GetClient(),
|
||||
Scheme: mgr.GetScheme(),
|
||||
dm: dm,
|
||||
pd: pd,
|
||||
options: options{
|
||||
defRevLimit: defRevisionLimit,
|
||||
},
|
||||
}
|
||||
Expect(r.SetupWithManager(mgr)).ToNot(HaveOccurred())
|
||||
var ctx context.Context
|
||||
|
||||
@@ -42,17 +42,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 TraitDefinition 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 TraitDefinition controller
|
||||
@@ -67,6 +74,11 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
|
||||
return ctrl.Result{}, client.IgnoreNotFound(err)
|
||||
}
|
||||
|
||||
if !r.matchControllerRequirement(&traitdefinition) {
|
||||
klog.InfoS("skip traitDefinition: not match the controller requirement of traitDefinition", "traitDefinition", klog.KObj(&traitdefinition))
|
||||
return ctrl.Result{}, nil
|
||||
}
|
||||
|
||||
// this is a placeholder for finalizer here in the future
|
||||
if traitdefinition.DeletionTimestamp != nil {
|
||||
klog.InfoS("The TraitDefinition is being deleted", "traitDefinition", klog.KRef(req.Namespace, req.Name))
|
||||
@@ -193,12 +205,32 @@ func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error {
|
||||
// Setup adds a controller that reconciles TraitDefinition.
|
||||
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(traitDefinition *v1beta1.TraitDefinition) bool {
|
||||
if traitDefinition.Annotations != nil {
|
||||
if requireVersion, ok := traitDefinition.Annotations[oam.AnnotationControllerRequirement]; ok {
|
||||
return requireVersion == r.controllerVersion
|
||||
}
|
||||
}
|
||||
if r.ignoreDefNoCtrlReq {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -90,11 +90,13 @@ var _ = BeforeSuite(func(done Done) {
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
r = Reconciler{
|
||||
Client: mgr.GetClient(),
|
||||
Scheme: mgr.GetScheme(),
|
||||
dm: dm,
|
||||
pd: pd,
|
||||
defRevLimit: defRevisionLimit,
|
||||
Client: mgr.GetClient(),
|
||||
Scheme: mgr.GetScheme(),
|
||||
dm: dm,
|
||||
pd: pd,
|
||||
options: options{
|
||||
defRevLimit: defRevisionLimit,
|
||||
},
|
||||
}
|
||||
Expect(r.SetupWithManager(mgr)).ToNot(HaveOccurred())
|
||||
var ctx context.Context
|
||||
|
||||
@@ -90,11 +90,13 @@ var _ = BeforeSuite(func(done Done) {
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
r = Reconciler{
|
||||
Client: mgr.GetClient(),
|
||||
Scheme: mgr.GetScheme(),
|
||||
dm: dm,
|
||||
pd: pd,
|
||||
defRevLimit: defRevisionLimit,
|
||||
Client: mgr.GetClient(),
|
||||
Scheme: mgr.GetScheme(),
|
||||
dm: dm,
|
||||
pd: pd,
|
||||
options: options{
|
||||
defRevLimit: defRevisionLimit,
|
||||
},
|
||||
}
|
||||
Expect(r.SetupWithManager(mgr)).ToNot(HaveOccurred())
|
||||
var ctx context.Context
|
||||
|
||||
@@ -42,17 +42,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 WorkflowStepDefinition 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 WorkflowStepDefinition 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(&wfstepdefinition) {
|
||||
klog.InfoS("skip workflowStepDefinition: not match the controller requirement of workflowStepDefinition", "workflowStepDefinition", klog.KObj(&wfstepdefinition))
|
||||
return ctrl.Result{}, nil
|
||||
}
|
||||
|
||||
// this is a placeholder for finalizer here in the future
|
||||
if wfstepdefinition.DeletionTimestamp != nil {
|
||||
return ctrl.Result{}, nil
|
||||
@@ -192,11 +204,32 @@ func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error {
|
||||
// Setup adds a controller that reconciles WorkflowStepDefinition.
|
||||
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,
|
||||
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(wfstepdefinition *v1beta1.WorkflowStepDefinition) bool {
|
||||
if wfstepdefinition.Annotations != nil {
|
||||
if requireVersion, ok := wfstepdefinition.Annotations[oam.AnnotationControllerRequirement]; ok {
|
||||
return requireVersion == r.controllerVersion
|
||||
}
|
||||
}
|
||||
if r.ignoreDefNoCtrlReq {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
|
||||
"cuelang.org/go/cue"
|
||||
"cuelang.org/go/cue/ast"
|
||||
"cuelang.org/go/cue/format"
|
||||
"cuelang.org/go/cue/parser"
|
||||
jsonpatch "github.com/evanphx/json-patch"
|
||||
"github.com/pkg/errors"
|
||||
@@ -361,7 +362,7 @@ func jsonMergePatch(base cue.Value, patch cue.Value) (string, error) {
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "failed to merge base value and patch value by JsonMergePatch")
|
||||
}
|
||||
output, err := OpenBaiscLit(string(merged))
|
||||
output, err := openJSON(string(merged))
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "failed to parse open basic lit for merged result")
|
||||
}
|
||||
@@ -386,9 +387,47 @@ func jsonPatch(base cue.Value, patch cue.Value) (string, error) {
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "failed to apply json patch")
|
||||
}
|
||||
output, err := OpenBaiscLit(string(merged))
|
||||
output, err := openJSON(string(merged))
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "failed to parse open basic lit for merged result")
|
||||
}
|
||||
return output, nil
|
||||
}
|
||||
|
||||
func isEllipsis(elt ast.Node) bool {
|
||||
_, ok := elt.(*ast.Ellipsis)
|
||||
return ok
|
||||
}
|
||||
|
||||
func openJSON(data string) (string, error) {
|
||||
f, err := parser.ParseFile("-", data, parser.ParseComments)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
ast.Walk(f, func(node ast.Node) bool {
|
||||
field, ok := node.(*ast.Field)
|
||||
if ok {
|
||||
v := field.Value
|
||||
switch lit := v.(type) {
|
||||
case *ast.StructLit:
|
||||
if len(lit.Elts) == 0 || !isEllipsis(lit.Elts[len(lit.Elts)-1]) {
|
||||
lit.Elts = append(lit.Elts, &ast.Ellipsis{})
|
||||
}
|
||||
case *ast.ListLit:
|
||||
if len(lit.Elts) == 0 || !isEllipsis(lit.Elts[len(lit.Elts)-1]) {
|
||||
lit.Elts = append(lit.Elts, &ast.Ellipsis{})
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}, nil)
|
||||
if len(f.Decls) > 0 {
|
||||
if emb, ok := f.Decls[0].(*ast.EmbedDecl); ok {
|
||||
if s, _ok := emb.Expr.(*ast.StructLit); _ok {
|
||||
f.Decls = s.Elts
|
||||
}
|
||||
}
|
||||
}
|
||||
b, err := format.Node(f)
|
||||
return string(b), err
|
||||
}
|
||||
|
||||
@@ -182,7 +182,8 @@ func peelCloseExpr(node ast.Node) ast.Node {
|
||||
|
||||
func lookField(node ast.Node, key string) ast.Node {
|
||||
if field, ok := node.(*ast.Field); ok {
|
||||
if labelStr(field.Label) == key {
|
||||
// Note: the trim here has side effect: "\(v)" will be trimmed to \(v), only used for comparing fields
|
||||
if strings.Trim(labelStr(field.Label), `"`) == strings.Trim(key, `"`) {
|
||||
return field.Value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,12 @@ const (
|
||||
AliasKey = "definition.oam.dev/alias"
|
||||
// UserPrefix defines the prefix of user customized label or annotation
|
||||
UserPrefix = "custom.definition.oam.dev/"
|
||||
// DefinitionAlias is alias of definition
|
||||
DefinitionAlias = "alias.config.oam.dev"
|
||||
// DefinitionType marks definition's usage type, like image-registry
|
||||
DefinitionType = "type.config.oam.dev"
|
||||
// ConfigCatalog marks definition is a catalog
|
||||
ConfigCatalog = "catalog.config.oam.dev"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@@ -208,7 +208,7 @@ const (
|
||||
// AnnotationWorkloadName indicates the managed workload's name by trait
|
||||
AnnotationWorkloadName = "trait.oam.dev/workload-name"
|
||||
|
||||
// AnnotationControllerRequirement indicates the controller version that can process the application.
|
||||
// AnnotationControllerRequirement indicates the controller version that can process the application/definition.
|
||||
AnnotationControllerRequirement = "app.oam.dev/controller-version-require"
|
||||
|
||||
// AnnotationApplicationServiceAccountName indicates the name of the ServiceAccount to use to apply Components and run Workflow.
|
||||
@@ -227,8 +227,12 @@ const (
|
||||
// AnnotationResourceURL records the source url of the Kubernetes object
|
||||
AnnotationResourceURL = "app.oam.dev/resource-url"
|
||||
|
||||
// AnnotationIgnoreWithoutCompKey indicates the bond component
|
||||
// AnnotationIgnoreWithoutCompKey indicates the bond component.
|
||||
// Deprecated: please use AnnotationAddonDefinitionBindCompKey.
|
||||
AnnotationIgnoreWithoutCompKey = "addon.oam.dev/ignore-without-component"
|
||||
|
||||
// AnnotationAddonDefinitionBondCompKey indicates the definition in addon bond component.
|
||||
AnnotationAddonDefinitionBondCompKey = "addon.oam.dev/bind-component"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -113,7 +113,7 @@ func (cache *resourceCache) exists(manifest *unstructured.Unstructured) bool {
|
||||
return true
|
||||
}
|
||||
appKey, controlledBy := apply.GetAppKey(cache.app), apply.GetControlledBy(manifest)
|
||||
if appKey == controlledBy {
|
||||
if appKey == controlledBy || manifest.GetResourceVersion() == "" {
|
||||
return true
|
||||
}
|
||||
annotations := manifest.GetAnnotations()
|
||||
|
||||
@@ -139,8 +139,9 @@ func TestResourceCacheExistenceCheck(t *testing.T) {
|
||||
createResource := func(appName, appNs, sharedBy string) *unstructured.Unstructured {
|
||||
return &unstructured.Unstructured{Object: map[string]interface{}{
|
||||
"metadata": map[string]interface{}{
|
||||
"labels": map[string]interface{}{oam.LabelAppName: appName, oam.LabelAppNamespace: appNs},
|
||||
"annotations": map[string]interface{}{oam.AnnotationAppSharedBy: sharedBy},
|
||||
"labels": map[string]interface{}{oam.LabelAppName: appName, oam.LabelAppNamespace: appNs},
|
||||
"annotations": map[string]interface{}{oam.AnnotationAppSharedBy: sharedBy},
|
||||
"resourceVersion": "-",
|
||||
},
|
||||
}}
|
||||
}
|
||||
|
||||
@@ -352,7 +352,7 @@ func (h *gcHandler) deleteManagedResource(ctx context.Context, mr v1beta1.Manage
|
||||
delete(labels, oam.LabelAppNamespace)
|
||||
entry.obj.SetLabels(labels)
|
||||
}
|
||||
return errors.Wrapf(h.Client.Update(ctx, entry.obj), "failed to remove owner labels for resource while skipping gc")
|
||||
return errors.Wrapf(h.Client.Update(_ctx, entry.obj), "failed to remove owner labels for resource while skipping gc")
|
||||
}
|
||||
if err := h.Client.Delete(_ctx, entry.obj); err != nil && !kerrors.IsNotFound(err) {
|
||||
return errors.Wrapf(err, "failed to delete resource %s", mr.ResourceKey())
|
||||
|
||||
@@ -276,6 +276,7 @@ var _ = Describe("Test ResourceKeeper StateKeep", func() {
|
||||
"metadata": map[string]interface{}{
|
||||
"name": name,
|
||||
"namespace": "default",
|
||||
"labels": map[string]interface{}{oam.LabelAppComponent: name},
|
||||
},
|
||||
"spec": map[string]interface{}{
|
||||
"replicas": value,
|
||||
|
||||
@@ -8,12 +8,15 @@
|
||||
body: string
|
||||
header: [string]: string
|
||||
trailer: [string]: string
|
||||
...
|
||||
}
|
||||
tls_config?: secret: string
|
||||
response: {
|
||||
body: string
|
||||
header?: [string]: [...string]
|
||||
trailer?: [string]: [...string]
|
||||
statusCode: number
|
||||
...
|
||||
}
|
||||
...
|
||||
}
|
||||
|
||||
@@ -299,7 +299,10 @@ func MustBeControlledByApp(app *v1beta1.Application) ApplyOption {
|
||||
return nil
|
||||
}
|
||||
appKey, controlledBy := GetAppKey(app), GetControlledBy(existing)
|
||||
if controlledBy == "" && !utilfeature.DefaultMutableFeatureGate.Enabled(features.LegacyResourceOwnerValidation) {
|
||||
// if the existing object has no resource version, it means this resource is an API response not directly from
|
||||
// an etcd object but from some external services, such as vela-prism. Then the response does not necessarily
|
||||
// contain the owner
|
||||
if controlledBy == "" && !utilfeature.DefaultMutableFeatureGate.Enabled(features.LegacyResourceOwnerValidation) && existing.GetResourceVersion() != "" {
|
||||
return fmt.Errorf("%s %s/%s exists but not managed by any application now", existing.GetObjectKind().GroupVersionKind().Kind, existing.GetNamespace(), existing.GetName())
|
||||
}
|
||||
if controlledBy != "" && controlledBy != appKey {
|
||||
|
||||
@@ -380,18 +380,20 @@ func TestMustBeControlledByApp(t *testing.T) {
|
||||
hasError: false,
|
||||
},
|
||||
"old app has no label": {
|
||||
existing: &appsv1.Deployment{},
|
||||
existing: &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{ResourceVersion: "-"}},
|
||||
hasError: true,
|
||||
},
|
||||
"old app has no app label": {
|
||||
existing: &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{
|
||||
Labels: map[string]string{},
|
||||
Labels: map[string]string{},
|
||||
ResourceVersion: "-",
|
||||
}},
|
||||
hasError: true,
|
||||
},
|
||||
"old app has no app ns label": {
|
||||
existing: &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{
|
||||
Labels: map[string]string{oam.LabelAppName: "app"},
|
||||
Labels: map[string]string{oam.LabelAppName: "app"},
|
||||
ResourceVersion: "-",
|
||||
}},
|
||||
hasError: true,
|
||||
},
|
||||
@@ -413,6 +415,18 @@ func TestMustBeControlledByApp(t *testing.T) {
|
||||
}},
|
||||
hasError: true,
|
||||
},
|
||||
"old app has no resource version but with bad app key": {
|
||||
existing: &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{
|
||||
Labels: map[string]string{oam.LabelAppName: "app", oam.LabelAppNamespace: "ns"},
|
||||
}},
|
||||
hasError: true,
|
||||
},
|
||||
"old app has no resource version": {
|
||||
existing: &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{
|
||||
Labels: map[string]string{},
|
||||
}},
|
||||
hasError: false,
|
||||
},
|
||||
}
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
|
||||
@@ -81,19 +81,26 @@ func (c *AppCollector) CollectResourceFromApp() ([]Resource, error) {
|
||||
}
|
||||
|
||||
// ListApplicationResources list application applied resources from tracker
|
||||
func (c *AppCollector) ListApplicationResources(app *v1beta1.Application, queryTree bool) ([]*types.AppliedResource, error) {
|
||||
ctx := context.Background()
|
||||
func (c *AppCollector) ListApplicationResources(ctx context.Context, app *v1beta1.Application) ([]*types.AppliedResource, error) {
|
||||
rootRT, currentRT, historyRTs, _, err := resourcetracker.ListApplicationResourceTrackers(ctx, c.k8sClient, app)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var managedResources []*types.AppliedResource
|
||||
existResources := make(map[common.ClusterObjectReference]bool, len(app.Spec.Components))
|
||||
for _, rt := range append(historyRTs, rootRT, currentRT) {
|
||||
if rt != nil {
|
||||
for _, managedResource := range rt.Spec.ManagedResources {
|
||||
if isResourceInTargetCluster(c.opt.Filter, managedResource.ClusterObjectReference) &&
|
||||
isResourceInTargetComponent(c.opt.Filter, managedResource.Component) &&
|
||||
(queryTree || isResourceMatchKindAndVersion(c.opt.Filter, managedResource.Kind, managedResource.APIVersion)) {
|
||||
(c.opt.WithTree || isResourceMatchKindAndVersion(c.opt.Filter, managedResource.Kind, managedResource.APIVersion)) {
|
||||
if c.opt.WithTree {
|
||||
// If we want to query the tree, we only need to query once for the same resource.
|
||||
if _, exist := existResources[managedResource.ClusterObjectReference]; exist {
|
||||
continue
|
||||
}
|
||||
existResources[managedResource.ClusterObjectReference] = true
|
||||
}
|
||||
managedResources = append(managedResources, &types.AppliedResource{
|
||||
Cluster: func() string {
|
||||
if managedResource.Cluster != "" {
|
||||
@@ -125,7 +132,7 @@ func (c *AppCollector) ListApplicationResources(app *v1beta1.Application, queryT
|
||||
}
|
||||
}
|
||||
|
||||
if !queryTree {
|
||||
if !c.opt.WithTree {
|
||||
return managedResources, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ func (h *provider) GeneratorServiceEndpoints(wfctx wfContext.Context, v *value.V
|
||||
serviceEndpoints := make([]querytypes.ServiceEndpoint, 0)
|
||||
var clusterGatewayNodeIP = make(map[string]string)
|
||||
collector := NewAppCollector(h.cli, opt)
|
||||
resources, err := collector.ListApplicationResources(app, opt.WithTree)
|
||||
resources, err := collector.ListApplicationResources(ctx, app)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -210,10 +210,10 @@ func generatorFromService(service corev1.Service, selectorNodeIP func() string,
|
||||
appp := judgeAppProtocol(port.Port)
|
||||
for _, ingress := range service.Status.LoadBalancer.Ingress {
|
||||
if ingress.Hostname != "" {
|
||||
serviceEndpoints = append(serviceEndpoints, formatEndpoint(ingress.Hostname, appp, port.Protocol, port.Port, false))
|
||||
serviceEndpoints = append(serviceEndpoints, formatEndpoint(ingress.Hostname, appp, port.Protocol, port.NodePort, false))
|
||||
}
|
||||
if ingress.IP != "" {
|
||||
serviceEndpoints = append(serviceEndpoints, formatEndpoint(ingress.IP, appp, port.Protocol, port.Port, false))
|
||||
serviceEndpoints = append(serviceEndpoints, formatEndpoint(ingress.IP, appp, port.Protocol, port.NodePort, false))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user