mirror of
https://github.com/kubevela/kubevela.git
synced 2026-03-02 09:40:51 +00:00
Compare commits
82 Commits
v1.7.0-alp
...
release-1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4209080adc | ||
|
|
61348b9d45 | ||
|
|
aa5e825683 | ||
|
|
95d04c370d | ||
|
|
a583f66b0d | ||
|
|
7ae1aff648 | ||
|
|
0ff40d75e5 | ||
|
|
3d410fed5f | ||
|
|
f8285df49d | ||
|
|
e4cd1ffd1d | ||
|
|
592f8b8e8f | ||
|
|
94c215c361 | ||
|
|
1723a1795d | ||
|
|
0861498ab8 | ||
|
|
52c9a8f0a3 | ||
|
|
c7f337fd35 | ||
|
|
9dca76e0de | ||
|
|
348f540a82 | ||
|
|
1c2df10299 | ||
|
|
918ed9727b | ||
|
|
fa78cb7632 | ||
|
|
f3cdbcf203 | ||
|
|
7bd2cf4dbc | ||
|
|
969babdd9e | ||
|
|
94c46a179b | ||
|
|
bec288c6b4 | ||
|
|
9a44be9788 | ||
|
|
9c7f4b7e03 | ||
|
|
539f1ed02b | ||
|
|
9e95122387 | ||
|
|
f49f11dd72 | ||
|
|
191d9038f1 | ||
|
|
e10e43b6c8 | ||
|
|
b9cc523267 | ||
|
|
7f1743ef58 | ||
|
|
dd39c38cf1 | ||
|
|
0851454c6f | ||
|
|
cd3577db53 | ||
|
|
d578adfe6e | ||
|
|
4b88cd201e | ||
|
|
492e7d7f0d | ||
|
|
0742ca9ee5 | ||
|
|
1cf4ae3fc3 | ||
|
|
444d315143 | ||
|
|
2e3a89f6b1 | ||
|
|
d94293ac59 | ||
|
|
cc604cfadb | ||
|
|
8ef2513b2e | ||
|
|
657e3b1bde | ||
|
|
004e2a814d | ||
|
|
6dcba5ef11 | ||
|
|
fd39804dc9 | ||
|
|
ce57fbb752 | ||
|
|
80b2b2c2d3 | ||
|
|
49d97e5c2b | ||
|
|
1ee5915546 | ||
|
|
3f6b38cc7f | ||
|
|
c2c7ab91f9 | ||
|
|
866ffb9689 | ||
|
|
61afb366ee | ||
|
|
a2a8d73a58 | ||
|
|
fc3b428788 | ||
|
|
500dc52b34 | ||
|
|
789aa38476 | ||
|
|
17adf35717 | ||
|
|
586f266798 | ||
|
|
b8dcbe4964 | ||
|
|
778579c79b | ||
|
|
69293f4094 | ||
|
|
3a917cb6af | ||
|
|
1c43c6d1c5 | ||
|
|
9bbf7bf01b | ||
|
|
5a845104fb | ||
|
|
693eb3cb1d | ||
|
|
78f5827fa6 | ||
|
|
af8a7eb695 | ||
|
|
97ce8ba500 | ||
|
|
03d892bcf1 | ||
|
|
360c9e24b2 | ||
|
|
ba0a726cfc | ||
|
|
b2f4e237c2 | ||
|
|
5f71d05db1 |
2
.github/bot.md
vendored
2
.github/bot.md
vendored
@@ -1,6 +1,6 @@
|
||||
### GitHub & kubevela automation
|
||||
|
||||
The bot is configured via [issue-commands.json](https://github.com/kubevela/kubevela/blob/master/.github/workflows/issue-commands.json)
|
||||
The bot is configured via [issue-commands.json](https://github.com/kubevela/kubevela/blob/master/.github/issue-commands.json)
|
||||
and some other GitHub [workflows](https://github.com/kubevela/kubevela/blob/master/.github/workflows).
|
||||
By default, users with write access to the repo is allowed to use the comments,
|
||||
the [userlist](https://github.com/kubevela/kubevela/blob/master/.github/comment.userlist)
|
||||
|
||||
4
.github/workflows/apiserver-test.yml
vendored
4
.github/workflows/apiserver-test.yml
vendored
@@ -64,6 +64,8 @@ jobs:
|
||||
|
||||
- name: Install ginkgo
|
||||
run: |
|
||||
sudo sed -i 's/azure\.//' /etc/apt/sources.list
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y golang-ginkgo-dev
|
||||
|
||||
- name: Start MongoDB
|
||||
@@ -184,7 +186,7 @@ jobs:
|
||||
uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
files: /tmp/e2e_apiserver_test.out
|
||||
files: /tmp/e2e-profile.out, /tmp/e2e_apiserver_test.out
|
||||
flags: apiserver-e2etests
|
||||
name: codecov-umbrella
|
||||
|
||||
|
||||
133
.github/workflows/release.yml
vendored
133
.github/workflows/release.yml
vendored
@@ -7,7 +7,6 @@ on:
|
||||
workflow_dispatch: { }
|
||||
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
BUCKET: ${{ secrets.CLI_OSS_BUCKET }}
|
||||
ENDPOINT: ${{ secrets.CLI_OSS_ENDPOINT }}
|
||||
ACCESS_KEY: ${{ secrets.CLI_OSS_ACCESS_KEY }}
|
||||
@@ -28,105 +27,36 @@ jobs:
|
||||
repository-projects: read
|
||||
statuses: read
|
||||
runs-on: ubuntu-latest
|
||||
name: build
|
||||
strategy:
|
||||
matrix:
|
||||
TARGETS: [ linux/amd64, darwin/amd64, windows/amd64, linux/arm64, darwin/arm64 ]
|
||||
env:
|
||||
VELA_VERSION_KEY: github.com/oam-dev/kubevela/version.VelaVersion
|
||||
VELA_GITVERSION_KEY: github.com/oam-dev/kubevela/version.GitRevision
|
||||
GO_BUILD_ENV: GO111MODULE=on CGO_ENABLED=0
|
||||
DIST_DIRS: find * -type d -exec
|
||||
name: goreleaser
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- run: git fetch --force --tags
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568
|
||||
with:
|
||||
go-version: 1.19
|
||||
- name: Get release
|
||||
id: get_release
|
||||
uses: bruceadams/get-release@74c3d60f5a28f358ccf241a00c9021ea16f0569f # v1.3.2
|
||||
cache: true
|
||||
- uses: goreleaser/goreleaser-action@9754a253a8673b0ea869c2e863b4e975497efd0c # v4.1.1
|
||||
with:
|
||||
distribution: goreleaser
|
||||
version: 1.14.1
|
||||
args: release --rm-dist --timeout 60m
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
# Since goreleaser haven't supported aliyun OSS, we need to upload the release manually
|
||||
- name: Get version
|
||||
run: echo "VELA_VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
|
||||
- name: Get matrix
|
||||
id: get_matrix
|
||||
run: |
|
||||
TARGETS=${{matrix.TARGETS}}
|
||||
echo "OS=${TARGETS%/*}" >> $GITHUB_OUTPUT
|
||||
echo "ARCH=${TARGETS#*/}" >> $GITHUB_OUTPUT
|
||||
- name: Get ldflags
|
||||
id: get_ldflags
|
||||
run: |
|
||||
LDFLAGS="-s -w -X ${{ env.VELA_VERSION_KEY }}=${{ env.VELA_VERSION }} -X ${{ env.VELA_GITVERSION_KEY }}=git-$(git rev-parse --short HEAD)"
|
||||
echo "LDFLAGS=${LDFLAGS}" >> $GITHUB_ENV
|
||||
- name: Build
|
||||
run: |
|
||||
${{ env.GO_BUILD_ENV }} GOOS=${{ steps.get_matrix.outputs.OS }} GOARCH=${{ steps.get_matrix.outputs.ARCH }} \
|
||||
go build -ldflags "${{ env.LDFLAGS }}" \
|
||||
-o _bin/vela/${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}/vela -v \
|
||||
./references/cmd/cli/main.go
|
||||
${{ env.GO_BUILD_ENV }} GOOS=${{ steps.get_matrix.outputs.OS }} GOARCH=${{ steps.get_matrix.outputs.ARCH }} \
|
||||
go build -ldflags "${{ env.LDFLAGS }}" \
|
||||
-o _bin/kubectl-vela/${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}/kubectl-vela -v \
|
||||
./cmd/plugin/main.go
|
||||
- name: Compress
|
||||
run: |
|
||||
echo "\n## Release Info\nVERSION: ${{ env.VELA_VERSION }}" >> README.md && \
|
||||
echo "GIT_COMMIT: ${GITHUB_SHA}\n" >> README.md && \
|
||||
cd _bin/vela && \
|
||||
${{ env.DIST_DIRS }} cp ../../LICENSE {} \; && \
|
||||
${{ env.DIST_DIRS }} cp ../../README.md {} \; && \
|
||||
${{ env.DIST_DIRS }} tar -zcf vela-{}.tar.gz {} \; && \
|
||||
${{ env.DIST_DIRS }} zip -r vela-{}.zip {} \; && \
|
||||
cd ../kubectl-vela && \
|
||||
${{ env.DIST_DIRS }} cp ../../LICENSE {} \; && \
|
||||
${{ env.DIST_DIRS }} cp ../../README.md {} \; && \
|
||||
${{ env.DIST_DIRS }} tar -zcf kubectl-vela-{}.tar.gz {} \; && \
|
||||
${{ env.DIST_DIRS }} zip -r kubectl-vela-{}.zip {} \; && \
|
||||
cd .. && \
|
||||
sha256sum vela/vela-* kubectl-vela/kubectl-vela-* >> sha256-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.txt \
|
||||
- name: Upload Vela tar.gz
|
||||
uses: kubevela/vela-upload-release-asset@9b3858e67d3205e056d6220e5972abb32fc47289 # v1.0.0
|
||||
with:
|
||||
release_id: ${{ steps.get_release.outputs.id }}
|
||||
asset_path: ./_bin/vela/vela-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.tar.gz
|
||||
asset_name: vela-${{ env.VELA_VERSION }}-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.tar.gz
|
||||
- name: Upload Vela zip
|
||||
uses: kubevela/vela-upload-release-asset@9b3858e67d3205e056d6220e5972abb32fc47289 # v1.0.0
|
||||
with:
|
||||
release_id: ${{ steps.get_release.outputs.id }}
|
||||
asset_path: ./_bin/vela/vela-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.zip
|
||||
asset_name: vela-${{ env.VELA_VERSION }}-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.zip
|
||||
- name: Upload Kubectl-Vela tar.gz
|
||||
uses: kubevela/vela-upload-release-asset@9b3858e67d3205e056d6220e5972abb32fc47289 # v1.0.0
|
||||
with:
|
||||
release_id: ${{ steps.get_release.outputs.id }}
|
||||
asset_path: ./_bin/kubectl-vela/kubectl-vela-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.tar.gz
|
||||
asset_name: kubectl-vela-${{ env.VELA_VERSION }}-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.tar.gz
|
||||
- name: Upload Kubectl-Vela zip
|
||||
uses: kubevela/vela-upload-release-asset@9b3858e67d3205e056d6220e5972abb32fc47289 # v1.0.0
|
||||
with:
|
||||
release_id: ${{ steps.get_release.outputs.id }}
|
||||
asset_path: ./_bin/kubectl-vela/kubectl-vela-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.zip
|
||||
asset_name: kubectl-vela-${{ env.VELA_VERSION }}-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.zip
|
||||
- name: Post sha256
|
||||
uses: actions/upload-artifact@83fd05a356d7e2593de66fc9913b3002723633cb # v3.1.1
|
||||
with:
|
||||
name: sha256sums
|
||||
path: ./_bin/sha256-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.txt
|
||||
retention-days: 1
|
||||
- name: clear the asset
|
||||
run: |
|
||||
rm -rf ./_bin/vela/${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}
|
||||
mv ./_bin/vela/vela-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.tar.gz ./_bin/vela/vela-${{ env.VELA_VERSION }}-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.tar.gz
|
||||
mv ./_bin/vela/vela-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.zip ./_bin/vela/vela-${{ env.VELA_VERSION }}-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.zip
|
||||
- name: Install ossutil
|
||||
run: wget http://gosspublic.alicdn.com/ossutil/1.7.0/ossutil64 && chmod +x ossutil64 && mv ossutil64 ossutil
|
||||
- name: Configure Alibaba Cloud OSSUTIL
|
||||
run: ./ossutil --config-file .ossutilconfig config -i ${ACCESS_KEY} -k ${ACCESS_KEY_SECRET} -e ${ENDPOINT} -c .ossutilconfig
|
||||
run: ./ossutil --config-file .ossutilconfig config -i ${ACCESS_KEY} -k ${ACCESS_KEY_SECRET} -e ${ENDPOINT}
|
||||
- name: split files to be upload
|
||||
run: mkdir -p ./dist/files_upload && mv ./dist/*.tar.gz ./dist/files_upload && mv ./dist/*.zip ./dist/files_upload
|
||||
- name: sync local to cloud
|
||||
run: ./ossutil --config-file .ossutilconfig sync ./_bin/vela oss://$BUCKET/binary/vela/${{ env.VELA_VERSION }}
|
||||
run: ./ossutil --config-file .ossutilconfig sync ./dist/files_upload oss://$BUCKET/binary/vela/${{ env.VELA_VERSION }}
|
||||
- name: sync the latest version file
|
||||
if: ${{ !contains(env.VELA_VERSION,'alpha') && !contains(env.VELA_VERSION,'beta') }}
|
||||
run: |
|
||||
@@ -137,7 +67,6 @@ jobs:
|
||||
verlte ${{ env.VELA_VERSION }} $LATEST_VERSION && echo "${{ env.VELA_VERSION }} <= $LATEST_VERSION, skip update" && exit 0
|
||||
echo ${{ env.VELA_VERSION }} > ./latest_version
|
||||
./ossutil --config-file .ossutilconfig cp -u ./latest_version oss://$BUCKET/binary/vela/latest_version
|
||||
|
||||
upload-plugin-homebrew:
|
||||
permissions:
|
||||
contents: write
|
||||
@@ -154,34 +83,6 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b
|
||||
- name: Get release
|
||||
id: get_release
|
||||
uses: bruceadams/get-release@74c3d60f5a28f358ccf241a00c9021ea16f0569f # v1.3.2
|
||||
- name: Download sha256sums
|
||||
uses: actions/download-artifact@9782bd6a9848b53b110e712e20e42d89988822b7 # v3.0.1
|
||||
with:
|
||||
name: sha256sums
|
||||
path: cli-artifacts
|
||||
- name: Display structure of downloaded files
|
||||
run: ls -R
|
||||
working-directory: cli-artifacts
|
||||
- name: Get version
|
||||
run: echo "VELA_VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
|
||||
- shell: bash
|
||||
working-directory: cli-artifacts
|
||||
run: |
|
||||
for file in *
|
||||
do
|
||||
sed -i "s/\/vela/-${{ env.VELA_VERSION }}/g" ${file}
|
||||
sed -i "s/\/kubectl-vela/-${{ env.VELA_VERSION }}/g" ${file}
|
||||
cat ${file} >> sha256sums.txt
|
||||
done
|
||||
- name: Upload Checksums
|
||||
uses: kubevela/vela-upload-release-asset@9b3858e67d3205e056d6220e5972abb32fc47289 # v1.0.0
|
||||
with:
|
||||
release_id: ${{ steps.get_release.outputs.id }}
|
||||
asset_path: cli-artifacts/sha256sums.txt
|
||||
asset_name: sha256sums.txt
|
||||
- name: Update kubectl plugin version in krew-index
|
||||
uses: rajatjindal/krew-release-bot@3320c0b546b5d2320613c46762bd3f73e2801bdc # v0.0.38
|
||||
- name: Update Homebrew formula
|
||||
|
||||
2
.github/workflows/unit-test.yml
vendored
2
.github/workflows/unit-test.yml
vendored
@@ -61,6 +61,8 @@ jobs:
|
||||
|
||||
- name: Install ginkgo
|
||||
run: |
|
||||
sudo sed -i 's/azure\.//' /etc/apt/sources.list
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y golang-ginkgo-dev
|
||||
|
||||
- name: Setup K3d
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -53,3 +53,5 @@ git-page/
|
||||
# e2e rollout runtime image build
|
||||
runtime/rollout/e2e/tmp
|
||||
vela.json
|
||||
|
||||
dist/
|
||||
|
||||
76
.goreleaser.yaml
Normal file
76
.goreleaser.yaml
Normal file
@@ -0,0 +1,76 @@
|
||||
# This is an example .goreleaser.yml file with some sensible defaults.
|
||||
# Make sure to check the documentation at https://goreleaser.com
|
||||
builds:
|
||||
- id: vela-cli
|
||||
binary: vela
|
||||
goos:
|
||||
- linux
|
||||
- windows
|
||||
- darwin
|
||||
goarch:
|
||||
- amd64
|
||||
- arm64
|
||||
main: ./references/cmd/cli/main.go
|
||||
ldflags:
|
||||
- -s -w -X github.com/oam-dev/kubevela/version.VelaVersion={{ .Version }} -X github.com/oam-dev/kubevela/version.GitRevision=git-{{.ShortCommit}}
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
|
||||
- id: kubectl-vela
|
||||
binary: kubectl-vela
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
goos:
|
||||
- linux
|
||||
- windows
|
||||
- darwin
|
||||
goarch:
|
||||
- amd64
|
||||
- arm64
|
||||
main: ./cmd/plugin/main.go
|
||||
ldflags:
|
||||
- -s -w -X github.com/oam-dev/kubevela/version.VelaVersion={{ .Version }} -X github.com/oam-dev/kubevela/version.GitRevision=git-{{.ShortCommit}}
|
||||
|
||||
archives:
|
||||
- format: tar.gz
|
||||
id: vela-cli-tgz
|
||||
wrap_in_directory: '{{ .Os }}-{{ .Arch }}'
|
||||
builds:
|
||||
- vela-cli
|
||||
name_template: '{{ trimsuffix .ArtifactName ".exe" }}-{{ .Tag }}-{{ .Os }}-{{ .Arch }}'
|
||||
files: [ LICENSE, README.md ]
|
||||
- format: zip
|
||||
id: vela-cli-zip
|
||||
builds:
|
||||
- vela-cli
|
||||
wrap_in_directory: '{{ .Os }}-{{ .Arch }}'
|
||||
name_template: '{{ trimsuffix .ArtifactName ".exe" }}-{{ .Tag }}-{{ .Os }}-{{ .Arch }}'
|
||||
files: [ LICENSE, README.md ]
|
||||
- format: tar.gz
|
||||
id: plugin-tgz
|
||||
builds:
|
||||
- kubectl-vela
|
||||
wrap_in_directory: '{{ .Os }}-{{ .Arch }}'
|
||||
name_template: '{{ trimsuffix .ArtifactName ".exe" }}-{{ .Tag }}-{{ .Os }}-{{ .Arch }}'
|
||||
files: [ LICENSE, README.md ]
|
||||
- format: zip
|
||||
id: plugin-zip
|
||||
builds:
|
||||
- kubectl-vela
|
||||
wrap_in_directory: '{{ .Os }}-{{ .Arch }}'
|
||||
name_template: '{{ trimsuffix .ArtifactName ".exe" }}-{{ .Tag }}-{{ .Os }}-{{ .Arch }}'
|
||||
files: [ LICENSE, README.md ]
|
||||
|
||||
checksum:
|
||||
name_template: 'sha256sums.txt'
|
||||
changelog:
|
||||
sort: asc
|
||||
filters:
|
||||
exclude:
|
||||
- '^docs:'
|
||||
- '^test:'
|
||||
|
||||
# The lines beneath this are called `modelines`. See `:help modeline`
|
||||
# Feel free to remove those if you don't want/use them.
|
||||
# yaml-language-server: $schema=https://goreleaser.com/static/schema.json
|
||||
# vim: set ts=2 sw=2 tw=0 fo=cnqoj
|
||||
@@ -33,8 +33,8 @@ spec:
|
||||
arch: amd64
|
||||
{{addURIAndSha "https://github.com/oam-dev/kubevela/releases/download/{{ .TagName }}/kubectl-vela-{{ .TagName }}-windows-amd64.zip" .TagName }}
|
||||
files:
|
||||
- from: "*/kubectl-vela"
|
||||
to: "kubectl-vela.exe"
|
||||
- from: "*/kubectl-vela.exe"
|
||||
to: "."
|
||||
- from: "*/LICENSE"
|
||||
to: "."
|
||||
bin: "kubectl-vela.exe"
|
||||
|
||||
@@ -336,7 +336,8 @@ type WorkflowStatus struct {
|
||||
Steps []workflowv1alpha1.WorkflowStepStatus `json:"steps,omitempty"`
|
||||
|
||||
StartTime metav1.Time `json:"startTime,omitempty"`
|
||||
EndTime metav1.Time `json:"endTime,omitempty"`
|
||||
// +nullable
|
||||
EndTime metav1.Time `json:"endTime,omitempty"`
|
||||
}
|
||||
|
||||
// DefinitionType describes the type of DefinitionRevision.
|
||||
|
||||
@@ -99,6 +99,7 @@ helm install --create-namespace -n vela-system kubevela kubevela/vela-core --wai
|
||||
| `featureGates.multiStageComponentApply` | if enabled, the multiStageComponentApply feature will be combined with the stage field in TraitDefinition to complete the multi-stage apply. | `false` |
|
||||
| `featureGates.gzipApplicationRevision` | compress apprev using gzip (good) before being stored. This is reduces network throughput when dealing with huge apprevs. | `false` |
|
||||
| `featureGates.zstdApplicationRevision` | compress apprev using zstd (fast and good) before being stored. This is reduces network throughput when dealing with huge apprevs. Note that zstd will be prioritized if you enable other compression options. | `true` |
|
||||
| `featureGates.preDispatchDryRun` | enable dryrun before dispatching resources. Enable this flag can help prevent unsuccessful dispatch resources entering resourcetracker and improve the user experiences of gc but at the cost of increasing network requests. | `true` |
|
||||
|
||||
|
||||
### MultiCluster parameters
|
||||
@@ -110,7 +111,7 @@ helm install --create-namespace -n vela-system kubevela kubevela/vela-core --wai
|
||||
| `multicluster.clusterGateway.replicaCount` | ClusterGateway replica count | `1` |
|
||||
| `multicluster.clusterGateway.port` | ClusterGateway port | `9443` |
|
||||
| `multicluster.clusterGateway.image.repository` | ClusterGateway image repository | `oamdev/cluster-gateway` |
|
||||
| `multicluster.clusterGateway.image.tag` | ClusterGateway image tag | `v1.4.0` |
|
||||
| `multicluster.clusterGateway.image.tag` | ClusterGateway image tag | `v1.7.0` |
|
||||
| `multicluster.clusterGateway.image.pullPolicy` | ClusterGateway image pull policy | `IfNotPresent` |
|
||||
| `multicluster.clusterGateway.resources.limits.cpu` | ClusterGateway cpu limit | `100m` |
|
||||
| `multicluster.clusterGateway.resources.limits.memory` | ClusterGateway memory limit | `200Mi` |
|
||||
@@ -149,7 +150,7 @@ helm install --create-namespace -n vela-system kubevela kubevela/vela-core --wai
|
||||
| `kubeClient.qps` | The qps for reconcile clients, default is 100 | `100` |
|
||||
| `kubeClient.burst` | The burst for reconcile clients, default is 200 | `200` |
|
||||
| `authentication.enabled` | Enable authentication for application | `false` |
|
||||
| `authentication.withUser` | Application authentication will impersonate as the request User | `false` |
|
||||
| `authentication.withUser` | Application authentication will impersonate as the request User | `true` |
|
||||
| `authentication.defaultUser` | Application authentication will impersonate as the User if no user provided in Application | `kubevela:vela-core` |
|
||||
| `authentication.groupPattern` | Application authentication will impersonate as the request Group that matches the pattern | `kubevela:*` |
|
||||
|
||||
|
||||
@@ -848,6 +848,7 @@ spec:
|
||||
x-kubernetes-map-type: atomic
|
||||
endTime:
|
||||
format: date-time
|
||||
nullable: true
|
||||
type: string
|
||||
finished:
|
||||
type: boolean
|
||||
@@ -2806,6 +2807,7 @@ spec:
|
||||
x-kubernetes-map-type: atomic
|
||||
endTime:
|
||||
format: date-time
|
||||
nullable: true
|
||||
type: string
|
||||
finished:
|
||||
type: boolean
|
||||
@@ -4942,6 +4944,7 @@ spec:
|
||||
x-kubernetes-map-type: atomic
|
||||
endTime:
|
||||
format: date-time
|
||||
nullable: true
|
||||
type: string
|
||||
finished:
|
||||
type: boolean
|
||||
|
||||
@@ -774,6 +774,7 @@ spec:
|
||||
x-kubernetes-map-type: atomic
|
||||
endTime:
|
||||
format: date-time
|
||||
nullable: true
|
||||
type: string
|
||||
finished:
|
||||
type: boolean
|
||||
@@ -1535,6 +1536,7 @@ spec:
|
||||
x-kubernetes-map-type: atomic
|
||||
endTime:
|
||||
format: date-time
|
||||
nullable: true
|
||||
type: string
|
||||
finished:
|
||||
type: boolean
|
||||
|
||||
@@ -32,6 +32,7 @@ spec:
|
||||
- "--secure-port={{ .Values.multicluster.clusterGateway.port }}"
|
||||
- "--secret-namespace={{ .Release.Namespace }}"
|
||||
- "--feature-gates=APIPriorityAndFairness=false,ClientIdentityPenetration={{ .Values.authentication.enabled }}"
|
||||
- "--cluster-gateway-proxy-config=/etc/proxy-config/config.yaml"
|
||||
{{- if .Values.multicluster.clusterGateway.secureTLS.enabled }}
|
||||
- "--tls-cert-file={{ .Values.multicluster.clusterGateway.secureTLS.certPath }}/tls.crt"
|
||||
- "--tls-private-key-file={{ .Values.multicluster.clusterGateway.secureTLS.certPath }}/tls.key"
|
||||
@@ -42,14 +43,20 @@ spec:
|
||||
{{- toYaml .Values.multicluster.clusterGateway.resources | nindent 12 }}
|
||||
ports:
|
||||
- containerPort: {{ .Values.multicluster.clusterGateway.port }}
|
||||
{{ if .Values.multicluster.clusterGateway.secureTLS.enabled }}
|
||||
volumeMounts:
|
||||
- mountPath: /etc/proxy-config
|
||||
name: proxy-config
|
||||
{{ if .Values.multicluster.clusterGateway.secureTLS.enabled }}
|
||||
- mountPath: {{ .Values.multicluster.clusterGateway.secureTLS.certPath }}
|
||||
name: tls-cert-vol
|
||||
readOnly: true
|
||||
{{- end }}
|
||||
{{ if .Values.multicluster.clusterGateway.secureTLS.enabled }}
|
||||
volumes:
|
||||
- configMap:
|
||||
defaultMode: 420
|
||||
name: {{ .Release.Name }}-cluster-gateway-proxy-config
|
||||
name: proxy-config
|
||||
{{ if .Values.multicluster.clusterGateway.secureTLS.enabled }}
|
||||
- name: tls-cert-vol
|
||||
secret:
|
||||
defaultMode: 420
|
||||
@@ -74,6 +81,23 @@ spec:
|
||||
maxUnavailable: 1
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ .Release.Name }}-cluster-gateway-proxy-config
|
||||
namespace: {{ .Release.Namespace }}
|
||||
data:
|
||||
config.yaml: |
|
||||
apiVersion: cluster.core.oam.dev/v1alpha1
|
||||
kind: ClusterGatewayProxyConfiguration
|
||||
spec:
|
||||
clientIdentityExchanger:
|
||||
rules:
|
||||
- name: super-user
|
||||
source:
|
||||
group: kubevela:ux
|
||||
type: PrivilegedIdentityExchanger
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ .Release.Name }}-cluster-gateway-service
|
||||
|
||||
@@ -116,7 +116,7 @@ spec:
|
||||
#ECProvider: {
|
||||
type: "ec"
|
||||
apiKey: *"" | string
|
||||
name: "ec-provider" | string
|
||||
name: *"ec-provider" | string
|
||||
}
|
||||
#GCPProvider: {
|
||||
credentials: string
|
||||
|
||||
@@ -72,7 +72,7 @@ spec:
|
||||
}]
|
||||
}
|
||||
}
|
||||
parameter: *#PatchParams | close({
|
||||
parameter: #PatchParams | close({
|
||||
// +usage=Specify the container image for multiple containers
|
||||
containers: [...#PatchParams]
|
||||
})
|
||||
|
||||
@@ -53,7 +53,10 @@ spec:
|
||||
}
|
||||
if service.spec.type == "LoadBalancer" {
|
||||
status: service.status
|
||||
isHealth: status != _|_ && status.loadBalancer != _|_ && status.loadBalancer.ingress != _|_ && len(status.loadBalancer.ingress) > 0
|
||||
isHealth: *false | bool
|
||||
if status != _|_ if status.loadBalancer != _|_ if status.loadBalancer.ingress != _|_ if len(status.loadBalancer.ingress) > 0 if status.loadBalancer.ingress[0].ip != _|_ {
|
||||
isHealth: true
|
||||
}
|
||||
if !isHealth {
|
||||
message: "ExternalIP: Pending"
|
||||
}
|
||||
@@ -62,10 +65,15 @@ spec:
|
||||
}
|
||||
}
|
||||
healthPolicy: |-
|
||||
isHealth: *true | bool
|
||||
service: context.outputs.service
|
||||
if service.spec.type == "LoadBalancer" {
|
||||
status: service.status
|
||||
isHealth: status != _|_ && status.loadBalancer != _|_ && status.loadBalancer.ingress != _|_ && len(status.loadBalancer.ingress) > 0
|
||||
isHealth: *false | bool
|
||||
if status != _|_ if status.loadBalancer != _|_ if status.loadBalancer.ingress != _|_ if len(status.loadBalancer.ingress) > 0 if status.loadBalancer.ingress[0].ip != _|_ {
|
||||
isHealth: true
|
||||
}
|
||||
}
|
||||
if service.spec.type != "LoadBalancer" {
|
||||
isHealth: true
|
||||
}
|
||||
|
||||
|
||||
@@ -113,19 +113,20 @@ spec:
|
||||
}
|
||||
if context.outputs.ingress.status.loadBalancer.ingress != _|_ {
|
||||
let igs = context.outputs.ingress.status.loadBalancer.ingress
|
||||
let host = context.outputs.ingress.spec.rules[0].host
|
||||
if igs[0].ip != _|_ {
|
||||
if igs[0].host != _|_ {
|
||||
if host != _|_ {
|
||||
message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host + ", IP: " + igs[0].ip
|
||||
}
|
||||
if igs[0].host == _|_ {
|
||||
if host == _|_ {
|
||||
message: "Host not specified, visit the cluster or load balancer in front of the cluster with IP: " + igs[0].ip
|
||||
}
|
||||
}
|
||||
if igs[0].ip == _|_ {
|
||||
if igs[0].host != _|_ {
|
||||
if host != _|_ {
|
||||
message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host
|
||||
}
|
||||
if igs[0].host != _|_ {
|
||||
if host != _|_ {
|
||||
message: "Host not specified, visit the cluster or load balancer in front of the cluster"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
# Code generated by KubeVela templates. DO NOT EDIT. Please edit the original cue file.
|
||||
# Definition source cue file: vela-templates/definitions/internal/k8s-update-strategy.cue
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/alias: ""
|
||||
definition.oam.dev/description: Set k8s update strategy for Deployment/DaemonSet/StatefulSet
|
||||
name: k8s-update-strategy
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
- daemonsets.apps
|
||||
conflictsWith: []
|
||||
podDisruptive: false
|
||||
schematic:
|
||||
cue:
|
||||
template: |
|
||||
patch: spec: {
|
||||
if parameter.targetKind == "Deployment" && parameter.strategy.type != "OnDelete" {
|
||||
// +patchStrategy=retainKeys
|
||||
strategy: {
|
||||
type: parameter.strategy.type
|
||||
if parameter.strategy.type == "RollingUpdate" {
|
||||
rollingUpdate: {
|
||||
maxSurge: parameter.strategy.rollingStrategy.maxSurge
|
||||
maxUnavailable: parameter.strategy.rollingStrategy.maxUnavailable
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if parameter.targetKind == "StatefulSet" && parameter.strategy.type != "Recreate" {
|
||||
// +patchStrategy=retainKeys
|
||||
updateStrategy: {
|
||||
type: parameter.strategy.type
|
||||
if parameter.strategy.type == "RollingUpdate" {
|
||||
rollingUpdate: partition: parameter.strategy.rollingStrategy.partition
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if parameter.targetKind == "DaemonSet" && parameter.strategy.type != "Recreate" {
|
||||
// +patchStrategy=retainKeys
|
||||
updateStrategy: {
|
||||
type: parameter.strategy.type
|
||||
if parameter.strategy.type == "RollingUpdate" {
|
||||
rollingUpdate: {
|
||||
maxSurge: parameter.strategy.rollingStrategy.maxSurge
|
||||
maxUnavailable: parameter.strategy.rollingStrategy.maxUnavailable
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
parameter: {
|
||||
// +usage=Specify the apiVersion of target
|
||||
targetAPIVersion: *"apps/v1" | string
|
||||
// +usage=Specify the kind of target
|
||||
targetKind: *"Deployment" | "StatefulSet" | "DaemonSet"
|
||||
// +usage=Specify the strategy of update
|
||||
strategy: {
|
||||
// +usage=Specify the strategy type
|
||||
type: *"RollingUpdate" | "Recreate" | "OnDelete"
|
||||
// +usage=Specify the parameters of rollong update strategy
|
||||
rollingStrategy?: {
|
||||
maxSurge: *"25%" | string
|
||||
maxUnavailable: *"25%" | string
|
||||
partition: *0 | int
|
||||
}
|
||||
}
|
||||
}
|
||||
workloadRefPath: ""
|
||||
|
||||
@@ -56,44 +56,41 @@ spec:
|
||||
// +usage=Specify the message that you want to sent, refer to [dingtalk messaging](https://developers.dingtalk.com/document/robots/custom-robot-access/title-72m-8ag-pqw)
|
||||
message: {
|
||||
// +usage=Specify the message content of dingtalk notification
|
||||
text?: *null | close({
|
||||
text?: close({
|
||||
content: string
|
||||
})
|
||||
// +usage=msgType can be text, link, mardown, actionCard, feedCard
|
||||
msgtype: *"text" | "link" | "markdown" | "actionCard" | "feedCard"
|
||||
link?: *null | close({
|
||||
#link: {
|
||||
text?: string
|
||||
title?: string
|
||||
messageUrl?: string
|
||||
picUrl?: string
|
||||
})
|
||||
markdown?: *null | close({
|
||||
}
|
||||
|
||||
link?: #link
|
||||
markdown?: close({
|
||||
text: string
|
||||
title: string
|
||||
})
|
||||
at?: *null | close({
|
||||
atMobiles?: *null | [...string]
|
||||
isAtAll?: bool
|
||||
at?: close({
|
||||
atMobiles?: [...string]
|
||||
isAtAll?: bool
|
||||
})
|
||||
actionCard?: *null | close({
|
||||
actionCard?: close({
|
||||
text: string
|
||||
title: string
|
||||
hideAvatar: string
|
||||
btnOrientation: string
|
||||
singleTitle: string
|
||||
singleURL: string
|
||||
btns: *null | close([...*null | close({
|
||||
btns?: [...close({
|
||||
title: string
|
||||
actionURL: string
|
||||
})])
|
||||
})]
|
||||
})
|
||||
feedCard?: *null | close({
|
||||
links: *null | close([...*null | close({
|
||||
text?: string
|
||||
title?: string
|
||||
messageUrl?: string
|
||||
picUrl?: string
|
||||
})])
|
||||
feedCard?: close({
|
||||
links: [...#link]
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -114,11 +111,11 @@ spec:
|
||||
// +usage=Specify the message that you want to sent, refer to [slack messaging](https://api.slack.com/reference/messaging/payload)
|
||||
message: {
|
||||
// +usage=Specify the message text for slack notification
|
||||
text: string
|
||||
blocks?: *null | close([...block])
|
||||
attachments?: *null | close({
|
||||
blocks?: *null | close([...block])
|
||||
color?: string
|
||||
text: string
|
||||
blocks?: [...block]
|
||||
attachments?: close({
|
||||
blocks?: [...block]
|
||||
color?: string
|
||||
})
|
||||
thread_ts?: string
|
||||
// +usage=Specify the message text format in markdown for slack notification
|
||||
|
||||
@@ -13,7 +13,7 @@ spec:
|
||||
template: |
|
||||
#PolicyRule: {
|
||||
// +usage=Specify how to select the targets of the rule
|
||||
selector: [...#RuleSelector]
|
||||
selector: #RuleSelector
|
||||
}
|
||||
#RuleSelector: {
|
||||
// +usage=Select resources by component names
|
||||
|
||||
@@ -54,6 +54,12 @@ spec:
|
||||
emptyDir: medium: v.medium
|
||||
}
|
||||
},
|
||||
if parameter.hostPath != _|_ for v in parameter.hostPath {
|
||||
{
|
||||
name: "hostpath-" + v.name
|
||||
path: v.path
|
||||
}
|
||||
},
|
||||
]
|
||||
volumeMountsList: [
|
||||
if parameter.pvc != _|_ for v in parameter.pvc {
|
||||
@@ -94,6 +100,12 @@ spec:
|
||||
}
|
||||
}
|
||||
},
|
||||
if parameter.hostPath != _|_ for v in parameter.hostPath {
|
||||
{
|
||||
name: "hostpath-" + v.name
|
||||
mountPath: v.mountPath
|
||||
}
|
||||
},
|
||||
]
|
||||
envList: [
|
||||
if parameter.configMap != _|_ for v in parameter.configMap if v.mountToEnv != _|_ {
|
||||
@@ -311,7 +323,7 @@ spec:
|
||||
envName: string
|
||||
secretKey: string
|
||||
}]
|
||||
mountPath?: string
|
||||
mountPath: string
|
||||
subPath?: string
|
||||
defaultMode: *420 | int
|
||||
readOnly: *false | bool
|
||||
@@ -331,5 +343,13 @@ spec:
|
||||
subPath?: string
|
||||
medium: *"" | "Memory"
|
||||
}]
|
||||
|
||||
// +usage=Declare host path type storage
|
||||
hostPath?: [...{
|
||||
name: string
|
||||
path: string
|
||||
mountPath: string
|
||||
type: *"Directory" | "DirectoryOrCreate" | "FileOrCreate" | "File" | "Socket" | "CharDevice" | "BlockDevice"
|
||||
}]
|
||||
}
|
||||
|
||||
|
||||
@@ -19,18 +19,24 @@ spec:
|
||||
mountsArray: [
|
||||
if parameter.storage != _|_ && parameter.storage.secret != _|_ for v in parameter.storage.secret {
|
||||
{
|
||||
name: "secret-" + v.name
|
||||
mountPath: v.mountPath
|
||||
if v.subPath != _|_ {
|
||||
subPath: v.subPath
|
||||
}
|
||||
name: v.name
|
||||
}
|
||||
},
|
||||
if parameter.storage != _|_ && parameter.storage.hostPath != _|_ for v in parameter.storage.hostPath {
|
||||
{
|
||||
name: "hostpath-" + v.name
|
||||
mountPath: v.mountPath
|
||||
}
|
||||
},
|
||||
]
|
||||
volumesList: [
|
||||
if parameter.storage != _|_ && parameter.storage.secret != _|_ for v in parameter.storage.secret {
|
||||
{
|
||||
name: v.name
|
||||
name: "secret-" + v.name
|
||||
secret: {
|
||||
defaultMode: v.defaultMode
|
||||
secretName: v.secretName
|
||||
@@ -39,6 +45,12 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
if parameter.storage != _|_ && parameter.storage.hostPath != _|_ for v in parameter.storage.hostPath {
|
||||
{
|
||||
name: "hostpath-" + v.name
|
||||
path: v.path
|
||||
}
|
||||
}
|
||||
},
|
||||
]
|
||||
deDupVolumesArray: [
|
||||
@@ -125,6 +137,13 @@ spec:
|
||||
mode: *511 | int
|
||||
}]
|
||||
}]
|
||||
// +usage=Declare host path type storage
|
||||
hostPath?: [...{
|
||||
name: string
|
||||
path: string
|
||||
mountPath: string
|
||||
type: *"Directory" | "DirectoryOrCreate" | "FileOrCreate" | "File" | "Socket" | "CharDevice" | "BlockDevice"
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,21 +11,6 @@ metadata:
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
---
|
||||
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: {{ include "kubevela.fullname" . }}:manager-rolebinding
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: {{ if .Values.authentication.enabled }} {{ include "kubevela.fullname" . }}:manager {{ else }} "cluster-admin" {{ end }}
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ include "kubevela.serviceAccountName" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
|
||||
{{ if .Values.authentication.enabled }}
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
@@ -66,9 +51,41 @@ rules:
|
||||
- apiGroups: ["authorization.k8s.io"]
|
||||
resources: ["subjectaccessreviews"]
|
||||
verbs: ["*"]
|
||||
{{ end }}
|
||||
|
||||
---
|
||||
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: {{ include "kubevela.fullname" . }}:manager-authentication-rolebinding
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: {{ include "kubevela.fullname" . }}:manager
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ include "kubevela.serviceAccountName" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
|
||||
{{ else }}
|
||||
|
||||
---
|
||||
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: {{ include "kubevela.fullname" . }}:manager-rolebinding
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: "cluster-admin"
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ include "kubevela.serviceAccountName" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
|
||||
{{ end }}
|
||||
---
|
||||
# permissions to do leader election.
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
@@ -255,8 +272,9 @@ spec:
|
||||
- "--feature-gates=ZstdResourceTracker={{- .Values.featureGates.zstdResourceTracker | toString -}}"
|
||||
- "--feature-gates=ApplyOnce={{- .Values.featureGates.applyOnce | toString -}}"
|
||||
- "--feature-gates=MultiStageComponentApply= {{- .Values.featureGates.multiStageComponentApply | toString -}}"
|
||||
- "--feature-gates=GzipApplicationRevision={{- .Values.featureGates.gzipResourceTracker | toString -}}"
|
||||
- "--feature-gates=ZstdApplicationRevision={{- .Values.featureGates.zstdResourceTracker | toString -}}"
|
||||
- "--feature-gates=GzipApplicationRevision={{- .Values.featureGates.gzipApplicationRevision | toString -}}"
|
||||
- "--feature-gates=ZstdApplicationRevision={{- .Values.featureGates.zstdApplicationRevision | toString -}}"
|
||||
- "--feature-gates=PreDispatchDryRun={{- .Values.featureGates.preDispatchDryRun | toString -}}"
|
||||
{{ if .Values.authentication.enabled }}
|
||||
{{ if .Values.authentication.withUser }}
|
||||
- "--authentication-with-user"
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
{{- if not (lookup "v1" "ConfigMap" (include "systemDefinitionNamespace" .) "component-pod-view") }}
|
||||
apiVersion: v1
|
||||
data:
|
||||
template: |
|
||||
import (
|
||||
"vela/ql"
|
||||
"vela/ql"
|
||||
)
|
||||
|
||||
parameter: {
|
||||
@@ -56,9 +55,15 @@ data:
|
||||
phase: pod.object.status.phase
|
||||
// refer to https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase
|
||||
if phase != "Pending" && phase != "Unknown" {
|
||||
podIP: pod.object.status.podIP
|
||||
hostIP: pod.object.status.hostIP
|
||||
nodeName: pod.object.spec.nodeName
|
||||
if pod.object.podIP != _|_ {
|
||||
podIP: pod.object.status.podIP
|
||||
}
|
||||
if pod.object.hostIP != _|_ {
|
||||
hostIP: pod.object.status.hostIP
|
||||
}
|
||||
if pod.object.nodeName != _|_ {
|
||||
nodeName: pod.object.spec.nodeName
|
||||
}
|
||||
}
|
||||
}
|
||||
}]
|
||||
@@ -74,4 +79,3 @@ kind: ConfigMap
|
||||
metadata:
|
||||
name: component-pod-view
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
{{- end }}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
{{- if not (lookup "v1" "ConfigMap" (include "systemDefinitionNamespace" .) "component-service-view") }}
|
||||
apiVersion: v1
|
||||
data:
|
||||
template: |
|
||||
@@ -47,4 +46,3 @@ kind: ConfigMap
|
||||
metadata:
|
||||
name: component-service-view
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
{{- end}}
|
||||
@@ -113,6 +113,7 @@ optimize:
|
||||
##@param featureGates.multiStageComponentApply if enabled, the multiStageComponentApply feature will be combined with the stage field in TraitDefinition to complete the multi-stage apply.
|
||||
##@param featureGates.gzipApplicationRevision compress apprev using gzip (good) before being stored. This is reduces network throughput when dealing with huge apprevs.
|
||||
##@param featureGates.zstdApplicationRevision compress apprev using zstd (fast and good) before being stored. This is reduces network throughput when dealing with huge apprevs. Note that zstd will be prioritized if you enable other compression options.
|
||||
##@param featureGates.preDispatchDryRun enable dryrun before dispatching resources. Enable this flag can help prevent unsuccessful dispatch resources entering resourcetracker and improve the user experiences of gc but at the cost of increasing network requests.
|
||||
##@param
|
||||
featureGates:
|
||||
enableLegacyComponentRevision: false
|
||||
@@ -122,6 +123,7 @@ featureGates:
|
||||
multiStageComponentApply: false
|
||||
gzipApplicationRevision: false
|
||||
zstdApplicationRevision: true
|
||||
preDispatchDryRun: true
|
||||
|
||||
## @section MultiCluster parameters
|
||||
|
||||
@@ -146,7 +148,7 @@ multicluster:
|
||||
port: 9443
|
||||
image:
|
||||
repository: oamdev/cluster-gateway
|
||||
tag: v1.4.0
|
||||
tag: v1.7.0
|
||||
pullPolicy: IfNotPresent
|
||||
resources:
|
||||
limits:
|
||||
@@ -263,6 +265,6 @@ kubeClient:
|
||||
## @param authentication.groupPattern Application authentication will impersonate as the request Group that matches the pattern
|
||||
authentication:
|
||||
enabled: false
|
||||
withUser: false
|
||||
withUser: true
|
||||
defaultUser: kubevela:vela-core
|
||||
groupPattern: kubevela:*
|
||||
|
||||
@@ -65,7 +65,6 @@ helm install --create-namespace -n vela-system kubevela kubevela/vela-minimal --
|
||||
| `controllerArgs.reSyncPeriod` | The period for resync the applications | `5m` |
|
||||
| `OAMSpecVer` | OAMSpecVer is the oam spec version controller want to setup | `minimal` |
|
||||
| `disableCaps` | Disable capability | `envbinding,rollout` |
|
||||
| `applyOnceOnly` | Valid applyOnceOnly values: true/false/on/off/force | `off` |
|
||||
| `dependCheckWait` | dependCheckWait is the time to wait for ApplicationConfiguration's dependent-resource ready | `30s` |
|
||||
|
||||
|
||||
@@ -97,20 +96,29 @@ helm install --create-namespace -n vela-system kubevela kubevela/vela-minimal --
|
||||
| `healthCheck.port` | KubeVela health check port | `9440` |
|
||||
|
||||
|
||||
### KubeVela controller optimization parameters
|
||||
|
||||
| Name | Description | Value |
|
||||
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- | ------- |
|
||||
| `featureGates.applyOnce` | if enabled, the apply-once feature will be applied to all applications, no state-keep and no resource data storage in ResourceTracker | `false` |
|
||||
|
||||
|
||||
### MultiCluster parameters
|
||||
|
||||
| Name | Description | Value |
|
||||
| ----------------------------------------------------- | -------------------------------- | -------------------------------- |
|
||||
| `multicluster.enabled` | Whether to enable multi-cluster | `true` |
|
||||
| `multicluster.clusterGateway.replicaCount` | ClusterGateway replica count | `1` |
|
||||
| `multicluster.clusterGateway.port` | ClusterGateway port | `9443` |
|
||||
| `multicluster.clusterGateway.image.repository` | ClusterGateway image repository | `oamdev/cluster-gateway` |
|
||||
| `multicluster.clusterGateway.image.tag` | ClusterGateway image tag | `v1.4.0` |
|
||||
| `multicluster.clusterGateway.image.pullPolicy` | ClusterGateway image pull policy | `IfNotPresent` |
|
||||
| `multicluster.clusterGateway.resources.limits.cpu` | ClusterGateway cpu limit | `100m` |
|
||||
| `multicluster.clusterGateway.resources.limits.memory` | ClusterGateway memory limit | `200Mi` |
|
||||
| `multicluster.clusterGateway.secureTLS.enabled` | Whether to enable secure TLS | `true` |
|
||||
| `multicluster.clusterGateway.secureTLS.certPath` | Path to the certificate file | `/etc/k8s-cluster-gateway-certs` |
|
||||
| Name | Description | Value |
|
||||
| ------------------------------------------------------- | -------------------------------- | -------------------------------- |
|
||||
| `multicluster.enabled` | Whether to enable multi-cluster | `true` |
|
||||
| `multicluster.clusterGateway.replicaCount` | ClusterGateway replica count | `1` |
|
||||
| `multicluster.clusterGateway.port` | ClusterGateway port | `9443` |
|
||||
| `multicluster.clusterGateway.image.repository` | ClusterGateway image repository | `oamdev/cluster-gateway` |
|
||||
| `multicluster.clusterGateway.image.tag` | ClusterGateway image tag | `v1.8.0-alpha.3` |
|
||||
| `multicluster.clusterGateway.image.pullPolicy` | ClusterGateway image pull policy | `IfNotPresent` |
|
||||
| `multicluster.clusterGateway.resources.requests.cpu` | ClusterGateway cpu request | `50m` |
|
||||
| `multicluster.clusterGateway.resources.requests.memory` | ClusterGateway memory request | `20Mi` |
|
||||
| `multicluster.clusterGateway.resources.limits.cpu` | ClusterGateway cpu limit | `500m` |
|
||||
| `multicluster.clusterGateway.resources.limits.memory` | ClusterGateway memory limit | `200Mi` |
|
||||
| `multicluster.clusterGateway.secureTLS.enabled` | Whether to enable secure TLS | `true` |
|
||||
| `multicluster.clusterGateway.secureTLS.certPath` | Path to the certificate file | `/etc/k8s-cluster-gateway-certs` |
|
||||
|
||||
|
||||
### Test parameters
|
||||
|
||||
@@ -848,6 +848,7 @@ spec:
|
||||
x-kubernetes-map-type: atomic
|
||||
endTime:
|
||||
format: date-time
|
||||
nullable: true
|
||||
type: string
|
||||
finished:
|
||||
type: boolean
|
||||
@@ -2806,6 +2807,7 @@ spec:
|
||||
x-kubernetes-map-type: atomic
|
||||
endTime:
|
||||
format: date-time
|
||||
nullable: true
|
||||
type: string
|
||||
finished:
|
||||
type: boolean
|
||||
@@ -4942,6 +4944,7 @@ spec:
|
||||
x-kubernetes-map-type: atomic
|
||||
endTime:
|
||||
format: date-time
|
||||
nullable: true
|
||||
type: string
|
||||
finished:
|
||||
type: boolean
|
||||
|
||||
@@ -774,6 +774,7 @@ spec:
|
||||
x-kubernetes-map-type: atomic
|
||||
endTime:
|
||||
format: date-time
|
||||
nullable: true
|
||||
type: string
|
||||
finished:
|
||||
type: boolean
|
||||
@@ -1535,6 +1536,7 @@ spec:
|
||||
x-kubernetes-map-type: atomic
|
||||
endTime:
|
||||
format: date-time
|
||||
nullable: true
|
||||
type: string
|
||||
finished:
|
||||
type: boolean
|
||||
|
||||
@@ -116,7 +116,7 @@ spec:
|
||||
#ECProvider: {
|
||||
type: "ec"
|
||||
apiKey: *"" | string
|
||||
name: "ec-provider" | string
|
||||
name: *"ec-provider" | string
|
||||
}
|
||||
#GCPProvider: {
|
||||
credentials: string
|
||||
|
||||
@@ -72,7 +72,7 @@ spec:
|
||||
}]
|
||||
}
|
||||
}
|
||||
parameter: *#PatchParams | close({
|
||||
parameter: #PatchParams | close({
|
||||
// +usage=Specify the container image for multiple containers
|
||||
containers: [...#PatchParams]
|
||||
})
|
||||
|
||||
@@ -53,7 +53,10 @@ spec:
|
||||
}
|
||||
if service.spec.type == "LoadBalancer" {
|
||||
status: service.status
|
||||
isHealth: status != _|_ && status.loadBalancer != _|_ && status.loadBalancer.ingress != _|_ && len(status.loadBalancer.ingress) > 0
|
||||
isHealth: *false | bool
|
||||
if status != _|_ if status.loadBalancer != _|_ if status.loadBalancer.ingress != _|_ if len(status.loadBalancer.ingress) > 0 if status.loadBalancer.ingress[0].ip != _|_ {
|
||||
isHealth: true
|
||||
}
|
||||
if !isHealth {
|
||||
message: "ExternalIP: Pending"
|
||||
}
|
||||
@@ -62,10 +65,15 @@ spec:
|
||||
}
|
||||
}
|
||||
healthPolicy: |-
|
||||
isHealth: *true | bool
|
||||
service: context.outputs.service
|
||||
if service.spec.type == "LoadBalancer" {
|
||||
status: service.status
|
||||
isHealth: status != _|_ && status.loadBalancer != _|_ && status.loadBalancer.ingress != _|_ && len(status.loadBalancer.ingress) > 0
|
||||
isHealth: *false | bool
|
||||
if status != _|_ if status.loadBalancer != _|_ if status.loadBalancer.ingress != _|_ if len(status.loadBalancer.ingress) > 0 if status.loadBalancer.ingress[0].ip != _|_ {
|
||||
isHealth: true
|
||||
}
|
||||
}
|
||||
if service.spec.type != "LoadBalancer" {
|
||||
isHealth: true
|
||||
}
|
||||
|
||||
|
||||
@@ -113,19 +113,20 @@ spec:
|
||||
}
|
||||
if context.outputs.ingress.status.loadBalancer.ingress != _|_ {
|
||||
let igs = context.outputs.ingress.status.loadBalancer.ingress
|
||||
let host = context.outputs.ingress.spec.rules[0].host
|
||||
if igs[0].ip != _|_ {
|
||||
if igs[0].host != _|_ {
|
||||
if host != _|_ {
|
||||
message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host + ", IP: " + igs[0].ip
|
||||
}
|
||||
if igs[0].host == _|_ {
|
||||
if host == _|_ {
|
||||
message: "Host not specified, visit the cluster or load balancer in front of the cluster with IP: " + igs[0].ip
|
||||
}
|
||||
}
|
||||
if igs[0].ip == _|_ {
|
||||
if igs[0].host != _|_ {
|
||||
if host != _|_ {
|
||||
message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host
|
||||
}
|
||||
if igs[0].host != _|_ {
|
||||
if host != _|_ {
|
||||
message: "Host not specified, visit the cluster or load balancer in front of the cluster"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
# Code generated by KubeVela templates. DO NOT EDIT. Please edit the original cue file.
|
||||
# Definition source cue file: vela-templates/definitions/internal/k8s-update-strategy.cue
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/alias: ""
|
||||
definition.oam.dev/description: Set k8s update strategy for Deployment/DaemonSet/StatefulSet
|
||||
name: k8s-update-strategy
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
- daemonsets.apps
|
||||
conflictsWith: []
|
||||
podDisruptive: false
|
||||
schematic:
|
||||
cue:
|
||||
template: |
|
||||
patch: spec: {
|
||||
if parameter.targetKind == "Deployment" && parameter.strategy.type != "OnDelete" {
|
||||
// +patchStrategy=retainKeys
|
||||
strategy: {
|
||||
type: parameter.strategy.type
|
||||
if parameter.strategy.type == "RollingUpdate" {
|
||||
rollingUpdate: {
|
||||
maxSurge: parameter.strategy.rollingStrategy.maxSurge
|
||||
maxUnavailable: parameter.strategy.rollingStrategy.maxUnavailable
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if parameter.targetKind == "StatefulSet" && parameter.strategy.type != "Recreate" {
|
||||
// +patchStrategy=retainKeys
|
||||
updateStrategy: {
|
||||
type: parameter.strategy.type
|
||||
if parameter.strategy.type == "RollingUpdate" {
|
||||
rollingUpdate: partition: parameter.strategy.rollingStrategy.partition
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if parameter.targetKind == "DaemonSet" && parameter.strategy.type != "Recreate" {
|
||||
// +patchStrategy=retainKeys
|
||||
updateStrategy: {
|
||||
type: parameter.strategy.type
|
||||
if parameter.strategy.type == "RollingUpdate" {
|
||||
rollingUpdate: {
|
||||
maxSurge: parameter.strategy.rollingStrategy.maxSurge
|
||||
maxUnavailable: parameter.strategy.rollingStrategy.maxUnavailable
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
parameter: {
|
||||
// +usage=Specify the apiVersion of target
|
||||
targetAPIVersion: *"apps/v1" | string
|
||||
// +usage=Specify the kind of target
|
||||
targetKind: *"Deployment" | "StatefulSet" | "DaemonSet"
|
||||
// +usage=Specify the strategy of update
|
||||
strategy: {
|
||||
// +usage=Specify the strategy type
|
||||
type: *"RollingUpdate" | "Recreate" | "OnDelete"
|
||||
// +usage=Specify the parameters of rollong update strategy
|
||||
rollingStrategy?: {
|
||||
maxSurge: *"25%" | string
|
||||
maxUnavailable: *"25%" | string
|
||||
partition: *0 | int
|
||||
}
|
||||
}
|
||||
}
|
||||
workloadRefPath: ""
|
||||
|
||||
@@ -56,44 +56,41 @@ spec:
|
||||
// +usage=Specify the message that you want to sent, refer to [dingtalk messaging](https://developers.dingtalk.com/document/robots/custom-robot-access/title-72m-8ag-pqw)
|
||||
message: {
|
||||
// +usage=Specify the message content of dingtalk notification
|
||||
text?: *null | close({
|
||||
text?: close({
|
||||
content: string
|
||||
})
|
||||
// +usage=msgType can be text, link, mardown, actionCard, feedCard
|
||||
msgtype: *"text" | "link" | "markdown" | "actionCard" | "feedCard"
|
||||
link?: *null | close({
|
||||
#link: {
|
||||
text?: string
|
||||
title?: string
|
||||
messageUrl?: string
|
||||
picUrl?: string
|
||||
})
|
||||
markdown?: *null | close({
|
||||
}
|
||||
|
||||
link?: #link
|
||||
markdown?: close({
|
||||
text: string
|
||||
title: string
|
||||
})
|
||||
at?: *null | close({
|
||||
atMobiles?: *null | [...string]
|
||||
isAtAll?: bool
|
||||
at?: close({
|
||||
atMobiles?: [...string]
|
||||
isAtAll?: bool
|
||||
})
|
||||
actionCard?: *null | close({
|
||||
actionCard?: close({
|
||||
text: string
|
||||
title: string
|
||||
hideAvatar: string
|
||||
btnOrientation: string
|
||||
singleTitle: string
|
||||
singleURL: string
|
||||
btns: *null | close([...*null | close({
|
||||
btns?: [...close({
|
||||
title: string
|
||||
actionURL: string
|
||||
})])
|
||||
})]
|
||||
})
|
||||
feedCard?: *null | close({
|
||||
links: *null | close([...*null | close({
|
||||
text?: string
|
||||
title?: string
|
||||
messageUrl?: string
|
||||
picUrl?: string
|
||||
})])
|
||||
feedCard?: close({
|
||||
links: [...#link]
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -114,11 +111,11 @@ spec:
|
||||
// +usage=Specify the message that you want to sent, refer to [slack messaging](https://api.slack.com/reference/messaging/payload)
|
||||
message: {
|
||||
// +usage=Specify the message text for slack notification
|
||||
text: string
|
||||
blocks?: *null | close([...block])
|
||||
attachments?: *null | close({
|
||||
blocks?: *null | close([...block])
|
||||
color?: string
|
||||
text: string
|
||||
blocks?: [...block]
|
||||
attachments?: close({
|
||||
blocks?: [...block]
|
||||
color?: string
|
||||
})
|
||||
thread_ts?: string
|
||||
// +usage=Specify the message text format in markdown for slack notification
|
||||
|
||||
@@ -13,7 +13,7 @@ spec:
|
||||
template: |
|
||||
#PolicyRule: {
|
||||
// +usage=Specify how to select the targets of the rule
|
||||
selector: [...#RuleSelector]
|
||||
selector: #RuleSelector
|
||||
}
|
||||
#RuleSelector: {
|
||||
// +usage=Select resources by component names
|
||||
|
||||
@@ -54,6 +54,12 @@ spec:
|
||||
emptyDir: medium: v.medium
|
||||
}
|
||||
},
|
||||
if parameter.hostPath != _|_ for v in parameter.hostPath {
|
||||
{
|
||||
name: "hostpath-" + v.name
|
||||
path: v.path
|
||||
}
|
||||
},
|
||||
]
|
||||
volumeMountsList: [
|
||||
if parameter.pvc != _|_ for v in parameter.pvc {
|
||||
@@ -94,6 +100,12 @@ spec:
|
||||
}
|
||||
}
|
||||
},
|
||||
if parameter.hostPath != _|_ for v in parameter.hostPath {
|
||||
{
|
||||
name: "hostpath-" + v.name
|
||||
mountPath: v.mountPath
|
||||
}
|
||||
},
|
||||
]
|
||||
envList: [
|
||||
if parameter.configMap != _|_ for v in parameter.configMap if v.mountToEnv != _|_ {
|
||||
@@ -311,7 +323,7 @@ spec:
|
||||
envName: string
|
||||
secretKey: string
|
||||
}]
|
||||
mountPath?: string
|
||||
mountPath: string
|
||||
subPath?: string
|
||||
defaultMode: *420 | int
|
||||
readOnly: *false | bool
|
||||
@@ -331,5 +343,13 @@ spec:
|
||||
subPath?: string
|
||||
medium: *"" | "Memory"
|
||||
}]
|
||||
|
||||
// +usage=Declare host path type storage
|
||||
hostPath?: [...{
|
||||
name: string
|
||||
path: string
|
||||
mountPath: string
|
||||
type: *"Directory" | "DirectoryOrCreate" | "FileOrCreate" | "File" | "Socket" | "CharDevice" | "BlockDevice"
|
||||
}]
|
||||
}
|
||||
|
||||
|
||||
@@ -19,18 +19,24 @@ spec:
|
||||
mountsArray: [
|
||||
if parameter.storage != _|_ && parameter.storage.secret != _|_ for v in parameter.storage.secret {
|
||||
{
|
||||
name: "secret-" + v.name
|
||||
mountPath: v.mountPath
|
||||
if v.subPath != _|_ {
|
||||
subPath: v.subPath
|
||||
}
|
||||
name: v.name
|
||||
}
|
||||
},
|
||||
if parameter.storage != _|_ && parameter.storage.hostPath != _|_ for v in parameter.storage.hostPath {
|
||||
{
|
||||
name: "hostpath-" + v.name
|
||||
mountPath: v.mountPath
|
||||
}
|
||||
},
|
||||
]
|
||||
volumesList: [
|
||||
if parameter.storage != _|_ && parameter.storage.secret != _|_ for v in parameter.storage.secret {
|
||||
{
|
||||
name: v.name
|
||||
name: "secret-" + v.name
|
||||
secret: {
|
||||
defaultMode: v.defaultMode
|
||||
secretName: v.secretName
|
||||
@@ -39,6 +45,12 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
if parameter.storage != _|_ && parameter.storage.hostPath != _|_ for v in parameter.storage.hostPath {
|
||||
{
|
||||
name: "hostpath-" + v.name
|
||||
path: v.path
|
||||
}
|
||||
}
|
||||
},
|
||||
]
|
||||
deDupVolumesArray: [
|
||||
@@ -125,6 +137,13 @@ spec:
|
||||
mode: *511 | int
|
||||
}]
|
||||
}]
|
||||
// +usage=Declare host path type storage
|
||||
hostPath?: [...{
|
||||
name: string
|
||||
path: string
|
||||
mountPath: string
|
||||
type: *"Directory" | "DirectoryOrCreate" | "FileOrCreate" | "File" | "Socket" | "CharDevice" | "BlockDevice"
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -166,10 +166,8 @@ spec:
|
||||
- "--use-webhook=true"
|
||||
- "--webhook-port={{ .Values.webhookService.port }}"
|
||||
- "--webhook-cert-dir={{ .Values.admissionWebhooks.certificate.mountPath }}"
|
||||
- "--autogen-workload-definition={{ .Values.admissionWebhooks.autoGenWorkloadDefinition }}"
|
||||
{{ end }}
|
||||
- "--health-addr=:{{ .Values.healthCheck.port }}"
|
||||
- "--apply-once-only={{ .Values.applyOnceOnly }}"
|
||||
{{ if ne .Values.disableCaps "" }}
|
||||
- "--disable-caps={{ .Values.disableCaps }}"
|
||||
{{ end }}
|
||||
@@ -188,6 +186,7 @@ spec:
|
||||
- "--max-workflow-step-error-retry-times={{ .Values.workflow.step.errorRetryTimes }}"
|
||||
- "--feature-gates=EnableSuspendOnFailure={{- .Values.workflow.enableSuspendOnFailure | toString -}}"
|
||||
- "--feature-gates=AuthenticateApplication={{- .Values.authentication.enabled | toString -}}"
|
||||
- "--feature-gates=ApplyOnce={{- .Values.featureGates.applyOnce | toString -}}"
|
||||
{{ if .Values.authentication.enabled }}
|
||||
{{ if .Values.authentication.withUser }}
|
||||
- "--authentication-with-user"
|
||||
|
||||
@@ -26,9 +26,6 @@ OAMSpecVer: "minimal"
|
||||
## @param disableCaps Disable capability
|
||||
disableCaps: "envbinding,rollout"
|
||||
|
||||
## @param applyOnceOnly Valid applyOnceOnly values: true/false/on/off/force
|
||||
applyOnceOnly: "off"
|
||||
|
||||
## @param dependCheckWait dependCheckWait is the time to wait for ApplicationConfiguration's dependent-resource ready
|
||||
dependCheckWait: 30s
|
||||
|
||||
@@ -86,6 +83,11 @@ webhookService:
|
||||
healthCheck:
|
||||
port: 9440
|
||||
|
||||
## @section KubeVela controller optimization parameters
|
||||
|
||||
##@param featureGates.applyOnce if enabled, the apply-once feature will be applied to all applications, no state-keep and no resource data storage in ResourceTracker
|
||||
featureGates:
|
||||
applyOnce: false
|
||||
|
||||
## @section MultiCluster parameters
|
||||
|
||||
@@ -95,6 +97,8 @@ healthCheck:
|
||||
## @param multicluster.clusterGateway.image.repository ClusterGateway image repository
|
||||
## @param multicluster.clusterGateway.image.tag ClusterGateway image tag
|
||||
## @param multicluster.clusterGateway.image.pullPolicy ClusterGateway image pull policy
|
||||
## @param multicluster.clusterGateway.resources.requests.cpu ClusterGateway cpu request
|
||||
## @param multicluster.clusterGateway.resources.requests.memory ClusterGateway memory request
|
||||
## @param multicluster.clusterGateway.resources.limits.cpu ClusterGateway cpu limit
|
||||
## @param multicluster.clusterGateway.resources.limits.memory ClusterGateway memory limit
|
||||
## @param multicluster.clusterGateway.secureTLS.enabled Whether to enable secure TLS
|
||||
@@ -106,11 +110,14 @@ multicluster:
|
||||
port: 9443
|
||||
image:
|
||||
repository: oamdev/cluster-gateway
|
||||
tag: v1.4.0
|
||||
tag: v1.8.0-alpha.3
|
||||
pullPolicy: IfNotPresent
|
||||
resources:
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 20Mi
|
||||
limits:
|
||||
cpu: 100m
|
||||
cpu: 500m
|
||||
memory: 200Mi
|
||||
secureTLS:
|
||||
enabled: true
|
||||
|
||||
@@ -17,10 +17,13 @@ limitations under the License.
|
||||
package options
|
||||
|
||||
import (
|
||||
"k8s.io/apiserver/pkg/util/feature"
|
||||
"flag"
|
||||
|
||||
cliflag "k8s.io/component-base/cli/flag"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/config"
|
||||
"github.com/oam-dev/kubevela/pkg/features"
|
||||
)
|
||||
|
||||
// ServerRunOptions contains everything necessary to create and run api server
|
||||
@@ -40,6 +43,9 @@ func NewServerRunOptions() *ServerRunOptions {
|
||||
func (s *ServerRunOptions) Flags() (fss cliflag.NamedFlagSets) {
|
||||
fs := fss.FlagSet("generic")
|
||||
s.GenericServerRunOptions.AddFlags(fs, s.GenericServerRunOptions)
|
||||
feature.DefaultMutableFeatureGate.AddFlag(fss.FlagSet("featuregate"))
|
||||
features.APIServerMutableFeatureGate.AddFlag(fss.FlagSet("featuregate"))
|
||||
local := flag.NewFlagSet("klog", flag.ExitOnError)
|
||||
klog.InitFlags(local)
|
||||
fs.AddGoFlagSet(local)
|
||||
return fss
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/kubevela/pkg/util/compression"
|
||||
"github.com/kubevela/pkg/util/k8s"
|
||||
"github.com/kubevela/pkg/util/singleton"
|
||||
"k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/klog/v2"
|
||||
@@ -55,7 +56,7 @@ func (in *SystemCRDValidationHook) Run(ctx context.Context) error {
|
||||
feature.DefaultMutableFeatureGate.Enabled(features.GzipApplicationRevision) {
|
||||
appRev := &v1beta1.ApplicationRevision{}
|
||||
appRev.Name = fmt.Sprintf("core.pre-check.%d", time.Now().UnixNano())
|
||||
appRev.Namespace = types.DefaultKubeVelaNS
|
||||
appRev.Namespace = k8s.GetRuntimeNamespace()
|
||||
key := client.ObjectKeyFromObject(appRev)
|
||||
appRev.SetLabels(map[string]string{oam.LabelPreCheck: types.VelaCoreName})
|
||||
appRev.Spec.Application.Name = appRev.Name
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
pkgclient "github.com/kubevela/pkg/controller/client"
|
||||
ctrlrec "github.com/kubevela/pkg/controller/reconciler"
|
||||
pkgmulticluster "github.com/kubevela/pkg/multicluster"
|
||||
wfTypes "github.com/kubevela/workflow/pkg/types"
|
||||
@@ -171,6 +172,7 @@ func (s *CoreOptions) Flags() cliflag.NamedFlagSets {
|
||||
local := flag.NewFlagSet("klog", flag.ExitOnError)
|
||||
klog.InitFlags(local)
|
||||
kfs.AddGoFlagSet(local)
|
||||
pkgclient.AddTimeoutControllerClientFlags(fss.FlagSet("controllerclient"))
|
||||
|
||||
if s.LogDebug {
|
||||
_ = kfs.Set("v", strconv.Itoa(int(commonconfig.LogDebug)))
|
||||
|
||||
@@ -1938,6 +1938,53 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/applications/{appName}/revisions/{revision}/rollback": {
|
||||
"post": {
|
||||
"consumes": [
|
||||
"application/xml",
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json",
|
||||
"application/xml"
|
||||
],
|
||||
"tags": [
|
||||
"application"
|
||||
],
|
||||
"summary": "detail revision for application",
|
||||
"operationId": "rollbackApplicationWithRevision",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "identifier of the application",
|
||||
"name": "appName",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "identifier of the application revision",
|
||||
"name": "revision",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/v1.ApplicationRollbackResponse"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/bcode.Bcode"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/applications/{appName}/statistics": {
|
||||
"get": {
|
||||
"consumes": [
|
||||
@@ -2039,7 +2086,7 @@
|
||||
"tags": [
|
||||
"application"
|
||||
],
|
||||
"summary": "list application triggers",
|
||||
"summary": "List the application triggers",
|
||||
"operationId": "listApplicationTriggers",
|
||||
"parameters": [
|
||||
{
|
||||
@@ -2077,7 +2124,7 @@
|
||||
"tags": [
|
||||
"application"
|
||||
],
|
||||
"summary": "create one application trigger",
|
||||
"summary": "Create an application trigger",
|
||||
"operationId": "createApplicationTrigger",
|
||||
"parameters": [
|
||||
{
|
||||
@@ -2113,6 +2160,51 @@
|
||||
}
|
||||
},
|
||||
"/api/v1/applications/{appName}/triggers/{token}": {
|
||||
"put": {
|
||||
"consumes": [
|
||||
"application/xml",
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json",
|
||||
"application/xml"
|
||||
],
|
||||
"tags": [
|
||||
"application"
|
||||
],
|
||||
"summary": "Update an application trigger",
|
||||
"operationId": "updateApplicationTrigger",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "identifier of the application ",
|
||||
"name": "appName",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "identifier of the trigger",
|
||||
"name": "token",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/v1.ApplicationTriggerBase"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/bcode.Bcode"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"consumes": [
|
||||
"application/xml",
|
||||
@@ -2125,7 +2217,7 @@
|
||||
"tags": [
|
||||
"application"
|
||||
],
|
||||
"summary": "delete one application trigger",
|
||||
"summary": "Delete an application trigger",
|
||||
"operationId": "deleteApplicationTrigger",
|
||||
"parameters": [
|
||||
{
|
||||
@@ -6540,7 +6632,7 @@
|
||||
"tags": [
|
||||
"project"
|
||||
],
|
||||
"summary": "add a user to a project",
|
||||
"summary": "update a user from a project",
|
||||
"operationId": "updateProjectUser",
|
||||
"parameters": [
|
||||
{
|
||||
@@ -8917,8 +9009,8 @@
|
||||
},
|
||||
"model.ApplicationRevision": {
|
||||
"required": [
|
||||
"createTime",
|
||||
"updateTime",
|
||||
"createTime",
|
||||
"appPrimaryKey",
|
||||
"version",
|
||||
"revisionCRName",
|
||||
@@ -9300,12 +9392,12 @@
|
||||
},
|
||||
"model.WorkflowStep": {
|
||||
"required": [
|
||||
"alias",
|
||||
"type",
|
||||
"orderIndex",
|
||||
"name",
|
||||
"dependsOn",
|
||||
"description",
|
||||
"dependsOn"
|
||||
"orderIndex",
|
||||
"alias",
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"alias": {
|
||||
@@ -9423,8 +9515,8 @@
|
||||
"model.WorkflowStepStatus": {
|
||||
"required": [
|
||||
"name",
|
||||
"id",
|
||||
"alias"
|
||||
"alias",
|
||||
"id"
|
||||
],
|
||||
"properties": {
|
||||
"alias": {
|
||||
@@ -10007,12 +10099,12 @@
|
||||
},
|
||||
"v1.ApplicationDeployResponse": {
|
||||
"required": [
|
||||
"triggerType",
|
||||
"version",
|
||||
"status",
|
||||
"envName",
|
||||
"createTime",
|
||||
"status",
|
||||
"note",
|
||||
"envName",
|
||||
"triggerType",
|
||||
"record"
|
||||
],
|
||||
"properties": {
|
||||
@@ -10150,6 +10242,16 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1.ApplicationRollbackResponse": {
|
||||
"required": [
|
||||
"record"
|
||||
],
|
||||
"properties": {
|
||||
"record": {
|
||||
"$ref": "#/definitions/v1.WorkflowRecordBase"
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1.ApplicationStatisticsResponse": {
|
||||
"required": [
|
||||
"envCount",
|
||||
@@ -10281,6 +10383,7 @@
|
||||
"type",
|
||||
"payloadType",
|
||||
"token",
|
||||
"registry",
|
||||
"createTime",
|
||||
"updateTime"
|
||||
],
|
||||
@@ -10304,6 +10407,9 @@
|
||||
"payloadType": {
|
||||
"type": "string"
|
||||
},
|
||||
"registry": {
|
||||
"type": "string"
|
||||
},
|
||||
"token": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -10776,13 +10882,13 @@
|
||||
},
|
||||
"v1.ConfigTemplateDetail": {
|
||||
"required": [
|
||||
"sensitive",
|
||||
"createTime",
|
||||
"alias",
|
||||
"name",
|
||||
"namespace",
|
||||
"description",
|
||||
"scope",
|
||||
"sensitive",
|
||||
"createTime",
|
||||
"schema",
|
||||
"uiSchema"
|
||||
],
|
||||
@@ -11613,9 +11719,9 @@
|
||||
"v1.DetailAddonResponse": {
|
||||
"required": [
|
||||
"name",
|
||||
"version",
|
||||
"icon",
|
||||
"invisible",
|
||||
"version",
|
||||
"description",
|
||||
"schema",
|
||||
"uiSchema",
|
||||
@@ -11696,11 +11802,11 @@
|
||||
},
|
||||
"v1.DetailApplicationResponse": {
|
||||
"required": [
|
||||
"createTime",
|
||||
"name",
|
||||
"alias",
|
||||
"project",
|
||||
"description",
|
||||
"createTime",
|
||||
"updateTime",
|
||||
"icon",
|
||||
"policies",
|
||||
@@ -11759,20 +11865,20 @@
|
||||
},
|
||||
"v1.DetailClusterResponse": {
|
||||
"required": [
|
||||
"alias",
|
||||
"description",
|
||||
"status",
|
||||
"provider",
|
||||
"apiServerURL",
|
||||
"updateTime",
|
||||
"createTime",
|
||||
"name",
|
||||
"dashboardURL",
|
||||
"description",
|
||||
"icon",
|
||||
"labels",
|
||||
"dashboardURL",
|
||||
"kubeConfig",
|
||||
"reason",
|
||||
"apiServerURL",
|
||||
"kubeConfigSecret",
|
||||
"alias",
|
||||
"updateTime",
|
||||
"name",
|
||||
"kubeConfig",
|
||||
"createTime",
|
||||
"resourceInfo"
|
||||
],
|
||||
"properties": {
|
||||
@@ -11830,14 +11936,14 @@
|
||||
},
|
||||
"v1.DetailComponentResponse": {
|
||||
"required": [
|
||||
"appPrimaryKey",
|
||||
"creator",
|
||||
"name",
|
||||
"main",
|
||||
"createTime",
|
||||
"updateTime",
|
||||
"alias",
|
||||
"creator",
|
||||
"name",
|
||||
"appPrimaryKey",
|
||||
"type",
|
||||
"main",
|
||||
"definition"
|
||||
],
|
||||
"properties": {
|
||||
@@ -11925,13 +12031,13 @@
|
||||
},
|
||||
"v1.DetailDefinitionResponse": {
|
||||
"required": [
|
||||
"status",
|
||||
"name",
|
||||
"description",
|
||||
"icon",
|
||||
"alias",
|
||||
"labels",
|
||||
"ownerAddon",
|
||||
"name",
|
||||
"description",
|
||||
"icon",
|
||||
"status",
|
||||
"schema",
|
||||
"uiSchema"
|
||||
],
|
||||
@@ -11988,15 +12094,15 @@
|
||||
},
|
||||
"v1.DetailPolicyResponse": {
|
||||
"required": [
|
||||
"alias",
|
||||
"createTime",
|
||||
"creator",
|
||||
"properties",
|
||||
"updateTime",
|
||||
"envName",
|
||||
"name",
|
||||
"type",
|
||||
"description"
|
||||
"description",
|
||||
"createTime",
|
||||
"updateTime",
|
||||
"alias",
|
||||
"creator",
|
||||
"properties",
|
||||
"envName"
|
||||
],
|
||||
"properties": {
|
||||
"alias": {
|
||||
@@ -12038,18 +12144,18 @@
|
||||
},
|
||||
"v1.DetailRevisionResponse": {
|
||||
"required": [
|
||||
"createTime",
|
||||
"status",
|
||||
"note",
|
||||
"appPrimaryKey",
|
||||
"deployUser",
|
||||
"triggerType",
|
||||
"updateTime",
|
||||
"revisionCRName",
|
||||
"reason",
|
||||
"envName",
|
||||
"version",
|
||||
"deployUser",
|
||||
"note",
|
||||
"workflowName",
|
||||
"appPrimaryKey",
|
||||
"status",
|
||||
"triggerType",
|
||||
"revisionCRName",
|
||||
"reason"
|
||||
"createTime"
|
||||
],
|
||||
"properties": {
|
||||
"appPrimaryKey": {
|
||||
@@ -12108,8 +12214,8 @@
|
||||
"required": [
|
||||
"updateTime",
|
||||
"name",
|
||||
"project",
|
||||
"createTime"
|
||||
"createTime",
|
||||
"project"
|
||||
],
|
||||
"properties": {
|
||||
"alias": {
|
||||
@@ -12149,11 +12255,11 @@
|
||||
},
|
||||
"v1.DetailUserResponse": {
|
||||
"required": [
|
||||
"disabled",
|
||||
"createTime",
|
||||
"lastLoginTime",
|
||||
"name",
|
||||
"email",
|
||||
"disabled",
|
||||
"projects",
|
||||
"roles"
|
||||
],
|
||||
@@ -12194,13 +12300,13 @@
|
||||
},
|
||||
"v1.DetailWorkflowRecordResponse": {
|
||||
"required": [
|
||||
"workflowAlias",
|
||||
"status",
|
||||
"workflowAlias",
|
||||
"applicationRevision",
|
||||
"message",
|
||||
"mode",
|
||||
"name",
|
||||
"namespace",
|
||||
"mode",
|
||||
"workflowName",
|
||||
"deployTime",
|
||||
"deployUser",
|
||||
@@ -12264,15 +12370,15 @@
|
||||
"v1.DetailWorkflowResponse": {
|
||||
"required": [
|
||||
"name",
|
||||
"enable",
|
||||
"envName",
|
||||
"updateTime",
|
||||
"mode",
|
||||
"createTime",
|
||||
"subMode",
|
||||
"alias",
|
||||
"description",
|
||||
"enable",
|
||||
"default"
|
||||
"default",
|
||||
"createTime",
|
||||
"updateTime",
|
||||
"mode",
|
||||
"subMode"
|
||||
],
|
||||
"properties": {
|
||||
"alias": {
|
||||
@@ -12480,8 +12586,8 @@
|
||||
},
|
||||
"v1.EnvBindingTarget": {
|
||||
"required": [
|
||||
"name",
|
||||
"alias"
|
||||
"alias",
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"alias": {
|
||||
@@ -12507,12 +12613,12 @@
|
||||
},
|
||||
"v1.GetPipelineResponse": {
|
||||
"required": [
|
||||
"spec",
|
||||
"description",
|
||||
"createTime",
|
||||
"name",
|
||||
"alias",
|
||||
"project",
|
||||
"description",
|
||||
"createTime",
|
||||
"spec",
|
||||
"info"
|
||||
],
|
||||
"properties": {
|
||||
@@ -13212,11 +13318,11 @@
|
||||
},
|
||||
"v1.LoginUserInfoResponse": {
|
||||
"required": [
|
||||
"createTime",
|
||||
"lastLoginTime",
|
||||
"name",
|
||||
"email",
|
||||
"disabled",
|
||||
"createTime",
|
||||
"projects",
|
||||
"platformPermissions",
|
||||
"projectPermissions"
|
||||
@@ -13418,11 +13524,11 @@
|
||||
},
|
||||
"v1.PipelineBase": {
|
||||
"required": [
|
||||
"description",
|
||||
"createTime",
|
||||
"name",
|
||||
"alias",
|
||||
"project",
|
||||
"description",
|
||||
"createTime",
|
||||
"spec"
|
||||
],
|
||||
"properties": {
|
||||
@@ -13463,11 +13569,11 @@
|
||||
},
|
||||
"v1.PipelineListItem": {
|
||||
"required": [
|
||||
"name",
|
||||
"alias",
|
||||
"project",
|
||||
"description",
|
||||
"createTime",
|
||||
"name",
|
||||
"info"
|
||||
],
|
||||
"properties": {
|
||||
@@ -13548,13 +13654,13 @@
|
||||
},
|
||||
"v1.PipelineRun": {
|
||||
"required": [
|
||||
"pipelineName",
|
||||
"project",
|
||||
"record",
|
||||
"contextName",
|
||||
"contextValues",
|
||||
"spec",
|
||||
"pipelineName",
|
||||
"project",
|
||||
"pipelineRunName",
|
||||
"record",
|
||||
"status"
|
||||
],
|
||||
"properties": {
|
||||
@@ -13590,9 +13696,9 @@
|
||||
},
|
||||
"v1.PipelineRunBase": {
|
||||
"required": [
|
||||
"pipelineRunName",
|
||||
"pipelineName",
|
||||
"project",
|
||||
"pipelineRunName",
|
||||
"record",
|
||||
"contextName",
|
||||
"contextValues",
|
||||
@@ -14036,10 +14142,10 @@
|
||||
},
|
||||
"v1.StepInputBase": {
|
||||
"required": [
|
||||
"id",
|
||||
"name",
|
||||
"type",
|
||||
"phase",
|
||||
"id",
|
||||
"values"
|
||||
],
|
||||
"properties": {
|
||||
@@ -14065,10 +14171,10 @@
|
||||
},
|
||||
"v1.StepOutputBase": {
|
||||
"required": [
|
||||
"id",
|
||||
"name",
|
||||
"type",
|
||||
"phase",
|
||||
"id",
|
||||
"values"
|
||||
],
|
||||
"properties": {
|
||||
@@ -14677,13 +14783,13 @@
|
||||
},
|
||||
"v1.WorkflowRecord": {
|
||||
"required": [
|
||||
"status",
|
||||
"name",
|
||||
"namespace",
|
||||
"mode",
|
||||
"workflowName",
|
||||
"workflowAlias",
|
||||
"applicationRevision",
|
||||
"status",
|
||||
"mode",
|
||||
"message"
|
||||
],
|
||||
"properties": {
|
||||
|
||||
@@ -74,6 +74,12 @@ var _ = Describe("Addon Test", func() {
|
||||
Expect(output).To(ContainSubstring("enabled successfully."))
|
||||
})
|
||||
|
||||
It("Enable addon with specified registry ", func() {
|
||||
output, err := e2e.LongTimeExec("vela addon enable KubeVela/test-addon", 300*time.Second)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(output).To(ContainSubstring("enabled successfully."))
|
||||
})
|
||||
|
||||
It("Disable addon test-addon", func() {
|
||||
output, err := e2e.LongTimeExec("vela addon disable test-addon", 600*time.Second)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
@@ -199,7 +199,7 @@ var ApplicationDeleteWithWaitOptions = func(context string, appName string) bool
|
||||
cli := fmt.Sprintf("vela delete %s --wait -y", appName)
|
||||
output, err := e2e.ExecAndTerminate(cli)
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
gomega.Expect(output).To(gomega.ContainSubstring("deleted"))
|
||||
gomega.Expect(output).To(gomega.ContainSubstring("succeeded"))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@ var (
|
||||
cli := fmt.Sprintf("vela delete %s -y", applicationName)
|
||||
output, err := Exec(cli)
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
gomega.Expect(output).To(gomega.ContainSubstring("deleted from namespace"))
|
||||
gomega.Expect(output).To(gomega.ContainSubstring("succeeded"))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
33
go.mod
33
go.mod
@@ -3,7 +3,7 @@ module github.com/oam-dev/kubevela
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
cuelang.org/go v0.5.0-alpha.1
|
||||
cuelang.org/go v0.5.0-beta.5
|
||||
github.com/AlecAivazis/survey/v2 v2.1.1
|
||||
github.com/FogDong/uitable v0.0.5
|
||||
github.com/Masterminds/semver/v3 v3.1.1
|
||||
@@ -49,23 +49,21 @@ require (
|
||||
github.com/google/go-github/v32 v32.1.0
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/gosuri/uilive v0.0.4
|
||||
github.com/gosuri/uitable v0.0.4
|
||||
github.com/hashicorp/go-version v1.6.0
|
||||
github.com/hashicorp/hcl/v2 v2.12.0
|
||||
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174
|
||||
github.com/imdario/mergo v0.3.13
|
||||
github.com/koding/websocketproxy v0.0.0-20181220232114-7ed82d81a28c
|
||||
github.com/kubevela/pkg v0.0.0-20221220022408-126a9c58aa3a
|
||||
github.com/kubevela/pkg v0.0.0-20230316114047-e2b41b377bac
|
||||
github.com/kubevela/prism v1.7.0-alpha.1
|
||||
github.com/kubevela/workflow v0.3.6-0.20221228071359-3da7f1a4df6b
|
||||
github.com/kubevela/workflow v0.4.3
|
||||
github.com/kyokomi/emoji v2.2.4+incompatible
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.1
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.2
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd
|
||||
github.com/oam-dev/cluster-gateway v1.7.0-alpha.1
|
||||
github.com/oam-dev/cluster-register v1.0.4-0.20220928064144-5f76a9d7ca8c
|
||||
github.com/oam-dev/terraform-config-inspect v0.0.0-20210418082552-fc72d929aa28
|
||||
github.com/oam-dev/terraform-controller v0.7.8
|
||||
github.com/oam-dev/terraform-controller v0.7.10
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
github.com/onsi/ginkgo v1.16.5
|
||||
github.com/onsi/ginkgo/v2 v2.1.6
|
||||
@@ -89,9 +87,9 @@ require (
|
||||
go.mongodb.org/mongo-driver v1.5.1
|
||||
go.uber.org/zap v1.21.0 // indirect
|
||||
golang.org/x/crypto v0.4.0
|
||||
golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2
|
||||
golang.org/x/term v0.3.0
|
||||
golang.org/x/text v0.5.0
|
||||
golang.org/x/oauth2 v0.0.0-20220722155238-128564f6959c
|
||||
golang.org/x/term v0.5.0
|
||||
golang.org/x/text v0.7.0
|
||||
gomodules.xyz/jsonpatch/v2 v2.2.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
gotest.tools v2.2.0+incompatible
|
||||
@@ -101,14 +99,14 @@ require (
|
||||
k8s.io/apiextensions-apiserver v0.25.2
|
||||
k8s.io/apimachinery v0.25.3
|
||||
k8s.io/apiserver v0.25.3
|
||||
k8s.io/cli-runtime v0.25.2
|
||||
k8s.io/cli-runtime v0.25.3
|
||||
k8s.io/client-go v0.25.3
|
||||
k8s.io/component-base v0.25.3
|
||||
k8s.io/helm v2.17.0+incompatible
|
||||
k8s.io/klog/v2 v2.70.1
|
||||
k8s.io/kube-aggregator v0.25.3
|
||||
k8s.io/kubectl v0.25.2
|
||||
k8s.io/metrics v0.25.2
|
||||
k8s.io/kubectl v0.25.3
|
||||
k8s.io/metrics v0.25.3
|
||||
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed
|
||||
open-cluster-management.io/api v0.7.0
|
||||
sigs.k8s.io/controller-runtime v0.12.3
|
||||
@@ -118,6 +116,8 @@ require (
|
||||
sigs.k8s.io/yaml v1.3.0
|
||||
)
|
||||
|
||||
require github.com/koding/websocketproxy v0.0.0-20181220232114-7ed82d81a28c
|
||||
|
||||
require (
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||
@@ -302,14 +302,14 @@ require (
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
go.uber.org/multierr v1.7.0 // indirect
|
||||
golang.org/x/mod v0.6.0 // indirect
|
||||
golang.org/x/net v0.3.0 // indirect
|
||||
golang.org/x/net v0.7.0 // indirect
|
||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde // indirect
|
||||
golang.org/x/sys v0.3.0 // indirect
|
||||
golang.org/x/sys v0.5.0 // indirect
|
||||
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
|
||||
golang.org/x/tools v0.2.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/grpc v1.48.0 // indirect
|
||||
google.golang.org/protobuf v1.28.0 // indirect
|
||||
google.golang.org/protobuf v1.28.1 // indirect
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
@@ -349,7 +349,6 @@ require (
|
||||
|
||||
replace (
|
||||
cloud.google.com/go => cloud.google.com/go v0.100.2
|
||||
cuelang.org/go => github.com/kubevela/cue v0.4.4-0.20221107123854-a976b0e340be
|
||||
github.com/docker/cli => github.com/docker/cli v20.10.9+incompatible
|
||||
github.com/docker/docker => github.com/moby/moby v17.12.0-ce-rc1.0.20200618181300-9dc6525e6118+incompatible
|
||||
github.com/wercker/stern => github.com/oam-dev/stern v1.13.2
|
||||
|
||||
57
go.sum
57
go.sum
@@ -34,6 +34,8 @@ cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3f
|
||||
collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE=
|
||||
contrib.go.opencensus.io/exporter/ocagent v0.6.0/go.mod h1:zmKjrJcdo0aYcVS7bmEeSEBLPA9YJp5bjrofdU3pIXs=
|
||||
contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc=
|
||||
cuelang.org/go v0.5.0-beta.5 h1:TAV4ZjXw2M6xf6jI8XyAAXCqWJ82Y0oxhlf9w3l544A=
|
||||
cuelang.org/go v0.5.0-beta.5/go.mod h1:okjJBHFQFer+a41sAe2SaGm1glWS8oEb6CmJvn5Zdws=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/AlecAivazis/survey/v2 v2.1.1 h1:LEMbHE0pLj75faaVEKClEX1TM4AJmmnOh9eimREzLWI=
|
||||
github.com/AlecAivazis/survey/v2 v2.1.1/go.mod h1:9FJRdMdDm8rnT+zHVbvQT2RTSTLq0Ttd6q3Vl2fahjk=
|
||||
@@ -1060,8 +1062,6 @@ github.com/gostaticanalysis/forcetypeassert v0.0.0-20200621232751-01d4955beaa5/g
|
||||
github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A=
|
||||
github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M=
|
||||
github.com/gostaticanalysis/testutil v0.4.0/go.mod h1:bLIoPefWXrRi/ssLFWX1dx7Repi5x3CuviD3dgAZaBU=
|
||||
github.com/gosuri/uilive v0.0.4 h1:hUEBpQDj8D8jXgtCdBu7sWsy5sbW/5GhuO8KBwJ2jyY=
|
||||
github.com/gosuri/uilive v0.0.4/go.mod h1:V/epo5LjjlDE5RJUcqx8dbw+zc93y5Ya3yg8tfZ74VI=
|
||||
github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY=
|
||||
github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo=
|
||||
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
@@ -1285,14 +1285,12 @@ github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kubevela/cue v0.4.4-0.20221107123854-a976b0e340be h1:0xj/Rh4yVy54mUD2nLmAuN1AYgBkkHxBh4PoLGbIg5g=
|
||||
github.com/kubevela/cue v0.4.4-0.20221107123854-a976b0e340be/go.mod h1:Ya12qn7FZc+LSN0qgEhzEpnzQsvnGHVgoDrqe9i3eNg=
|
||||
github.com/kubevela/pkg v0.0.0-20221220022408-126a9c58aa3a h1:kWBTjpxcA6ZQTGyk1Mm+1/MT2+3Fv3ffQnK/1GYdXo4=
|
||||
github.com/kubevela/pkg v0.0.0-20221220022408-126a9c58aa3a/go.mod h1:IQ0/t6H7+580nwFlkt08gbPyH9S4zQNxnKTM2eiK0TI=
|
||||
github.com/kubevela/pkg v0.0.0-20230316114047-e2b41b377bac h1:TLQchMx+BRTnHyebDpOWF2RpF2eTczFBtJro3/H9vwI=
|
||||
github.com/kubevela/pkg v0.0.0-20230316114047-e2b41b377bac/go.mod h1:GilLxt+9L4sU2tLeZAGHga8wiYmjjfPX/Q6JkyuuXSM=
|
||||
github.com/kubevela/prism v1.7.0-alpha.1 h1:oeZFn1Oy6gxSSFzMTfsWjLOCKaaooMVm1JGNK4j4Mlo=
|
||||
github.com/kubevela/prism v1.7.0-alpha.1/go.mod h1:AJSDfdA+RkRSnWx3xEcogbmOTpX+l7RSIwqVHxwUtaI=
|
||||
github.com/kubevela/workflow v0.3.6-0.20221228071359-3da7f1a4df6b h1:zbBG/fTXIyhwyS3XfoYxEWJ3F1xGGQN7bCZQhlI0KYI=
|
||||
github.com/kubevela/workflow v0.3.6-0.20221228071359-3da7f1a4df6b/go.mod h1:AX/WL3G/YBkpmNpA/SKKm9M3Y0T9y95gZA8mFWylkyM=
|
||||
github.com/kubevela/workflow v0.4.3 h1:1WAMb4xrRXQW5hK5bXwV2WFHlxn2+ezkblai8oC5DmY=
|
||||
github.com/kubevela/workflow v0.4.3/go.mod h1:U94Hz5rlHPAatN+Birhumly26zjAguMumdhrYk+e5mo=
|
||||
github.com/kulti/thelper v0.4.0/go.mod h1:vMu2Cizjy/grP+jmsvOFDx1kYP6+PD1lqg4Yu5exl2U=
|
||||
github.com/kunwardeep/paralleltest v1.0.3/go.mod h1:vLydzomDFpk7yu5UX02RmP0H8QfRPOV/oFhWN85Mjb4=
|
||||
github.com/kylelemons/godebug v0.0.0-20160406211939-eadb3ce320cb/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
|
||||
@@ -1437,8 +1435,8 @@ github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQ
|
||||
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
|
||||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||
github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ=
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.1 h1:L60q1+q7cXE4JeEJJKMnh2brFIe3rZxCihYAB61ypAY=
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.1/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
|
||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
@@ -1525,8 +1523,8 @@ github.com/oam-dev/stern v1.13.2 h1:jlGgtJbKmIVhzkH44ft5plkgs8XEfvxbFrQdX60CQR4=
|
||||
github.com/oam-dev/stern v1.13.2/go.mod h1:0pLjZt0amXE/ErF16Rdrgd98H2owN8Hmn3/7CX5+AeA=
|
||||
github.com/oam-dev/terraform-config-inspect v0.0.0-20210418082552-fc72d929aa28 h1:tD8HiFKnt0jnwdTWjeqUnfnUYLD/+Nsmj8ZGIxqDWiU=
|
||||
github.com/oam-dev/terraform-config-inspect v0.0.0-20210418082552-fc72d929aa28/go.mod h1:Mu8i0/DdplvnjwRbAYPsc8+LRR27n/mp8VWdkN10GzE=
|
||||
github.com/oam-dev/terraform-controller v0.7.8 h1:4Kss5EnMljKecw8o2aPCpZdOTP1L1ODgf8BjmgN/cMI=
|
||||
github.com/oam-dev/terraform-controller v0.7.8/go.mod h1:83eY+m0ehYAnQytilG9TVjuCgDQWl3+pnE6oIJ9EujE=
|
||||
github.com/oam-dev/terraform-controller v0.7.10 h1:e2STz6Od53S4Ra4+QQs65lujF50vIb6eQtTMuvvofjk=
|
||||
github.com/oam-dev/terraform-controller v0.7.10/go.mod h1:xvgChKG0pij0WEKRrX7w30SdVBPVOlRl/+Mv7+2C1cI=
|
||||
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
|
||||
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
||||
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
|
||||
@@ -2302,8 +2300,8 @@ golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.3.0 h1:VWL6FNY2bEEmsGVKabSlHu5Irp34xmMRoqb/9lF9lxk=
|
||||
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
||||
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@@ -2321,8 +2319,8 @@ golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j
|
||||
golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||
golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE=
|
||||
golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2 h1:+jnHzr9VPj32ykQVai5DNahi9+NSp7yYuCsl5eAQtL0=
|
||||
golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE=
|
||||
golang.org/x/oauth2 v0.0.0-20220722155238-128564f6959c h1:q3gFqPqH7NVofKo3c3yETAP//pPI+G5mvB7qqj1Y5kY=
|
||||
golang.org/x/oauth2 v0.0.0-20220722155238-128564f6959c/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -2486,8 +2484,8 @@ golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
|
||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
|
||||
golang.org/x/sys v0.5.0/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-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
@@ -2496,8 +2494,8 @@ golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuX
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI=
|
||||
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
|
||||
golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180805044716-cb6730876b98/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -2509,8 +2507,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
|
||||
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
@@ -2815,8 +2813,9 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
|
||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
|
||||
@@ -2971,8 +2970,8 @@ k8s.io/apiserver v0.22.2/go.mod h1:vrpMmbyjWrgdyOvZTSpsusQq5iigKNWv9o9KlDAbBHI=
|
||||
k8s.io/apiserver v0.22.6/go.mod h1:OlL1rGa2kKWGj2JEXnwBcul/BwC9Twe95gm4ohtiIIs=
|
||||
k8s.io/apiserver v0.25.3 h1:m7+xGuG5+KYAnEsqaFtDyWMkmMMEOFYlu+NlWv5qSBI=
|
||||
k8s.io/apiserver v0.25.3/go.mod h1:9bT47iM2fzRuhICJpM/RcQR9sqDDfZ7Yw60h0p3JW08=
|
||||
k8s.io/cli-runtime v0.25.2 h1:XOx+SKRjBpYMLY/J292BHTkmyDffl/qOx3YSuFZkTuc=
|
||||
k8s.io/cli-runtime v0.25.2/go.mod h1:OQx3+/0st6x5YpkkJQlEWLC73V0wHsOFMC1/roxV8Oc=
|
||||
k8s.io/cli-runtime v0.25.3 h1:Zs7P7l7db/5J+KDePOVtDlArAa9pZXaDinGWGZl0aM8=
|
||||
k8s.io/cli-runtime v0.25.3/go.mod h1:InHHsjkyW5hQsILJGpGjeruiDZT/R0OkROQgD6GzxO4=
|
||||
k8s.io/client-go v0.0.0-20190620085101-78d2af792bab/go.mod h1:E95RaSlHr79aHaX0aGSwcPNfygDiPKOVXdmivCIZT0k=
|
||||
k8s.io/client-go v0.0.0-20190918160344-1fbdaa4c8d90/go.mod h1:J69/JveO6XESwVgG53q3Uz5OSfgsv4uxpScmmyYOOlk=
|
||||
k8s.io/client-go v0.0.0-20191122220542-ed16ecbdf3a0/go.mod h1:tyxNgOmR/Xi39HrlQ/9LQgiHJgBvmY7gp95o5GpBA4o=
|
||||
@@ -3065,11 +3064,11 @@ k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c/go.mod h1:vHXdDvt9+2spS2R
|
||||
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65/go.mod h1:sX9MT8g7NVZM5lVL/j8QyCCJe8YSMW30QvGZWaCIDIk=
|
||||
k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 h1:MQ8BAZPZlWk3S9K4a9NCkIFQtZShWqoha7snGixVgEA=
|
||||
k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU=
|
||||
k8s.io/kubectl v0.25.2 h1:2993lTeVimxKSWx/7z2PiJxUILygRa3tmC4QhFaeioA=
|
||||
k8s.io/kubectl v0.25.2/go.mod h1:eoBGJtKUj7x38KXelz+dqVtbtbKwCqyKzJWmBHU0prg=
|
||||
k8s.io/kubectl v0.25.3 h1:HnWJziEtmsm4JaJiKT33kG0kadx68MXxUE8UEbXnN4U=
|
||||
k8s.io/kubectl v0.25.3/go.mod h1:glU7PiVj/R6Ud4A9FJdTcJjyzOtCJyc0eO7Mrbh3jlI=
|
||||
k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
|
||||
k8s.io/metrics v0.25.2 h1:105TuPaIFfr4EHzN56WwZJO7r1UesuDytNTzeMqGySo=
|
||||
k8s.io/metrics v0.25.2/go.mod h1:4NDAauOuEJ+NWO2+hWkhFE4rWBx/plLWJOYU3vGl0sA=
|
||||
k8s.io/metrics v0.25.3 h1:fp5RuALkbwI3UbKITdNYu6sa3LF4JPANR/ofq3oe+Fg=
|
||||
k8s.io/metrics v0.25.3/go.mod h1:5j5FKJb8RHsb3Q2PLsD/p1mLiA1fTrl+a62Les+KDhc=
|
||||
k8s.io/utils v0.0.0-20190221042446-c2654d5206da/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0=
|
||||
k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||
|
||||
@@ -848,6 +848,7 @@ spec:
|
||||
x-kubernetes-map-type: atomic
|
||||
endTime:
|
||||
format: date-time
|
||||
nullable: true
|
||||
type: string
|
||||
finished:
|
||||
type: boolean
|
||||
@@ -2806,6 +2807,7 @@ spec:
|
||||
x-kubernetes-map-type: atomic
|
||||
endTime:
|
||||
format: date-time
|
||||
nullable: true
|
||||
type: string
|
||||
finished:
|
||||
type: boolean
|
||||
@@ -4942,6 +4944,7 @@ spec:
|
||||
x-kubernetes-map-type: atomic
|
||||
endTime:
|
||||
format: date-time
|
||||
nullable: true
|
||||
type: string
|
||||
finished:
|
||||
type: boolean
|
||||
|
||||
@@ -774,6 +774,7 @@ spec:
|
||||
x-kubernetes-map-type: atomic
|
||||
endTime:
|
||||
format: date-time
|
||||
nullable: true
|
||||
type: string
|
||||
finished:
|
||||
type: boolean
|
||||
@@ -1535,6 +1536,7 @@ spec:
|
||||
x-kubernetes-map-type: atomic
|
||||
endTime:
|
||||
format: date-time
|
||||
nullable: true
|
||||
type: string
|
||||
finished:
|
||||
type: boolean
|
||||
|
||||
@@ -60,6 +60,7 @@ import (
|
||||
common2 "github.com/oam-dev/kubevela/apis/core.oam.dev/common"
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
||||
"github.com/oam-dev/kubevela/apis/types"
|
||||
apiutils "github.com/oam-dev/kubevela/pkg/apiserver/utils"
|
||||
"github.com/oam-dev/kubevela/pkg/config"
|
||||
"github.com/oam-dev/kubevela/pkg/cue/script"
|
||||
"github.com/oam-dev/kubevela/pkg/definition"
|
||||
@@ -910,7 +911,6 @@ func NewAddonInstaller(ctx context.Context, cli client.Client, discoveryClient *
|
||||
func (h *Installer) enableAddon(addon *InstallPackage) (string, error) {
|
||||
var err error
|
||||
h.addon = addon
|
||||
|
||||
if !h.skipVersionValidate {
|
||||
err = checkAddonVersionMeetRequired(h.ctx, addon.SystemRequirements, h.cli, h.dc)
|
||||
if err != nil {
|
||||
@@ -1075,23 +1075,25 @@ func (h *Installer) checkDependency(addon *InstallPackage) ([]string, error) {
|
||||
|
||||
// createOrUpdate will return true if updated
|
||||
func (h *Installer) createOrUpdate(app *v1beta1.Application) (bool, error) {
|
||||
var getapp v1beta1.Application
|
||||
err := h.cli.Get(h.ctx, client.ObjectKey{Name: app.Name, Namespace: app.Namespace}, &getapp)
|
||||
// Set the publish version for the addon application
|
||||
oam.SetPublishVersion(app, apiutils.GenerateVersion("addon"))
|
||||
var existApp v1beta1.Application
|
||||
err := h.cli.Get(h.ctx, client.ObjectKey{Name: app.Name, Namespace: app.Namespace}, &existApp)
|
||||
if apierrors.IsNotFound(err) {
|
||||
return false, h.cli.Create(h.ctx, app)
|
||||
}
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
getapp.Spec = app.Spec
|
||||
getapp.Labels = app.Labels
|
||||
getapp.Annotations = app.Annotations
|
||||
err = h.cli.Update(h.ctx, &getapp)
|
||||
existApp.Spec = app.Spec
|
||||
existApp.Labels = app.Labels
|
||||
existApp.Annotations = app.Annotations
|
||||
err = h.cli.Update(h.ctx, &existApp)
|
||||
if err != nil {
|
||||
klog.Errorf("fail to create application: %v", err)
|
||||
return false, errors.Wrap(err, "fail to create application")
|
||||
}
|
||||
getapp.DeepCopyInto(app)
|
||||
existApp.DeepCopyInto(app)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
@@ -1208,6 +1210,9 @@ func (h *Installer) dispatchAddonResource(addon *InstallPackage) error {
|
||||
}
|
||||
|
||||
func (h *Installer) renderNotes(addon *InstallPackage) (string, error) {
|
||||
if len(addon.Notes.Data) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
r := addonCueTemplateRender{
|
||||
addon: addon,
|
||||
inputArgs: h.args,
|
||||
@@ -1219,7 +1224,7 @@ func (h *Installer) renderNotes(addon *InstallPackage) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
notesFile := addon.Notes.Data + "\n" + contextFile
|
||||
notesFile := contextFile + "\n" + addon.Notes.Data
|
||||
val, err := value.NewValue(notesFile, nil, "")
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "build values for NOTES.cue")
|
||||
|
||||
@@ -67,13 +67,18 @@ func NewCache(ds RegistryDataStore) *Cache {
|
||||
}
|
||||
|
||||
// DiscoverAndRefreshLoop will run a loop to automatically discovery and refresh addons from registry
|
||||
func (u *Cache) DiscoverAndRefreshLoop(cacheTime time.Duration) {
|
||||
func (u *Cache) DiscoverAndRefreshLoop(ctx context.Context, cacheTime time.Duration) {
|
||||
ticker := time.NewTicker(cacheTime)
|
||||
defer ticker.Stop()
|
||||
|
||||
// This is infinite loop, we can receive a channel for close
|
||||
for ; true; <-ticker.C {
|
||||
u.discoverAndRefreshRegistry()
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
u.discoverAndRefreshRegistry()
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,9 @@ func EnableAddon(ctx context.Context, name string, version string, cli client.Cl
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err := validateAddonPackage(pkg); err != nil {
|
||||
return "", errors.Wrap(err, fmt.Sprintf("failed to enable addon: %s", name))
|
||||
}
|
||||
return h.enableAddon(pkg)
|
||||
}
|
||||
|
||||
@@ -106,6 +109,9 @@ func EnableAddonByLocalDir(ctx context.Context, name string, dir string, cli cli
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err := validateAddonPackage(pkg); err != nil {
|
||||
return "", errors.Wrap(err, fmt.Sprintf("failed to enable addon by local dir: %s", dir))
|
||||
}
|
||||
h := NewAddonInstaller(ctx, cli, dc, applicator, config, &Registry{Name: LocalAddonRegistryName}, args, nil, nil, opts...)
|
||||
needEnableAddonNames, err := h.checkDependency(pkg)
|
||||
if err != nil {
|
||||
|
||||
@@ -17,9 +17,12 @@ limitations under the License.
|
||||
package addon
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
@@ -29,6 +32,38 @@ import (
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
func setupMockServer() *httptest.Server {
|
||||
var listenURL string
|
||||
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
fileList := []string{
|
||||
"index.yaml",
|
||||
"fluxcd-test-version-1.0.0.tgz",
|
||||
"fluxcd-test-version-2.0.0.tgz",
|
||||
"vela-workflow-v0.3.5.tgz",
|
||||
"foo-v1.0.0.tgz",
|
||||
"bar-v1.0.0.tgz",
|
||||
"bar-v2.0.0.tgz",
|
||||
"mock-be-dep-addon-v1.0.0.tgz",
|
||||
}
|
||||
for _, f := range fileList {
|
||||
if strings.Contains(req.URL.Path, f) {
|
||||
file, err := os.ReadFile("../../e2e/addon/mock/testrepo/helm-repo/" + f)
|
||||
if err != nil {
|
||||
_, _ = w.Write([]byte(err.Error()))
|
||||
}
|
||||
if f == "index.yaml" {
|
||||
// in index.yaml, url is hardcoded to 127.0.0.1:9098,
|
||||
// so we need to replace it with the real random listen url
|
||||
file = bytes.ReplaceAll(file, []byte("http://127.0.0.1:9098"), []byte(listenURL))
|
||||
}
|
||||
_, _ = w.Write(file)
|
||||
}
|
||||
}
|
||||
}))
|
||||
listenURL = s.URL
|
||||
return s
|
||||
}
|
||||
|
||||
var _ = Describe("test FindAddonPackagesDetailFromRegistry", func() {
|
||||
Describe("when no registry is added, no matter what you do, it will just return error", func() {
|
||||
Context("when empty addonNames and registryNames is supplied", func() {
|
||||
@@ -50,12 +85,15 @@ var _ = Describe("test FindAddonPackagesDetailFromRegistry", func() {
|
||||
})
|
||||
|
||||
Describe("one versioned registry is added", func() {
|
||||
var s *httptest.Server
|
||||
|
||||
BeforeEach(func() {
|
||||
// Prepare KubeVela registry
|
||||
s = setupMockServer()
|
||||
// Prepare registry
|
||||
reg := &Registry{
|
||||
Name: "KubeVela",
|
||||
Name: "addon_helper_test",
|
||||
Helm: &HelmSource{
|
||||
URL: "https://addons.kubevela.net",
|
||||
URL: s.URL,
|
||||
},
|
||||
}
|
||||
ds := NewRegistryDataStore(k8sClient)
|
||||
@@ -63,38 +101,36 @@ var _ = Describe("test FindAddonPackagesDetailFromRegistry", func() {
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
// Clean up KubeVela registry
|
||||
// Clean up registry
|
||||
ds := NewRegistryDataStore(k8sClient)
|
||||
Expect(ds.DeleteRegistry(context.Background(), "KubeVela")).To(Succeed())
|
||||
Expect(ds.DeleteRegistry(context.Background(), "addon_helper_test")).To(Succeed())
|
||||
s.Close()
|
||||
})
|
||||
|
||||
Context("when empty addonNames and registryNames is supplied", func() {
|
||||
It("should return error, empty addonNames are not allowed", func() {
|
||||
_, err := FindAddonPackagesDetailFromRegistry(context.Background(), k8sClient, []string{}, []string{"KubeVela"})
|
||||
_, err := FindAddonPackagesDetailFromRegistry(context.Background(), k8sClient, []string{}, []string{"addon_helper_test"})
|
||||
Expect(err).To(HaveOccurred())
|
||||
})
|
||||
It("should return error, empty addonNames are not allowed", func() {
|
||||
_, err := FindAddonPackagesDetailFromRegistry(context.Background(), k8sClient, nil, []string{"KubeVela"})
|
||||
_, err := FindAddonPackagesDetailFromRegistry(context.Background(), k8sClient, nil, []string{"addon_helper_test"})
|
||||
Expect(err).To(HaveOccurred())
|
||||
})
|
||||
})
|
||||
|
||||
Context("one existing addon name provided", func() {
|
||||
It("should return one valid result, matching all registries", func() {
|
||||
res, err := FindAddonPackagesDetailFromRegistry(context.Background(), k8sClient, []string{"velaux"}, nil)
|
||||
res, err := FindAddonPackagesDetailFromRegistry(context.Background(), k8sClient, []string{"foo"}, nil)
|
||||
|
||||
Expect(err).To(Succeed())
|
||||
Expect(res).To(HaveLen(1))
|
||||
Expect(res[0].Name).To(Equal("velaux"))
|
||||
Expect(res[0].InstallPackage).ToNot(BeNil())
|
||||
Expect(res[0].APISchema).ToNot(BeNil())
|
||||
Expect(res[0].Name).To(Equal("foo"))
|
||||
})
|
||||
It("should return one valid result, matching one registry", func() {
|
||||
res, err := FindAddonPackagesDetailFromRegistry(context.Background(), k8sClient, []string{"velaux"}, []string{"KubeVela"})
|
||||
res, err := FindAddonPackagesDetailFromRegistry(context.Background(), k8sClient, []string{"foo"}, []string{"addon_helper_test"})
|
||||
Expect(err).To(Succeed())
|
||||
Expect(res).To(HaveLen(1))
|
||||
Expect(res[0].Name).To(Equal("velaux"))
|
||||
Expect(res[0].InstallPackage).ToNot(BeNil())
|
||||
Expect(res[0].APISchema).ToNot(BeNil())
|
||||
Expect(res[0].Name).To(Equal("foo"))
|
||||
})
|
||||
})
|
||||
|
||||
@@ -108,26 +144,20 @@ var _ = Describe("test FindAddonPackagesDetailFromRegistry", func() {
|
||||
|
||||
Context("two existing addon names provided", func() {
|
||||
It("should return two valid result", func() {
|
||||
res, err := FindAddonPackagesDetailFromRegistry(context.Background(), k8sClient, []string{"velaux", "traefik"}, nil)
|
||||
res, err := FindAddonPackagesDetailFromRegistry(context.Background(), k8sClient, []string{"foo", "bar"}, nil)
|
||||
Expect(err).To(Succeed())
|
||||
Expect(res).To(HaveLen(2))
|
||||
Expect(res[0].Name).To(Equal("velaux"))
|
||||
Expect(res[0].InstallPackage).ToNot(BeNil())
|
||||
Expect(res[0].APISchema).ToNot(BeNil())
|
||||
Expect(res[1].Name).To(Equal("traefik"))
|
||||
Expect(res[1].InstallPackage).ToNot(BeNil())
|
||||
Expect(res[1].APISchema).ToNot(BeNil())
|
||||
Expect(res[0].Name).To(Equal("foo"))
|
||||
Expect(res[1].Name).To(Equal("bar"))
|
||||
})
|
||||
})
|
||||
|
||||
Context("one existing addon name and one non-existent addon name provided", func() {
|
||||
It("should return only one valid result", func() {
|
||||
res, err := FindAddonPackagesDetailFromRegistry(context.Background(), k8sClient, []string{"velaux", "non-existent-addon"}, nil)
|
||||
res, err := FindAddonPackagesDetailFromRegistry(context.Background(), k8sClient, []string{"foo", "non-existent-addon"}, nil)
|
||||
Expect(err).To(Succeed())
|
||||
Expect(res).To(HaveLen(1))
|
||||
Expect(res[0].Name).To(Equal("velaux"))
|
||||
Expect(res[0].InstallPackage).ToNot(BeNil())
|
||||
Expect(res[0].APISchema).ToNot(BeNil())
|
||||
Expect(res[0].Name).To(Equal("foo"))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -196,9 +196,13 @@ func (cmd *InitCmd) createHelmComponent() error {
|
||||
tmpl := helmComponentTmpl{}
|
||||
tmpl.Type = "helm"
|
||||
tmpl.Properties.RepoType = "helm"
|
||||
if strings.HasPrefix(cmd.HelmRepoURL, "oci") {
|
||||
tmpl.Properties.RepoType = "oci"
|
||||
}
|
||||
tmpl.Properties.URL = cmd.HelmRepoURL
|
||||
tmpl.Properties.Chart = cmd.HelmChartName
|
||||
tmpl.Properties.Version = cmd.HelmChartVersion
|
||||
tmpl.Name = "addon-" + cmd.AddonName
|
||||
|
||||
str, err := toCUEResourceString(tmpl)
|
||||
if err != nil {
|
||||
@@ -383,6 +387,7 @@ func (cmd *InitCmd) writeFiles() error {
|
||||
|
||||
// helmComponentTmpl is a template for a helm component .cue in an addon
|
||||
type helmComponentTmpl struct {
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Properties struct {
|
||||
RepoType string `json:"repoType"`
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
@@ -503,6 +504,19 @@ func checkBondComponentExist(u unstructured.Unstructured, app v1beta1.Applicatio
|
||||
return false
|
||||
}
|
||||
|
||||
func validateAddonPackage(addonPkg *InstallPackage) error {
|
||||
if reflect.DeepEqual(addonPkg.Meta, Meta{}) {
|
||||
return fmt.Errorf("the addon package doesn't have `metadata.yaml`")
|
||||
}
|
||||
if addonPkg.Name == "" {
|
||||
return fmt.Errorf("`matadata.yaml` must define the name of addon")
|
||||
}
|
||||
if addonPkg.Version == "" {
|
||||
return fmt.Errorf("`matadata.yaml` must define the version of addon")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FilterDependencyRegistries will return all registries besides the target registry itself
|
||||
func FilterDependencyRegistries(i int, rs []Registry) []Registry {
|
||||
if i >= len(rs) {
|
||||
|
||||
@@ -17,9 +17,11 @@ limitations under the License.
|
||||
package addon
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@@ -402,6 +404,30 @@ func TestFilterDependencyRegistries(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckAddonPackageValid(t *testing.T) {
|
||||
testCases := []struct {
|
||||
testCase Meta
|
||||
err error
|
||||
}{{
|
||||
testCase: Meta{},
|
||||
err: fmt.Errorf("the addon package doesn't have `metadata.yaml`"),
|
||||
}, {
|
||||
testCase: Meta{Version: "v1.4.0"},
|
||||
err: fmt.Errorf("`matadata.yaml` must define the name of addon"),
|
||||
}, {
|
||||
testCase: Meta{Name: "test-addon"},
|
||||
err: fmt.Errorf("`matadata.yaml` must define the version of addon"),
|
||||
}, {
|
||||
testCase: Meta{Name: "test-addon", Version: "1.4.5"},
|
||||
err: nil,
|
||||
},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
err := validateAddonPackage(&InstallPackage{Meta: testCase.testCase})
|
||||
assert.Equal(t, reflect.DeepEqual(err, testCase.err), true)
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
compDefYaml = `
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
|
||||
@@ -149,7 +149,7 @@ func (i versionedRegistry) loadAddon(ctx context.Context, name, version string)
|
||||
if addonVersion == nil {
|
||||
return nil, errors.Errorf("specified version %s not exist", utils.Sanitize(version))
|
||||
}
|
||||
klog.Infof("Addon '%s' with version '%s' found from registry '%s'", addonVersion.Name, addonVersion.Version, i.name)
|
||||
klog.V(5).Infof("Addon '%s' with version '%s' found from registry '%s'", addonVersion.Name, addonVersion.Version, i.name)
|
||||
for _, chartURL := range addonVersion.URLs {
|
||||
if !utils.IsValidURL(chartURL) {
|
||||
chartURL, err = utils.JoinURL(i.url, chartURL)
|
||||
@@ -174,7 +174,7 @@ func (i versionedRegistry) loadAddon(ctx context.Context, name, version string)
|
||||
addonPkg.AvailableVersions = availableVersions
|
||||
addonPkg.RegistryName = i.name
|
||||
addonPkg.Meta.SystemRequirements = LoadSystemRequirements(addonVersion.Annotations)
|
||||
klog.Infof("Addon '%s' with version '%s' loaded successfully from registry '%s'", addonVersion.Name, addonVersion.Version, i.name)
|
||||
klog.V(5).Infof("Addon '%s' with version '%s' loaded successfully from registry '%s'", addonVersion.Name, addonVersion.Version, i.name)
|
||||
return addonPkg, nil
|
||||
}
|
||||
return nil, ErrFetch
|
||||
|
||||
@@ -59,8 +59,8 @@ func (a *Application) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (a *Application) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (a *Application) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if a.Name != "" {
|
||||
index["name"] = a.Name
|
||||
}
|
||||
@@ -154,8 +154,8 @@ func (a *ApplicationComponent) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (a *ApplicationComponent) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (a *ApplicationComponent) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if a.Name != "" {
|
||||
index["name"] = a.Name
|
||||
}
|
||||
@@ -202,8 +202,8 @@ func (a *ApplicationPolicy) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (a *ApplicationPolicy) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (a *ApplicationPolicy) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if a.Name != "" {
|
||||
index["name"] = a.Name
|
||||
}
|
||||
@@ -348,8 +348,8 @@ func (a *ApplicationRevision) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (a *ApplicationRevision) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (a *ApplicationRevision) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if a.Version != "" {
|
||||
index["version"] = a.Version
|
||||
}
|
||||
@@ -434,8 +434,8 @@ func (w *ApplicationTrigger) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (w *ApplicationTrigger) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (w *ApplicationTrigger) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if w.AppPrimaryKey != "" {
|
||||
index["appPrimaryKey"] = w.AppPrimaryKey
|
||||
}
|
||||
|
||||
@@ -93,8 +93,8 @@ func (c *Cluster) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index set to nil for list
|
||||
func (c *Cluster) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (c *Cluster) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if c.Name != "" {
|
||||
index["name"] = c.Name
|
||||
}
|
||||
|
||||
@@ -53,8 +53,8 @@ func (p *Env) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (p *Env) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (p *Env) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if p.Name != "" {
|
||||
index["name"] = p.Name
|
||||
}
|
||||
|
||||
@@ -62,8 +62,8 @@ func (e *EnvBinding) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (e *EnvBinding) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (e *EnvBinding) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if e.Name != "" {
|
||||
index["name"] = e.Name
|
||||
}
|
||||
|
||||
@@ -61,8 +61,8 @@ func (p Pipeline) ShortTableName() string {
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (p Pipeline) Index() map[string]string {
|
||||
var index = make(map[string]string)
|
||||
func (p Pipeline) Index() map[string]interface{} {
|
||||
var index = make(map[string]interface{})
|
||||
if p.Project != "" {
|
||||
index["project"] = p.Project
|
||||
}
|
||||
@@ -102,8 +102,8 @@ func (c *PipelineContext) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (c *PipelineContext) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (c *PipelineContext) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if c.ProjectName != "" {
|
||||
index["project_name"] = c.ProjectName
|
||||
}
|
||||
|
||||
@@ -54,8 +54,8 @@ func (p *Project) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (p *Project) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (p *Project) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if p.Name != "" {
|
||||
index["name"] = p.Name
|
||||
}
|
||||
|
||||
@@ -146,8 +146,8 @@ func (u *SystemInfo) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (u *SystemInfo) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (u *SystemInfo) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if u.InstallID != "" {
|
||||
index["installID"] = u.InstallID
|
||||
}
|
||||
|
||||
@@ -48,8 +48,8 @@ func (d *Target) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (d *Target) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (d *Target) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if d.Name != "" {
|
||||
index["name"] = d.Name
|
||||
}
|
||||
|
||||
@@ -67,8 +67,8 @@ func (u *User) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (u *User) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (u *User) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if u.Name != "" {
|
||||
index["name"] = u.Name
|
||||
}
|
||||
@@ -106,8 +106,8 @@ func (u *ProjectUser) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (u *ProjectUser) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (u *ProjectUser) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if u.Username != "" {
|
||||
index["username"] = u.Username
|
||||
}
|
||||
@@ -177,8 +177,8 @@ func (r *Role) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (r *Role) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (r *Role) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if r.Name != "" {
|
||||
index["name"] = r.Name
|
||||
}
|
||||
@@ -207,8 +207,8 @@ func (p *Permission) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (p *Permission) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (p *Permission) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if p.Name != "" {
|
||||
index["name"] = p.Name
|
||||
}
|
||||
@@ -250,8 +250,8 @@ func (p *PermissionTemplate) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (p *PermissionTemplate) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (p *PermissionTemplate) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if p.Name != "" {
|
||||
index["name"] = p.Name
|
||||
}
|
||||
|
||||
@@ -38,6 +38,8 @@ const (
|
||||
|
||||
// LabelSyncGeneration describes the generation synced from
|
||||
LabelSyncGeneration = "ux.oam.dev/synced-generation"
|
||||
// LabelSyncRevision describes the revision name synced from
|
||||
LabelSyncRevision = "ux.oam.dev/synced-revision"
|
||||
// LabelSyncNamespace describes the namespace synced from
|
||||
LabelSyncNamespace = "ux.oam.dev/from-namespace"
|
||||
)
|
||||
|
||||
@@ -18,7 +18,6 @@ package model
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
workflowv1alpha1 "github.com/kubevela/workflow/api/v1alpha1"
|
||||
@@ -51,7 +50,7 @@ type Workflow struct {
|
||||
|
||||
// WorkflowStep defines how to execute a workflow step.
|
||||
type WorkflowStep struct {
|
||||
WorkflowStepBase `json:",inline"`
|
||||
WorkflowStepBase `json:",inline" bson:",inline"`
|
||||
SubSteps []WorkflowStepBase `json:"subSteps,omitempty"`
|
||||
}
|
||||
|
||||
@@ -88,8 +87,8 @@ func (w *Workflow) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom primary key
|
||||
func (w *Workflow) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (w *Workflow) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if w.Name != "" {
|
||||
index["name"] = w.Name
|
||||
}
|
||||
@@ -100,7 +99,7 @@ func (w *Workflow) Index() map[string]string {
|
||||
index["envName"] = w.EnvName
|
||||
}
|
||||
if w.Default != nil {
|
||||
index["default"] = strconv.FormatBool(*w.Default)
|
||||
index["default"] = *w.Default
|
||||
}
|
||||
|
||||
return index
|
||||
@@ -128,7 +127,7 @@ type WorkflowRecord struct {
|
||||
|
||||
// WorkflowStepStatus is the workflow step status database model
|
||||
type WorkflowStepStatus struct {
|
||||
StepStatus `json:",inline"`
|
||||
StepStatus `json:",inline" bson:",inline"`
|
||||
SubStepsStatus []StepStatus `json:"subSteps,omitempty"`
|
||||
}
|
||||
|
||||
@@ -161,8 +160,8 @@ func (w *WorkflowRecord) PrimaryKey() string {
|
||||
}
|
||||
|
||||
// Index return custom primary key
|
||||
func (w *WorkflowRecord) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
func (w *WorkflowRecord) Index() map[string]interface{} {
|
||||
index := make(map[string]interface{})
|
||||
if w.Name != "" {
|
||||
index["name"] = w.Name
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ func CreateEnv(ctx context.Context, kubeClient client.Client, ds datastore.DataS
|
||||
env.Namespace = env.Name
|
||||
}
|
||||
|
||||
// create namespace at first
|
||||
// Creating the namespace at first.
|
||||
err = util.CreateOrUpdateNamespace(ctx, kubeClient, env.Namespace,
|
||||
util.MergeOverrideLabels(map[string]string{
|
||||
oam.LabelControlPlaneNamespaceUsage: oam.VelaNamespaceUsageEnv,
|
||||
|
||||
@@ -120,10 +120,10 @@ func pickEnv(envs []*model.Env, name string) (*model.Env, error) {
|
||||
return nil, bcode.ErrEnvNotExisted
|
||||
}
|
||||
|
||||
func pickEnvWorkflow(envs []*model.Workflow, name string) (*model.Workflow, error) {
|
||||
for _, e := range envs {
|
||||
if e.EnvName == name {
|
||||
return e, nil
|
||||
func pickEnvWorkflow(workflows []*model.Workflow, name string) (*model.Workflow, error) {
|
||||
for _, w := range workflows {
|
||||
if w.EnvName == name {
|
||||
return w, nil
|
||||
}
|
||||
}
|
||||
return nil, bcode.ErrWorkflowNotExist
|
||||
|
||||
@@ -106,7 +106,7 @@ func NewDatastore(cfg datastore.Config) (ds datastore.DataStore, err error) {
|
||||
return nil, fmt.Errorf("create mongodb datastore instance failure %w", err)
|
||||
}
|
||||
case "kubeapi":
|
||||
ds, err = kubeapi.New(context.Background(), cfg)
|
||||
ds, err = kubeapi.New(context.Background(), cfg, k8sClient)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create mongodb datastore instance failure %w", err)
|
||||
}
|
||||
|
||||
@@ -660,7 +660,7 @@ func ListWorkflowForApp(ctx context.Context, ds datastore.DataStore, appPrimaryK
|
||||
var workflow = model.Workflow{
|
||||
AppPrimaryKey: appPrimaryKey,
|
||||
}
|
||||
workflows, err := ds.List(ctx, &workflow, nil)
|
||||
workflows, err := ds.List(ctx, &workflow, &datastore.ListOptions{SortBy: []datastore.SortOption{{Key: "createTime", Order: datastore.SortOrderDescending}}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -67,6 +67,7 @@ type AddonService interface {
|
||||
DisableAddon(ctx context.Context, name string, force bool) error
|
||||
ListEnabledAddon(ctx context.Context) ([]*apis.AddonBaseStatus, error)
|
||||
UpdateAddon(ctx context.Context, name string, args apis.EnableAddonRequest) error
|
||||
Init(ctx context.Context) error
|
||||
}
|
||||
|
||||
// AddonImpl2AddonRes convert pkgaddon.UIData to the type apiserver need
|
||||
@@ -116,44 +117,35 @@ func AddonImpl2AddonRes(impl *pkgaddon.UIData, config *rest.Config) (*apis.Detai
|
||||
|
||||
// NewAddonService returns an addon service
|
||||
func NewAddonService(cacheTime time.Duration) AddonService {
|
||||
config, err := clients.GetKubeConfig()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
kubecli, err := clients.GetKubeClient()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
dc, err := clients.GetDiscoveryClient()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
ds := pkgaddon.NewRegistryDataStore(kubecli)
|
||||
cache := pkgaddon.NewCache(ds)
|
||||
|
||||
// TODO(@wonderflow): it's better to add a close channel here, but it should be fine as it's only invoke once in APIServer.
|
||||
go cache.DiscoverAndRefreshLoop(cacheTime)
|
||||
|
||||
return &addonServiceImpl{
|
||||
addonRegistryCache: cache,
|
||||
addonRegistryDS: ds,
|
||||
kubeClient: kubecli,
|
||||
config: config,
|
||||
apply: apply.NewAPIApplicator(kubecli),
|
||||
mutex: new(sync.RWMutex),
|
||||
discoveryClient: dc,
|
||||
cacheTime: cacheTime,
|
||||
mutex: new(sync.RWMutex),
|
||||
discoveryClient: dc,
|
||||
}
|
||||
}
|
||||
|
||||
type addonServiceImpl struct {
|
||||
cacheTime time.Duration
|
||||
addonRegistryCache *pkgaddon.Cache
|
||||
addonRegistryDS pkgaddon.RegistryDataStore
|
||||
kubeClient client.Client
|
||||
config *rest.Config
|
||||
apply apply.Applicator
|
||||
RegistryDS pkgaddon.RegistryDataStore `inject:"registryDatastore"`
|
||||
KubeClient client.Client `inject:"kubeClient"`
|
||||
KubeConfig *rest.Config `inject:"kubeConfig"`
|
||||
Apply apply.Applicator `inject:"apply"`
|
||||
discoveryClient *discovery.DiscoveryClient
|
||||
mutex *sync.RWMutex
|
||||
}
|
||||
|
||||
mutex *sync.RWMutex
|
||||
func (u *addonServiceImpl) Init(ctx context.Context) error {
|
||||
cache := pkgaddon.NewCache(u.RegistryDS)
|
||||
// TODO(@wonderflow): it's better to add a close channel here, but it should be fine as it's only invoke once in APIServer.
|
||||
go cache.DiscoverAndRefreshLoop(ctx, u.cacheTime)
|
||||
u.addonRegistryCache = cache
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetAddon will get addon information
|
||||
@@ -161,7 +153,7 @@ func (u *addonServiceImpl) GetAddon(ctx context.Context, name string, registry s
|
||||
var addon *pkgaddon.UIData
|
||||
var err error
|
||||
if registry == "" {
|
||||
registries, err := u.addonRegistryDS.ListRegistries(ctx)
|
||||
registries, err := u.RegistryDS.ListRegistries(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -175,7 +167,7 @@ func (u *addonServiceImpl) GetAddon(ctx context.Context, name string, registry s
|
||||
}
|
||||
}
|
||||
} else {
|
||||
addonRegistry, err := u.addonRegistryDS.GetRegistry(ctx, registry)
|
||||
addonRegistry, err := u.RegistryDS.GetRegistry(ctx, registry)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -189,9 +181,9 @@ func (u *addonServiceImpl) GetAddon(ctx context.Context, name string, registry s
|
||||
return nil, bcode.ErrAddonNotExist
|
||||
}
|
||||
|
||||
addon.UISchema = renderAddonCustomUISchema(ctx, u.kubeClient, name, renderDefaultUISchema(addon.APISchema))
|
||||
addon.UISchema = renderAddonCustomUISchema(ctx, u.KubeClient, name, renderDefaultUISchema(addon.APISchema))
|
||||
|
||||
a, err := AddonImpl2AddonRes(addon, u.config)
|
||||
a, err := AddonImpl2AddonRes(addon, u.KubeConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -199,12 +191,12 @@ func (u *addonServiceImpl) GetAddon(ctx context.Context, name string, registry s
|
||||
}
|
||||
|
||||
func (u *addonServiceImpl) StatusAddon(ctx context.Context, name string) (*apis.AddonStatusResponse, error) {
|
||||
status, err := pkgaddon.GetAddonStatus(ctx, u.kubeClient, name)
|
||||
status, err := pkgaddon.GetAddonStatus(ctx, u.KubeClient, name)
|
||||
if err != nil {
|
||||
return nil, bcode.ErrGetAddonApplication
|
||||
}
|
||||
var allClusters []apis.NameAlias
|
||||
clusters, err := multicluster.ListVirtualClusters(ctx, u.kubeClient)
|
||||
clusters, err := multicluster.ListVirtualClusters(ctx, u.KubeClient)
|
||||
if err != nil {
|
||||
klog.Errorf("err while list all clusters: %v", err)
|
||||
}
|
||||
@@ -235,7 +227,7 @@ func (u *addonServiceImpl) StatusAddon(ctx context.Context, name string) (*apis.
|
||||
}
|
||||
|
||||
var sec v1.Secret
|
||||
err = u.kubeClient.Get(ctx, client.ObjectKey{
|
||||
err = u.KubeClient.Get(ctx, client.ObjectKey{
|
||||
Namespace: types.DefaultKubeVelaNS,
|
||||
Name: addonutil.Addon2SecName(name),
|
||||
}, &sec)
|
||||
@@ -255,7 +247,7 @@ func (u *addonServiceImpl) StatusAddon(ctx context.Context, name string) (*apis.
|
||||
|
||||
func (u *addonServiceImpl) ListAddons(ctx context.Context, registry, query string) ([]*apis.DetailAddonResponse, error) {
|
||||
var addons []*pkgaddon.UIData
|
||||
rs, err := u.addonRegistryDS.ListRegistries(ctx)
|
||||
rs, err := u.RegistryDS.ListRegistries(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -300,7 +292,7 @@ func (u *addonServiceImpl) ListAddons(ctx context.Context, registry, query strin
|
||||
|
||||
var addonResources []*apis.DetailAddonResponse
|
||||
for _, a := range addons {
|
||||
addonRes, err := AddonImpl2AddonRes(a, u.config)
|
||||
addonRes, err := AddonImpl2AddonRes(a, u.KubeConfig)
|
||||
if err != nil {
|
||||
klog.Errorf("err while converting AddonImpl to DetailAddonResponse: %v", err)
|
||||
continue
|
||||
@@ -314,13 +306,13 @@ func (u *addonServiceImpl) ListAddons(ctx context.Context, registry, query strin
|
||||
}
|
||||
|
||||
func (u *addonServiceImpl) DeleteAddonRegistry(ctx context.Context, name string) error {
|
||||
return u.addonRegistryDS.DeleteRegistry(ctx, name)
|
||||
return u.RegistryDS.DeleteRegistry(ctx, name)
|
||||
}
|
||||
|
||||
func (u *addonServiceImpl) CreateAddonRegistry(ctx context.Context, req apis.CreateAddonRegistryRequest) (*apis.AddonRegistry, error) {
|
||||
r := addonRegistryModelFromCreateAddonRegistryRequest(req)
|
||||
|
||||
err := u.addonRegistryDS.AddRegistry(ctx, r)
|
||||
err := u.RegistryDS.AddRegistry(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -340,7 +332,7 @@ func convertAddonRegistry(r pkgaddon.Registry) *apis.AddonRegistry {
|
||||
}
|
||||
|
||||
func (u *addonServiceImpl) GetAddonRegistry(ctx context.Context, name string) (*apis.AddonRegistry, error) {
|
||||
r, err := u.addonRegistryDS.GetRegistry(ctx, name)
|
||||
r, err := u.RegistryDS.GetRegistry(ctx, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -348,7 +340,7 @@ func (u *addonServiceImpl) GetAddonRegistry(ctx context.Context, name string) (*
|
||||
}
|
||||
|
||||
func (u addonServiceImpl) UpdateAddonRegistry(ctx context.Context, name string, req apis.UpdateAddonRegistryRequest) (*apis.AddonRegistry, error) {
|
||||
r, err := u.addonRegistryDS.GetRegistry(ctx, name)
|
||||
r, err := u.RegistryDS.GetRegistry(ctx, name)
|
||||
if err != nil {
|
||||
return nil, bcode.ErrAddonRegistryNotExist
|
||||
}
|
||||
@@ -365,7 +357,7 @@ func (u addonServiceImpl) UpdateAddonRegistry(ctx context.Context, name string,
|
||||
r.Gitlab = req.Gitlab
|
||||
}
|
||||
|
||||
err = u.addonRegistryDS.UpdateRegistry(ctx, r)
|
||||
err = u.RegistryDS.UpdateRegistry(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -376,7 +368,7 @@ func (u addonServiceImpl) UpdateAddonRegistry(ctx context.Context, name string,
|
||||
func (u *addonServiceImpl) ListAddonRegistries(ctx context.Context) ([]*apis.AddonRegistry, error) {
|
||||
|
||||
var list []*apis.AddonRegistry
|
||||
registries, err := u.addonRegistryDS.ListRegistries(ctx)
|
||||
registries, err := u.RegistryDS.ListRegistries(ctx)
|
||||
if err != nil {
|
||||
// the storage configmap still not exist, don't return error add registry will create the configmap
|
||||
if errors2.IsNotFound(err) {
|
||||
@@ -396,7 +388,7 @@ func (u *addonServiceImpl) ListAddonRegistries(ctx context.Context) ([]*apis.Add
|
||||
|
||||
func (u *addonServiceImpl) EnableAddon(ctx context.Context, name string, args apis.EnableAddonRequest) error {
|
||||
var err error
|
||||
registries, err := u.addonRegistryDS.ListRegistries(ctx)
|
||||
registries, err := u.RegistryDS.ListRegistries(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -416,7 +408,7 @@ func (u *addonServiceImpl) EnableAddon(ctx context.Context, name string, args ap
|
||||
continue
|
||||
}
|
||||
// TODO: response the additional info to velaux users
|
||||
_, err = pkgaddon.EnableAddon(ctx, name, args.Version, u.kubeClient, u.discoveryClient, u.apply, u.config, r, args.Args, u.addonRegistryCache, pkgaddon.FilterDependencyRegistries(i, registries))
|
||||
_, err = pkgaddon.EnableAddon(ctx, name, args.Version, u.KubeClient, u.discoveryClient, u.Apply, u.KubeConfig, r, args.Args, u.addonRegistryCache, pkgaddon.FilterDependencyRegistries(i, registries))
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
@@ -441,7 +433,7 @@ func (u *addonServiceImpl) EnableAddon(ctx context.Context, name string, args ap
|
||||
}
|
||||
|
||||
func (u *addonServiceImpl) DisableAddon(ctx context.Context, name string, force bool) error {
|
||||
err := pkgaddon.DisableAddon(ctx, u.kubeClient, name, u.config, force)
|
||||
err := pkgaddon.DisableAddon(ctx, u.KubeClient, name, u.KubeConfig, force)
|
||||
if err != nil {
|
||||
klog.Errorf("delete application fail: %s", err.Error())
|
||||
return err
|
||||
@@ -451,7 +443,7 @@ func (u *addonServiceImpl) DisableAddon(ctx context.Context, name string, force
|
||||
|
||||
func (u *addonServiceImpl) ListEnabledAddon(ctx context.Context) ([]*apis.AddonBaseStatus, error) {
|
||||
apps := &v1beta1.ApplicationList{}
|
||||
if err := u.kubeClient.List(ctx, apps, client.InNamespace(types.DefaultKubeVelaNS), client.HasLabels{oam.LabelAddonName}); err != nil {
|
||||
if err := u.KubeClient.List(ctx, apps, client.InNamespace(types.DefaultKubeVelaNS), client.HasLabels{oam.LabelAddonName}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var response []*apis.AddonBaseStatus
|
||||
@@ -470,10 +462,9 @@ func (u *addonServiceImpl) ListEnabledAddon(ctx context.Context) ([]*apis.AddonB
|
||||
}
|
||||
|
||||
func (u *addonServiceImpl) UpdateAddon(ctx context.Context, name string, args apis.EnableAddonRequest) error {
|
||||
|
||||
var app v1beta1.Application
|
||||
// check addon application whether exist
|
||||
err := u.kubeClient.Get(ctx, client.ObjectKey{
|
||||
err := u.KubeClient.Get(ctx, client.ObjectKey{
|
||||
Namespace: types.DefaultKubeVelaNS,
|
||||
Name: addonutil.Addon2AppName(name),
|
||||
}, &app)
|
||||
@@ -481,22 +472,20 @@ func (u *addonServiceImpl) UpdateAddon(ctx context.Context, name string, args ap
|
||||
return err
|
||||
}
|
||||
|
||||
registries, err := u.addonRegistryDS.ListRegistries(ctx)
|
||||
registries, err := u.RegistryDS.ListRegistries(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i, r := range registries {
|
||||
// TODO: response the additional info to velaux users
|
||||
_, err = pkgaddon.EnableAddon(ctx, name, args.Version, u.kubeClient, u.discoveryClient, u.apply, u.config, r, args.Args, u.addonRegistryCache, pkgaddon.FilterDependencyRegistries(i, registries))
|
||||
_, err = pkgaddon.EnableAddon(ctx, name, args.Version, u.KubeClient, u.discoveryClient, u.Apply, u.KubeConfig, r, args.Args, u.addonRegistryCache, pkgaddon.FilterDependencyRegistries(i, registries))
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if errors.Is(err, pkgaddon.ErrNotExist) {
|
||||
continue
|
||||
}
|
||||
|
||||
// wrap this error with special bcode
|
||||
if errors.As(err, &pkgaddon.VersionUnMatchError{}) {
|
||||
return bcode.ErrAddonSystemVersionMismatch
|
||||
|
||||
@@ -41,7 +41,7 @@ import (
|
||||
velatypes "github.com/oam-dev/kubevela/apis/types"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/domain/model"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/domain/repository"
|
||||
syncconvert "github.com/oam-dev/kubevela/pkg/apiserver/event/sync/convert"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/event/sync/convert"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore"
|
||||
assembler "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/assembler/v1"
|
||||
apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1"
|
||||
@@ -51,6 +51,7 @@ import (
|
||||
"github.com/oam-dev/kubevela/pkg/oam"
|
||||
"github.com/oam-dev/kubevela/pkg/oam/discoverymapper"
|
||||
pkgUtils "github.com/oam-dev/kubevela/pkg/utils"
|
||||
"github.com/oam-dev/kubevela/pkg/utils/app"
|
||||
"github.com/oam-dev/kubevela/pkg/utils/apply"
|
||||
commonutil "github.com/oam-dev/kubevela/pkg/utils/common"
|
||||
)
|
||||
@@ -89,6 +90,7 @@ type ApplicationService interface {
|
||||
UpdateApplicationTrait(ctx context.Context, app *model.Application, component *model.ApplicationComponent, traitType string, req apisv1.UpdateApplicationTraitRequest) (*apisv1.ApplicationTrait, error)
|
||||
ListRevisions(ctx context.Context, appName, envName, status string, page, pageSize int) (*apisv1.ListRevisionsResponse, error)
|
||||
DetailRevision(ctx context.Context, appName, revisionName string) (*apisv1.DetailRevisionResponse, error)
|
||||
RollbackWithRevision(ctx context.Context, app *model.Application, revisionName string) (*apisv1.ApplicationRollbackResponse, error)
|
||||
Statistics(ctx context.Context, app *model.Application) (*apisv1.ApplicationStatisticsResponse, error)
|
||||
ListRecords(ctx context.Context, appName string) (*apisv1.ListWorkflowRecordsResponse, error)
|
||||
CompareApp(ctx context.Context, app *model.Application, compareReq apisv1.AppCompareReq) (*apisv1.AppCompareResponse, error)
|
||||
@@ -97,6 +99,7 @@ type ApplicationService interface {
|
||||
CreateApplicationTrigger(ctx context.Context, app *model.Application, req apisv1.CreateApplicationTriggerRequest) (*apisv1.ApplicationTriggerBase, error)
|
||||
ListApplicationTriggers(ctx context.Context, app *model.Application) ([]*apisv1.ApplicationTriggerBase, error)
|
||||
DeleteApplicationTrigger(ctx context.Context, app *model.Application, triggerName string) error
|
||||
UpdateApplicationTrigger(ctx context.Context, app *model.Application, token string, req apisv1.UpdateApplicationTriggerRequest) (*apisv1.ApplicationTriggerBase, error)
|
||||
}
|
||||
|
||||
type applicationServiceImpl struct {
|
||||
@@ -408,6 +411,18 @@ func (c *applicationServiceImpl) CreateApplication(ctx context.Context, req apis
|
||||
|
||||
// CreateApplicationTrigger create application trigger
|
||||
func (c *applicationServiceImpl) CreateApplicationTrigger(ctx context.Context, app *model.Application, req apisv1.CreateApplicationTriggerRequest) (*apisv1.ApplicationTriggerBase, error) {
|
||||
// checking the workflow
|
||||
_, err := c.WorkflowService.GetWorkflow(ctx, app, req.WorkflowName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if req.ComponentName != "" {
|
||||
_, err := c.GetApplicationComponent(ctx, app, req.ComponentName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
trigger := &model.ApplicationTrigger{
|
||||
AppPrimaryKey: app.Name,
|
||||
WorkflowName: req.WorkflowName,
|
||||
@@ -425,18 +440,7 @@ func (c *applicationServiceImpl) CreateApplicationTrigger(ctx context.Context, a
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &apisv1.ApplicationTriggerBase{
|
||||
WorkflowName: req.WorkflowName,
|
||||
Name: req.Name,
|
||||
Alias: req.Alias,
|
||||
Description: req.Description,
|
||||
Type: req.Type,
|
||||
PayloadType: req.PayloadType,
|
||||
Token: trigger.Token,
|
||||
ComponentName: trigger.ComponentName,
|
||||
CreateTime: trigger.CreateTime,
|
||||
UpdateTime: trigger.UpdateTime,
|
||||
}, nil
|
||||
return assembler.ConvertTrigger2DTO(*trigger), nil
|
||||
}
|
||||
|
||||
// DeleteApplicationTrigger delete application trigger
|
||||
@@ -455,6 +459,42 @@ func (c *applicationServiceImpl) DeleteApplicationTrigger(ctx context.Context, a
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateApplicationTrigger update application trigger
|
||||
func (c *applicationServiceImpl) UpdateApplicationTrigger(ctx context.Context, app *model.Application, token string, req apisv1.UpdateApplicationTriggerRequest) (*apisv1.ApplicationTriggerBase, error) {
|
||||
trigger := model.ApplicationTrigger{
|
||||
AppPrimaryKey: app.PrimaryKey(),
|
||||
Token: token,
|
||||
}
|
||||
if err := c.Store.Get(ctx, &trigger); err != nil {
|
||||
if errors.Is(err, datastore.ErrRecordNotExist) {
|
||||
return nil, bcode.ErrApplicationTriggerNotExist
|
||||
}
|
||||
klog.Warningf("get app trigger failure %s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
// checking the workflow
|
||||
_, err := c.WorkflowService.GetWorkflow(ctx, app, req.WorkflowName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if req.ComponentName != "" {
|
||||
_, err := c.GetApplicationComponent(ctx, app, req.ComponentName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
trigger.Alias = req.Alias
|
||||
trigger.ComponentName = req.ComponentName
|
||||
trigger.Description = req.Description
|
||||
trigger.WorkflowName = req.WorkflowName
|
||||
trigger.Registry = req.Registry
|
||||
trigger.PayloadType = req.PayloadType
|
||||
if err := c.Store.Put(ctx, &trigger); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return assembler.ConvertTrigger2DTO(trigger), nil
|
||||
}
|
||||
|
||||
// ListApplicationTrigger list application triggers
|
||||
func (c *applicationServiceImpl) ListApplicationTriggers(ctx context.Context, app *model.Application) ([]*apisv1.ApplicationTriggerBase, error) {
|
||||
trigger := &model.ApplicationTrigger{
|
||||
@@ -537,7 +577,9 @@ func (c *applicationServiceImpl) ListRecords(ctx context.Context, appName string
|
||||
AppPrimaryKey: appName,
|
||||
Finished: model.UnFinished,
|
||||
}
|
||||
records, err := c.Store.List(ctx, &record, &datastore.ListOptions{})
|
||||
records, err := c.Store.List(ctx, &record, &datastore.ListOptions{SortBy: []datastore.SortOption{
|
||||
{Key: "createTime", Order: datastore.SortOrderDescending},
|
||||
}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -603,7 +645,8 @@ func (c *applicationServiceImpl) DetailComponent(ctx context.Context, app *model
|
||||
return nil, err
|
||||
}
|
||||
var cd v1beta1.ComponentDefinition
|
||||
if err := c.KubeClient.Get(ctx, types.NamespacedName{Name: component.Type, Namespace: velatypes.DefaultKubeVelaNS}, &cd); err != nil {
|
||||
loadCtx := utils.WithProject(ctx, "")
|
||||
if err := c.KubeClient.Get(loadCtx, types.NamespacedName{Name: component.Type, Namespace: velatypes.DefaultKubeVelaNS}, &cd); err != nil {
|
||||
klog.Warningf("component definition %s get failure. %s", pkgUtils.Sanitize(component.Type), err.Error())
|
||||
}
|
||||
|
||||
@@ -698,16 +741,17 @@ func (c *applicationServiceImpl) Deploy(ctx context.Context, app *model.Applicat
|
||||
status = revision.Status
|
||||
}
|
||||
if status != model.RevisionStatusComplete && status != model.RevisionStatusTerminated && status != model.RevisionStatusFail {
|
||||
klog.Warningf("last app revision can not complete %s/%s", list[0].(*model.ApplicationRevision).AppPrimaryKey, list[0].(*model.ApplicationRevision).Version)
|
||||
klog.Warningf("last app revision can not complete %s/%s,the current status is %s", list[0].(*model.ApplicationRevision).AppPrimaryKey, list[0].(*model.ApplicationRevision).Version, status)
|
||||
return nil, bcode.ErrDeployConflict
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var appRevision = &model.ApplicationRevision{
|
||||
AppPrimaryKey: app.PrimaryKey(),
|
||||
Version: version,
|
||||
RevisionCRName: version,
|
||||
AppPrimaryKey: app.PrimaryKey(),
|
||||
Version: version,
|
||||
// Setting it when syncing the workflow status
|
||||
RevisionCRName: "",
|
||||
ApplyAppConfig: string(configByte),
|
||||
Status: model.RevisionStatusInit,
|
||||
DeployUser: userName,
|
||||
@@ -1067,7 +1111,8 @@ func (c *applicationServiceImpl) UpdateComponent(ctx context.Context, app *model
|
||||
|
||||
func (c *applicationServiceImpl) createComponent(ctx context.Context, app *model.Application, com apisv1.CreateComponentRequest, main bool) (*apisv1.ComponentBase, error) {
|
||||
var cd v1beta1.ComponentDefinition
|
||||
if err := c.KubeClient.Get(ctx, types.NamespacedName{Name: com.ComponentType, Namespace: velatypes.DefaultKubeVelaNS}, &cd); err != nil {
|
||||
loadCtx := utils.WithProject(ctx, "")
|
||||
if err := c.KubeClient.Get(loadCtx, types.NamespacedName{Name: com.ComponentType, Namespace: velatypes.DefaultKubeVelaNS}, &cd); err != nil {
|
||||
klog.Warningf("component definition %s get failure. %s", pkgUtils.Sanitize(com.ComponentType), err.Error())
|
||||
return nil, bcode.ErrComponentTypeNotSupport
|
||||
}
|
||||
@@ -1425,13 +1470,29 @@ func (c *applicationServiceImpl) CompareApp(ctx context.Context, appModel *model
|
||||
var base, compareTarget *v1beta1.Application
|
||||
var err error
|
||||
var envNameByRevision string
|
||||
|
||||
getRunningApp := func() *v1beta1.Application {
|
||||
var envName string
|
||||
if compareReq.CompareLatestWithRunning != nil {
|
||||
envName = compareReq.CompareLatestWithRunning.Env
|
||||
}
|
||||
if compareReq.CompareRevisionWithRunning != nil {
|
||||
envName = envNameByRevision
|
||||
}
|
||||
if envName == "" {
|
||||
return nil
|
||||
}
|
||||
app, err := c.GetApplicationCRInEnv(ctx, appModel, envName)
|
||||
if err != nil {
|
||||
klog.Errorf("failed to query the application CR %s", err.Error())
|
||||
return nil
|
||||
}
|
||||
return app
|
||||
}
|
||||
switch {
|
||||
case compareReq.CompareLatestWithRunning != nil:
|
||||
base, err = c.renderOAMApplication(ctx, appModel, "", compareReq.CompareLatestWithRunning.Env, "")
|
||||
if err != nil {
|
||||
klog.Errorf("failed to build the latest application %s", err.Error())
|
||||
break
|
||||
}
|
||||
base = getRunningApp()
|
||||
|
||||
case compareReq.CompareRevisionWithRunning != nil || compareReq.CompareRevisionWithLatest != nil:
|
||||
var revision = ""
|
||||
if compareReq.CompareRevisionWithRunning != nil {
|
||||
@@ -1448,23 +1509,9 @@ func (c *applicationServiceImpl) CompareApp(ctx context.Context, appModel *model
|
||||
}
|
||||
|
||||
switch {
|
||||
case compareReq.CompareLatestWithRunning != nil || compareReq.CompareRevisionWithRunning != nil:
|
||||
var envName string
|
||||
if compareReq.CompareLatestWithRunning != nil {
|
||||
envName = compareReq.CompareLatestWithRunning.Env
|
||||
}
|
||||
if compareReq.CompareRevisionWithRunning != nil {
|
||||
envName = envNameByRevision
|
||||
}
|
||||
if envName == "" {
|
||||
break
|
||||
}
|
||||
compareTarget, err = c.GetApplicationCRInEnv(ctx, appModel, envName)
|
||||
if err != nil {
|
||||
klog.Errorf("failed to query the application CR %s", err.Error())
|
||||
break
|
||||
}
|
||||
case compareReq.CompareRevisionWithLatest != nil:
|
||||
case compareReq.CompareRevisionWithRunning != nil:
|
||||
compareTarget = getRunningApp()
|
||||
case compareReq.CompareRevisionWithLatest != nil || compareReq.CompareLatestWithRunning != nil:
|
||||
compareTarget, err = c.renderOAMApplication(ctx, appModel, "", envNameByRevision, "")
|
||||
if err != nil {
|
||||
klog.Errorf("failed to build the latest application %s", err.Error())
|
||||
@@ -1625,7 +1672,7 @@ func (c *applicationServiceImpl) resetApp(ctx context.Context, targetApp *v1beta
|
||||
for _, comp := range targetComps {
|
||||
// add or update new app's components from old app
|
||||
if utils.StringsContain(readyToAdd, comp.Name) || utils.StringsContain(readyToUpdate, comp.Name) {
|
||||
compModel, err := syncconvert.FromCRComponent(appPrimaryKey, comp)
|
||||
compModel, err := convert.FromCRComponent(appPrimaryKey, comp)
|
||||
if err != nil {
|
||||
return &apisv1.AppResetResponse{}, bcode.ErrInvalidProperties
|
||||
}
|
||||
@@ -1650,6 +1697,75 @@ func (c *applicationServiceImpl) resetApp(ctx context.Context, targetApp *v1beta
|
||||
return &apisv1.AppResetResponse{IsReset: true}, nil
|
||||
}
|
||||
|
||||
func (c *applicationServiceImpl) RollbackWithRevision(ctx context.Context, application *model.Application, revisionVersion string) (*apisv1.ApplicationRollbackResponse, error) {
|
||||
revision, err := c.DetailRevision(ctx, application.Name, revisionVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
appCR, err := c.GetApplicationCRInEnv(ctx, application, revision.EnvName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var publishVersion = utils.GenerateVersion(revision.WorkflowName)
|
||||
noRevision := false
|
||||
var rollbackApplication *v1beta1.Application
|
||||
if appCR != nil {
|
||||
// The RevisionCRName is incorrect in the old version, ignore it.
|
||||
if revision.RevisionCRName == revision.Version || revision.RevisionCRName == "" {
|
||||
noRevision = true
|
||||
} else {
|
||||
_, appCR, err := app.RollbackApplicationWithRevision(ctx, c.KubeClient, appCR.Name, appCR.Namespace, revision.RevisionCRName, publishVersion)
|
||||
if err != nil {
|
||||
switch {
|
||||
case errors.Is(err, app.ErrNotMatchRevision):
|
||||
noRevision = true
|
||||
case errors.Is(err, app.ErrRevisionNotChange):
|
||||
return nil, bcode.ErrApplicationRevisionConflict
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
rollbackApplication = appCR
|
||||
}
|
||||
}
|
||||
|
||||
// Rollback by the local revision
|
||||
if appCR == nil || noRevision {
|
||||
rollBackApp := &v1beta1.Application{}
|
||||
if err := yaml.Unmarshal([]byte(revision.ApplyAppConfig), rollBackApp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
oam.SetPublishVersion(rollBackApp, publishVersion)
|
||||
if appCR != nil {
|
||||
rollBackApp.ResourceVersion = appCR.ResourceVersion
|
||||
} else {
|
||||
rollBackApp.ResourceVersion = ""
|
||||
}
|
||||
err = c.Apply.Apply(ctx, rollBackApp)
|
||||
if err != nil {
|
||||
klog.Errorf("rollback the app %s failure %s", application.PrimaryKey(), err.Error())
|
||||
return nil, err
|
||||
}
|
||||
rollbackApplication = rollBackApp
|
||||
}
|
||||
|
||||
work, _, err := convert.FromCRWorkflow(ctx, c.KubeClient, application.PrimaryKey(), rollbackApplication, revision.EnvName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// The deploy version is the primary key of the revision
|
||||
if rollbackApplication.Annotations[oam.AnnotationDeployVersion] == "" {
|
||||
rollbackApplication.Annotations[oam.AnnotationDeployVersion] = publishVersion
|
||||
}
|
||||
record, err := c.WorkflowService.CreateWorkflowRecord(ctx, application, rollbackApplication, &work)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create workflow record failure %w", err)
|
||||
}
|
||||
return &apisv1.ApplicationRollbackResponse{
|
||||
WorkflowRecord: assembler.ConvertFromRecordModel(record).WorkflowRecordBase,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func dryRunApplication(ctx context.Context, c commonutil.Args, app *v1beta1.Application) (bytes.Buffer, error) {
|
||||
var buff = bytes.Buffer{}
|
||||
if _, err := fmt.Fprintf(&buff, "---\n# Application(%s) \n---\n\n", app.Name); err != nil {
|
||||
@@ -1693,9 +1809,7 @@ func dryRunApplication(ctx context.Context, c commonutil.Args, app *v1beta1.Appl
|
||||
// ignore the workflow spec
|
||||
func ignoreSomeParams(o *v1beta1.Application) {
|
||||
var defaultApplication = v1beta1.Application{}
|
||||
// only compare the spec without the workflow
|
||||
defaultApplication.Spec = o.Spec
|
||||
defaultApplication.Spec.Workflow = nil
|
||||
defaultApplication.Name = o.Name
|
||||
defaultApplication.Namespace = o.Namespace
|
||||
|
||||
|
||||
@@ -208,15 +208,17 @@ var _ = Describe("Test application service function", func() {
|
||||
appModel, err := appService.GetApplication(context.TODO(), testApp)
|
||||
Expect(err).Should(BeNil())
|
||||
_, err = appService.CreateApplicationTrigger(context.TODO(), appModel, v1.CreateApplicationTriggerRequest{
|
||||
Name: "trigger-name",
|
||||
Name: "trigger-name",
|
||||
WorkflowName: repository.ConvertWorkflowName("app-dev"),
|
||||
})
|
||||
Expect(err).Should(BeNil())
|
||||
base, err := appService.CreateApplicationTrigger(context.TODO(), appModel, v1.CreateApplicationTriggerRequest{
|
||||
Name: "trigger-name-2",
|
||||
ComponentName: "trigger-component",
|
||||
ComponentName: "component-name",
|
||||
WorkflowName: repository.ConvertWorkflowName("app-dev"),
|
||||
})
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(base.ComponentName).Should(Equal("trigger-component"))
|
||||
Expect(base.ComponentName).Should(Equal("component-name"))
|
||||
})
|
||||
|
||||
It("Test ListTriggers function", func() {
|
||||
@@ -299,6 +301,33 @@ var _ = Describe("Test application service function", func() {
|
||||
Expect(cmp.Diff(len(detailResponse.Traits), 2)).Should(BeEmpty())
|
||||
})
|
||||
|
||||
It("Test UpdateTrigger function", func() {
|
||||
appModel, err := appService.GetApplication(context.TODO(), testApp)
|
||||
Expect(err).Should(BeNil())
|
||||
triggers, err := appService.ListApplicationTriggers(context.TODO(), appModel)
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(len(triggers)).Should(Equal(2))
|
||||
_, err = appService.UpdateApplicationTrigger(context.TODO(), appModel, triggers[1].Token, v1.UpdateApplicationTriggerRequest{
|
||||
ComponentName: "notfound",
|
||||
WorkflowName: repository.ConvertWorkflowName("app-dev"),
|
||||
})
|
||||
Expect(err).Should(Equal(bcode.ErrApplicationComponentNotExist))
|
||||
_, err = appService.UpdateApplicationTrigger(context.TODO(), appModel, triggers[1].Token, v1.UpdateApplicationTriggerRequest{
|
||||
WorkflowName: "notfound",
|
||||
})
|
||||
Expect(err).Should(Equal(bcode.ErrWorkflowNotExist))
|
||||
base, err := appService.UpdateApplicationTrigger(context.TODO(), appModel, triggers[1].Token, v1.UpdateApplicationTriggerRequest{
|
||||
Alias: triggers[1].Alias,
|
||||
Description: triggers[1].Description,
|
||||
ComponentName: "test2",
|
||||
WorkflowName: repository.ConvertWorkflowName("app-dev"),
|
||||
PayloadType: triggers[1].PayloadType,
|
||||
Registry: triggers[1].Registry,
|
||||
})
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(cmp.Diff(base.ComponentName, "test2")).Should(BeEmpty())
|
||||
})
|
||||
|
||||
It("Test DetailComponent function", func() {
|
||||
appModel, err := appService.GetApplication(context.TODO(), testApp)
|
||||
Expect(err).Should(BeNil())
|
||||
@@ -532,8 +561,10 @@ var _ = Describe("Test application service function", func() {
|
||||
})
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(cmp.Diff(compareResponse.IsDiff, true)).Should(BeEmpty())
|
||||
Expect(cmp.Diff(compareResponse.TargetAppYAML, "")).Should(BeEmpty())
|
||||
Expect(cmp.Diff(compareResponse.BaseAppYAML, "")).ShouldNot(BeEmpty())
|
||||
// The target represents the latest config
|
||||
Expect(cmp.Diff(compareResponse.TargetAppYAML, "")).ShouldNot(BeEmpty())
|
||||
// The base represents the running config
|
||||
Expect(cmp.Diff(compareResponse.BaseAppYAML, "")).Should(BeEmpty())
|
||||
|
||||
By("compare when app's env add target, should return false")
|
||||
_, err = targetService.CreateTarget(context.TODO(), v1.CreateTargetRequest{Name: "dev-target1", Project: appModel.Project, Cluster: &v1.ClusterTarget{ClusterName: "local", Namespace: "dev-target1"}})
|
||||
|
||||
@@ -387,7 +387,10 @@ func (c *clusterServiceImpl) DeleteKubeCluster(ctx context.Context, clusterName
|
||||
cluster, err := c.getClusterFromDataStore(ctx, clusterName)
|
||||
if err != nil {
|
||||
if errors.Is(err, datastore.ErrRecordNotExist) {
|
||||
return nil, bcode.ErrClusterNotFoundInDataStore
|
||||
if err = multicluster.DetachCluster(ctx, c.K8sClient, clusterName); err != nil {
|
||||
return nil, bcode.ErrClusterNotFoundInDataStore
|
||||
}
|
||||
return &apis.ClusterBase{Name: clusterName}, nil
|
||||
}
|
||||
return nil, errors.Wrapf(err, "failed to found cluster %s in data store", clusterName)
|
||||
}
|
||||
|
||||
@@ -98,6 +98,27 @@ var _ = Describe("Test cluster service function", func() {
|
||||
Expect(err).Should(Equal(bcode.ErrClusterNotFoundInDataStore))
|
||||
})
|
||||
|
||||
It("Test delete kube cluster", func() {
|
||||
service := clusterServiceImpl{
|
||||
Store: ds,
|
||||
caches: cache,
|
||||
K8sClient: k8sClient,
|
||||
}
|
||||
Expect(createClusterSecret("prism-cluster", "prism-alias")).Should(Succeed())
|
||||
Expect(ds.Add(ctx, &model.Cluster{Name: "prism-cluster", Alias: "prism-alias", Icon: "prism-icon"})).Should(Succeed())
|
||||
resp, err := service.DeleteKubeCluster(ctx, "prism-cluster")
|
||||
Expect(err).Should(Succeed())
|
||||
Expect(resp.Name).Should(Equal("prism-cluster"))
|
||||
Expect(resp.Alias).Should(Equal("prism-alias"))
|
||||
Expect(resp.Icon).Should(Equal("prism-icon"))
|
||||
_, err = service.DeleteKubeCluster(ctx, "non-exist-cluster")
|
||||
Expect(err).Should(Equal(bcode.ErrClusterNotFoundInDataStore))
|
||||
Expect(createClusterSecret("secret-exist-cm-non-exist-cluster", "secret-exist-cm-non-exist-cluster")).Should(Succeed())
|
||||
resp, err = service.DeleteKubeCluster(ctx, "secret-exist-cm-non-exist-cluster")
|
||||
Expect(err).Should(Succeed())
|
||||
Expect(resp.Name).Should(Equal("secret-exist-cm-non-exist-cluster"))
|
||||
})
|
||||
|
||||
It("Test list kube clusters", func() {
|
||||
service := clusterServiceImpl{
|
||||
Store: ds,
|
||||
|
||||
@@ -22,15 +22,14 @@ import (
|
||||
"sort"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/klog/v2"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/types"
|
||||
apis "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/utils"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode"
|
||||
"github.com/oam-dev/kubevela/pkg/config"
|
||||
"github.com/oam-dev/kubevela/pkg/utils"
|
||||
"github.com/oam-dev/kubevela/pkg/utils/apply"
|
||||
)
|
||||
|
||||
@@ -62,7 +61,8 @@ type configServiceImpl struct {
|
||||
|
||||
// ListTemplates list the config templates
|
||||
func (u *configServiceImpl) ListTemplates(ctx context.Context, project, scope string) ([]*apis.ConfigTemplate, error) {
|
||||
queryTemplates, err := u.Factory.ListTemplates(ctx, types.DefaultKubeVelaNS, scope)
|
||||
listCtx := utils.WithProject(ctx, "")
|
||||
queryTemplates, err := u.Factory.ListTemplates(listCtx, types.DefaultKubeVelaNS, scope)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -100,7 +100,8 @@ func (u *configServiceImpl) GetTemplate(ctx context.Context, tem config.Namespac
|
||||
if tem.Namespace == "" {
|
||||
tem.Namespace = types.DefaultKubeVelaNS
|
||||
}
|
||||
template, err := u.Factory.LoadTemplate(ctx, tem.Name, tem.Namespace)
|
||||
getCtx := utils.WithProject(ctx, "")
|
||||
template, err := u.Factory.LoadTemplate(getCtx, tem.Name, tem.Namespace)
|
||||
if err != nil {
|
||||
if errors.Is(err, config.ErrTemplateNotFound) {
|
||||
return nil, bcode.ErrTemplateNotFound
|
||||
@@ -133,9 +134,14 @@ func (u *configServiceImpl) CreateConfig(ctx context.Context, project string, re
|
||||
return nil, err
|
||||
}
|
||||
ns = pro.GetNamespace()
|
||||
if err := utils.CreateNamespace(ctx, u.KubeClient, ns); err != nil && !apierrors.IsAlreadyExists(err) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
exist, err := u.Factory.IsExist(ctx, ns, req.Name)
|
||||
if err != nil {
|
||||
klog.Errorf("check config name is exist failure %s", err.Error())
|
||||
return nil, bcode.ErrConfigExist
|
||||
}
|
||||
if exist {
|
||||
return nil, bcode.ErrConfigExist
|
||||
}
|
||||
var properties = make(map[string]interface{})
|
||||
if err := json.Unmarshal([]byte(req.Properties), &properties); err != nil {
|
||||
@@ -156,9 +162,6 @@ func (u *configServiceImpl) CreateConfig(ctx context.Context, project string, re
|
||||
return nil, err
|
||||
}
|
||||
if err := u.Factory.CreateOrUpdateConfig(ctx, configItem, ns); err != nil {
|
||||
if errors.Is(err, config.ErrConfigExist) {
|
||||
return nil, bcode.ErrConfigExist
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return convertConfig(project, *configItem), nil
|
||||
@@ -196,9 +199,12 @@ func (u *configServiceImpl) UpdateConfig(ctx context.Context, project string, na
|
||||
return nil, err
|
||||
}
|
||||
if err := u.Factory.CreateOrUpdateConfig(ctx, configItem, ns); err != nil {
|
||||
if errors.Is(err, config.ErrConfigExist) {
|
||||
if errors.Is(err, config.ErrChangeTemplate) {
|
||||
return nil, bcode.ErrChangeTemplate
|
||||
}
|
||||
if errors.Is(err, config.ErrChangeSecretType) {
|
||||
return nil, bcode.ErrChangeSecretType
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return convertConfig(project, *configItem), nil
|
||||
@@ -210,6 +216,7 @@ func (u *configServiceImpl) ListConfigs(ctx context.Context, project string, tem
|
||||
var list []*apis.Config
|
||||
scope := ""
|
||||
var projectNamespace string
|
||||
listCtx := utils.WithProject(ctx, "")
|
||||
if project != "" {
|
||||
scope = "project"
|
||||
pro, err := u.ProjectService.GetProject(ctx, project)
|
||||
@@ -218,7 +225,7 @@ func (u *configServiceImpl) ListConfigs(ctx context.Context, project string, tem
|
||||
}
|
||||
projectNamespace = pro.GetNamespace()
|
||||
// query the configs belong to the project scope from the system namespace
|
||||
configs, err := u.Factory.ListConfigs(ctx, pro.GetNamespace(), template, "", true)
|
||||
configs, err := u.Factory.ListConfigs(listCtx, pro.GetNamespace(), template, "", true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -227,7 +234,7 @@ func (u *configServiceImpl) ListConfigs(ctx context.Context, project string, tem
|
||||
}
|
||||
}
|
||||
|
||||
configs, err := u.Factory.ListConfigs(ctx, types.DefaultKubeVelaNS, template, scope, true)
|
||||
configs, err := u.Factory.ListConfigs(listCtx, types.DefaultKubeVelaNS, template, scope, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ template: {
|
||||
|
||||
parameter: {
|
||||
//+usage=The name of Terraform Provider for Alibaba Cloud
|
||||
name: *"default" | string
|
||||
name: string
|
||||
//+usage=Get ALICLOUD_ACCESS_KEY per this guide https://help.aliyun.com/knowledge_detail/38738.html
|
||||
ALICLOUD_ACCESS_KEY: string
|
||||
//+usage=Get ALICLOUD_SECRET_KEY per this guide https://help.aliyun.com/knowledge_detail/38738.html
|
||||
@@ -144,7 +144,7 @@ var _ = Describe("Test config service", func() {
|
||||
Expect(err).ToNot(BeNil())
|
||||
var paramErr = &script.ParameterError{}
|
||||
Expect(errors.As(err, ¶mErr)).To(Equal(true))
|
||||
Expect(paramErr.Name).To(Equal("ALICLOUD_ACCESS_KEY"))
|
||||
Expect(paramErr.Name).To(Equal("name"))
|
||||
Expect(paramErr.Message).To(Equal("This parameter is required"))
|
||||
|
||||
config, err := configService.CreateConfig(context.TODO(), "", v1.CreateConfigRequest{
|
||||
|
||||
@@ -239,7 +239,9 @@ func (p *envServiceImpl) UpdateEnv(ctx context.Context, name string, req apisv1.
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := managePrivilegesForEnvironment(ctx, p.KubeClient, env, false); err != nil {
|
||||
// Updating the role and role binding can't use the login user permissions.
|
||||
updateRoleCtx := utils.WithProject(ctx, "")
|
||||
if err := managePrivilegesForEnvironment(updateRoleCtx, p.KubeClient, env, false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -289,12 +291,14 @@ func (p *envServiceImpl) CreateEnv(ctx context.Context, req apisv1.CreateEnvRequ
|
||||
}
|
||||
}
|
||||
|
||||
err = repository.CreateEnv(ctx, p.KubeClient, p.Store, newEnv)
|
||||
// Creating the namespace can't use the login user permissions.
|
||||
createNamespaceCtx := utils.WithProject(ctx, "")
|
||||
err = repository.CreateEnv(createNamespaceCtx, p.KubeClient, p.Store, newEnv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := managePrivilegesForEnvironment(ctx, p.KubeClient, newEnv, false); err != nil {
|
||||
if err := managePrivilegesForEnvironment(createNamespaceCtx, p.KubeClient, newEnv, false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
@@ -45,8 +45,9 @@ func NewHelmService() HelmService {
|
||||
type HelmService interface {
|
||||
ListChartNames(ctx context.Context, url string, secretName string, skipCache bool) ([]string, error)
|
||||
ListChartVersions(ctx context.Context, url string, chartName string, secretName string, skipCache bool) (repo.ChartVersions, error)
|
||||
GetChartValues(ctx context.Context, url string, chartName string, version string, secretName string, skipCache bool) (map[string]interface{}, error)
|
||||
ListChartValuesFiles(ctx context.Context, url string, chartName string, version string, secretName string, repoType string, skipCache bool) (map[string]string, error)
|
||||
ListChartRepo(ctx context.Context, projectName string) (*v1.ChartRepoResponseList, error)
|
||||
GetChartValues(ctx context.Context, repoURL string, chartName string, version string, secretName string, repoType string, skipCache bool) (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
type defaultHelmImpl struct {
|
||||
@@ -99,7 +100,7 @@ func (d defaultHelmImpl) ListChartVersions(ctx context.Context, repoURL string,
|
||||
return chartVersions, nil
|
||||
}
|
||||
|
||||
func (d defaultHelmImpl) GetChartValues(ctx context.Context, repoURL string, chartName string, version string, secretName string, skipCache bool) (map[string]interface{}, error) {
|
||||
func (d defaultHelmImpl) ListChartValuesFiles(ctx context.Context, repoURL string, chartName string, version string, secretName string, repoType string, skipCache bool) (map[string]string, error) {
|
||||
if !utils.IsValidURL(repoURL) {
|
||||
return nil, bcode.ErrRepoInvalidURL
|
||||
}
|
||||
@@ -111,13 +112,33 @@ func (d defaultHelmImpl) GetChartValues(ctx context.Context, repoURL string, cha
|
||||
return nil, bcode.ErrRepoBasicAuth
|
||||
}
|
||||
}
|
||||
v, err := d.helper.GetValuesFromChart(repoURL, chartName, version, skipCache, opts)
|
||||
v, err := d.helper.GetValuesFromChart(repoURL, chartName, version, skipCache, repoType, opts)
|
||||
if err != nil {
|
||||
klog.Errorf("cannot fetch chart values repo: %s, chart: %s, version: %s, error: %s", utils.Sanitize(repoURL), utils.Sanitize(chartName), utils.Sanitize(version), err.Error())
|
||||
return nil, bcode.ErrGetChartValues
|
||||
}
|
||||
res := make(map[string]interface{}, len(v))
|
||||
flattenKey("", v, res)
|
||||
return v.Data, nil
|
||||
}
|
||||
|
||||
func (d defaultHelmImpl) GetChartValues(ctx context.Context, repoURL string, chartName string, version string, secretName string, repoType string, skipCache bool) (map[string]interface{}, error) {
|
||||
if !utils.IsValidURL(repoURL) {
|
||||
return nil, bcode.ErrRepoInvalidURL
|
||||
}
|
||||
var opts *common.HTTPOption
|
||||
var err error
|
||||
if len(secretName) != 0 {
|
||||
opts, err = helm.SetHTTPOption(ctx, d.K8sClient, types2.NamespacedName{Namespace: types.DefaultKubeVelaNS, Name: secretName})
|
||||
if err != nil {
|
||||
return nil, bcode.ErrRepoBasicAuth
|
||||
}
|
||||
}
|
||||
v, err := d.helper.GetValuesFromChart(repoURL, chartName, version, skipCache, repoType, opts)
|
||||
if err != nil {
|
||||
klog.Errorf("cannot fetch chart values repo: %s, chart: %s, version: %s, error: %s", utils.Sanitize(repoURL), utils.Sanitize(chartName), utils.Sanitize(version), err.Error())
|
||||
return nil, bcode.ErrGetChartValues
|
||||
}
|
||||
res := make(map[string]interface{}, len(v.Values))
|
||||
flattenKey("", v.Values, res)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -213,7 +213,7 @@ var _ = Describe("test helm usecasae", func() {
|
||||
Expect(len(versions)).Should(BeEquivalentTo(1))
|
||||
Expect(versions[0].Version).Should(BeEquivalentTo("8.8.23"))
|
||||
|
||||
values, err := u.GetChartValues(ctx, mockServer.URL, "mysql", "8.8.23", "repo-secret", false)
|
||||
values, err := u.ListChartValuesFiles(ctx, mockServer.URL, "mysql", "8.8.23", "repo-secret", "helm", false)
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(values).ShouldNot(BeNil())
|
||||
Expect(len(values)).ShouldNot(BeEquivalentTo(0))
|
||||
@@ -228,7 +228,7 @@ var _ = Describe("test helm usecasae", func() {
|
||||
_, err = u.ListChartVersions(ctx, "http://127.0.0.1:8080", "mysql", "repo-secret-notExist", false)
|
||||
Expect(err).ShouldNot(BeNil())
|
||||
|
||||
_, err = u.GetChartValues(ctx, "http://127.0.0.1:8080", "mysql", "8.8.23", "repo-secret-notExist", false)
|
||||
_, err = u.ListChartValuesFiles(ctx, "http://127.0.0.1:8080", "mysql", "8.8.23", "repo-secret-notExist", "helm", false)
|
||||
Expect(err).ShouldNot(BeNil())
|
||||
})
|
||||
})
|
||||
|
||||
@@ -17,6 +17,7 @@ limitations under the License.
|
||||
package service
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -31,7 +32,9 @@ import (
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/domain/model"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore"
|
||||
apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1"
|
||||
apiutils "github.com/oam-dev/kubevela/pkg/apiserver/utils"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode"
|
||||
"github.com/oam-dev/kubevela/pkg/auth"
|
||||
"github.com/oam-dev/kubevela/pkg/multicluster"
|
||||
"github.com/oam-dev/kubevela/pkg/utils"
|
||||
)
|
||||
@@ -291,6 +294,10 @@ func (p *projectServiceImpl) DeleteProject(ctx context.Context, name string) err
|
||||
if err := p.Store.Delete(ctx, &model.Project{Name: name}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := managePrivilegesForProject(ctx, p.K8sClient, &model.Project{Name: name}, true); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -322,10 +329,10 @@ func (p *projectServiceImpl) CreateProject(ctx context.Context, req apisv1.Creat
|
||||
if namespace == "" {
|
||||
namespace = req.Name
|
||||
}
|
||||
if err := utils.CreateNamespace(ctx, p.K8sClient, namespace); err != nil && !apierrors.IsAlreadyExists(err) {
|
||||
createCtx := apiutils.WithProject(ctx, "")
|
||||
if err := utils.CreateNamespace(createCtx, p.K8sClient, namespace); err != nil && !apierrors.IsAlreadyExists(err) {
|
||||
return nil, bcode.ErrProjectNamespaceFail
|
||||
}
|
||||
|
||||
newProject := &model.Project{
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
@@ -338,6 +345,10 @@ func (p *projectServiceImpl) CreateProject(ctx context.Context, req apisv1.Creat
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := managePrivilegesForProject(createCtx, p.K8sClient, newProject, false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := p.RbacService.SyncDefaultRoleAndUsersForProject(ctx, newProject); err != nil {
|
||||
klog.Errorf("fail to sync the default role and users for the project: %s", err.Error())
|
||||
}
|
||||
@@ -345,6 +356,22 @@ func (p *projectServiceImpl) CreateProject(ctx context.Context, req apisv1.Creat
|
||||
return ConvertProjectModel2Base(newProject, user), nil
|
||||
}
|
||||
|
||||
// managePrivilegesForProject grant or revoke privileges for project
|
||||
func managePrivilegesForProject(ctx context.Context, cli client.Client, project *model.Project, revoke bool) error {
|
||||
p := &auth.ApplicationPrivilege{Cluster: types.ClusterLocalName, Namespace: project.Namespace}
|
||||
identity := &auth.Identity{Groups: []string{apiutils.KubeVelaProjectGroupPrefix + project.Name}}
|
||||
writer := &bytes.Buffer{}
|
||||
f, msg := auth.GrantPrivileges, "GrantPrivileges"
|
||||
if revoke {
|
||||
f, msg = auth.RevokePrivileges, "RevokePrivileges"
|
||||
}
|
||||
if err := f(ctx, cli, []auth.PrivilegeDescription{p}, identity, writer); err != nil {
|
||||
return err
|
||||
}
|
||||
klog.Infof("%s: %s", msg, writer.String())
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateProject update project
|
||||
func (p *projectServiceImpl) UpdateProject(ctx context.Context, projectName string, req apisv1.UpdateProjectRequest) (*apisv1.ProjectBase, error) {
|
||||
project, err := p.GetProject(ctx, projectName)
|
||||
@@ -373,6 +400,9 @@ func (p *projectServiceImpl) UpdateProject(ctx context.Context, projectName stri
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := managePrivilegesForProject(ctx, p.K8sClient, project, false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ConvertProjectModel2Base(project, user), nil
|
||||
}
|
||||
|
||||
@@ -510,7 +540,8 @@ func (p *projectServiceImpl) UpdateProjectUser(ctx context.Context, projectName
|
||||
|
||||
func (p *projectServiceImpl) ListTerraformProviders(ctx context.Context, projectName string) ([]*apisv1.TerraformProvider, error) {
|
||||
l := &terraformapi.ProviderList{}
|
||||
if err := p.K8sClient.List(ctx, l, client.InNamespace(types.ProviderNamespace)); err != nil {
|
||||
listCtx := apiutils.WithProject(ctx, "")
|
||||
if err := p.K8sClient.List(listCtx, l, client.InNamespace(types.ProviderNamespace)); err != nil {
|
||||
if meta.IsNoMatchError(err) {
|
||||
return []*apisv1.TerraformProvider{}, nil
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ var defaultProjectPermissionTemplate = []*model.PermissionTemplate{
|
||||
Name: "pipeline-management",
|
||||
Alias: "Pipeline Management",
|
||||
Resources: []string{
|
||||
"project:{projectName}/pipeline:*",
|
||||
"project:{projectName}/pipeline:*/*",
|
||||
},
|
||||
Actions: []string{"*"},
|
||||
Effect: "Allow",
|
||||
|
||||
@@ -49,7 +49,7 @@ func InitServiceBean(c config.Config) []interface{} {
|
||||
pipelineService := NewPipelineService(c.WorkflowVersion)
|
||||
pipelineRunService := NewPipelineRunService()
|
||||
contextService := NewContextService()
|
||||
needInitData = []DataInit{clusterService, userService, rbacService, projectService, targetService, systemInfoService}
|
||||
needInitData = []DataInit{clusterService, userService, rbacService, projectService, targetService, systemInfoService, addonService}
|
||||
return []interface{}{
|
||||
clusterService, rbacService, projectService, envService, targetService, workflowService, oamApplicationService,
|
||||
velaQLService, definitionService, addonService, envBindingService, systemInfoService, helmService, userService,
|
||||
|
||||
@@ -104,7 +104,7 @@ func NewDatastore(cfg datastore.Config) (ds datastore.DataStore, err error) {
|
||||
return nil, fmt.Errorf("create mongodb datastore instance failure %w", err)
|
||||
}
|
||||
case "kubeapi":
|
||||
ds, err = kubeapi.New(context.Background(), cfg)
|
||||
ds, err = kubeapi.New(context.Background(), cfg, k8sClient)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create mongodb datastore instance failure %w", err)
|
||||
}
|
||||
|
||||
@@ -148,10 +148,11 @@ func (dt *targetServiceImpl) CreateTarget(ctx context.Context, req apisv1.Create
|
||||
if req.Cluster == nil {
|
||||
req.Cluster = &apisv1.ClusterTarget{ClusterName: multicluster.ClusterLocalName, Namespace: req.Name}
|
||||
}
|
||||
if err := repository.CreateTargetNamespace(ctx, dt.K8sClient, req.Cluster.ClusterName, req.Cluster.Namespace, req.Name); err != nil {
|
||||
createTargetCtx := utils.WithProject(ctx, "")
|
||||
if err := repository.CreateTargetNamespace(createTargetCtx, dt.K8sClient, req.Cluster.ClusterName, req.Cluster.Namespace, req.Name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := managePrivilegesForTarget(ctx, dt.K8sClient, &target, false); err != nil {
|
||||
if err := managePrivilegesForTarget(createTargetCtx, dt.K8sClient, &target, false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err := repository.CreateTarget(ctx, dt.Store, &target)
|
||||
@@ -167,7 +168,8 @@ func (dt *targetServiceImpl) UpdateTarget(ctx context.Context, target *model.Tar
|
||||
return nil, err
|
||||
}
|
||||
// Compatible with historical data, if the existing Target has not been authorized, perform an update action.
|
||||
if err := managePrivilegesForTarget(ctx, dt.K8sClient, targetModel, false); err != nil {
|
||||
updateCtx := utils.WithProject(ctx, "")
|
||||
if err := managePrivilegesForTarget(updateCtx, dt.K8sClient, targetModel, false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dt.DetailTarget(ctx, targetModel)
|
||||
@@ -257,7 +259,9 @@ func managePrivilegesForTarget(ctx context.Context, cli client.Client, target *m
|
||||
f, msg = auth.RevokePrivileges, "RevokePrivileges"
|
||||
}
|
||||
if err := f(ctx, cli, []auth.PrivilegeDescription{p}, identity, writer); err != nil {
|
||||
return err
|
||||
klog.Warningf("error encountered for %s: %s", msg, err.Error())
|
||||
// for some cluster, authn/authz is not supported, ignore errors
|
||||
return client.IgnoreNotFound(err)
|
||||
}
|
||||
klog.Infof("%s: %s", msg, writer.String())
|
||||
return nil
|
||||
|
||||
@@ -18,6 +18,7 @@ package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// guaranteePolicyExist check the slice whether contain the target policy, if not put it in.
|
||||
@@ -57,16 +58,36 @@ func extractPolicyListAndProperty(property map[string]interface{}) ([]string, ma
|
||||
if policies == nil {
|
||||
return nil, property, nil
|
||||
}
|
||||
list, ok := policies.([]interface{})
|
||||
if !ok {
|
||||
list, err := InterfaceSlice(policies)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("the policies incorrect")
|
||||
}
|
||||
if len(list) == 0 {
|
||||
return nil, property, nil
|
||||
}
|
||||
res := []string{}
|
||||
var res []string
|
||||
for _, i := range list {
|
||||
res = append(res, i.(string))
|
||||
}
|
||||
return res, property, nil
|
||||
}
|
||||
|
||||
// InterfaceSlice interface to []interface{}
|
||||
func InterfaceSlice(slice interface{}) ([]interface{}, error) {
|
||||
if arr, ok := slice.([]interface{}); ok {
|
||||
return arr, nil
|
||||
}
|
||||
s := reflect.ValueOf(slice)
|
||||
if s.Kind() != reflect.Slice {
|
||||
return nil, fmt.Errorf("InterfaceSlice() given a non-slice type")
|
||||
}
|
||||
// Keep the distinction between nil and empty slice input
|
||||
if s.IsNil() {
|
||||
return nil, nil
|
||||
}
|
||||
ret := make([]interface{}, s.Len())
|
||||
for i := 0; i < s.Len(); i++ {
|
||||
ret[i] = s.Index(i).Interface()
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
@@ -174,61 +174,87 @@ func TestExtractPolicyListAndProperty(t *testing.T) {
|
||||
testCases := []struct {
|
||||
input string
|
||||
res struct {
|
||||
policies []string
|
||||
properties map[string]interface{}
|
||||
noError bool
|
||||
policies []string
|
||||
properties map[string]interface{}
|
||||
noUnmarshallError bool
|
||||
noExtractError bool
|
||||
}
|
||||
}{
|
||||
{
|
||||
input: `{"policies": null, "components": null}`,
|
||||
res: struct {
|
||||
policies []string
|
||||
properties map[string]interface{}
|
||||
noUnmarshallError bool
|
||||
noExtractError bool
|
||||
}{policies: nil, properties: map[string]interface{}{
|
||||
"policies": nil,
|
||||
"components": nil,
|
||||
}, noUnmarshallError: true, noExtractError: true},
|
||||
},
|
||||
{
|
||||
input: `{"policies": "policy1", "components": "comp1"}`,
|
||||
res: struct {
|
||||
policies []string
|
||||
properties map[string]interface{}
|
||||
noUnmarshallError bool
|
||||
noExtractError bool
|
||||
}{policies: nil, properties: nil, noUnmarshallError: true, noExtractError: false},
|
||||
},
|
||||
{
|
||||
input: `{"policies":["policy1","policy2"], "components": ["comp1"]}`,
|
||||
res: struct {
|
||||
policies []string
|
||||
properties map[string]interface{}
|
||||
noError bool
|
||||
policies []string
|
||||
properties map[string]interface{}
|
||||
noUnmarshallError bool
|
||||
noExtractError bool
|
||||
}{policies: []string{"policy1", "policy2"}, properties: map[string]interface{}{
|
||||
"policies": []interface{}{"policy1", "policy2"},
|
||||
"components": []interface{}{"comp1"},
|
||||
}, noError: true},
|
||||
}, noUnmarshallError: true, noExtractError: true},
|
||||
},
|
||||
{
|
||||
input: `{"policies":["policy1"], "components": ["comp1"]}`,
|
||||
res: struct {
|
||||
policies []string
|
||||
properties map[string]interface{}
|
||||
noError bool
|
||||
policies []string
|
||||
properties map[string]interface{}
|
||||
noUnmarshallError bool
|
||||
noExtractError bool
|
||||
}{policies: []string{"policy1"}, properties: map[string]interface{}{
|
||||
"policies": []interface{}{"policy1"},
|
||||
"components": []interface{}{"comp1"},
|
||||
}, noError: true},
|
||||
}, noUnmarshallError: true, noExtractError: true},
|
||||
},
|
||||
{
|
||||
input: `{"policies":["policy1", "components": ["comp1"]}`,
|
||||
res: struct {
|
||||
policies []string
|
||||
properties map[string]interface{}
|
||||
noError bool
|
||||
}{noError: false},
|
||||
policies []string
|
||||
properties map[string]interface{}
|
||||
noUnmarshallError bool
|
||||
noExtractError bool
|
||||
}{noUnmarshallError: false, noExtractError: false},
|
||||
},
|
||||
{
|
||||
input: `{}`,
|
||||
res: struct {
|
||||
policies []string
|
||||
properties map[string]interface{}
|
||||
noError bool
|
||||
}{policies: nil, properties: nil, noError: true},
|
||||
policies []string
|
||||
properties map[string]interface{}
|
||||
noUnmarshallError bool
|
||||
noExtractError bool
|
||||
}{policies: nil, properties: nil, noUnmarshallError: true, noExtractError: true},
|
||||
},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
var in = map[string]interface{}{}
|
||||
err := json.Unmarshal([]byte(testCase.input), &in)
|
||||
if testCase.res.noError {
|
||||
if testCase.res.noUnmarshallError {
|
||||
assert.NilError(t, err)
|
||||
} else {
|
||||
assert.Equal(t, err != nil, true)
|
||||
continue
|
||||
}
|
||||
policy, properties, err := extractPolicyListAndProperty(in)
|
||||
if testCase.res.noError {
|
||||
if testCase.res.noExtractError {
|
||||
assert.NilError(t, err)
|
||||
} else {
|
||||
assert.Equal(t, err != nil, true)
|
||||
|
||||
@@ -29,6 +29,7 @@ import (
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/types"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/domain/model"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/domain/repository"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/datastore"
|
||||
apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/interfaces/api/dto/v1"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode"
|
||||
@@ -168,6 +169,7 @@ var _ = Describe("Test application service function", func() {
|
||||
Name: "test-acr",
|
||||
PayloadType: "acr",
|
||||
Type: "webhook",
|
||||
WorkflowName: repository.ConvertWorkflowName("webhook-dev"),
|
||||
ComponentName: "component-name-webhook",
|
||||
})
|
||||
Expect(err).Should(BeNil())
|
||||
@@ -202,6 +204,7 @@ var _ = Describe("Test application service function", func() {
|
||||
PayloadType: "acr",
|
||||
Type: "webhook",
|
||||
ComponentName: "component-name-webhook",
|
||||
WorkflowName: repository.ConvertWorkflowName("webhook-dev"),
|
||||
Registry: "test-enterprise-registry.test-region.cr.aliyuncs.com",
|
||||
})
|
||||
Expect(err).Should(BeNil())
|
||||
@@ -236,6 +239,7 @@ var _ = Describe("Test application service function", func() {
|
||||
PayloadType: "harbor",
|
||||
Type: "webhook",
|
||||
ComponentName: "component-name-webhook",
|
||||
WorkflowName: repository.ConvertWorkflowName("webhook-dev"),
|
||||
})
|
||||
Expect(err).Should(BeNil())
|
||||
|
||||
@@ -274,6 +278,7 @@ var _ = Describe("Test application service function", func() {
|
||||
PayloadType: "dockerhub",
|
||||
Type: "webhook",
|
||||
ComponentName: "component-name-webhook",
|
||||
WorkflowName: repository.ConvertWorkflowName("webhook-dev"),
|
||||
})
|
||||
Expect(err).Should(BeNil())
|
||||
|
||||
@@ -306,6 +311,7 @@ var _ = Describe("Test application service function", func() {
|
||||
PayloadType: "jfrog",
|
||||
Type: "webhook",
|
||||
ComponentName: "component-name-webhook",
|
||||
WorkflowName: repository.ConvertWorkflowName("webhook-dev"),
|
||||
})
|
||||
Expect(err).Should(BeNil())
|
||||
jfrogBody := apisv1.HandleApplicationTriggerJFrogRequest{
|
||||
|
||||
@@ -290,7 +290,9 @@ func (w *workflowServiceImpl) ListWorkflowRecords(ctx context.Context, workflow
|
||||
AppPrimaryKey: workflow.AppPrimaryKey,
|
||||
WorkflowName: workflow.Name,
|
||||
}
|
||||
records, err := w.Store.List(ctx, &record, &datastore.ListOptions{Page: page, PageSize: pageSize})
|
||||
records, err := w.Store.List(ctx, &record, &datastore.ListOptions{Page: page, PageSize: pageSize, SortBy: []datastore.SortOption{
|
||||
{Key: "createTime", Order: datastore.SortOrderAscending},
|
||||
}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -386,6 +388,7 @@ func (w *workflowServiceImpl) SyncWorkflowRecord(ctx context.Context) error {
|
||||
Namespace: record.Namespace,
|
||||
}, app); err != nil {
|
||||
if apierrors.IsNotFound(err) {
|
||||
klog.Warningf("can't find the application %s/%s, set the record status to terminated", appName, record.Namespace)
|
||||
if err := w.setRecordToTerminated(ctx, record.AppPrimaryKey, record.Name); err != nil {
|
||||
klog.Errorf("failed to set the record status to terminated %s", err.Error())
|
||||
}
|
||||
@@ -399,6 +402,11 @@ func (w *workflowServiceImpl) SyncWorkflowRecord(ctx context.Context) error {
|
||||
continue
|
||||
}
|
||||
|
||||
// This means the application workflow has not run.
|
||||
if app.Generation > app.Status.ObservedGeneration {
|
||||
continue
|
||||
}
|
||||
|
||||
// there is a ":" in the default app revision
|
||||
recordName := strings.Replace(app.Status.Workflow.AppRevision, ":", "-", 1)
|
||||
|
||||
@@ -407,6 +415,9 @@ func (w *workflowServiceImpl) SyncWorkflowRecord(ctx context.Context) error {
|
||||
if err := w.syncWorkflowStatus(ctx, record.AppPrimaryKey, app, record.Name, app.Name, nil); err != nil {
|
||||
klog.ErrorS(err, "failed to sync workflow status", "oam app name", appName, "workflow name", record.WorkflowName, "record name", record.Name)
|
||||
}
|
||||
}
|
||||
|
||||
if record.Name == oam.GetPublishVersion(app) {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -436,6 +447,7 @@ func (w *workflowServiceImpl) SyncWorkflowRecord(ctx context.Context) error {
|
||||
var appRevision v1beta1.ApplicationRevision
|
||||
if err := w.KubeClient.Get(ctx, types.NamespacedName{Namespace: app.Namespace, Name: revision.RevisionCRName}, &appRevision); err != nil {
|
||||
if apierrors.IsNotFound(err) {
|
||||
klog.Warningf("can't find the application revision %s/%s, set the record status to terminated", revision.RevisionCRName, app.Namespace)
|
||||
if err := w.setRecordToTerminated(ctx, record.AppPrimaryKey, record.Name); err != nil {
|
||||
klog.Errorf("failed to set the record status to terminated %s", err.Error())
|
||||
}
|
||||
@@ -456,7 +468,7 @@ func (w *workflowServiceImpl) SyncWorkflowRecord(ctx context.Context) error {
|
||||
record.AppPrimaryKey,
|
||||
&appRevision.Spec.Application,
|
||||
record.Name,
|
||||
revision.RevisionCRName,
|
||||
appRevision.Name,
|
||||
appRevision.Status.WorkflowContext,
|
||||
); err != nil {
|
||||
klog.ErrorS(err, "failed to sync workflow status", "oam app name", appName, "workflow name", record.WorkflowName, "record name", record.Name)
|
||||
@@ -538,10 +550,10 @@ func (w *workflowServiceImpl) syncWorkflowStatus(ctx context.Context,
|
||||
record.Message = status.Message
|
||||
record.Mode = status.Mode
|
||||
|
||||
if cb := app.Status.Workflow.ContextBackend; cb != nil && workflowContext == nil {
|
||||
if cb := app.Status.Workflow.ContextBackend; cb != nil && workflowContext == nil && cb.Namespace != "" && cb.Name != "" {
|
||||
var cm corev1.ConfigMap
|
||||
if err := w.KubeClient.Get(ctx, types.NamespacedName{Namespace: cb.Namespace, Name: cb.Name}, &cm); err != nil {
|
||||
klog.Error(err, "failed to load the context values", "Application", app.Name)
|
||||
klog.Errorf("failed to load the context values of the application %s:%s", app.Name, err.Error())
|
||||
}
|
||||
record.ContextValue = cm.Data
|
||||
}
|
||||
@@ -583,6 +595,9 @@ func (w *workflowServiceImpl) syncWorkflowStatus(ctx context.Context,
|
||||
}
|
||||
|
||||
revision.Status = generateRevisionStatus(status.Phase)
|
||||
if app.Status.LatestRevision != nil {
|
||||
revision.RevisionCRName = app.Status.LatestRevision.Name
|
||||
}
|
||||
if err := w.Store.Put(ctx, revision); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -651,7 +666,7 @@ func (w *workflowServiceImpl) CreateWorkflowRecord(ctx context.Context, appModel
|
||||
}
|
||||
|
||||
if err := w.Store.Add(ctx, workflowRecord); err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("failed to create the workflow record %s: %w", workflowRecord.Name, err)
|
||||
}
|
||||
|
||||
if err := resetRevisionsAndRecords(ctx, w.Store, appModel.PrimaryKey(), workflow.Name, app.Annotations[oam.AnnotationDeployVersion], app.Annotations[oam.AnnotationPublishVersion]); err != nil {
|
||||
@@ -851,8 +866,8 @@ func (w *workflowServiceImpl) RollbackRecord(ctx context.Context, appModel *mode
|
||||
if len(revisions) == 0 {
|
||||
return nil, bcode.ErrApplicationNoReadyRevision
|
||||
}
|
||||
revisionVersion = revisions[0].Index()["version"]
|
||||
klog.Infof("select lastest complete revision %s", revisions[0].Index()["version"])
|
||||
revisionVersion = pkgUtils.ToString(revisions[0].Index()["version"])
|
||||
klog.Infof("select lastest complete revision %s", revisionVersion)
|
||||
}
|
||||
|
||||
var record = &model.WorkflowRecord{
|
||||
|
||||
@@ -48,6 +48,7 @@ var _ = Describe("Test workflow service functions", func() {
|
||||
projectService *projectServiceImpl
|
||||
envService *envServiceImpl
|
||||
envBinding *envBindingServiceImpl
|
||||
targetService *targetServiceImpl
|
||||
testProject = "workflow-project"
|
||||
ds datastore.DataStore
|
||||
)
|
||||
@@ -60,6 +61,7 @@ var _ = Describe("Test workflow service functions", func() {
|
||||
rbacService := &rbacServiceImpl{Store: ds}
|
||||
projectService = &projectServiceImpl{Store: ds, RbacService: rbacService, K8sClient: k8sClient}
|
||||
envService = &envServiceImpl{Store: ds, KubeClient: k8sClient, ProjectService: projectService}
|
||||
targetService = &targetServiceImpl{Store: ds, K8sClient: k8sClient}
|
||||
envBinding = &envBindingServiceImpl{
|
||||
Store: ds,
|
||||
WorkflowService: workflowService,
|
||||
@@ -77,11 +79,20 @@ var _ = Describe("Test workflow service functions", func() {
|
||||
ProjectService: projectService,
|
||||
EnvService: envService,
|
||||
EnvBindingService: envBinding,
|
||||
WorkflowService: workflowService,
|
||||
}
|
||||
})
|
||||
It("Test CreateWorkflow function", func() {
|
||||
|
||||
_, err := projectService.CreateProject(context.TODO(), apisv1.CreateProjectRequest{Name: testProject})
|
||||
Expect(err).Should(BeNil())
|
||||
_, err = targetService.CreateTarget(context.TODO(), apisv1.CreateTargetRequest{
|
||||
Name: "dev-1", Project: testProject, Cluster: &apisv1.ClusterTarget{ClusterName: "local", Namespace: "dev-1"}})
|
||||
Expect(err).Should(BeNil())
|
||||
|
||||
_, err = envService.CreateEnv(context.TODO(), apisv1.CreateEnvRequest{Name: "dev", Namespace: "dev-1", Targets: []string{"dev-1"}, Project: testProject})
|
||||
Expect(err).Should(BeNil())
|
||||
|
||||
reqApp := apisv1.CreateApplicationRequest{
|
||||
Name: appName,
|
||||
Project: testProject,
|
||||
@@ -259,6 +270,7 @@ var _ = Describe("Test workflow service functions", func() {
|
||||
app.Status.Workflow.Finished = true
|
||||
err = workflowService.KubeClient.Create(ctx, app.DeepCopy())
|
||||
Expect(err).Should(BeNil())
|
||||
app.Status.ObservedGeneration = 1
|
||||
err = workflowService.KubeClient.Status().Patch(ctx, app, client.Merge)
|
||||
Expect(err).Should(BeNil())
|
||||
err = workflowService.SyncWorkflowRecord(ctx)
|
||||
|
||||
@@ -89,7 +89,7 @@ func NewDatastore(cfg datastore.Config) (ds datastore.DataStore, err error) {
|
||||
return nil, fmt.Errorf("create mongodb datastore instance failure %w", err)
|
||||
}
|
||||
case "kubeapi":
|
||||
ds, err = kubeapi.New(context.Background(), cfg)
|
||||
ds, err = kubeapi.New(context.Background(), cfg, k8sClient)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create mongodb datastore instance failure %w", err)
|
||||
}
|
||||
|
||||
@@ -21,14 +21,13 @@ import (
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
client2 "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
||||
"github.com/oam-dev/kubevela/apis/types"
|
||||
"github.com/oam-dev/kubevela/pkg/oam"
|
||||
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/infrastructure/clients"
|
||||
"github.com/oam-dev/kubevela/pkg/multicluster"
|
||||
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/domain/model"
|
||||
@@ -56,8 +55,9 @@ var waitBackOff = wait.Backoff{
|
||||
|
||||
// InfoCalculateCronJob is the cronJob to calculate the system info store in db
|
||||
type InfoCalculateCronJob struct {
|
||||
Store datastore.DataStore `inject:"datastore"`
|
||||
cron *cron.Cron
|
||||
KubeClient client.Client `inject:"kubeClient"`
|
||||
Store datastore.DataStore `inject:"datastore"`
|
||||
cron *cron.Cron
|
||||
}
|
||||
|
||||
// Start start the worker
|
||||
@@ -230,12 +230,8 @@ func (i InfoCalculateCronJob) calculateAppInfo(ctx context.Context) (int, []stri
|
||||
}
|
||||
|
||||
func (i InfoCalculateCronJob) calculateAddonInfo(ctx context.Context) (map[string]string, error) {
|
||||
client, err := clients.GetKubeClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
apps := &v1beta1.ApplicationList{}
|
||||
if err := client.List(ctx, apps, client2.InNamespace(types.DefaultKubeVelaNS), client2.HasLabels{oam.LabelAddonName}); err != nil {
|
||||
if err := i.KubeClient.List(ctx, apps, client.InNamespace(types.DefaultKubeVelaNS), client.HasLabels{oam.LabelAddonName}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res := map[string]string{}
|
||||
@@ -257,11 +253,7 @@ func (i InfoCalculateCronJob) calculateAddonInfo(ctx context.Context) (map[strin
|
||||
}
|
||||
|
||||
func (i InfoCalculateCronJob) calculateClusterInfo(ctx context.Context) (int, error) {
|
||||
client, err := clients.GetKubeClient()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
cs, err := multicluster.ListVirtualClusters(ctx, client)
|
||||
cs, err := multicluster.ListVirtualClusters(ctx, i.KubeClient)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
@@ -83,7 +83,8 @@ var _ = Describe("Test calculate cronJob", func() {
|
||||
testProject = "test-cronjob-project"
|
||||
mockDataInDs()
|
||||
i = InfoCalculateCronJob{
|
||||
Store: ds,
|
||||
Store: ds,
|
||||
KubeClient: k8sClient,
|
||||
}
|
||||
systemInfo := model.SystemInfo{InstallID: "test-id", EnableCollection: true}
|
||||
Expect(ds.Add(ctx, &systemInfo)).Should(SatisfyAny(BeNil(), DataExistMatcher{}))
|
||||
|
||||
@@ -19,7 +19,6 @@ package sync
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"k8s.io/klog/v2"
|
||||
@@ -31,8 +30,8 @@ import (
|
||||
)
|
||||
|
||||
type cached struct {
|
||||
generation int64
|
||||
targets int64
|
||||
revision string
|
||||
targets int64
|
||||
}
|
||||
|
||||
// initCache will initialize the cache
|
||||
@@ -49,8 +48,8 @@ func (c *CR2UX) initCache(ctx context.Context) error {
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
gen, ok := app.Labels[model.LabelSyncGeneration]
|
||||
if !ok || gen == "" {
|
||||
revision, ok := app.Labels[model.LabelSyncRevision]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
namespace := app.Labels[model.LabelSyncNamespace]
|
||||
@@ -58,10 +57,9 @@ func (c *CR2UX) initCache(ctx context.Context) error {
|
||||
if strings.HasSuffix(app.Name, namespace) {
|
||||
key = app.Name
|
||||
}
|
||||
generation, _ := strconv.ParseInt(gen, 10, 64)
|
||||
|
||||
// we should check targets if we synced from app status
|
||||
c.syncCache(key, generation, 0)
|
||||
c.syncCache(key, revision, 0)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -79,8 +77,10 @@ func (c *CR2UX) shouldSync(ctx context.Context, targetApp *v1beta1.Application,
|
||||
}
|
||||
|
||||
// if no LabelSourceOfTruth label, it means the app is existing ones, check the existing labels and annotations
|
||||
if _, appName := targetApp.Annotations[oam.AnnotationAppName]; appName {
|
||||
return false
|
||||
if targetApp.Annotations != nil {
|
||||
if _, exist := targetApp.Annotations[oam.AnnotationAppName]; exist {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
key := formatAppComposedName(targetApp.Name, targetApp.Namespace)
|
||||
@@ -91,16 +91,15 @@ func (c *CR2UX) shouldSync(ctx context.Context, targetApp *v1beta1.Application,
|
||||
_, _, err := c.getApp(ctx, targetApp.Name, targetApp.Namespace)
|
||||
if del || err != nil {
|
||||
c.cache.Delete(key)
|
||||
} else if cd.generation == targetApp.Generation {
|
||||
klog.Infof("app %s/%s with generation(%v) hasn't updated, ignore the sync event..", targetApp.Name, targetApp.Namespace, targetApp.Generation)
|
||||
} else if cd.revision == getRevision(*targetApp) {
|
||||
klog.V(5).Infof("app %s/%s with resource revision(%v) hasn't updated, ignore the sync event..", targetApp.Name, targetApp.Namespace, targetApp.ResourceVersion)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *CR2UX) syncCache(key string, generation, targets int64) {
|
||||
func (c *CR2UX) syncCache(key string, revision string, targets int64) {
|
||||
// update cache
|
||||
c.cache.Store(key, &cached{generation: generation, targets: targets})
|
||||
c.cache.Store(key, &cached{revision: revision, targets: targets})
|
||||
}
|
||||
|
||||
@@ -68,33 +68,36 @@ var _ = Describe("Test Cache", func() {
|
||||
app1 := &v1beta1.Application{}
|
||||
app1.Name = "app1"
|
||||
app1.Namespace = "app1-ns"
|
||||
app1.Generation = 1
|
||||
Expect(cr2ux.shouldSync(ctx, app1, false)).Should(BeEquivalentTo(true))
|
||||
|
||||
app2 := &v1beta1.Application{}
|
||||
app2.Name = "app2"
|
||||
app2.Namespace = "app2-ns"
|
||||
app2.Generation = 1
|
||||
app2.Status.LatestRevision = &common.Revision{Name: "v1"}
|
||||
|
||||
Expect(cr2ux.shouldSync(ctx, app2, false)).Should(BeEquivalentTo(true))
|
||||
|
||||
// Only need to sync once.
|
||||
cr2ux.syncCache(formatAppComposedName(app2.Name, app2.Namespace), "v1", 1)
|
||||
Expect(cr2ux.shouldSync(ctx, app2, false)).Should(BeEquivalentTo(false))
|
||||
|
||||
app3 := &v1beta1.Application{}
|
||||
app3.Name = "app3"
|
||||
app3.Namespace = "app3-ns"
|
||||
app3.Generation = 3
|
||||
app3.ResourceVersion = "3"
|
||||
app3.Labels = map[string]string{
|
||||
model.LabelSyncGeneration: "1",
|
||||
model.LabelSyncNamespace: "app3-ns",
|
||||
model.LabelSourceOfTruth: model.FromUX,
|
||||
model.LabelSourceOfTruth: model.FromUX,
|
||||
}
|
||||
|
||||
Expect(cr2ux.shouldSync(ctx, app3, false)).Should(BeEquivalentTo(false))
|
||||
|
||||
Expect(ds.Put(ctx, &model.Application{Name: "app1", Labels: map[string]string{
|
||||
model.LabelSyncGeneration: "1",
|
||||
model.LabelSyncNamespace: "app1-ns",
|
||||
model.LabelSyncRevision: "v1",
|
||||
model.LabelSyncNamespace: "app1-ns",
|
||||
}})).Should(BeNil())
|
||||
cr2ux.syncCache(formatAppComposedName(app1.Name, app1.Namespace), 1, 0)
|
||||
cr2ux.syncCache(formatAppComposedName(app1.Name, app1.Namespace), "v1", 0)
|
||||
app1.Status.LatestRevision = &common.Revision{Name: "v1"}
|
||||
Expect(cr2ux.shouldSync(ctx, app1, false)).Should(BeEquivalentTo(false))
|
||||
Expect(cr2ux.shouldSync(ctx, app1, true)).Should(BeEquivalentTo(true))
|
||||
Expect(ds.Delete(ctx, &model.Application{Name: "app1"})).Should(BeNil())
|
||||
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
||||
apitypes "github.com/oam-dev/kubevela/apis/types"
|
||||
@@ -45,11 +46,7 @@ func (c *CR2UX) ConvertApp2DatastoreApp(ctx context.Context, targetApp *v1beta1.
|
||||
}
|
||||
sourceOfTruth := model.FromCR
|
||||
if _, ok := targetApp.Labels[oam.LabelAddonName]; ok && strings.HasPrefix(targetApp.Name, "addon-") && targetApp.Namespace == apitypes.DefaultKubeVelaNS {
|
||||
project = v1.CreateProjectRequest{
|
||||
Name: model.DefaultSystemProject,
|
||||
Alias: model.DefaultSystemProjectAlias,
|
||||
Namespace: targetApp.Namespace,
|
||||
}
|
||||
project = c.generateSystemProject(ctx, targetApp.Namespace)
|
||||
sourceOfTruth = model.FromInner
|
||||
}
|
||||
|
||||
@@ -61,6 +58,7 @@ func (c *CR2UX) ConvertApp2DatastoreApp(ctx context.Context, targetApp *v1beta1.
|
||||
Labels: map[string]string{
|
||||
model.LabelSyncNamespace: targetApp.Namespace,
|
||||
model.LabelSyncGeneration: strconv.FormatInt(targetApp.Generation, 10),
|
||||
model.LabelSyncRevision: getRevision(*targetApp),
|
||||
model.LabelSourceOfTruth: sourceOfTruth,
|
||||
},
|
||||
}
|
||||
@@ -86,6 +84,7 @@ func (c *CR2UX) ConvertApp2DatastoreApp(ctx context.Context, targetApp *v1beta1.
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
klog.V(5).Infof("generate the environment %s for the application %s", env.Name, targetApp.Name)
|
||||
dsApp.Env = env
|
||||
if newProject != "" {
|
||||
project = v1.CreateProjectRequest{
|
||||
@@ -117,11 +116,10 @@ func (c *CR2UX) ConvertApp2DatastoreApp(ctx context.Context, targetApp *v1beta1.
|
||||
}
|
||||
|
||||
// 5. convert workflow
|
||||
wf, steps, err := convert.FromCRWorkflow(ctx, cli, appMeta.PrimaryKey(), targetApp)
|
||||
wf, steps, err := convert.FromCRWorkflow(ctx, cli, appMeta.PrimaryKey(), targetApp, dsApp.Env.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
wf.EnvName = dsApp.Env.Name
|
||||
dsApp.Workflow = &wf
|
||||
|
||||
// 6. convert policy, some policies are references in workflow step, we need to sync all the outside policy to make that work
|
||||
@@ -148,6 +146,8 @@ func (c *CR2UX) ConvertApp2DatastoreApp(ctx context.Context, targetApp *v1beta1.
|
||||
// 7. convert the revision
|
||||
if revision := convert.FromCRApplicationRevision(ctx, cli, targetApp, *dsApp.Workflow, dsApp.Env.Name); revision != nil {
|
||||
dsApp.Revision = revision
|
||||
} else {
|
||||
klog.Warningf("can't generate the application revision(%s) for the app %s", getRevision(*targetApp), targetApp.Name)
|
||||
}
|
||||
// 8. convert the workflow record
|
||||
if record := convert.FromCRWorkflowRecord(targetApp, *dsApp.Workflow, dsApp.Revision); record != nil {
|
||||
@@ -156,6 +156,27 @@ func (c *CR2UX) ConvertApp2DatastoreApp(ctx context.Context, targetApp *v1beta1.
|
||||
return dsApp, nil
|
||||
}
|
||||
|
||||
// In order to maintain compatibility with old data,
|
||||
// if there is a project named addons, continue to use it, but change the alias to System.
|
||||
func (c *CR2UX) generateSystemProject(ctx context.Context, ns string) v1.CreateProjectRequest {
|
||||
var pro = model.Project{Name: "addons"}
|
||||
if err := c.ds.Get(ctx, &pro); err == nil {
|
||||
if pro.Alias == "Addons" {
|
||||
pro.Alias = model.DefaultSystemProjectAlias
|
||||
pro.Namespace = ns
|
||||
if err := c.ds.Put(ctx, &pro); err != nil {
|
||||
klog.Warningf("failed to update the project alias to System:%s", err.Error())
|
||||
}
|
||||
}
|
||||
return v1.CreateProjectRequest{Name: pro.Name, Alias: pro.Alias, Namespace: pro.Namespace}
|
||||
}
|
||||
return v1.CreateProjectRequest{
|
||||
Name: model.DefaultSystemProject,
|
||||
Alias: model.DefaultSystemProjectAlias,
|
||||
Namespace: ns,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CR2UX) generateEnv(ctx context.Context, defaultProject string, envNamespace string, envTargetNames map[string]string) (*model.Env, string, error) {
|
||||
existEnv := &model.Env{Namespace: envNamespace}
|
||||
existEnvs, err := c.ds.List(ctx, existEnv, nil)
|
||||
@@ -169,7 +190,7 @@ func (c *CR2UX) generateEnv(ctx context.Context, defaultProject string, envNames
|
||||
env.Targets = append(env.Targets, name)
|
||||
}
|
||||
}
|
||||
return env, "", nil
|
||||
return env, env.Project, nil
|
||||
}
|
||||
|
||||
// generate new environment
|
||||
@@ -211,3 +232,17 @@ func (c *CR2UX) generateEnv(ctx context.Context, defaultProject string, envNames
|
||||
}
|
||||
return env, "", nil
|
||||
}
|
||||
|
||||
func getRevision(app v1beta1.Application) string {
|
||||
if app.Status.LatestRevision == nil {
|
||||
return ""
|
||||
}
|
||||
return app.Status.LatestRevision.Name
|
||||
}
|
||||
|
||||
func getSyncedRevision(rev *model.ApplicationRevision) string {
|
||||
if rev == nil {
|
||||
return ""
|
||||
}
|
||||
return rev.Version
|
||||
}
|
||||
|
||||
@@ -32,7 +32,9 @@ 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/utils"
|
||||
"github.com/oam-dev/kubevela/pkg/multicluster"
|
||||
"github.com/oam-dev/kubevela/pkg/oam"
|
||||
"github.com/oam-dev/kubevela/pkg/policy"
|
||||
)
|
||||
|
||||
@@ -85,17 +87,19 @@ func FromCRPolicy(appPrimaryKey string, policyCR v1beta1.AppPolicy, creator stri
|
||||
}
|
||||
|
||||
// FromCRWorkflow converts Application CR Workflow section into velaux data store workflow
|
||||
func FromCRWorkflow(ctx context.Context, cli client.Client, appPrimaryKey string, app *v1beta1.Application) (model.Workflow, []workflowv1alpha1.WorkflowStep, error) {
|
||||
func FromCRWorkflow(ctx context.Context, cli client.Client, appPrimaryKey string, app *v1beta1.Application, envName string) (model.Workflow, []workflowv1alpha1.WorkflowStep, error) {
|
||||
var defaultWorkflow = true
|
||||
name := app.Annotations[oam.AnnotationWorkflowName]
|
||||
if name == "" {
|
||||
name = fmt.Sprintf("workflow-%s", envName)
|
||||
}
|
||||
dataWf := model.Workflow{
|
||||
AppPrimaryKey: appPrimaryKey,
|
||||
// every namespace has a synced env
|
||||
EnvName: model.AutoGenEnvNamePrefix + app.Namespace,
|
||||
// every application has a synced workflow
|
||||
Name: model.AutoGenWorkflowNamePrefix + appPrimaryKey,
|
||||
Alias: model.AutoGenWorkflowNamePrefix + app.Name,
|
||||
Description: model.AutoGenDesc,
|
||||
Default: &defaultWorkflow,
|
||||
EnvName: envName,
|
||||
Name: name,
|
||||
Alias: fmt.Sprintf("%s Workflow", utils.FirstUpper(envName)),
|
||||
Description: model.AutoGenDesc,
|
||||
Default: &defaultWorkflow,
|
||||
}
|
||||
if app.Spec.Workflow == nil {
|
||||
return dataWf, nil, nil
|
||||
@@ -252,14 +256,30 @@ func FromCRApplicationRevision(ctx context.Context, cli client.Client, app *v1be
|
||||
if app.Status.Workflow == nil || app.Status.Workflow.AppRevision == "" {
|
||||
return nil
|
||||
}
|
||||
versions := strings.Split(app.Status.Workflow.AppRevision, ":")
|
||||
versionName := versions[0]
|
||||
var appRevision v1beta1.ApplicationRevision
|
||||
ctxTimeout, cancel := context.WithTimeout(ctx, time.Second*20)
|
||||
defer cancel()
|
||||
if err := cli.Get(ctxTimeout, types.NamespacedName{Namespace: app.Namespace, Name: versionName}, &appRevision); err != nil {
|
||||
klog.Errorf("failed to get the application revision %s", err.Error())
|
||||
return nil
|
||||
publishVersion := app.Status.Workflow.AppRevision
|
||||
var appRevision *v1beta1.ApplicationRevision
|
||||
var appRevisionList v1beta1.ApplicationRevisionList
|
||||
if err := cli.List(ctx, &appRevisionList,
|
||||
client.HasLabels{fmt.Sprintf("%s=%s", oam.LabelAppName, app.Name)},
|
||||
client.InNamespace(app.Namespace)); err == nil && len(appRevisionList.Items) > 0 {
|
||||
for i, rev := range appRevisionList.Items {
|
||||
if rev.Annotations[oam.AnnotationPublishVersion] == publishVersion {
|
||||
appRevision = &appRevisionList.Items[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if appRevision == nil {
|
||||
versions := strings.Split(app.Status.Workflow.AppRevision, ":")
|
||||
versionName := versions[0]
|
||||
var loadAR v1beta1.ApplicationRevision
|
||||
ctxTimeout, cancel := context.WithTimeout(ctx, time.Second*20)
|
||||
defer cancel()
|
||||
if err := cli.Get(ctxTimeout, types.NamespacedName{Namespace: app.Namespace, Name: versionName}, &loadAR); err != nil {
|
||||
klog.Errorf("failed to get the application revision %s", err.Error())
|
||||
return nil
|
||||
}
|
||||
appRevision = &loadAR
|
||||
}
|
||||
configByte, _ := yaml.Marshal(appRevision.Spec.Application)
|
||||
return &model.ApplicationRevision{
|
||||
@@ -270,7 +290,7 @@ func FromCRApplicationRevision(ctx context.Context, cli client.Client, app *v1be
|
||||
AppPrimaryKey: workflow.AppPrimaryKey,
|
||||
RevisionCRName: appRevision.Name,
|
||||
WorkflowName: workflow.Name,
|
||||
Version: versionName,
|
||||
Version: appRevision.Name,
|
||||
ApplyAppConfig: string(configByte),
|
||||
TriggerType: "SyncFromCR",
|
||||
EnvName: envName,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user