Compare commits

..

29 Commits

Author SHA1 Message Date
github-actions[bot]
1c2df10299 Fix: swagger DateType (#5570)
Signed-off-by: yueyongyue <yueyongyue@sina.cn>
(cherry picked from commit a4a4d64729)

Co-authored-by: yueyongyue <yueyongyue@sina.cn>
2023-02-27 09:53:52 +08:00
github-actions[bot]
918ed9727b [Backport release-1.7] Fix: delete the secret of the cluster (#5517)
* Fix: delete the secret of the cluster

Signed-off-by: suwanliang_yewu <suwanliang_yewu@cmss.chinamobile.com>
(cherry picked from commit ec466ab67e)

* Fix: add test

Signed-off-by: suwanliang_yewu <suwanliang_yewu@cmss.chinamobile.com>
(cherry picked from commit 63c44fdc39)

* Fix: modify error

Signed-off-by: suwanliang_yewu <suwanliang_yewu@cmss.chinamobile.com>
(cherry picked from commit e580597367)

* Fix: solve check-diff

Signed-off-by: suwanliang_yewu <suwanliang_yewu@cmss.chinamobile.com>
(cherry picked from commit c2316e10e8)

* Fix: modify test

Signed-off-by: suwanliang_yewu <suwanliang_yewu@cmss.chinamobile.com>
(cherry picked from commit afca7e6027)

---------

Co-authored-by: suwanliang_yewu <suwanliang_yewu@cmss.chinamobile.com>
2023-02-16 14:04:41 +08:00
github-actions[bot]
fa78cb7632 [Backport release-1.7] Fix: removes default parameter name for terraform provider (#5516)
* removes default name for terraform provider

Signed-off-by: afzalbin64 <afzal442@gmail.com>
(cherry picked from commit 92e7bf8263)

* fixes minor typos

Signed-off-by: afzalbin64 <afzal442@gmail.com>

undo the changes to typo

fixes minor typos in go_test files

updates config_test to support name as required param

(cherry picked from commit 51c2650a95)

---------

Co-authored-by: afzalbin64 <afzal442@gmail.com>
2023-02-16 14:02:10 +08:00
github-actions[bot]
f3cdbcf203 [Backport release-1.7] Feat: The vela-apiserver supports displaying chart values stored in the OCI registry (#5509)
* support helm chart values

Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>

rebase

Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>

no lint

Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>

fix lint error

Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>

add test and deprecated API

Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>

fix url bug

Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>

fix tests panic

Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>

fix tests

Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
(cherry picked from commit fc1d8c248d)

* fix golint

Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
(cherry picked from commit 6c462b7850)

* return values.yaml

Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
(cherry picked from commit 70d8cc5d52)

* fix test

Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
(cherry picked from commit ef4574a188)

* fix return values

Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
(cherry picked from commit c1488eee77)

* add multiple valeus yaml in

Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
(cherry picked from commit 04436188ff)

* add old interface back

Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
(cherry picked from commit ae0ac9f50f)

* fix golint

Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>

fix test

Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
(cherry picked from commit 00957744c0)

---------

Co-authored-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
2023-02-15 14:00:16 +08:00
github-actions[bot]
7bd2cf4dbc [Backport release-1.7] Fix: read-only definition in cue spec (#5508)
* Fix: ref-object and take-over definition in cue spec

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 23723af9af)

* rollback ref-objects

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 1af2c3934f)

---------

Co-authored-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
2023-02-15 13:59:48 +08:00
github-actions[bot]
969babdd9e Fix: apply-terraform-provider and container-image definition (#5486)
Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 978feccf91)

Co-authored-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
2023-02-13 11:21:52 +08:00
github-actions[bot]
94c46a179b Fix: use correct helm value when setting apprev compression (#5478)
Signed-off-by: Charlie Chiang <charlie_c_0129@outlook.com>
(cherry picked from commit 17c36206bc)

Co-authored-by: Charlie Chiang <charlie_c_0129@outlook.com>
2023-02-10 19:18:14 +08:00
Tianxin Dong
bec288c6b4 Chore: update cue version to v0.5.0-beta.5 to fix certain bugs in the old version (#5475)
Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2023-02-10 19:17:51 +08:00
github-actions[bot]
9a44be9788 Fix: pod view invalid cue for special pod output (#5474)
Signed-off-by: Somefive <yd219913@alibaba-inc.com>
(cherry picked from commit ece0396425)

Co-authored-by: Somefive <yd219913@alibaba-inc.com>
2023-02-10 13:07:21 +08:00
github-actions[bot]
9c7f4b7e03 Feat: enhance expose trait and adopt (#5473)
Signed-off-by: Somefive <yd219913@alibaba-inc.com>
(cherry picked from commit a05e4c8643)

Co-authored-by: Somefive <yd219913@alibaba-inc.com>
2023-02-10 11:30:20 +08:00
github-actions[bot]
539f1ed02b Fix: expose trait load balance cue check bug (#5461)
Signed-off-by: Somefive <yd219913@alibaba-inc.com>
(cherry picked from commit 9dccfcea1e)

Co-authored-by: Somefive <yd219913@alibaba-inc.com>
2023-02-08 23:25:11 +08:00
github-actions[bot]
9e95122387 Chore: fix krew release with new binary format for .exe (#5462)
Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
(cherry picked from commit a4ea6ccb04)

Co-authored-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
2023-02-08 23:24:37 +08:00
github-actions[bot]
f49f11dd72 Fix: suppress klog logs output for vela top (#5452)
Signed-off-by: Somefive <yd219913@alibaba-inc.com>
(cherry picked from commit 55662b645a)

Co-authored-by: Somefive <yd219913@alibaba-inc.com>
2023-02-08 16:26:44 +08:00
github-actions[bot]
191d9038f1 [Backport release-1.7] Fix: use get before create or update (#5450)
* Fix: use get before create or update

Signed-off-by: Somefive <yd219913@alibaba-inc.com>
(cherry picked from commit 93c1881663)

* Fix: ignore resource not found error when manage privileges for target

Signed-off-by: Somefive <yd219913@alibaba-inc.com>
(cherry picked from commit dd4864c6d1)

---------

Co-authored-by: Somefive <yd219913@alibaba-inc.com>
2023-02-08 14:50:38 +08:00
github-actions[bot]
e10e43b6c8 [Backport release-1.7] Fix: simplify notification parameters (#5446)
* Fix: simplify notification parameters

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit a9a8a18529)

* remove close

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 123c3f51b2)

* format

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit e2eee58a4b)

---------

Co-authored-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
2023-02-08 14:05:13 +08:00
github-actions[bot]
b9cc523267 [Backport release-1.7] Fix: Add confirmation prompt for vela adopt --apply with existing app name (#5419)
* Add confirmation prompt for vela adopt --apply with existing app name

Signed-off-by: Karanjot Singh <drquark@duck.com>
(cherry picked from commit 5278e1b350)

* Added changes according to the review

Signed-off-by: Karanjot Singh <drquark@duck.com>
(cherry picked from commit 0a437e336f)

* Fixed Userinput and used loadremoteApplication

Signed-off-by: Karanjot Singh <drquark@duck.com>

minor fixes

Signed-off-by: Karanjot Singh <drquark@duck.com>

used loadRemoteApplication

Signed-off-by: Karanjot Singh <drquark@duck.com>

Minor Fix

Signed-off-by: Karanjot Singh <drquark@duck.com>

Minor Fix

Signed-off-by: Karanjot Singh <drquark@duck.com>

Minor Fix

Signed-off-by: Karanjot Singh <drquark@duck.com>

Minor Fix

Signed-off-by: Karanjot Singh <drquark@duck.com>

Minor Fix

Signed-off-by: Karanjot Singh <drquark@duck.com>

Minor fix

Signed-off-by: Karanjot Singh <drquark@duck.com>

Minor fix

Signed-off-by: Karanjot Singh <drquark@duck.com>
(cherry picked from commit 4e92eaf73e)

* Used f.Client().Get method

Signed-off-by: Karanjot Singh <drquark@duck.com>

minor fix

Signed-off-by: Karanjot Singh <drquark@duck.com>

minor fix

Signed-off-by: Karanjot Singh <drquark@duck.com>
(cherry picked from commit 96a2ae8fb7)

* Changed bool to False

Signed-off-by: Karanjot Singh <drquark@duck.com>
(cherry picked from commit 17a1131b90)

---------

Co-authored-by: Karanjot Singh <drquark@duck.com>
2023-02-03 18:03:42 +08:00
github-actions[bot]
7f1743ef58 [Backport release-1.7] Fix: sync project from app crd to velaux (#5410)
* Fix: sync project from app crd to velaux

Signed-off-by: wuzhongjian <wuzhongjian_yewu@cmss.chinamobile.com>
(cherry picked from commit 3c613d7358)

* Fix: sync project from app crd to velaux

Signed-off-by: wuzhongjian <wuzhongjian_yewu@cmss.chinamobile.com>
(cherry picked from commit 2492e3725c)

* Fix: sync project from app crd to velaux

Signed-off-by: wuzhongjian <wuzhongjian_yewu@cmss.chinamobile.com>
(cherry picked from commit db3c7ea0a5)

* Fix: sync project from app crd to velaux

Signed-off-by: wuzhongjian <wuzhongjian_yewu@cmss.chinamobile.com>
(cherry picked from commit 1a364e0737)

* Fix: sync project from app crd to velaux

Signed-off-by: wuzhongjian <wuzhongjian_yewu@cmss.chinamobile.com>
(cherry picked from commit 363f56ac2a)

* Fix: sync project from app crd to velaux

Signed-off-by: wuzhongjian <wuzhongjian_yewu@cmss.chinamobile.com>
(cherry picked from commit 279517c142)

---------

Co-authored-by: wuzhongjian <wuzhongjian_yewu@cmss.chinamobile.com>
2023-02-02 15:31:25 +08:00
github-actions[bot]
dd39c38cf1 fix bugs of specified addonName (#5407)
Signed-off-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
(cherry picked from commit 3a9df79b3a)

Co-authored-by: 楚岳 <wangyike.wyk@alibaba-inc.com>
2023-02-01 16:44:30 +08:00
github-actions[bot]
0851454c6f Fix: ignore validation webhook for ref-objects typed component (#5406)
Signed-off-by: Somefive <yd219913@alibaba-inc.com>
(cherry picked from commit 0fb1ab497b)

Co-authored-by: Somefive <yd219913@alibaba-inc.com>
2023-02-01 16:10:16 +08:00
github-actions[bot]
cd3577db53 Fix: skip last-applied-configuration error for threewaymergepatch (#5405)
Signed-off-by: Somefive <yd219913@alibaba-inc.com>
(cherry picked from commit 6bf79461d4)

Co-authored-by: Somefive <yd219913@alibaba-inc.com>
2023-02-01 16:00:44 +08:00
github-actions[bot]
d578adfe6e Fix: longer releaser timeout (#5400)
Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 4ca1acdc22)

Co-authored-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
2023-02-01 14:01:07 +08:00
github-actions[bot]
4b88cd201e [Backport release-1.7] Fix: replace homemade release script with goreleaser (#5398)
* Replace homemade release script with goreleaser

refactor release.yml

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 00ee1513a1)

* wrap files in a directory

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit ba4ed6ad0f)

---------

Co-authored-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
2023-01-31 20:55:06 +08:00
github-actions[bot]
492e7d7f0d [Backport release-1.7] Fix: use the namespace specified in the resource if -n is not s… (#5396)
* fix #5368, use the namespace specified in the resource if -n is not specified

Signed-off-by: Basuotian <basuoluomiu@gmail.com>
(cherry picked from commit 47c9b4457b)

* add default namespace for the case missing namespace in resourceRef

Signed-off-by: Basuotian <basuoluomiu@gmail.com>
(cherry picked from commit 3ae0657796)

* add test case

Signed-off-by: Basuotian <basuoluomiu@gmail.com>
(cherry picked from commit 4ba5eb88eb)

---------

Co-authored-by: Basuotian <basuoluomiu@gmail.com>
2023-01-31 20:16:18 +08:00
Jianbo Sun
0742ca9ee5 Fix: aligin config create to be managed by apps with Dispatch function (#5384) (#5394)
Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
2023-01-31 18:04:36 +08:00
github-actions[bot]
1cf4ae3fc3 [Backport release-1.7] Feat: add the updating the application trigger API (#5395)
* Feat: add the updating the application trigger API

Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
(cherry picked from commit 05bc42bc50)

* Fix: change the test case

Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
(cherry picked from commit d6f3e0e90b)

* Fix: imported more than once

Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
(cherry picked from commit 37f7af0beb)

---------

Co-authored-by: barnettZQG <barnett.zqg@gmail.com>
2023-01-31 17:14:03 +08:00
qiaozp
444d315143 Fix: rework on apisrever e2e test covergae (#5390)
Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
2023-01-31 15:04:24 +08:00
github-actions[bot]
2e3a89f6b1 Chore: update workflow version to fix panic (#5386)
Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
(cherry picked from commit 4ae1fe044e)

Co-authored-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2023-01-31 10:57:40 +08:00
github-actions[bot]
d94293ac59 Fix: failed to create the record when rollbacking the application (#5381)
Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
(cherry picked from commit 57d85ecb7c)

Co-authored-by: barnettZQG <barnett.zqg@gmail.com>
2023-01-30 20:51:04 +08:00
github-actions[bot]
cc604cfadb Feat: upgrade cluster gateway to 1.7.0 (#5356)
Signed-off-by: Somefive <yd219913@alibaba-inc.com>
(cherry picked from commit 3245ea148c)

Co-authored-by: Somefive <yd219913@alibaba-inc.com>
2023-01-19 11:21:38 +08:00
70 changed files with 1521 additions and 435 deletions

View File

@@ -186,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

View File

@@ -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
.gitignore vendored
View File

@@ -53,3 +53,5 @@ git-page/
# e2e rollout runtime image build
runtime/rollout/e2e/tmp
vela.json
dist/

76
.goreleaser.yaml Normal file
View 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

View File

@@ -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"

View File

@@ -111,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.7.0-alpha.3` |
| `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` |

View File

@@ -116,7 +116,7 @@ spec:
#ECProvider: {
type: "ec"
apiKey: *"" | string
name: "ec-provider" | string
name: *"ec-provider" | string
}
#GCPProvider: {
credentials: string

View File

@@ -72,7 +72,7 @@ spec:
}]
}
}
parameter: *#PatchParams | close({
parameter: #PatchParams | close({
// +usage=Specify the container image for multiple containers
containers: [...#PatchParams]
})

View File

@@ -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
}

View File

@@ -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

View File

@@ -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

View File

@@ -272,8 +272,8 @@ 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 }}

View File

@@ -2,7 +2,7 @@ apiVersion: v1
data:
template: |
import (
"vela/ql"
"vela/ql"
)
parameter: {
@@ -55,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
}
}
}
}]

View File

@@ -148,7 +148,7 @@ multicluster:
port: 9443
image:
repository: oamdev/cluster-gateway
tag: v1.7.0-alpha.3
tag: v1.7.0
pullPolicy: IfNotPresent
resources:
limits:

View File

@@ -105,7 +105,7 @@ helm install --create-namespace -n vela-system kubevela kubevela/vela-minimal --
| `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` |

View File

@@ -116,7 +116,7 @@ spec:
#ECProvider: {
type: "ec"
apiKey: *"" | string
name: "ec-provider" | string
name: *"ec-provider" | string
}
#GCPProvider: {
credentials: string

View File

@@ -72,7 +72,7 @@ spec:
}]
}
}
parameter: *#PatchParams | close({
parameter: #PatchParams | close({
// +usage=Specify the container image for multiple containers
containers: [...#PatchParams]
})

View File

@@ -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
}

View File

@@ -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

View File

@@ -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

View File

@@ -106,7 +106,7 @@ multicluster:
port: 9443
image:
repository: oamdev/cluster-gateway
tag: v1.4.0
tag: v1.7.0
pullPolicy: IfNotPresent
resources:
limits:

View File

@@ -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)))

View File

@@ -2086,7 +2086,7 @@
"tags": [
"application"
],
"summary": "list application triggers",
"summary": "List the application triggers",
"operationId": "listApplicationTriggers",
"parameters": [
{
@@ -2124,7 +2124,7 @@
"tags": [
"application"
],
"summary": "create one application trigger",
"summary": "Create an application trigger",
"operationId": "createApplicationTrigger",
"parameters": [
{
@@ -2160,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",
@@ -2172,7 +2217,7 @@
"tags": [
"application"
],
"summary": "delete one application trigger",
"summary": "Delete an application trigger",
"operationId": "deleteApplicationTrigger",
"parameters": [
{
@@ -8964,8 +9009,8 @@
},
"model.ApplicationRevision": {
"required": [
"createTime",
"updateTime",
"createTime",
"appPrimaryKey",
"version",
"revisionCRName",
@@ -9347,11 +9392,11 @@
},
"model.WorkflowStep": {
"required": [
"alias",
"name",
"dependsOn",
"description",
"orderIndex",
"dependsOn",
"name",
"alias",
"type"
],
"properties": {
@@ -9469,9 +9514,9 @@
},
"model.WorkflowStepStatus": {
"required": [
"id",
"name",
"alias"
"alias",
"id"
],
"properties": {
"alias": {
@@ -10055,11 +10100,11 @@
"v1.ApplicationDeployResponse": {
"required": [
"version",
"status",
"triggerType",
"createTime",
"status",
"note",
"envName",
"triggerType",
"record"
],
"properties": {
@@ -10338,6 +10383,7 @@
"type",
"payloadType",
"token",
"registry",
"createTime",
"updateTime"
],
@@ -10361,6 +10407,9 @@
"payloadType": {
"type": "string"
},
"registry": {
"type": "string"
},
"token": {
"type": "string"
},
@@ -10833,13 +10882,13 @@
},
"v1.ConfigTemplateDetail": {
"required": [
"sensitive",
"createTime",
"alias",
"name",
"namespace",
"description",
"scope",
"sensitive",
"createTime",
"alias",
"schema",
"uiSchema"
],
@@ -11669,11 +11718,11 @@
},
"v1.DetailAddonResponse": {
"required": [
"invisible",
"name",
"version",
"description",
"icon",
"invisible",
"description",
"schema",
"uiSchema",
"definitions",
@@ -11753,12 +11802,12 @@
},
"v1.DetailApplicationResponse": {
"required": [
"project",
"createTime",
"updateTime",
"name",
"alias",
"project",
"description",
"createTime",
"updateTime",
"icon",
"policies",
"envBindings",
@@ -11816,20 +11865,20 @@
},
"v1.DetailClusterResponse": {
"required": [
"status",
"provider",
"dashboardURL",
"description",
"icon",
"labels",
"reason",
"apiServerURL",
"kubeConfigSecret",
"alias",
"status",
"dashboardURL",
"icon",
"description",
"reason",
"createTime",
"updateTime",
"name",
"kubeConfig",
"labels",
"provider",
"apiServerURL",
"createTime",
"resourceInfo"
],
"properties": {
@@ -11887,13 +11936,13 @@
},
"v1.DetailComponentResponse": {
"required": [
"name",
"main",
"alias",
"createTime",
"updateTime",
"appPrimaryKey",
"creator",
"name",
"main",
"createTime",
"updateTime",
"alias",
"type",
"definition"
],
@@ -11982,12 +12031,12 @@
},
"v1.DetailDefinitionResponse": {
"required": [
"alias",
"labels",
"ownerAddon",
"name",
"alias",
"icon",
"labels",
"description",
"icon",
"status",
"schema",
"uiSchema"
@@ -12045,15 +12094,15 @@
},
"v1.DetailPolicyResponse": {
"required": [
"description",
"creator",
"envName",
"name",
"alias",
"type",
"description",
"createTime",
"updateTime",
"type",
"properties"
"alias",
"creator",
"properties",
"envName"
],
"properties": {
"alias": {
@@ -12095,18 +12144,18 @@
},
"v1.DetailRevisionResponse": {
"required": [
"appPrimaryKey",
"revisionCRName",
"triggerType",
"workflowName",
"version",
"status",
"deployUser",
"note",
"createTime",
"appPrimaryKey",
"deployUser",
"triggerType",
"updateTime",
"revisionCRName",
"reason",
"envName"
"envName",
"version",
"workflowName",
"createTime"
],
"properties": {
"appPrimaryKey": {
@@ -12163,10 +12212,10 @@
},
"v1.DetailTargetResponse": {
"required": [
"updateTime",
"name",
"project",
"createTime",
"updateTime"
"project"
],
"properties": {
"alias": {
@@ -12206,11 +12255,11 @@
},
"v1.DetailUserResponse": {
"required": [
"email",
"disabled",
"createTime",
"lastLoginTime",
"name",
"email",
"projects",
"roles"
],
@@ -12252,12 +12301,12 @@
"v1.DetailWorkflowRecordResponse": {
"required": [
"status",
"mode",
"workflowAlias",
"applicationRevision",
"namespace",
"message",
"mode",
"name",
"namespace",
"workflowName",
"deployTime",
"deployUser",
@@ -12321,15 +12370,15 @@
"v1.DetailWorkflowResponse": {
"required": [
"name",
"enable",
"envName",
"alias",
"description",
"default",
"createTime",
"updateTime",
"subMode",
"alias",
"enable",
"default",
"envName",
"mode"
"mode",
"subMode"
],
"properties": {
"alias": {
@@ -12537,8 +12586,8 @@
},
"v1.EnvBindingTarget": {
"required": [
"name",
"alias"
"alias",
"name"
],
"properties": {
"alias": {
@@ -12565,11 +12614,11 @@
"v1.GetPipelineResponse": {
"required": [
"spec",
"description",
"createTime",
"name",
"alias",
"project",
"description",
"info"
],
"properties": {
@@ -12612,10 +12661,10 @@
},
"v1.GetPipelineRunLogResponse": {
"required": [
"phase",
"id",
"name",
"type",
"phase",
"source",
"log"
],
@@ -13269,11 +13318,11 @@
},
"v1.LoginUserInfoResponse": {
"required": [
"createTime",
"lastLoginTime",
"name",
"email",
"disabled",
"createTime",
"lastLoginTime",
"projects",
"platformPermissions",
"projectPermissions"
@@ -13475,11 +13524,11 @@
},
"v1.PipelineBase": {
"required": [
"description",
"createTime",
"name",
"alias",
"project",
"description",
"spec"
],
"properties": {
@@ -13578,11 +13627,11 @@
},
"v1.PipelineMetaResponse": {
"required": [
"name",
"alias",
"project",
"description",
"createTime",
"name",
"alias"
"createTime"
],
"properties": {
"alias": {
@@ -13605,13 +13654,13 @@
},
"v1.PipelineRun": {
"required": [
"contextName",
"contextValues",
"spec",
"pipelineName",
"project",
"pipelineRunName",
"record",
"contextName",
"contextValues",
"spec",
"status"
],
"properties": {
@@ -14208,9 +14257,9 @@
},
"v1.SystemInfoResponse": {
"required": [
"loginType",
"platformID",
"enableCollection",
"loginType",
"systemVersion"
],
"properties": {
@@ -14734,14 +14783,14 @@
},
"v1.WorkflowRecord": {
"required": [
"namespace",
"message",
"status",
"mode",
"name",
"namespace",
"workflowName",
"workflowAlias",
"applicationRevision"
"applicationRevision",
"mode",
"message"
],
"properties": {
"applicationRevision": {
@@ -14832,8 +14881,8 @@
},
"v1.WorkflowStep": {
"required": [
"type",
"name"
"name",
"type"
],
"properties": {
"alias": {

View File

@@ -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())

5
go.mod
View File

@@ -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
@@ -57,7 +57,7 @@ require (
github.com/koding/websocketproxy v0.0.0-20181220232114-7ed82d81a28c
github.com/kubevela/pkg v0.0.0-20230105054759-263dc191bf51
github.com/kubevela/prism v1.7.0-alpha.1
github.com/kubevela/workflow v0.4.0
github.com/kubevela/workflow v0.4.1
github.com/kyokomi/emoji v2.2.4+incompatible
github.com/mitchellh/hashstructure/v2 v2.0.1
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd
@@ -348,7 +348,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

8
go.sum
View File

@@ -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=
@@ -1283,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-20230105054759-263dc191bf51 h1:xrcNNaAjqC6tr1leSYcjLFgrXKpZ8u87jpB5TolhUIc=
github.com/kubevela/pkg v0.0.0-20230105054759-263dc191bf51/go.mod h1:ZRnxY/gOcg/8FilZA+eYr+rtVXb1ijT5HFTe8zrv9zo=
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.4.0 h1:Zzb9wPOvLUGEArdnC6EsfNM5j3VNJj0/v2iDKq1JT3k=
github.com/kubevela/workflow v0.4.0/go.mod h1:AX/WL3G/YBkpmNpA/SKKm9M3Y0T9y95gZA8mFWylkyM=
github.com/kubevela/workflow v0.4.1 h1:lYeWE9KgSSkb368u8G7cGfyzCz41Am8MdxgViRFJxXE=
github.com/kubevela/workflow v0.4.1/go.mod h1:AX/WL3G/YBkpmNpA/SKKm9M3Y0T9y95gZA8mFWylkyM=
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=

View File

@@ -99,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 {
@@ -410,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,
@@ -427,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
@@ -457,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{
@@ -1715,6 +1753,10 @@ func (c *applicationServiceImpl) RollbackWithRevision(ctx context.Context, appli
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)

View File

@@ -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())

View File

@@ -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)
}

View File

@@ -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,

View File

@@ -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, &paramErr)).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{

View File

@@ -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
}

View File

@@ -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())
})
})

View File

@@ -259,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

View File

@@ -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{

View File

@@ -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,

View File

@@ -190,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

View File

@@ -217,6 +217,47 @@ var _ = Describe("Test CR convert to ux", func() {
Expect(count).Should(Equal(int64(2)))
})
It("Test to sync the project which existed env belongs", func() {
dbNamespace := "update-app-db-ns1-test"
ds, err := NewDatastore(datastore.Config{Type: "kubeapi", Database: dbNamespace})
Expect(err).Should(BeNil())
cr2ux := newCR2UX(ds)
projectName := "project-test"
_, err = cr2ux.projectService.CreateProject(context.TODO(), v1.CreateProjectRequest{
Name: projectName,
Owner: "admin",
})
Expect(err).Should(BeNil())
_, err = cr2ux.targetService.CreateTarget(context.TODO(), v1.CreateTargetRequest{
Name: "target-test1",
Project: projectName,
Cluster: &v1.ClusterTarget{
ClusterName: "local",
Namespace: "target-test1",
},
})
Expect(err).Should(BeNil())
_, err = cr2ux.envService.CreateEnv(context.TODO(), v1.CreateEnvRequest{
Name: "env-test1",
Project: projectName,
Namespace: "env-test1",
Targets: []string{"target-test1"},
})
Expect(err).Should(BeNil())
app5 := &v1beta1.Application{}
Expect(common2.ReadYamlToObject("testdata/test-app5.yaml", app5)).Should(BeNil())
app5.Namespace = "env-test1"
Expect(cr2ux.AddOrUpdate(context.Background(), app5)).Should(BeNil())
app, err := cr2ux.applicationService.GetApplication(context.TODO(), app5.Name)
Expect(err).Should(BeNil())
Expect(app.Project).Should(Equal("project-test"))
})
})
func newCR2UX(ds datastore.DataStore) *CR2UX {

View File

@@ -0,0 +1,16 @@
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: example-sync-project
spec:
components:
- name: example-exist-env
type: webservice
properties:
image: wordpress
traits:
- type: gateway
properties:
domain: testsvc.example.com
http:
"/": 8000

View File

@@ -118,7 +118,7 @@ func (c *application) GetWebServiceRoute() *restful.WebService {
Writes(apis.ApplicationStatisticsResponse{}))
ws.Route(ws.POST("/{appName}/triggers").To(c.createApplicationTrigger).
Doc("create one application trigger").
Doc("Create an application trigger").
Metadata(restfulspec.KeyOpenAPITags, tags).
Filter(c.RbacService.CheckPerm("trigger", "create")).
Filter(c.appCheckFilter).
@@ -129,7 +129,7 @@ func (c *application) GetWebServiceRoute() *restful.WebService {
Writes(apis.ApplicationTriggerBase{}))
ws.Route(ws.DELETE("/{appName}/triggers/{token}").To(c.deleteApplicationTrigger).
Doc("delete one application trigger").
Doc("Delete an application trigger").
Metadata(restfulspec.KeyOpenAPITags, tags).
Filter(c.RbacService.CheckPerm("trigger", "delete")).
Filter(c.appCheckFilter).
@@ -139,8 +139,19 @@ func (c *application) GetWebServiceRoute() *restful.WebService {
Returns(400, "Bad Request", bcode.Bcode{}).
Writes([]*apis.EmptyResponse{}))
ws.Route(ws.PUT("/{appName}/triggers/{token}").To(c.updateApplicationTrigger).
Doc("Update an application trigger").
Metadata(restfulspec.KeyOpenAPITags, tags).
Filter(c.RbacService.CheckPerm("trigger", "update")).
Filter(c.appCheckFilter).
Param(ws.PathParameter("appName", "identifier of the application ").DataType("string")).
Param(ws.PathParameter("token", "identifier of the trigger").DataType("string")).
Returns(200, "OK", apis.ApplicationTriggerBase{}).
Returns(400, "Bad Request", bcode.Bcode{}).
Writes([]*apis.ApplicationTriggerBase{}))
ws.Route(ws.GET("/{appName}/triggers").To(c.listApplicationTriggers).
Doc("list application triggers").
Doc("List the application triggers").
Metadata(restfulspec.KeyOpenAPITags, tags).
Filter(c.RbacService.CheckPerm("trigger", "list")).
Filter(c.appCheckFilter).
@@ -747,6 +758,24 @@ func (c *application) deleteApplicationTrigger(req *restful.Request, res *restfu
}
}
func (c *application) updateApplicationTrigger(req *restful.Request, res *restful.Response) {
var updateReq apis.UpdateApplicationTriggerRequest
if err := req.ReadEntity(&updateReq); err != nil {
bcode.ReturnError(req, res, err)
return
}
app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application)
trigger, err := c.ApplicationService.UpdateApplicationTrigger(req.Request.Context(), app, req.PathParameter("token"), updateReq)
if err != nil {
bcode.ReturnError(req, res, err)
return
}
if err := res.WriteEntity(trigger); err != nil {
bcode.ReturnError(req, res, err)
return
}
}
func (c *application) publishApplicationTemplate(req *restful.Request, res *restful.Response) {
app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.Application)
base, err := c.ApplicationService.PublishApplicationTemplate(req.Request.Context(), app)

View File

@@ -274,6 +274,23 @@ func ConvertPermission2DTO(permission *model.Permission) *apisv1.PermissionBase
}
}
// ConvertTrigger2DTO convert trigger model to the DTO
func ConvertTrigger2DTO(trigger model.ApplicationTrigger) *apisv1.ApplicationTriggerBase {
return &apisv1.ApplicationTriggerBase{
WorkflowName: trigger.WorkflowName,
Name: trigger.Name,
Alias: trigger.Alias,
Description: trigger.Description,
Type: trigger.Type,
PayloadType: trigger.PayloadType,
Token: trigger.Token,
Registry: trigger.Registry,
ComponentName: trigger.ComponentName,
CreateTime: trigger.CreateTime,
UpdateTime: trigger.UpdateTime,
}
}
func convertBool(b *bool) bool {
if b == nil {
return false

View File

@@ -512,6 +512,16 @@ type CreateApplicationTriggerRequest struct {
Registry string `json:"registry,omitempty" optional:"true"`
}
// UpdateApplicationTriggerRequest update application trigger
type UpdateApplicationTriggerRequest struct {
Alias string `json:"alias" validate:"checkalias" optional:"true"`
Description string `json:"description" optional:"true"`
WorkflowName string `json:"workflowName"`
PayloadType string `json:"payloadType" validate:"checkpayloadtype"`
ComponentName string `json:"componentName,omitempty" optional:"true"`
Registry string `json:"registry,omitempty" optional:"true"`
}
// ApplicationTriggerBase application trigger base model
type ApplicationTriggerBase struct {
Name string `json:"name"`
@@ -522,6 +532,7 @@ type ApplicationTriggerBase struct {
PayloadType string `json:"payloadType"`
Token string `json:"token"`
ComponentName string `json:"componentName,omitempty"`
Registry string `json:"registry"`
CreateTime time.Time `json:"createTime"`
UpdateTime time.Time `json:"updateTime"`
}

View File

@@ -234,7 +234,7 @@ func (n *pipeline) GetWebServiceRoute() *restful.WebService {
Doc("list pipelines").
Param(ws.QueryParameter("query", "Fuzzy search based on name or description").DataType("string")).
Param(ws.QueryParameter("projectName", "query pipelines within a project").DataType("string")).
Param(ws.QueryParameter("detailed", "query pipelines with detail").DataType("bool").DefaultValue("true")).
Param(ws.QueryParameter("detailed", "query pipelines with detail").DataType("boolean").DefaultValue("true")).
Returns(200, "OK", apis.ListPipelineResponse{}).
Returns(400, "Bad Request", bcode.Bcode{}).
Writes(apis.ListPipelineResponse{}).Do(meta))

View File

@@ -69,9 +69,19 @@ func (h repository) GetWebServiceRoute() *restful.WebService {
Writes([]string{}))
// List available chart versions
ws.Route(ws.GET("/charts/{chart}/versions").To(h.listVersions).
ws.Route(ws.GET("/chart/versions").To(h.listVersionsFromQuery).
Doc("list versions").
Metadata(restfulspec.KeyOpenAPITags, tags).
Param(ws.QueryParameter("chart", "helm chart").DataType("string").Required(true)).
Param(ws.QueryParameter("repoUrl", "helm repository url").DataType("string").Required(true)).
Param(ws.QueryParameter("secretName", "secret of the repo").DataType("string")).
Returns(200, "OK", v1.ChartVersionListResponse{}).
Returns(400, "Bad Request", bcode.Bcode{}).
Writes([]string{}))
ws.Route(ws.GET("/charts/{chart}/versions").To(h.listChartVersions).
Doc("list versions").Deprecate().
Metadata(restfulspec.KeyOpenAPITags, tags).
Param(ws.QueryParameter("repoUrl", "helm repository url").DataType("string")).
Param(ws.QueryParameter("secretName", "secret of the repo").DataType("string")).
Returns(200, "OK", v1.ChartVersionListResponse{}).
@@ -79,14 +89,26 @@ func (h repository) GetWebServiceRoute() *restful.WebService {
Writes([]string{}))
// List available chart versions
ws.Route(ws.GET("/charts/{chart}/versions/{version}/values").To(h.chartValues).
ws.Route(ws.GET("/chart/values").To(h.chartValues).
Doc("get chart value").
Metadata(restfulspec.KeyOpenAPITags, tags).
Param(ws.QueryParameter("chart", "helm chart").DataType("string").Required(true)).
Param(ws.QueryParameter("version", "helm chart version").DataType("string").Required(true)).
Param(ws.QueryParameter("repoUrl", "helm repository url").DataType("string").Required(true)).
Param(ws.QueryParameter("repoType", "helm repository type").DataType("string").Required(true)).
Param(ws.QueryParameter("secretName", "secret of the repo").DataType("string")).
Returns(200, "OK", "").
Returns(400, "Bad Request", bcode.Bcode{}).
Writes(map[string]string{}))
ws.Route(ws.GET("/charts/{chart}/versions/{version}/values").To(h.getChartValues).
Doc("get chart value").Deprecate().
Metadata(restfulspec.KeyOpenAPITags, tags).
Param(ws.QueryParameter("repoUrl", "helm repository url").DataType("string")).
Param(ws.QueryParameter("secretName", "secret of the repo").DataType("string")).
Returns(200, "OK", map[string]interface{}{}).
Returns(400, "Bad Request", bcode.Bcode{}).
Writes([]string{}))
Writes(map[string]interface{}{}))
ws.Route(ws.GET("/image/repos").To(h.getImageRepos).
Doc("get the oci repos").
@@ -132,9 +154,9 @@ func (h repository) listCharts(req *restful.Request, res *restful.Response) {
}
}
func (h repository) listVersions(req *restful.Request, res *restful.Response) {
func (h repository) listVersionsFromQuery(req *restful.Request, res *restful.Response) {
url := req.QueryParameter("repoUrl")
chartName := req.PathParameter("chart")
chartName := req.QueryParameter("chart")
secName := req.QueryParameter("secretName")
skipCache, err := isSkipCache(req)
if err != nil {
@@ -154,7 +176,7 @@ func (h repository) listVersions(req *restful.Request, res *restful.Response) {
}
}
func (h repository) chartValues(req *restful.Request, res *restful.Response) {
func (h repository) getChartValues(req *restful.Request, res *restful.Response) {
url := req.QueryParameter("repoUrl")
secName := req.QueryParameter("secretName")
chartName := req.PathParameter("chart")
@@ -165,12 +187,57 @@ func (h repository) chartValues(req *restful.Request, res *restful.Response) {
return
}
versions, err := h.HelmService.GetChartValues(req.Request.Context(), url, chartName, version, secName, skipCache)
values, err := h.HelmService.GetChartValues(req.Request.Context(), url, chartName, version, secName, "helm", skipCache)
if err != nil {
bcode.ReturnError(req, res, err)
return
}
err = res.WriteEntity(versions)
err = res.WriteEntity(values)
if err != nil {
bcode.ReturnError(req, res, err)
return
}
}
func (h repository) listChartVersions(req *restful.Request, res *restful.Response) {
url := req.QueryParameter("repoUrl")
chartName := req.PathParameter("chart")
secName := req.QueryParameter("secretName")
skipCache, err := isSkipCache(req)
if err != nil {
bcode.ReturnError(req, res, bcode.ErrSkipCacheParameter)
return
}
versions, err := h.HelmService.ListChartVersions(req.Request.Context(), url, chartName, secName, skipCache)
if err != nil {
bcode.ReturnError(req, res, err)
return
}
err = res.WriteEntity(v1.ChartVersionListResponse{Versions: versions})
if err != nil {
bcode.ReturnError(req, res, err)
return
}
}
func (h repository) chartValues(req *restful.Request, res *restful.Response) {
url := req.QueryParameter("repoUrl")
secName := req.QueryParameter("secretName")
chartName := req.QueryParameter("chart")
version := req.QueryParameter("version")
repoType := req.QueryParameter("repoType")
skipCache, err := isSkipCache(req)
if err != nil {
bcode.ReturnError(req, res, bcode.ErrSkipCacheParameter)
return
}
values, err := h.HelmService.ListChartValuesFiles(req.Request.Context(), url, chartName, version, secName, repoType, skipCache)
if err != nil {
bcode.ReturnError(req, res, err)
return
}
err = res.WriteEntity(values)
if err != nil {
bcode.ReturnError(req, res, err)
return

View File

@@ -23,21 +23,21 @@ var (
// ErrNoConfigOrTarget means there is no target or config when creating the distribution.
ErrNoConfigOrTarget = NewBcode(400, 16002, "you must specify the config name and destination to distribute")
// ErrConfigExist means the config is exist
ErrConfigExist = NewBcode(400, 16003, "the config name is exist")
// ErrConfigExist means the config does exist
ErrConfigExist = NewBcode(400, 16003, "the config name does exist")
// ErrChangeTemplate the template of the config can not be change
ErrChangeTemplate = NewBcode(400, 16004, "the template of the config can not be change")
// ErrChangeTemplate the template of the config can not be changed
ErrChangeTemplate = NewBcode(400, 16004, "the template of the config can not be changed")
// ErrTemplateNotFound means the template is not exist
ErrTemplateNotFound = NewBcode(404, 16005, "the template is not exist")
// ErrTemplateNotFound means the template does not exist
ErrTemplateNotFound = NewBcode(404, 16005, "the template does not exist")
// ErrConfigNotFound means the config is not exist
ErrConfigNotFound = NewBcode(404, 16006, "the config is not exist")
// ErrConfigNotFound means the config does not exist
ErrConfigNotFound = NewBcode(404, 16006, "the config does not exist")
// ErrNotFoundDistribution means the distribution is not exist
ErrNotFoundDistribution = NewBcode(404, 16007, "the distribution is not exist")
// ErrNotFoundDistribution means the distribution does not exist
ErrNotFoundDistribution = NewBcode(404, 16007, "the distribution does not exist")
// ErrChangeSecretType the secret type of the config can not be change
ErrChangeSecretType = NewBcode(400, 16008, "the secret type of the config can not be change")
// ErrChangeSecretType the secret type of the config can not be changed
ErrChangeSecretType = NewBcode(400, 16008, "the secret type of the config can not be changed")
)

View File

@@ -23,6 +23,7 @@ import (
"github.com/kubevela/workflow/pkg/cue/process"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha1"
"github.com/oam-dev/kubevela/apis/types"
velaprocess "github.com/oam-dev/kubevela/pkg/cue/process"
)
@@ -32,7 +33,7 @@ func (p *Parser) ValidateCUESchematicAppfile(a *Appfile) error {
for _, wl := range a.Workloads {
// because helm & kube schematic has no CUE template
// it only validates CUE schematic workload
if wl.CapabilityCategory != types.CUECategory {
if wl.CapabilityCategory != types.CUECategory || wl.Type == v1alpha1.RefObjectsComponentType {
continue
}
ctxData := GenerateContextDataFromAppFile(a, wl.Name)

View File

@@ -76,23 +76,23 @@ var ErrSensitiveConfig = errors.New("the config is sensitive")
// ErrNoConfigOrTarget means the config or the target is empty.
var ErrNoConfigOrTarget = errors.New("you must specify the config name and destination to distribute")
// ErrNotFoundDistribution means the app of the distribution is not exist.
var ErrNotFoundDistribution = errors.New("the distribution is not found")
// ErrNotFoundDistribution means the app of the distribution does not exist.
var ErrNotFoundDistribution = errors.New("the distribution does not found")
// ErrConfigExist means the config is exist.
var ErrConfigExist = errors.New("the config is exist")
// ErrConfigExist means the config does exist.
var ErrConfigExist = errors.New("the config does exist")
// ErrConfigNotFound means the config is not exist
var ErrConfigNotFound = errors.New("the config is not exist")
// ErrConfigNotFound means the config does not exist
var ErrConfigNotFound = errors.New("the config does not exist")
// ErrTemplateNotFound means the template is not exist
var ErrTemplateNotFound = errors.New("the template is not exist")
// ErrTemplateNotFound means the template does not exist
var ErrTemplateNotFound = errors.New("the template does not exist")
// ErrChangeTemplate means the template of the config can not be change
var ErrChangeTemplate = errors.New("the template of the config can not be change")
// ErrChangeTemplate means the template of the config can not be changed
var ErrChangeTemplate = errors.New("the template of the config can not be changed")
// ErrChangeSecretType means the secret type of the config can not be change
var ErrChangeSecretType = errors.New("the secret type of the config can not be change")
// ErrChangeSecretType means the secret type of the config can not be changed
var ErrChangeSecretType = errors.New("the secret type of the config can not be changed")
// NamespacedName the namespace and name model
type NamespacedName struct {
@@ -206,14 +206,37 @@ type Factory interface {
MergeDistributionStatus(ctx context.Context, config *Config, namespace string) error
}
// Dispatcher is a client for apply resources.
type Dispatcher func(context.Context, []*unstructured.Unstructured, []apply.ApplyOption) error
// NewConfigFactory create a config factory instance
func NewConfigFactory(cli client.Client) Factory {
return &kubeConfigFactory{cli: cli, apiApply: apply.NewAPIApplicator(cli)}
return &kubeConfigFactory{cli: cli, apiApply: defaultDispatcher(cli)}
}
// NewConfigFactoryWithDispatcher create a config factory instance with a specified dispatcher
func NewConfigFactoryWithDispatcher(cli client.Client, ds Dispatcher) Factory {
if ds == nil {
ds = defaultDispatcher(cli)
}
return &kubeConfigFactory{cli: cli, apiApply: ds}
}
func defaultDispatcher(cli client.Client) Dispatcher {
api := apply.NewAPIApplicator(cli)
return func(ctx context.Context, manifests []*unstructured.Unstructured, ao []apply.ApplyOption) error {
for _, m := range manifests {
if err := api.Apply(ctx, m, ao...); err != nil {
return err
}
}
return nil
}
}
type kubeConfigFactory struct {
cli client.Client
apiApply *apply.APIApplicator
apiApply Dispatcher
}
// ParseTemplate parse a config template instance form the cue script
@@ -307,7 +330,14 @@ func (k *kubeConfigFactory) CreateOrUpdateConfigTemplate(ctx context.Context, ns
if ns != "" {
it.ConfigMap.Namespace = ns
}
return k.apiApply.Apply(ctx, it.ConfigMap, apply.DisableUpdateAnnotation(), apply.Quiet())
obj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(it.ConfigMap)
if err != nil {
return fmt.Errorf("fail to convert configmap to unstructured: %w", err)
}
us := &unstructured.Unstructured{Object: obj}
us.SetAPIVersion("v1")
us.SetKind("ConfigMap")
return k.apiApply(ctx, []*unstructured.Unstructured{us}, []apply.ApplyOption{apply.DisableUpdateAnnotation(), apply.Quiet()})
}
func convertConfigMap2Template(cm v1.ConfigMap) (*Template, error) {
@@ -562,11 +592,20 @@ func (k *kubeConfigFactory) CreateOrUpdateConfig(ctx context.Context, i *Config,
return ErrChangeSecretType
}
}
if err := k.apiApply.Apply(ctx, i.Secret, apply.Quiet()); err != nil {
obj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(i.Secret)
if err != nil {
return fmt.Errorf("fail to convert secret to unstructured: %w", err)
}
us := &unstructured.Unstructured{Object: obj}
us.SetAPIVersion("v1")
us.SetKind("Secret")
if err := k.apiApply(ctx, []*unstructured.Unstructured{us}, []apply.ApplyOption{apply.DisableUpdateAnnotation(), apply.Quiet()}); err != nil {
return fmt.Errorf("fail to apply the secret: %w", err)
}
for key, obj := range i.OutputObjects {
if err := k.apiApply.Apply(ctx, obj, apply.Quiet()); err != nil {
if err := k.apiApply(ctx, []*unstructured.Unstructured{obj}, []apply.ApplyOption{apply.DisableUpdateAnnotation(), apply.Quiet()}); err != nil {
return fmt.Errorf("fail to apply the object %s: %w", key, err)
}
}
@@ -768,7 +807,15 @@ func (k *kubeConfigFactory) CreateOrUpdateDistribution(ctx context.Context, ns,
Policies: policies,
},
}
return k.apiApply.Apply(ctx, distribution, apply.Quiet())
obj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(distribution)
if err != nil {
return fmt.Errorf("fail to convert application to unstructured: %w", err)
}
us := &unstructured.Unstructured{Object: obj}
us.SetAPIVersion(v1beta1.SchemeGroupVersion.String())
us.SetKind(v1beta1.ApplicationKind)
return k.apiApply(ctx, []*unstructured.Unstructured{us}, []apply.ApplyOption{apply.DisableUpdateAnnotation(), apply.Quiet()})
}
func (k *kubeConfigFactory) ListDistributions(ctx context.Context, ns string) ([]*Distribution, error) {

View File

@@ -0,0 +1,147 @@
/*
Copyright 2023 The KubeVela Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package provider
import (
"errors"
"strings"
"sigs.k8s.io/controller-runtime/pkg/client"
monitorContext "github.com/kubevela/pkg/monitor/context"
wfContext "github.com/kubevela/workflow/pkg/context"
"github.com/kubevela/workflow/pkg/cue/model/value"
"github.com/kubevela/workflow/pkg/types"
"github.com/oam-dev/kubevela/pkg/config"
)
const (
// ProviderName is provider name
ProviderName = "config"
)
// ErrRequestInvalid means the request is invalid
var ErrRequestInvalid = errors.New("the request is in valid")
type provider struct {
factory config.Factory
}
// CreateConfigProperties the request body for creating a config
type CreateConfigProperties struct {
Name string `json:"name"`
Namespace string `json:"namespace"`
Template string `json:"template,omitempty"`
Config map[string]interface{} `json:"config"`
}
// Response the response body
type Response struct {
Status string `json:"status"`
Message string `json:"message"`
}
func (p *provider) Create(ctx monitorContext.Context, wfCtx wfContext.Context, v *value.Value, act types.Action) error {
var ccp CreateConfigProperties
if err := v.UnmarshalTo(&ccp); err != nil {
return ErrRequestInvalid
}
name := ccp.Template
namespace := "vela-system"
if strings.Contains(ccp.Template, "/") {
namespacedName := strings.SplitN(ccp.Template, "/", 2)
namespace = namespacedName[0]
name = namespacedName[1]
}
configItem, err := p.factory.ParseConfig(ctx.GetContext(), config.NamespacedName{
Name: name,
Namespace: namespace,
}, config.Metadata{
NamespacedName: config.NamespacedName{
Name: ccp.Name,
Namespace: ccp.Namespace,
},
Properties: ccp.Config,
})
if err != nil {
return err
}
return p.factory.CreateOrUpdateConfig(ctx.GetContext(), configItem, ccp.Namespace)
}
func (p *provider) Read(ctx monitorContext.Context, wfCtx wfContext.Context, v *value.Value, act types.Action) error {
var nn config.NamespacedName
if err := v.UnmarshalTo(&nn); err != nil {
return ErrRequestInvalid
}
content, err := p.factory.ReadConfig(ctx.GetContext(), nn.Namespace, nn.Name)
if err != nil {
return err
}
return v.FillObject(content, "config")
}
func (p *provider) List(ctx monitorContext.Context, wfCtx wfContext.Context, v *value.Value, act types.Action) error {
template, err := v.GetString("template")
if err != nil {
return ErrRequestInvalid
}
namespace, err := v.GetString("namespace")
if err != nil {
return ErrRequestInvalid
}
if strings.Contains(template, "/") {
namespacedName := strings.SplitN(template, "/", 2)
template = namespacedName[1]
}
configs, err := p.factory.ListConfigs(ctx.GetContext(), namespace, template, "", false)
if err != nil {
return err
}
var contents = []map[string]interface{}{}
for _, config := range configs {
contents = append(contents, map[string]interface{}{
"name": config.Name,
"alias": config.Alias,
"description": config.Description,
"config": config.Properties,
})
}
return v.FillObject(contents, "configs")
}
func (p *provider) Delete(ctx monitorContext.Context, wfCtx wfContext.Context, v *value.Value, act types.Action) error {
var nn config.NamespacedName
if err := v.UnmarshalTo(&nn); err != nil {
return errors.New("the request is in valid")
}
return p.factory.DeleteConfig(ctx.GetContext(), nn.Namespace, nn.Name)
}
// Install register handlers to provider discover.
func Install(p types.Providers, cli client.Client, apply config.Dispatcher) {
prd := &provider{
factory: config.NewConfigFactoryWithDispatcher(cli, apply),
}
p.Register(ProviderName, map[string]types.Handler{
"create": prd.Create,
"read": prd.Read,
"list": prd.List,
"delete": prd.Delete,
})
}

View File

@@ -0,0 +1,237 @@
/*
Copyright 2023 The KubeVela Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package provider
import (
"context"
"strings"
"testing"
"time"
monitorContext "github.com/kubevela/pkg/monitor/context"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"k8s.io/apimachinery/pkg/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest"
"k8s.io/utils/pointer"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/envtest"
wfContext "github.com/kubevela/workflow/pkg/context"
"github.com/kubevela/workflow/pkg/cue/model/value"
"github.com/oam-dev/kubevela/pkg/config"
)
var cfg *rest.Config
var k8sClient client.Client
var testEnv *envtest.Environment
var scheme = runtime.NewScheme()
var p *provider
func TestProvider(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Test Config Suite")
}
var _ = BeforeSuite(func(done Done) {
By("Bootstrapping test environment")
testEnv = &envtest.Environment{
ControlPlaneStartTimeout: time.Minute,
ControlPlaneStopTimeout: time.Minute,
UseExistingCluster: pointer.BoolPtr(false),
}
var err error
cfg, err = testEnv.Start()
Expect(err).ToNot(HaveOccurred())
Expect(cfg).ToNot(BeNil())
Expect(clientgoscheme.AddToScheme(scheme)).Should(BeNil())
// +kubebuilder:scaffold:scheme
By("Create the k8s client")
k8sClient, err = client.New(cfg, client.Options{Scheme: scheme})
Expect(err).ToNot(HaveOccurred())
Expect(k8sClient).ToNot(BeNil())
p = &provider{
factory: config.NewConfigFactory(k8sClient),
}
close(done)
}, 120)
var _ = AfterSuite(func() {
By("Tearing down the test environment")
err := testEnv.Stop()
Expect(err).ToNot(HaveOccurred())
})
var _ = Describe("Test the config provider", func() {
It("test creating a config", func() {
mCtx := monitorContext.NewTraceContext(context.Background(), "")
v, err := value.NewValue(`
name: "hub-kubevela"
namespace: "default"
template: "default/test-image-registry"
config: {
registry: "hub.kubevela.net"
}
`, nil, "")
Expect(err).ToNot(HaveOccurred())
err = p.Create(mCtx, new(wfContext.WorkflowContext), v, nil)
Expect(strings.Contains(err.Error(), "the template does not exist")).Should(BeTrue())
template, err := p.factory.ParseTemplate("test-image-registry", []byte(templateContent))
Expect(err).ToNot(HaveOccurred())
Expect(p.factory.CreateOrUpdateConfigTemplate(context.TODO(), "default", template)).ToNot(HaveOccurred())
Expect(p.Create(mCtx, new(wfContext.WorkflowContext), v, nil)).ToNot(HaveOccurred())
})
It("test creating a config without the template", func() {
mCtx := monitorContext.NewTraceContext(context.Background(), "")
v, err := value.NewValue(`
name: "www-kubevela"
namespace: "default"
config: {
url: "kubevela.net"
}
`, nil, "")
Expect(err).ToNot(HaveOccurred())
Expect(p.Create(mCtx, new(wfContext.WorkflowContext), v, nil)).ToNot(HaveOccurred())
})
It("test listing the config", func() {
mCtx := monitorContext.NewTraceContext(context.Background(), "")
v, err := value.NewValue(`
namespace: "default"
template: "test-image-registry"
`, nil, "")
Expect(err).ToNot(HaveOccurred())
Expect(p.List(mCtx, new(wfContext.WorkflowContext), v, nil)).ToNot(HaveOccurred())
configs, err := v.LookupValue("configs")
Expect(err).ToNot(HaveOccurred())
var contents []map[string]interface{}
Expect(configs.UnmarshalTo(&contents)).ToNot(HaveOccurred())
Expect(len(contents)).To(Equal(1))
Expect(contents[0]["config"].(map[string]interface{})["registry"]).To(Equal("hub.kubevela.net"))
})
It("test reading the config", func() {
mCtx := monitorContext.NewTraceContext(context.Background(), "")
v, err := value.NewValue(`
name: "hub-kubevela"
namespace: "default"
`, nil, "")
Expect(err).ToNot(HaveOccurred())
Expect(p.Read(mCtx, new(wfContext.WorkflowContext), v, nil)).ToNot(HaveOccurred())
registry, err := v.GetString("config", "registry")
Expect(err).ToNot(HaveOccurred())
Expect(registry).To(Equal("hub.kubevela.net"))
})
It("test deleting the config", func() {
mCtx := monitorContext.NewTraceContext(context.Background(), "")
v, err := value.NewValue(`
name: "hub-kubevela"
namespace: "default"
`, nil, "")
Expect(err).ToNot(HaveOccurred())
Expect(p.Delete(mCtx, new(wfContext.WorkflowContext), v, nil)).ToNot(HaveOccurred())
configs, err := p.factory.ListConfigs(context.Background(), "default", "", "", false)
Expect(err).ToNot(HaveOccurred())
Expect(len(configs)).To(Equal(1))
Expect(configs[0].Properties["url"]).To(Equal("kubevela.net"))
})
})
var templateContent = `
import (
"encoding/base64"
"encoding/json"
"strconv"
)
metadata: {
name: "image-registry"
alias: "Image Registry"
scope: "project"
description: "Config information to authenticate image registry"
sensitive: false
}
template: {
output: {
apiVersion: "v1"
kind: "Secret"
metadata: {
name: context.name
namespace: context.namespace
labels: {
"config.oam.dev/catalog": "velacore-config"
"config.oam.dev/type": "image-registry"
}
}
if parameter.auth != _|_ {
type: "kubernetes.io/dockerconfigjson"
}
if parameter.auth == _|_ {
type: "Opaque"
}
stringData: {
if parameter.auth != _|_ && parameter.auth.username != _|_ {
".dockerconfigjson": json.Marshal({
"auths": (parameter.registry): {
"username": parameter.auth.username
"password": parameter.auth.password
if parameter.auth.email != _|_ {
"email": parameter.auth.email
}
"auth": base64.Encode(null, (parameter.auth.username + ":" + parameter.auth.password))
}
})
}
if parameter.insecure != _|_ {
"insecure-skip-verify": strconv.FormatBool(parameter.insecure)
}
if parameter.useHTTP != _|_ {
"protocol-use-http": strconv.FormatBool(parameter.useHTTP)
}
}
}
parameter: {
// +usage=Image registry FQDN, such as: index.docker.io
registry: *"index.docker.io" | string
// +usage=Authenticate the image registry
auth?: {
// +usage=Private Image registry username
username: string
// +usage=Private Image registry password
password: string
// +usage=Private Image registry email
email?: string
}
// +usage=For the registry server that uses the self-signed certificate
insecure?: bool
// +usage=For the registry server that uses the HTTP protocol
useHTTP?: bool
}
}
`

View File

@@ -25,7 +25,9 @@ import (
pkgmulticluster "github.com/kubevela/pkg/multicluster"
utilfeature "k8s.io/apiserver/pkg/util/feature"
configprovider "github.com/oam-dev/kubevela/pkg/config/provider"
"github.com/oam-dev/kubevela/pkg/features"
"github.com/oam-dev/kubevela/pkg/utils/apply"
"github.com/crossplane/crossplane-runtime/pkg/meta"
"github.com/pkg/errors"
@@ -86,15 +88,21 @@ func (h *AppHandler) GenerateApplicationSteps(ctx monitorContext.Context,
af *appfile.Appfile,
appRev *v1beta1.ApplicationRevision) (*wfTypes.WorkflowInstance, []wfTypes.TaskRunner, error) {
appLabels := map[string]string{
oam.LabelAppName: app.Name,
oam.LabelAppNamespace: app.Namespace,
}
handlerProviders := providers.NewProviders()
kube.Install(handlerProviders, h.r.Client,
map[string]string{
oam.LabelAppName: app.Name,
oam.LabelAppNamespace: app.Namespace,
}, &kube.Handlers{
Apply: h.Dispatch,
Delete: h.Delete,
})
kube.Install(handlerProviders, h.r.Client, appLabels, &kube.Handlers{
Apply: h.Dispatch,
Delete: h.Delete,
})
configprovider.Install(handlerProviders, h.r.Client, func(ctx context.Context, resources []*unstructured.Unstructured, applyOptions []apply.ApplyOption) error {
for _, res := range resources {
res.SetLabels(util.MergeMapOverrideWithDst(res.GetLabels(), appLabels))
}
return h.resourceKeeper.Dispatch(ctx, resources, applyOptions)
})
oamProvider.Install(handlerProviders, app, af, h.r.Client, h.applyComponentFunc(
appParser, appRev, af), h.renderComponentFunc(appParser, appRev, af))
pCtx := velaprocess.NewContext(generateContextDataFromApp(app, appRev.Name))

View File

@@ -121,8 +121,8 @@ func loggingApply(msg string, desired client.Object, quiet bool) {
klog.InfoS(msg, "name", d.GetName(), "resource", desired.GetObjectKind().GroupVersionKind().String())
}
// filterRecordForSpecial will filter special object that can reduce the record for "app.oam.dev/last-applied-configuration" annotation.
func filterRecordForSpecial(desired client.Object) bool {
// trimLastAppliedConfigurationForSpecialResources will filter special object that can reduce the record for "app.oam.dev/last-applied-configuration" annotation.
func trimLastAppliedConfigurationForSpecialResources(desired client.Object) bool {
if desired == nil {
return false
}
@@ -159,7 +159,7 @@ func (a *APIApplicator) Apply(ctx context.Context, desired client.Object, ao ...
if err != nil {
return err
}
applyAct := &applyAction{updateAnnotation: filterRecordForSpecial(desired)}
applyAct := &applyAction{updateAnnotation: trimLastAppliedConfigurationForSpecialResources(desired)}
existing, err := a.createOrGetExisting(ctx, applyAct, a.c, desired, ao...)
if err != nil {
return err

View File

@@ -574,15 +574,15 @@ func TestFilterSpecialAnn(t *testing.T) {
var sc = &corev1.Secret{}
var dp = &appsv1.Deployment{}
var crd = &v1.CustomResourceDefinition{}
assert.Equal(t, false, filterRecordForSpecial(cm))
assert.Equal(t, false, filterRecordForSpecial(sc))
assert.Equal(t, false, filterRecordForSpecial(crd))
assert.Equal(t, true, filterRecordForSpecial(dp))
assert.Equal(t, false, trimLastAppliedConfigurationForSpecialResources(cm))
assert.Equal(t, false, trimLastAppliedConfigurationForSpecialResources(sc))
assert.Equal(t, false, trimLastAppliedConfigurationForSpecialResources(crd))
assert.Equal(t, true, trimLastAppliedConfigurationForSpecialResources(dp))
dp.Annotations = map[string]string{oam.AnnotationLastAppliedConfig: "-"}
assert.Equal(t, false, filterRecordForSpecial(dp))
assert.Equal(t, false, trimLastAppliedConfigurationForSpecialResources(dp))
dp.Annotations = map[string]string{oam.AnnotationLastAppliedConfig: "skip"}
assert.Equal(t, false, filterRecordForSpecial(dp))
assert.Equal(t, false, trimLastAppliedConfigurationForSpecialResources(dp))
dp.Annotations = map[string]string{oam.AnnotationLastAppliedConfig: "xxx"}
assert.Equal(t, true, filterRecordForSpecial(dp))
assert.Equal(t, true, trimLastAppliedConfigurationForSpecialResources(dp))
}

View File

@@ -164,7 +164,7 @@ func getOriginalConfiguration(obj runtime.Object) ([]byte, error) {
return nil, nil
}
original, ok := annots[oam.AnnotationLastAppliedConfig]
if !ok {
if !ok || original == "-" || original == "skip" {
return nil, nil
}
return []byte(original), nil

View File

@@ -24,6 +24,7 @@ import (
"os"
"path"
"path/filepath"
"regexp"
"strings"
"time"
@@ -32,6 +33,9 @@ import (
"helm.sh/helm/v3/pkg/chart"
"helm.sh/helm/v3/pkg/chart/loader"
"helm.sh/helm/v3/pkg/chartutil"
"helm.sh/helm/v3/pkg/cli"
"helm.sh/helm/v3/pkg/downloader"
"helm.sh/helm/v3/pkg/getter"
"helm.sh/helm/v3/pkg/kube"
"helm.sh/helm/v3/pkg/release"
relutil "helm.sh/helm/v3/pkg/releaseutil"
@@ -56,6 +60,12 @@ const (
valuesPatten = "repoUrl: %s, chart: %s, version: %s"
)
// ChartValues contain all values files in chart and default chart values
type ChartValues struct {
Data map[string]string
Values map[string]interface{}
}
// Helper provides helper functions for common Helm operations
type Helper struct {
cache *utils2.MemoryCacheStore
@@ -309,12 +319,22 @@ func (h *Helper) ListChartsFromRepo(repoURL string, skipCache bool, opts *common
}
// GetValuesFromChart will extract the parameter from a helm chart
func (h *Helper) GetValuesFromChart(repoURL string, chartName string, version string, skipCache bool, opts *common.HTTPOption) (map[string]interface{}, error) {
func (h *Helper) GetValuesFromChart(repoURL string, chartName string, version string, skipCache bool, repoType string, opts *common.HTTPOption) (*ChartValues, error) {
if h.cache != nil && !skipCache {
if v := h.cache.Get(fmt.Sprintf(valuesPatten, repoURL, chartName, version)); v != nil {
return v.(map[string]interface{}), nil
return v.(*ChartValues), nil
}
}
if repoType == "oci" {
v, err := fetchChartValuesFromOciRepo(repoURL, chartName, version, opts)
if err != nil {
return nil, err
}
if h.cache != nil {
h.cache.Put(fmt.Sprintf(valuesPatten, repoURL, chartName, version), v, 20*time.Minute)
}
return v, nil
}
i, err := h.GetIndexInfo(repoURL, skipCache, opts)
if err != nil {
return nil, err
@@ -334,10 +354,17 @@ func (h *Helper) GetValuesFromChart(repoURL string, chartName string, version st
if err != nil {
continue
}
if h.cache != nil {
h.cache.Put(fmt.Sprintf(valuesPatten, repoURL, chartName, version), c.Values, calculateCacheTimeFromIndex(len(i.Entries)))
v := &ChartValues{
Data: loadValuesYamlFile(c),
Values: c.Values,
}
return c.Values, nil
if err != nil {
return nil, err
}
if h.cache != nil {
h.cache.Put(fmt.Sprintf(valuesPatten, repoURL, chartName, version), v, calculateCacheTimeFromIndex(len(i.Entries)))
}
return v, nil
}
return nil, fmt.Errorf("cannot load chart from chart repo")
}
@@ -351,3 +378,49 @@ func calculateCacheTimeFromIndex(length int) time.Duration {
}
return cacheTime
}
// nolint
func fetchChartValuesFromOciRepo(repoURL string, chartName string, version string, opts *common.HTTPOption) (*ChartValues, error) {
d := downloader.ChartDownloader{
Verify: downloader.VerifyNever,
Getters: getter.All(cli.New()),
}
if opts != nil {
d.Options = append(d.Options, getter.WithInsecureSkipVerifyTLS(opts.InsecureSkipTLS),
getter.WithTLSClientConfig(opts.CertFile, opts.KeyFile, opts.CaFile),
getter.WithBasicAuth(opts.Username, opts.Password))
}
var err error
dest, err := os.MkdirTemp("", "helm-")
if err != nil {
return nil, errors.Wrap(err, "failed to fetch values file")
}
defer os.RemoveAll(dest)
chartRef := fmt.Sprintf("%s/%s", repoURL, chartName)
saved, _, err := d.DownloadTo(chartRef, version, dest)
if err != nil {
return nil, err
}
c, err := loader.Load(saved)
if err != nil {
return nil, errors.Wrap(err, "failed to fetch values file")
}
return &ChartValues{
Data: loadValuesYamlFile(c),
Values: c.Values,
}, nil
}
func loadValuesYamlFile(chart *chart.Chart) map[string]string {
result := map[string]string{}
re := regexp.MustCompile(`.*yaml$`)
for _, f := range chart.Raw {
if re.MatchString(f.Name) && !strings.Contains(f.Name, "/") && f.Name != "Chart.yaml" {
result[f.Name] = string(f.Data)
}
}
return result
}

View File

@@ -114,9 +114,9 @@ var _ = Describe("Test helm helper", func() {
It("Test getValues from chart", func() {
helper := NewHelper()
values, err := helper.GetValuesFromChart("./testdata", "autoscalertrait", "0.2.0", true, nil)
values, err := helper.GetValuesFromChart("./testdata", "autoscalertrait", "0.2.0", true, "helm", nil)
Expect(err).Should(BeNil())
Expect(values).ShouldNot(BeEmpty())
Expect(values).ShouldNot(BeNil())
})
})

View File

@@ -92,12 +92,26 @@ func MergeNoConflictLabels(labels map[string]string) MutateOption {
// CreateOrUpdateNamespace will create a namespace if not exist, it will also update a namespace if exists
// It will report an error if the labels conflict while it will override the annotations
func CreateOrUpdateNamespace(ctx context.Context, kubeClient client.Client, name string, options ...MutateOption) error {
err := CreateNamespace(ctx, kubeClient, name, options...)
// only if namespace don't have the env label that we need to update it
if apierrors.IsAlreadyExists(err) {
return UpdateNamespace(ctx, kubeClient, name, options...)
ns, err := GetNamespace(ctx, kubeClient, name)
switch {
case err == nil:
return PatchNamespace(ctx, kubeClient, ns, options...)
case apierrors.IsNotFound(err):
return CreateNamespace(ctx, kubeClient, name, options...)
default:
return err
}
return err
}
// PatchNamespace will patch a namespace
func PatchNamespace(ctx context.Context, kubeClient client.Client, ns *corev1.Namespace, options ...MutateOption) error {
original := ns.DeepCopy()
for _, op := range options {
if err := op(ns); err != nil {
return err
}
}
return kubeClient.Patch(ctx, ns, client.MergeFrom(original))
}
// CreateNamespace will create a namespace with mutate option

View File

@@ -167,7 +167,7 @@ func NewAddonEnableCommand(c common.Args, ioStream cmdutil.IOStreams) *cobra.Com
addonArgs[pkgaddon.InstallerRuntimeOption] = map[string]interface{}{
"upgrade": false,
}
var addonName string
if file, err := os.Stat(addonOrDir); err == nil {
if !file.IsDir() {
return fmt.Errorf("%s is not addon dir", addonOrDir)
@@ -178,13 +178,13 @@ func NewAddonEnableCommand(c common.Args, ioStream cmdutil.IOStreams) *cobra.Com
if err != nil {
return errors.Wrapf(err, "directory %s is invalid", addonOrDir)
}
name = filepath.Base(abs)
addonName = filepath.Base(abs)
if !yes2all {
if err := checkUninstallFromClusters(ctx, k8sClient, name, addonArgs); err != nil {
if err := checkUninstallFromClusters(ctx, k8sClient, addonName, addonArgs); err != nil {
return err
}
}
additionalInfo, err = enableAddonByLocal(ctx, name, addonOrDir, k8sClient, dc, config, addonArgs)
additionalInfo, err = enableAddonByLocal(ctx, addonName, addonOrDir, k8sClient, dc, config, addonArgs)
if err != nil {
return err
}
@@ -192,8 +192,12 @@ func NewAddonEnableCommand(c common.Args, ioStream cmdutil.IOStreams) *cobra.Com
if filepath.IsAbs(addonOrDir) || strings.HasPrefix(addonOrDir, ".") || strings.HasSuffix(addonOrDir, "/") {
return fmt.Errorf("addon directory %s not found in local file system", addonOrDir)
}
_, addonName, err = splitSpecifyRegistry(name)
if err != nil {
return fmt.Errorf("failed to split addonName and addonRegistry: %w", err)
}
if !yes2all {
if err := checkUninstallFromClusters(ctx, k8sClient, name, addonArgs); err != nil {
if err := checkUninstallFromClusters(ctx, k8sClient, addonName, addonArgs); err != nil {
return err
}
}
@@ -205,8 +209,8 @@ func NewAddonEnableCommand(c common.Args, ioStream cmdutil.IOStreams) *cobra.Com
if dryRun {
return nil
}
fmt.Printf("Addon %s enabled successfully.\n", name)
AdditionalEndpointPrinter(ctx, c, k8sClient, name, additionalInfo, false)
fmt.Printf("Addon %s enabled successfully.\n", addonName)
AdditionalEndpointPrinter(ctx, c, k8sClient, addonName, additionalInfo, false)
return nil
},
}

View File

@@ -17,6 +17,7 @@ limitations under the License.
package cli
import (
"context"
_ "embed"
"encoding/json"
"fmt"
@@ -52,6 +53,7 @@ import (
velacmd "github.com/oam-dev/kubevela/pkg/cmd"
cmdutil "github.com/oam-dev/kubevela/pkg/cmd/util"
"github.com/oam-dev/kubevela/pkg/utils/apply"
"github.com/oam-dev/kubevela/pkg/utils/env"
"github.com/oam-dev/kubevela/pkg/utils/util"
)
@@ -98,6 +100,7 @@ type AdoptOptions struct {
Apply bool
Recycle bool
Yes bool
AdoptTemplateFile string
AdoptTemplate string
@@ -133,6 +136,9 @@ func (opt *AdoptOptions) parseResourceRef(f velacmd.Factory, cmd *cobra.Command,
or.Name = parts[1]
if mapping.Scope.Name() == meta.RESTScopeNameNamespace {
or.Namespace = velacmd.GetNamespace(f, cmd)
if or.Namespace == "" {
or.Namespace = env.DefaultEnvNamespace
}
}
case 3:
or.Namespace = parts[1]
@@ -160,6 +166,9 @@ func (opt *AdoptOptions) Complete(f velacmd.Factory, cmd *cobra.Command, args []
}) {
opt.AppName = opt.NativeResourceRefs[0].Name
}
if opt.AppNamespace == "" {
opt.AppNamespace = opt.NativeResourceRefs[0].Namespace
}
case adoptTypeHelm:
if len(args) > 0 {
opt.HelmReleaseName = args[0]
@@ -188,6 +197,20 @@ func (opt *AdoptOptions) Complete(f velacmd.Factory, cmd *cobra.Command, args []
} else {
opt.AdoptTemplate = defaultAdoptTemplate
}
if opt.AppName != "" {
var ctx = context.Background()
app := &v1beta1.Application{}
err := f.Client().Get(ctx, apitypes.NamespacedName{Namespace: opt.AppNamespace, Name: opt.AppName}, app)
if err == nil && app != nil {
if !opt.Yes {
userInput := NewUserInput()
confirm := userInput.AskBool("Application '%s' already exists, apply will override the existing app with the adopted one, please confirm [Y/n]: "+opt.AppName, &UserInputOptions{AssumeYes: false})
if !confirm {
return nil
}
}
}
}
opt.AdoptTemplateCUEValue = cuecontext.New().CompileString(fmt.Sprintf("%s\n\n%s: %s", opt.AdoptTemplate, adoptCUETempVal, adoptCUETempFunc))
return nil
}
@@ -278,6 +301,12 @@ func (opt *AdoptOptions) render() (*v1beta1.Application, error) {
if err = json.Unmarshal(bs, app); err != nil {
return nil, fmt.Errorf("failed to parse template $returns into application: %w", err)
}
if app.Name == "" {
app.Name = opt.AppName
}
if app.Namespace == "" {
app.Namespace = opt.AppNamespace
}
return app, nil
}
@@ -450,6 +479,7 @@ func NewAdoptCommand(f velacmd.Factory, streams util.IOStreams) *cobra.Command {
cmd.Flags().StringVarP(&o.HelmDriver, "driver", "d", o.HelmDriver, "The storage backend of helm adoption. Only take effect when --type=helm.")
cmd.Flags().BoolVarP(&o.Apply, "apply", "", o.Apply, "If true, the application for adoption will be applied. Otherwise, it will only be printed.")
cmd.Flags().BoolVarP(&o.Recycle, "recycle", "", o.Recycle, "If true, when the adoption application is successfully applied, the old storage (like Helm secret) will be recycled.")
cmd.Flags().BoolVarP(&o.Yes, "yes", "y", o.Yes, "Skip confirmation prompt")
return velacmd.NewCommandBuilder(f, cmd).
WithNamespaceFlag().
WithResponsiveWriter().

View File

@@ -0,0 +1,58 @@
/*
Copyright 2021 The KubeVela Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cli
import (
"testing"
"github.com/stretchr/testify/assert"
"sigs.k8s.io/controller-runtime/pkg/client/config"
velacmd "github.com/oam-dev/kubevela/pkg/cmd"
"github.com/oam-dev/kubevela/pkg/utils/util"
)
func TestDefaultNamespace(t *testing.T) {
testcase := []struct {
namespace string
args []string
}{
{
namespace: "kube-system",
args: []string{"deployment/kube-system/metrics-server"},
},
{
namespace: "default",
args: []string{"deployment/metrics-server"},
},
}
for _, c := range testcase {
opt := &AdoptOptions{
Type: adoptTypeNative,
Mode: adoptModeReadOnly,
}
f := velacmd.NewDeferredFactory(config.GetConfig)
ioStream := util.IOStreams{}
cmd := NewAdoptCommand(f, ioStream)
err := opt.Complete(f, cmd, c.args)
if err != nil {
t.Fatalf("failed to parse resourceRef: %v", err)
}
assert.Equal(t, opt.AppNamespace, c.namespace)
}
}

View File

@@ -307,7 +307,7 @@ func (opt *DeleteOptions) Run(f velacmd.Factory, cmd *cobra.Command) error {
app := &v1beta1.Application{}
if err := f.Client().Get(cmd.Context(), apitypes.NamespacedName{Namespace: opt.Namespace, Name: appName}, app); err != nil {
if kerrors.IsNotFound(err) {
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "application %s/%s already deleted", opt.Namespace, appName)
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "application %s/%s already deleted\n", opt.Namespace, appName)
return nil
}
return fmt.Errorf("failed to get application %s/%s: %w", opt.Namespace, appName, err)

View File

@@ -19,7 +19,10 @@ package cli
import (
"fmt"
"github.com/go-logr/logr"
"github.com/spf13/cobra"
"k8s.io/klog/v2"
"sigs.k8s.io/controller-runtime/pkg/log"
"github.com/oam-dev/kubevela/apis/types"
"github.com/oam-dev/kubevela/pkg/utils/common"
@@ -50,6 +53,7 @@ func NewTopCommand(c common.Args, order string, ioStreams cmdutil.IOStreams) *co
if AllNamespace {
namespace = ""
}
klog.SetLogger(logr.New(log.NullLogSink{}))
return launchUI(c, namespace)
},
Annotations: map[string]string{

View File

@@ -34,9 +34,33 @@ import (
var appName = "app-e2e"
var appProject = "test-app-project"
func prepareEnv(envName string) {
var targetName = testNSprefix + strconv.FormatInt(time.Now().UnixNano(), 10)
// create target
var createTarget = apisv1.CreateTargetRequest{
Name: targetName,
Project: appProject,
Cluster: &apisv1.ClusterTarget{
ClusterName: "local",
Namespace: targetName,
},
}
res := post("/targets", createTarget)
Expect(decodeResponseBody(res, nil)).Should(Succeed())
// create env
var createEnvReq = apisv1.CreateEnvRequest{
Name: envName,
Targets: []string{targetName},
}
res = post("/envs", createEnvReq)
Expect(decodeResponseBody(res, nil)).Should(Succeed())
}
var _ = Describe("Test application rest api", func() {
It("Test create app", func() {
defer GinkgoRecover()
prepareEnv("dev-env")
var req = apisv1.CreateApplicationRequest{
Name: appName,
Project: appProject,
@@ -58,7 +82,7 @@ var _ = Describe("Test application rest api", func() {
Expect(cmp.Diff(appBase.Labels["test"], req.Labels["test"])).Should(BeEmpty())
})
It("Test list components", func() {
It("Test listing components", func() {
defer GinkgoRecover()
res := get("/applications/" + appName + "/components")
var components apisv1.ComponentListResponse
@@ -66,37 +90,42 @@ var _ = Describe("Test application rest api", func() {
Expect(cmp.Diff(len(components.Components), 1)).Should(BeEmpty())
})
It("Test updating a trigger", func() {
defer GinkgoRecover()
res := get("/applications/" + appName + "/triggers")
var triggers apisv1.ListApplicationTriggerResponse
Expect(decodeResponseBody(res, &triggers)).Should(Succeed())
Expect(cmp.Diff(len(triggers.Triggers), 1)).Should(BeEmpty())
old := triggers.Triggers[0]
var req = apisv1.UpdateApplicationTriggerRequest{
Alias: "Update",
Description: "Update the description",
WorkflowName: old.WorkflowName,
PayloadType: old.PayloadType,
ComponentName: old.ComponentName,
Registry: old.Registry,
}
res = put("/applications/"+appName+"/triggers/"+old.Token, req)
var base apisv1.ApplicationTriggerBase
Expect(decodeResponseBody(res, &base)).Should(Succeed())
Expect(cmp.Diff(base.Alias, req.Alias)).Should(BeEmpty())
Expect(cmp.Diff(base.Description, req.Description)).Should(BeEmpty())
})
It("Test detail application", func() {
defer GinkgoRecover()
res := get("/applications/" + appName)
var detail apisv1.DetailApplicationResponse
Expect(decodeResponseBody(res, &detail)).Should(Succeed())
Expect(cmp.Diff(len(detail.Policies), 0)).Should(BeEmpty())
// The policy for the dev-env environment
Expect(cmp.Diff(len(detail.Policies), 1)).Should(BeEmpty())
})
It("Test deploy application", func() {
defer GinkgoRecover()
var targetName = testNSprefix + strconv.FormatInt(time.Now().UnixNano(), 10)
var envName = "dev"
// create target
var createTarget = apisv1.CreateTargetRequest{
Name: targetName,
Project: appProject,
Cluster: &apisv1.ClusterTarget{
ClusterName: "local",
Namespace: targetName,
},
}
res := post("/targets", createTarget)
Expect(decodeResponseBody(res, nil)).Should(Succeed())
// create env
var createEnvReq = apisv1.CreateEnvRequest{
Name: envName,
Targets: []string{targetName},
}
res = post("/envs", createEnvReq)
Expect(decodeResponseBody(res, nil)).Should(Succeed())
prepareEnv(envName)
// create envbinding
var createEnvbindingReq = apisv1.CreateApplicationEnvbindingRequest{
@@ -104,7 +133,7 @@ var _ = Describe("Test application rest api", func() {
Name: envName,
},
}
res = post("/applications/"+appName+"/envs", createEnvbindingReq)
res := post("/applications/"+appName+"/envs", createEnvbindingReq)
Expect(decodeResponseBody(res, nil)).Should(Succeed())
// deploy app

View File

@@ -153,7 +153,7 @@ var _ = Describe("Test the rest api about the config", func() {
Expect(config.Secret).Should(BeNil())
Expect(config.Properties["registry"]).Should(Equal("kubevela.test.com"))
By("the config name is exist")
By("the config name does exist")
req = v1.CreateConfigRequest{
Name: "test-registry",
Alias: "Test Registry",
@@ -164,7 +164,7 @@ var _ = Describe("Test the rest api about the config", func() {
res = post("/configs", req)
Expect(res.StatusCode).Should(Equal(400))
By("the template is not exist")
By("the template does not exist")
req = v1.CreateConfigRequest{
Name: "test-registry2",
Alias: "Test Registry",

View File

@@ -0,0 +1,42 @@
/*
Copyright 2022 The KubeVela Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package e2e_apiserver_test
import (
"io"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("Helm rest api test", func() {
Describe("helm repo api test", func() {
It("test fetching chart values in OCI registry", func() {
resp := getWithQuery("/repository/chart/values", map[string]string{
"repoUrl": "oci://ghcr.io",
"chart": "stefanprodan/charts/podinfo",
"repoType": "oci",
"version": "6.1.0",
})
defer resp.Body.Close()
values, err := io.ReadAll(resp.Body)
Expect(err).Should(BeNil())
Expect(len(values)).ShouldNot(BeEquivalentTo(0))
})
})
})

View File

@@ -191,6 +191,26 @@ func get(path string) *http.Response {
return response
}
func getWithQuery(path string, params map[string]string) *http.Response {
client := &http.Client{}
if !strings.HasPrefix(path, "/v1") {
path = baseURL + path
} else {
path = baseDomain + path
}
req, err := http.NewRequest(http.MethodGet, path, nil)
Expect(err).Should(BeNil())
req.Header.Add("Authorization", token)
query := req.URL.Query()
for k, v := range params {
query.Set(k, v)
}
req.URL.RawQuery = query.Encode()
response, err := client.Do(req)
Expect(err).Should(BeNil())
return response
}
func delete(path string) *http.Response {
client := &http.Client{}
if !strings.HasPrefix(path, "/v1") {

View File

@@ -9,7 +9,7 @@
template: {
#PolicyRule: {
// +usage=Specify how to select the targets of the rule
selector: [...#RuleSelector]
selector: #RuleSelector
}
#RuleSelector: {

View File

@@ -64,7 +64,7 @@ template: {
}
}
parameter: *#PatchParams | close({
parameter: #PatchParams | close({
// +usage=Specify the container image for multiple containers
containers: [...#PatchParams]
})

View File

@@ -18,7 +18,10 @@ expose: {
}
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"
}
@@ -28,11 +31,16 @@ expose: {
}
"""#
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
}
"""#
}

View File

@@ -113,7 +113,7 @@ template: {
#ECProvider: {
type: "ec"
apiKey: *"" | string
name: "ec-provider" | string
name: *"ec-provider" | string
}
#GCPProvider: {
credentials: string

View File

@@ -51,44 +51,41 @@ template: {
// +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]
})
}
}
@@ -109,11 +106,11 @@ template: {
// +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