diff --git a/.gitignore b/.gitignore index f14da075..7950ec30 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ paas/action/test.sh mvn_deploy.sh mvn_install.sh *.iml +*.swp diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 10646f30..807260f8 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -46,3 +46,4 @@ This Code of Conduct is adapted from the [Contributor Covenant][homepage], versi [version]: https://contributor-covenant.org/version/1/4/ + diff --git a/README-CN.md b/README-CN.md index 47fb99af..f2733405 100644 --- a/README-CN.md +++ b/README-CN.md @@ -10,6 +10,8 @@

产品文档 + 开源官网 + 国内代码库

--- @@ -37,12 +39,12 @@ SREWorks 作为阿里云大数据SRE团队对SRE理念的工程实践,专注 回归到运维领域的需求,无论上层产品和业务形态怎么变化,运维本质上解决的还是“质量、成本、效率、安全”相关需求。SREWorks 用一个运维 SaaS 应用界面来支撑上述需求,同时以“数智”思想为内核驱动 SaaS 能力,具体包括交付、监测、管理、控制、运营、服务六部分。 -![image.png](/paas/sw-frontend/docs/pictures/1650211475047-fdfccb84-61bd-4e1f-8451-9505847a48a7.png) +![image.png](paas/sw-frontend/docs/docs/pictures/1666944785433-f3417e59-35be-420c-9f11-fae88b4f7e30.jpeg.png) ## 入门指南 -- [快速安装](/paas/sw-frontend/docs/documents/rr5g10.md) -- [源码安装](/paas/sw-frontend/docs/documents/mzz07m.md) +- [快速安装](/paas/sw-frontend/docs/docs/rr5g10.md) +- [源码安装](/paas/sw-frontend/docs/docs/mzz07m.md) - [产品文档](https://www.yuque.com/sreworks-doc/docs/) - [在线体验](https://wj.qq.com/s2/10565748/53da/) diff --git a/README.md b/README.md index d2d22ab1..bb638287 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@

Documentation + Website

--- @@ -31,12 +32,12 @@ Alibaba Cloud Big Data SRE team has been working hard to practice the "DataOps a There are many excellent open-source O & M platforms that reflect cloud-native scenarios in the traditional IT O&M field. There are currently no systematic O & M solutions available. With the rise of the cloud-native era, the Alibaba Cloud Big Data SRE team will open-source its O & M platform, SREWorks, in the hopes of providing O & M engineers with an out-of-the-box experience. -![image.png](paas/sw-frontend/docs/pictures/1650534633770-0f784bd7-1996-473a-9b6f-91a54064a155.png) +![image.png](paas/sw-frontend/docs/docs/pictures/1663627633334-32214451-31cf-4e1a-b0a3-3cc3047ab842.jpeg.png) ## Getting Started -- [Quick Install](/paas/sw-frontend/docs/documents/rr5g10.md) -- [Installation from source code](/paas/sw-frontend/docs/documents/mzz07m.md) +- [Quick Install](/paas/sw-frontend/docs/docs/rr5g10.md) +- [Installation from source code](/paas/sw-frontend/docs/docs/mzz07m.md) - [Document](https://www.yuque.com/sreworks-doc/docs/) - [Online Demo](https://wj.qq.com/s2/10565748/53da/) diff --git a/build.sh b/build.sh index fe282001..e74d132c 100755 --- a/build.sh +++ b/build.sh @@ -236,34 +236,34 @@ target_swcli(){ download_packages(){ PKG_URL="${SREWORKS_BUILTIN_PACKAGE_URL}/${tag}" - mkdir -p $SW_ROOT/saas/desktop/ui/ && wget "${PKG_URL}/saas/desktop/ui/desktop-auto.zip" -O $SW_ROOT/saas/desktop/ui/desktop-auto.zip - mkdir -p $SW_ROOT/saas/swadmin/ui/ && wget "${PKG_URL}/saas/swadmin/ui/swadmin-auto.zip" -O $SW_ROOT/saas/swadmin/ui/swadmin-auto.zip - mkdir -p $SW_ROOT/saas/system/ui/ && wget "${PKG_URL}/saas/system/ui/system-auto.zip" -O $SW_ROOT/saas/system/ui/system-auto.zip - mkdir -p $SW_ROOT/saas/upload/ui/ && wget "${PKG_URL}/saas/upload/ui/upload-auto.zip" -O $SW_ROOT/saas/upload/ui/upload-auto.zip - mkdir -p $SW_ROOT/saas/team/ui/ && wget "${PKG_URL}/saas/team/ui/team-auto.zip" -O $SW_ROOT/saas/team/ui/team-auto.zip - mkdir -p $SW_ROOT/saas/search/ui/ && wget "${PKG_URL}/saas/search/ui/search-auto.zip" -O $SW_ROOT/saas/search/ui/search-auto.zip - mkdir -p $SW_ROOT/saas/ocenter/ui/ && wget "${PKG_URL}/saas/ocenter/ui/ocenter-auto.zip" -O $SW_ROOT/saas/ocenter/ui/ocenter-auto.zip - mkdir -p $SW_ROOT/saas/aiops/ui/ && wget "${PKG_URL}/saas/aiops/ui/aiops-auto.zip" -O $SW_ROOT/saas/aiops/ui/aiops-auto.zip - mkdir -p $SW_ROOT/saas/app/ui/ && wget "${PKG_URL}/saas/app/ui/app-auto.zip" -O $SW_ROOT/saas/app/ui/app-auto.zip - mkdir -p $SW_ROOT/saas/cluster/ui/ && wget "${PKG_URL}/saas/cluster/ui/cluster-auto.zip" -O $SW_ROOT/saas/cluster/ui/cluster-auto.zip - mkdir -p $SW_ROOT/saas/dataops/ui/data/ && wget "${PKG_URL}/saas/dataops/ui/data/data-auto.zip" -O $SW_ROOT/saas/dataops/ui/data/data-auto.zip - mkdir -p $SW_ROOT/saas/healing/ui/ && wget "${PKG_URL}/saas/healing/ui/healing-auto.zip" -O $SW_ROOT/saas/healing/ui/healing-auto.zip - mkdir -p $SW_ROOT/saas/health/ui/ && wget "${PKG_URL}/saas/health/ui/health-auto.zip" -O $SW_ROOT/saas/health/ui/health-auto.zip - mkdir -p $SW_ROOT/saas/help/ui/ && wget "${PKG_URL}/saas/help/ui/help-auto.zip" -O $SW_ROOT/saas/help/ui/help-auto.zip - mkdir -p $SW_ROOT/saas/job/ui/ && wget "${PKG_URL}/saas/job/ui/job-auto.zip" -O $SW_ROOT/saas/job/ui/job-auto.zip - mkdir -p $SW_ROOT/saas/template/ui/ && wget "${PKG_URL}/saas/template/ui/template-auto.zip" -O $SW_ROOT/saas/template/ui/template-auto.zip + #mkdir -p $SW_ROOT/saas/desktop/ui/ && wget "${PKG_URL}/saas/desktop/ui/desktop-auto.zip" -O $SW_ROOT/saas/desktop/ui/desktop-auto.zip + #mkdir -p $SW_ROOT/saas/swadmin/ui/ && wget "${PKG_URL}/saas/swadmin/ui/swadmin-auto.zip" -O $SW_ROOT/saas/swadmin/ui/swadmin-auto.zip + #mkdir -p $SW_ROOT/saas/system/ui/ && wget "${PKG_URL}/saas/system/ui/system-auto.zip" -O $SW_ROOT/saas/system/ui/system-auto.zip + #mkdir -p $SW_ROOT/saas/upload/ui/ && wget "${PKG_URL}/saas/upload/ui/upload-auto.zip" -O $SW_ROOT/saas/upload/ui/upload-auto.zip + #mkdir -p $SW_ROOT/saas/team/ui/ && wget "${PKG_URL}/saas/team/ui/team-auto.zip" -O $SW_ROOT/saas/team/ui/team-auto.zip + #mkdir -p $SW_ROOT/saas/search/ui/ && wget "${PKG_URL}/saas/search/ui/search-auto.zip" -O $SW_ROOT/saas/search/ui/search-auto.zip + #mkdir -p $SW_ROOT/saas/ocenter/ui/ && wget "${PKG_URL}/saas/ocenter/ui/ocenter-auto.zip" -O $SW_ROOT/saas/ocenter/ui/ocenter-auto.zip + #mkdir -p $SW_ROOT/saas/aiops/ui/ && wget "${PKG_URL}/saas/aiops/ui/aiops-auto.zip" -O $SW_ROOT/saas/aiops/ui/aiops-auto.zip + #mkdir -p $SW_ROOT/saas/app/ui/ && wget "${PKG_URL}/saas/app/ui/app-auto.zip" -O $SW_ROOT/saas/app/ui/app-auto.zip + #mkdir -p $SW_ROOT/saas/cluster/ui/ && wget "${PKG_URL}/saas/cluster/ui/cluster-auto.zip" -O $SW_ROOT/saas/cluster/ui/cluster-auto.zip + #mkdir -p $SW_ROOT/saas/dataops/ui/data/ && wget "${PKG_URL}/saas/dataops/ui/data/data-auto.zip" -O $SW_ROOT/saas/dataops/ui/data/data-auto.zip + #mkdir -p $SW_ROOT/saas/healing/ui/ && wget "${PKG_URL}/saas/healing/ui/healing-auto.zip" -O $SW_ROOT/saas/healing/ui/healing-auto.zip + #mkdir -p $SW_ROOT/saas/health/ui/ && wget "${PKG_URL}/saas/health/ui/health-auto.zip" -O $SW_ROOT/saas/health/ui/health-auto.zip + #mkdir -p $SW_ROOT/saas/help/ui/ && wget "${PKG_URL}/saas/help/ui/help-auto.zip" -O $SW_ROOT/saas/help/ui/help-auto.zip + #mkdir -p $SW_ROOT/saas/job/ui/ && wget "${PKG_URL}/saas/job/ui/job-auto.zip" -O $SW_ROOT/saas/job/ui/job-auto.zip + #mkdir -p $SW_ROOT/saas/template/ui/ && wget "${PKG_URL}/saas/template/ui/template-auto.zip" -O $SW_ROOT/saas/template/ui/template-auto.zip - wget "${PKG_URL}/saas/aiops/aiops.zip" -O $SW_ROOT/saas/aiops/aiops.zip - wget "${PKG_URL}/saas/app/app.zip" -O $SW_ROOT/saas/app/app.zip - wget "${PKG_URL}/saas/cluster/cluster.zip" -O $SW_ROOT/saas/cluster/cluster.zip - wget "${PKG_URL}/saas/dataops/data.zip" -O $SW_ROOT/saas/dataops/data.zip - wget "${PKG_URL}/saas/health/health.zip" -O $SW_ROOT/saas/health/health.zip - wget "${PKG_URL}/saas/job/job.zip" -O $SW_ROOT/saas/job/job.zip - wget "${PKG_URL}/saas/search/search.zip" -O $SW_ROOT/saas/search/search.zip + #wget "${PKG_URL}/saas/aiops/aiops.zip" -O $SW_ROOT/saas/aiops/aiops.zip + #wget "${PKG_URL}/saas/app/app.zip" -O $SW_ROOT/saas/app/app.zip + #wget "${PKG_URL}/saas/cluster/cluster.zip" -O $SW_ROOT/saas/cluster/cluster.zip + #wget "${PKG_URL}/saas/dataops/data.zip" -O $SW_ROOT/saas/dataops/data.zip + #wget "${PKG_URL}/saas/health/health.zip" -O $SW_ROOT/saas/health/health.zip + #wget "${PKG_URL}/saas/job/job.zip" -O $SW_ROOT/saas/job/job.zip + #wget "${PKG_URL}/saas/search/search.zip" -O $SW_ROOT/saas/search/search.zip wget "${PKG_URL}/saas/swcore/flycore.zip" -O $SW_ROOT/saas/swcore/flycore.zip - wget "${PKG_URL}/saas/system/system.zip" -O $SW_ROOT/saas/system/system.zip - wget "${PKG_URL}/saas/team/team.zip" -O $SW_ROOT/saas/team/team.zip - wget "${PKG_URL}/saas/upload/upload.zip" -O $SW_ROOT/saas/upload/upload.zip + #wget "${PKG_URL}/saas/system/system.zip" -O $SW_ROOT/saas/system/system.zip + #wget "${PKG_URL}/saas/team/team.zip" -O $SW_ROOT/saas/team/team.zip + #wget "${PKG_URL}/saas/upload/upload.zip" -O $SW_ROOT/saas/upload/upload.zip } @@ -278,6 +278,7 @@ target_swcli_builtin_package(){ download_packages cp -r $SW_ROOT/saas $SW_ROOT/paas/swcli/builtin_package/saas cp -r $SW_ROOT/chart $SW_ROOT/paas/swcli/builtin_package/chart + cp -r $SW_ROOT/plugins $SW_ROOT/paas/swcli/builtin_package/plugins TMP_DOCKERFILE="/tmp/${RANDOM}.dockerfile" envsubst < $SW_ROOT/paas/swcli/Dockerfile_builtin_package.tpl > ${TMP_DOCKERFILE} docker build -t swcli-builtin-package:$tag -f ${TMP_DOCKERFILE} $SW_ROOT/paas/swcli diff --git a/built-in.json b/built-in.json index a842124b..18f98fae 100644 --- a/built-in.json +++ b/built-in.json @@ -3,11 +3,56 @@ "packagePath": "saas/template/build" },{ "appId": "job", - "packagePath": "saas/job/build" + "packagePath": "saas/job/build", + "patch": "saas/job/api/patch.yaml" },{ "appId": "app", - "packagePath": "saas/app/build" + "packagePath": "saas/app/build", + "patch": "saas/app/api/patch.yaml" },{ "appId": "cluster", - "packagePath": "saas/cluster/build" + "packagePath": "saas/cluster/build", + "patch": "saas/cluster/api/patch.yaml" +},{ + "appId": "swadmin", + "packagePath": "saas/swadmin/build" +},{ + "appId": "team", + "packagePath": "saas/team/build", + "patch": "saas/team/api/patch.yaml" +},{ + "appId": "help", + "packagePath": "saas/help/build" +},{ + "appId": "health", + "packagePath": "saas/health/build", + "patch": "saas/health/api/patch.yaml" +},{ + "appId": "search", + "packagePath": "saas/search/build", + "patch": "saas/search/api/patch.yaml" +},{ + "appId": "upload", + "packagePath": "saas/upload/build", + "patch": "saas/upload/api/patch.yaml" +},{ + "appId": "ocenter", + "packagePath": "saas/ocenter/build" +},{ + "appId": "healing", + "packagePath": "saas/healing/build" +},{ + "appId": "desktop", + "packagePath": "saas/desktop/build" +},{ + "appId": "aiops", + "packagePath": "saas/aiops/build", + "patch": "saas/aiops/api/patch.yaml" +},{ + "appId": "system", + "packagePath": "saas/system/build" +},{ + "appId": "dataops", + "packagePath": "saas/dataops/build", + "patch": "saas/dataops/api/patch.yaml" }] diff --git a/chart/sreworks-chart/charts/appmanager/templates/server-deployment.yaml b/chart/sreworks-chart/charts/appmanager/templates/server-deployment.yaml index 94c5225e..321c4258 100644 --- a/chart/sreworks-chart/charts/appmanager/templates/server-deployment.yaml +++ b/chart/sreworks-chart/charts/appmanager/templates/server-deployment.yaml @@ -34,8 +34,13 @@ spec: ports: - containerPort: 7001 envFrom: + {{- if .Values.server.sreworksEnvs }} + - configMapRef: + name: init-configmap + {{- end }} - configMapRef: name: {{ template "name.server-configmap" . }} + securityContext: privileged: true {{- end -}} diff --git a/chart/sreworks-chart/charts/appmanager/values.yaml b/chart/sreworks-chart/charts/appmanager/values.yaml index ee0ea870..54634ca9 100644 --- a/chart/sreworks-chart/charts/appmanager/values.yaml +++ b/chart/sreworks-chart/charts/appmanager/values.yaml @@ -18,6 +18,7 @@ images: rbacProxy: sreworks-registry.cn-beijing.cr.aliyuncs.com/mirror/kube-rbac-proxy:v0.8.0 server: + sreworksEnvs: false rbac: admin database: #host: diff --git a/chart/sreworks-chart/charts/appmanagerbase/values.yaml b/chart/sreworks-chart/charts/appmanagerbase/values.yaml index 5b4d400e..69cccf95 100644 --- a/chart/sreworks-chart/charts/appmanagerbase/values.yaml +++ b/chart/sreworks-chart/charts/appmanagerbase/values.yaml @@ -111,7 +111,7 @@ kruise: enabled: true kafka: - enabled: true + enabled: false persistence: size: 20Gi diff --git a/chart/sreworks-chart/templates/NOTES.txt b/chart/sreworks-chart/templates/NOTES.txt index 7ae49287..60e69988 100644 --- a/chart/sreworks-chart/templates/NOTES.txt +++ b/chart/sreworks-chart/templates/NOTES.txt @@ -1,4 +1,9 @@ +Please execute following command in terminal to trace the install progress: + +> +> kubectl logs job.batch/sreworks-progress-check -nsreworks -f +> After install finished (5-10mins) open the following URL in your browser: diff --git a/chart/sreworks-chart/templates/init-configmap.yaml b/chart/sreworks-chart/templates/init-configmap.yaml index c3d9c8db..bcaef87e 100644 --- a/chart/sreworks-chart/templates/init-configmap.yaml +++ b/chart/sreworks-chart/templates/init-configmap.yaml @@ -17,6 +17,7 @@ data: JRE11_IMAGE: {{ .Values.global.artifacts.openjdk11Image }} MAVEN_SETTINGS_XML: {{ .Values.global.artifacts.mavenSettingsXml }} NODE_IMAGE: {{ .Values.global.artifacts.nodeImage }} + NODE_IMAGE2: {{ .Values.global.artifacts.nodeImage2 }} ALPINE_IMAGE: {{ .Values.global.artifacts.alpineImage }} MIGRATE_IMAGE: {{ template "migrate.image" . }} POSTRUN_IMAGE: {{ template "postrun.image" . }} @@ -68,7 +69,7 @@ data: ZOOKEEPER_ENDPOINT: {{ .Release.Name }}-zookeeper ENDPOINT_PAAS_MINIO: {{ template "minio.endpoint" . }} APPMANAGER_ENDPOINT: {{ .Release.Name }}-appmanager - KAFKA_ENDPOINT: {{ .Release.Name }}-kafka.{{ .Release.Namespace }} + KAFKA_ENDPOINT: prod-dataops-kafka.sreworks-dataops AUTHPROXY_ENDPOINT: {{ .Values.core.stageId }}-{{ .Values.core.appId }}-paas-authproxy REDIS_ENDPOINT: {{ .Release.Name }}-redis-master.{{ .Release.Namespace }} REDIS_PASSWORD: {{ .Values.appmanagerbase.redis.password | quote }} @@ -103,14 +104,20 @@ data: DATAOPS_DB_PASSWORD: {{ .Values.saas.dataops.dbPassword | quote }} DATAOPS_DB_PORT: {{ .Values.saas.dataops.dbPort | quote }} DATAOPS_DB_USER: {{ .Values.saas.dataops.dbUser | quote }} + DATA_DB_HOST: {{ .Values.saas.dataops.dbHost | quote }} + DATA_DB_PASSWORD: {{ .Values.saas.dataops.dbPassword | quote }} + DATA_DB_PORT: {{ .Values.saas.dataops.dbPort | quote }} + DATA_DB_USER: {{ .Values.saas.dataops.dbUser | quote }} GRAFANA_ADMIN_PASSWORD: {{ .Values.saas.grafana.password | quote }} DATA_ES_HOST: {{ .Values.saas.dataops.esHost | quote }} DATA_ES_PORT: {{ .Values.saas.dataops.esPort | quote }} DATA_ES_USER: {{ .Values.saas.dataops.esUser | quote }} DATA_ES_PASSWORD: {{ .Values.saas.dataops.esPassword | quote }} + DATAOPS_FILEBEAT_ENABLE: {{ .Values.saas.dataops.filebeatEnable | quote}} + DATAOPS_METRICBEAT_ENABLE: {{ .Values.saas.dataops.metricbeatEnable | quote}} - DATA_PROM_HOST: "localhost" - DATA_PROM_PORT: "80" + DATA_PROM_HOST: {{ .Values.saas.dataops.prometheusHost | quote }} + DATA_PROM_PORT: {{ .Values.saas.dataops.prometheusPort | quote }} ACCOUNT_SUPER_CLIENT_ID: {{ .Values.appmanager.gateway.account_super_client_id }} ACCOUNT_SUPER_CLIENT_SECRET: {{ .Values.appmanager.gateway.account_super_client_secret }} diff --git a/chart/sreworks-chart/templates/init-run.yaml b/chart/sreworks-chart/templates/init-run.yaml index 72d13765..c16bcf1a 100644 --- a/chart/sreworks-chart/templates/init-run.yaml +++ b/chart/sreworks-chart/templates/init-run.yaml @@ -16,6 +16,8 @@ data: #fi #cd sreworks-flycore + sh /app/upload-plugins.sh + cd /root/saas/swcore/api/core/ @@ -46,7 +48,7 @@ data: fi result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id=${CORE_APP_ID} --filepath /root/saas/swcore/flycore.zip --print-only-app-package-id=true --reset-version=true) - /root/swcli --config /swcli/swcli.yaml deployment launch --app-id=${CORE_APP_ID} --stage=prod --namespace=${NAMESPACE_ID} --path /root/saas/swcore/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master + /root/swcli --config /swcli/swcli.yaml deployment launch --wait-max-seconds 300 --app-id=${CORE_APP_ID} --stage=prod --namespace=${NAMESPACE_ID} --path /root/saas/swcore/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master fi @@ -56,30 +58,30 @@ data: sh /app/core-action-service-check.sh # import&launch saas desktop - envsubst < /root/saas/desktop/launch-v2.yaml.tpl > /root/saas/desktop/launch.yaml - envsubst < /root/saas/desktop/launch-v2-dev.yaml.tpl > /root/saas/desktop/launch-dev.yaml + envsubst < /root/saas/desktop/build/launch-frontend.yaml.tpl > /root/saas/desktop/launch-frontend.yaml + envsubst < /root/saas/desktop/build/launch-frontend-dev.yaml.tpl > /root/saas/desktop/launch-frontend-dev.yaml if [[ "$ONLY_BASE" == "true" ]] ; then - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id desktop --filepath /root/saas/desktop/ui/desktop-nosearch.zip --print-only-app-package-id=true --reset-version=true) - else - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id desktop --filepath /root/saas/desktop/ui/desktop-auto.zip --print-only-app-package-id=true --reset-version=true) + sed -i 's/searchConfig\\":true/searchConfig\\":false/g' /root/saas/desktop/build/INTERNAL_ADDON_productopsv2.zip.dir/content.json fi - /root/swcli --config /swcli/swcli.yaml deployment launch --app-id desktop --stage=prod --namespace=${NAMESPACE_ID} --path /root/saas/desktop/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --app-id desktop --stage=dev --namespace=${NAMESPACE_ID} --path /root/saas/desktop/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master - - # import&launch saas swadmin - envsubst < /root/saas/swadmin/launch-v2.yaml.tpl > /root/saas/swadmin/launch.yaml - envsubst < /root/saas/swadmin/launch-v2-dev.yaml.tpl > /root/saas/swadmin/launch-dev.yaml - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id swadmin --filepath /root/saas/swadmin/ui/swadmin-auto.zip --print-only-app-package-id=true --reset-version=true) - /root/swcli --config /swcli/swcli.yaml deployment launch --app-id swadmin --path /root/saas/swadmin/launch.yaml --stage=prod --namespace=${NAMESPACE_ID} --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --app-id swadmin --path /root/saas/swadmin/launch-dev.yaml --stage dev --namespace=${NAMESPACE_ID} --app-package-id $result --arch x86 --wait=true --cluster master + python /app/pack.py --src /root/saas/desktop/build --dest /root/saas/desktop/build.zip + + sh /app/import.sh desktop /root/saas/desktop/build.zip /root/saas/desktop/launch-frontend.yaml /root/saas/desktop/launch-frontend-dev.yaml + + # import&launch saas swadmin + python /app/pack.py --src /root/saas/swadmin/build --dest /root/saas/swadmin/build.zip + envsubst < /root/saas/swadmin/build/launch-frontend.yaml.tpl > /root/saas/swadmin/launch-frontend.yaml + envsubst < /root/saas/swadmin/build/launch-frontend-dev.yaml.tpl > /root/saas/swadmin/launch-frontend-dev.yaml + + sh /app/import.sh swadmin /root/saas/swadmin/build.zip /root/saas/swadmin/launch-frontend.yaml /root/saas/swadmin/launch-frontend-dev.yaml + # import&launch saas template - envsubst < /root/saas/template/launch-v2.yaml.tpl > /root/saas/template/launch.yaml - envsubst < /root/saas/template/launch-v2-dev.yaml.tpl > /root/saas/template/launch-dev.yaml - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id template --filepath /root/saas/template/ui/template-auto.zip --print-only-app-package-id=true --reset-version=true) - /root/swcli --config /swcli/swcli.yaml deployment launch --app-id template --path /root/saas/template/launch.yaml --stage=prod --namespace=${NAMESPACE_ID} --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --app-id template --path /root/saas/template/launch-dev.yaml --stage dev --namespace=${NAMESPACE_ID} --app-package-id $result --arch x86 --wait=true --cluster master + python /app/pack.py --src /root/saas/template/build --dest /root/saas/template/build.zip + envsubst < /root/saas/template/build/launch-frontend.yaml.tpl > /root/saas/template/launch-frontend.yaml + envsubst < /root/saas/template/build/launch-frontend-dev.yaml.tpl > /root/saas/template/launch-frontend-dev.yaml + + sh /app/import.sh template /root/saas/template/build.zip /root/saas/template/launch-frontend.yaml /root/saas/template/launch-frontend-dev.yaml fi @@ -123,42 +125,28 @@ data: # build&launch cluster api export NAMESPACE_ID=$(cat /run/secrets/kubernetes.io/serviceaccount/namespace) envsubst < /root/saas/cluster/api/build.yaml.tpl > /root/saas/cluster/api/build.yaml - envsubst < /root/saas/cluster/api/launch.yaml.tpl > /root/saas/cluster/api/launch.yaml - envsubst < /root/saas/cluster/ui/launch-v2.yaml.tpl > /root/saas/cluster/ui/launch.yaml - envsubst < /root/saas/cluster/ui/launch-v2-dev.yaml.tpl > /root/saas/cluster/ui/launch-dev.yaml + envsubst < /root/saas/cluster/build/launch.yaml.tpl > /root/saas/cluster/launch.yaml + envsubst < /root/saas/cluster/build/launch-backend.yaml.tpl > /root/saas/cluster/launch-backend.yaml + envsubst < /root/saas/cluster/build/launch-frontend.yaml.tpl > /root/saas/cluster/launch-frontend.yaml + envsubst < /root/saas/cluster/build/launch-frontend-dev.yaml.tpl > /root/saas/cluster/launch-frontend-dev.yaml + python /app/pack.py --src /root/saas/cluster/build --dest /root/saas/cluster/build.zip if [[ "$IMAGE_BUILD_ENABLE" == "true" ]] ; then cd /root/saas/cluster/api/ - /root/swcli --config /swcli/swcli.yaml app-package oneflow --app-id=cluster --stage=prod --namespace=${NAMESPACE_ID} --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=./launch.yaml --disable-dir-check + /root/swcli --config /swcli/swcli.yaml app-package oneflow --app-id=cluster --stage=prod --namespace=${NAMESPACE_ID} --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=../launch-backend.yaml --disable-dir-check # wait flycore if [[ "$IMPORT_FRONTEND" == "true" ]] ; then - # import&launch cluster ui - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id cluster --filepath /root/saas/cluster/ui/cluster-auto.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id cluster --path /root/saas/cluster/ui/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id cluster --path /root/saas/cluster/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master + sh /app/import.sh cluster /root/saas/cluster/build.zip /root/saas/cluster/launch-frontend.yaml /root/saas/cluster/launch-frontend-dev.yaml + fi else - cd /root/saas/cluster/ - - sh /app/core-action-service-check.sh - - echo "" > merge-launch.yaml - cat /root/saas/cluster/api/launch.yaml >> merge-launch.yaml - echo "---" >> merge-launch.yaml - cat /root/saas/cluster/ui/launch.yaml >> merge-launch.yaml - cat merge-launch.yaml | python /app/reduce.py > launch.yaml - - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id cluster --filepath /root/saas/cluster/cluster.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id cluster --path /root/saas/cluster/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id cluster --path /root/saas/cluster/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master + sh /app/import.sh cluster /root/saas/cluster/build.zip /root/saas/cluster/launch.yaml /root/saas/cluster/launch-frontend-dev.yaml fi @@ -173,40 +161,27 @@ data: export NAMESPACE_ID=$(cat /run/secrets/kubernetes.io/serviceaccount/namespace) envsubst < /root/saas/app/api/build.yaml.tpl > /root/saas/app/api/build.yaml - envsubst < /root/saas/app/api/launch.yaml.tpl > /root/saas/app/api/launch.yaml - envsubst < /root/saas/app/ui/launch-v2.yaml.tpl > /root/saas/app/ui/launch.yaml - envsubst < /root/saas/app/ui/launch-v2-dev.yaml.tpl > /root/saas/app/ui/launch-dev.yaml + envsubst < /root/saas/app/build/launch.yaml.tpl > /root/saas/app/launch.yaml + envsubst < /root/saas/app/build/launch-backend.yaml.tpl > /root/saas/app/launch-backend.yaml + envsubst < /root/saas/app/build/launch-frontend.yaml.tpl > /root/saas/app/launch-frontend.yaml + envsubst < /root/saas/app/build/launch-frontend-dev.yaml.tpl > /root/saas/app/launch-frontend-dev.yaml + python /app/pack.py --src /root/saas/app/build --dest /root/saas/app/build.zip if [[ "$IMAGE_BUILD_ENABLE" == "true" ]] ; then cd /root/saas/app/api/ - /root/swcli --config /swcli/swcli.yaml app-package oneflow --app-id=app --stage=prod --namespace=${NAMESPACE_ID} --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=./launch.yaml --disable-dir-check + /root/swcli --config /swcli/swcli.yaml app-package oneflow --app-id=app --stage=prod --namespace=${NAMESPACE_ID} --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=../launch-backend.yaml --disable-dir-check if [[ "$IMPORT_FRONTEND" == "true" ]] ; then + + sh /app/import.sh app /root/saas/app/build.zip /root/saas/app/launch-frontend.yaml /root/saas/app/launch-frontend-dev.yaml - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id app --filepath /root/saas/app/ui/app-auto.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id app --path /root/saas/app/ui/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id app --path /root/saas/app/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master fi else - - cd /root/saas/app/ - - sh /app/core-action-service-check.sh - echo "" > merge-launch.yaml - cat /root/saas/app/api/launch.yaml >> merge-launch.yaml - echo "---" >> merge-launch.yaml - cat /root/saas/app/ui/launch.yaml >> merge-launch.yaml - cat merge-launch.yaml | python /app/reduce.py > launch.yaml - - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id app --filepath /root/saas/app/app.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id app --path /root/saas/app/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id app --path /root/saas/app/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master + sh /app/import.sh app /root/saas/app/build.zip /root/saas/app/launch.yaml /root/saas/app/launch-frontend-dev.yaml fi @@ -222,42 +197,26 @@ data: export NAMESPACE_ID=$(cat /run/secrets/kubernetes.io/serviceaccount/namespace) envsubst < /root/saas/system/api/build.yaml.tpl > /root/saas/system/api/build.yaml - envsubst < /root/saas/system/api/launch.yaml.tpl > /root/saas/system/api/launch.yaml - envsubst < /root/saas/system/ui/launch-v2.yaml.tpl > /root/saas/system/ui/launch.yaml - envsubst < /root/saas/system/ui/launch-v2-dev.yaml.tpl > /root/saas/system/ui/launch-dev.yaml - - + envsubst < /root/saas/system/build/launch.yaml.tpl > /root/saas/system/launch.yaml + envsubst < /root/saas/system/build/launch-backend.yaml.tpl > /root/saas/system/launch-backend.yaml + envsubst < /root/saas/system/build/launch-frontend.yaml.tpl > /root/saas/system/launch-frontend.yaml + envsubst < /root/saas/system/build/launch-frontend-dev.yaml.tpl > /root/saas/system/launch-frontend-dev.yaml + python /app/pack.py --src /root/saas/system/build --dest /root/saas/system/build.zip + if [[ "$IMAGE_BUILD_ENABLE" == "true" ]] ; then cd /root/saas/system/api/ - /root/swcli --config /swcli/swcli.yaml app-package oneflow --app-id=system --stage=prod --namespace=${NAMESPACE_ID} --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=./launch.yaml --disable-dir-check + /root/swcli --config /swcli/swcli.yaml app-package oneflow --app-id=system --stage=prod --namespace=${NAMESPACE_ID} --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=../launch-backend.yaml --disable-dir-check if [[ "$IMPORT_FRONTEND" == "true" ]] ; then - - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id system --filepath /root/saas/system/ui/system-auto.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id system --path /root/saas/system/ui/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id system --path /root/saas/system/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master + sh /app/import.sh system /root/saas/system/build.zip /root/saas/system/launch-frontend.yaml /root/saas/system/launch-frontend-dev.yaml fi else - - cd /root/saas/system/ - - sh /app/core-action-service-check.sh - echo "" > merge-launch.yaml - cat /root/saas/system/api/launch.yaml >> merge-launch.yaml - echo "---" >> merge-launch.yaml - cat /root/saas/system/ui/launch.yaml >> merge-launch.yaml - cat merge-launch.yaml | python /app/reduce.py > launch.yaml - - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id system --filepath /root/saas/system/system.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id system --path /root/saas/system/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id system --path /root/saas/system/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master + sh /app/import.sh system /root/saas/system/build.zip /root/saas/system/launch.yaml /root/saas/system/launch-frontend-dev.yaml fi @@ -270,47 +229,45 @@ data: sh /app/core-deploy-check.sh cd /root - export NAMESPACE_ID=$(cat /run/secrets/kubernetes.io/serviceaccount/namespace) - - export NAMESPACE_ID=$(cat /run/secrets/kubernetes.io/serviceaccount/namespace) + export NAMESPACE_ID=$(cat /run/secrets/kubernetes.io/serviceaccount/namespace) envsubst < /root/saas/upload/api/build.yaml.tpl > /root/saas/upload/api/build.yaml - envsubst < /root/saas/upload/api/launch.yaml.tpl > /root/saas/upload/api/launch.yaml - envsubst < /root/saas/upload/ui/launch-v2.yaml.tpl > /root/saas/upload/ui/launch.yaml - envsubst < /root/saas/upload/ui/launch-v2-dev.yaml.tpl > /root/saas/upload/ui/launch-dev.yaml + envsubst < /root/saas/upload/build/launch.yaml.tpl > /root/saas/upload/launch.yaml + envsubst < /root/saas/upload/build/launch-backend.yaml.tpl > /root/saas/upload/launch-backend.yaml + envsubst < /root/saas/upload/build/launch-frontend.yaml.tpl > /root/saas/upload/launch-frontend.yaml + envsubst < /root/saas/upload/build/launch-frontend-dev.yaml.tpl > /root/saas/upload/launch-frontend-dev.yaml + python /app/pack.py --src /root/saas/upload/build --dest /root/saas/upload/build.zip if [[ "$IMAGE_BUILD_ENABLE" == "true" ]] ; then cd /root/saas/upload/api/ - /root/swcli --config /swcli/swcli.yaml app-package oneflow --app-id=upload --stage=prod --namespace=${NAMESPACE_ID} --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=./launch.yaml --disable-dir-check + /root/swcli --config /swcli/swcli.yaml app-package oneflow --app-id=upload --stage=prod --namespace=${NAMESPACE_ID} --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=../launch-backend.yaml --disable-dir-check if [[ "$IMPORT_FRONTEND" == "true" ]] ; then + sh /app/import.sh upload /root/saas/upload/build.zip /root/saas/upload/launch-frontend.yaml /root/saas/upload/launch-frontend-dev.yaml - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id upload --filepath /root/saas/upload/ui/upload-auto.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id upload --path /root/saas/upload/ui/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id upload --path /root/saas/upload/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master fi else - cd /root/saas/upload/ - sh /app/core-action-service-check.sh - - echo "" > merge-launch.yaml - cat /root/saas/upload/api/launch.yaml >> merge-launch.yaml - echo "---" >> merge-launch.yaml - cat /root/saas/upload/ui/launch.yaml >> merge-launch.yaml - cat merge-launch.yaml | python /app/reduce.py > launch.yaml - - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id upload --filepath /root/saas/upload/upload.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id upload --path /root/saas/upload/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id upload --path /root/saas/upload/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master + sh /app/import.sh upload /root/saas/upload/build.zip /root/saas/upload/launch.yaml /root/saas/upload/launch-frontend-dev.yaml fi + + import.sh: | + + set -e + set -x + + sh /app/core-action-service-check.sh + + result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id $1 --filepath $2 --print-only-app-package-id=true --reset-version=true) + + /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id $1 --path $3 --app-package-id $result --arch x86 --wait=true --cluster master + /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id $1 --path $4 --app-package-id $result --arch x86 --wait=true --cluster master + reduce.py: | import sys import yaml @@ -332,8 +289,118 @@ data: res = reduce(merge, [yaml.safe_load(raw) for raw in sys.stdin.read().strip().split("---")]) print(yaml.dump(res)) - + + pack.py: | + import shutil + import tempfile + import os + import argparse + + parser = argparse.ArgumentParser(description='package tool') + parser.add_argument("-s",'--src', type=str, dest="src", required=True) + parser.add_argument("-d",'--dest', type=str, dest="dest", required=True) + args = parser.parse_args() + + packagePath = tempfile.mkdtemp() + targetPath = packagePath + "/target" + + shutil.copytree(args.src, targetPath) + + for path in os.listdir(targetPath): + if path.endswith(".zip.dir"): + shutil.make_archive(targetPath + "/" + path.split(".zip")[0], 'zip', targetPath + "/" + path) + shutil.rmtree(targetPath + "/" + path) + + shutil.make_archive(args.dest.split(".zip")[0], 'zip', targetPath + "/") + + remove-components.py: | + + import yaml + import argparse + + parser = argparse.ArgumentParser(description='remove components tool') + parser.add_argument("-s",'--src', type=str, dest="src", required=True) + parser.add_argument("-c",'--components', type=str, nargs="+", dest="components", required=True) + args = parser.parse_args() + + f = open(args.src, 'r') + srcData = yaml.safe_load(f.read()) + f.close() + + srcData["spec"]["components"] = list(filter(lambda c: c.get("revisionName") not in args.components, srcData["spec"]["components"])) + + f = open(args.src, 'w') + f.write(yaml.safe_dump(srcData, width=float("inf"))) + f.close() + saas-dataops.sh: | + + set -e + set -x + + cd /root + + sh /app/core-deploy-check.sh + + # build&launch dataops api + export NAMESPACE_ID=${NAMESPACE_DATAOPS} + export NODE_NAME='$''{''NODE_NAME''}' + export NODE_IP='$''{''NODE_IP''}' + envsubst < /root/saas/dataops/api/build.yaml.tpl > /root/saas/dataops/api/build.yaml + envsubst < /root/saas/dataops/build/launch.yaml.tpl > /root/saas/dataops/launch.yaml + envsubst < /root/saas/dataops/build/launch-backend.yaml.tpl > /root/saas/dataops/launch-backend.yaml + envsubst < /root/saas/dataops/build/launch-frontend.yaml.tpl > /root/saas/dataops/launch-frontend.yaml + envsubst < /root/saas/dataops/build/launch-frontend-dev.yaml.tpl > /root/saas/dataops/launch-frontend-dev.yaml + python /app/pack.py --src /root/saas/dataops/build --dest /root/saas/dataops/build.zip + + + # mysql地址如果从外部传入就不拉起mysql + if [[ "$DATAOPS_DB_HOST" != "prod-dataops-mysql.sreworks-dataops" ]] + then + python /app/remove-components.py -s /root/saas/dataops/launch.yaml -c "HELM|mysql|_" + python /app/remove-components.py -s /root/saas/dataops/launch-frontend.yaml -c "HELM|mysql|_" + fi + + if [[ "$DATA_ES_HOST" != "prod-dataops-elasticsearch-master.sreworks-dataops" ]] + then + python /app/remove-components.py -s /root/saas/dataops/launch.yaml -c "HELM|elasticsearch|_" + python /app/remove-components.py -s /root/saas/dataops/launch-frontend.yaml -c "HELM|elasticsearch|_" + fi + + if [[ "$DATAOPS_FILEBEAT_ENABLE" == "false" ]] + then + python /app/remove-components.py -s /root/saas/dataops/launch.yaml -c "HELM|filebeat|_" + python /app/remove-components.py -s /root/saas/dataops/launch-frontend.yaml -c "HELM|filebeat|_" + fi + + if [[ "$DATAOPS_METRICBEAT_ENABLE" == "false" ]] + then + python /app/remove-components.py -s /root/saas/dataops/launch.yaml -c "HELM|metricbeat|_" + python /app/remove-components.py -s /root/saas/dataops/launch-frontend.yaml -c "HELM|metricbeat|_" + fi + + + if [[ "$IMAGE_BUILD_ENABLE" == "true" ]] ; then + + cd /root/saas/dataops/api/ + /root/swcli --config /swcli/swcli.yaml app-package oneflow --app-id=dataops --stage=prod --namespace=${NAMESPACE_ID} --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=../launch-backend.yaml --disable-dir-check + + # wait flycore + if [[ "$IMPORT_FRONTEND" == "true" ]] ; then + + sh /app/import.sh dataops /root/saas/dataops/build.zip /root/saas/dataops/launch-frontend.yaml /root/saas/dataops/launch-frontend-dev.yaml + + fi + + else + + sh /app/import.sh dataops /root/saas/dataops/build.zip /root/saas/dataops/launch.yaml /root/saas/dataops/launch-frontend-dev.yaml + + fi + + + + saas-dataops1.sh: | set -e set -x @@ -391,6 +458,10 @@ data: envsubst < /root/saas/dataops/api/skywalking/launch.yaml.tpl > tmp-launch.yaml split + envsubst < /root/saas/dataops/api/prometheus/build.yaml.tpl > tmp-build.yaml + envsubst < /root/saas/dataops/api/prometheus/launch.yaml.tpl > tmp-launch.yaml + split + #envsubst < /root/saas/dataops/api/mongodb/build.yaml.tpl > tmp-build.yaml #envsubst < /root/saas/dataops/api/mongodb/launch.yaml.tpl > tmp-launch.yaml #split @@ -454,44 +525,30 @@ data: export NAMESPACE_ID=$(cat /run/secrets/kubernetes.io/serviceaccount/namespace) envsubst < /root/saas/team/api/build.yaml.tpl > /root/saas/team/api/build.yaml - envsubst < /root/saas/team/api/launch.yaml.tpl > /root/saas/team/api/launch.yaml - envsubst < /root/saas/team/ui/launch-v2.yaml.tpl > /root/saas/team/ui/launch.yaml - envsubst < /root/saas/team/ui/launch-v2-dev.yaml.tpl > /root/saas/team/ui/launch-dev.yaml + envsubst < /root/saas/team/build/launch.yaml.tpl > /root/saas/team/launch.yaml + envsubst < /root/saas/team/build/launch-backend.yaml.tpl > /root/saas/team/launch-backend.yaml + envsubst < /root/saas/team/build/launch-frontend.yaml.tpl > /root/saas/team/launch-frontend.yaml + envsubst < /root/saas/team/build/launch-frontend-dev.yaml.tpl > /root/saas/team/launch-frontend-dev.yaml + python /app/pack.py --src /root/saas/team/build --dest /root/saas/team/build.zip if [[ "$IMAGE_BUILD_ENABLE" == "true" ]] ; then cd /root/saas/team/api/ - /root/swcli --config /swcli/swcli.yaml app-package oneflow --stage=prod --namespace=${NAMESPACE_ID} --app-id=team --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=./launch.yaml --disable-dir-check + /root/swcli --config /swcli/swcli.yaml app-package oneflow --stage=prod --namespace=${NAMESPACE_ID} --app-id=team --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=../launch-backend.yaml --disable-dir-check if [[ "$IMPORT_FRONTEND" == "true" ]] ; then - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id team --filepath /root/saas/team/ui/team-auto.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id team --path /root/saas/team/ui/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id team --path /root/saas/team/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master + sh /app/import.sh team /root/saas/team/build.zip /root/saas/team/launch-frontend.yaml /root/saas/team/launch-frontend-dev.yaml + fi else - cd /root/saas/team/ - - sh /app/core-action-service-check.sh + sh /app/import.sh team /root/saas/team/build.zip /root/saas/team/launch.yaml /root/saas/team/launch-frontend-dev.yaml - echo "" > merge-launch.yaml - cat /root/saas/team/api/launch.yaml >> merge-launch.yaml - echo "---" >> merge-launch.yaml - cat /root/saas/team/ui/launch.yaml >> merge-launch.yaml - cat merge-launch.yaml | python /app/reduce.py > launch.yaml - - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id team --filepath /root/saas/team/team.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id team --path /root/saas/team/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id team --path /root/saas/team/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master - fi - saas-aiops.sh: | set -e @@ -508,43 +565,26 @@ data: fi envsubst < /root/saas/aiops/api/build.yaml.tpl > /root/saas/aiops/api/build.yaml - envsubst < /root/saas/aiops/api/launch.yaml.tpl > /root/saas/aiops/api/launch.yaml - envsubst < /root/saas/aiops/ui/launch-v2.yaml.tpl > /root/saas/aiops/ui/launch.yaml - envsubst < /root/saas/aiops/ui/launch-v2-dev.yaml.tpl > /root/saas/aiops/ui/launch-dev.yaml - + envsubst < /root/saas/aiops/build/launch.yaml.tpl > /root/saas/aiops/launch.yaml + envsubst < /root/saas/aiops/build/launch-backend.yaml.tpl > /root/saas/aiops/launch-backend.yaml + envsubst < /root/saas/aiops/build/launch-frontend.yaml.tpl > /root/saas/aiops/launch-frontend.yaml + envsubst < /root/saas/aiops/build/launch-frontend-dev.yaml.tpl > /root/saas/aiops/launch-frontend-dev.yaml + python /app/pack.py --src /root/saas/aiops/build --dest /root/saas/aiops/build.zip if [[ "$IMAGE_BUILD_ENABLE" == "true" ]] ; then cd /root/saas/aiops/api/ - /root/swcli --config /swcli/swcli.yaml app-package oneflow --app-id=aiops --stage=prod --namespace=${NAMESPACE_ID} --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=./launch.yaml --disable-dir-check - + /root/swcli --config /swcli/swcli.yaml app-package oneflow --app-id=aiops --stage=prod --namespace=${NAMESPACE_ID} --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=../launch-backend.yaml --disable-dir-check if [[ "$IMPORT_FRONTEND" == "true" ]] ; then + + sh /app/import.sh aiops /root/saas/aiops/build.zip /root/saas/aiops/launch-frontend.yaml /root/saas/aiops/launch-frontend-dev.yaml - sh /app/core-deploy-check.sh - - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id aiops --filepath /root/saas/aiops/ui/aiops-auto.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id aiops --path /root/saas/aiops/ui/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id aiops --path /root/saas/aiops/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master fi else - - cd /root/saas/aiops/ - - sh /app/core-action-service-check.sh - echo "" > merge-launch.yaml - cat /root/saas/aiops/api/launch.yaml >> merge-launch.yaml - echo "---" >> merge-launch.yaml - cat /root/saas/aiops/ui/launch.yaml >> merge-launch.yaml - cat merge-launch.yaml | python /app/reduce.py > launch.yaml - - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id aiops --filepath /root/saas/aiops/aiops.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id aiops --path /root/saas/aiops/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id aiops --path /root/saas/aiops/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master + sh /app/import.sh aiops /root/saas/aiops/build.zip /root/saas/aiops/launch.yaml /root/saas/aiops/launch-frontend-dev.yaml fi @@ -561,43 +601,26 @@ data: # build&launch cluster api export NAMESPACE_ID=$(cat /run/secrets/kubernetes.io/serviceaccount/namespace) envsubst < /root/saas/job/api/build.yaml.tpl > /root/saas/job/api/build.yaml - envsubst < /root/saas/job/api/launch.yaml.tpl > /root/saas/job/api/launch.yaml - envsubst < /root/saas/job/ui/launch-v2.yaml.tpl > /root/saas/job/ui/launch.yaml - envsubst < /root/saas/job/ui/launch-v2-dev.yaml.tpl > /root/saas/job/ui/launch-dev.yaml - + envsubst < /root/saas/job/build/launch.yaml.tpl > /root/saas/job/launch.yaml + envsubst < /root/saas/job/build/launch-backend.yaml.tpl > /root/saas/job/launch-backend.yaml + envsubst < /root/saas/job/build/launch-frontend.yaml.tpl > /root/saas/job/launch-frontend.yaml + envsubst < /root/saas/job/build/launch-frontend-dev.yaml.tpl > /root/saas/job/launch-frontend-dev.yaml + python /app/pack.py --src /root/saas/job/build --dest /root/saas/job/build.zip if [[ "$IMAGE_BUILD_ENABLE" == "true" ]] ; then cd /root/saas/job/api/ - /root/swcli --config /swcli/swcli.yaml app-package oneflow --app-id=job --stage=prod --namespace=${NAMESPACE_ID} --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=./launch.yaml --disable-dir-check + /root/swcli --config /swcli/swcli.yaml app-package oneflow --app-id=job --stage=prod --namespace=${NAMESPACE_ID} --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=../launch-backend.yaml --disable-dir-check if [[ "$IMPORT_FRONTEND" == "true" ]] ; then + sh /app/import.sh job /root/saas/job/build.zip /root/saas/job/launch-frontend.yaml /root/saas/job/launch-frontend-dev.yaml - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id job --filepath /root/saas/job/ui/job-auto.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id job --path /root/saas/job/ui/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id job --path /root/saas/job/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master fi else - - cd /root/saas/job/ - - sh /app/core-action-service-check.sh - - echo "" > merge-launch.yaml - cat /root/saas/job/api/launch.yaml >> merge-launch.yaml - echo "---" >> merge-launch.yaml - cat /root/saas/job/ui/launch.yaml >> merge-launch.yaml - cat merge-launch.yaml | python /app/reduce.py > launch.yaml - - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id job --filepath /root/saas/job/job.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id job --path /root/saas/job/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id job --path /root/saas/job/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master - + sh /app/import.sh job /root/saas/job/build.zip /root/saas/job/launch.yaml /root/saas/job/launch-frontend-dev.yaml fi @@ -614,14 +637,13 @@ data: export NAMESPACE_ID=$(cat /run/secrets/kubernetes.io/serviceaccount/namespace) if [[ "$IMPORT_FRONTEND" == "true" ]] ; then + + envsubst < /root/saas/healing/build/launch-frontend.yaml.tpl > /root/saas/healing/launch-frontend.yaml + envsubst < /root/saas/healing/build/launch-frontend-dev.yaml.tpl > /root/saas/healing/launch-frontend-dev.yaml + python /app/pack.py --src /root/saas/healing/build --dest /root/saas/healing/build.zip + sh /app/import.sh healing /root/saas/healing/build.zip /root/saas/healing/launch-frontend.yaml /root/saas/healing/launch-frontend-dev.yaml - envsubst < /root/saas/healing/ui/launch-v2.yaml.tpl > /root/saas/healing/ui/launch.yaml - envsubst < /root/saas/healing/ui/launch-v2-dev.yaml.tpl > /root/saas/healing/ui/launch-dev.yaml - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id healing --filepath /root/saas/healing/ui/healing-auto.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id healing --path /root/saas/healing/ui/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id healing --path /root/saas/healing/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master fi saas-health.sh: | @@ -634,6 +656,7 @@ data: cd /root export NAMESPACE_ID=$(cat /run/secrets/kubernetes.io/serviceaccount/namespace) + export VERSION_CHECK=$(python /app/version_check.py /root/saas/health/build) if [[ "$DATAOPS_DB_HOST" == "default-mysql" ]] then @@ -642,41 +665,27 @@ data: fi envsubst < /root/saas/health/api/build.yaml.tpl > /root/saas/health/api/build.yaml - envsubst < /root/saas/health/api/launch.yaml.tpl > /root/saas/health/api/launch.yaml - envsubst < /root/saas/health/ui/launch-v2.yaml.tpl > /root/saas/health/ui/launch.yaml - envsubst < /root/saas/health/ui/launch-v2-dev.yaml.tpl > /root/saas/health/ui/launch-dev.yaml - + envsubst < /root/saas/health/build/launch.yaml.tpl > /root/saas/health/launch.yaml + envsubst < /root/saas/health/build/launch-backend.yaml.tpl > /root/saas/health/launch-backend.yaml + envsubst < /root/saas/health/build/launch-frontend.yaml.tpl > /root/saas/health/launch-frontend.yaml + envsubst < /root/saas/health/build/launch-frontend-dev.yaml.tpl > /root/saas/health/launch-frontend-dev.yaml + python /app/pack.py --src /root/saas/health/build --dest /root/saas/health/build.zip + + if [[ "$IMAGE_BUILD_ENABLE" == "true" ]] ; then cd /root/saas/health/api/ - /root/swcli --config /swcli/swcli.yaml app-package oneflow --app-id=health --stage=prod --namespace=${NAMESPACE_ID} --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=./launch.yaml --disable-dir-check - + /root/swcli --config /swcli/swcli.yaml app-package oneflow --app-id=health --stage=prod --namespace=${NAMESPACE_ID} --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=../launch-backend.yaml --disable-dir-check if [[ "$IMPORT_FRONTEND" == "true" ]] ; then + sh /app/import.sh health /root/saas/health/build.zip /root/saas/health/launch-frontend.yaml /root/saas/health/launch-frontend-dev.yaml - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id health --filepath /root/saas/health/ui/health-auto.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id health --path /root/saas/health/ui/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id health --path /root/saas/health/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master fi - else - - cd /root/saas/health/ - - sh /app/core-action-service-check.sh + elif [[ "$VERSION_CHECK" == "NEED UPDATE" ]] ; then - echo "" > merge-launch.yaml - cat /root/saas/health/api/launch.yaml >> merge-launch.yaml - echo "---" >> merge-launch.yaml - cat /root/saas/health/ui/launch.yaml >> merge-launch.yaml - cat merge-launch.yaml | python /app/reduce.py > launch.yaml - - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id health --filepath /root/saas/health/health.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id health --path /root/saas/health/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id health --path /root/saas/health/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master + sh /app/import.sh health /root/saas/health/build.zip /root/saas/health/launch.yaml /root/saas/health/launch-frontend-dev.yaml fi @@ -692,16 +701,16 @@ data: cd /root export NAMESPACE_ID=$(cat /run/secrets/kubernetes.io/serviceaccount/namespace) + export VERSION_CHECK=$(python /app/version_check.py /root/saas/ocenter/build) - if [[ "$IMPORT_FRONTEND" == "true" ]] ; then + envsubst < /root/saas/ocenter/build/launch.yaml.tpl > /root/saas/ocenter/launch.yaml + envsubst < /root/saas/ocenter/build/launch-frontend-dev.yaml.tpl > /root/saas/ocenter/launch-frontend-dev.yaml + python /app/pack.py --src /root/saas/ocenter/build --dest /root/saas/ocenter/build.zip + + if [[ "$IMPORT_FRONTEND" == "true" && "$VERSION_CHECK" == "NEED UPDATE" ]] ; then + sh /app/import.sh ocenter /root/saas/ocenter/build.zip /root/saas/ocenter/launch.yaml /root/saas/ocenter/launch-frontend-dev.yaml - envsubst < /root/saas/ocenter/ui/launch-v2.yaml.tpl > /root/saas/ocenter/ui/launch.yaml - envsubst < /root/saas/ocenter/ui/launch-v2-dev.yaml.tpl > /root/saas/ocenter/ui/launch-dev.yaml - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id ocenter --filepath /root/saas/ocenter/ui/ocenter-auto.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id ocenter --path /root/saas/ocenter/ui/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id ocenter --path /root/saas/ocenter/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master fi saas-help.sh: | @@ -714,16 +723,17 @@ data: cd /root export NAMESPACE_ID=$(cat /run/secrets/kubernetes.io/serviceaccount/namespace) + export VERSION_CHECK=$(python /app/version_check.py /root/saas/help/build) - if [[ "$IMPORT_FRONTEND" == "true" ]] ; then - + envsubst < /root/saas/help/build/launch.yaml.tpl > /root/saas/help/launch.yaml + envsubst < /root/saas/help/build/launch-frontend-dev.yaml.tpl > /root/saas/help/launch-frontend-dev.yaml + python /app/pack.py --src /root/saas/help/build --dest /root/saas/help/build.zip - envsubst < /root/saas/help/ui/launch-v2.yaml.tpl > /root/saas/help/ui/launch.yaml - envsubst < /root/saas/help/ui/launch-v2-dev.yaml.tpl > /root/saas/help/ui/launch-dev.yaml - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id help --filepath /root/saas/help/ui/help-auto.zip --print-only-app-package-id=true --reset-version=true) - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id help --path /root/saas/help/ui/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id help --path /root/saas/help/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master + if [[ "$IMPORT_FRONTEND" == "true" && "$VERSION_CHECK" == "NEED UPDATE" ]] ; then + + sh /app/import.sh help /root/saas/help/build.zip /root/saas/help/launch.yaml /root/saas/help/launch-frontend-dev.yaml + fi @@ -738,83 +748,32 @@ data: # build&launch search api export NAMESPACE_ID=$(cat /run/secrets/kubernetes.io/serviceaccount/namespace) + export VERSION_CHECK=$(python /app/version_check.py /root/saas/search/build) envsubst < /root/saas/search/api/build.yaml.tpl > /root/saas/search/api/build.yaml - envsubst < /root/saas/search/api/launch.yaml.tpl > /root/saas/search/api/launch.yaml - envsubst < /root/saas/search/ui/launch-v2.yaml.tpl > /root/saas/search/ui/launch.yaml - envsubst < /root/saas/search/ui/launch-v2-dev.yaml.tpl > /root/saas/search/ui/launch-dev.yaml - + envsubst < /root/saas/search/build/launch.yaml.tpl > /root/saas/search/launch.yaml + envsubst < /root/saas/search/build/launch-backend.yaml.tpl > /root/saas/search/launch-backend.yaml + envsubst < /root/saas/search/build/launch-frontend.yaml.tpl > /root/saas/search/launch-frontend.yaml + envsubst < /root/saas/search/build/launch-frontend-dev.yaml.tpl > /root/saas/search/launch-frontend-dev.yaml + python /app/pack.py --src /root/saas/search/build --dest /root/saas/search/build.zip if [[ "$IMAGE_BUILD_ENABLE" == "true" ]] ; then cd /root/saas/search/api/ - /root/swcli --config /swcli/swcli.yaml app-package oneflow --app-id=search --stage=prod --namespace=${NAMESPACE_ID} --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=./launch.yaml --disable-dir-check + /root/swcli --config /swcli/swcli.yaml app-package oneflow --app-id=search --stage=prod --namespace=${NAMESPACE_ID} --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=../launch-backend.yaml --disable-dir-check if [[ "$IMPORT_FRONTEND" == "true" ]] ; then + + sh /app/import.sh search /root/saas/search/build.zip /root/saas/search/launch-frontend.yaml /root/saas/search/launch-frontend-dev.yaml - envsubst < /root/saas/search/ui/launch-v2.yaml.tpl > /root/saas/search/ui/launch.yaml - envsubst < /root/saas/search/ui/launch-v2-dev.yaml.tpl > /root/saas/search/ui/launch-dev.yaml - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id search --filepath /root/saas/search/ui/search-auto.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id search --path /root/saas/search/ui/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id search --path /root/saas/search/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master fi - else + elif [[ "$VERSION_CHECK" == "NEED UPDATE" ]] ; then - cd /root/saas/search/ - - sh /app/core-action-service-check.sh + sh /app/import.sh search /root/saas/search/build.zip /root/saas/search/launch.yaml /root/saas/search/launch-frontend-dev.yaml - echo "" > merge-launch.yaml - cat /root/saas/search/api/launch.yaml >> merge-launch.yaml - echo "---" >> merge-launch.yaml - cat /root/saas/search/ui/launch.yaml >> merge-launch.yaml - cat merge-launch.yaml | python /app/reduce.py > launch.yaml - - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id search --filepath /root/saas/search/search.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id search --path /root/saas/search/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id search --path /root/saas/search/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master - fi - - saas-dataops-grafana-import.sh: | - - set -e - set -x - - cd /root - - until $(curl --silent --fail --show-error --output /dev/null http://admin:${GRAFANA_ADMIN_PASSWORD}@${SAAS_STAGE_ID}-dataops-grafana.${NAMESPACE_DATAOPS}/api/datasources); do - printf '.' ; sleep 1 ; - done ; - - - for file in /root/saas/dataops/ui/grafana/datasource/*.json ; do - if [ -e "$file" ] ; then - echo "importing $file" && - curl --silent --fail --show-error \ - --request POST http://admin:${GRAFANA_ADMIN_PASSWORD}@${SAAS_STAGE_ID}-dataops-grafana.${NAMESPACE_DATAOPS}/api/datasources \ - --header "Content-Type: application/json" \ - --data-binary "@$file" ; - echo "" ; - fi - done ; - - for file in /root/saas/dataops/ui/grafana/dashboard/*.json ; do - if [ -e "$file" ] ; then - echo "importing $file" && - curl --silent --fail --show-error \ - --request POST http://admin:${GRAFANA_ADMIN_PASSWORD}@${SAAS_STAGE_ID}-dataops-grafana.${NAMESPACE_DATAOPS}/api/dashboards/import \ - --header "Content-Type: application/json" \ - --data-binary "@$file" ; - echo "" ; - fi - done - - saas-demoapp.sh: | set -e @@ -830,6 +789,94 @@ data: /root/swcli --config /swcli/swcli.yaml deployment launch --namespace sreworks --stage prod --app-id sreworks1 --path /root/saas/app/launch-demoApp.yaml --app-package-id $result --arch x86 --wait=true --cluster master fi + version_check.py: | + + import sys + import os + import yaml + from oauthlib.oauth2 import LegacyApplicationClient + from requests_oauthlib import OAuth2Session + from distutils.version import StrictVersion + + ENDPOINT = 'http://sreworks-appmanager' + CLIENT_ID = os.getenv('APPMANAGER_CLIENT_ID') + CLIENT_SECRET = os.getenv('APPMANAGER_CLIENT_SECRET') + USERNAME = os.getenv('APPMANAGER_USERNAME') + PASSWORD = os.getenv('APPMANAGER_PASSWORD') + + class AppManagerClient(object): + + def __init__(self, endpoint, client_id, client_secret, username, password): + os.environ.setdefault('OAUTHLIB_INSECURE_TRANSPORT', '1') + self._endpoint = endpoint + self._client_id = client_id + self._client_secret = client_secret + self._username = username + self._password = password + self._token = self._fetch_token() + + @property + def client(self): + return OAuth2Session(self._client_id, token=self._token) + + def _fetch_token(self): + oauth = OAuth2Session(client=LegacyApplicationClient(client_id=CLIENT_ID)) + return oauth.fetch_token( + token_url=os.path.join(ENDPOINT, 'oauth/token'), + username=self._username, + password=self._password, + client_id=self._client_id, + client_secret=self._client_secret + ) + + appBuildPath = sys.argv[1] + + f = open(appBuildPath + "/meta.yaml", 'r') + metaData = yaml.safe_load(f.read()) + f.close() + + appId = metaData["appId"] + baselineVersion = metaData["packageVersion"].split("+")[0] + + appmanagerClient = AppManagerClient(ENDPOINT, CLIENT_ID, CLIENT_SECRET, USERNAME, PASSWORD) + res = appmanagerClient.client.get(ENDPOINT + "/realtime/app-instances?appId=" + appId + "&stageId=prod") + items = res.json()["data"].get("items", []) + if len(items) == 0: + print("NEED UPDATE") + sys.exit(0) + + for item in items: + if StrictVersion(baselineVersion) > StrictVersion(item["simpleVersion"]): + print("NEED UPDATE") + sys.exit(0) + + if StrictVersion(baselineVersion) == StrictVersion(item["simpleVersion"]) and item["status"] not in ["RUNNING","PENDING"]: + print("NEED UPDATE") + sys.exit(0) + + + print("NO UPDATE") + sys.exit(0) + + upload-plugins.sh: | + set -x + + cat /root/plugins/auto-install.list | while read line + do + python3 /root/plugins/pack.py -f /root/plugins/$line -t /tmp/plugin + + /root/swcli plugin upload --config /swcli/swcli.yaml --filepath="/tmp/plugin.zip" --overwrite=true + rm /tmp/plugin.zip + + version=$(cat /root/plugins/${line}/definition.yaml |grep 'definition.oam.dev/version'|awk '{print $NF}'|awk -F '"' '{print $2}') + name=$(echo $line| awk -F '/' '{print $2"/"$3}') + echo $version + echo $name + /root/swcli plugin operate --config /swcli/swcli.yaml --name=$name --version=$version --operation=enable + done + + echo "all the plugins upload to the appmanager" + saas-sleep.sh: | sleep 999999999999 diff --git a/chart/sreworks-chart/templates/progress-check-job.yaml b/chart/sreworks-chart/templates/progress-check-job.yaml index 98523cbb..35236ff8 100644 --- a/chart/sreworks-chart/templates/progress-check-job.yaml +++ b/chart/sreworks-chart/templates/progress-check-job.yaml @@ -16,7 +16,10 @@ spec: - image: {{ template "images.progressCheck" . }} name: job imagePullPolicy: Always - + envFrom: + - configMapRef: + name: init-configmap + {{ end }} diff --git a/chart/sreworks-chart/values.yaml b/chart/sreworks-chart/values.yaml index e59cceeb..23360287 100644 --- a/chart/sreworks-chart/values.yaml +++ b/chart/sreworks-chart/values.yaml @@ -7,7 +7,7 @@ global: images: registry: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks - tag: v1.2 + tag: v1.3 accessMode: ingress @@ -20,6 +20,7 @@ global: mavenSettingsXml: https://sreworks.oss-cn-beijing.aliyuncs.com/resource/settings.xml alpineImage: sreworks-registry.cn-beijing.cr.aliyuncs.com/mirror/alpine:latest nodeImage: sreworks-registry.cn-beijing.cr.aliyuncs.com/mirror/node:14.20.0-alpine3.15 + nodeImage2: sreworks-registry.cn-beijing.cr.aliyuncs.com/mirror/node:16.17-alpine npmRegistryUrl: https://registry.npmmirror.com migrateImage: sw-migrate postrunImage: sw-postrun @@ -32,8 +33,8 @@ global: grafanaImage: sreworks-registry.cn-beijing.cr.aliyuncs.com/mirror/grafana:7.5.3 kibanaImage: sreworks-registry.cn-beijing.cr.aliyuncs.com/mirror/kibana:7.10.2 elasticsearchImage: sreworks-registry.cn-beijing.cr.aliyuncs.com/mirror/elasticsearch:7.10.2-with-plugins - skywalkingOapImage: sreworks-registry.cn-beijing.cr.aliyuncs.com/mirror/skywalking-oap-server-utc-8:8.5.0-es7 - skywalkingUiImage: sreworks-registry.cn-beijing.cr.aliyuncs.com/mirror/skywalking-ui:8.5.0 + skywalkingOapImage: sreworks-registry.cn-beijing.cr.aliyuncs.com/mirror/skywalking-oap-server-utc-8:9.2.0 + skywalkingUiImage: sreworks-registry.cn-beijing.cr.aliyuncs.com/mirror/skywalking-ui:9.2.0 busyboxImage: sreworks-registry.cn-beijing.cr.aliyuncs.com/mirror/busybox:1.30 vvpRegistry: sreworks-registry.cn-beijing.cr.aliyuncs.com/mirror @@ -50,7 +51,7 @@ platformLogo: /static/publicMedia/sreworks.png installMode: default -progressCheck: false +progressCheck: true debug: false adminInitPassword: "12345678" @@ -72,6 +73,7 @@ saas: stageId: prod onlyBase: false list: + - demoapp - cluster - app - team @@ -85,7 +87,6 @@ saas: - ocenter - help - upload - - demoapp baseList: - cluster - app @@ -103,6 +104,11 @@ saas: esPort: 9200 esUser: "elastic" esPassword: "sreworkses123." + prometheusHost: "prod-dataops-prometheus-server.sreworks-dataops" + prometheusPort: "80" + filebeatEnable: true + metricbeatEnable: true + grafana: password: "sreworks123456" @@ -113,7 +119,7 @@ swcli: clientSecret: stLCjCPKbWmki65DsAj2jPoeBLPimpJa source: - branch: v1.2 + branch: v1.3 repo: https://code.aliyun.com/sreworks_public/mirror.git appmanagerbase: @@ -131,6 +137,7 @@ appmanager: account_super_secret_key: test-super-secret-key server: + sreworksEnvs: true jvmXMX: "512m" docker: enableKaniko: true diff --git a/chart/sreworks.yaml b/chart/sreworks.yaml index 462c24ba..c691f5db 100644 --- a/chart/sreworks.yaml +++ b/chart/sreworks.yaml @@ -75,6 +75,17 @@ metadata: secrets: - name: sreworks-mysql --- +# Source: sreworks/charts/appmanagerbase/charts/openebs/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: sreworks-openebs + labels: + app: openebs + chart: openebs-3.1.0 + release: sreworks + heritage: Helm +--- # Source: sreworks/charts/appmanager/templates/server-docker-secret.yaml apiVersion: v1 kind: Secret @@ -121,7 +132,7 @@ metadata: type: Opaque data: mysql-root-password: "Ykd1d3NBV1FNNks=" - mysql-password: "bWxDRm9GS25Faw==" + mysql-password: "ZHQ0b0JOeUVrNQ==" --- # Source: sreworks/charts/appmanagerbase/charts/redis/templates/secret.yaml apiVersion: v1 @@ -275,6 +286,51 @@ data: socket=/opt/bitnami/mysql/tmp/mysql.sock pid-file=/opt/bitnami/mysql/tmp/mysqld.pid --- +# Source: sreworks/charts/appmanagerbase/charts/openebs/templates/ndm/cm-node-disk-manager.yaml +# This is the node-disk-manager related config. +# It can be used to customize the disks probes and filters +apiVersion: v1 +kind: ConfigMap +metadata: + name: sreworks-openebs-ndm-config + labels: + app: openebs + chart: openebs-3.1.0 + release: sreworks + heritage: Helm + component: ndm-config + openebs.io/component-name: ndm-config +data: + # udev-probe is default or primary probe which should be enabled to run ndm + # filterconfigs contains configs of filters - in the form of include + # and exclude comma separated strings + node-disk-manager.config: | + probeconfigs: + - key: udev-probe + name: udev probe + state: true + - key: seachest-probe + name: seachest probe + state: false + - key: smart-probe + name: smart probe + state: true + filterconfigs: + - key: os-disk-exclude-filter + name: os disk exclude filter + state: true + exclude: "/,/etc/hosts,/boot" + - key: vendor-filter + name: vendor filter + state: true + include: "" + exclude: "CLOUDBYT,OpenEBS" + - key: path-filter + name: path filter + state: true + include: "" + exclude: "/dev/loop,/dev/fd0,/dev/sr0,/dev/ram,/dev/dm-,/dev/md,/dev/rbd,/dev/zd" +--- # Source: sreworks/charts/appmanagerbase/charts/redis/templates/configmap-scripts.yaml apiVersion: v1 kind: ConfigMap @@ -441,7 +497,7 @@ data: res=$(/root/swcli --config /swcli/swcli.yaml app-package build --app-id=cluster --tags="release=sreworks/x86_64" -j -d) package_name=$(echo $res | python -c 'import sys;import json;print(json.loads(sys.stdin.read())["packageVersion"])') - /root/mc alias set sw http://${ENDPOINT_PAAS_MINIO}:9000 ${MINIO_ACCESS_KEY} ${MINIO_SECRET_KEY} + /root/mc alias set sw http://${ENDPOINT_PAAS_MINIO} ${MINIO_ACCESS_KEY} ${MINIO_SECRET_KEY} /root/mc share download sw/abm-oxs-appmanager-daily/apps/cluster/${package_name}.zip|grep 'Share'|awk '{print $2}' @@ -565,19 +621,64 @@ data: IMAGE_PUSH_REGISTRY: registry.cn-zhangjiakou.aliyuncs.com/builds - MAVEN_IMAGE: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/sw-maven:v0.5 - PYTHON2_IMAGE: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/sw-python27:v0.5 - MIGRATE_IMAGE: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/sw-migrate:v0.5 - JRE8_IMAGE: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/sw-openjdk8-jre:v0.5 - POSTRUN_IMAGE: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/sw-postrun:v0.5 - SOURCE_BRANCH: "master" + APK_REPO_DOMAIN: mirrors.tuna.tsinghua.edu.cn + MAVEN_IMAGE: sreworks-registry.cn-beijing.cr.aliyuncs.com/mirror/maven:3.8.3-adoptopenjdk-11 + JRE8_IMAGE: sreworks-registry.cn-beijing.cr.aliyuncs.com/mirror/openjdk8:alpine-jre + JRE11_IMAGE: sreworks-registry.cn-beijing.cr.aliyuncs.com/mirror/openjdk:11.0.10-jre + MAVEN_SETTINGS_XML: https://sreworks.oss-cn-beijing.aliyuncs.com/resource/settings.xml + NODE_IMAGE: sreworks-registry.cn-beijing.cr.aliyuncs.com/mirror/node:14.20.0-alpine3.15 + NODE_IMAGE2: sreworks-registry.cn-beijing.cr.aliyuncs.com/mirror/node:16.17-alpine + ALPINE_IMAGE: sreworks-registry.cn-beijing.cr.aliyuncs.com/mirror/alpine:latest + MIGRATE_IMAGE: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/sw-migrate:v1.2 + POSTRUN_IMAGE: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/sw-postrun:v1.2 + NPM_REGISTRY_URL: https://registry.npmmirror.com + JRE11_ALPINE_IMAGE: sreworks-registry.cn-beijing.cr.aliyuncs.com/mirror/openjdk11:alpine-jre + PYTHON_PIP: http://mirrors.aliyun.com/pypi/simple + PYTHON_PIP_DOMAIN: "mirrors.aliyun.com" + MINIO_CLIENT_URL: https://sreworks.oss-cn-beijing.aliyuncs.com/bin/mc-linux-amd64 + PYTHON3_IMAGE: sreworks-registry.cn-beijing.cr.aliyuncs.com/mirror/python:3.9.12-alpine + BENTOML_IMAGE: sreworks-registry.cn-beijing.cr.aliyuncs.com/mirror/bentoml-model-server:0.13.1-py37 + + LOGSTASH_IMAGE: "sreworks-registry.cn-beijing.cr.aliyuncs.com/mirror/logstash" + LOGSTASH_IMAGE_TAG: "7.10.2" + GRAFANA_IMAGE: "sreworks-registry.cn-beijing.cr.aliyuncs.com/mirror/grafana" + GRAFANA_IMAGE_TAG: "7.5.3" + KIBANA_IMAGE: "sreworks-registry.cn-beijing.cr.aliyuncs.com/mirror/kibana" + KIBANA_IMAGE_TAG: "7.10.2" + ELASTICSEARCH_IMAGE: "sreworks-registry.cn-beijing.cr.aliyuncs.com/mirror/elasticsearch" + ELASTICSEARCH_IMAGE_TAG: "7.10.2-with-plugins" + ELASTICSEARCH_IMAGE: "sreworks-registry.cn-beijing.cr.aliyuncs.com/mirror/elasticsearch" + ELASTICSEARCH_IMAGE_TAG: "7.10.2-with-plugins" + SKYWALKING_OAP_IMAGE: "sreworks-registry.cn-beijing.cr.aliyuncs.com/mirror/skywalking-oap-server-utc-8" + SKYWALKING_OAP_IMAGE_TAG: "8.5.0-es7" + SKYWALKING_UI_IMAGE: "sreworks-registry.cn-beijing.cr.aliyuncs.com/mirror/skywalking-ui" + SKYWALKING_UI_IMAGE_TAG: "8.5.0" + BUSYBOX_IMAGE: "sreworks-registry.cn-beijing.cr.aliyuncs.com/mirror/busybox" + BUSYBOX_IMAGE_TAG: "1.30" + + VVP_REPO: "sreworks-registry.cn-beijing.cr.aliyuncs.com/mirror" + VVP_APPMANAGER_REPO: "vvp-appmanager" + VVP_APPMANAGER_IMAGE_TAG: "2.6.1" + VVP_UI_REPO: "vvp-ui" + VVP_UI_IMAGE_TAG: "2.6.1" + VVP_GATEWAY_REPO: "vvp-gateway" + VVP_GATEWAY_IMAGE_TAG: "2.6.1" + METRICBEAT_IMAGE: "sreworks-registry.cn-beijing.cr.aliyuncs.com/mirror/metricbeat" + METRICBEAT_IMAGE_TAG: "7.10.2" + FILEBEAT_IMAGE: "sreworks-registry.cn-beijing.cr.aliyuncs.com/mirror/filebeat" + FILEBEAT_IMAGE_TAG: "7.10.2" + MYSQL_REGISTRY: "sreworks-registry.cn-beijing.cr.aliyuncs.com" + MYSQL_REPO: "mirror/mysql" + MYSQL_IMAGE_TAG: "8.0.22-debian-10-r44" + + SOURCE_BRANCH: "v1.2" SOURCE_REPO: https://code.aliyun.com/sreworks_public/mirror.git SOURCE_CI_ACCOUNT: "" SOURCE_CI_TOKEN: "" ZOOKEEPER_ENDPOINT: sreworks-zookeeper - ENDPOINT_PAAS_MINIO: sreworks-minio.sreworks + ENDPOINT_PAAS_MINIO: "sreworks-minio.sreworks:9000" APPMANAGER_ENDPOINT: sreworks-appmanager KAFKA_ENDPOINT: sreworks-kafka.sreworks AUTHPROXY_ENDPOINT: prod-flycore-paas-authproxy @@ -601,9 +702,6 @@ data: SAAS_STAGE_ID: prod - DOMAIN_BASE_INGRESS: - DOMAIN_NETWORK_PROTOCOL: "__HOME_URL__" - PLATFORM_NAME: SREWorks PLATFORM_LOGO: /static/publicMedia/sreworks.png @@ -613,8 +711,18 @@ data: IMPORT_FRONTEND: "true" IMAGE_BUILD_ENABLE: "false" - DATAOPS_DB_PASSWORD: cb56b5is5e21_c359b42223 - GRAFANA_ADMIN_PASSWORD: sreworks123456 + DATAOPS_DB_HOST: "prod-dataops-mysql.sreworks-dataops" + DATAOPS_DB_PASSWORD: "cb56b5is5e21_c359b42223" + DATAOPS_DB_PORT: "3306" + DATAOPS_DB_USER: "root" + GRAFANA_ADMIN_PASSWORD: "sreworks123456" + DATA_ES_HOST: "prod-dataops-elasticsearch-master.sreworks-dataops" + DATA_ES_PORT: "9200" + DATA_ES_USER: "elastic" + DATA_ES_PASSWORD: "sreworkses123." + + DATA_PROM_HOST: "localhost" + DATA_PROM_PORT: "80" ACCOUNT_SUPER_CLIENT_ID: common ACCOUNT_SUPER_CLIENT_SECRET: common-9efab2399c7c560b34de477b9aa0a465 @@ -622,7 +730,9 @@ data: ACCOUNT_SUPER_SECRET_KEY: test-super-secret-key HOME_BUILD: "false" + ONLY_BASE: "false" + ADMIN_INIT_PASSWORD: "12345678" kind: ConfigMap metadata: @@ -685,17 +795,31 @@ data: sh /app/core-action-service-check.sh # import&launch saas desktop - envsubst < /root/saas/desktop/launch-v2.yaml.tpl > /root/saas/desktop/launch.yaml + envsubst < /root/saas/desktop/build/launch-frontend.yaml.tpl > /root/saas/desktop/launch-frontend.yaml + envsubst < /root/saas/desktop/build/launch-frontend-dev.yaml.tpl > /root/saas/desktop/launch-frontend-dev.yaml - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id desktop --filepath /root/saas/desktop/ui/desktop-auto.zip --print-only-app-package-id=true --reset-version=true) - /root/swcli --config /swcli/swcli.yaml deployment launch --app-id desktop --stage=prod --namespace=${NAMESPACE_ID} --path /root/saas/desktop/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - + if [[ "$ONLY_BASE" == "true" ]] ; then + sed -i 's/searchConfig\\":true/searchConfig\\":false/g' saas/desktop/build/INTERNAL_ADDON_productopsv2.zip.dir/content.json + fi + + python /app/pack.py --src /root/saas/desktop/build --dest /root/saas/desktop/build.zip + + sh /app/import.sh desktop /root/saas/desktop/build.zip /root/saas/desktop/launch-frontend.yaml /root/saas/desktop/launch-frontend-dev.yaml + # import&launch saas swadmin - envsubst < /root/saas/swadmin/launch-v2.yaml.tpl > /root/saas/swadmin/launch.yaml - envsubst < /root/saas/swadmin/launch-v2-dev.yaml.tpl > /root/saas/swadmin/launch-dev.yaml - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id swadmin --filepath /root/saas/swadmin/ui/swadmin-auto.zip --print-only-app-package-id=true --reset-version=true) - /root/swcli --config /swcli/swcli.yaml deployment launch --app-id swadmin --path /root/saas/swadmin/launch.yaml --stage=prod --namespace=${NAMESPACE_ID} --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --app-id swadmin --path /root/saas/swadmin/launch-dev.yaml --stage dev --namespace=${NAMESPACE_ID} --app-package-id $result --arch x86 --wait=true --cluster master + python /app/pack.py --src /root/saas/swadmin/build --dest /root/saas/swadmin/build.zip + envsubst < /root/saas/swadmin/build/launch-frontend.yaml.tpl > /root/saas/swadmin/launch-frontend.yaml + envsubst < /root/saas/swadmin/build/launch-frontend-dev.yaml.tpl > /root/saas/swadmin/launch-frontend-dev.yaml + + sh /app/import.sh swadmin /root/saas/swadmin/build.zip /root/saas/swadmin/launch-frontend.yaml /root/saas/swadmin/launch-frontend-dev.yaml + + # import&launch saas template + python /app/pack.py --src /root/saas/template/build --dest /root/saas/template/build.zip + envsubst < /root/saas/template/build/launch-frontend.yaml.tpl > /root/saas/template/launch-frontend.yaml + envsubst < /root/saas/template/build/launch-frontend-dev.yaml.tpl > /root/saas/template/launch-frontend-dev.yaml + + sh /app/import.sh template /root/saas/template/build.zip /root/saas/template/launch-frontend.yaml /root/saas/template/launch-frontend-dev.yaml + fi @@ -738,42 +862,28 @@ data: # build&launch cluster api export NAMESPACE_ID=$(cat /run/secrets/kubernetes.io/serviceaccount/namespace) envsubst < /root/saas/cluster/api/build.yaml.tpl > /root/saas/cluster/api/build.yaml - envsubst < /root/saas/cluster/api/launch.yaml.tpl > /root/saas/cluster/api/launch.yaml - envsubst < /root/saas/cluster/ui/launch-v2.yaml.tpl > /root/saas/cluster/ui/launch.yaml - envsubst < /root/saas/cluster/ui/launch-v2-dev.yaml.tpl > /root/saas/cluster/ui/launch-dev.yaml + envsubst < /root/saas/cluster/build/launch.yaml.tpl > /root/saas/cluster/launch.yaml + envsubst < /root/saas/cluster/build/launch-backend.yaml.tpl > /root/saas/cluster/launch-backend.yaml + envsubst < /root/saas/cluster/build/launch-frontend.yaml.tpl > /root/saas/cluster/launch-frontend.yaml + envsubst < /root/saas/cluster/build/launch-frontend-dev.yaml.tpl > /root/saas/cluster/launch-frontend-dev.yaml + python /app/pack.py --src /root/saas/cluster/build --dest /root/saas/cluster/build.zip if [[ "$IMAGE_BUILD_ENABLE" == "true" ]] ; then cd /root/saas/cluster/api/ - /root/swcli --config /swcli/swcli.yaml app-package oneflow --app-id=cluster --stage=prod --namespace=${NAMESPACE_ID} --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=./launch.yaml --disable-dir-check + /root/swcli --config /swcli/swcli.yaml app-package oneflow --app-id=cluster --stage=prod --namespace=${NAMESPACE_ID} --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=../launch-backend.yaml --disable-dir-check # wait flycore if [[ "$IMPORT_FRONTEND" == "true" ]] ; then - # import&launch cluster ui - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id cluster --filepath /root/saas/cluster/ui/cluster-auto.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id cluster --path /root/saas/cluster/ui/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id cluster --path /root/saas/cluster/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master + sh /app/import.sh cluster /root/saas/cluster/build.zip /root/saas/cluster/launch-frontend.yaml /root/saas/cluster/launch-frontend-dev.yaml + fi else - cd /root/saas/cluster/ - - sh /app/core-action-service-check.sh - - echo "" > merge-launch.yaml - cat /root/saas/cluster/api/launch.yaml >> merge-launch.yaml - echo "---" >> merge-launch.yaml - cat /root/saas/cluster/ui/launch.yaml >> merge-launch.yaml - cat merge-launch.yaml | python /app/reduce.py > launch.yaml - - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id cluster --filepath /root/saas/cluster/cluster.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id cluster --path /root/saas/cluster/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id cluster --path /root/saas/cluster/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master + sh /app/import.sh cluster /root/saas/cluster/build.zip /root/saas/cluster/launch.yaml /root/saas/cluster/launch-frontend-dev.yaml fi @@ -788,40 +898,27 @@ data: export NAMESPACE_ID=$(cat /run/secrets/kubernetes.io/serviceaccount/namespace) envsubst < /root/saas/app/api/build.yaml.tpl > /root/saas/app/api/build.yaml - envsubst < /root/saas/app/api/launch.yaml.tpl > /root/saas/app/api/launch.yaml - envsubst < /root/saas/app/ui/launch-v2.yaml.tpl > /root/saas/app/ui/launch.yaml - envsubst < /root/saas/app/ui/launch-v2-dev.yaml.tpl > /root/saas/app/ui/launch-dev.yaml + envsubst < /root/saas/app/build/launch.yaml.tpl > /root/saas/app/launch.yaml + envsubst < /root/saas/app/build/launch-backend.yaml.tpl > /root/saas/app/launch-backend.yaml + envsubst < /root/saas/app/build/launch-frontend.yaml.tpl > /root/saas/app/launch-frontend.yaml + envsubst < /root/saas/app/build/launch-frontend-dev.yaml.tpl > /root/saas/app/launch-frontend-dev.yaml + python /app/pack.py --src /root/saas/app/build --dest /root/saas/app/build.zip if [[ "$IMAGE_BUILD_ENABLE" == "true" ]] ; then cd /root/saas/app/api/ - /root/swcli --config /swcli/swcli.yaml app-package oneflow --app-id=app --stage=prod --namespace=${NAMESPACE_ID} --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=./launch.yaml --disable-dir-check + /root/swcli --config /swcli/swcli.yaml app-package oneflow --app-id=app --stage=prod --namespace=${NAMESPACE_ID} --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=../launch-backend.yaml --disable-dir-check if [[ "$IMPORT_FRONTEND" == "true" ]] ; then + + sh /app/import.sh app /root/saas/app/build.zip /root/saas/app/launch-frontend.yaml /root/saas/app/launch-frontend-dev.yaml - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id app --filepath /root/saas/app/ui/app-auto.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id app --path /root/saas/app/ui/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id app --path /root/saas/app/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master fi else - - cd /root/saas/app/ - - sh /app/core-action-service-check.sh - echo "" > merge-launch.yaml - cat /root/saas/app/api/launch.yaml >> merge-launch.yaml - echo "---" >> merge-launch.yaml - cat /root/saas/app/ui/launch.yaml >> merge-launch.yaml - cat merge-launch.yaml | python /app/reduce.py > launch.yaml - - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id app --filepath /root/saas/app/app.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id app --path /root/saas/app/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id app --path /root/saas/app/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master + sh /app/import.sh app /root/saas/app/build.zip /root/saas/app/launch.yaml /root/saas/app/launch-frontend-dev.yaml fi @@ -837,42 +934,26 @@ data: export NAMESPACE_ID=$(cat /run/secrets/kubernetes.io/serviceaccount/namespace) envsubst < /root/saas/system/api/build.yaml.tpl > /root/saas/system/api/build.yaml - envsubst < /root/saas/system/api/launch.yaml.tpl > /root/saas/system/api/launch.yaml - envsubst < /root/saas/system/ui/launch-v2.yaml.tpl > /root/saas/system/ui/launch.yaml - envsubst < /root/saas/system/ui/launch-v2-dev.yaml.tpl > /root/saas/system/ui/launch-dev.yaml - - + envsubst < /root/saas/system/build/launch.yaml.tpl > /root/saas/system/launch.yaml + envsubst < /root/saas/system/build/launch-backend.yaml.tpl > /root/saas/system/launch-backend.yaml + envsubst < /root/saas/system/build/launch-frontend.yaml.tpl > /root/saas/system/launch-frontend.yaml + envsubst < /root/saas/system/build/launch-frontend-dev.yaml.tpl > /root/saas/system/launch-frontend-dev.yaml + python /app/pack.py --src /root/saas/system/build --dest /root/saas/system/build.zip + if [[ "$IMAGE_BUILD_ENABLE" == "true" ]] ; then cd /root/saas/system/api/ - /root/swcli --config /swcli/swcli.yaml app-package oneflow --app-id=system --stage=prod --namespace=${NAMESPACE_ID} --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=./launch.yaml --disable-dir-check + /root/swcli --config /swcli/swcli.yaml app-package oneflow --app-id=system --stage=prod --namespace=${NAMESPACE_ID} --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=../launch-backend.yaml --disable-dir-check if [[ "$IMPORT_FRONTEND" == "true" ]] ; then - - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id system --filepath /root/saas/system/ui/system-auto.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id system --path /root/saas/system/ui/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id system --path /root/saas/system/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master + sh /app/import.sh system /root/saas/system/build.zip /root/saas/system/launch-frontend.yaml /root/saas/system/launch-frontend-dev.yaml fi else - - cd /root/saas/system/ - - sh /app/core-action-service-check.sh - echo "" > merge-launch.yaml - cat /root/saas/system/api/launch.yaml >> merge-launch.yaml - echo "---" >> merge-launch.yaml - cat /root/saas/system/ui/launch.yaml >> merge-launch.yaml - cat merge-launch.yaml | python /app/reduce.py > launch.yaml - - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id system --filepath /root/saas/system/system.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id system --path /root/saas/system/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id system --path /root/saas/system/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master + sh /app/import.sh system /root/saas/system/build.zip /root/saas/system/launch.yaml /root/saas/system/launch-frontend-dev.yaml fi @@ -885,51 +966,47 @@ data: sh /app/core-deploy-check.sh cd /root - export NAMESPACE_ID=$(cat /run/secrets/kubernetes.io/serviceaccount/namespace) - - export NAMESPACE_ID=$(cat /run/secrets/kubernetes.io/serviceaccount/namespace) + export NAMESPACE_ID=$(cat /run/secrets/kubernetes.io/serviceaccount/namespace) envsubst < /root/saas/upload/api/build.yaml.tpl > /root/saas/upload/api/build.yaml - envsubst < /root/saas/upload/api/launch.yaml.tpl > /root/saas/upload/api/launch.yaml - envsubst < /root/saas/upload/ui/launch-v2.yaml.tpl > /root/saas/upload/ui/launch.yaml - envsubst < /root/saas/upload/ui/launch-v2-dev.yaml.tpl > /root/saas/upload/ui/launch-dev.yaml + envsubst < /root/saas/upload/build/launch.yaml.tpl > /root/saas/upload/launch.yaml + envsubst < /root/saas/upload/build/launch-backend.yaml.tpl > /root/saas/upload/launch-backend.yaml + envsubst < /root/saas/upload/build/launch-frontend.yaml.tpl > /root/saas/upload/launch-frontend.yaml + envsubst < /root/saas/upload/build/launch-frontend-dev.yaml.tpl > /root/saas/upload/launch-frontend-dev.yaml + python /app/pack.py --src /root/saas/upload/build --dest /root/saas/upload/build.zip if [[ "$IMAGE_BUILD_ENABLE" == "true" ]] ; then cd /root/saas/upload/api/ - /root/swcli --config /swcli/swcli.yaml app-package oneflow --app-id=upload --stage=prod --namespace=${NAMESPACE_ID} --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=./launch.yaml --disable-dir-check + /root/swcli --config /swcli/swcli.yaml app-package oneflow --app-id=upload --stage=prod --namespace=${NAMESPACE_ID} --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=../launch-backend.yaml --disable-dir-check if [[ "$IMPORT_FRONTEND" == "true" ]] ; then + sh /app/import.sh upload /root/saas/upload/build.zip /root/saas/upload/launch-frontend.yaml /root/saas/upload/launch-frontend-dev.yaml - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id upload --filepath /root/saas/upload/ui/upload-auto.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id upload --path /root/saas/upload/ui/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id upload --path /root/saas/upload/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master fi else - cd /root/saas/upload/ - sh /app/core-action-service-check.sh - - echo "" > merge-launch.yaml - cat /root/saas/upload/api/launch.yaml >> merge-launch.yaml - echo "---" >> merge-launch.yaml - cat /root/saas/upload/ui/launch.yaml >> merge-launch.yaml - cat merge-launch.yaml | python /app/reduce.py > launch.yaml - - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id upload --filepath /root/saas/upload/upload.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id upload --path /root/saas/upload/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id upload --path /root/saas/upload/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master + sh /app/import.sh upload /root/saas/upload/build.zip /root/saas/upload/launch.yaml /root/saas/upload/launch-frontend-dev.yaml fi + + import.sh: | + + sh /app/core-action-service-check.sh + + result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id $1 --filepath $2 --print-only-app-package-id=true --reset-version=true) + + /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id $1 --path $3 --app-package-id $result --arch x86 --wait=true --cluster master + /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id $1 --path $4 --app-package-id $result --arch x86 --wait=true --cluster master + reduce.py: | import sys import yaml import json + from functools import reduce def merge(a, b): if b is None: @@ -946,6 +1023,31 @@ data: res = reduce(merge, [yaml.safe_load(raw) for raw in sys.stdin.read().strip().split("---")]) print(yaml.dump(res)) + + pack.py: | + import shutil + import tempfile + import os + import argparse + + parser = argparse.ArgumentParser(description='package tool') + parser.add_argument("-s",'--src', type=str, dest="src", required=True) + parser.add_argument("-d",'--dest', type=str, dest="dest", required=True) + args = parser.parse_args() + + packagePath = tempfile.mkdtemp() + targetPath = packagePath + "/target" + + shutil.copytree(args.src, targetPath) + + for path in os.listdir(targetPath): + if path.endswith(".zip.dir"): + shutil.make_archive(targetPath + "/" + path.split(".zip")[0], 'zip', targetPath + "/" + path) + shutil.rmtree(targetPath + "/" + path) + + + shutil.make_archive(args.dest.split(".zip")[0], 'zip', targetPath + "/") + saas-dataops.sh: | set -e @@ -968,13 +1070,22 @@ data: echo "---" >> tmp-merge-launch.yaml } - envsubst < /root/saas/dataops/api/mysql/build.yaml.tpl > tmp-build.yaml - envsubst < /root/saas/dataops/api/mysql/launch.yaml.tpl > tmp-launch.yaml - split - envsubst < /root/saas/dataops/api/elasticsearch/build.yaml.tpl > tmp-build.yaml - envsubst < /root/saas/dataops/api/elasticsearch/launch.yaml.tpl > tmp-launch.yaml - split + # mysql地址如果从外部传入就不拉起mysql + if [[ "$DATAOPS_DB_HOST" == "prod-dataops-mysql.sreworks-dataops" ]] + then + envsubst < /root/saas/dataops/api/mysql/build.yaml.tpl > tmp-build.yaml + envsubst < /root/saas/dataops/api/mysql/launch.yaml.tpl > tmp-launch.yaml + split + fi + + if [[ "$DATA_ES_HOST" == "prod-dataops-elasticsearch-master.sreworks-dataops" ]] + then + envsubst < /root/saas/dataops/api/elasticsearch/build.yaml.tpl > tmp-build.yaml + envsubst < /root/saas/dataops/api/elasticsearch/launch.yaml.tpl > tmp-launch.yaml + split + fi + envsubst < /root/saas/dataops/api/grafana/build.yaml.tpl > tmp-build.yaml envsubst < /root/saas/dataops/api/grafana/launch.yaml.tpl > tmp-launch.yaml @@ -996,6 +1107,10 @@ data: envsubst < /root/saas/dataops/api/skywalking/launch.yaml.tpl > tmp-launch.yaml split + envsubst < /root/saas/dataops/api/prometheus/build.yaml.tpl > tmp-build.yaml + envsubst < /root/saas/dataops/api/prometheus/launch.yaml.tpl > tmp-launch.yaml + split + #envsubst < /root/saas/dataops/api/mongodb/build.yaml.tpl > tmp-build.yaml #envsubst < /root/saas/dataops/api/mongodb/launch.yaml.tpl > tmp-launch.yaml #split @@ -1004,9 +1119,9 @@ data: envsubst < /root/saas/dataops/api/ververica-platform/launch.yaml.tpl > tmp-launch.yaml split - #envsubst < /root/saas/dataops/api/logstash/build.yaml.tpl > tmp-build.yaml - #envsubst < /root/saas/dataops/api/logstash/launch.yaml.tpl > tmp-launch.yaml - #split + envsubst < /root/saas/dataops/api/logstash/build.yaml.tpl > tmp-build.yaml + envsubst < /root/saas/dataops/api/logstash/launch.yaml.tpl > tmp-launch.yaml + split envsubst < /root/saas/dataops/api/build.yaml.tpl > tmp-build.yaml envsubst < /root/saas/dataops/api/launch.yaml.tpl > tmp-launch.yaml @@ -1059,44 +1174,30 @@ data: export NAMESPACE_ID=$(cat /run/secrets/kubernetes.io/serviceaccount/namespace) envsubst < /root/saas/team/api/build.yaml.tpl > /root/saas/team/api/build.yaml - envsubst < /root/saas/team/api/launch.yaml.tpl > /root/saas/team/api/launch.yaml - envsubst < /root/saas/team/ui/launch-v2.yaml.tpl > /root/saas/team/ui/launch.yaml - envsubst < /root/saas/team/ui/launch-v2-dev.yaml.tpl > /root/saas/team/ui/launch-dev.yaml + envsubst < /root/saas/team/build/launch.yaml.tpl > /root/saas/team/launch.yaml + envsubst < /root/saas/team/build/launch-backend.yaml.tpl > /root/saas/team/launch-backend.yaml + envsubst < /root/saas/team/build/launch-frontend.yaml.tpl > /root/saas/team/launch-frontend.yaml + envsubst < /root/saas/team/build/launch-frontend-dev.yaml.tpl > /root/saas/team/launch-frontend-dev.yaml + python /app/pack.py --src /root/saas/team/build --dest /root/saas/team/build.zip if [[ "$IMAGE_BUILD_ENABLE" == "true" ]] ; then cd /root/saas/team/api/ - /root/swcli --config /swcli/swcli.yaml app-package oneflow --stage=prod --namespace=${NAMESPACE_ID} --app-id=team --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=./launch.yaml --disable-dir-check + /root/swcli --config /swcli/swcli.yaml app-package oneflow --stage=prod --namespace=${NAMESPACE_ID} --app-id=team --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=../launch-backend.yaml --disable-dir-check if [[ "$IMPORT_FRONTEND" == "true" ]] ; then - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id team --filepath /root/saas/team/ui/team-auto.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id team --path /root/saas/team/ui/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id team --path /root/saas/team/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master + sh /app/import.sh team /root/saas/team/build.zip /root/saas/team/launch-frontend.yaml /root/saas/team/launch-frontend-dev.yaml + fi else - cd /root/saas/team/ - - sh /app/core-action-service-check.sh + sh /app/import.sh team /root/saas/team/build.zip /root/saas/team/launch.yaml /root/saas/team/launch-frontend-dev.yaml - echo "" > merge-launch.yaml - cat /root/saas/team/api/launch.yaml >> merge-launch.yaml - echo "---" >> merge-launch.yaml - cat /root/saas/team/ui/launch.yaml >> merge-launch.yaml - cat merge-launch.yaml | python /app/reduce.py > launch.yaml - - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id team --filepath /root/saas/team/team.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id team --path /root/saas/team/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id team --path /root/saas/team/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master - fi - saas-aiops.sh: | set -e @@ -1106,44 +1207,33 @@ data: sh /app/core-deploy-check.sh export NAMESPACE_ID=${NAMESPACE_AIOPS} + if [[ "$DATAOPS_DB_HOST" == "default-mysql" ]] + then + DATAOPS_DB_HOST='\{\{ Global.STAGE_ID \}\}-\{\{ Global.APP_ID \}\}-mysql.sreworks-dataops' + export DATAOPS_DB_HOST=$(echo $DATAOPS_DB_HOST|sed 's/\\//g') + fi + envsubst < /root/saas/aiops/api/build.yaml.tpl > /root/saas/aiops/api/build.yaml - envsubst < /root/saas/aiops/api/launch.yaml.tpl > /root/saas/aiops/api/launch.yaml - envsubst < /root/saas/aiops/ui/launch-v2.yaml.tpl > /root/saas/aiops/ui/launch.yaml - envsubst < /root/saas/aiops/ui/launch-v2-dev.yaml.tpl > /root/saas/aiops/ui/launch-dev.yaml - + envsubst < /root/saas/aiops/build/launch.yaml.tpl > /root/saas/aiops/launch.yaml + envsubst < /root/saas/aiops/build/launch-backend.yaml.tpl > /root/saas/aiops/launch-backend.yaml + envsubst < /root/saas/aiops/build/launch-frontend.yaml.tpl > /root/saas/aiops/launch-frontend.yaml + envsubst < /root/saas/aiops/build/launch-frontend-dev.yaml.tpl > /root/saas/aiops/launch-frontend-dev.yaml + python /app/pack.py --src /root/saas/aiops/build --dest /root/saas/aiops/build.zip if [[ "$IMAGE_BUILD_ENABLE" == "true" ]] ; then cd /root/saas/aiops/api/ - /root/swcli --config /swcli/swcli.yaml app-package oneflow --app-id=aiops --stage=prod --namespace=${NAMESPACE_ID} --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=./launch.yaml --disable-dir-check - + /root/swcli --config /swcli/swcli.yaml app-package oneflow --app-id=aiops --stage=prod --namespace=${NAMESPACE_ID} --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=../launch-backend.yaml --disable-dir-check if [[ "$IMPORT_FRONTEND" == "true" ]] ; then + + sh /app/import.sh aiops /root/saas/aiops/build.zip /root/saas/aiops/launch-frontend.yaml /root/saas/aiops/launch-frontend-dev.yaml - sh /app/core-deploy-check.sh - - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id aiops --filepath /root/saas/aiops/ui/aiops-auto.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id aiops --path /root/saas/aiops/ui/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id aiops --path /root/saas/aiops/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master fi else - - cd /root/saas/aiops/ - - sh /app/core-action-service-check.sh - echo "" > merge-launch.yaml - cat /root/saas/aiops/api/launch.yaml >> merge-launch.yaml - echo "---" >> merge-launch.yaml - cat /root/saas/aiops/ui/launch.yaml >> merge-launch.yaml - cat merge-launch.yaml | python /app/reduce.py > launch.yaml - - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id aiops --filepath /root/saas/aiops/aiops.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id aiops --path /root/saas/aiops/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id aiops --path /root/saas/aiops/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master + sh /app/import.sh aiops /root/saas/aiops/build.zip /root/saas/aiops/launch.yaml /root/saas/aiops/launch-frontend-dev.yaml fi @@ -1160,43 +1250,26 @@ data: # build&launch cluster api export NAMESPACE_ID=$(cat /run/secrets/kubernetes.io/serviceaccount/namespace) envsubst < /root/saas/job/api/build.yaml.tpl > /root/saas/job/api/build.yaml - envsubst < /root/saas/job/api/launch.yaml.tpl > /root/saas/job/api/launch.yaml - envsubst < /root/saas/job/ui/launch-v2.yaml.tpl > /root/saas/job/ui/launch.yaml - envsubst < /root/saas/job/ui/launch-v2-dev.yaml.tpl > /root/saas/job/ui/launch-dev.yaml - + envsubst < /root/saas/job/build/launch.yaml.tpl > /root/saas/job/launch.yaml + envsubst < /root/saas/job/build/launch-backend.yaml.tpl > /root/saas/job/launch-backend.yaml + envsubst < /root/saas/job/build/launch-frontend.yaml.tpl > /root/saas/job/launch-frontend.yaml + envsubst < /root/saas/job/build/launch-frontend-dev.yaml.tpl > /root/saas/job/launch-frontend-dev.yaml + python /app/pack.py --src /root/saas/job/build --dest /root/saas/job/build.zip if [[ "$IMAGE_BUILD_ENABLE" == "true" ]] ; then cd /root/saas/job/api/ - /root/swcli --config /swcli/swcli.yaml app-package oneflow --app-id=job --stage=prod --namespace=${NAMESPACE_ID} --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=./launch.yaml --disable-dir-check + /root/swcli --config /swcli/swcli.yaml app-package oneflow --app-id=job --stage=prod --namespace=${NAMESPACE_ID} --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=../launch-backend.yaml --disable-dir-check if [[ "$IMPORT_FRONTEND" == "true" ]] ; then + sh /app/import.sh job /root/saas/job/build.zip /root/saas/job/launch-frontend.yaml /root/saas/job/launch-frontend-dev.yaml - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id job --filepath /root/saas/job/ui/job-auto.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id job --path /root/saas/job/ui/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id job --path /root/saas/job/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master fi else - - cd /root/saas/job/ - - sh /app/core-action-service-check.sh - - echo "" > merge-launch.yaml - cat /root/saas/job/api/launch.yaml >> merge-launch.yaml - echo "---" >> merge-launch.yaml - cat /root/saas/job/ui/launch.yaml >> merge-launch.yaml - cat merge-launch.yaml | python /app/reduce.py > launch.yaml - - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id job --filepath /root/saas/job/job.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id job --path /root/saas/job/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id job --path /root/saas/job/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master - + sh /app/import.sh job /root/saas/job/build.zip /root/saas/job/launch.yaml /root/saas/job/launch-frontend-dev.yaml fi @@ -1213,14 +1286,13 @@ data: export NAMESPACE_ID=$(cat /run/secrets/kubernetes.io/serviceaccount/namespace) if [[ "$IMPORT_FRONTEND" == "true" ]] ; then + + envsubst < /root/saas/healing/build/launch-frontend.yaml.tpl > /root/saas/healing/launch-frontend.yaml + envsubst < /root/saas/healing/build/launch-frontend-dev.yaml.tpl > /root/saas/healing/launch-frontend-dev.yaml + python /app/pack.py --src /root/saas/healing/build --dest /root/saas/healing/build.zip + sh /app/import.sh healing /root/saas/healing/build.zip /root/saas/healing/launch-frontend.yaml /root/saas/healing/launch-frontend-dev.yaml - envsubst < /root/saas/healing/ui/launch-v2.yaml.tpl > /root/saas/healing/ui/launch.yaml - envsubst < /root/saas/healing/ui/launch-v2-dev.yaml.tpl > /root/saas/healing/ui/launch-dev.yaml - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id healing --filepath /root/saas/healing/ui/healing-auto.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id healing --path /root/saas/healing/ui/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id healing --path /root/saas/healing/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master fi saas-health.sh: | @@ -1233,43 +1305,36 @@ data: cd /root export NAMESPACE_ID=$(cat /run/secrets/kubernetes.io/serviceaccount/namespace) + export VERSION_CHECK=$(python /app/version_check.py /root/saas/health/build) + + if [[ "$DATAOPS_DB_HOST" == "default-mysql" ]] + then + DATAOPS_DB_HOST='\{\{ Global.STAGE_ID \}\}-\{\{ Global.APP_ID \}\}-mysql.sreworks-dataops' + export DATAOPS_DB_HOST=$(echo $DATAOPS_DB_HOST|sed 's/\\//g') + fi envsubst < /root/saas/health/api/build.yaml.tpl > /root/saas/health/api/build.yaml - envsubst < /root/saas/health/api/launch.yaml.tpl > /root/saas/health/api/launch.yaml - envsubst < /root/saas/health/ui/launch-v2.yaml.tpl > /root/saas/health/ui/launch.yaml - envsubst < /root/saas/health/ui/launch-v2-dev.yaml.tpl > /root/saas/health/ui/launch-dev.yaml - + envsubst < /root/saas/health/build/launch.yaml.tpl > /root/saas/health/launch.yaml + envsubst < /root/saas/health/build/launch-backend.yaml.tpl > /root/saas/health/launch-backend.yaml + envsubst < /root/saas/health/build/launch-frontend.yaml.tpl > /root/saas/health/launch-frontend.yaml + envsubst < /root/saas/health/build/launch-frontend-dev.yaml.tpl > /root/saas/health/launch-frontend-dev.yaml + python /app/pack.py --src /root/saas/health/build --dest /root/saas/health/build.zip + + if [[ "$IMAGE_BUILD_ENABLE" == "true" ]] ; then cd /root/saas/health/api/ - /root/swcli --config /swcli/swcli.yaml app-package oneflow --app-id=health --stage=prod --namespace=${NAMESPACE_ID} --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=./launch.yaml --disable-dir-check - + /root/swcli --config /swcli/swcli.yaml app-package oneflow --app-id=health --stage=prod --namespace=${NAMESPACE_ID} --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=../launch-backend.yaml --disable-dir-check if [[ "$IMPORT_FRONTEND" == "true" ]] ; then + sh /app/import.sh health /root/saas/health/build.zip /root/saas/health/launch-frontend.yaml /root/saas/health/launch-frontend-dev.yaml - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id health --filepath /root/saas/health/ui/health-auto.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id health --path /root/saas/health/ui/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id health --path /root/saas/health/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master fi - else - - cd /root/saas/health/ - - sh /app/core-action-service-check.sh + elif [[ "$VERSION_CHECK" == "NEED UPDATE" ]] ; then - echo "" > merge-launch.yaml - cat /root/saas/health/api/launch.yaml >> merge-launch.yaml - echo "---" >> merge-launch.yaml - cat /root/saas/health/ui/launch.yaml >> merge-launch.yaml - cat merge-launch.yaml | python /app/reduce.py > launch.yaml - - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id health --filepath /root/saas/health/health.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id health --path /root/saas/health/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id health --path /root/saas/health/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master + sh /app/import.sh health /root/saas/health/build.zip /root/saas/health/launch.yaml /root/saas/health/launch-frontend-dev.yaml fi @@ -1285,16 +1350,17 @@ data: cd /root export NAMESPACE_ID=$(cat /run/secrets/kubernetes.io/serviceaccount/namespace) + export VERSION_CHECK=$(python /app/version_check.py /root/saas/ocenter/build) - if [[ "$IMPORT_FRONTEND" == "true" ]] ; then + if [[ "$IMPORT_FRONTEND" == "true" && "$VERSION_CHECK" == "NEED UPDATE" ]] ; then - envsubst < /root/saas/ocenter/ui/launch-v2.yaml.tpl > /root/saas/ocenter/ui/launch.yaml - envsubst < /root/saas/ocenter/ui/launch-v2-dev.yaml.tpl > /root/saas/ocenter/ui/launch-dev.yaml - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id ocenter --filepath /root/saas/ocenter/ui/ocenter-auto.zip --print-only-app-package-id=true --reset-version=true) + envsubst < /root/saas/ocenter/build/launch-frontend.yaml.tpl > /root/saas/ocenter/launch-frontend.yaml + envsubst < /root/saas/ocenter/build/launch-frontend-dev.yaml.tpl > /root/saas/ocenter/launch-frontend-dev.yaml + python /app/pack.py --src /root/saas/ocenter/build --dest /root/saas/ocenter/build.zip + + sh /app/import.sh ocenter /root/saas/ocenter/build.zip /root/saas/health/launch.yaml /root/saas/ocenter/launch-frontend-dev.yaml - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id ocenter --path /root/saas/ocenter/ui/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id ocenter --path /root/saas/ocenter/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master fi saas-help.sh: | @@ -1307,16 +1373,17 @@ data: cd /root export NAMESPACE_ID=$(cat /run/secrets/kubernetes.io/serviceaccount/namespace) + export VERSION_CHECK=$(python /app/version_check.py /root/saas/help/build) - if [[ "$IMPORT_FRONTEND" == "true" ]] ; then - + if [[ "$IMPORT_FRONTEND" == "true" && "$VERSION_CHECK" == "NEED UPDATE" ]] ; then - envsubst < /root/saas/help/ui/launch-v2.yaml.tpl > /root/saas/help/ui/launch.yaml - envsubst < /root/saas/help/ui/launch-v2-dev.yaml.tpl > /root/saas/help/ui/launch-dev.yaml - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id help --filepath /root/saas/help/ui/help-auto.zip --print-only-app-package-id=true --reset-version=true) + + python /app/pack.py --src /root/saas/help/build --dest /root/saas/help/build.zip + envsubst < /root/saas/job/build/launch-frontend.yaml.tpl > /root/saas/help/launch-frontend.yaml + envsubst < /root/saas/job/build/launch-frontend-dev.yaml.tpl > /root/saas/help/launch-frontend-dev.yaml + + sh /app/import.sh help /root/saas/help/build.zip /root/saas/help/launch-frontend.yaml /root/saas/help/launch-frontend-dev.yaml - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id help --path /root/saas/help/ui/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id help --path /root/saas/help/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master fi @@ -1331,44 +1398,29 @@ data: # build&launch search api export NAMESPACE_ID=$(cat /run/secrets/kubernetes.io/serviceaccount/namespace) + export VERSION_CHECK=$(python /app/version_check.py /root/saas/search/build) envsubst < /root/saas/search/api/build.yaml.tpl > /root/saas/search/api/build.yaml - envsubst < /root/saas/search/api/launch.yaml.tpl > /root/saas/search/api/launch.yaml - envsubst < /root/saas/search/ui/launch-v2.yaml.tpl > /root/saas/search/ui/launch.yaml - envsubst < /root/saas/search/ui/launch-v2-dev.yaml.tpl > /root/saas/search/ui/launch-dev.yaml - + envsubst < /root/saas/search/build/launch.yaml.tpl > /root/saas/search/launch.yaml + envsubst < /root/saas/search/build/launch-backend.yaml.tpl > /root/saas/search/launch-backend.yaml + envsubst < /root/saas/search/build/launch-frontend.yaml.tpl > /root/saas/search/launch-frontend.yaml + envsubst < /root/saas/search/build/launch-frontend-dev.yaml.tpl > /root/saas/search/launch-frontend-dev.yaml + python /app/pack.py --src /root/saas/search/build --dest /root/saas/search/build.zip if [[ "$IMAGE_BUILD_ENABLE" == "true" ]] ; then cd /root/saas/search/api/ - /root/swcli --config /swcli/swcli.yaml app-package oneflow --app-id=search --stage=prod --namespace=${NAMESPACE_ID} --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=./launch.yaml --disable-dir-check + /root/swcli --config /swcli/swcli.yaml app-package oneflow --app-id=search --stage=prod --namespace=${NAMESPACE_ID} --tags="release=sreworks/x86_64" --arch=x86 --cluster=master --path=../launch-backend.yaml --disable-dir-check if [[ "$IMPORT_FRONTEND" == "true" ]] ; then + + sh /app/import.sh search /root/saas/search/build.zip /root/saas/search/launch-frontend.yaml /root/saas/search/launch-frontend-dev.yaml - envsubst < /root/saas/search/ui/launch-v2.yaml.tpl > /root/saas/search/ui/launch.yaml - envsubst < /root/saas/search/ui/launch-v2-dev.yaml.tpl > /root/saas/search/ui/launch-dev.yaml - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id search --filepath /root/saas/search/ui/search-auto.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id search --path /root/saas/search/ui/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id search --path /root/saas/search/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master fi - else + elif [[ "$VERSION_CHECK" == "NEED UPDATE" ]] ; then - cd /root/saas/search/ - - sh /app/core-action-service-check.sh + sh /app/import.sh search /root/saas/search/build.zip /root/saas/search/launch.yaml /root/saas/search/launch-frontend-dev.yaml - echo "" > merge-launch.yaml - cat /root/saas/search/api/launch.yaml >> merge-launch.yaml - echo "---" >> merge-launch.yaml - cat /root/saas/search/ui/launch.yaml >> merge-launch.yaml - cat merge-launch.yaml | python /app/reduce.py > launch.yaml - - result=$(/root/swcli --config /swcli/swcli.yaml app-package import --app-id search --filepath /root/saas/search/search.zip --print-only-app-package-id=true --reset-version=true) - - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage prod --app-id search --path /root/saas/search/launch.yaml --app-package-id $result --arch x86 --wait=true --cluster master - /root/swcli --config /swcli/swcli.yaml deployment launch --namespace ${NAMESPACE_ID} --stage dev --app-id search --path /root/saas/search/ui/launch-dev.yaml --app-package-id $result --arch x86 --wait=true --cluster master - fi @@ -1423,6 +1475,75 @@ data: /root/swcli --config /swcli/swcli.yaml deployment launch --namespace sreworks --stage prod --app-id sreworks1 --path /root/saas/app/launch-demoApp.yaml --app-package-id $result --arch x86 --wait=true --cluster master fi + version_check.py: | + + import sys + import os + import yaml + from oauthlib.oauth2 import LegacyApplicationClient + from requests_oauthlib import OAuth2Session + from distutils.version import StrictVersion + + ENDPOINT = 'http://sreworks-appmanager' + CLIENT_ID = os.getenv('APPMANAGER_CLIENT_ID') + CLIENT_SECRET = os.getenv('APPMANAGER_CLIENT_SECRET') + USERNAME = os.getenv('APPMANAGER_USERNAME') + PASSWORD = os.getenv('APPMANAGER_PASSWORD') + + class AppManagerClient(object): + + def __init__(self, endpoint, client_id, client_secret, username, password): + os.environ.setdefault('OAUTHLIB_INSECURE_TRANSPORT', '1') + self._endpoint = endpoint + self._client_id = client_id + self._client_secret = client_secret + self._username = username + self._password = password + self._token = self._fetch_token() + + @property + def client(self): + return OAuth2Session(self._client_id, token=self._token) + + def _fetch_token(self): + oauth = OAuth2Session(client=LegacyApplicationClient(client_id=CLIENT_ID)) + return oauth.fetch_token( + token_url=os.path.join(ENDPOINT, 'oauth/token'), + username=self._username, + password=self._password, + client_id=self._client_id, + client_secret=self._client_secret + ) + + appBuildPath = sys.argv[1] + + f = open(appBuildPath + "/meta.yaml", 'r') + metaData = yaml.safe_load(f.read()) + f.close() + + appId = metaData["appId"] + baselineVersion = metaData["packageVersion"].split("+")[0] + + appmanagerClient = AppManagerClient(ENDPOINT, CLIENT_ID, CLIENT_SECRET, USERNAME, PASSWORD) + res = appmanagerClient.client.get(ENDPOINT + "/realtime/app-instances?appId=" + appId + "&stageId=prod") + items = res.json()["data"].get("items", []) + if len(items) == 0: + print("NEED UPDATE") + sys.exit(0) + + for item in items: + if StrictVersion(baselineVersion) > StrictVersion(item["simpleVersion"]): + print("NEED UPDATE") + sys.exit(0) + + if StrictVersion(baselineVersion) == StrictVersion(item["simpleVersion"]) and item["status"] not in ["RUNNING","PENDING"]: + print("NEED UPDATE") + sys.exit(0) + + + print("NO UPDATE") + sys.exit(0) + saas-sleep.sh: | sleep 999999999999 @@ -1445,6 +1566,24 @@ kind: ConfigMap metadata: name: init-swcli --- +# Source: sreworks/charts/appmanagerbase/charts/openebs/templates/localprovisioner/hostpath-class.yaml +# The second operand in the AND operation can be removed +# when enableHostpathClass is deprecated. +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: sreworks-hostpath + annotations: + openebs.io/cas-type: local + cas.openebs.io/config: | + - name: StorageType + value: "hostpath" + - name: BasePath + value: "/var/openebs/local" +provisioner: openebs.io/local +volumeBindingMode: WaitForFirstConsumer +reclaimPolicy: Delete +--- # Source: sreworks/charts/appmanagerbase/charts/minio/templates/pvc-standalone.yaml kind: PersistentVolumeClaim apiVersion: v1 @@ -15481,6 +15620,56 @@ rules: - list - watch --- +# Source: sreworks/charts/appmanagerbase/charts/openebs/templates/clusterrole.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: sreworks-openebs + labels: + app: openebs + chart: openebs-3.1.0 + release: sreworks + heritage: Helm +rules: +- apiGroups: ["*"] + resources: ["nodes", "nodes/proxy"] + verbs: ["*"] +- apiGroups: ["*"] + resources: ["namespaces", "services", "pods", "pods/exec", "deployments", "deployments/finalizers", "replicationcontrollers", "replicasets", "events", "endpoints", "configmaps", "secrets", "jobs", "cronjobs" ] + verbs: ["*"] +- apiGroups: ["*"] + resources: ["statefulsets", "daemonsets"] + verbs: ["*"] +- apiGroups: ["*"] + resources: ["resourcequotas", "limitranges"] + verbs: ["list", "watch"] +- apiGroups: ["*"] + resources: ["ingresses", "horizontalpodautoscalers", "verticalpodautoscalers", "poddisruptionbudgets", "certificatesigningrequests"] + verbs: ["list", "watch"] +- apiGroups: ["*"] + resources: ["storageclasses", "persistentvolumeclaims", "persistentvolumes"] + verbs: ["*"] +- apiGroups: ["volumesnapshot.external-storage.k8s.io"] + resources: ["volumesnapshots", "volumesnapshotdatas"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] +- apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: [ "get", "list", "create", "update", "delete", "patch"] +- apiGroups: ["openebs.io"] + resources: [ "*"] + verbs: ["*" ] +- apiGroups: ["cstor.openebs.io"] + resources: [ "*"] + verbs: ["*" ] +- apiGroups: ["coordination.k8s.io"] + resources: ["leases"] + verbs: ["get", "watch", "list", "delete", "update", "create"] +- apiGroups: ["admissionregistration.k8s.io"] + resources: ["validatingwebhookconfigurations", "mutatingwebhookconfigurations"] + verbs: ["get", "create", "list", "delete", "update", "patch"] +- nonResourceURLs: ["/metrics"] + verbs: ["get"] +--- # Source: sreworks/charts/appmanager/templates/rbac-admin.yaml kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 @@ -15523,6 +15712,25 @@ subjects: name: kruise-daemon namespace: kruise-system --- +# Source: sreworks/charts/appmanagerbase/charts/openebs/templates/clusterrolebinding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: sreworks-openebs + labels: + app: openebs + chart: openebs-3.1.0 + release: sreworks + heritage: Helm +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: sreworks-openebs +subjects: +- kind: ServiceAccount + name: sreworks-openebs + namespace: sreworks +--- # Source: sreworks/charts/appmanagerbase/charts/kruise/templates/rbac_role.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: Role @@ -15920,6 +16128,135 @@ spec: type: "" name: runtime-socket --- +# Source: sreworks/charts/appmanagerbase/charts/openebs/templates/ndm/daemonset-ndm.yaml +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: sreworks-openebs-ndm + labels: + app: openebs + chart: openebs-3.1.0 + release: sreworks + heritage: Helm + component: ndm + openebs.io/component-name: ndm + openebs.io/version: 3.1.0 +spec: + updateStrategy: + type: "RollingUpdate" + selector: + matchLabels: + app: openebs + release: sreworks + component: ndm + template: + metadata: + labels: + app: openebs + release: sreworks + component: ndm + openebs.io/component-name: ndm + name: openebs-ndm + openebs.io/version: 3.1.0 + spec: + serviceAccountName: sreworks-openebs + hostNetwork: true + # host PID is used to check status of iSCSI Service when the NDM + # API service is enabled + containers: + - name: openebs-ndm + image: "openebs/node-disk-manager:1.8.0" + args: + - -v=4 + - --feature-gates=GPTBasedUUID + imagePullPolicy: IfNotPresent + securityContext: + privileged: true + env: + # namespace in which NDM is installed will be passed to NDM Daemonset + # as environment variable + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + # pass hostname as env variable using downward API to the NDM container + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + # specify the directory where the sparse files need to be created. + # if not specified, then sparse files will not be created. + - name: SPARSE_FILE_DIR + value: "/var/openebs/sparse" + # Size(bytes) of the sparse file to be created. + - name: SPARSE_FILE_SIZE + value: "10737418240" + # Specify the number of sparse files to be created + - name: SPARSE_FILE_COUNT + value: "0" + # Process name used for matching is limited to the 15 characters + # present in the pgrep output. + # So fullname can be used here with pgrep (cmd is < 15 chars). + livenessProbe: + exec: + command: + - pgrep + - "ndm" + initialDelaySeconds: 30 + periodSeconds: 60 + volumeMounts: + - name: config + mountPath: /host/node-disk-manager.config + subPath: node-disk-manager.config + readOnly: true + - name: udev + mountPath: /run/udev + - name: procmount + mountPath: /host/proc + readOnly: true + - name: devmount + mountPath: /dev + - name: basepath + mountPath: /var/openebs/ndm + - name: sparsepath + mountPath: /var/openebs/sparse + volumes: + - name: config + configMap: + name: sreworks-openebs-ndm-config + - name: udev + hostPath: + path: /run/udev + type: Directory + # mount /proc (to access mount file of process 1 of host) inside container + # to read mount-point of disks and partitions + - name: procmount + hostPath: + path: /proc + type: Directory + # the /dev directory is mounted so that we have access to the devices that + # are connected at runtime of the pod. + - name: devmount + hostPath: + path: /dev + type: Directory + - name: basepath + hostPath: + path: "/var/openebs/ndm" + type: DirectoryOrCreate + - name: sparsepath + hostPath: + path: /var/openebs/sparse + # By default the node-disk-manager will be run on all kubernetes nodes + # If you would like to limit this to only some nodes, say the nodes + # that have storage attached, you could label those node and use + # nodeSelector. + # + # e.g. label the storage nodes with - "openebs.io/nodegroup"="storage-node" + # kubectl label node "openebs.io/nodegroup"="storage-node" + #nodeSelector: + # "openebs.io/nodegroup": "storage-node" +--- # Source: sreworks/charts/appmanager/templates/operator-deployment.yaml apiVersion: apps/v1 kind: Deployment @@ -15956,7 +16293,7 @@ spec: - --global-listener=true command: - /manager - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/sw-paas-appmanager-operator:v0.5 + image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/sw-paas-appmanager-operator:v1.2 imagePullPolicy: Always name: manager resources: @@ -15985,7 +16322,7 @@ spec: spec: initContainers: - name: server-init - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/sw-paas-appmanager-db-migration:v0.5 + image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/sw-paas-appmanager-db-migration:v1.2 imagePullPolicy: Always envFrom: - configMapRef: @@ -15996,10 +16333,10 @@ spec: httpGet: path: /status.taobao port: 7001 - initialDelaySeconds: 120 + initialDelaySeconds: 1200 failureThreshold: 5 periodSeconds: 20 - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/sw-paas-appmanager:v0.5 + image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/sw-paas-appmanager:v1.2 imagePullPolicy: Always ports: - containerPort: 7001 @@ -16199,6 +16536,173 @@ spec: persistentVolumeClaim: claimName: sreworks-minio --- +# Source: sreworks/charts/appmanagerbase/charts/openebs/templates/localprovisioner/deployment-local-provisioner.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: sreworks-openebs-localpv-provisioner + labels: + app: openebs + chart: openebs-3.1.0 + release: sreworks + heritage: Helm + component: localpv-provisioner + openebs.io/component-name: openebs-localpv-provisioner + openebs.io/version: 3.1.0 +spec: + replicas: 1 + strategy: + type: "Recreate" + rollingUpdate: null + selector: + matchLabels: + app: openebs + release: sreworks + template: + metadata: + labels: + app: openebs + release: sreworks + component: localpv-provisioner + name: openebs-localpv-provisioner + openebs.io/component-name: openebs-localpv-provisioner + openebs.io/version: 3.1.0 + spec: + serviceAccountName: sreworks-openebs + containers: + - name: openebs-localpv-provisioner + image: "openebs/provisioner-localpv:3.1.0" + imagePullPolicy: IfNotPresent + args: + - "--bd-time-out=$(BDC_BD_BIND_RETRIES)" + env: + # OPENEBS_IO_K8S_MASTER enables openebs provisioner to connect to K8s + # based on this address. This is ignored if empty. + # This is supported for openebs provisioner version 0.5.2 onwards + #- name: OPENEBS_IO_K8S_MASTER + # value: "http://10.128.0.12:8080" + # OPENEBS_IO_KUBE_CONFIG enables openebs provisioner to connect to K8s + # based on this config. This is ignored if empty. + # This is supported for openebs provisioner version 0.5.2 onwards + #- name: OPENEBS_IO_KUBE_CONFIG + # value: "/home/ubuntu/.kube/config" + # This sets the number of times the provisioner should try + # with a polling interval of 5 seconds, to get the Blockdevice + # Name from a BlockDeviceClaim, before the BlockDeviceClaim + # is deleted. E.g. 12 * 5 seconds = 60 seconds timeout + - name: BDC_BD_BIND_RETRIES + value: "12" + # OPENEBS_NAMESPACE is the namespace that this provisioner will + # lookup to find maya api service + - name: OPENEBS_NAMESPACE + value: "sreworks" + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + # OPENEBS_SERVICE_ACCOUNT provides the service account of this pod as + # environment variable + - name: OPENEBS_SERVICE_ACCOUNT + valueFrom: + fieldRef: + fieldPath: spec.serviceAccountName + # OPENEBS_IO_BASE_PATH is the environment variable that provides the + # default base path on the node where host-path PVs will be provisioned. + - name: OPENEBS_IO_ENABLE_ANALYTICS + value: "true" + - name: OPENEBS_IO_BASE_PATH + value: "/var/openebs/local" + - name: OPENEBS_IO_HELPER_IMAGE + value: "openebs/linux-utils:3.1.0" + - name: OPENEBS_IO_INSTALLER_TYPE + value: "charts-helm" + # LEADER_ELECTION_ENABLED is used to enable/disable leader election. By default + # leader election is enabled. + - name: LEADER_ELECTION_ENABLED + value: "true" + # Process name used for matching is limited to the 15 characters + # present in the pgrep output. + # So fullname can't be used here with pgrep (>15 chars).A regular expression + # that matches the entire command name has to specified. + # Anchor `^` : matches any string that starts with `provisioner-loc` + # `.*`: matches any string that has `provisioner-loc` followed by zero or more char + livenessProbe: + exec: + command: + - sh + - -c + - test `pgrep -c "^provisioner-loc.*"` = 1 + initialDelaySeconds: 30 + periodSeconds: 60 +--- +# Source: sreworks/charts/appmanagerbase/charts/openebs/templates/ndm/deployment-ndm-operator.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: sreworks-openebs-ndm-operator + labels: + app: openebs + chart: openebs-3.1.0 + release: sreworks + heritage: Helm + component: ndm-operator + openebs.io/component-name: ndm-operator + openebs.io/version: 3.1.0 + name: ndm-operator +spec: + replicas: 1 + strategy: + type: "Recreate" + rollingUpdate: null + selector: + matchLabels: + app: openebs + release: sreworks + template: + metadata: + labels: + app: openebs + release: sreworks + component: ndm-operator + name: ndm-operator + openebs.io/component-name: ndm-operator + openebs.io/version: 3.1.0 + spec: + serviceAccountName: sreworks-openebs + containers: + - name: sreworks-openebs-ndm-operator + image: "openebs/node-disk-operator:1.8.0" + imagePullPolicy: IfNotPresent + livenessProbe: + httpGet: + path: /healthz + port: 8585 + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + httpGet: + path: /readyz + port: 8585 + initialDelaySeconds: 5 + periodSeconds: 10 + env: + - name: WATCH_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: SERVICE_ACCOUNT + valueFrom: + fieldRef: + fieldPath: spec.serviceAccountName + - name: OPERATOR_NAME + value: "node-disk-operator" + - name: CLEANUP_JOB_IMAGE + value: "openebs/linux-utils:3.1.0" +--- # Source: sreworks/charts/appmanagerbase/charts/kafka/templates/statefulset.yaml apiVersion: apps/v1 kind: StatefulSet @@ -16829,7 +17333,7 @@ spec: spec: containers: - name: job - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/sw-paas-appmanager-cluster-init:v0.5 + image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/sw-paas-appmanager-cluster-init:v1.2 imagePullPolicy: Always envFrom: - configMapRef: @@ -16853,7 +17357,7 @@ spec: spec: containers: - name: job - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/sw-paas-appmanager-postrun:v0.5 + image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/sw-paas-appmanager-postrun:v1.2 imagePullPolicy: Always envFrom: - configMapRef: @@ -16867,7 +17371,7 @@ metadata: name: sreworks-core-init-job annotations: spec: - backoffLimit: 20 + backoffLimit: 100000 ttlSecondsAfterFinished: 600 template: spec: @@ -16875,7 +17379,7 @@ spec: restartPolicy: OnFailure containers: - - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/swcli-builtin-package:v0.5 + - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/swcli-builtin-package:v1.2 name: job command: ["sh"] args: ["/app/core.sh"] @@ -16903,10 +17407,10 @@ spec: apiVersion: batch/v1 kind: Job metadata: - name: sreworks-saas-cluster-init-job + name: sreworks-saas-demoapp-init-job annotations: spec: - backoffLimit: 20 + backoffLimit: 100000 ttlSecondsAfterFinished: 600 template: spec: @@ -16914,7 +17418,46 @@ spec: restartPolicy: OnFailure containers: - - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/swcli-builtin-package:v0.5 + - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/swcli-builtin-package:v1.2 + name: job + command: ["sh"] + #args: ["/app/sleep.sh"] + imagePullPolicy: Always + args: ["/app/saas-demoapp.sh"] + workingDir: /root + envFrom: + - configMapRef: + name: init-configmap + volumeMounts: + - name: run-volume + mountPath: /app + - name: swcli-volume + mountPath: /swcli + + volumes: + - name: run-volume + configMap: + name: init-run + - name: swcli-volume + configMap: + name: init-swcli +--- +# Source: sreworks/templates/init-job.yaml +apiVersion: batch/v1 +kind: Job +metadata: + name: sreworks-saas-cluster-init-job + annotations: +spec: + backoffLimit: 100000 + ttlSecondsAfterFinished: 600 + template: + spec: + + restartPolicy: OnFailure + + containers: + - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/swcli-builtin-package:v1.2 name: job command: ["sh"] #args: ["/app/sleep.sh"] @@ -16945,7 +17488,7 @@ metadata: name: sreworks-saas-app-init-job annotations: spec: - backoffLimit: 20 + backoffLimit: 100000 ttlSecondsAfterFinished: 600 template: spec: @@ -16953,7 +17496,7 @@ spec: restartPolicy: OnFailure containers: - - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/swcli-builtin-package:v0.5 + - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/swcli-builtin-package:v1.2 name: job command: ["sh"] #args: ["/app/sleep.sh"] @@ -16984,7 +17527,7 @@ metadata: name: sreworks-saas-team-init-job annotations: spec: - backoffLimit: 20 + backoffLimit: 100000 ttlSecondsAfterFinished: 600 template: spec: @@ -16992,7 +17535,7 @@ spec: restartPolicy: OnFailure containers: - - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/swcli-builtin-package:v0.5 + - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/swcli-builtin-package:v1.2 name: job command: ["sh"] #args: ["/app/sleep.sh"] @@ -17023,7 +17566,7 @@ metadata: name: sreworks-saas-dataops-init-job annotations: spec: - backoffLimit: 20 + backoffLimit: 100000 ttlSecondsAfterFinished: 600 template: spec: @@ -17031,7 +17574,7 @@ spec: restartPolicy: OnFailure containers: - - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/swcli-builtin-package:v0.5 + - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/swcli-builtin-package:v1.2 name: job command: ["sh"] #args: ["/app/sleep.sh"] @@ -17062,7 +17605,7 @@ metadata: name: sreworks-saas-system-init-job annotations: spec: - backoffLimit: 20 + backoffLimit: 100000 ttlSecondsAfterFinished: 600 template: spec: @@ -17070,7 +17613,7 @@ spec: restartPolicy: OnFailure containers: - - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/swcli-builtin-package:v0.5 + - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/swcli-builtin-package:v1.2 name: job command: ["sh"] #args: ["/app/sleep.sh"] @@ -17101,7 +17644,7 @@ metadata: name: sreworks-saas-job-init-job annotations: spec: - backoffLimit: 20 + backoffLimit: 100000 ttlSecondsAfterFinished: 600 template: spec: @@ -17109,7 +17652,7 @@ spec: restartPolicy: OnFailure containers: - - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/swcli-builtin-package:v0.5 + - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/swcli-builtin-package:v1.2 name: job command: ["sh"] #args: ["/app/sleep.sh"] @@ -17140,7 +17683,7 @@ metadata: name: sreworks-saas-search-init-job annotations: spec: - backoffLimit: 20 + backoffLimit: 100000 ttlSecondsAfterFinished: 600 template: spec: @@ -17148,7 +17691,7 @@ spec: restartPolicy: OnFailure containers: - - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/swcli-builtin-package:v0.5 + - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/swcli-builtin-package:v1.2 name: job command: ["sh"] #args: ["/app/sleep.sh"] @@ -17179,7 +17722,7 @@ metadata: name: sreworks-saas-healing-init-job annotations: spec: - backoffLimit: 20 + backoffLimit: 100000 ttlSecondsAfterFinished: 600 template: spec: @@ -17187,7 +17730,7 @@ spec: restartPolicy: OnFailure containers: - - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/swcli-builtin-package:v0.5 + - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/swcli-builtin-package:v1.2 name: job command: ["sh"] #args: ["/app/sleep.sh"] @@ -17218,7 +17761,7 @@ metadata: name: sreworks-saas-aiops-init-job annotations: spec: - backoffLimit: 20 + backoffLimit: 100000 ttlSecondsAfterFinished: 600 template: spec: @@ -17226,7 +17769,7 @@ spec: restartPolicy: OnFailure containers: - - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/swcli-builtin-package:v0.5 + - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/swcli-builtin-package:v1.2 name: job command: ["sh"] #args: ["/app/sleep.sh"] @@ -17257,7 +17800,7 @@ metadata: name: sreworks-saas-health-init-job annotations: spec: - backoffLimit: 20 + backoffLimit: 100000 ttlSecondsAfterFinished: 600 template: spec: @@ -17265,7 +17808,7 @@ spec: restartPolicy: OnFailure containers: - - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/swcli-builtin-package:v0.5 + - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/swcli-builtin-package:v1.2 name: job command: ["sh"] #args: ["/app/sleep.sh"] @@ -17296,7 +17839,7 @@ metadata: name: sreworks-saas-ocenter-init-job annotations: spec: - backoffLimit: 20 + backoffLimit: 100000 ttlSecondsAfterFinished: 600 template: spec: @@ -17304,7 +17847,7 @@ spec: restartPolicy: OnFailure containers: - - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/swcli-builtin-package:v0.5 + - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/swcli-builtin-package:v1.2 name: job command: ["sh"] #args: ["/app/sleep.sh"] @@ -17335,7 +17878,7 @@ metadata: name: sreworks-saas-help-init-job annotations: spec: - backoffLimit: 20 + backoffLimit: 100000 ttlSecondsAfterFinished: 600 template: spec: @@ -17343,7 +17886,7 @@ spec: restartPolicy: OnFailure containers: - - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/swcli-builtin-package:v0.5 + - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/swcli-builtin-package:v1.2 name: job command: ["sh"] #args: ["/app/sleep.sh"] @@ -17374,7 +17917,7 @@ metadata: name: sreworks-saas-upload-init-job annotations: spec: - backoffLimit: 20 + backoffLimit: 100000 ttlSecondsAfterFinished: 600 template: spec: @@ -17382,7 +17925,7 @@ spec: restartPolicy: OnFailure containers: - - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/swcli-builtin-package:v0.5 + - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/swcli-builtin-package:v1.2 name: job command: ["sh"] #args: ["/app/sleep.sh"] @@ -17406,44 +17949,28 @@ spec: configMap: name: init-swcli --- -# Source: sreworks/templates/init-job.yaml +# Source: sreworks/templates/progress-check-job.yaml apiVersion: batch/v1 kind: Job metadata: - name: sreworks-saas-demoapp-init-job - annotations: + name: sreworks-progress-check spec: - backoffLimit: 20 + backoffLimit: 100000 ttlSecondsAfterFinished: 600 template: spec: - restartPolicy: OnFailure - containers: - - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/swcli-builtin-package:v0.5 + - image: sreworks-registry.cn-beijing.cr.aliyuncs.com/sreworks/sw-progress-check:v1.2 name: job - command: ["sh"] - #args: ["/app/sleep.sh"] imagePullPolicy: Always - args: ["/app/saas-demoapp.sh"] - workingDir: /root envFrom: - configMapRef: name: init-configmap - volumeMounts: - - name: run-volume - mountPath: /app - - name: swcli-volume - mountPath: /swcli - - volumes: - - name: run-volume - configMap: - name: init-run - - name: swcli-volume - configMap: - name: init-swcli +--- +# Source: sreworks/charts/appmanagerbase/charts/openebs/templates/localprovisioner/device-class.yaml +# The second operand in the AND operation can be removed +# when enableDeviceClass is deprecated. --- # Source: sreworks/charts/appmanagerbase/charts/kruise/templates/webhookconfiguration.yaml apiVersion: admissionregistration.k8s.io/v1 diff --git a/paas/action/src/main/resources/application.properties b/paas/action/src/main/resources/application.properties deleted file mode 100644 index 4a1c55b2..00000000 --- a/paas/action/src/main/resources/application.properties +++ /dev/null @@ -1,26 +0,0 @@ -server.address=0.0.0.0 -server.servletPath=/ -spring.application.name=action -server.port=7001 -management.server.port=-1 -# DB -spring.datasource.driver-class-name=com.mysql.jdbc.Driver -spring.datasource.url=jdbc:mysql://appmanager-mysql.ca221ae8860d9421688e59c8ab45c8b21.cn-hangzhou.alicontainer.com:3306/sreworks?useUnicode=true&characterEncoding=utf-8&useSSL=false -spring.datasource.username=root -spring.datasource.password=bguwsawqm6k -# TKGONE -kg.search.endpoint=http://100.67.175.100:8001/data/elasticsearch/queryByKvPre -kg.insert.endpoint=http://100.67.175.100:8001/database/elasticsearch/document/upserts -# Index -tesla.abm.url=tesla.alibaba-inc.com/# -env.new.api.prefix=http://tesla.alibaba-inc.com/# -# MyBatis -mybatis.mapper-locations=classpath*:/mybatis/*Mapper.xml -mybatis.configuration.map-underscore-to-camel-case=true -# jpa -#spring.jpa.properties.hibernate.hbm2ddl.auto=update -spring.jpa.show-sql=false -spring.jpa.open-in-view=false -spring.jpa.hibernate.use-new-id-generator-mappings=false -# swagger -tesla.config.swagger.base-package=com.alibaba.tesla \ No newline at end of file diff --git a/paas/appmanager-kind-operator/Dockerfile b/paas/appmanager-kind-operator/Dockerfile index b5e0cbc7..7500c3bf 100644 --- a/paas/appmanager-kind-operator/Dockerfile +++ b/paas/appmanager-kind-operator/Dockerfile @@ -7,7 +7,7 @@ COPY go.mod go.mod COPY go.sum go.sum # cache deps before building and copying source so that we don't need to re-download as much # and so that source changes don't invalidate our downloaded layer -RUN go env -w GO111MODULE=on && go env -w GOPROXY=https://goproxy.cn,direct && go mod download +RUN go env -w GO111MODULE=on GOPROXY=https://goproxy.cn,direct && go mod download # Copy the go source COPY main.go main.go diff --git a/paas/appmanager-kind-operator/Dockerfile.arm64v8 b/paas/appmanager-kind-operator/Dockerfile.arm64v8 index 5f891d47..b22fe80c 100644 --- a/paas/appmanager-kind-operator/Dockerfile.arm64v8 +++ b/paas/appmanager-kind-operator/Dockerfile.arm64v8 @@ -7,7 +7,7 @@ COPY go.mod go.mod COPY go.sum go.sum # cache deps before building and copying source so that we don't need to re-download as much # and so that source changes don't invalidate our downloaded layer -RUN GOPROXY=https://goproxy.io,direct GOSUMDB='off' go mod download +RUN GOSUMDB='off' go mod download # Copy the go source COPY main.go main.go diff --git a/paas/appmanager-kind-operator/Makefile b/paas/appmanager-kind-operator/Makefile index cea55460..a2448503 100644 --- a/paas/appmanager-kind-operator/Makefile +++ b/paas/appmanager-kind-operator/Makefile @@ -1,7 +1,7 @@ # Image URL to use all building/pushing image targets IMG ?= controller:latest # Produce CRDs that work back to Kubernetes 1.11 (no version conversion) -CRD_OPTIONS ?= "crd:trivialVersions=true" +CRD_OPTIONS ?= "crd" # Default Dockerfile path DOCKERFILE ?= "./Dockerfile" # Go Proxy URL @@ -64,11 +64,11 @@ generate: controller-gen # Build the docker image docker-build: test - docker build . -t ${IMG} -f ${DOCKERFILE} + docker build . -t ${IMG} # Build the docker image docker-build-arm: test - sudo docker build . -t ${IMG} -f ./Dockerfile.arm64v8 + docker build . -t ${IMG} -f ./Dockerfile.arm64v8 # Build the docker image docker-build-sw: diff --git a/paas/appmanager-kind-operator/controllers/microservice_workload_advancedstatefulset.go b/paas/appmanager-kind-operator/controllers/microservice_workload_advancedstatefulset.go index 73c714b4..7a404148 100644 --- a/paas/appmanager-kind-operator/controllers/microservice_workload_advancedstatefulset.go +++ b/paas/appmanager-kind-operator/controllers/microservice_workload_advancedstatefulset.go @@ -146,7 +146,7 @@ func (r *MicroserviceReconciler) ReconcileMicroserviceAdvancedStatefulSet( return err } log.V(1).Info("deleted conflict advancedStatefulSet", "AdvancedStatefulSet", instance) - return nil + return err } log.V(1).Info(fmt.Sprintf("update AdvancedStatefulSet %s spec to %+v", microservice.Name, instance.Spec)) return nil diff --git a/paas/appmanager-kind-operator/controllers/microservice_workload_cloneset.go b/paas/appmanager-kind-operator/controllers/microservice_workload_cloneset.go index 34470fe5..9fb7a8a5 100644 --- a/paas/appmanager-kind-operator/controllers/microservice_workload_cloneset.go +++ b/paas/appmanager-kind-operator/controllers/microservice_workload_cloneset.go @@ -153,7 +153,7 @@ func (r *MicroserviceReconciler) ReconcileMicroserviceCloneSet(ctx context.Conte return err } log.V(1).Info("deleted conflict cloneset", "CloneSet", instance) - return nil + return err } log.V(1).Info(fmt.Sprintf("update CloneSet %s spec to %+v", microservice.Name, instance.Spec)) return nil diff --git a/paas/appmanager-kind-operator/main.go b/paas/appmanager-kind-operator/main.go index ca31bb08..28ac8691 100644 --- a/paas/appmanager-kind-operator/main.go +++ b/paas/appmanager-kind-operator/main.go @@ -76,7 +76,7 @@ func main() { if globalListener { options = ctrl.Options{ Scheme: scheme, - MetricsBindAddress: metricsAddr, + MetricsBindAddress: "0", Port: 9443, LeaderElection: enableLeaderElection, LeaderElectionID: namespace + ".leader.abm.io", @@ -84,7 +84,7 @@ func main() { } else { options = ctrl.Options{ Scheme: scheme, - MetricsBindAddress: metricsAddr, + MetricsBindAddress: "0", Port: 9443, LeaderElection: enableLeaderElection, LeaderElectionID: namespace + ".leader.abm.io", diff --git a/paas/appmanager/APP-META-PRIVATE/db/115_plugin_resource.up.sql b/paas/appmanager/APP-META-PRIVATE/db/115_plugin_resource.up.sql new file mode 100644 index 00000000..da02f500 --- /dev/null +++ b/paas/appmanager/APP-META-PRIVATE/db/115_plugin_resource.up.sql @@ -0,0 +1,5 @@ +alter table am_plugin_resource + modify plugin_name varchar(64) not null comment 'Plugin 唯一标识'; + +alter table am_plugin_resource + collate = utf8mb4_general_ci; diff --git a/paas/appmanager/APP-META-PRIVATE/db/116_add_app_component.up.sql b/paas/appmanager/APP-META-PRIVATE/db/116_add_app_component.up.sql new file mode 100644 index 00000000..ea3eca3c --- /dev/null +++ b/paas/appmanager/APP-META-PRIVATE/db/116_add_app_component.up.sql @@ -0,0 +1,15 @@ +CREATE TABLE IF NOT EXISTS `am_app_component` +( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID', + `gmt_create` datetime DEFAULT NULL COMMENT '创建时间', + `gmt_modified` datetime DEFAULT NULL COMMENT '最后修改时间', + `app_id` varchar(64) NOT NULL COMMENT '应用 ID', + `component_type` varchar(32) NOT NULL COMMENT '组件类型', + `component_name` varchar(64) NOT NULL COMMENT '组件名称', + `config` longtext NOT NULL COMMENT '配置内容', + PRIMARY KEY (`id`), + UNIQUE INDEX `uk_app_id_component_type_name` (`app_id`, `component_type`, `component_name`) USING BTREE, + KEY `idx_gmt_create` (`gmt_create`), + KEY `idx_gmt_modified` (`gmt_modified`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 COMMENT ='应用组件绑定表'; \ No newline at end of file diff --git a/paas/appmanager/APP-META-PRIVATE/db/117_modify_app_component.up.sql b/paas/appmanager/APP-META-PRIVATE/db/117_modify_app_component.up.sql new file mode 100644 index 00000000..87950e80 --- /dev/null +++ b/paas/appmanager/APP-META-PRIVATE/db/117_modify_app_component.up.sql @@ -0,0 +1,20 @@ +DROP TABLE IF EXISTS `am_app_component`; +CREATE TABLE IF NOT EXISTS `am_app_component` +( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID', + `gmt_create` datetime DEFAULT NULL COMMENT '创建时间', + `gmt_modified` datetime DEFAULT NULL COMMENT '最后修改时间', + `namespace_id` varchar(64) NULL COMMENT 'Namespace ID', + `stage_id` varchar(64) NULL COMMENT 'Stage ID', + `app_id` varchar(64) NOT NULL COMMENT '应用 ID', + `component_type` varchar(32) NOT NULL COMMENT '组件类型', + `component_name` varchar(64) NOT NULL COMMENT '组件名称', + `config` longtext NOT NULL COMMENT '配置内容', + PRIMARY KEY (`id`), + KEY `idx_namespace_id` (`namespace_id`), + KEY `idx_stage_id` (`stage_id`), + UNIQUE INDEX `uk_app_id_component_type_name` (`app_id`, `component_type`, `component_name`) USING BTREE, + KEY `idx_gmt_create` (`gmt_create`), + KEY `idx_gmt_modified` (`gmt_modified`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 COMMENT ='应用组件绑定表'; \ No newline at end of file diff --git a/paas/appmanager/APP-META-PRIVATE/db/118_modify_app_component.up.sql b/paas/appmanager/APP-META-PRIVATE/db/118_modify_app_component.up.sql new file mode 100644 index 00000000..40a65c83 --- /dev/null +++ b/paas/appmanager/APP-META-PRIVATE/db/118_modify_app_component.up.sql @@ -0,0 +1,21 @@ +DROP TABLE IF EXISTS `am_app_component`; +CREATE TABLE IF NOT EXISTS `am_app_component` +( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID', + `gmt_create` datetime DEFAULT NULL COMMENT '创建时间', + `gmt_modified` datetime DEFAULT NULL COMMENT '最后修改时间', + `namespace_id` varchar(64) NULL COMMENT 'Namespace ID', + `stage_id` varchar(64) NULL COMMENT 'Stage ID', + `app_id` varchar(64) NOT NULL COMMENT '应用 ID', + `category` varchar(32) NOT NULL COMMENT '分类', + `component_type` varchar(32) NOT NULL COMMENT '组件类型', + `component_name` varchar(64) NOT NULL COMMENT '组件名称', + `config` longtext NOT NULL COMMENT '配置内容', + PRIMARY KEY (`id`), + KEY `idx_namespace_id` (`namespace_id`), + KEY `idx_stage_id` (`stage_id`), + UNIQUE INDEX `uk_unique` (`app_id`, `category`, `component_type`, `component_name`) USING BTREE, + KEY `idx_gmt_create` (`gmt_create`), + KEY `idx_gmt_modified` (`gmt_modified`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 COMMENT ='应用组件绑定表'; \ No newline at end of file diff --git a/paas/appmanager/APP-META-PRIVATE/db/119_workflow_category.up.sql b/paas/appmanager/APP-META-PRIVATE/db/119_workflow_category.up.sql new file mode 100644 index 00000000..fad589f3 --- /dev/null +++ b/paas/appmanager/APP-META-PRIVATE/db/119_workflow_category.up.sql @@ -0,0 +1,8 @@ +alter table am_workflow_instance + collate = utf8mb4_general_ci; + +alter table am_workflow_instance + add category varchar(32) null comment 'Workflow 分类' after app_id; + +create index idx_category + on am_workflow_instance (category); diff --git a/paas/appmanager/APP-META-PRIVATE/db/120_modify_app_component.up.sql b/paas/appmanager/APP-META-PRIVATE/db/120_modify_app_component.up.sql new file mode 100644 index 00000000..7b37c64f --- /dev/null +++ b/paas/appmanager/APP-META-PRIVATE/db/120_modify_app_component.up.sql @@ -0,0 +1,17 @@ +alter table am_app_component + modify component_type varchar(96) not null comment '组件类型'; + +alter table am_component_package_task + modify component_type varchar(96) null comment '组件类型'; + +alter table am_component_package + modify component_type varchar(96) null comment '组件类型'; + +alter table am_helm_meta + modify component_type varchar(96) null comment '组件类型'; + +alter table am_k8s_micro_service_meta + modify component_type varchar(96) null comment '组件类型'; + +alter table am_rt_component_instance + modify component_type varchar(96) null comment '组件类型'; diff --git a/paas/appmanager/APP-META-PRIVATE/db/121_fix_deploy_config_index.up.sql b/paas/appmanager/APP-META-PRIVATE/db/121_fix_deploy_config_index.up.sql new file mode 100644 index 00000000..046d0677 --- /dev/null +++ b/paas/appmanager/APP-META-PRIVATE/db/121_fix_deploy_config_index.up.sql @@ -0,0 +1,5 @@ +alter table am_deploy_config collate = utf8mb4_general_ci; +alter table am_deploy_config_history collate = utf8mb4_general_ci; + +alter table am_deploy_config modify type_id varchar(191) not null comment '类型 ID'; +alter table am_deploy_config_history modify type_id varchar(191) not null comment '类型 ID'; diff --git a/paas/appmanager/APP-META-PRIVATE/db/122_workflow_task_add.up.sql b/paas/appmanager/APP-META-PRIVATE/db/122_workflow_task_add.up.sql new file mode 100644 index 00000000..0a55b40f --- /dev/null +++ b/paas/appmanager/APP-META-PRIVATE/db/122_workflow_task_add.up.sql @@ -0,0 +1,20 @@ +alter table am_workflow_task + modify deploy_app_id bigint default 0 null comment '发起的新 DeployApp ID'; + +alter table am_workflow_task + modify deploy_app_unit_id varchar(64) default '' null comment '发起的新 DeployApp ID 归属单元'; + +alter table am_workflow_task + modify deploy_app_namespace_id varchar(64) default '' null comment '发起的新 DeployApp ID 归属 Namespace'; + +alter table am_workflow_task + modify deploy_app_stage_id varchar(64) default '' null comment '发起的新 DeployApp ID 归属 Stage'; + +alter table am_workflow_task + collate = utf8mb4_general_ci; + +alter table am_workflow_task + add deploy_workflow_instance_id bigint null comment '发起的新 WorkflowInstance ID'; + +create index idx_deploy_workflow_instance_id + on am_workflow_task (deploy_workflow_instance_id); diff --git a/paas/appmanager/APP-META-PRIVATE/db/123_add_workflow_task_inputs.up.sql b/paas/appmanager/APP-META-PRIVATE/db/123_add_workflow_task_inputs.up.sql new file mode 100644 index 00000000..fb761fbd --- /dev/null +++ b/paas/appmanager/APP-META-PRIVATE/db/123_add_workflow_task_inputs.up.sql @@ -0,0 +1,5 @@ +alter table am_workflow_task + add task_outputs longtext default null COMMENT 'Workflow 任务节点输出 (JSONArray 字符串)'; + +alter table am_workflow_task + add task_inputs longtext default null COMMENT 'Workflow 任务节点输入 (JSONArray 字符串)'; \ No newline at end of file diff --git a/paas/appmanager/APP-META-PRIVATE/postrun/definition_schemas/secret.schema.abm.io.json b/paas/appmanager/APP-META-PRIVATE/postrun/definition_schemas/secret.schema.abm.io.json new file mode 100644 index 00000000..90fd1fdb --- /dev/null +++ b/paas/appmanager/APP-META-PRIVATE/postrun/definition_schemas/secret.schema.abm.io.json @@ -0,0 +1,5 @@ +{ + "name": "secret.schema.abm.io", + "jsonSchema": { + } +} \ No newline at end of file diff --git a/paas/appmanager/APP-META-PRIVATE/postrun/swapps/system-env.yaml b/paas/appmanager/APP-META-PRIVATE/postrun/swapps/system-env.yaml index 40e4fc22..a3159041 100644 --- a/paas/appmanager/APP-META-PRIVATE/postrun/swapps/system-env.yaml +++ b/paas/appmanager/APP-META-PRIVATE/postrun/swapps/system-env.yaml @@ -23,7 +23,21 @@ spec: - STORAGE_CLASS - ACCOUNT_SUPER_CLIENT_ID - ACCOUNT_SUPER_CLIENT_SECRET - + - DATA_ES_PASSWORD + - DATA_ES_USER + - DATA_ES_HOST + - DATA_ES_PORT + - DATA_PROM_HOST + - DATA_PROM_PORT + - DATA_DB_HOST + - DATA_DB_PORT + - DATA_DB_USER + - DATA_DB_PASSWORD + - KAFKA_ENDPOINT + - MINIO_ENDPOINT + - MINIO_ACCESS_KEY + - MINIO_SECRET_KEY + toFieldPaths: - spec.keys dataOutputs: @@ -59,4 +73,31 @@ spec: fieldPath: '{{ spec.env.ACCOUNT_SUPER_CLIENT_ID }}' - name: Global.ACCOUNT_SUPER_CLIENT_SECRET fieldPath: '{{ spec.env.ACCOUNT_SUPER_CLIENT_SECRET }}' - + - name: Global.DATA_ES_PASSWORD + fieldPath: '{{ spec.env.DATA_ES_PASSWORD }}' + - name: Global.DATA_ES_USER + fieldPath: '{{ spec.env.DATA_ES_USER }}' + - name: Global.DATA_ES_HOST + fieldPath: '{{ spec.env.DATA_ES_HOST }}' + - name: Global.DATA_ES_PORT + fieldPath: '{{ spec.env.DATA_ES_PORT }}' + - name: Global.DATA_PROM_HOST + fieldPath: '{{ spec.env.DATA_PROM_HOST }}' + - name: Global.DATA_PROM_PORT + fieldPath: '{{ spec.env.DATA_PROM_PORT }}' + - name: Global.DATA_DB_PORT + fieldPath: '{{ spec.env.DATA_DB_PORT }}' + - name: Global.DATA_DB_HOST + fieldPath: '{{ spec.env.DATA_DB_HOST }}' + - name: Global.DATA_DB_USER + fieldPath: '{{ spec.env.DATA_DB_USER }}' + - name: Global.DATA_DB_PASSWORD + fieldPath: '{{ spec.env.DATA_DB_PASSWORD }}' + - name: Global.KAFKA_ENDPOINT + fieldPath: '{{ spec.env.KAFKA_ENDPOINT }}' + - name: Global.MINIO_ENDPOINT + fieldPath: '{{ spec.env.MINIO_ENDPOINT }}' + - name: Global.MINIO_ACCESS_KEY + fieldPath: '{{ spec.env.MINIO_ACCESS_KEY }}' + - name: Global.MINIO_SECRET_KEY + fieldPath: '{{ spec.env.MINIO_SECRET_KEY }}' diff --git a/paas/appmanager/APP-META-PRIVATE/postrun/traits/secret.trait.abm.io.yaml b/paas/appmanager/APP-META-PRIVATE/postrun/traits/secret.trait.abm.io.yaml new file mode 100644 index 00000000..bf74793d --- /dev/null +++ b/paas/appmanager/APP-META-PRIVATE/postrun/traits/secret.trait.abm.io.yaml @@ -0,0 +1,11 @@ +apiVersion: core.oam.dev/v1alpha2 +kind: TraitDefinition +metadata: + name: secret.trait.abm.io +spec: + runtime: pre + appliesToWorkloads: + - "*" + definitionRef: + name: secret.schema.abm.io + example: {} diff --git a/paas/appmanager/Dockerfile_sreworks b/paas/appmanager/Dockerfile_sreworks index 5699b97e..d808b3a5 100644 --- a/paas/appmanager/Dockerfile_sreworks +++ b/paas/appmanager/Dockerfile_sreworks @@ -14,8 +14,8 @@ ARG APP_NAME=tesla-appmanager COPY --from=build /app/${APP_NAME}-start-standalone/target/${APP_NAME}.jar /app/${APP_NAME}-standalone.jar COPY --from=build /app/${APP_NAME}-start-standalone/target/${APP_NAME}/BOOT-INF/classes/application-docker.properties /app/config/application.properties # Copy Resources -COPY --from=build /app/${APP_NAME}-start-standalone/target/${APP_NAME}/BOOT-INF/classes/dynamicscripts /app/dynamicscripts -COPY --from=build /app/${APP_NAME}-start-standalone/target/${APP_NAME}/BOOT-INF/classes/jinja /app/jinja +COPY --from=build /app/${APP_NAME}-start-standalone/target/classes/dynamicscripts /app/dynamicscripts +COPY --from=build /app/${APP_NAME}-start-standalone/target/classes/jinja /app/jinja RUN wget -O /app/helm "https://abm-storage.oss-cn-zhangjiakou.aliyuncs.com/lib/helm" \ && chmod +x /app/helm \ && wget -O /app/kustomize "https://abm-storage.oss-cn-zhangjiakou.aliyuncs.com/lib/kustomize" \ diff --git a/paas/appmanager/Dockerfile_sreworks.tpl b/paas/appmanager/Dockerfile_sreworks.tpl index 743db693..a9fc5aa3 100644 --- a/paas/appmanager/Dockerfile_sreworks.tpl +++ b/paas/appmanager/Dockerfile_sreworks.tpl @@ -13,8 +13,8 @@ WORKDIR /root COPY --from=build /app/tesla-appmanager-start-standalone/target/tesla-appmanager.jar /app/tesla-appmanager-standalone.jar COPY --from=build /app/tesla-appmanager-start-standalone/target/tesla-appmanager/BOOT-INF/classes/application-docker.properties /app/config/application.properties # Copy Resources -COPY --from=build /app/tesla-appmanager-start-standalone/target/tesla-appmanager/BOOT-INF/classes/dynamicscripts /app/dynamicscripts -COPY --from=build /app/tesla-appmanager-start-standalone/target/tesla-appmanager/BOOT-INF/classes/jinja /app/jinja +COPY --from=build /app/tesla-appmanager-start-standalone/target/classes/dynamicscripts /app/dynamicscripts +COPY --from=build /app/tesla-appmanager-start-standalone/target/classes/jinja /app/jinja RUN curl -o /app/helm "${HELM_BIN_URL}" \ && chmod +x /app/helm \ && curl -o /app/kustomize "${KUSTOMIZE_BIN_URL}" \ diff --git a/paas/appmanager/pom.xml b/paas/appmanager/pom.xml index 4cd9b905..8f2a248d 100644 --- a/paas/appmanager/pom.xml +++ b/paas/appmanager/pom.xml @@ -7,7 +7,7 @@ com.alibaba.tesla tesla-appmanager pom - 1.0.4-SNAPSHOT + 1.0.5-SNAPSHOT tesla-appmanager-api tesla-appmanager-common @@ -63,6 +63,8 @@ 1.1.0 + 3.0.3 + 1.6.11 2.13.2 5.1.10 1.4.1 @@ -87,6 +89,9 @@ 3.14.0 + + 0.6.71 + 1.3.7 2.1.210 @@ -274,6 +279,18 @@ ${spring-cloud-stream-test-support.version} + + + com.github.xiaoymin + knife4j-springdoc-ui + ${knife4j-springdoc-ui.version} + + + org.springdoc + springdoc-openapi-ui + ${springdoc-openapi-ui.version} + + org.codehaus.groovy @@ -588,6 +605,13 @@ ${aliyun-sdk-oss.version} + + + com.aliyun.openservices + aliyun-log + ${aliyun-sdk-sls.version} + + org.yaml snakeyaml @@ -669,9 +693,45 @@ + + org.jacoco + jacoco-maven-plugin + 0.8.7 + + + default-prepare-agent + + prepare-agent + + + + default-report + + report + + + + + + **/test/** + **/repository/** + **/domain/** + + + + + + + org.jacoco + jacoco-maven-plugin + 0.8.7 + + + + snapshots diff --git a/paas/appmanager/tesla-appmanager-api/pom.xml b/paas/appmanager/tesla-appmanager-api/pom.xml index 3230af65..9a1be03a 100644 --- a/paas/appmanager/tesla-appmanager-api/pom.xml +++ b/paas/appmanager/tesla-appmanager-api/pom.xml @@ -7,7 +7,7 @@ com.alibaba.tesla tesla-appmanager - 1.0.4-SNAPSHOT + 1.0.5-SNAPSHOT ../pom.xml diff --git a/paas/appmanager/tesla-appmanager-api/src/main/java/com/alibaba/tesla/appmanager/api/provider/AppComponentProvider.java b/paas/appmanager/tesla-appmanager-api/src/main/java/com/alibaba/tesla/appmanager/api/provider/AppComponentProvider.java index f69cb43b..a47f61b9 100644 --- a/paas/appmanager/tesla-appmanager-api/src/main/java/com/alibaba/tesla/appmanager/api/provider/AppComponentProvider.java +++ b/paas/appmanager/tesla-appmanager-api/src/main/java/com/alibaba/tesla/appmanager/api/provider/AppComponentProvider.java @@ -1,7 +1,10 @@ package com.alibaba.tesla.appmanager.api.provider; import com.alibaba.tesla.appmanager.domain.dto.AppComponentDTO; +import com.alibaba.tesla.appmanager.domain.req.appcomponent.AppComponentCreateReq; +import com.alibaba.tesla.appmanager.domain.req.appcomponent.AppComponentDeleteReq; import com.alibaba.tesla.appmanager.domain.req.appcomponent.AppComponentQueryReq; +import com.alibaba.tesla.appmanager.domain.req.appcomponent.AppComponentUpdateReq; import java.util.List; @@ -12,10 +15,46 @@ import java.util.List; */ public interface AppComponentProvider { + /** + * 获取指定应用下的指定关联 Component 对象 + * + * @param request 应用组件绑定查询请求 + * @param operator 操作人 + * @return AppComponentDTO + */ + AppComponentDTO get(AppComponentQueryReq request, String operator); + + /** + * 创建应用下的关联 Component 绑定 + * + * @param request 创建请求 + * @param operator 操作人 + * @return 绑定后的结果 + */ + AppComponentDTO create(AppComponentCreateReq request, String operator); + + /** + * 更新应用下的关联 Component 绑定 + * + * @param request 更新请求 + * @param operator 操作人 + * @return 绑定后的结果 + */ + AppComponentDTO update(AppComponentUpdateReq request, String operator); + + /** + * 删除指定应用下的指定关联 Component 对象 + * + * @param request 应用组件绑定查询请求 + * @param operator 操作人 + * @return AppComponentDTO + */ + void delete(AppComponentDeleteReq request, String operator); + /** * 获取指定 appId 下的所有关联 Component 对象 * - * @param request 查询请求 + * @param request 查询请求 * @param operator 操作人 * @return List of AppComponentDTO */ diff --git a/paas/appmanager/tesla-appmanager-api/src/main/java/com/alibaba/tesla/appmanager/api/provider/DeployConfigProvider.java b/paas/appmanager/tesla-appmanager-api/src/main/java/com/alibaba/tesla/appmanager/api/provider/DeployConfigProvider.java index 30aa7863..bab6d68b 100644 --- a/paas/appmanager/tesla-appmanager-api/src/main/java/com/alibaba/tesla/appmanager/api/provider/DeployConfigProvider.java +++ b/paas/appmanager/tesla-appmanager-api/src/main/java/com/alibaba/tesla/appmanager/api/provider/DeployConfigProvider.java @@ -1,9 +1,8 @@ package com.alibaba.tesla.appmanager.api.provider; +import com.alibaba.tesla.appmanager.common.pagination.Pagination; import com.alibaba.tesla.appmanager.domain.dto.DeployConfigDTO; -import com.alibaba.tesla.appmanager.domain.req.deployconfig.DeployConfigApplyTemplateReq; -import com.alibaba.tesla.appmanager.domain.req.deployconfig.DeployConfigDeleteReq; -import com.alibaba.tesla.appmanager.domain.req.deployconfig.DeployConfigGenerateReq; +import com.alibaba.tesla.appmanager.domain.req.deployconfig.*; import com.alibaba.tesla.appmanager.domain.res.deployconfig.DeployConfigApplyTemplateRes; import com.alibaba.tesla.appmanager.domain.res.deployconfig.DeployConfigGenerateRes; @@ -30,6 +29,22 @@ public interface DeployConfigProvider { */ DeployConfigGenerateRes generate(DeployConfigGenerateReq req); + /** + * 根据指定查询条件获取列表(不支持继承) + * + * @param req 查询请求 + * @return 部署配置列表 + */ + Pagination list(DeployConfigListReq req); + + /** + * 更新指定 apiVersion + appId + typeId + envId 对应的 DeployConfig 记录 + * + * @param req 更新请求 + * @return 更新后的对象 + */ + DeployConfigDTO upsert(DeployConfigUpsertReq req); + /** * 删除指定 apiVersion + appId + typeId + envId 对应的 DeployConfig 记录 * diff --git a/paas/appmanager/tesla-appmanager-api/src/main/java/com/alibaba/tesla/appmanager/api/provider/PluginProvider.java b/paas/appmanager/tesla-appmanager-api/src/main/java/com/alibaba/tesla/appmanager/api/provider/PluginProvider.java index 486222e6..2360ca14 100644 --- a/paas/appmanager/tesla-appmanager-api/src/main/java/com/alibaba/tesla/appmanager/api/provider/PluginProvider.java +++ b/paas/appmanager/tesla-appmanager-api/src/main/java/com/alibaba/tesla/appmanager/api/provider/PluginProvider.java @@ -1,6 +1,10 @@ package com.alibaba.tesla.appmanager.api.provider; +import com.alibaba.tesla.appmanager.common.pagination.Pagination; import com.alibaba.tesla.appmanager.domain.dto.PluginDefinitionDTO; +import com.alibaba.tesla.appmanager.domain.dto.PluginFrontendDTO; +import com.alibaba.tesla.appmanager.domain.req.PluginQueryReq; +import com.alibaba.tesla.appmanager.domain.req.plugin.*; import org.springframework.web.multipart.MultipartFile; /** @@ -10,12 +14,51 @@ import org.springframework.web.multipart.MultipartFile; */ public interface PluginProvider { + /** + * 获取插件列表 + * + * @param request 查询插件列表请求 + * @return 插件列表 + */ + Pagination list(PluginQueryReq request); + + /** + * 查询单个插件 + * + * @return 插件列表 + */ + PluginDefinitionDTO get(PluginGetReq request); + + /** + * 启用指定插件 + * + * @param request 插件启用请求 + * @return 开启后的 PluginDefinition 对象 + */ + PluginDefinitionDTO enable(PluginEnableReq request); + + /** + * 关闭指定插件 + * + * @param request 插件关闭请求 + * @return 关闭后的 PluginDefinition 对象 + */ + PluginDefinitionDTO disable(PluginDisableReq request); + /** * 上传插件 (默认不启用) * - * @param file API 上传文件 - * @param force 是否强制上传覆盖 + * @param file API 上传文件 + * @param request 上传插件请求 * @return PluginDefinitionDTO */ - PluginDefinitionDTO upload(MultipartFile file, boolean force); + PluginDefinitionDTO upload(MultipartFile file, PluginUploadReq request); + + /** + * 获取 Plugin Frontend 资源 + * + * @param request 获取请求 + * @return PluginFrontend DTO 对象 + */ + PluginFrontendDTO getFrontend(PluginFrontendGetReq request); } diff --git a/paas/appmanager/tesla-appmanager-api/src/main/java/com/alibaba/tesla/appmanager/api/provider/TraitProvider.java b/paas/appmanager/tesla-appmanager-api/src/main/java/com/alibaba/tesla/appmanager/api/provider/TraitProvider.java index f0318693..f0d30d41 100644 --- a/paas/appmanager/tesla-appmanager-api/src/main/java/com/alibaba/tesla/appmanager/api/provider/TraitProvider.java +++ b/paas/appmanager/tesla-appmanager-api/src/main/java/com/alibaba/tesla/appmanager/api/provider/TraitProvider.java @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject; import com.alibaba.tesla.appmanager.common.pagination.Pagination; import com.alibaba.tesla.appmanager.domain.dto.TraitDTO; import com.alibaba.tesla.appmanager.domain.req.trait.TraitQueryReq; +import com.alibaba.tesla.appmanager.domain.schema.TraitDefinition; /** * Trait 服务 @@ -38,6 +39,14 @@ public interface TraitProvider { */ void apply(String request, String operator); + /** + * 向系统中新增或更新一个 Trait + * + * @param traitDefinition TraitDefinition + * @param operator 操作人 + */ + void apply(TraitDefinition traitDefinition, String operator); + /** * 删除指定条件的 Trait * diff --git a/paas/appmanager/tesla-appmanager-api/src/main/java/com/alibaba/tesla/appmanager/api/provider/WorkflowInstanceProvider.java b/paas/appmanager/tesla-appmanager-api/src/main/java/com/alibaba/tesla/appmanager/api/provider/WorkflowInstanceProvider.java index 368ca660..c75d5def 100644 --- a/paas/appmanager/tesla-appmanager-api/src/main/java/com/alibaba/tesla/appmanager/api/provider/WorkflowInstanceProvider.java +++ b/paas/appmanager/tesla-appmanager-api/src/main/java/com/alibaba/tesla/appmanager/api/provider/WorkflowInstanceProvider.java @@ -1,5 +1,6 @@ package com.alibaba.tesla.appmanager.api.provider; +import com.alibaba.fastjson.JSONObject; import com.alibaba.tesla.appmanager.common.pagination.Pagination; import com.alibaba.tesla.appmanager.domain.dto.WorkflowInstanceDTO; import com.alibaba.tesla.appmanager.domain.option.WorkflowInstanceOption; @@ -30,6 +31,23 @@ public interface WorkflowInstanceProvider { */ Pagination list(WorkflowInstanceListReq request); + /** + * 覆写 Context 到指定 Workflow 实例 + * + * @param workflowInstanceId Workflow 实例 ID + * @param context Context JSONObject + */ + void putContext(Long workflowInstanceId, JSONObject context); + + /** + * 获取指定应用指定 category 的最后一个 SUCCESS 状态的 Workflow 实例 + * + * @param appId 应用 ID + * @param category 分类 + * @return WorkflowInstanceDTO + */ + WorkflowInstanceDTO getLastSuccessInstance(String appId, String category); + /** * 启动一个 Workflow 实例 * @@ -41,7 +59,7 @@ public interface WorkflowInstanceProvider { WorkflowInstanceDTO launch(String appId, String configuration, WorkflowInstanceOption options); /** - * 恢复处于 SUSPEND 状态的 Workflow 实例 + * 唤醒处于 SUSPEND 状态的 Workflow 实例 * * @param workflowInstanceId Workflow 实例 ID * @return 执行结果 diff --git a/paas/appmanager/tesla-appmanager-auth-client/pom.xml b/paas/appmanager/tesla-appmanager-auth-client/pom.xml index c3cbb78b..7ee261e5 100644 --- a/paas/appmanager/tesla-appmanager-auth-client/pom.xml +++ b/paas/appmanager/tesla-appmanager-auth-client/pom.xml @@ -13,7 +13,7 @@ com.alibaba.tesla tesla-appmanager-auth-client - 1.0.4-SNAPSHOT + 1.0.5-SNAPSHOT 11 diff --git a/paas/appmanager/tesla-appmanager-auth-client/src/main/java/com/alibaba/tesla/appmanager/client/AppManagerClient.java b/paas/appmanager/tesla-appmanager-auth-client/src/main/java/com/alibaba/tesla/appmanager/client/AppManagerClient.java index 35acd61b..1dfb26a8 100644 --- a/paas/appmanager/tesla-appmanager-auth-client/src/main/java/com/alibaba/tesla/appmanager/client/AppManagerClient.java +++ b/paas/appmanager/tesla-appmanager-auth-client/src/main/java/com/alibaba/tesla/appmanager/client/AppManagerClient.java @@ -156,8 +156,10 @@ public class AppManagerClient { Request request; if (!StringUtils.isEmpty(internalAuthToken)) { request = requestBuilder.header("Authorization", "Bearer " + internalAuthToken).build(); + log.info("action=appmanagerAccessToken|token={}|expiresAt={}", internalAuthToken, internalExpiresAt); } else { request = requestBuilder.header("X-EmpId", "SYSTEM").build(); + log.info("action=appmanagerAccessToken|empId=SYSTEM"); } return httpClient.newCall(request).execute(); } @@ -174,8 +176,10 @@ public class AppManagerClient { Request request; if (!StringUtils.isEmpty(internalAuthToken)) { request = requestBuilder.header("Authorization", "Bearer " + internalAuthToken).build(); + log.info("action=appmanagerAccessToken|token={}|expiresAt={}", internalAuthToken, internalExpiresAt); } else { request = requestBuilder.header("X-EmpId", "SYSTEM").build(); + log.info("action=appmanagerAccessToken|empId=SYSTEM"); } Response response = httpClient.newCall(request).execute(); ResponseBody responseBody = response.body(); diff --git a/paas/appmanager/tesla-appmanager-auth/pom.xml b/paas/appmanager/tesla-appmanager-auth/pom.xml index 30d57406..948e110c 100644 --- a/paas/appmanager/tesla-appmanager-auth/pom.xml +++ b/paas/appmanager/tesla-appmanager-auth/pom.xml @@ -7,7 +7,7 @@ com.alibaba.tesla tesla-appmanager - 1.0.4-SNAPSHOT + 1.0.5-SNAPSHOT ../pom.xml diff --git a/paas/appmanager/tesla-appmanager-auth/src/main/java/com/alibaba/tesla/appmanager/auth/config/SecurityConfig.java b/paas/appmanager/tesla-appmanager-auth/src/main/java/com/alibaba/tesla/appmanager/auth/config/SecurityConfig.java index 3d880a2c..e50c286d 100644 --- a/paas/appmanager/tesla-appmanager-auth/src/main/java/com/alibaba/tesla/appmanager/auth/config/SecurityConfig.java +++ b/paas/appmanager/tesla-appmanager-auth/src/main/java/com/alibaba/tesla/appmanager/auth/config/SecurityConfig.java @@ -1,6 +1,7 @@ package com.alibaba.tesla.appmanager.auth.config; import com.alibaba.tesla.appmanager.autoconfig.AuthProperties; +import com.alibaba.tesla.appmanager.autoconfig.SystemProperties; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.http.HttpMethod; @@ -20,6 +21,9 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private AuthProperties authProperties; + @Autowired + private SystemProperties systemProperties; + @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); @@ -44,15 +48,21 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override public void configure(WebSecurity web) throws Exception { if (authProperties.getEnableAuth()) { - web.ignoring() + WebSecurity.IgnoredRequestConfigurer pre = web.ignoring() .antMatchers("/status.taobao") .antMatchers("/actuator/**") .antMatchers("/traits**") .antMatchers("/flow-manager/**") .antMatchers("/traits/**") - .antMatchers(HttpMethod.POST, "/apps") .antMatchers("/definition-schemas**") .antMatchers(HttpMethod.GET, "/realtime/**"); + if (systemProperties.isEnableOpenApiUi()) { + pre.antMatchers("/doc.html") + .antMatchers("/webjars**") + .antMatchers("/webjars/**") + .antMatchers("/v3/api-docs*") + .antMatchers("/v3/api-docs/*"); + } } else { web.ignoring().antMatchers("/**"); } diff --git a/paas/appmanager/tesla-appmanager-autoconfig/pom.xml b/paas/appmanager/tesla-appmanager-autoconfig/pom.xml index d665970b..196718b4 100644 --- a/paas/appmanager/tesla-appmanager-autoconfig/pom.xml +++ b/paas/appmanager/tesla-appmanager-autoconfig/pom.xml @@ -5,7 +5,7 @@ tesla-appmanager com.alibaba.tesla - 1.0.4-SNAPSHOT + 1.0.5-SNAPSHOT ../pom.xml 4.0.0 diff --git a/paas/appmanager/tesla-appmanager-autoconfig/src/main/java/com/alibaba/tesla/appmanager/autoconfig/SystemProperties.java b/paas/appmanager/tesla-appmanager-autoconfig/src/main/java/com/alibaba/tesla/appmanager/autoconfig/SystemProperties.java index fbe0e0d9..29bd88c3 100644 --- a/paas/appmanager/tesla-appmanager-autoconfig/src/main/java/com/alibaba/tesla/appmanager/autoconfig/SystemProperties.java +++ b/paas/appmanager/tesla-appmanager-autoconfig/src/main/java/com/alibaba/tesla/appmanager/autoconfig/SystemProperties.java @@ -22,6 +22,11 @@ public class SystemProperties { */ private boolean enableProductTaskExecutor = true; + /** + * 是否开启 doc.html (Knife4j) + */ + private boolean enableOpenApiUi = false; + /** * 流程历史保留时长(秒) */ diff --git a/paas/appmanager/tesla-appmanager-common-service/pom.xml b/paas/appmanager/tesla-appmanager-common-service/pom.xml index af7771b4..b164645b 100644 --- a/paas/appmanager/tesla-appmanager-common-service/pom.xml +++ b/paas/appmanager/tesla-appmanager-common-service/pom.xml @@ -5,7 +5,8 @@ tesla-appmanager com.alibaba.tesla - 1.0.4-SNAPSHOT + 1.0.5-SNAPSHOT + ../pom.xml 4.0.0 diff --git a/paas/appmanager/tesla-appmanager-common-service/src/main/java/com/alibaba/tesla/appmanager/common/service/impl/GitServiceImpl.java b/paas/appmanager/tesla-appmanager-common-service/src/main/java/com/alibaba/tesla/appmanager/common/service/impl/GitServiceImpl.java index e0cab1c4..6cbf2036 100644 --- a/paas/appmanager/tesla-appmanager-common-service/src/main/java/com/alibaba/tesla/appmanager/common/service/impl/GitServiceImpl.java +++ b/paas/appmanager/tesla-appmanager-common-service/src/main/java/com/alibaba/tesla/appmanager/common/service/impl/GitServiceImpl.java @@ -91,9 +91,20 @@ public class GitServiceImpl implements GitService { // 存在 repoPath 的时候,需要将 repoPath 对应的目录拷贝到 dir 实际对应的目录中 if (StringUtils.isNotEmpty(request.getRepoPath())) { - Path fromdir = tmpDir.resolve(request.getRepoPath()); - Path todir = dir.resolve(request.getRepoPath()).getParent(); - FileUtils.moveDirectoryToDirectory(fromdir.toFile(), todir.toFile(), true); + Path fromdir; + Path todir; + if(request.getRepoPath().startsWith("/")){ + fromdir = tmpDir.resolve(request.getRepoPath().substring(1)); + }else{ + fromdir = tmpDir.resolve(request.getRepoPath()); + } + if(StringUtils.isNotEmpty(request.getRewriteRepoPath())){ + todir = dir.resolve(request.getRewriteRepoPath()); + FileUtils.moveDirectory(fromdir.toFile(), todir.toFile()); + }else{ + todir = dir.resolve(request.getRepoPath()).getParent(); + FileUtils.moveDirectoryToDirectory(fromdir.toFile(), todir.toFile(), true); + } } } catch (IOException e) { throw new AppException(AppErrorCode.UNKNOWN_ERROR, "cannot create temp directory", e); @@ -180,7 +191,7 @@ public class GitServiceImpl implements GitService { String rest = StringUtil.trimStringByString(repo, HTTPS_PREFIX); return String.format("%s%s:%s@%s", HTTPS_PREFIX, ciAccount, ciToken, rest); } else { - return String.format("http://%s:%s@gitlab-sc.alibaba-inc.com/%s", ciAccount, ciToken, repo); + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "not supported"); } } diff --git a/paas/appmanager/tesla-appmanager-common/pom.xml b/paas/appmanager/tesla-appmanager-common/pom.xml index 122fffe6..087b4fc4 100644 --- a/paas/appmanager/tesla-appmanager-common/pom.xml +++ b/paas/appmanager/tesla-appmanager-common/pom.xml @@ -8,7 +8,7 @@ com.alibaba.tesla tesla-appmanager - 1.0.4-SNAPSHOT + 1.0.5-SNAPSHOT ../pom.xml diff --git a/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/constants/AppFlowVariableKey.java b/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/constants/AppFlowVariableKey.java index ee151a10..cfb97658 100644 --- a/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/constants/AppFlowVariableKey.java +++ b/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/constants/AppFlowVariableKey.java @@ -52,6 +52,11 @@ public class AppFlowVariableKey { */ public static final String CONFIGURATION = "CONFIGURATION"; + /** + * 启动覆盖全局参数 + */ + public static final String OVERWRITE_PARAMS = "OVERWRITE_PARAMS"; + /** * 当前系统中的组件包列表 */ diff --git a/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/constants/DefaultConstant.java b/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/constants/DefaultConstant.java index dee97589..fc39118f 100644 --- a/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/constants/DefaultConstant.java +++ b/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/constants/DefaultConstant.java @@ -114,4 +114,9 @@ public class DefaultConstant { public static final String UNIT = "Unit"; public static final String PRIVATE_ABM_CATEGORY = "专有云"; + + /** + * 默认 Workflow 分类 + */ + public static final String WORKFLOW_CATEGORY = "DEFAULT"; } diff --git a/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/constants/PatternConstant.java b/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/constants/PatternConstant.java new file mode 100644 index 00000000..1a212250 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/constants/PatternConstant.java @@ -0,0 +1,19 @@ +package com.alibaba.tesla.appmanager.common.constants; + +/** + * Pattern 常量 + * + * @author yaoxing.gyx@alibaba-inc.com + */ +public class PatternConstant { + + /** + * 合法 DNS REGEX + */ + public static final String DNS_REGEX = "^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]*[a-zA-Z0-9])\\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\\-]*[A-Za-z0-9])$"; + + /** + * 字母/数字 REGEX + */ + public static final String ALPHANUMERIC_REGEX = "^[a-zA-Z0-9]+$"; +} diff --git a/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/constants/PluginConstant.java b/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/constants/PluginConstant.java new file mode 100644 index 00000000..fa2bd161 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/constants/PluginConstant.java @@ -0,0 +1,14 @@ +package com.alibaba.tesla.appmanager.common.constants; + +/** + * Plugin 常量 + * + * @author yaoxing.gyx@alibaba-inc.com + */ +public class PluginConstant { + + /** + * Plugin 的当前版本 + */ + public static final String PLUGIN_CURRENT_VERSION = "current"; +} diff --git a/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/constants/WorkflowContextKeyConstant.java b/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/constants/WorkflowContextKeyConstant.java new file mode 100644 index 00000000..20395547 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/constants/WorkflowContextKeyConstant.java @@ -0,0 +1,34 @@ +package com.alibaba.tesla.appmanager.common.constants; + +/** + * Workflow Context 中内置 Key 常量清单 + * + * @author yaoxing.gyx@alibaba-inc.com + */ +public class WorkflowContextKeyConstant { + + /** + * 部署单覆盖参数 (用于 apply-components 的上下过程连接) + */ + public static final String DEPLOY_OVERWRITE_PARAMETERS = "_internal_overwrite_parameters"; + + /** + * 部署单覆盖参数 (用于 apply-components 的上下过程连接) + */ + public static final String DEPLOY_DELIVER_PARAMETERS = "_internal_deliver_parameters"; + + /** + * 终止后续执行 + */ + public static final String CANCEL_EXECUTION = "_internal_cancel_execution"; + + /** + * 终止后续执行原因 + */ + public static final String CANCEL_EXECUTION_REASON = "_internal_cancel_execution_reason"; + + /** + * 安静执行模式 (不需要人工确认) + */ + public static final String QUIET_MODE = "_internal_quiet_mode"; +} diff --git a/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/enums/ComponentTypeEnum.java b/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/enums/ComponentTypeEnum.java index 672f0704..9db64427 100644 --- a/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/enums/ComponentTypeEnum.java +++ b/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/enums/ComponentTypeEnum.java @@ -1,9 +1,5 @@ package com.alibaba.tesla.appmanager.common.enums; -import com.alibaba.tesla.appmanager.common.exception.AppErrorCode; -import com.alibaba.tesla.appmanager.common.exception.AppException; -import com.google.common.base.Enums; - /** * 组件类型 Enum * @@ -91,75 +87,25 @@ public enum ComponentTypeEnum { */ SCRIPT; - public static ComponentTypeEnum parse(String value) { - ComponentTypeEnum result = Enums.getIfPresent(ComponentTypeEnum.class, value).orNull(); - if (result == null) { - throw new AppException(AppErrorCode.INVALID_USER_ARGS, - String.format("invalid component type %s", value)); - } - return result; + /** + * 返回指定的 componentType 是否为 addon + * + * @param componentType Component Type + * @return true or false + */ + public static boolean isAddon(String componentType) { + return RESOURCE_ADDON.toString().equals(componentType) + || TRAIT_ADDON.toString().equals(componentType) + || CUSTOM_ADDON.toString().equals(componentType); } /** - * 返回当前 component 类型是否为非 Addon + * 返回指定的 componentType 是否为 K8S_MICROSERVICE || K8S_JOB * + * @param componentType Component Type * @return true or false */ - public boolean isNotAddon() { - return !RESOURCE_ADDON.equals(this) && !TRAIT_ADDON.equals(this) && !CUSTOM_ADDON.equals(this); - } - - /** - * 返回当前 component 类型是否为 Addon - * - * @return true or false - */ - public boolean isAddon() { - return RESOURCE_ADDON.equals(this) || INTERNAL_ADDON.equals(this); - } - - /** - * 返回当前 component 类型是否为 RESOURCE_ADDON - * - * @return true or false - */ - public boolean isResourceAddon() { - return RESOURCE_ADDON.equals(this); - } - - /** - * 返回当前 component 类型是否为 INTERNAL_ADDON - * - * @return true or false - */ - public boolean isInternalAddon() { - return INTERNAL_ADDON.equals(this); - } - - /** - * 返回当前 component 类型是否为 K8S_MICROSERVICE - * - * @return true or false - */ - public boolean isKubernetesMicroservice() { - return K8S_MICROSERVICE.equals(this); - } - - /** - * 返回当前 component 类型是否为 K8S_JOB - * - * @return true or false - */ - public boolean isKubernetesJob() { - return K8S_JOB.equals(this); - } - - /** - * 返回当前 component 类型是否为 HELM - * - * @return true or false - */ - public boolean isHelm() { - return HELM.equals(this); + public static boolean isMicroserviceOrJob(String componentType) { + return K8S_MICROSERVICE.toString().equals(componentType) || K8S_JOB.toString().equals(componentType); } } diff --git a/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/enums/DeployAppAttrTypeEnum.java b/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/enums/DeployAppAttrTypeEnum.java index 2eb19a35..ff14ff04 100644 --- a/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/enums/DeployAppAttrTypeEnum.java +++ b/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/enums/DeployAppAttrTypeEnum.java @@ -20,5 +20,10 @@ public enum DeployAppAttrTypeEnum { /** * 全局变量 (初始化) */ - GLOBAL_VARIABLES; + GLOBAL_VARIABLES, + + /** + * 初始化时提供的覆盖变量 (用于 GLOBAL_PARAMS 的覆盖) + */ + OVERWRITE_PARAMS; } diff --git a/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/enums/PluginKindEnum.java b/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/enums/PluginKindEnum.java index 7b76f1bf..a0cbc650 100644 --- a/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/enums/PluginKindEnum.java +++ b/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/enums/PluginKindEnum.java @@ -15,6 +15,11 @@ public enum PluginKindEnum { */ COMPONENT_DEFINITION("ComponentDefinition"), + /** + * Resource Addon + */ + RESOURCE_ADDON_DEFINITION("ResourceAddonDefinition"), + /** * Trait */ diff --git a/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/exception/AppErrorCode.java b/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/exception/AppErrorCode.java index 2115f25b..bfe2fc80 100644 --- a/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/exception/AppErrorCode.java +++ b/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/exception/AppErrorCode.java @@ -80,7 +80,12 @@ public enum AppErrorCode { /** * 认证异常 */ - AUTHORIZED_ERROR(10013, "AUTHORIZED_ERROR"); + AUTHORIZED_ERROR(10013, "AUTHORIZED_ERROR"), + + /** + * Groovy 脚本异常 + */ + GROOVY_ERROR(10014, "GROOVY_ERROR"); private final int code; private final String description; diff --git a/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/util/AddonUtil.java b/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/util/AddonUtil.java index aa64bf89..4a195bed 100644 --- a/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/util/AddonUtil.java +++ b/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/util/AddonUtil.java @@ -39,7 +39,7 @@ public class AddonUtil { * @param addonId Addon ID * @return Addon Key */ - public static String combineAddonKey(ComponentTypeEnum componentType, String addonId) { + public static String combineAddonKey(String componentType, String addonId) { return String.format("%s-%s", componentType, addonId); } } diff --git a/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/util/ExceptionUtil.java b/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/util/ExceptionUtil.java new file mode 100644 index 00000000..d5bec02f --- /dev/null +++ b/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/util/ExceptionUtil.java @@ -0,0 +1,23 @@ +package com.alibaba.tesla.appmanager.common.util; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.Writer; + +/** + * @ClassName: ExceptionUtil + * @Author: dyj + * @DATE: 2021-04-01 + * @Description: + **/ +public class ExceptionUtil { + public static String getStackTrace(Throwable aThrowable) { + if (aThrowable == null) { + return null; + } + final Writer result = new StringWriter(); + final PrintWriter printWriter = new PrintWriter(result); + aThrowable.printStackTrace(printWriter); + return result.toString(); + } +} diff --git a/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/util/PackageUtil.java b/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/util/PackageUtil.java index 0948b8ad..3dab8878 100644 --- a/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/util/PackageUtil.java +++ b/paas/appmanager/tesla-appmanager-common/src/main/java/com/alibaba/tesla/appmanager/common/util/PackageUtil.java @@ -117,4 +117,15 @@ public class PackageUtil { } } } + + /** + * 构造组件包 ZIP 的 basename (componentType 中 / 替换为 _) + * + * @param componentType 组件类型 + * @param componentName 组件名称 + * @return 构造后的一层文件名 basename + */ + public static String buildComponentPackageZipBasename(String componentType, String componentName) { + return String.format("%s_%s.zip", componentType.replaceAll("/", "_"), componentName); + } } diff --git a/paas/appmanager/tesla-appmanager-definition/pom.xml b/paas/appmanager/tesla-appmanager-definition/pom.xml index 820a0321..cf6d4462 100644 --- a/paas/appmanager/tesla-appmanager-definition/pom.xml +++ b/paas/appmanager/tesla-appmanager-definition/pom.xml @@ -7,7 +7,7 @@ com.alibaba.tesla tesla-appmanager - 1.0.4-SNAPSHOT + 1.0.5-SNAPSHOT ../pom.xml @@ -27,6 +27,10 @@ com.alibaba.tesla tesla-appmanager-api + + com.alibaba.tesla + tesla-appmanager-spring + io.sreworks diff --git a/paas/appmanager/tesla-appmanager-definition/src/main/java/com/alibaba/tesla/appmanager/definition/controller/DefinitionSchemaController.java b/paas/appmanager/tesla-appmanager-definition/src/main/java/com/alibaba/tesla/appmanager/definition/controller/DefinitionSchemaController.java index 07ecd5da..e0c71795 100644 --- a/paas/appmanager/tesla-appmanager-definition/src/main/java/com/alibaba/tesla/appmanager/definition/controller/DefinitionSchemaController.java +++ b/paas/appmanager/tesla-appmanager-definition/src/main/java/com/alibaba/tesla/appmanager/definition/controller/DefinitionSchemaController.java @@ -6,6 +6,7 @@ import com.alibaba.tesla.appmanager.domain.dto.DefinitionSchemaDTO; import com.alibaba.tesla.appmanager.domain.req.DefinitionSchemaQueryReq; import com.alibaba.tesla.common.base.TeslaBaseResult; import com.alibaba.tesla.web.controller.BaseController; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @@ -18,6 +19,7 @@ import java.util.HashMap; * @author yaoxing.gyx@alibaba-inc.com */ @Slf4j +@Tag(name = "DefinitionSchema API") @RequestMapping("/definition-schemas") @RestController public class DefinitionSchemaController extends BaseController { diff --git a/paas/appmanager/tesla-appmanager-deploy-config/pom.xml b/paas/appmanager/tesla-appmanager-deploy-config/pom.xml index 99a9b4e3..b532ef70 100644 --- a/paas/appmanager/tesla-appmanager-deploy-config/pom.xml +++ b/paas/appmanager/tesla-appmanager-deploy-config/pom.xml @@ -6,7 +6,7 @@ com.alibaba.tesla tesla-appmanager - 1.0.4-SNAPSHOT + 1.0.5-SNAPSHOT ../pom.xml diff --git a/paas/appmanager/tesla-appmanager-deploy-config/src/main/java/com/alibaba/tesla/appmanager/deployconfig/assembly/DeployConfigDtoConvert.java b/paas/appmanager/tesla-appmanager-deploy-config/src/main/java/com/alibaba/tesla/appmanager/deployconfig/assembly/DeployConfigDtoConvert.java index ae5c2ef5..de1a81c7 100644 --- a/paas/appmanager/tesla-appmanager-deploy-config/src/main/java/com/alibaba/tesla/appmanager/deployconfig/assembly/DeployConfigDtoConvert.java +++ b/paas/appmanager/tesla-appmanager-deploy-config/src/main/java/com/alibaba/tesla/appmanager/deployconfig/assembly/DeployConfigDtoConvert.java @@ -1,11 +1,18 @@ package com.alibaba.tesla.appmanager.deployconfig.assembly; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; import com.alibaba.tesla.appmanager.common.assembly.BaseDtoConvert; +import com.alibaba.tesla.appmanager.common.util.ClassUtil; +import com.alibaba.tesla.appmanager.common.util.SchemaUtil; import com.alibaba.tesla.appmanager.deployconfig.repository.domain.DeployConfigDO; import com.alibaba.tesla.appmanager.domain.dto.DeployConfigDTO; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; +import java.util.List; + /** * Deploy Config DTO Converter * @@ -18,4 +25,27 @@ public class DeployConfigDtoConvert extends BaseDtoConvert list = SchemaUtil.toSchemaList(JSONObject.class, result.getConfig()); + result.setConfigJson(JSONArray.parseArray(JSONArray.toJSONString(list))); + } else { + result.setConfigJson(SchemaUtil.toSchema(JSONObject.class, result.getConfig())); + } + } + return result; + } } diff --git a/paas/appmanager/tesla-appmanager-deploy-config/src/main/java/com/alibaba/tesla/appmanager/deployconfig/provider/impl/DeployConfigProviderImpl.java b/paas/appmanager/tesla-appmanager-deploy-config/src/main/java/com/alibaba/tesla/appmanager/deployconfig/provider/impl/DeployConfigProviderImpl.java index 7bb01714..2f6d3da0 100644 --- a/paas/appmanager/tesla-appmanager-deploy-config/src/main/java/com/alibaba/tesla/appmanager/deployconfig/provider/impl/DeployConfigProviderImpl.java +++ b/paas/appmanager/tesla-appmanager-deploy-config/src/main/java/com/alibaba/tesla/appmanager/deployconfig/provider/impl/DeployConfigProviderImpl.java @@ -1,18 +1,21 @@ package com.alibaba.tesla.appmanager.deployconfig.provider.impl; +import com.alibaba.fastjson.JSONObject; import com.alibaba.tesla.appmanager.api.provider.DeployConfigProvider; +import com.alibaba.tesla.appmanager.common.pagination.Pagination; +import com.alibaba.tesla.appmanager.common.util.ClassUtil; import com.alibaba.tesla.appmanager.deployconfig.assembly.DeployConfigDtoConvert; +import com.alibaba.tesla.appmanager.deployconfig.repository.condition.DeployConfigQueryCondition; import com.alibaba.tesla.appmanager.deployconfig.repository.domain.DeployConfigDO; import com.alibaba.tesla.appmanager.deployconfig.service.DeployConfigService; import com.alibaba.tesla.appmanager.domain.dto.DeployConfigDTO; -import com.alibaba.tesla.appmanager.domain.req.deployconfig.DeployConfigApplyTemplateReq; -import com.alibaba.tesla.appmanager.domain.req.deployconfig.DeployConfigDeleteReq; -import com.alibaba.tesla.appmanager.domain.req.deployconfig.DeployConfigGenerateReq; +import com.alibaba.tesla.appmanager.domain.req.deployconfig.*; import com.alibaba.tesla.appmanager.domain.res.deployconfig.DeployConfigApplyTemplateRes; import com.alibaba.tesla.appmanager.domain.res.deployconfig.DeployConfigGenerateRes; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import java.util.List; import java.util.stream.Collectors; /** @@ -60,6 +63,33 @@ public class DeployConfigProviderImpl implements DeployConfigProvider { return deployConfigService.generate(req); } + /** + * 根据指定查询条件获取列表(不支持继承) + * + * @param req 查询请求 + * @return 部署配置列表 + */ + @Override + public Pagination list(DeployConfigListReq req) { + DeployConfigQueryCondition condition = new DeployConfigQueryCondition(); + ClassUtil.copy(req, condition); + List results = deployConfigService.list(condition); + log.info("list deploy config from database|condition={}|resultSize={}", + JSONObject.toJSONString(condition), results.size()); + return Pagination.valueOf(results, deployConfigDtoConvert::to); + } + + /** + * 更新指定 apiVersion + appId + typeId + envId 对应的 DeployConfig 记录 + * + * @param req 更新请求 + * @return 更新后的对象 + */ + @Override + public DeployConfigDTO upsert(DeployConfigUpsertReq req) { + return deployConfigDtoConvert.to(deployConfigService.update(req)); + } + /** * 删除指定 apiVersion + appId + typeId + envId 对应的 DeployConfig 记录 * diff --git a/paas/appmanager/tesla-appmanager-deploy-config/src/main/java/com/alibaba/tesla/appmanager/deployconfig/repository/condition/DeployConfigQueryCondition.java b/paas/appmanager/tesla-appmanager-deploy-config/src/main/java/com/alibaba/tesla/appmanager/deployconfig/repository/condition/DeployConfigQueryCondition.java index 010abc2c..f35c9731 100644 --- a/paas/appmanager/tesla-appmanager-deploy-config/src/main/java/com/alibaba/tesla/appmanager/deployconfig/repository/condition/DeployConfigQueryCondition.java +++ b/paas/appmanager/tesla-appmanager-deploy-config/src/main/java/com/alibaba/tesla/appmanager/deployconfig/repository/condition/DeployConfigQueryCondition.java @@ -27,6 +27,11 @@ public class DeployConfigQueryCondition extends BaseCondition { */ private String typeId; + /** + * 类型 ID 前缀 + */ + private String typeIdPrefix; + /** * 环境 ID */ diff --git a/paas/appmanager/tesla-appmanager-deploy-config/src/main/java/com/alibaba/tesla/appmanager/deployconfig/repository/impl/DeployConfigRepositoryImpl.java b/paas/appmanager/tesla-appmanager-deploy-config/src/main/java/com/alibaba/tesla/appmanager/deployconfig/repository/impl/DeployConfigRepositoryImpl.java index 2011e28c..05264deb 100644 --- a/paas/appmanager/tesla-appmanager-deploy-config/src/main/java/com/alibaba/tesla/appmanager/deployconfig/repository/impl/DeployConfigRepositoryImpl.java +++ b/paas/appmanager/tesla-appmanager-deploy-config/src/main/java/com/alibaba/tesla/appmanager/deployconfig/repository/impl/DeployConfigRepositoryImpl.java @@ -7,6 +7,7 @@ import com.alibaba.tesla.appmanager.deployconfig.repository.domain.DeployConfigD import com.alibaba.tesla.appmanager.deployconfig.repository.domain.DeployConfigDOExample; import com.alibaba.tesla.appmanager.deployconfig.repository.mapper.DeployConfigDOMapper; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; @@ -60,6 +61,8 @@ public class DeployConfigRepositoryImpl implements DeployConfigRepository { } if (StringUtils.isNotBlank(condition.getTypeId())) { criteria.andTypeIdEqualTo(condition.getTypeId()); + } else if (StringUtils.isNotEmpty(condition.getTypeIdPrefix())) { + criteria.andTypeIdLike(StringEscapeUtils.escapeSql(condition.getTypeIdPrefix()) + "%"); } if (condition.getEnvId() != null) { criteria.andEnvIdEqualTo(condition.getEnvId()); diff --git a/paas/appmanager/tesla-appmanager-deploy-config/src/main/java/com/alibaba/tesla/appmanager/deployconfig/service/DeployConfigService.java b/paas/appmanager/tesla-appmanager-deploy-config/src/main/java/com/alibaba/tesla/appmanager/deployconfig/service/DeployConfigService.java index 44db8f4d..bf0e498c 100644 --- a/paas/appmanager/tesla-appmanager-deploy-config/src/main/java/com/alibaba/tesla/appmanager/deployconfig/service/DeployConfigService.java +++ b/paas/appmanager/tesla-appmanager-deploy-config/src/main/java/com/alibaba/tesla/appmanager/deployconfig/service/DeployConfigService.java @@ -46,7 +46,7 @@ public interface DeployConfigService { * @param req 更新请求 * @return 更新后的对象 */ - DeployConfigDO update(DeployConfigUpdateReq req); + DeployConfigDO update(DeployConfigUpsertReq req); /** * 删除指定 apiVersion + appId + typeId + envId 对应的 DeployConfig 记录 diff --git a/paas/appmanager/tesla-appmanager-deploy-config/src/main/java/com/alibaba/tesla/appmanager/deployconfig/service/impl/DeployConfigServiceImpl.java b/paas/appmanager/tesla-appmanager-deploy-config/src/main/java/com/alibaba/tesla/appmanager/deployconfig/service/impl/DeployConfigServiceImpl.java index 73aec8eb..a5389c57 100644 --- a/paas/appmanager/tesla-appmanager-deploy-config/src/main/java/com/alibaba/tesla/appmanager/deployconfig/service/impl/DeployConfigServiceImpl.java +++ b/paas/appmanager/tesla-appmanager-deploy-config/src/main/java/com/alibaba/tesla/appmanager/deployconfig/service/impl/DeployConfigServiceImpl.java @@ -17,10 +17,7 @@ import com.alibaba.tesla.appmanager.deployconfig.service.DeployConfigService; import com.alibaba.tesla.appmanager.domain.container.DeployAppRevisionName; import com.alibaba.tesla.appmanager.domain.container.DeployConfigEnvId; import com.alibaba.tesla.appmanager.domain.container.DeployConfigTypeId; -import com.alibaba.tesla.appmanager.domain.req.deployconfig.DeployConfigApplyTemplateReq; -import com.alibaba.tesla.appmanager.domain.req.deployconfig.DeployConfigDeleteReq; -import com.alibaba.tesla.appmanager.domain.req.deployconfig.DeployConfigGenerateReq; -import com.alibaba.tesla.appmanager.domain.req.deployconfig.DeployConfigUpdateReq; +import com.alibaba.tesla.appmanager.domain.req.deployconfig.*; import com.alibaba.tesla.appmanager.domain.res.deployconfig.DeployConfigApplyTemplateRes; import com.alibaba.tesla.appmanager.domain.res.deployconfig.DeployConfigGenerateRes; import com.alibaba.tesla.appmanager.domain.schema.DeployAppSchema; @@ -165,7 +162,7 @@ public class DeployConfigServiceImpl implements DeployConfigService { * @return 更新后的对象 */ @Override - public DeployConfigDO update(DeployConfigUpdateReq req) { + public DeployConfigDO update(DeployConfigUpsertReq req) { String apiVersion = req.getApiVersion(); String appId = req.getAppId(); String isolateNamespaceId = req.getIsolateNamespaceId(); @@ -173,6 +170,14 @@ public class DeployConfigServiceImpl implements DeployConfigService { String envId = req.getEnvId(); String typeId = req.getTypeId(); String config = req.getConfig(); + JSONArray configJsonArray = req.getConfigJsonArray(); + if (configJsonArray != null) { + config = SchemaUtil.toYamlStr(configJsonArray, JSONArray.class); + } + JSONObject configJsonObject = req.getConfigJsonObject(); + if (configJsonObject != null) { + config = SchemaUtil.toYamlStr(configJsonObject, JSONObject.class); + } boolean inherit = req.isInherit(); String productId = req.getProductId(); String releaseId = req.getReleaseId(); @@ -233,6 +238,30 @@ public class DeployConfigServiceImpl implements DeployConfigService { .build(); } + /** + * 将指定应用加入到指定环境中 + * + * @param req 加入环境请求 + */ + public void bindEnvironment(DeployConfigBindEnvironmentReq req) { + String appId = req.getAppId(); + String isolateNamespaceId = req.getIsolateNamespaceId(); + String isolateStageId = req.getIsolateStageId(); + String envId = req.getEnvId(); + String productId = req.getProductId(); + String releaseId = req.getReleaseId(); + String baselineBranch = req.getBaselineBranch(); + + // 写入 Type:envBinding 的类型记录 + String apiVersion = DefaultConstant.API_VERSION_V1_ALPHA2; + DeployConfigTypeId typeId = new DeployConfigTypeId(DeployConfigTypeId.TYPE_ENV_BINDING); + applySingleConfig(apiVersion, appId, typeId.toString(), envId, "", true, false, + isolateNamespaceId, isolateStageId, productId, releaseId); + } + + public void getGlobalTemplate(String isolateNamespaceId, String isolateStageId) { + + } /** * 根据 deploy config 配置生成 application configuration @@ -290,52 +319,102 @@ public class DeployConfigServiceImpl implements DeployConfigService { List typeIds = CollectionUtils.isEmpty(req.getTypeIds()) ? distinctTypeIds(appRecords) : req.getTypeIds(); - for (String typeId : typeIds) { - List filterAppRecords = appRecords.stream() - .filter(item -> item.getTypeId().equals(typeId)) - .collect(Collectors.toList()); - List filterRootRecords = rootRecords.stream() - .filter(item -> item.getTypeId().equals(typeId)) - .collect(Collectors.toList()); - DeployConfigDO best = findBestConfigInRecordsBySpecifiedName( - filterAppRecords, filterRootRecords, unitId, clusterId, namespaceId, stageId); - if (best == null) { - throw new AppException(AppErrorCode.INVALID_USER_ARGS, - String.format("cannot find best config in database|appId=%s|typeId=%s|clusterId=%s|" + - "namespaceId=%s|stageId=%s", appId, typeId, - clusterId, namespaceId, stageId)); - } - String config = best.getConfig(); - if (StringUtils.isEmpty(config)) { - if (StringUtils.isNotEmpty(best.getProductId()) && StringUtils.isNotEmpty(best.getReleaseId())) { - config = fetchConfigInGit(best.getProductId(), best.getReleaseId(), appId, typeId); - log.info("fetch config in git succeed|productId={}|releaseId={}|appId={}|typeId={}|config={}", - best.getProductId(), best.getReleaseId(), appId, typeId, config); - } else { - throw new AppException(AppErrorCode.INVALID_USER_ARGS, - String.format("invalid inherit config, cannot get config by typeId %s|appRecords=%s|" + - "rootRecords=%s", typeId, JSONArray.toJSONString(filterAppRecords), - JSONArray.toJSONString(filterRootRecords))); + // step==0 非 traits 类型组装, step==1 traits 类型组装 (step==1 依赖 step==0 完成) + for (int step = 0; step < 2; step++) { + for (String typeId : typeIds) { + DeployConfigTypeId typeIdObj = DeployConfigTypeId.valueOf(typeId); + if (step == 0 && DeployConfigTypeId.TYPE_TRAITS.equals(typeIdObj.getType())) { + continue; + } else if (step == 1 && !DeployConfigTypeId.TYPE_TRAITS.equals(typeIdObj.getType())) { + continue; + } + + List filterAppRecords = appRecords.stream() + .filter(item -> item.getTypeId().equals(typeId)) + .collect(Collectors.toList()); + List filterRootRecords = rootRecords.stream() + .filter(item -> item.getTypeId().equals(typeId)) + .collect(Collectors.toList()); + DeployConfigDO best = findBestConfigInRecordsBySpecifiedName( + filterAppRecords, filterRootRecords, unitId, clusterId, namespaceId, stageId); + if (best == null) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("cannot find best config in database|appId=%s|typeId=%s|clusterId=%s|" + + "namespaceId=%s|stageId=%s", appId, typeId, + clusterId, namespaceId, stageId)); + } + String config = best.getConfig(); + if (StringUtils.isEmpty(config)) { + if (StringUtils.isNotEmpty(best.getProductId()) && StringUtils.isNotEmpty(best.getReleaseId())) { + config = fetchConfigInGit(best.getProductId(), best.getReleaseId(), appId, typeId); + log.info("fetch config in git succeed|productId={}|releaseId={}|appId={}|typeId={}|config={}", + best.getProductId(), best.getReleaseId(), appId, typeId, config); + } else { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("invalid inherit config, cannot get config by typeId %s|appRecords=%s|" + + "rootRecords=%s", typeId, JSONArray.toJSONString(filterAppRecords), + JSONArray.toJSONString(filterRootRecords))); + } + } + switch (typeIdObj.getType()) { + case DeployConfigTypeId.TYPE_PARAMETER_VALUES: + schema.getSpec().setParameterValues( + SchemaUtil.toSchemaList(DeployAppSchema.ParameterValue.class, config)); + break; + case DeployConfigTypeId.TYPE_COMPONENTS: + DeployAppSchema.SpecComponent component = enrichComponentScopes( + req, SchemaUtil.toSchema(DeployAppSchema.SpecComponent.class, config)); + schema.getSpec().getComponents().add(component); + break; + case DeployConfigTypeId.TYPE_TRAITS: + String componentType = typeIdObj.getAttr(DeployConfigTypeId.ATTR_COMPONENT_TYPE); + String componentName = typeIdObj.getAttr(DeployConfigTypeId.ATTR_COMPONENT_NAME); + String traitName = typeIdObj.getAttr(DeployConfigTypeId.ATTR_TRAIT); + if (StringUtils.isAnyEmpty(componentType, componentName, traitName)) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("invalid trait typeId found, ComponentType/ComponentName/Trait " + + "are required|typeId=%s", typeId)); + } + DeployAppSchema.SpecComponentTrait trait = SchemaUtil + .toSchema(DeployAppSchema.SpecComponentTrait.class, config); + trait.setName(traitName); + if (StringUtils.isEmpty(trait.getRuntime())) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + "the field 'runtime' is required in trait deploy config"); + } + boolean componentFound = false; + for (DeployAppSchema.SpecComponent specComponent : schema.getSpec().getComponents()) { + DeployAppRevisionName revisionName = DeployAppRevisionName + .valueOf(specComponent.getRevisionName()); + if (componentType.equalsIgnoreCase(revisionName.getComponentType()) + && componentName.equals(revisionName.getComponentName())) { + componentFound = true; + for (DeployAppSchema.SpecComponentTrait specComponentTrait + : specComponent.getTraits()) { + if (traitName.equals(specComponentTrait.getName())) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("conflict trait deploy config, which already " + + "exists at the component level|typeId=%s", typeId)); + } + } + specComponent.getTraits().add(trait); + } + } + if (!componentFound) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("cannot find related component when processing trait " + + "deploy config|typeId=%s", typeId)); + } + break; + case DeployConfigTypeId.TYPE_POLICIES: + schema.getSpec().setPolicies(SchemaUtil.toSchemaList(DeployAppSchema.Policy.class, config)); + break; + case DeployConfigTypeId.TYPE_WORKFLOW: + schema.getSpec().setWorkflow(SchemaUtil.toSchema(DeployAppSchema.Workflow.class, config)); + break; + default: + break; } - } - switch (DeployConfigTypeId.valueOf(typeId).getType()) { - case DeployConfigTypeId.TYPE_PARAMETER_VALUES: - schema.getSpec().setParameterValues( - SchemaUtil.toSchemaList(DeployAppSchema.ParameterValue.class, config)); - break; - case DeployConfigTypeId.TYPE_COMPONENTS: - DeployAppSchema.SpecComponent component = enrichComponentScopes( - req, SchemaUtil.toSchema(DeployAppSchema.SpecComponent.class, config)); - schema.getSpec().getComponents().add(component); - break; - case DeployConfigTypeId.TYPE_POLICIES: - schema.getSpec().setPolicies(SchemaUtil.toSchemaList(DeployAppSchema.Policy.class, config)); - break; - case DeployConfigTypeId.TYPE_WORKFLOW: - schema.getSpec().setWorkflow(SchemaUtil.toSchema(DeployAppSchema.Workflow.class, config)); - break; - default: - break; } } return schema; @@ -478,6 +557,9 @@ public class DeployConfigServiceImpl implements DeployConfigService { List appRecords, List rootRecords, String unitId, String clusterId, String namespaceId, String stageId) { List priorities = new ArrayList<>(); + if (StringUtils.isNotEmpty(unitId) && StringUtils.isNotEmpty(namespaceId) && StringUtils.isNotEmpty(stageId)) { + priorities.add(DeployConfigEnvId.unitNamespaceStageStr(unitId, namespaceId, stageId)); + } if (StringUtils.isNotEmpty(stageId)) { priorities.add(DeployConfigEnvId.stageStr(stageId)); } diff --git a/paas/appmanager/tesla-appmanager-deploy-config/src/main/java/com/alibaba/tesla/appmanager/deployconfig/util/DeployConfigGenerator.java b/paas/appmanager/tesla-appmanager-deploy-config/src/main/java/com/alibaba/tesla/appmanager/deployconfig/util/DeployConfigGenerator.java new file mode 100644 index 00000000..612af095 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-deploy-config/src/main/java/com/alibaba/tesla/appmanager/deployconfig/util/DeployConfigGenerator.java @@ -0,0 +1,58 @@ +package com.alibaba.tesla.appmanager.deployconfig.util; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.tesla.appmanager.common.util.SchemaUtil; + +/** + * 部署配置生成器 + * + * @author yaoxing.gyx@alibaba-inc.com + */ +public class DeployConfigGenerator { + + private final JSONObject config; + + public DeployConfigGenerator() { + this.config = new JSONObject(); + } + + public DeployConfigGenerator addRevisionName(String componentType, String componentName) { + config.put("revisionName", String.format("%s|%s|_", componentType, componentName)); + return this; + } + + public DeployConfigGenerator addScope(String kind, String name) { + config.putIfAbsent("scopes", new JSONArray()); + config.getJSONArray("scopes").add(new JSONObject()); + int scopeLength = config.getJSONArray("scopes").size(); + config.getJSONArray("scopes").getJSONObject(scopeLength - 1).put("scopeRef", new JSONObject()); + config.getJSONArray("scopes").getJSONObject(scopeLength - 1) + .getJSONObject("scopeRef").put("apiVersion", "core.oam.dev/v1alpha2"); + config.getJSONArray("scopes").getJSONObject(scopeLength - 1) + .getJSONObject("scopeRef").put("kind", kind); + config.getJSONArray("scopes").getJSONObject(scopeLength - 1) + .getJSONObject("scopeRef").put("name", name); + return this; + } + + public DeployConfigGenerator addDataInputs(JSONArray dataInputs) { + if (dataInputs == null) { + return this; + } + config.put("dataInputs", dataInputs); + return this; + } + + public DeployConfigGenerator addDataOutputs(JSONArray dataOutputs) { + if (dataOutputs == null) { + return this; + } + config.put("dataOutputs", dataOutputs); + return this; + } + + public String toString() { + return SchemaUtil.createYaml(JSONObject.class).dumpAsMap(config); + } +} diff --git a/paas/appmanager/tesla-appmanager-deploy-config/src/test/java/com/alibaba/tesla/appmanager/deployconfig/service/TestDeployConfigDtoConverter.java b/paas/appmanager/tesla-appmanager-deploy-config/src/test/java/com/alibaba/tesla/appmanager/deployconfig/service/TestDeployConfigDtoConverter.java new file mode 100644 index 00000000..f3c32d17 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-deploy-config/src/test/java/com/alibaba/tesla/appmanager/deployconfig/service/TestDeployConfigDtoConverter.java @@ -0,0 +1,52 @@ +package com.alibaba.tesla.appmanager.deployconfig.service; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.tesla.appmanager.deployconfig.assembly.DeployConfigDtoConvert; +import com.alibaba.tesla.appmanager.deployconfig.repository.domain.DeployConfigDO; +import com.alibaba.tesla.appmanager.domain.dto.DeployConfigDTO; +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringRunner.class) +@Slf4j +public class TestDeployConfigDtoConverter { + + @Test + public void testTo1() { + String yaml = "!!map\n" + + "- name: a\n" + + " value: b\n" + + "- name: c\n" + + " value: d"; + DeployConfigDO record = new DeployConfigDO(); + record.setConfig(yaml); + DeployConfigDTO dto = (new DeployConfigDtoConvert()).to(record); + assertThat(((JSONArray) dto.getConfigJson()).size()).isEqualTo(2); + } + + @Test + public void testTo2() { + String yaml = "- name: c\n" + + " value: d"; + DeployConfigDO record = new DeployConfigDO(); + record.setConfig(yaml); + DeployConfigDTO dto = (new DeployConfigDtoConvert()).to(record); + assertThat(((JSONArray) dto.getConfigJson()).size()).isEqualTo(1); + } + + @Test + public void testTo3() { + String yaml = "name: c\n" + + "value: d"; + DeployConfigDO record = new DeployConfigDO(); + record.setConfig(yaml); + DeployConfigDTO dto = (new DeployConfigDtoConvert()).to(record); + assertThat(((JSONObject) dto.getConfigJson()).get("name")).isEqualTo("c"); + assertThat(((JSONObject) dto.getConfigJson()).get("value")).isEqualTo("d"); + } +} diff --git a/paas/appmanager/tesla-appmanager-deploy-config/src/test/java/com/alibaba/tesla/appmanager/deployconfig/service/TestServiceDeployConfigApplyTemplate.java b/paas/appmanager/tesla-appmanager-deploy-config/src/test/java/com/alibaba/tesla/appmanager/deployconfig/service/TestServiceDeployConfigApplyTemplate.java index 1227345f..5421e13f 100644 --- a/paas/appmanager/tesla-appmanager-deploy-config/src/test/java/com/alibaba/tesla/appmanager/deployconfig/service/TestServiceDeployConfigApplyTemplate.java +++ b/paas/appmanager/tesla-appmanager-deploy-config/src/test/java/com/alibaba/tesla/appmanager/deployconfig/service/TestServiceDeployConfigApplyTemplate.java @@ -59,7 +59,7 @@ public class TestServiceDeployConfigApplyTemplate { @Test public void testWithExistsRecords() throws Exception { String parameterValueTypeId = new DeployConfigTypeId(DeployConfigTypeId.TYPE_PARAMETER_VALUES).toString(); - String componentTypeId = new DeployConfigTypeId(ComponentTypeEnum.K8S_MICROSERVICE, "aiops-server").toString(); + String componentTypeId = new DeployConfigTypeId(ComponentTypeEnum.K8S_MICROSERVICE.toString(), "aiops-server").toString(); Mockito.doReturn(Collections.singletonList(DeployConfigHistoryDO.builder().revision(10).build())) .when(deployConfigHistoryRepository) .selectByExample(DeployConfigHistoryQueryCondition.builder() @@ -174,7 +174,7 @@ public class TestServiceDeployConfigApplyTemplate { @Test public void testWithNoRecords() throws Exception { String parameterValueTypeId = new DeployConfigTypeId(DeployConfigTypeId.TYPE_PARAMETER_VALUES).toString(); - String componentTypeId = new DeployConfigTypeId(ComponentTypeEnum.K8S_MICROSERVICE, "aiops-server").toString(); + String componentTypeId = new DeployConfigTypeId(ComponentTypeEnum.K8S_MICROSERVICE.toString(), "aiops-server").toString(); String config = getConfig(); DeployConfigApplyTemplateRes res = deployConfigService.applyTemplate( DeployConfigApplyTemplateReq.builder() diff --git a/paas/appmanager/tesla-appmanager-deploy-config/src/test/java/com/alibaba/tesla/appmanager/deployconfig/service/TestServiceDeployConfigGenerateByAddonInherit.java b/paas/appmanager/tesla-appmanager-deploy-config/src/test/java/com/alibaba/tesla/appmanager/deployconfig/service/TestServiceDeployConfigGenerateByAddonInherit.java index e3084ad1..89118b18 100644 --- a/paas/appmanager/tesla-appmanager-deploy-config/src/test/java/com/alibaba/tesla/appmanager/deployconfig/service/TestServiceDeployConfigGenerateByAddonInherit.java +++ b/paas/appmanager/tesla-appmanager-deploy-config/src/test/java/com/alibaba/tesla/appmanager/deployconfig/service/TestServiceDeployConfigGenerateByAddonInherit.java @@ -69,7 +69,7 @@ public class TestServiceDeployConfigGenerateByAddonInherit { public void testGenerateInternalAddonWithInherit() throws Exception { // 准备数据 String typeId = new DeployConfigTypeId( - ComponentTypeEnum.INTERNAL_ADDON, "productopsv2@productopsv2").toString(); + ComponentTypeEnum.INTERNAL_ADDON.toString(), "productopsv2@productopsv2").toString(); Mockito.doReturn( Collections.singletonList(DeployConfigDO.builder() .appId(APP_ID) diff --git a/paas/appmanager/tesla-appmanager-deploy-config/src/test/java/com/alibaba/tesla/appmanager/deployconfig/service/TestServiceDeployConfigGenerateByConfiguration.java b/paas/appmanager/tesla-appmanager-deploy-config/src/test/java/com/alibaba/tesla/appmanager/deployconfig/service/TestServiceDeployConfigGenerateByConfiguration.java index 5cb4e3a2..4d1316b8 100644 --- a/paas/appmanager/tesla-appmanager-deploy-config/src/test/java/com/alibaba/tesla/appmanager/deployconfig/service/TestServiceDeployConfigGenerateByConfiguration.java +++ b/paas/appmanager/tesla-appmanager-deploy-config/src/test/java/com/alibaba/tesla/appmanager/deployconfig/service/TestServiceDeployConfigGenerateByConfiguration.java @@ -60,6 +60,62 @@ public class TestServiceDeployConfigGenerateByConfiguration { )); } + /** + * 测试生成 Trait 的 ApplicationConfiguration + */ + @Test + public void testGenerateTraitNoInherit() throws Exception { + // 准备数据 + String traitTypeId = "Type:traits::ComponentType:K8S_MICROSERVICE::ComponentName:aiops-server::Trait:test.abm.io"; + String componentTypeId = new DeployConfigTypeId(ComponentTypeEnum.K8S_MICROSERVICE.toString(), "aiops-server").toString(); + String config = getConfig(); + DeployAppSchema schema = SchemaUtil.toSchema(DeployAppSchema.class, config); + List mockResults = new ArrayList<>(); + mockResults.add(DeployConfigDO.builder() + .appId(APP_ID) + .typeId(traitTypeId) + .envId("") + .apiVersion(API_VERSION) + .currentRevision(0) + .config(SchemaUtil.toYamlStr(schema.getSpec().getComponents().get(0).getTraits().get(0), DeployAppSchema.SpecComponentTrait.class)) + .enabled(true) + .inherit(false) + .build()); + // 删除 example 中的 traits + schema.getSpec().getComponents().get(0).setTraits(new ArrayList<>()); + mockResults.add(DeployConfigDO.builder() + .appId(APP_ID) + .typeId(componentTypeId) + .envId("") + .apiVersion(API_VERSION) + .currentRevision(0) + .config(SchemaUtil.toYamlMapStr(schema.getSpec().getComponents().get(0))) + .enabled(true) + .inherit(false) + .build()); + Mockito.doReturn(mockResults) + .when(deployConfigRepository) + .selectByCondition(DeployConfigQueryCondition.builder() + .apiVersion(API_VERSION) + .appId(APP_ID) + .enabled(true) + .build()); + + // 测试调用 + DeployConfigGenerateReq req = DeployConfigGenerateReq.builder() + .apiVersion(API_VERSION) + .appId(APP_ID) + .appPackageId(APP_PACKAGE_ID) + .clusterId(CLUSTER_ID) + .namespaceId(NAMESPACE_ID) + .stageId(STAGE_ID) + .appInstanceName(APP_INSTANCE_NAME) + .build(); + DeployConfigGenerateRes res = deployConfigService.generate(req); + log.info("generateRes: {}", JSONObject.toJSONString(res.getSchema())); +// DeployAppSchema generatedSchema = res.getSchema(); + } + /** * 测试生成 K8S Microservice 的 ApplicationConfiguration */ @@ -67,7 +123,7 @@ public class TestServiceDeployConfigGenerateByConfiguration { public void testGenerateK8SMicroserviceNoInherit() throws Exception { // 准备数据 String parameterValueTypeId = new DeployConfigTypeId(DeployConfigTypeId.TYPE_PARAMETER_VALUES).toString(); - String componentTypeId = new DeployConfigTypeId(ComponentTypeEnum.K8S_MICROSERVICE, "aiops-server").toString(); + String componentTypeId = new DeployConfigTypeId(ComponentTypeEnum.K8S_MICROSERVICE.toString(), "aiops-server").toString(); String config = getConfig(); DeployAppSchema schema = SchemaUtil.toSchema(DeployAppSchema.class, config); List mockResults = new ArrayList<>(); @@ -136,7 +192,7 @@ public class TestServiceDeployConfigGenerateByConfiguration { public void testGenerateK8SMicroserviceWithInherit() throws Exception { // 准备数据 String parameterValueTypeId = new DeployConfigTypeId(DeployConfigTypeId.TYPE_PARAMETER_VALUES).toString(); - String componentTypeId = new DeployConfigTypeId(ComponentTypeEnum.K8S_MICROSERVICE, "aiops-server").toString(); + String componentTypeId = new DeployConfigTypeId(ComponentTypeEnum.K8S_MICROSERVICE.toString(), "aiops-server").toString(); String config = getConfig(); DeployAppSchema schema = SchemaUtil.toSchema(DeployAppSchema.class, config); Mockito.doReturn( diff --git a/paas/appmanager/tesla-appmanager-deploy-config/src/test/java/com/alibaba/tesla/appmanager/deployconfig/service/TestUtilDeployConfigGenerator.java b/paas/appmanager/tesla-appmanager-deploy-config/src/test/java/com/alibaba/tesla/appmanager/deployconfig/service/TestUtilDeployConfigGenerator.java new file mode 100644 index 00000000..0b9ee66c --- /dev/null +++ b/paas/appmanager/tesla-appmanager-deploy-config/src/test/java/com/alibaba/tesla/appmanager/deployconfig/service/TestUtilDeployConfigGenerator.java @@ -0,0 +1,50 @@ +package com.alibaba.tesla.appmanager.deployconfig.service; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.tesla.appmanager.common.util.SchemaUtil; +import com.alibaba.tesla.appmanager.deployconfig.util.DeployConfigGenerator; +import com.alibaba.tesla.appmanager.domain.schema.DeployAppSchema; +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.Collections; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringRunner.class) +@Slf4j +public class TestUtilDeployConfigGenerator { + + /** + * 测试生成一个普通的 SpecComponent 配置 + */ + @Test + public void testGenerate() { + DeployConfigGenerator config = new DeployConfigGenerator(); + config.addRevisionName("HELM", "test"); + config.addScope("Namespace", "testNamespace"); + config.addScope("Stage", "testStage"); + config.addDataInputs(JSONArray.parseArray(JSONArray.toJSONString( + Collections.singletonList(DeployAppSchema.DataInput.builder() + .valueFrom(DeployAppSchema.DataInputValueFrom.builder() + .dataOutputName("test") + .build()) + .toFieldPaths(List.of("to1")) + .build())))); + config.addDataOutputs(JSONArray.parseArray(JSONArray.toJSONString( + Collections.singletonList(DeployAppSchema.DataOutput.builder() + .name("testname") + .fieldPath("testfieldpath") + .build())))); + DeployAppSchema.SpecComponent specComponent = SchemaUtil + .toSchema(DeployAppSchema.SpecComponent.class, config.toString()); + assertThat(specComponent.getNamespaceId()).isEqualTo("testNamespace"); + assertThat(specComponent.getStageId()).isEqualTo("testStage"); + assertThat(specComponent.getRevisionName()).isEqualTo("HELM|test|_"); + assertThat(specComponent.getDataInputs().get(0).getValueFrom().getDataOutputName()).isEqualTo("test"); + assertThat(specComponent.getDataOutputs().get(0).getFieldPath()).isEqualTo("testfieldpath"); + } +} diff --git a/paas/appmanager/tesla-appmanager-domain/pom.xml b/paas/appmanager/tesla-appmanager-domain/pom.xml index fe973d0b..b4489156 100644 --- a/paas/appmanager/tesla-appmanager-domain/pom.xml +++ b/paas/appmanager/tesla-appmanager-domain/pom.xml @@ -7,7 +7,7 @@ com.alibaba.tesla tesla-appmanager - 1.0.4-SNAPSHOT + 1.0.5-SNAPSHOT ../pom.xml diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/builder/AppConfigComponentFluent.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/builder/AppConfigComponentFluent.java index d2db5938..4ccb1451 100644 --- a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/builder/AppConfigComponentFluent.java +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/builder/AppConfigComponentFluent.java @@ -8,7 +8,7 @@ public interface AppConfigComponentFluent> String getRevisionName(); - ComponentTypeEnum getComponentType(); + String getComponentType(); String getComponentName(); @@ -16,7 +16,7 @@ public interface AppConfigComponentFluent> A withRevisionName(String revisionName); - A withRevisionName(ComponentTypeEnum componentType, String componentName, String packageVersion); + A withRevisionName(String componentType, String componentName, String packageVersion); List getParameterValues(); diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/builder/AppConfigComponentFluentImpl.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/builder/AppConfigComponentFluentImpl.java index fc997de0..5753abc7 100644 --- a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/builder/AppConfigComponentFluentImpl.java +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/builder/AppConfigComponentFluentImpl.java @@ -20,7 +20,7 @@ public class AppConfigComponentFluentImpl> } @Override - public ComponentTypeEnum getComponentType() { + public String getComponentType() { return DeployAppRevisionName.valueOf(this.revisionName).getComponentType(); } @@ -41,8 +41,8 @@ public class AppConfigComponentFluentImpl> } @Override - public A withRevisionName(ComponentTypeEnum componentType, String componentName, String packageVersion) { - this.revisionName = String.format("%s|%s|%s", componentType.toString(), componentName, packageVersion); + public A withRevisionName(String componentType, String componentName, String packageVersion) { + this.revisionName = String.format("%s|%s|%s", componentType, componentName, packageVersion); return (A) this; } diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/container/ComponentPackageTaskMessage.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/container/ComponentPackageTaskMessage.java index cd985097..57a660d6 100644 --- a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/container/ComponentPackageTaskMessage.java +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/container/ComponentPackageTaskMessage.java @@ -28,6 +28,8 @@ public class ComponentPackageTaskMessage { private String stageId; + private String category; + private String operator; private ComponentBinder component; diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/container/DeployAppRevisionName.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/container/DeployAppRevisionName.java index 5ebcb045..eeb11a1a 100644 --- a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/container/DeployAppRevisionName.java +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/container/DeployAppRevisionName.java @@ -10,6 +10,7 @@ import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import java.util.Arrays; @@ -37,7 +38,7 @@ public class DeployAppRevisionName { /** * 组件类型 */ - private ComponentTypeEnum componentType; + private String componentType; /** * 组件名称 @@ -60,8 +61,8 @@ public class DeployAppRevisionName { private DeployAppRevisionName(String revisionName, boolean mirrorFlag) { String[] splitNames = revisionName.split(SPLITTER, SPLIT_LIMIT); assert splitNames.length == SPLIT_LIMIT; - this.componentType = Enums.getIfPresent(ComponentTypeEnum.class, splitNames[0]).orNull(); - if (this.componentType == null) { + this.componentType = splitNames[0]; + if (StringUtils.isEmpty(this.componentType)) { throw new AppException(AppErrorCode.INVALID_USER_ARGS, String.format("cannot parse revisionName %s", revisionName)); } @@ -109,9 +110,9 @@ public class DeployAppRevisionName { * @return addonId */ public String addonId() { - assert componentType.equals(ComponentTypeEnum.RESOURCE_ADDON) - || componentType.equals(ComponentTypeEnum.TRAIT_ADDON) - || componentType.equals(ComponentTypeEnum.CUSTOM_ADDON); + assert componentType.equals(ComponentTypeEnum.RESOURCE_ADDON.toString()) + || componentType.equals(ComponentTypeEnum.TRAIT_ADDON.toString()) + || componentType.equals(ComponentTypeEnum.CUSTOM_ADDON.toString()); String[] array = componentName.split("@", 2); assert array.length == 2; return array[0]; @@ -123,9 +124,9 @@ public class DeployAppRevisionName { * @return addonName */ public String addonName() { - assert componentType.equals(ComponentTypeEnum.RESOURCE_ADDON) - || componentType.equals(ComponentTypeEnum.TRAIT_ADDON) - || componentType.equals(ComponentTypeEnum.CUSTOM_ADDON); + assert componentType.equals(ComponentTypeEnum.RESOURCE_ADDON.toString()) + || componentType.equals(ComponentTypeEnum.TRAIT_ADDON.toString()) + || componentType.equals(ComponentTypeEnum.CUSTOM_ADDON.toString()); String[] array = componentName.split("@", 2); assert array.length == 2; return array[1]; diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/container/DeployConfigEnvId.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/container/DeployConfigEnvId.java index 9c655595..d60adda6 100644 --- a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/container/DeployConfigEnvId.java +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/container/DeployConfigEnvId.java @@ -55,6 +55,18 @@ public class DeployConfigEnvId { return "Unit"; } + /** + * 返回 Unit + Namespace + Stage 字符串标识 + * + * @param unitId Unit ID + * @param namespaceId Namespace ID + * @param stageId Stage ID + * @return 字符串标识 + */ + public static String unitNamespaceStageStr(String unitId, String namespaceId, String stageId) { + return String.format("Unit:%s::Namespace:%s::Stage:%s", unitId, namespaceId, stageId); + } + /** * 返回 Stage 字符串标识 * diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/container/DeployConfigTypeId.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/container/DeployConfigTypeId.java index 6e1ede76..d2511bf8 100644 --- a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/container/DeployConfigTypeId.java +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/container/DeployConfigTypeId.java @@ -4,6 +4,7 @@ import com.alibaba.tesla.appmanager.common.enums.ComponentTypeEnum; import com.alibaba.tesla.appmanager.common.exception.AppErrorCode; import com.alibaba.tesla.appmanager.common.exception.AppException; import lombok.Getter; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import java.util.ArrayList; @@ -16,13 +17,17 @@ import java.util.List; */ public class DeployConfigTypeId { + public static final String TYPE_ENV_BINDING = "envBinding"; public static final String TYPE_PARAMETER_VALUES = "parameterValues"; public static final String TYPE_COMPONENTS = "components"; public static final String TYPE_POLICIES = "policies"; public static final String TYPE_WORKFLOW = "workflow"; + // 注意,TYPE_COMPONENT_TRAITS 仅附属于 components,无法独立存在 + public static final String TYPE_TRAITS = "traits"; public static final String ATTR_COMPONENT_TYPE = "ComponentType"; public static final String ATTR_COMPONENT_NAME = "ComponentName"; + public static final String ATTR_TRAIT = "Trait"; @Getter private final String type; @@ -34,17 +39,13 @@ public class DeployConfigTypeId { this.attrs = new ArrayList<>(); } - public DeployConfigTypeId(ComponentTypeEnum componentType) { + public DeployConfigTypeId(String componentType, String componentName) { this.type = TYPE_COMPONENTS; this.attrs = new ArrayList<>(); - this.attrs.add(Pair.of(ATTR_COMPONENT_TYPE, componentType.toString())); - } - - public DeployConfigTypeId(ComponentTypeEnum componentType, String componentName) { - this.type = TYPE_COMPONENTS; - this.attrs = new ArrayList<>(); - this.attrs.add(Pair.of(ATTR_COMPONENT_TYPE, componentType.toString())); - this.attrs.add(Pair.of(ATTR_COMPONENT_NAME, componentName)); + this.attrs.add(Pair.of(ATTR_COMPONENT_TYPE, componentType)); + if (StringUtils.isNotEmpty(componentName)) { + this.attrs.add(Pair.of(ATTR_COMPONENT_NAME, componentName)); + } } /** @@ -63,6 +64,9 @@ public class DeployConfigTypeId { } public static DeployConfigTypeId valueOf(String typeId) { + if (StringUtils.isEmpty(typeId)) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "empty typeId parameter"); + } String[] arr = typeId.split("::"); if (arr.length == 0) { throw new AppException(AppErrorCode.INVALID_USER_ARGS, "typeId must have :: spliter"); diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/core/ScriptIdentifier.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/core/ScriptIdentifier.java new file mode 100644 index 00000000..73f8e129 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/core/ScriptIdentifier.java @@ -0,0 +1,33 @@ +package com.alibaba.tesla.appmanager.domain.core; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * Groovy 脚本标识 + * + * @author yaoxing.gyx@alibaba-inc.com + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ScriptIdentifier { + + /** + * 类型 + */ + private String kind; + + /** + * 名称 + */ + private String name; + + /** + * 版本 + */ + private Integer revision; +} diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/AppAddonDTO.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/AppAddonDTO.java index cefbb4b5..f962ec01 100644 --- a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/AppAddonDTO.java +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/AppAddonDTO.java @@ -52,7 +52,7 @@ public class AppAddonDTO { /** * Addon 类型 */ - private ComponentTypeEnum addonType; + private String addonType; /** * Addon 唯一标识 diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/AppComponentDTO.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/AppComponentDTO.java index 2f91492c..4a81c3ee 100644 --- a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/AppComponentDTO.java +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/AppComponentDTO.java @@ -1,29 +1,38 @@ package com.alibaba.tesla.appmanager.domain.dto; -import com.alibaba.tesla.appmanager.common.enums.ComponentTypeEnum; - +import com.alibaba.fastjson.JSONObject; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -/** - * 应用关联组件 DTO - * - * @author qianmo.zm@alibaba-inc.com - */ +import java.util.Date; + @Data @Builder @NoArgsConstructor @AllArgsConstructor public class AppComponentDTO { + /** + * ID + */ private Long id; /** - * 应用 ID + * 是否为兼容记录 (true: 历史上的兼容记录, false: 通用记录) */ - private String appId; + private boolean compatible; + + /** + * 创建时间 + */ + private Date gmtCreate; + + /** + * 最后修改时间 + */ + private Date gmtModified; /** * Namespace ID @@ -36,22 +45,37 @@ public class AppComponentDTO { private String stageId; /** - * 组件描述 + * 应用 ID */ - private String componentLabel; + private String appId; + + /** + * 分类 + */ + private String category; /** * 组件类型 */ - private ComponentTypeEnum componentType; + private String componentType; /** - * 组件唯一标示 + * 组件名称 */ private String componentName; /** - * 组件版本 + * 组件对应的当前应用插件版本 */ - private String componentVersion; + private String pluginVersion; + + /** + * 配置内容 + */ + private JSONObject config; + + /** + * 自动生成: 当前组件对应的类型 ID + */ + private String typeId; } diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/DefinitionSchemaDTO.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/DefinitionSchemaDTO.java index 2d0cdf2e..a74fc7a8 100644 --- a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/DefinitionSchemaDTO.java +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/DefinitionSchemaDTO.java @@ -1,6 +1,9 @@ package com.alibaba.tesla.appmanager.domain.dto; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; +import lombok.NoArgsConstructor; /** * Definition Schema DTO @@ -8,6 +11,9 @@ import lombok.Data; * @author yaoxing.gyx@alibaba-inc.com */ @Data +@Builder +@NoArgsConstructor +@AllArgsConstructor public class DefinitionSchemaDTO { /** diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/DeployConfigDTO.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/DeployConfigDTO.java index d71b0ac4..b580b7c8 100644 --- a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/DeployConfigDTO.java +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/DeployConfigDTO.java @@ -1,5 +1,7 @@ package com.alibaba.tesla.appmanager.domain.dto; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -89,4 +91,9 @@ public class DeployConfigDTO { * 发布版本 ID */ private String releaseId; + + /** + * 自动生成: 配置内容的 JSON 形式 + */ + private JSON configJson; } \ No newline at end of file diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/HelmMetaDTO.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/HelmMetaDTO.java index 0a344360..c29c3972 100644 --- a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/HelmMetaDTO.java +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/HelmMetaDTO.java @@ -53,7 +53,7 @@ public class HelmMetaDTO { /** * 组件类型 */ - private ComponentTypeEnum componentType; + private String componentType; /** * 包类型 diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/InitContainerDTO.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/InitContainerDTO.java index 23b0caf6..2e47f433 100644 --- a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/InitContainerDTO.java +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/InitContainerDTO.java @@ -30,6 +30,11 @@ public class InitContainerDTO { */ private String dockerfilePath; + /** + * 仓库地址,不填则默认继承container的repoPath + */ + private String repoPath; + public String createDockerFileTemplate() { return "Dockerfile-" + createContainerName() + ".tpl"; } diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/K8sMicroServiceMetaDTO.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/K8sMicroServiceMetaDTO.java index 91ce7257..00a88f6f 100644 --- a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/K8sMicroServiceMetaDTO.java +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/K8sMicroServiceMetaDTO.java @@ -66,7 +66,7 @@ public class K8sMicroServiceMetaDTO { /** * 组件类型 */ - private ComponentTypeEnum componentType; + private String componentType; /** * 架构 diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/ParamBinderDTO.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/ParamBinderDTO.java index 54378fd3..dbcd1fbe 100644 --- a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/ParamBinderDTO.java +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/ParamBinderDTO.java @@ -21,7 +21,10 @@ public class ParamBinderDTO { */ private String componentName; - private ComponentTypeEnum componentType; + /** + * 组件类型 + */ + private String componentType; /** * 插件输出参数名 diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/PluginFrontendDTO.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/PluginFrontendDTO.java new file mode 100644 index 00000000..058f26f8 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/PluginFrontendDTO.java @@ -0,0 +1,56 @@ +package com.alibaba.tesla.appmanager.domain.dto; + +import com.alibaba.fastjson.JSONObject; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Date; + +/** + * Plugin Frontend 资源 DTO + * + * @author yaoxing.gyx@alibaba-inc.com + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PluginFrontendDTO { + + /** + * ID + */ + private Long id; + + /** + * 创建时间 + */ + private Date gmtCreate; + + /** + * 修改时间 + */ + private Date gmtModified; + + /** + * Plugin 唯一标识 + */ + private String pluginName; + + /** + * Plugin 版本 (SemVer) + */ + private String pluginVersion; + + /** + * 名称 + */ + private String name; + + /** + * 页面配置 + */ + private JSONObject config; +} diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/WorkflowInstanceDTO.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/WorkflowInstanceDTO.java index 91137b25..61a0fe4a 100644 --- a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/WorkflowInstanceDTO.java +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/dto/WorkflowInstanceDTO.java @@ -38,6 +38,11 @@ public class WorkflowInstanceDTO { */ private String appId; + /** + * 分类 + */ + private String category; + /** * 开始时间 */ @@ -78,6 +83,11 @@ public class WorkflowInstanceDTO { */ private String workflowCreator; + /** + * Workflow Context + */ + private JSONObject workflowContext; + /** * 乐观锁版本 */ diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/option/WorkflowInstanceOption.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/option/WorkflowInstanceOption.java index 75da2e4c..b497e8a6 100644 --- a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/option/WorkflowInstanceOption.java +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/option/WorkflowInstanceOption.java @@ -1,5 +1,6 @@ package com.alibaba.tesla.appmanager.domain.option; +import com.alibaba.fastjson.JSONObject; import com.alibaba.tesla.appmanager.common.exception.AppErrorCode; import com.alibaba.tesla.appmanager.common.exception.AppException; import com.alibaba.tesla.appmanager.domain.schema.DeployAppSchema; @@ -17,6 +18,11 @@ import java.util.List; @AllArgsConstructor public class WorkflowInstanceOption { + /** + * Workflow 分类 + */ + private String category; + /** * Workflow Task 执行顺序 (不提供该参数则默认全量按需执行) *

@@ -31,6 +37,11 @@ public class WorkflowInstanceOption { */ private String creator; + /** + * 初始化上下文 + */ + private JSONObject initContext; + /** * 计算并获取当前实际的 workflow instance 中的 workflow tasks 的执行顺序 * diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/AddonInstanceQueryReq.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/AddonInstanceQueryReq.java deleted file mode 100644 index 151d08ef..00000000 --- a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/AddonInstanceQueryReq.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.alibaba.tesla.appmanager.domain.req; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.io.Serializable; - -/** - * @author qiuqiang.qq@alibaba-inc.com - */ -@Data -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class AddonInstanceQueryReq implements Serializable { - private static final long serialVersionUID = 2701332248815871881L; - - private String namespaceId; - - private String addonId; - - private String addonVersion; - - private String addonInstanceId; -} diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/AppAddonQueryReq.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/AppAddonQueryReq.java index 3de2f449..1c3aaef4 100644 --- a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/AppAddonQueryReq.java +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/AppAddonQueryReq.java @@ -37,5 +37,5 @@ public class AppAddonQueryReq extends BaseRequest { /** * 类型 */ - private List addonTypeList; + private List addonTypeList; } diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/K8sMicroServiceMetaCreateReq.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/K8sMicroServiceMetaCreateReq.java index a2d7c2c6..b38a5443 100644 --- a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/K8sMicroServiceMetaCreateReq.java +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/K8sMicroServiceMetaCreateReq.java @@ -49,7 +49,7 @@ public class K8sMicroServiceMetaCreateReq { /** * 组件类型 */ - private ComponentTypeEnum componentType; + private String componentType; private JSONObject service; } diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/K8sMicroServiceMetaQuickUpdateReq.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/K8sMicroServiceMetaQuickUpdateReq.java index 0ed3b099..0e08f74b 100644 --- a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/K8sMicroServiceMetaQuickUpdateReq.java +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/K8sMicroServiceMetaQuickUpdateReq.java @@ -54,7 +54,7 @@ public class K8sMicroServiceMetaQuickUpdateReq { /** * 组件类型 */ - private ComponentTypeEnum componentType; + private String componentType; /** * 架构 diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/K8sMicroServiceMetaUpdateReq.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/K8sMicroServiceMetaUpdateReq.java index 16c24b9f..ed991118 100644 --- a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/K8sMicroServiceMetaUpdateReq.java +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/K8sMicroServiceMetaUpdateReq.java @@ -54,7 +54,7 @@ public class K8sMicroServiceMetaUpdateReq { /** * 组件类型 */ - private ComponentTypeEnum componentType; + private String componentType; /** * 架构 diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/PluginQueryReq.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/PluginQueryReq.java index 8e4b74b5..3b75bf9e 100644 --- a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/PluginQueryReq.java +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/PluginQueryReq.java @@ -6,13 +6,26 @@ import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; - @Data @SuperBuilder @NoArgsConstructor @AllArgsConstructor public class PluginQueryReq extends BaseRequest { + /** + * 插件类型 + */ + private String pluginKind; + + /** + * 插件名称 + */ + private String pluginName; + + /** + * 插件版本 + */ + private String pluginVersion; /** * Tag key @@ -23,4 +36,9 @@ public class PluginQueryReq extends BaseRequest { * Tag Value */ private String tagValue; + + /** + * Plugin is registered + */ + private Boolean pluginRegistered; } diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/appcomponent/AppComponentCreateReq.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/appcomponent/AppComponentCreateReq.java new file mode 100644 index 00000000..db17a38d --- /dev/null +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/appcomponent/AppComponentCreateReq.java @@ -0,0 +1,54 @@ +package com.alibaba.tesla.appmanager.domain.req.appcomponent; + +import com.alibaba.fastjson.JSONObject; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 应用关联组件创建请求 + * + * @author yaoxing.gyx@alibaba-inc.com + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class AppComponentCreateReq { + + /** + * Namespace ID + */ + private String namespaceId; + + /** + * Stage ID + */ + private String stageId; + + /** + * 应用 ID + */ + private String appId; + + /** + * 分类 + */ + private String category; + + /** + * 组件类型 + */ + private String componentType; + + /** + * 组件名称 + */ + private String componentName; + + /** + * 配置内容 + */ + private JSONObject config; +} diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/appcomponent/AppComponentDeleteReq.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/appcomponent/AppComponentDeleteReq.java new file mode 100644 index 00000000..ca51f720 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/appcomponent/AppComponentDeleteReq.java @@ -0,0 +1,24 @@ +package com.alibaba.tesla.appmanager.domain.req.appcomponent; + +import com.alibaba.fastjson.JSONObject; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 应用关联组件删除请求 + * + * @author yaoxing.gyx@alibaba-inc.com + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class AppComponentDeleteReq { + + /** + * 应用组件绑定 ID + */ + private Long id; +} diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/appcomponent/AppComponentQueryReq.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/appcomponent/AppComponentQueryReq.java index ab419256..1dd868f6 100644 --- a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/appcomponent/AppComponentQueryReq.java +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/appcomponent/AppComponentQueryReq.java @@ -17,11 +17,21 @@ import lombok.experimental.SuperBuilder; @AllArgsConstructor public class AppComponentQueryReq extends BaseRequest { + /** + * ID + */ + private Long id; + /** * 应用 ID */ private String appId; + /** + * 分类 + */ + private String category; + /** * Namespace ID */ diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/appcomponent/AppComponentUpdateReq.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/appcomponent/AppComponentUpdateReq.java new file mode 100644 index 00000000..0c5c1380 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/appcomponent/AppComponentUpdateReq.java @@ -0,0 +1,59 @@ +package com.alibaba.tesla.appmanager.domain.req.appcomponent; + +import com.alibaba.fastjson.JSONObject; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 应用关联组件更新请求 + * + * @author yaoxing.gyx@alibaba-inc.com + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class AppComponentUpdateReq { + + /** + * 应用组件绑定 ID + */ + private Long id; + + /** + * Namespace ID + */ + private String namespaceId; + + /** + * Stage ID + */ + private String stageId; + + /** + * 应用 ID + */ + private String appId; + + /** + * 分类 + */ + private String category; + + /** + * 组件类型 + */ + private String componentType; + + /** + * 组件名称 + */ + private String componentName; + + /** + * 配置内容 + */ + private JSONObject config; +} diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/apppackage/ComponentBinder.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/apppackage/ComponentBinder.java index 602fcd6a..0a90b157 100644 --- a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/apppackage/ComponentBinder.java +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/apppackage/ComponentBinder.java @@ -23,7 +23,7 @@ public class ComponentBinder { /** * 组件类型 */ - private ComponentTypeEnum componentType; + private String componentType; /** * 组件唯一标示 @@ -31,9 +31,9 @@ public class ComponentBinder { private String componentName; /** - * 组件名称 + * 分类 */ - private String componentLabel; + private String category; /** * 组件版本 diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/deploy/DeployAppLaunchReq.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/deploy/DeployAppLaunchReq.java index dd4a0da9..f83bf3e1 100644 --- a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/deploy/DeployAppLaunchReq.java +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/deploy/DeployAppLaunchReq.java @@ -1,5 +1,6 @@ package com.alibaba.tesla.appmanager.domain.req.deploy; +import com.alibaba.fastjson.JSONObject; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -39,4 +40,9 @@ public class DeployAppLaunchReq implements Serializable { * 是否移除应用 ID 后缀 */ private Boolean removeSuffix = false; + + /** + * 覆盖参数对象 (内部使用) + */ + private JSONObject overwriteParameters; } diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/deployconfig/DeployConfigBindEnvironmentReq.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/deployconfig/DeployConfigBindEnvironmentReq.java new file mode 100644 index 00000000..80934900 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/deployconfig/DeployConfigBindEnvironmentReq.java @@ -0,0 +1,53 @@ +package com.alibaba.tesla.appmanager.domain.req.deployconfig; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 将指定应用绑定到指定环境 + * + * @author yaoxing.gyx@alibaba-inc.com + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class DeployConfigBindEnvironmentReq { + + /** + * 应用 ID + */ + private String appId; + + /** + * 隔离 Namespace ID + */ + private String isolateNamespaceId; + + /** + * 隔离 Stage ID + */ + private String isolateStageId; + + /** + * 环境 ID + */ + private String envId; + + /** + * 产品 ID + */ + private String productId; + + /** + * 发布版本 ID + */ + private String releaseId; + + /** + * 基线分支 + */ + private String baselineBranch; +} diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/deployconfig/DeployConfigGetGlobalTemplateReq.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/deployconfig/DeployConfigGetGlobalTemplateReq.java new file mode 100644 index 00000000..7d7e3bba --- /dev/null +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/deployconfig/DeployConfigGetGlobalTemplateReq.java @@ -0,0 +1,33 @@ +package com.alibaba.tesla.appmanager.domain.req.deployconfig; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 获取 DeployConfig 下的全局模板 + * + * @author yaoxing.gyx@alibaba-inc.com + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class DeployConfigGetGlobalTemplateReq { + + /** + * 隔离 Namespace + */ + private String isolateNamespaceId; + + /** + * 隔离 Stage + */ + private String isolateStageId; + + /** + * 环境 ID + */ + private String envId; +} diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/deployconfig/DeployConfigListReq.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/deployconfig/DeployConfigListReq.java new file mode 100644 index 00000000..a7aacd8a --- /dev/null +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/deployconfig/DeployConfigListReq.java @@ -0,0 +1,78 @@ +package com.alibaba.tesla.appmanager.domain.req.deployconfig; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 部署配置查询请求 + * + * @author yaoxing.gyx@alibaba-inc.com + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class DeployConfigListReq { + + /** + * ID + */ + private Long id; + + /** + * 应用 ID + */ + private String appId; + + /** + * 类型 ID + */ + private String typeId; + + /** + * 类型 ID 前缀 + */ + private String typeIdPrefix; + + /** + * 环境 ID + */ + private String envId; + + /** + * API 版本 + */ + private String apiVersion; + + /** + * 是否启用 + */ + private Boolean enabled; + + /** + * 是否继承 + */ + private Boolean inherit; + + /** + * Namespace ID + */ + private String isolateNamespaceId; + + /** + * Namespace ID 不等条件 + */ + private String isolateNamespaceIdNotEqualTo; + + /** + * Stage ID + */ + private String isolateStageId; + + /** + * Stage ID 不等条件 + */ + private String isolateStageIdNotEqualTo; +} diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/deployconfig/DeployConfigUpsertGlobalTemplateReq.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/deployconfig/DeployConfigUpsertGlobalTemplateReq.java new file mode 100644 index 00000000..000d80c4 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/deployconfig/DeployConfigUpsertGlobalTemplateReq.java @@ -0,0 +1,35 @@ +package com.alibaba.tesla.appmanager.domain.req.deployconfig; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * DeployConfig 更新全局模板请求 + * + * @author yaoxing.gyx@alibaba-inc.com + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class DeployConfigUpsertGlobalTemplateReq { + + /** + * 隔离 Namespace + */ + private String isolateNamespaceId; + + /** + * 隔离 Stage + */ + private String isolateStageId; + + /** + * 环境 ID + */ + private String envId; + + +} diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/deployconfig/DeployConfigUpdateReq.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/deployconfig/DeployConfigUpsertReq.java similarity index 66% rename from paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/deployconfig/DeployConfigUpdateReq.java rename to paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/deployconfig/DeployConfigUpsertReq.java index 5ce74e0f..e105e3cc 100644 --- a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/deployconfig/DeployConfigUpdateReq.java +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/deployconfig/DeployConfigUpsertReq.java @@ -1,5 +1,8 @@ package com.alibaba.tesla.appmanager.domain.req.deployconfig; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -9,7 +12,7 @@ import lombok.NoArgsConstructor; @Builder @NoArgsConstructor @AllArgsConstructor -public class DeployConfigUpdateReq { +public class DeployConfigUpsertReq { /** * API 版本 @@ -32,10 +35,20 @@ public class DeployConfigUpdateReq { private String envId; /** - * 配置信息 + * 配置信息 (Yaml) */ private String config; + /** + * 配置信息 (JSONArray), 如果传递了当前值,则 config 无效 + */ + private JSONArray configJsonArray; + + /** + * 配置信息 (JSONObject), 如果传递了当前值,则 config 无效 + */ + private JSONObject configJsonObject; + /** * 是否继承 */ diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/git/GitCloneReq.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/git/GitCloneReq.java index be9bd694..8d60ba7b 100644 --- a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/git/GitCloneReq.java +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/git/GitCloneReq.java @@ -52,4 +52,10 @@ public class GitCloneReq implements Serializable { * 保留 .git 文件 */ private boolean keepGitFiles = false; + + /** + * 是否重置目录路径 + */ + private String rewriteRepoPath = ""; + } diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/imagebuilder/ImageBuilderCreateReq.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/imagebuilder/ImageBuilderCreateReq.java index d214e13a..edcbea8a 100644 --- a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/imagebuilder/ImageBuilderCreateReq.java +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/imagebuilder/ImageBuilderCreateReq.java @@ -47,6 +47,11 @@ public class ImageBuilderCreateReq implements Serializable { */ private Boolean imagePushUseBranchAsTag; + /** + * 是否保留 .git 仓库文件 + */ + private boolean keepGitFiles; + /** * 构建好的镜像名称 (不提供则自动生成) */ diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/plugin/PluginDisableReq.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/plugin/PluginDisableReq.java new file mode 100644 index 00000000..c72524b5 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/plugin/PluginDisableReq.java @@ -0,0 +1,33 @@ +package com.alibaba.tesla.appmanager.domain.req.plugin; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 关闭插件请求 + * + * @author yaoxing.gyx@alibaba-inc.com + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PluginDisableReq { + + /** + * 插件名称 + */ + private String pluginName; + + /** + * 插件版本 + */ + private String pluginVersion; + + /** + * 是否忽略 Groovy 脚本 + */ + private boolean ignoreGroovyFiles; +} diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/plugin/PluginEnableReq.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/plugin/PluginEnableReq.java new file mode 100644 index 00000000..72156410 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/plugin/PluginEnableReq.java @@ -0,0 +1,28 @@ +package com.alibaba.tesla.appmanager.domain.req.plugin; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 启用插件请求 + * + * @author yaoxing.gyx@alibaba-inc.com + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PluginEnableReq { + + /** + * 插件名称 + */ + private String pluginName; + + /** + * 插件版本 + */ + private String pluginVersion; +} diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/plugin/PluginFrontendGetReq.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/plugin/PluginFrontendGetReq.java new file mode 100644 index 00000000..4ef79a2d --- /dev/null +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/plugin/PluginFrontendGetReq.java @@ -0,0 +1,33 @@ +package com.alibaba.tesla.appmanager.domain.req.plugin; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * Plugin Frontend 资源获取请求 + * + * @author yaoxing.gyx@alibaba-inc.com + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PluginFrontendGetReq { + + /** + * 插件名称 + */ + private String pluginName; + + /** + * 插件版本 + */ + private String pluginVersion; + + /** + * 名称 + */ + private String name; +} diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/plugin/PluginGetReq.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/plugin/PluginGetReq.java new file mode 100644 index 00000000..fa5a4a16 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/plugin/PluginGetReq.java @@ -0,0 +1,18 @@ +package com.alibaba.tesla.appmanager.domain.req.plugin; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PluginGetReq { + + private String pluginName; + + private String pluginVersion; + +} diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/plugin/PluginOperateReq.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/plugin/PluginOperateReq.java new file mode 100644 index 00000000..17b4dfcf --- /dev/null +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/plugin/PluginOperateReq.java @@ -0,0 +1,17 @@ +package com.alibaba.tesla.appmanager.domain.req.plugin; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PluginOperateReq { + + private String operation; + + private Boolean disableOthers = false; +} diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/plugin/PluginUploadReq.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/plugin/PluginUploadReq.java new file mode 100644 index 00000000..3762dee8 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/plugin/PluginUploadReq.java @@ -0,0 +1,23 @@ +package com.alibaba.tesla.appmanager.domain.req.plugin; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PluginUploadReq { + + /** + * 是否强制覆盖 + */ + private boolean overwrite; + + /** + * 是否默认开启 + */ + private boolean enable; +} diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/workflow/WorkflowPutContextReq.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/workflow/WorkflowPutContextReq.java new file mode 100644 index 00000000..d17e2ebb --- /dev/null +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/workflow/WorkflowPutContextReq.java @@ -0,0 +1,21 @@ +package com.alibaba.tesla.appmanager.domain.req.workflow; + +import com.alibaba.fastjson.JSONObject; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class WorkflowPutContextReq implements Serializable { + + /** + * Context + */ + private JSONObject context; +} diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/workflow/WorkflowTaskListReq.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/workflow/WorkflowTaskListReq.java index 0c0d7174..22e8224a 100644 --- a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/workflow/WorkflowTaskListReq.java +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/workflow/WorkflowTaskListReq.java @@ -42,4 +42,9 @@ public class WorkflowTaskListReq implements Serializable { * 部署单 ID */ private Long deployAppId; + + /** + * 部署 Workflow Instance ID + */ + private Long deployWorkflowInstanceId; } diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/workflow/WorkflowTaskSuspendReq.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/workflow/WorkflowTaskSuspendReq.java new file mode 100644 index 00000000..83b91417 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/workflow/WorkflowTaskSuspendReq.java @@ -0,0 +1,19 @@ +package com.alibaba.tesla.appmanager.domain.req.workflow; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class WorkflowTaskSuspendReq implements Serializable { + + private Long workflowTaskId; + + private String extMessage; +} diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/workflow/WorkflowTaskTerminateReq.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/workflow/WorkflowTaskTerminateReq.java new file mode 100644 index 00000000..04769cff --- /dev/null +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/req/workflow/WorkflowTaskTerminateReq.java @@ -0,0 +1,19 @@ +package com.alibaba.tesla.appmanager.domain.req.workflow; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class WorkflowTaskTerminateReq implements Serializable { + + private Long workflowTaskId; + + private String extMessage; +} diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/res/workflow/ExecuteWorkflowHandlerRes.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/res/workflow/ExecuteWorkflowHandlerRes.java index 1007d246..7f534b94 100644 --- a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/res/workflow/ExecuteWorkflowHandlerRes.java +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/res/workflow/ExecuteWorkflowHandlerRes.java @@ -31,7 +31,12 @@ public class ExecuteWorkflowHandlerRes implements Serializable { private DeployAppSchema configuration; /** - * 如果当前 workflow 触发了部署,那么此处返回部署单 ID + * 如果当前 Workflow 触发了新的 Workflow,那么此处返回 Workflow 实例 ID + */ + private Long deployWorkflowInstanceId; + + /** + * 如果当前 Workflow 触发了部署,那么此处返回部署单 ID */ private Long deployAppId; @@ -54,4 +59,14 @@ public class ExecuteWorkflowHandlerRes implements Serializable { * 是否暂停 */ private boolean suspend; + + /** + * 是否自行终止后续所有 workflow 任务执行 + */ + private boolean terminate; + + /** + * 终止原因 + */ + private String terminateReason; } diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/schema/DeployAppSchema.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/schema/DeployAppSchema.java index 382b4cf1..a5f6178e 100644 --- a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/schema/DeployAppSchema.java +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/schema/DeployAppSchema.java @@ -1,5 +1,6 @@ package com.alibaba.tesla.appmanager.domain.schema; +import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.annotation.JSONField; import com.alibaba.tesla.appmanager.common.constants.DefaultConstant; @@ -123,6 +124,9 @@ public class DeployAppSchema implements Schema, Serializable { } @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor public static class DataOutput implements Serializable { private static final long serialVersionUID = 2150471143237594995L; @@ -307,9 +311,9 @@ public class DeployAppSchema implements Schema, Serializable { @JSONField(serialize = false) public String getUniqueId(DeployAppRevisionName componentRevisionContainer) { DeployAppRevisionName container = DeployAppRevisionName.builder() - .componentType(ComponentTypeEnum.TRAIT_ADDON) + .componentType(ComponentTypeEnum.TRAIT_ADDON.toString()) .componentName(String.join("~", Arrays.asList( - componentRevisionContainer.getComponentType().toString(), + componentRevisionContainer.getComponentType(), componentRevisionContainer.getComponentName(), name ))) @@ -335,6 +339,16 @@ public class DeployAppSchema implements Schema, Serializable { */ private String type; + /** + * Workflow 传递参数输出 + */ + private JSONArray outputs = new JSONArray(); + + /** + * Workflow 传递参数输入 + */ + private JSONArray inputs = new JSONArray(); + /** * Workflow 任务运行时机 (pre-render/post-render/post-deploy) */ diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/schema/PluginDefinitionSchema.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/schema/PluginDefinitionSchema.java index 955c021f..1dc476e1 100644 --- a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/schema/PluginDefinitionSchema.java +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/schema/PluginDefinitionSchema.java @@ -25,6 +25,7 @@ import java.util.List; @AllArgsConstructor public class PluginDefinitionSchema implements Schema { + public static final String ANNOTATIONS_LABEL = "definition.oam.dev/label"; public static final String ANNOTATIONS_DESCRIPTION = "definition.oam.dev/description"; public static final String ANNOTATIONS_VERSION = "definition.oam.dev/version"; public static final String ANNOTATIONS_TAGS = "definition.oam.dev/tags"; @@ -35,7 +36,7 @@ public class PluginDefinitionSchema implements Schema { private Spec spec; public PluginKindEnum getPluginKind() { - return PluginKindEnum.valueOf(kind); + return PluginKindEnum.fromString(kind); } public String getPluginName() { @@ -141,6 +142,7 @@ public class PluginDefinitionSchema implements Schema { private String kind; private String name; private String path; + private JSONObject properties; } @Data diff --git a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/schema/TraitDefinition.java b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/schema/TraitDefinition.java index ee3ced06..ab345155 100644 --- a/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/schema/TraitDefinition.java +++ b/paas/appmanager/tesla-appmanager-domain/src/main/java/com/alibaba/tesla/appmanager/domain/schema/TraitDefinition.java @@ -1,7 +1,10 @@ package com.alibaba.tesla.appmanager.domain.schema; import com.alibaba.fastjson.JSONObject; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; +import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; import java.io.Serializable; @@ -15,6 +18,9 @@ import java.util.List; */ @Slf4j @Data +@Builder +@NoArgsConstructor +@AllArgsConstructor public class TraitDefinition implements Serializable { private static final long serialVersionUID = 7095150105558418313L; @@ -43,6 +49,9 @@ public class TraitDefinition implements Serializable { * 元信息 */ @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor public static class MetaData implements Serializable { private static final long serialVersionUID = -3040036214175436386L; @@ -57,6 +66,9 @@ public class TraitDefinition implements Serializable { * Spec */ @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor public static class Spec implements Serializable { private static final long serialVersionUID = -1592974598970779373L; @@ -80,6 +92,9 @@ public class TraitDefinition implements Serializable { * defintionRef */ @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor public static class SpecDefinitionRef implements Serializable { private static final long serialVersionUID = -6624030971546732668L; @@ -88,6 +103,9 @@ public class TraitDefinition implements Serializable { } @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor public static class DataOutput implements Serializable { private static final long serialVersionUID = 2150471143237594995L; diff --git a/paas/appmanager/tesla-appmanager-dynamic-script/pom.xml b/paas/appmanager/tesla-appmanager-dynamic-script/pom.xml index e6ca06c7..19e72365 100644 --- a/paas/appmanager/tesla-appmanager-dynamic-script/pom.xml +++ b/paas/appmanager/tesla-appmanager-dynamic-script/pom.xml @@ -7,7 +7,7 @@ com.alibaba.tesla tesla-appmanager - 1.0.4-SNAPSHOT + 1.0.5-SNAPSHOT ../pom.xml @@ -31,6 +31,10 @@ com.alibaba.tesla tesla-appmanager-spring + + com.alibaba.tesla + tesla-appmanager-kubernetes + io.sreworks tesla-webmvc-spring-boot-starter diff --git a/paas/appmanager/tesla-appmanager-dynamic-script/src/main/java/com/alibaba/tesla/appmanager/dynamicscript/core/GroovyHandlerFactory.java b/paas/appmanager/tesla-appmanager-dynamic-script/src/main/java/com/alibaba/tesla/appmanager/dynamicscript/core/GroovyHandlerFactory.java index 9405ede6..7e5fa40e 100644 --- a/paas/appmanager/tesla-appmanager-dynamic-script/src/main/java/com/alibaba/tesla/appmanager/dynamicscript/core/GroovyHandlerFactory.java +++ b/paas/appmanager/tesla-appmanager-dynamic-script/src/main/java/com/alibaba/tesla/appmanager/dynamicscript/core/GroovyHandlerFactory.java @@ -9,6 +9,7 @@ import com.alibaba.tesla.appmanager.common.exception.AppException; import com.alibaba.tesla.appmanager.dynamicscript.repository.condition.DynamicScriptQueryCondition; import com.alibaba.tesla.appmanager.dynamicscript.repository.domain.DynamicScriptDO; import com.alibaba.tesla.appmanager.dynamicscript.service.DynamicScriptService; +import com.alibaba.tesla.appmanager.server.dynamicscript.handler.ComponentHandler; import com.alibaba.tesla.appmanager.spring.util.SpringBeanUtil; import groovy.lang.GroovyClassLoader; import lombok.Builder; @@ -149,121 +150,23 @@ public class GroovyHandlerFactory { * @return Handler 如果不支持,返回 null */ public T getByComponentType( - Class scriptClass, String appId, ComponentTypeEnum componentType, String componentName, + Class scriptClass, String appId, String componentType, String componentName, ComponentActionEnum action) { assert ComponentActionEnum.BUILD.equals(action) || ComponentActionEnum.DEPLOY.equals(action); - switch (componentType) { - case K8S_MICROSERVICE: - if (ComponentActionEnum.BUILD.equals(action)) { - return get(scriptClass, - DynamicScriptKindEnum.BUILD_MICROSERVICE_COMPONENT.toString(), - DefaultConstant.DEFAULT_GROOVY_HANDLER); - } else { - return get(scriptClass, - DynamicScriptKindEnum.DEPLOY_MICROSERVICE_COMPONENT.toString(), - DefaultConstant.DEFAULT_GROOVY_HANDLER); - } - case K8S_JOB: - if (ComponentActionEnum.BUILD.equals(action)) { - return get(scriptClass, - DynamicScriptKindEnum.BUILD_JOB_COMPONENT.toString(), - DefaultConstant.DEFAULT_GROOVY_HANDLER); - } else { - return get(scriptClass, - DynamicScriptKindEnum.DEPLOY_JOB_COMPONENT.toString(), - DefaultConstant.DEFAULT_GROOVY_HANDLER); - } - case ABM_OPERATOR_TVD: - if (ComponentActionEnum.BUILD.equals(action)) { - return get(scriptClass, - DynamicScriptKindEnum.BUILD_ABM_OPERATOR_TVD_COMPONENT.toString(), - DefaultConstant.DEFAULT_GROOVY_HANDLER); - } else { - return get(scriptClass, - DynamicScriptKindEnum.DEPLOY_ABM_OPERATOR_TVD_COMPONENT.toString(), - DefaultConstant.DEFAULT_GROOVY_HANDLER); - } - case HELM: - if (ComponentActionEnum.BUILD.equals(action)) { - return get(scriptClass, - DynamicScriptKindEnum.BUILD_HELM_COMPONENT.toString(), - DefaultConstant.DEFAULT_GROOVY_HANDLER); - } else { - return get(scriptClass, - DynamicScriptKindEnum.DEPLOY_HELM_COMPONENT.toString(), - DefaultConstant.DEFAULT_GROOVY_HANDLER); - } - case ABM_CHART: - if (ComponentActionEnum.BUILD.equals(action)) { - return get(scriptClass, - DynamicScriptKindEnum.BUILD_ABM_CHART_COMPONENT.toString(), - DefaultConstant.DEFAULT_GROOVY_HANDLER); - } else { - return get(scriptClass, - DynamicScriptKindEnum.DEPLOY_ABM_CHART_COMPONENT.toString(), - DefaultConstant.DEFAULT_GROOVY_HANDLER); - } - case ASI_COMPONENT: - if (ComponentActionEnum.BUILD.equals(action)) { - return get(scriptClass, - DynamicScriptKindEnum.BUILD_ASI_COMPONENT.toString(), - DefaultConstant.DEFAULT_GROOVY_HANDLER); - } else { - return get(scriptClass, - DynamicScriptKindEnum.DEPLOY_ASI_COMPONENT.toString(), - DefaultConstant.DEFAULT_GROOVY_HANDLER); - } - case ABM_KUSTOMIZE: - if (ComponentActionEnum.BUILD.equals(action)) { - return get(scriptClass, - DynamicScriptKindEnum.BUILD_ABM_KUSTOMIZE_COMPONENT.toString(), - DefaultConstant.DEFAULT_GROOVY_HANDLER); - } else { - return get(scriptClass, - DynamicScriptKindEnum.DEPLOY_ABM_KUSTOMIZE_COMPONENT.toString(), - DefaultConstant.DEFAULT_GROOVY_HANDLER); - } - case ABM_HELM: - if (ComponentActionEnum.BUILD.equals(action)) { - return get(scriptClass, - DynamicScriptKindEnum.BUILD_ABM_HELM_COMPONENT.toString(), - DefaultConstant.DEFAULT_GROOVY_HANDLER); - } else { - return get(scriptClass, - DynamicScriptKindEnum.DEPLOY_ABM_HELM_COMPONENT.toString(), - DefaultConstant.DEFAULT_GROOVY_HANDLER); - } - case SCRIPT: - if (ComponentActionEnum.BUILD.equals(action)) { - return get(scriptClass, - DynamicScriptKindEnum.BUILD_SCRIPT_COMPONENT.toString(), - DefaultConstant.DEFAULT_GROOVY_HANDLER); - } else { - return get(scriptClass, - DynamicScriptKindEnum.DEPLOY_SCRIPT_COMPONENT.toString(), - DefaultConstant.DEFAULT_GROOVY_HANDLER); - } - case ABM_STATUS: - if (ComponentActionEnum.BUILD.equals(action)) { - return get(scriptClass, - DynamicScriptKindEnum.BUILD_ABM_STATUS_COMPONENT.toString(), - DefaultConstant.DEFAULT_GROOVY_HANDLER); - } else { - return get(scriptClass, - DynamicScriptKindEnum.DEPLOY_ABM_STATUS_COMPONENT.toString(), - DefaultConstant.DEFAULT_GROOVY_HANDLER); - } - case ABM_ES_STATUS: - if (ComponentActionEnum.BUILD.equals(action)) { - return get(scriptClass, - DynamicScriptKindEnum.BUILD_ABM_ES_STATUS_COMPONENT.toString(), - DefaultConstant.DEFAULT_GROOVY_HANDLER); - } else { - return get(scriptClass, - DynamicScriptKindEnum.DEPLOY_ABM_ES_STATUS_COMPONENT.toString(), - DefaultConstant.DEFAULT_GROOVY_HANDLER); - } - case INTERNAL_ADDON: + try { + ComponentHandler componentHandler = get(ComponentHandler.class, "COMPONENT", componentType); + if (ComponentActionEnum.BUILD.equals(action)) { + return get(scriptClass, DynamicScriptKindEnum.COMPONENT_BUILD.toString(), + componentHandler.buildScriptName()); + } else { + return get(scriptClass, DynamicScriptKindEnum.COMPONENT_DEPLOY.toString(), + componentHandler.deployScriptName()); + } + } catch (Exception e) { + log.error("failed to get executor via generic method, fallback|appId={}|componentType={}|" + + "componentName={}|action={}|exception={}", appId, componentType, + componentName, action, e.getMessage()); + if (ComponentTypeEnum.INTERNAL_ADDON.toString().equals(componentType)) { if ("tianji_productops".equals(componentName)) { if (ComponentActionEnum.BUILD.equals(action)) { return get(scriptClass, @@ -317,7 +220,7 @@ public class GroovyHandlerFactory { } else { return null; } - case RESOURCE_ADDON: + } else if (ComponentTypeEnum.RESOURCE_ADDON.toString().equals(componentType)) { if (ComponentActionEnum.BUILD.equals(action)) { return get(scriptClass, DynamicScriptKindEnum.BUILD_RESOURCE_ADDON_COMPONENT.toString(), @@ -327,8 +230,9 @@ public class GroovyHandlerFactory { DynamicScriptKindEnum.DEPLOY_RESOURCE_ADDON_COMPONENT.toString(), DefaultConstant.DEFAULT_GROOVY_HANDLER); } - default: + } else { return null; + } } } @@ -369,6 +273,25 @@ public class GroovyHandlerFactory { } } + /** + * 删除 Handler + * + * @param kind 动态脚本类型 + * @param name 动态脚本唯一标识 + */ + public void uninstall(String kind, String name) { + String key = keyGenerator(kind, name); + if (!VERSION_MAP.containsKey(key)) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("the plugin has not been loaded|kind=%s|name=%s", kind, name)); + } + synchronized (GroovyHandlerFactory.class) { + VERSION_MAP.remove(key); + HANDLER_INSTANCES.remove(key); + log.info("groovy handler has unloaded|kind={}|name={}", kind, name); + } + } + /** * 依赖注入 * diff --git a/paas/appmanager/tesla-appmanager-dynamic-script/src/main/java/com/alibaba/tesla/appmanager/dynamicscript/service/DynamicScriptService.java b/paas/appmanager/tesla-appmanager-dynamic-script/src/main/java/com/alibaba/tesla/appmanager/dynamicscript/service/DynamicScriptService.java index b1494420..647090a3 100644 --- a/paas/appmanager/tesla-appmanager-dynamic-script/src/main/java/com/alibaba/tesla/appmanager/dynamicscript/service/DynamicScriptService.java +++ b/paas/appmanager/tesla-appmanager-dynamic-script/src/main/java/com/alibaba/tesla/appmanager/dynamicscript/service/DynamicScriptService.java @@ -28,6 +28,13 @@ public interface DynamicScriptService { */ List list(DynamicScriptQueryCondition condition); + /** + * 删除指定的动态脚本 (所有 node 感知后会自动卸载) + * + * @param condition 查询条件 + */ + void removeScript(DynamicScriptQueryCondition condition); + /** * 初始化脚本 *

diff --git a/paas/appmanager/tesla-appmanager-dynamic-script/src/main/java/com/alibaba/tesla/appmanager/dynamicscript/service/impl/DynamicScriptServiceImpl.java b/paas/appmanager/tesla-appmanager-dynamic-script/src/main/java/com/alibaba/tesla/appmanager/dynamicscript/service/impl/DynamicScriptServiceImpl.java index c9ea4642..49756e73 100644 --- a/paas/appmanager/tesla-appmanager-dynamic-script/src/main/java/com/alibaba/tesla/appmanager/dynamicscript/service/impl/DynamicScriptServiceImpl.java +++ b/paas/appmanager/tesla-appmanager-dynamic-script/src/main/java/com/alibaba/tesla/appmanager/dynamicscript/service/impl/DynamicScriptServiceImpl.java @@ -1,5 +1,7 @@ package com.alibaba.tesla.appmanager.dynamicscript.service.impl; +import com.alibaba.tesla.appmanager.common.exception.AppErrorCode; +import com.alibaba.tesla.appmanager.common.exception.AppException; import com.alibaba.tesla.appmanager.dynamicscript.repository.DynamicScriptHistoryRepository; import com.alibaba.tesla.appmanager.dynamicscript.repository.DynamicScriptRepository; import com.alibaba.tesla.appmanager.dynamicscript.repository.condition.DynamicScriptQueryCondition; @@ -7,6 +9,7 @@ import com.alibaba.tesla.appmanager.dynamicscript.repository.domain.DynamicScrip import com.alibaba.tesla.appmanager.dynamicscript.repository.domain.DynamicScriptHistoryDO; import com.alibaba.tesla.appmanager.dynamicscript.service.DynamicScriptService; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -50,6 +53,22 @@ public class DynamicScriptServiceImpl implements DynamicScriptService { return dynamicScriptRepository.selectByCondition(condition); } + /** + * 删除指定的动态脚本 (所有 node 感知后会自动卸载) + * + * @param condition 查询条件 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void removeScript(DynamicScriptQueryCondition condition) { + if (StringUtils.isAnyEmpty(condition.getKind(), condition.getName())) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "must provide kind/name parameters"); + } + int count = dynamicScriptRepository.deleteByCondition(condition); + log.info("dynamic script has removed|kind={}|name={}|count={}", + condition.getKind(), condition.getName(), count); + } + /** * 初始化脚本 *

@@ -58,7 +77,7 @@ public class DynamicScriptServiceImpl implements DynamicScriptService { * * 如果 version 小于等于当前版本,不进行操作 * * @param condition 查询条件 - * @param revision 提供的脚本版本 + * @param revision 提供的脚本版本 * @param code Groovy 代码 */ @Override @@ -72,11 +91,11 @@ public class DynamicScriptServiceImpl implements DynamicScriptService { return; } else if (script == null) { dynamicScriptRepository.insert(DynamicScriptDO.builder() - .kind(kind) - .name(name) - .currentRevision(revision) - .code(code) - .build()); + .kind(kind) + .name(name) + .currentRevision(revision) + .code(code) + .build()); log.info("dynamic script has inserted into database|kind={}|name={}|revision={}", kind, name, revision); } else { script.setCurrentRevision(revision); @@ -87,10 +106,10 @@ public class DynamicScriptServiceImpl implements DynamicScriptService { // 插入历史数据 dynamicScriptHistoryRepository.insert(DynamicScriptHistoryDO.builder() - .kind(kind) - .name(name) - .revision(revision) - .code(code) - .build()); + .kind(kind) + .name(name) + .revision(revision) + .code(code) + .build()); } } diff --git a/paas/appmanager/tesla-appmanager-dynamic-script/src/main/java/com/alibaba/tesla/appmanager/dynamicscript/util/GroovyUtil.java b/paas/appmanager/tesla-appmanager-dynamic-script/src/main/java/com/alibaba/tesla/appmanager/dynamicscript/util/GroovyUtil.java new file mode 100644 index 00000000..f8c88292 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-dynamic-script/src/main/java/com/alibaba/tesla/appmanager/dynamicscript/util/GroovyUtil.java @@ -0,0 +1,55 @@ +package com.alibaba.tesla.appmanager.dynamicscript.util; + +import com.alibaba.tesla.appmanager.common.exception.AppErrorCode; +import com.alibaba.tesla.appmanager.common.exception.AppException; +import com.alibaba.tesla.appmanager.domain.core.ScriptIdentifier; +import org.apache.commons.lang3.StringUtils; + +import java.lang.reflect.Field; + +/** + * Groovy 工具类 + * + * @author yaoxing.gyx@alibaba-inc.com + */ +public class GroovyUtil { + + /** + * 从 clazz 中获取 Script 标识信息 (kind/name/revision) + * + * @param clazz Class + * @return Script 标识信息 + * @throws IllegalAccessException + */ + public static ScriptIdentifier getScriptIdentifierFromClass(Class clazz) throws IllegalAccessException { + String kind = null, name = null; + Integer revision = null; + for (Field f : clazz.getFields()) { + if (f.getType().equals(String.class) || f.getType().equals(Integer.class)) { + String key = f.getName(); + Object value = f.get(null); + switch (key) { + case "KIND": + kind = (String) value; + break; + case "NAME": + name = (String) value; + break; + case "REVISION": + revision = (Integer) value; + break; + default: + break; + } + } + } + if (StringUtils.isAnyEmpty(kind, name) || revision == null) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "cannot find kind/name/revision in class"); + } + return ScriptIdentifier.builder() + .kind(kind) + .name(name) + .revision(revision) + .build(); + } +} diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dynamicscript/handler/ComponentBuildHandler.java b/paas/appmanager/tesla-appmanager-dynamic-script/src/main/java/com/alibaba/tesla/appmanager/server/dynamicscript/handler/ComponentBuildHandler.java similarity index 100% rename from paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dynamicscript/handler/ComponentBuildHandler.java rename to paas/appmanager/tesla-appmanager-dynamic-script/src/main/java/com/alibaba/tesla/appmanager/server/dynamicscript/handler/ComponentBuildHandler.java diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dynamicscript/handler/ComponentCustomStatusHandler.java b/paas/appmanager/tesla-appmanager-dynamic-script/src/main/java/com/alibaba/tesla/appmanager/server/dynamicscript/handler/ComponentCustomStatusHandler.java similarity index 100% rename from paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dynamicscript/handler/ComponentCustomStatusHandler.java rename to paas/appmanager/tesla-appmanager-dynamic-script/src/main/java/com/alibaba/tesla/appmanager/server/dynamicscript/handler/ComponentCustomStatusHandler.java diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dynamicscript/handler/ComponentDeployHandler.java b/paas/appmanager/tesla-appmanager-dynamic-script/src/main/java/com/alibaba/tesla/appmanager/server/dynamicscript/handler/ComponentDeployHandler.java similarity index 100% rename from paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dynamicscript/handler/ComponentDeployHandler.java rename to paas/appmanager/tesla-appmanager-dynamic-script/src/main/java/com/alibaba/tesla/appmanager/server/dynamicscript/handler/ComponentDeployHandler.java diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dynamicscript/handler/ComponentDestroyHandler.java b/paas/appmanager/tesla-appmanager-dynamic-script/src/main/java/com/alibaba/tesla/appmanager/server/dynamicscript/handler/ComponentDestroyHandler.java similarity index 100% rename from paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dynamicscript/handler/ComponentDestroyHandler.java rename to paas/appmanager/tesla-appmanager-dynamic-script/src/main/java/com/alibaba/tesla/appmanager/server/dynamicscript/handler/ComponentDestroyHandler.java diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dynamicscript/handler/ComponentHandler.java b/paas/appmanager/tesla-appmanager-dynamic-script/src/main/java/com/alibaba/tesla/appmanager/server/dynamicscript/handler/ComponentHandler.java similarity index 100% rename from paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dynamicscript/handler/ComponentHandler.java rename to paas/appmanager/tesla-appmanager-dynamic-script/src/main/java/com/alibaba/tesla/appmanager/server/dynamicscript/handler/ComponentHandler.java diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dynamicscript/handler/ComponentWatchCronHandler.java b/paas/appmanager/tesla-appmanager-dynamic-script/src/main/java/com/alibaba/tesla/appmanager/server/dynamicscript/handler/ComponentWatchCronHandler.java similarity index 100% rename from paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dynamicscript/handler/ComponentWatchCronHandler.java rename to paas/appmanager/tesla-appmanager-dynamic-script/src/main/java/com/alibaba/tesla/appmanager/server/dynamicscript/handler/ComponentWatchCronHandler.java diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dynamicscript/handler/ComponentWatchKubernetesInformerHandler.java b/paas/appmanager/tesla-appmanager-dynamic-script/src/main/java/com/alibaba/tesla/appmanager/server/dynamicscript/handler/ComponentWatchKubernetesInformerHandler.java similarity index 100% rename from paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dynamicscript/handler/ComponentWatchKubernetesInformerHandler.java rename to paas/appmanager/tesla-appmanager-dynamic-script/src/main/java/com/alibaba/tesla/appmanager/server/dynamicscript/handler/ComponentWatchKubernetesInformerHandler.java diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dynamicscript/handler/TraitHandler.java b/paas/appmanager/tesla-appmanager-dynamic-script/src/main/java/com/alibaba/tesla/appmanager/server/dynamicscript/handler/TraitHandler.java similarity index 100% rename from paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dynamicscript/handler/TraitHandler.java rename to paas/appmanager/tesla-appmanager-dynamic-script/src/main/java/com/alibaba/tesla/appmanager/server/dynamicscript/handler/TraitHandler.java diff --git a/paas/appmanager/tesla-appmanager-kubernetes/pom.xml b/paas/appmanager/tesla-appmanager-kubernetes/pom.xml index a28e566f..828ca0c9 100644 --- a/paas/appmanager/tesla-appmanager-kubernetes/pom.xml +++ b/paas/appmanager/tesla-appmanager-kubernetes/pom.xml @@ -7,7 +7,7 @@ com.alibaba.tesla tesla-appmanager - 1.0.4-SNAPSHOT + 1.0.5-SNAPSHOT ../pom.xml diff --git a/paas/appmanager/tesla-appmanager-kubernetes/src/main/java/com/alibaba/tesla/appmanager/kubernetes/KubernetesClientFactory.java b/paas/appmanager/tesla-appmanager-kubernetes/src/main/java/com/alibaba/tesla/appmanager/kubernetes/KubernetesClientFactory.java index e1627e7b..6936b74f 100644 --- a/paas/appmanager/tesla-appmanager-kubernetes/src/main/java/com/alibaba/tesla/appmanager/kubernetes/KubernetesClientFactory.java +++ b/paas/appmanager/tesla-appmanager-kubernetes/src/main/java/com/alibaba/tesla/appmanager/kubernetes/KubernetesClientFactory.java @@ -92,8 +92,7 @@ public class KubernetesClientFactory { // 针对专有云场景,直接使用当前的 service account token String cloudType = System.getenv("CLOUD_TYPE"); if ("ApsaraStack".equals(cloudType) - || "ApsaraStackAgility".equals(cloudType) - || (EnvUtil.isSreworks() && "master".equals(clusterId))) { + || "ApsaraStackAgility".equals(cloudType)) { DefaultKubernetesClient client = clientMap.get(clusterId); if (client != null) { return client; @@ -109,6 +108,24 @@ public class KubernetesClientFactory { log.info("kubernetes client for cluster {} has put into client map", clusterId); return newClient; } + } else if (EnvUtil.isSreworks() && "master".equals(clusterId)) { + DefaultKubernetesClient client = clientMap.get(clusterId); + if (client != null) { + return client; + } + synchronized (clientMap) { + // double check + client = clientMap.get(clusterId); + if (client != null) { + return client; + } + + Config config = new ConfigBuilder().withNamespace(null).build(); + DefaultKubernetesClient newClient = new DefaultKubernetesClient(config); + clientMap.put(clusterId, newClient); + log.info("kubernetes client for cluster {} has put into client map", clusterId); + return newClient; + } } ClusterDTO clusterDTO = clusterProvider.get(clusterId); diff --git a/paas/appmanager/tesla-appmanager-market/pom.xml b/paas/appmanager/tesla-appmanager-market/pom.xml index 94b758bd..bd6b0bcc 100644 --- a/paas/appmanager/tesla-appmanager-market/pom.xml +++ b/paas/appmanager/tesla-appmanager-market/pom.xml @@ -5,7 +5,8 @@ tesla-appmanager com.alibaba.tesla - 1.0.4-SNAPSHOT + 1.0.5-SNAPSHOT + ../pom.xml 4.0.0 diff --git a/paas/appmanager/tesla-appmanager-meta-helm/pom.xml b/paas/appmanager/tesla-appmanager-meta-helm/pom.xml index 6d13f585..cdedeab6 100644 --- a/paas/appmanager/tesla-appmanager-meta-helm/pom.xml +++ b/paas/appmanager/tesla-appmanager-meta-helm/pom.xml @@ -7,7 +7,7 @@ com.alibaba.tesla tesla-appmanager - 1.0.4-SNAPSHOT + 1.0.5-SNAPSHOT ../pom.xml diff --git a/paas/appmanager/tesla-appmanager-meta-helm/src/main/java/com/alibaba/tesla/appmanager/meta/helm/assembly/HelmMetaDtoConvert.java b/paas/appmanager/tesla-appmanager-meta-helm/src/main/java/com/alibaba/tesla/appmanager/meta/helm/assembly/HelmMetaDtoConvert.java index b996ca53..5b99681c 100644 --- a/paas/appmanager/tesla-appmanager-meta-helm/src/main/java/com/alibaba/tesla/appmanager/meta/helm/assembly/HelmMetaDtoConvert.java +++ b/paas/appmanager/tesla-appmanager-meta-helm/src/main/java/com/alibaba/tesla/appmanager/meta/helm/assembly/HelmMetaDtoConvert.java @@ -24,7 +24,7 @@ public class HelmMetaDtoConvert extends BaseDtoConvert{ @Override public HelmMetaDTO to(HelmMetaDO source) { HelmMetaDTO helmMetaDTO = super.to(source); - helmMetaDTO.setComponentType(ComponentTypeEnum.valueOf(source.getComponentType())); + helmMetaDTO.setComponentType(source.getComponentType()); helmMetaDTO.setPackageType(PackageTypeEnum.valueOf(source.getPackageType())); helmMetaDTO.setHelmExt(JSONObject.parseObject(source.getHelmExt())); return helmMetaDTO; @@ -45,7 +45,7 @@ public class HelmMetaDtoConvert extends BaseDtoConvert{ @Override public HelmMetaDO from(HelmMetaDTO source) { HelmMetaDO helmMetaDO = super.from(source); - helmMetaDO.setComponentType(source.getComponentType().name()); + helmMetaDO.setComponentType(source.getComponentType()); helmMetaDO.setPackageType(source.getPackageType().name()); helmMetaDO.setHelmExt(source.getHelmExt().toJSONString()); return helmMetaDO; diff --git a/paas/appmanager/tesla-appmanager-meta-helm/src/main/java/com/alibaba/tesla/appmanager/meta/helm/controller/HelmGlobalController.java b/paas/appmanager/tesla-appmanager-meta-helm/src/main/java/com/alibaba/tesla/appmanager/meta/helm/controller/HelmGlobalController.java index cce8db22..33c6d252 100644 --- a/paas/appmanager/tesla-appmanager-meta-helm/src/main/java/com/alibaba/tesla/appmanager/meta/helm/controller/HelmGlobalController.java +++ b/paas/appmanager/tesla-appmanager-meta-helm/src/main/java/com/alibaba/tesla/appmanager/meta/helm/controller/HelmGlobalController.java @@ -5,11 +5,13 @@ import com.alibaba.tesla.appmanager.auth.controller.AppManagerBaseController; import com.alibaba.tesla.appmanager.domain.container.BizAppContainer; import com.alibaba.tesla.appmanager.domain.req.helm.HelmMetaQueryReq; import com.alibaba.tesla.common.base.TeslaBaseResult; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @RestController +@Tag(name = "Helm API") @RequestMapping("/components/helm") @Slf4j public class HelmGlobalController extends AppManagerBaseController { diff --git a/paas/appmanager/tesla-appmanager-meta-helm/src/main/java/com/alibaba/tesla/appmanager/meta/helm/controller/HelmItemController.java b/paas/appmanager/tesla-appmanager-meta-helm/src/main/java/com/alibaba/tesla/appmanager/meta/helm/controller/HelmItemController.java index fefd774f..3ae6a440 100644 --- a/paas/appmanager/tesla-appmanager-meta-helm/src/main/java/com/alibaba/tesla/appmanager/meta/helm/controller/HelmItemController.java +++ b/paas/appmanager/tesla-appmanager-meta-helm/src/main/java/com/alibaba/tesla/appmanager/meta/helm/controller/HelmItemController.java @@ -8,6 +8,7 @@ import com.alibaba.tesla.appmanager.domain.req.helm.HelmMetaCreateReq; import com.alibaba.tesla.appmanager.domain.req.helm.HelmMetaQueryReq; import com.alibaba.tesla.appmanager.domain.req.helm.HelmMetaUpdateReq; import com.alibaba.tesla.common.base.TeslaBaseResult; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @@ -15,6 +16,7 @@ import org.springframework.web.bind.annotation.*; import java.util.Objects; @RestController +@Tag(name = "Helm API") @RequestMapping("/apps/{appId}/helm") @Slf4j public class HelmItemController extends AppManagerBaseController { diff --git a/paas/appmanager/tesla-appmanager-meta-helm/src/main/java/com/alibaba/tesla/appmanager/meta/helm/service/impl/HelmMetaServiceImpl.java b/paas/appmanager/tesla-appmanager-meta-helm/src/main/java/com/alibaba/tesla/appmanager/meta/helm/service/impl/HelmMetaServiceImpl.java index e4b4f42e..60e9e741 100644 --- a/paas/appmanager/tesla-appmanager-meta-helm/src/main/java/com/alibaba/tesla/appmanager/meta/helm/service/impl/HelmMetaServiceImpl.java +++ b/paas/appmanager/tesla-appmanager-meta-helm/src/main/java/com/alibaba/tesla/appmanager/meta/helm/service/impl/HelmMetaServiceImpl.java @@ -14,7 +14,7 @@ import com.alibaba.tesla.appmanager.deployconfig.repository.domain.DeployConfigD import com.alibaba.tesla.appmanager.deployconfig.service.DeployConfigService; import com.alibaba.tesla.appmanager.domain.container.DeployConfigTypeId; import com.alibaba.tesla.appmanager.domain.req.deployconfig.DeployConfigDeleteReq; -import com.alibaba.tesla.appmanager.domain.req.deployconfig.DeployConfigUpdateReq; +import com.alibaba.tesla.appmanager.domain.req.deployconfig.DeployConfigUpsertReq; import com.alibaba.tesla.appmanager.meta.helm.repository.HelmMetaRepository; import com.alibaba.tesla.appmanager.meta.helm.repository.condition.HelmMetaQueryCondition; import com.alibaba.tesla.appmanager.meta.helm.repository.domain.HelmMetaDO; @@ -160,7 +160,7 @@ public class HelmMetaServiceImpl implements HelmMetaService { traits.add(gatewayTrait); } - String systemTypeId = new DeployConfigTypeId(ComponentTypeEnum.RESOURCE_ADDON, "system-env@system-env").toString(); + String systemTypeId = new DeployConfigTypeId(ComponentTypeEnum.RESOURCE_ADDON.toString(), "system-env@system-env").toString(); List configs = deployConfigService.list( DeployConfigQueryCondition.builder() @@ -189,8 +189,8 @@ public class HelmMetaServiceImpl implements HelmMetaService { configObject.put("scopes", scopes); Yaml yaml = SchemaUtil.createYaml(JSONObject.class); - String typeId = new DeployConfigTypeId(ComponentTypeEnum.HELM, record.getHelmPackageId()).toString(); - deployConfigService.update(DeployConfigUpdateReq.builder() + String typeId = new DeployConfigTypeId(ComponentTypeEnum.HELM.toString(), record.getHelmPackageId()).toString(); + deployConfigService.update(DeployConfigUpsertReq.builder() .apiVersion(DefaultConstant.API_VERSION_V1_ALPHA2) .appId(record.getAppId()) .typeId(typeId) @@ -224,7 +224,7 @@ public class HelmMetaServiceImpl implements HelmMetaService { } HelmMetaDO record = this.get(id, namespaceId, stageId); - String typeId = new DeployConfigTypeId(ComponentTypeEnum.HELM, record.getHelmPackageId()).toString(); + String typeId = new DeployConfigTypeId(ComponentTypeEnum.HELM.toString(), record.getHelmPackageId()).toString(); deployConfigService.delete(DeployConfigDeleteReq.builder() .apiVersion(DefaultConstant.API_VERSION_V1_ALPHA2) .appId(record.getAppId()) diff --git a/paas/appmanager/tesla-appmanager-meta-k8s-microservice/pom.xml b/paas/appmanager/tesla-appmanager-meta-k8s-microservice/pom.xml index 825afe13..14b0aa61 100644 --- a/paas/appmanager/tesla-appmanager-meta-k8s-microservice/pom.xml +++ b/paas/appmanager/tesla-appmanager-meta-k8s-microservice/pom.xml @@ -7,7 +7,7 @@ com.alibaba.tesla tesla-appmanager - 1.0.4-SNAPSHOT + 1.0.5-SNAPSHOT ../pom.xml diff --git a/paas/appmanager/tesla-appmanager-meta-k8s-microservice/src/main/java/com/alibaba/tesla/appmanager/meta/k8smicroservice/api/K8sMicroServiceMetaProviderImpl.java b/paas/appmanager/tesla-appmanager-meta-k8s-microservice/src/main/java/com/alibaba/tesla/appmanager/meta/k8smicroservice/api/K8sMicroServiceMetaProviderImpl.java index ea53aa6a..a9309bca 100644 --- a/paas/appmanager/tesla-appmanager-meta-k8s-microservice/src/main/java/com/alibaba/tesla/appmanager/meta/k8smicroservice/api/K8sMicroServiceMetaProviderImpl.java +++ b/paas/appmanager/tesla-appmanager-meta-k8s-microservice/src/main/java/com/alibaba/tesla/appmanager/meta/k8smicroservice/api/K8sMicroServiceMetaProviderImpl.java @@ -20,7 +20,7 @@ import com.alibaba.tesla.appmanager.domain.req.K8sMicroServiceMetaQuickUpdateReq import com.alibaba.tesla.appmanager.domain.req.K8sMicroServiceMetaUpdateByOptionReq; import com.alibaba.tesla.appmanager.domain.req.K8sMicroServiceMetaUpdateReq; import com.alibaba.tesla.appmanager.domain.req.deployconfig.DeployConfigDeleteReq; -import com.alibaba.tesla.appmanager.domain.req.deployconfig.DeployConfigUpdateReq; +import com.alibaba.tesla.appmanager.domain.req.deployconfig.DeployConfigUpsertReq; import com.alibaba.tesla.appmanager.meta.k8smicroservice.assembly.K8sMicroServiceMetaDtoConvert; import com.alibaba.tesla.appmanager.meta.k8smicroservice.repository.condition.K8sMicroserviceMetaQueryCondition; import com.alibaba.tesla.appmanager.meta.k8smicroservice.repository.domain.K8sMicroServiceMetaDO; @@ -111,7 +111,7 @@ public class K8sMicroServiceMetaProviderImpl implements K8sMicroServiceMetaProvi return true; } K8sMicroServiceMetaDTO metaDO = this.get(id); - String typeId = new DeployConfigTypeId(ComponentTypeEnum.K8S_MICROSERVICE, metaDO.getMicroServiceId()).toString(); + String typeId = new DeployConfigTypeId(ComponentTypeEnum.K8S_MICROSERVICE.toString(), metaDO.getMicroServiceId()).toString(); deployConfigService.delete(DeployConfigDeleteReq.builder() .apiVersion(DefaultConstant.API_VERSION_V1_ALPHA2) .appId(metaDO.getAppId()) @@ -305,7 +305,7 @@ public class K8sMicroServiceMetaProviderImpl implements K8sMicroServiceMetaProvi */ private void refreshDeployConfig(K8sMicroServiceMetaDTO dto) { if (StringUtils.isNotEmpty(dto.getProductId()) && StringUtils.isNotEmpty(dto.getReleaseId())) { - deployConfigService.update(DeployConfigUpdateReq.builder() + deployConfigService.update(DeployConfigUpsertReq.builder() .apiVersion(DefaultConstant.API_VERSION_V1_ALPHA2) .appId(dto.getAppId()) .typeId(new DeployConfigTypeId(DeployConfigTypeId.TYPE_PARAMETER_VALUES).toString()) @@ -317,7 +317,7 @@ public class K8sMicroServiceMetaProviderImpl implements K8sMicroServiceMetaProvi .productId(dto.getProductId()) .releaseId(dto.getReleaseId()) .build()); - deployConfigService.update(DeployConfigUpdateReq.builder() + deployConfigService.update(DeployConfigUpsertReq.builder() .apiVersion(DefaultConstant.API_VERSION_V1_ALPHA2) .appId(dto.getAppId()) .typeId(new DeployConfigTypeId(dto.getComponentType(), dto.getMicroServiceId()).toString()) @@ -329,7 +329,7 @@ public class K8sMicroServiceMetaProviderImpl implements K8sMicroServiceMetaProvi .productId(dto.getProductId()) .releaseId(dto.getReleaseId()) .build()); - deployConfigService.update(DeployConfigUpdateReq.builder() + deployConfigService.update(DeployConfigUpsertReq.builder() .apiVersion(DefaultConstant.API_VERSION_V1_ALPHA2) .appId(dto.getAppId()) .typeId(new DeployConfigTypeId(DeployConfigTypeId.TYPE_POLICIES).toString()) @@ -341,7 +341,7 @@ public class K8sMicroServiceMetaProviderImpl implements K8sMicroServiceMetaProvi .productId(dto.getProductId()) .releaseId(dto.getReleaseId()) .build()); - deployConfigService.update(DeployConfigUpdateReq.builder() + deployConfigService.update(DeployConfigUpsertReq.builder() .apiVersion(DefaultConstant.API_VERSION_V1_ALPHA2) .appId(dto.getAppId()) .typeId(new DeployConfigTypeId(DeployConfigTypeId.TYPE_WORKFLOW).toString()) @@ -600,7 +600,7 @@ public class K8sMicroServiceMetaProviderImpl implements K8sMicroServiceMetaProvi traits.add(envTrait); } - String systemTypeId = new DeployConfigTypeId(ComponentTypeEnum.RESOURCE_ADDON, "system-env@system-env").toString(); + String systemTypeId = new DeployConfigTypeId(ComponentTypeEnum.RESOURCE_ADDON.toString(), "system-env@system-env").toString(); List configs = deployConfigService.list( DeployConfigQueryCondition.builder() @@ -629,7 +629,7 @@ public class K8sMicroServiceMetaProviderImpl implements K8sMicroServiceMetaProvi configObject.put("scopes", scopes); Yaml yaml = SchemaUtil.createYaml(JSONObject.class); - String typeId = new DeployConfigTypeId(ComponentTypeEnum.K8S_MICROSERVICE, meta.getMicroServiceId()).toString(); + String typeId = new DeployConfigTypeId(ComponentTypeEnum.K8S_MICROSERVICE.toString(), meta.getMicroServiceId()).toString(); String metaNamespaceId = meta.getNamespaceId(); String metaStageId = meta.getStageId(); // TODO: FOR SREWORKS ONLY TEMPORARY @@ -637,7 +637,7 @@ public class K8sMicroServiceMetaProviderImpl implements K8sMicroServiceMetaProvi metaNamespaceId = EnvUtil.defaultNamespaceId(); metaStageId = EnvUtil.defaultStageId(); } - deployConfigService.update(DeployConfigUpdateReq.builder() + deployConfigService.update(DeployConfigUpsertReq.builder() .apiVersion(DefaultConstant.API_VERSION_V1_ALPHA2) .appId(meta.getAppId()) .typeId(typeId) diff --git a/paas/appmanager/tesla-appmanager-meta-k8s-microservice/src/main/java/com/alibaba/tesla/appmanager/meta/k8smicroservice/assembly/K8sMicroServiceMetaDtoConvert.java b/paas/appmanager/tesla-appmanager-meta-k8s-microservice/src/main/java/com/alibaba/tesla/appmanager/meta/k8smicroservice/assembly/K8sMicroServiceMetaDtoConvert.java index 449db698..b548e46e 100644 --- a/paas/appmanager/tesla-appmanager-meta-k8s-microservice/src/main/java/com/alibaba/tesla/appmanager/meta/k8smicroservice/assembly/K8sMicroServiceMetaDtoConvert.java +++ b/paas/appmanager/tesla-appmanager-meta-k8s-microservice/src/main/java/com/alibaba/tesla/appmanager/meta/k8smicroservice/assembly/K8sMicroServiceMetaDtoConvert.java @@ -13,7 +13,6 @@ import com.alibaba.tesla.appmanager.common.util.ClassUtil; import com.alibaba.tesla.appmanager.common.util.SchemaUtil; import com.alibaba.tesla.appmanager.domain.dto.*; import com.alibaba.tesla.appmanager.meta.k8smicroservice.repository.domain.K8sMicroServiceMetaDO; -import com.google.common.base.Enums; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapUtils; import org.apache.commons.lang3.StringUtils; @@ -219,7 +218,7 @@ public class K8sMicroServiceMetaDtoConvert extends BaseDtoConvert envList, + String componentType, String kind, List envList, List containerObjectDTOList, ImagePushDTO imagePushObject) { JSONObject options = new JSONObject(); options.put("kind", kind); @@ -418,7 +420,8 @@ public class K8sMicroServiceMetaDtoConvert extends BaseDtoConvert containerObjectDTOList, + JSONObject options, String componentType, List containerObjectDTOList, ImagePushDTO imagePushObject) { JSONArray initContainers = new JSONArray(); JSONArray containers = new JSONArray(); @@ -492,7 +495,7 @@ public class K8sMicroServiceMetaDtoConvert extends BaseDtoConvert containerObjectList = request.getContainerObjectList(); - if (request.getComponentType() == ComponentTypeEnum.K8S_MICROSERVICE) { + if (Objects.equals(request.getComponentType(), ComponentTypeEnum.K8S_MICROSERVICE.toString())) { ContainerObjectDTO mainContainer = containerObjectList.stream() .filter(containerObject -> containerObject.getContainerType() == ContainerTypeEnum.CONTAINER) .findFirst() @@ -267,7 +269,7 @@ public class K8sMicroserviceItemController extends AppManagerBaseController { container.setRepo(mainContainer.getRepo()); container.setBranch(mainContainer.getBranch()); }); - } else if (request.getComponentType() == ComponentTypeEnum.K8S_JOB) { + } else if (Objects.equals(request.getComponentType(), ComponentTypeEnum.K8S_JOB.toString())) { if (CollectionUtils.size(containerObjectList) != 1) { throw new AppException(AppErrorCode.INVALID_USER_ARGS, "JOB 缺失"); } diff --git a/paas/appmanager/tesla-appmanager-meta-k8s-microservice/src/main/java/com/alibaba/tesla/appmanager/meta/k8smicroservice/repository/domain/K8sMicroServiceMetaDO.java b/paas/appmanager/tesla-appmanager-meta-k8s-microservice/src/main/java/com/alibaba/tesla/appmanager/meta/k8smicroservice/repository/domain/K8sMicroServiceMetaDO.java index abe1e5ac..e42b6bd4 100644 --- a/paas/appmanager/tesla-appmanager-meta-k8s-microservice/src/main/java/com/alibaba/tesla/appmanager/meta/k8smicroservice/repository/domain/K8sMicroServiceMetaDO.java +++ b/paas/appmanager/tesla-appmanager-meta-k8s-microservice/src/main/java/com/alibaba/tesla/appmanager/meta/k8smicroservice/repository/domain/K8sMicroServiceMetaDO.java @@ -54,7 +54,7 @@ public class K8sMicroServiceMetaDO { /** * 组件类型 */ - private ComponentTypeEnum componentType; + private String componentType; /** * Namespace ID diff --git a/paas/appmanager/tesla-appmanager-meta-k8s-microservice/src/main/java/com/alibaba/tesla/appmanager/meta/k8smicroservice/util/K8sMicroServiceUtil.java b/paas/appmanager/tesla-appmanager-meta-k8s-microservice/src/main/java/com/alibaba/tesla/appmanager/meta/k8smicroservice/util/K8sMicroServiceUtil.java index 3cbf094c..a6357f38 100644 --- a/paas/appmanager/tesla-appmanager-meta-k8s-microservice/src/main/java/com/alibaba/tesla/appmanager/meta/k8smicroservice/util/K8sMicroServiceUtil.java +++ b/paas/appmanager/tesla-appmanager-meta-k8s-microservice/src/main/java/com/alibaba/tesla/appmanager/meta/k8smicroservice/util/K8sMicroServiceUtil.java @@ -22,59 +22,53 @@ public class K8sMicroServiceUtil { * @param branch 实际分支 * @return 修改后的 Options 对象 (build.yaml) */ - public static JSONObject replaceOptionsBranch( - ComponentTypeEnum componentType, String options, String branch, - String dockerRegistry, String dockerNamespace) { + public static JSONObject replaceOptionsBranch(String componentType, String options, String branch, + String dockerRegistry, String dockerNamespace) { Yaml yaml = SchemaUtil.createYaml(JSONObject.class); JSONObject root = yaml.loadAs(options, JSONObject.class); JSONObject optionsJson = root.getJSONObject("options"); optionsJson.putIfAbsent("kind", DefaultConstant.DEFAULT_K8S_MICROSERVICE_KIND); - switch (componentType) { - case K8S_JOB: - JSONObject job = optionsJson.getJSONObject("job"); - if (job != null) { - JSONObject build = job.getJSONObject("build"); + if (ComponentTypeEnum.K8S_JOB.toString().equals(componentType)) { + JSONObject job = optionsJson.getJSONObject("job"); + if (job != null) { + JSONObject build = job.getJSONObject("build"); + if (StringUtils.isNotEmpty(branch)) { + build.put("branch", branch); + } + + if (!build.containsKey("imagePush")) { + addImagePushProperties(build, dockerRegistry, dockerNamespace); + } + } + } else if (ComponentTypeEnum.K8S_MICROSERVICE.toString().equals(componentType)) { + JSONArray containers = optionsJson.getJSONArray("containers"); + if (CollectionUtils.isNotEmpty(containers)) { + for (int i = 0; i < containers.size(); i++) { + JSONObject container = containers.getJSONObject(i); + JSONObject build = container.getJSONObject("build"); if (StringUtils.isNotEmpty(branch)) { build.put("branch", branch); } - if (!build.containsKey("imagePush")) { addImagePushProperties(build, dockerRegistry, dockerNamespace); } } - break; - case K8S_MICROSERVICE: - JSONArray containers = optionsJson.getJSONArray("containers"); - if (CollectionUtils.isNotEmpty(containers)) { - for (int i = 0; i < containers.size(); i++) { - JSONObject container = containers.getJSONObject(i); - JSONObject build = container.getJSONObject("build"); - if (StringUtils.isNotEmpty(branch)) { - build.put("branch", branch); - } - if (!build.containsKey("imagePush")) { - addImagePushProperties(build, dockerRegistry, dockerNamespace); - } - } - } + } - JSONArray initContainers = optionsJson.getJSONArray("initContainers"); - if (CollectionUtils.isNotEmpty(initContainers)) { - for (int i = 0; i < initContainers.size(); i++) { - JSONObject initContainer = initContainers.getJSONObject(i); - JSONObject build = initContainer.getJSONObject("build"); - if (StringUtils.isNotEmpty(branch)) { - build.put("branch", branch); - } - if (!build.containsKey("imagePush")) { - addImagePushProperties(build, dockerRegistry, dockerNamespace); - } + JSONArray initContainers = optionsJson.getJSONArray("initContainers"); + if (CollectionUtils.isNotEmpty(initContainers)) { + for (int i = 0; i < initContainers.size(); i++) { + JSONObject initContainer = initContainers.getJSONObject(i); + JSONObject build = initContainer.getJSONObject("build"); + if (StringUtils.isNotEmpty(branch)) { + build.put("branch", branch); + } + if (!build.containsKey("imagePush")) { + addImagePushProperties(build, dockerRegistry, dockerNamespace); } } - break; - default: - break; + } } return optionsJson; } @@ -82,8 +76,8 @@ public class K8sMicroServiceUtil { /** * 增加 imagePush 配置 * - * @param build 构建对象 - * @param dockerRegistry Docker Registry + * @param build 构建对象 + * @param dockerRegistry Docker Registry * @param dockerNamespace Docker Namespace */ private static void addImagePushProperties(JSONObject build, String dockerRegistry, String dockerNamespace) { diff --git a/paas/appmanager/tesla-appmanager-meta-k8s-microservice/src/test/java/com/alibaba/tesla/appmanager/meta/k8smicroservice/service/TestTransformerDtoToExt.java b/paas/appmanager/tesla-appmanager-meta-k8s-microservice/src/test/java/com/alibaba/tesla/appmanager/meta/k8smicroservice/service/TestTransformerDtoToExt.java index 5602a0ec..b22a600f 100644 --- a/paas/appmanager/tesla-appmanager-meta-k8s-microservice/src/test/java/com/alibaba/tesla/appmanager/meta/k8smicroservice/service/TestTransformerDtoToExt.java +++ b/paas/appmanager/tesla-appmanager-meta-k8s-microservice/src/test/java/com/alibaba/tesla/appmanager/meta/k8smicroservice/service/TestTransformerDtoToExt.java @@ -85,7 +85,7 @@ public class TestTransformerDtoToExt { log.info("meta: {}", JSONObject.toJSONString(meta)); assertThat(meta.getAppId()).isEqualTo(APP_ID); assertThat(meta.getArch()).isEqualTo(ARCH); - assertThat(meta.getComponentType()).isEqualTo(ComponentTypeEnum.K8S_MICROSERVICE); + assertThat(meta.getComponentType()).isEqualTo(ComponentTypeEnum.K8S_MICROSERVICE.toString()); assertThat(meta.getDescription()).isEqualTo(MICROSERVICE_DESCRIPTION); assertThat(meta.getId()).isEqualTo(ID); assertThat(meta.getMicroServiceId()).isEqualTo(MICROSERVICE_ID); @@ -185,7 +185,7 @@ public class TestTransformerDtoToExt { .microServiceId(MICROSERVICE_ID) .name(MICROSERVICE_ID) .description(MICROSERVICE_DESCRIPTION) - .componentType(ComponentTypeEnum.K8S_MICROSERVICE) + .componentType(ComponentTypeEnum.K8S_MICROSERVICE.toString()) .arch(ARCH) .kind("AdvancedStatefulSet") .envList(Collections.singletonList(EnvMetaDTO.builder() diff --git a/paas/appmanager/tesla-appmanager-meta-k8s-microservice/src/test/java/com/alibaba/tesla/appmanager/meta/k8smicroservice/service/TestTransformerExtToDTO.java b/paas/appmanager/tesla-appmanager-meta-k8s-microservice/src/test/java/com/alibaba/tesla/appmanager/meta/k8smicroservice/service/TestTransformerExtToDTO.java index 2da78936..d8d7a4e2 100644 --- a/paas/appmanager/tesla-appmanager-meta-k8s-microservice/src/test/java/com/alibaba/tesla/appmanager/meta/k8smicroservice/service/TestTransformerExtToDTO.java +++ b/paas/appmanager/tesla-appmanager-meta-k8s-microservice/src/test/java/com/alibaba/tesla/appmanager/meta/k8smicroservice/service/TestTransformerExtToDTO.java @@ -136,7 +136,7 @@ public class TestTransformerExtToDto { .microServiceId(MICROSERVICE_ID) .name(MICROSERVICE_ID) .description(MICROSERVICE_DESCRIPTION) - .componentType(ComponentTypeEnum.K8S_MICROSERVICE) + .componentType(ComponentTypeEnum.K8S_MICROSERVICE.toString()) .microServiceExt(MICROSERVICE_EXT) .options("") .build()), Function.identity())) @@ -155,7 +155,7 @@ public class TestTransformerExtToDto { assertThat(meta.getMicroServiceId()).isEqualTo(MICROSERVICE_ID); assertThat(meta.getName()).isEqualTo(MICROSERVICE_ID); assertThat(meta.getDescription()).isEqualTo(MICROSERVICE_DESCRIPTION); - assertThat(meta.getComponentType()).isEqualTo(ComponentTypeEnum.K8S_MICROSERVICE); + assertThat(meta.getComponentType()).isEqualTo(ComponentTypeEnum.K8S_MICROSERVICE.toString()); // 解析部分 assertThat(meta.getKind()).isEqualTo("AdvancedStatefulSet"); diff --git a/paas/appmanager/tesla-appmanager-meta-k8s-microservice/src/test/java/com/alibaba/tesla/appmanager/meta/k8smicroservice/util/TestK8sMicroServiceUtil.java b/paas/appmanager/tesla-appmanager-meta-k8s-microservice/src/test/java/com/alibaba/tesla/appmanager/meta/k8smicroservice/util/TestK8sMicroServiceUtil.java index c2a89d41..2af735e7 100644 --- a/paas/appmanager/tesla-appmanager-meta-k8s-microservice/src/test/java/com/alibaba/tesla/appmanager/meta/k8smicroservice/util/TestK8sMicroServiceUtil.java +++ b/paas/appmanager/tesla-appmanager-meta-k8s-microservice/src/test/java/com/alibaba/tesla/appmanager/meta/k8smicroservice/util/TestK8sMicroServiceUtil.java @@ -44,7 +44,7 @@ public class TestK8sMicroServiceUtil { @Test public void testReplaceOptionsBranch() { JSONObject res = K8sMicroServiceUtil.replaceOptionsBranch( - ComponentTypeEnum.K8S_MICROSERVICE, OPTIONS, "newbranch", "docker.test.com", "testgroup"); + ComponentTypeEnum.K8S_MICROSERVICE.toString(), OPTIONS, "newbranch", "docker.test.com", "testgroup"); log.info("final options: {}", JSONObject.toJSONString(res)); assertThat(res.getJSONArray("containers").getJSONObject(0).getJSONObject("build").getString("branch")).isEqualTo("newbranch"); assertThat(res.getJSONArray("containers").getJSONObject(0).getJSONObject("build").getBoolean("imagePush")).isEqualTo(true); diff --git a/paas/appmanager/tesla-appmanager-plugin/pom.xml b/paas/appmanager/tesla-appmanager-plugin/pom.xml index 2662a5ab..07e2cc3f 100644 --- a/paas/appmanager/tesla-appmanager-plugin/pom.xml +++ b/paas/appmanager/tesla-appmanager-plugin/pom.xml @@ -5,7 +5,8 @@ tesla-appmanager com.alibaba.tesla - 1.0.4-SNAPSHOT + 1.0.5-SNAPSHOT + ../pom.xml 4.0.0 @@ -25,6 +26,10 @@ com.alibaba.tesla tesla-appmanager-common + + com.alibaba.tesla + tesla-appmanager-auth + com.alibaba.tesla tesla-appmanager-api @@ -37,6 +42,14 @@ com.alibaba.tesla tesla-appmanager-dynamic-script + + com.alibaba.tesla + tesla-appmanager-definition + + + com.alibaba.tesla + tesla-appmanager-trait + com.alibaba.tesla tesla-appmanager-spring @@ -62,6 +75,32 @@ org.mybatis.spring.boot mybatis-spring-boot-starter - + + + org.springframework.boot + spring-boot-starter + test + + + org.mockito + mockito-core + test + + + org.assertj + assertj-core + test + + + org.springframework.boot + spring-boot-starter-test + test + + + junit + junit + test + + \ No newline at end of file diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/api/PluginProviderImpl.java b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/api/PluginProviderImpl.java index 7017c841..444e41d2 100644 --- a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/api/PluginProviderImpl.java +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/api/PluginProviderImpl.java @@ -3,11 +3,22 @@ package com.alibaba.tesla.appmanager.plugin.api; import com.alibaba.tesla.appmanager.api.provider.PluginProvider; import com.alibaba.tesla.appmanager.common.exception.AppErrorCode; import com.alibaba.tesla.appmanager.common.exception.AppException; +import com.alibaba.tesla.appmanager.common.pagination.Pagination; +import com.alibaba.tesla.appmanager.common.util.ClassUtil; import com.alibaba.tesla.appmanager.domain.dto.PluginDefinitionDTO; +import com.alibaba.tesla.appmanager.domain.dto.PluginFrontendDTO; +import com.alibaba.tesla.appmanager.domain.req.PluginQueryReq; +import com.alibaba.tesla.appmanager.domain.req.plugin.*; import com.alibaba.tesla.appmanager.plugin.assembly.PluginDefinitionDtoConvert; +import com.alibaba.tesla.appmanager.plugin.assembly.PluginFrontendDtoConvert; +import com.alibaba.tesla.appmanager.plugin.repository.condition.PluginDefinitionQueryCondition; +import com.alibaba.tesla.appmanager.plugin.repository.condition.PluginFrontendQueryCondition; import com.alibaba.tesla.appmanager.plugin.repository.domain.PluginDefinitionDO; -import com.alibaba.tesla.appmanager.plugin.service.PluginDefinitionService; +import com.alibaba.tesla.appmanager.plugin.repository.domain.PluginFrontendDO; +import com.alibaba.tesla.appmanager.plugin.service.PluginFrontendService; +import com.alibaba.tesla.appmanager.plugin.service.PluginService; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; @@ -24,25 +35,98 @@ import java.io.IOException; public class PluginProviderImpl implements PluginProvider { @Autowired - private PluginDefinitionService pluginDefinitionService; + private PluginService pluginService; + + @Autowired + private PluginFrontendService pluginFrontendService; @Autowired private PluginDefinitionDtoConvert pluginDefinitionDtoConvert; + @Autowired + private PluginFrontendDtoConvert pluginFrontendDtoConvert; + + /** + * 获取插件列表 + * + * @param request 查询插件列表请求 + * @return 插件列表 + */ + @Override + public Pagination list(PluginQueryReq request) { + PluginDefinitionQueryCondition condition = new PluginDefinitionQueryCondition(); + ClassUtil.copy(request, condition); + Pagination records = pluginService.list(condition); + return Pagination.transform(records, record -> pluginDefinitionDtoConvert.to(record)); + } + + @Override + public PluginDefinitionDTO get(PluginGetReq request) { + PluginDefinitionQueryCondition condition = new PluginDefinitionQueryCondition(); + ClassUtil.copy(request, condition); + return pluginDefinitionDtoConvert.to(pluginService.get(condition)); + } + + /** + * 启用指定插件 + * + * @param request 插件启用请求 + * @return 开启后的 PluginDefinition 对象 + */ + @Override + public PluginDefinitionDTO enable(PluginEnableReq request) { + PluginDefinitionDO definition = pluginService.enable(request); + return pluginDefinitionDtoConvert.to(definition); + } + + /** + * 关闭指定插件 + * + * @param request 插件关闭请求 + * @return 关闭后的 PluginDefinition 对象 + */ + @Override + public PluginDefinitionDTO disable(PluginDisableReq request) { + PluginDefinitionDO definition = pluginService.disable(request); + return pluginDefinitionDtoConvert.to(definition); + } + /** * 上传插件 (默认不启用) * - * @param file API 上传文件 - * @param force 是否强制上传覆盖 + * @param file API 上传文件 + * @param request 上传插件请求 * @return PluginDefinitionDTO */ @Override - public PluginDefinitionDTO upload(MultipartFile file, boolean force) { + public PluginDefinitionDTO upload(MultipartFile file, PluginUploadReq request) { try { - PluginDefinitionDO definition = pluginDefinitionService.upload(file, force); + PluginDefinitionDO definition = pluginService.upload(file, request.isOverwrite()); + if (request.isEnable()) { + definition = pluginService.enable(PluginEnableReq.builder() + .pluginName(definition.getPluginName()) + .pluginVersion(definition.getPluginVersion()) + .build()); + } return pluginDefinitionDtoConvert.to(definition); } catch (IOException e) { throw new AppException(AppErrorCode.INVALID_USER_ARGS, "upload plugin failed", e); } } + + /** + * 获取 Plugin Frontend 资源 + * + * @param request 获取请求 + * @return PluginFrontend DTO 对象 + */ + @Override + public PluginFrontendDTO getFrontend(PluginFrontendGetReq request) { + PluginFrontendDO frontend = pluginFrontendService.get(PluginFrontendQueryCondition.builder() + .pluginName(request.getPluginName()) + .pluginVersion(request.getPluginVersion()) + .name(request.getName()) + .build()); + return pluginFrontendDtoConvert.to(frontend); + } } diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/assembly/PluginFrontendDtoConvert.java b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/assembly/PluginFrontendDtoConvert.java new file mode 100644 index 00000000..f922e1c3 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/assembly/PluginFrontendDtoConvert.java @@ -0,0 +1,16 @@ +package com.alibaba.tesla.appmanager.plugin.assembly; + +import com.alibaba.tesla.appmanager.common.assembly.BaseDtoConvert; +import com.alibaba.tesla.appmanager.domain.dto.PluginFrontendDTO; +import com.alibaba.tesla.appmanager.plugin.repository.domain.PluginFrontendDO; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +@Slf4j +@Component +public class PluginFrontendDtoConvert extends BaseDtoConvert { + + public PluginFrontendDtoConvert() { + super(PluginFrontendDTO.class, PluginFrontendDO.class); + } +} \ No newline at end of file diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/controller/PluginController.java b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/controller/PluginController.java index 44a61124..49f32082 100644 --- a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/controller/PluginController.java +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/controller/PluginController.java @@ -1,11 +1,18 @@ package com.alibaba.tesla.appmanager.plugin.controller; import com.alibaba.tesla.appmanager.api.provider.PluginProvider; +import com.alibaba.tesla.appmanager.auth.controller.AppManagerBaseController; +import com.alibaba.tesla.appmanager.common.pagination.Pagination; +import com.alibaba.tesla.appmanager.domain.dto.PluginDefinitionDTO; import com.alibaba.tesla.appmanager.domain.req.PluginQueryReq; +import com.alibaba.tesla.appmanager.domain.req.plugin.*; +import com.alibaba.tesla.appmanager.plugin.util.PluginNameGenerator; import com.alibaba.tesla.common.base.TeslaBaseResult; -import com.alibaba.tesla.web.controller.BaseController; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -17,31 +24,109 @@ import java.io.IOException; * @author yaoxing.gyx@alibaba-inc.com */ @Slf4j +@Tag(name = "插件 API") @RequestMapping("/plugins") @RestController -public class PluginController extends BaseController { - +public class PluginController extends AppManagerBaseController { @Autowired private PluginProvider pluginProvider; - /** - * @api {get} /plugins 获取已安装的插件列表 - * @apiName GetPluginList - * @apiGroup 插件API - */ + @Operation(summary = "查询插件列表") @GetMapping - public TeslaBaseResult list(@ModelAttribute PluginQueryReq request) { - return buildSucceedResult(null); + public TeslaBaseResult list(@ModelAttribute PluginQueryReq request, OAuth2Authentication auth) { + return buildSucceedResult(pluginProvider.list(request)); } - /** - * @api {post} /plugins 新增插件 - * @apiName UploadPlugin - * @apiGroup 插件API - */ + @Operation(summary = "查询单个插件") + @GetMapping("{pluginNamePrefix}/{pluginNameSuffix}/{pluginVersion}") + public TeslaBaseResult getPluginInfo( + @PathVariable("pluginNamePrefix") String pluginNamePrefix, + @PathVariable("pluginNameSuffix") String pluginNameSuffix, + @PathVariable("pluginVersion") String pluginVersion, + OAuth2Authentication auth) throws IOException { + String pluginName = PluginNameGenerator.generate(pluginNamePrefix, pluginNameSuffix); + return buildSucceedResult(pluginProvider.get(PluginGetReq.builder() + .pluginName(pluginName) + .pluginVersion(pluginVersion) + .build())); + } + + @Operation(summary = "上传插件") @PostMapping - public TeslaBaseResult upload(@RequestParam("file") MultipartFile file) throws IOException { - return buildSucceedResult(pluginProvider.upload(file, true)); + public TeslaBaseResult upload( + @RequestParam("file") MultipartFile file, + @RequestParam(value = "override", defaultValue = "true") Boolean override, + @RequestParam(value = "enable", defaultValue = "false") Boolean enable, + OAuth2Authentication auth) throws IOException { + return buildSucceedResult(pluginProvider.upload(file, PluginUploadReq.builder() + .enable(enable) + .overwrite(override) + .build())); + } + + @Operation(summary = "操作插件") + @PutMapping("{pluginNamePrefix}/{pluginNameSuffix}/{pluginVersion}/operate") + public TeslaBaseResult operate( + @PathVariable("pluginNamePrefix") String pluginNamePrefix, + @PathVariable("pluginNameSuffix") String pluginNameSuffix, + @PathVariable("pluginVersion") String pluginVersion, + @RequestBody PluginOperateReq request, + OAuth2Authentication auth) throws IOException { + String pluginName = PluginNameGenerator.generate(pluginNamePrefix, pluginNameSuffix); + if ("enable".equals(request.getOperation())) { + PluginDefinitionDTO enablePlugin = pluginProvider.enable(PluginEnableReq.builder() + .pluginName(pluginName) + .pluginVersion(pluginVersion) + .build()); + + /** + * disable all enable plugins with the same pluginName + */ + if (request.getDisableOthers()) { + Pagination pluginList = pluginProvider.list( + PluginQueryReq.builder() + .pluginName(pluginName) + .pluginRegistered(true) + .build() + ); + + for (PluginDefinitionDTO plugin : pluginList.getItems()) { + if (plugin.getPluginName().equals(pluginName) && plugin.getPluginVersion().equals(pluginVersion)) { + continue; + } + pluginProvider.disable(PluginDisableReq.builder() + .pluginName(plugin.getPluginName()) + .pluginVersion(plugin.getPluginVersion()) + .ignoreGroovyFiles(true) + .build()); + } + } + + return buildSucceedResult(enablePlugin); + } else if ("disable".equals(request.getOperation())) { + return buildSucceedResult(pluginProvider.disable(PluginDisableReq.builder() + .pluginName(pluginName) + .pluginVersion(pluginVersion) + .build())); + } else { + return buildClientErrorResult("invalid plugin operation"); + } + } + + @Operation(summary = "获取插件前端资源") + @GetMapping("{pluginNamePrefix}/{pluginNameSuffix}/{pluginVersion}/frontend/{name}") + public TeslaBaseResult getPluginFrontend( + @PathVariable("pluginNamePrefix") String pluginNamePrefix, + @PathVariable("pluginNameSuffix") String pluginNameSuffix, + @PathVariable("pluginVersion") String pluginVersion, + @PathVariable("name") String name, + OAuth2Authentication auth) throws IOException { + String pluginName = PluginNameGenerator.generate(pluginNamePrefix, pluginNameSuffix); + return buildSucceedResult(pluginProvider.getFrontend(PluginFrontendGetReq.builder() + .pluginName(pluginName) + .pluginVersion(pluginVersion) + .name(name) + .build())); } } \ No newline at end of file diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/PluginDefinitionRepository.java b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/PluginDefinitionRepository.java index 73171322..725eb685 100644 --- a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/PluginDefinitionRepository.java +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/PluginDefinitionRepository.java @@ -1,9 +1,21 @@ package com.alibaba.tesla.appmanager.plugin.repository; +import com.alibaba.tesla.appmanager.plugin.repository.condition.PluginDefinitionQueryCondition; import com.alibaba.tesla.appmanager.plugin.repository.domain.PluginDefinitionDO; +import java.util.List; + public interface PluginDefinitionRepository { + long countByCondition(PluginDefinitionQueryCondition condition); + + int deleteByCondition(PluginDefinitionQueryCondition condition); + int insert(PluginDefinitionDO record); + List selectByCondition(PluginDefinitionQueryCondition condition); + + PluginDefinitionDO getByCondition(PluginDefinitionQueryCondition condition); + + int updateByCondition(PluginDefinitionDO record, PluginDefinitionQueryCondition condition); } diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/PluginFrontendRepository.java b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/PluginFrontendRepository.java new file mode 100644 index 00000000..f42cb506 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/PluginFrontendRepository.java @@ -0,0 +1,21 @@ +package com.alibaba.tesla.appmanager.plugin.repository; + +import com.alibaba.tesla.appmanager.plugin.repository.condition.PluginFrontendQueryCondition; +import com.alibaba.tesla.appmanager.plugin.repository.domain.PluginFrontendDO; + +import java.util.List; + +public interface PluginFrontendRepository { + + long countByCondition(PluginFrontendQueryCondition condition); + + int deleteByCondition(PluginFrontendQueryCondition condition); + + int insert(PluginFrontendDO record); + + List selectByCondition(PluginFrontendQueryCondition condition); + + PluginFrontendDO getByCondition(PluginFrontendQueryCondition condition); + + int updateByCondition(PluginFrontendDO record, PluginFrontendQueryCondition condition); +} diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/PluginResourceRepository.java b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/PluginResourceRepository.java new file mode 100644 index 00000000..a746d803 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/PluginResourceRepository.java @@ -0,0 +1,21 @@ +package com.alibaba.tesla.appmanager.plugin.repository; + +import com.alibaba.tesla.appmanager.plugin.repository.condition.PluginResourceQueryCondition; +import com.alibaba.tesla.appmanager.plugin.repository.domain.PluginResourceDO; + +import java.util.List; + +public interface PluginResourceRepository { + + long countByCondition(PluginResourceQueryCondition condition); + + int deleteByCondition(PluginResourceQueryCondition condition); + + int insert(PluginResourceDO record); + + List selectByCondition(PluginResourceQueryCondition condition); + + PluginResourceDO getByCondition(PluginResourceQueryCondition condition); + + int updateByCondition(PluginResourceDO record, PluginResourceQueryCondition condition); +} diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/PluginResourceWorkflowRelRepository.java b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/PluginResourceWorkflowRelRepository.java new file mode 100644 index 00000000..17312a53 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/PluginResourceWorkflowRelRepository.java @@ -0,0 +1,21 @@ +package com.alibaba.tesla.appmanager.plugin.repository; + +import com.alibaba.tesla.appmanager.plugin.repository.condition.PluginResourceWorkflowRelQueryCondition; +import com.alibaba.tesla.appmanager.plugin.repository.domain.PluginResourceWorkflowRelDO; + +import java.util.List; + +public interface PluginResourceWorkflowRelRepository { + + long countByCondition(PluginResourceWorkflowRelQueryCondition condition); + + int deleteByCondition(PluginResourceWorkflowRelQueryCondition condition); + + int insert(PluginResourceWorkflowRelDO record); + + List selectByCondition(PluginResourceWorkflowRelQueryCondition condition); + + PluginResourceWorkflowRelDO getByCondition(PluginResourceWorkflowRelQueryCondition condition); + + int updateByCondition(PluginResourceWorkflowRelDO record, PluginResourceWorkflowRelQueryCondition condition); +} diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/PluginTagRepository.java b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/PluginTagRepository.java new file mode 100644 index 00000000..6049e067 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/PluginTagRepository.java @@ -0,0 +1,21 @@ +package com.alibaba.tesla.appmanager.plugin.repository; + +import com.alibaba.tesla.appmanager.plugin.repository.condition.PluginTagQueryCondition; +import com.alibaba.tesla.appmanager.plugin.repository.domain.PluginTagDO; + +import java.util.List; + +public interface PluginTagRepository { + + long countByCondition(PluginTagQueryCondition condition); + + int deleteByCondition(PluginTagQueryCondition condition); + + int insert(PluginTagDO record); + + List selectByCondition(PluginTagQueryCondition condition); + + PluginTagDO getByCondition(PluginTagQueryCondition condition); + + int updateByCondition(PluginTagDO record, PluginTagQueryCondition condition); +} diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/condition/PluginDefinitionQueryCondition.java b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/condition/PluginDefinitionQueryCondition.java new file mode 100644 index 00000000..fad1a63a --- /dev/null +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/condition/PluginDefinitionQueryCondition.java @@ -0,0 +1,24 @@ +package com.alibaba.tesla.appmanager.plugin.repository.condition; + +import com.alibaba.tesla.appmanager.common.BaseCondition; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * Plugin Definition 查询条件 + * + * @author yaoxing.gyx@alibaba-inc.com + */ +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public class PluginDefinitionQueryCondition extends BaseCondition { + + private String pluginKind; + private String pluginName; + private String pluginVersion; + private Boolean pluginRegistered; +} diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/condition/PluginFrontendQueryCondition.java b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/condition/PluginFrontendQueryCondition.java new file mode 100644 index 00000000..c167f1ee --- /dev/null +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/condition/PluginFrontendQueryCondition.java @@ -0,0 +1,23 @@ +package com.alibaba.tesla.appmanager.plugin.repository.condition; + +import com.alibaba.tesla.appmanager.common.BaseCondition; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * Plugin Frontend 查询条件 + * + * @author yaoxing.gyx@alibaba-inc.com + */ +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public class PluginFrontendQueryCondition extends BaseCondition { + + private String pluginName; + private String pluginVersion; + private String name; +} diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/condition/PluginResourceQueryCondition.java b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/condition/PluginResourceQueryCondition.java new file mode 100644 index 00000000..ee3d9287 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/condition/PluginResourceQueryCondition.java @@ -0,0 +1,25 @@ +package com.alibaba.tesla.appmanager.plugin.repository.condition; + +import com.alibaba.tesla.appmanager.common.BaseCondition; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * Plugin Resource 查询条件 + * + * @author yaoxing.gyx@alibaba-inc.com + */ +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public class PluginResourceQueryCondition extends BaseCondition { + + private String pluginName; + private String pluginVersion; + private String clusterId; + private String instanceStatus; + private Boolean instanceRegistered; +} diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/condition/PluginResourceWorkflowRelQueryCondition.java b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/condition/PluginResourceWorkflowRelQueryCondition.java new file mode 100644 index 00000000..fbd5327f --- /dev/null +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/condition/PluginResourceWorkflowRelQueryCondition.java @@ -0,0 +1,23 @@ +package com.alibaba.tesla.appmanager.plugin.repository.condition; + +import com.alibaba.tesla.appmanager.common.BaseCondition; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * Plugin Resource 关联 Workflow 查询条件 + * + * @author yaoxing.gyx@alibaba-inc.com + */ +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public class PluginResourceWorkflowRelQueryCondition extends BaseCondition { + + private Long pluginResourceId; + private String clusterId; + private String workflowType; +} diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/condition/PluginTagQueryCondition.java b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/condition/PluginTagQueryCondition.java new file mode 100644 index 00000000..a6c44391 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/condition/PluginTagQueryCondition.java @@ -0,0 +1,21 @@ +package com.alibaba.tesla.appmanager.plugin.repository.condition; + +import com.alibaba.tesla.appmanager.common.BaseCondition; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * Plugin Tag 查询条件 + * + * @author yaoxing.gyx@alibaba-inc.com + */ +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public class PluginTagQueryCondition extends BaseCondition { + + private Long pluginId; +} diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/domain/PluginResourceDO.java b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/domain/PluginResourceDO.java index 46e3114e..a6447ce3 100644 --- a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/domain/PluginResourceDO.java +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/domain/PluginResourceDO.java @@ -33,10 +33,10 @@ public class PluginResourceDO { /** * Plugin 唯一标识 */ - private Long pluginName; + private String pluginName; /** - * Plugin 版本 + * Plugin 版本 (SemVer) */ private String pluginVersion; diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/domain/PluginResourceDOExample.java b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/domain/PluginResourceDOExample.java index 34bbf32e..6d328b74 100644 --- a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/domain/PluginResourceDOExample.java +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/domain/PluginResourceDOExample.java @@ -295,52 +295,62 @@ public class PluginResourceDOExample { return (Criteria) this; } - public Criteria andPluginNameEqualTo(Long value) { + public Criteria andPluginNameEqualTo(String value) { addCriterion("plugin_name =", value, "pluginName"); return (Criteria) this; } - public Criteria andPluginNameNotEqualTo(Long value) { + public Criteria andPluginNameNotEqualTo(String value) { addCriterion("plugin_name <>", value, "pluginName"); return (Criteria) this; } - public Criteria andPluginNameGreaterThan(Long value) { + public Criteria andPluginNameGreaterThan(String value) { addCriterion("plugin_name >", value, "pluginName"); return (Criteria) this; } - public Criteria andPluginNameGreaterThanOrEqualTo(Long value) { + public Criteria andPluginNameGreaterThanOrEqualTo(String value) { addCriterion("plugin_name >=", value, "pluginName"); return (Criteria) this; } - public Criteria andPluginNameLessThan(Long value) { + public Criteria andPluginNameLessThan(String value) { addCriterion("plugin_name <", value, "pluginName"); return (Criteria) this; } - public Criteria andPluginNameLessThanOrEqualTo(Long value) { + public Criteria andPluginNameLessThanOrEqualTo(String value) { addCriterion("plugin_name <=", value, "pluginName"); return (Criteria) this; } - public Criteria andPluginNameIn(List values) { + public Criteria andPluginNameLike(String value) { + addCriterion("plugin_name like", value, "pluginName"); + return (Criteria) this; + } + + public Criteria andPluginNameNotLike(String value) { + addCriterion("plugin_name not like", value, "pluginName"); + return (Criteria) this; + } + + public Criteria andPluginNameIn(List values) { addCriterion("plugin_name in", values, "pluginName"); return (Criteria) this; } - public Criteria andPluginNameNotIn(List values) { + public Criteria andPluginNameNotIn(List values) { addCriterion("plugin_name not in", values, "pluginName"); return (Criteria) this; } - public Criteria andPluginNameBetween(Long value1, Long value2) { + public Criteria andPluginNameBetween(String value1, String value2) { addCriterion("plugin_name between", value1, value2, "pluginName"); return (Criteria) this; } - public Criteria andPluginNameNotBetween(Long value1, Long value2) { + public Criteria andPluginNameNotBetween(String value1, String value2) { addCriterion("plugin_name not between", value1, value2, "pluginName"); return (Criteria) this; } diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/impl/PluginDefinitionRepositoryImpl.java b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/impl/PluginDefinitionRepositoryImpl.java index d34bc0d0..99721164 100644 --- a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/impl/PluginDefinitionRepositoryImpl.java +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/impl/PluginDefinitionRepositoryImpl.java @@ -1,14 +1,21 @@ package com.alibaba.tesla.appmanager.plugin.repository.impl; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.tesla.appmanager.common.exception.AppErrorCode; +import com.alibaba.tesla.appmanager.common.exception.AppException; import com.alibaba.tesla.appmanager.common.util.DateUtil; import com.alibaba.tesla.appmanager.plugin.repository.PluginDefinitionRepository; +import com.alibaba.tesla.appmanager.plugin.repository.condition.PluginDefinitionQueryCondition; import com.alibaba.tesla.appmanager.plugin.repository.domain.PluginDefinitionDO; +import com.alibaba.tesla.appmanager.plugin.repository.domain.PluginDefinitionDOExample; import com.alibaba.tesla.appmanager.plugin.repository.mapper.PluginDefinitionDOMapper; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.Date; +import java.util.List; /** * Plugin Repository @@ -20,11 +27,67 @@ import java.util.Date; public class PluginDefinitionRepositoryImpl implements PluginDefinitionRepository { @Autowired - private PluginDefinitionDOMapper mapper; + private PluginDefinitionDOMapper pluginDefinitionDOMapper; + + @Override + public long countByCondition(PluginDefinitionQueryCondition condition) { + return pluginDefinitionDOMapper.countByExample(buildExample(condition)); + } + + @Override + public int deleteByCondition(PluginDefinitionQueryCondition condition) { + return pluginDefinitionDOMapper.deleteByExample(buildExample(condition)); + } @Override public int insert(PluginDefinitionDO record) { - return mapper.insertSelective(insertDate(record)); + return pluginDefinitionDOMapper.insertSelective(insertDate(record)); + } + + @Override + public List selectByCondition(PluginDefinitionQueryCondition condition) { + if (condition.isWithBlobs()) { + return pluginDefinitionDOMapper.selectByExampleWithBLOBs(buildExample(condition)); + } else { + return pluginDefinitionDOMapper.selectByExample(buildExample(condition)); + } + } + + @Override + public PluginDefinitionDO getByCondition(PluginDefinitionQueryCondition condition) { + condition.setWithBlobs(true); + List records = selectByCondition(condition); + if (records.size() == 0) { + return null; + } else if (records.size() > 1) { + throw new AppException(AppErrorCode.UNKNOWN_ERROR, + "multiple plugin definition found|%s", JSONObject.toJSONString(condition)); + } else { + return records.get(0); + } + } + + @Override + public int updateByCondition(PluginDefinitionDO record, PluginDefinitionQueryCondition condition) { + return pluginDefinitionDOMapper.updateByExampleSelective(updateDate(record), buildExample(condition)); + } + + private PluginDefinitionDOExample buildExample(PluginDefinitionQueryCondition condition) { + PluginDefinitionDOExample example = new PluginDefinitionDOExample(); + PluginDefinitionDOExample.Criteria criteria = example.createCriteria(); + if (StringUtils.isNotBlank(condition.getPluginKind())) { + criteria.andPluginKindEqualTo(condition.getPluginKind()); + } + if (StringUtils.isNotBlank(condition.getPluginName())) { + criteria.andPluginNameEqualTo(condition.getPluginName()); + } + if (StringUtils.isNotBlank(condition.getPluginVersion())) { + criteria.andPluginVersionEqualTo(condition.getPluginVersion()); + } + if (condition.getPluginRegistered() != null) { + criteria.andPluginRegisteredEqualTo(condition.getPluginRegistered()); + } + return example; } private PluginDefinitionDO insertDate(PluginDefinitionDO record) { @@ -33,4 +96,10 @@ public class PluginDefinitionRepositoryImpl implements PluginDefinitionRepositor record.setGmtModified(now); return record; } + + private PluginDefinitionDO updateDate(PluginDefinitionDO record) { + Date now = DateUtil.now(); + record.setGmtModified(now); + return record; + } } diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/impl/PluginFrontendRepositoryImpl.java b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/impl/PluginFrontendRepositoryImpl.java new file mode 100644 index 00000000..699c4dcd --- /dev/null +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/impl/PluginFrontendRepositoryImpl.java @@ -0,0 +1,97 @@ +package com.alibaba.tesla.appmanager.plugin.repository.impl; + +import com.alibaba.fastjson.JSONObject; +import com.alibaba.tesla.appmanager.common.exception.AppErrorCode; +import com.alibaba.tesla.appmanager.common.exception.AppException; +import com.alibaba.tesla.appmanager.common.util.DateUtil; +import com.alibaba.tesla.appmanager.plugin.repository.PluginFrontendRepository; +import com.alibaba.tesla.appmanager.plugin.repository.condition.PluginFrontendQueryCondition; +import com.alibaba.tesla.appmanager.plugin.repository.domain.PluginFrontendDO; +import com.alibaba.tesla.appmanager.plugin.repository.domain.PluginFrontendDOExample; +import com.alibaba.tesla.appmanager.plugin.repository.mapper.PluginFrontendDOMapper; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Date; +import java.util.List; + +/** + * Plugin Frontend Repository + * + * @author yaoxing.gyx@alibaba-inc.com + */ +@Service +@Slf4j +public class PluginFrontendRepositoryImpl implements PluginFrontendRepository { + + @Autowired + private PluginFrontendDOMapper mapper; + + @Override + public long countByCondition(PluginFrontendQueryCondition condition) { + return mapper.countByExample(buildExample(condition)); + } + + @Override + public int deleteByCondition(PluginFrontendQueryCondition condition) { + return mapper.deleteByExample(buildExample(condition)); + } + + @Override + public int insert(PluginFrontendDO record) { + return mapper.insertSelective(insertDate(record)); + } + + @Override + public List selectByCondition(PluginFrontendQueryCondition condition) { + return mapper.selectByExample(buildExample(condition)); + } + + @Override + public PluginFrontendDO getByCondition(PluginFrontendQueryCondition condition) { + List records = selectByCondition(condition); + if (records.size() == 0) { + return null; + } else if (records.size() > 1) { + throw new AppException(AppErrorCode.UNKNOWN_ERROR, + "multiple plugin definition found|%s", JSONObject.toJSONString(condition)); + } else { + return records.get(0); + } + } + + @Override + public int updateByCondition(PluginFrontendDO record, PluginFrontendQueryCondition condition) { + return mapper.updateByExampleSelective(updateDate(record), buildExample(condition)); + } + + private PluginFrontendDOExample buildExample(PluginFrontendQueryCondition condition) { + PluginFrontendDOExample example = new PluginFrontendDOExample(); + PluginFrontendDOExample.Criteria criteria = example.createCriteria(); + if (StringUtils.isNotBlank(condition.getPluginName())) { + criteria.andPluginNameEqualTo(condition.getPluginName()); + } + if (StringUtils.isNotBlank(condition.getPluginVersion())) { + criteria.andPluginVersionEqualTo(condition.getPluginVersion()); + } + if (StringUtils.isNotBlank(condition.getName())) { + criteria.andNameEqualTo(condition.getName()); + } + return example; + } + + private PluginFrontendDO insertDate(PluginFrontendDO record) { + Date now = DateUtil.now(); + record.setGmtCreate(now); + record.setGmtModified(now); + return record; + } + + private PluginFrontendDO updateDate(PluginFrontendDO record) { + Date now = DateUtil.now(); + record.setGmtModified(now); + return record; + } +} diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/impl/PluginResourceRepositoryImpl.java b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/impl/PluginResourceRepositoryImpl.java new file mode 100644 index 00000000..d22603d0 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/impl/PluginResourceRepositoryImpl.java @@ -0,0 +1,103 @@ +package com.alibaba.tesla.appmanager.plugin.repository.impl; + +import com.alibaba.fastjson.JSONObject; +import com.alibaba.tesla.appmanager.common.exception.AppErrorCode; +import com.alibaba.tesla.appmanager.common.exception.AppException; +import com.alibaba.tesla.appmanager.common.util.DateUtil; +import com.alibaba.tesla.appmanager.plugin.repository.PluginResourceRepository; +import com.alibaba.tesla.appmanager.plugin.repository.condition.PluginResourceQueryCondition; +import com.alibaba.tesla.appmanager.plugin.repository.domain.PluginResourceDO; +import com.alibaba.tesla.appmanager.plugin.repository.domain.PluginResourceDOExample; +import com.alibaba.tesla.appmanager.plugin.repository.mapper.PluginResourceDOMapper; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Date; +import java.util.List; + +/** + * Plugin Resource Repository + * + * @author yaoxing.gyx@alibaba-inc.com + */ +@Service +@Slf4j +public class PluginResourceRepositoryImpl implements PluginResourceRepository { + + @Autowired + private PluginResourceDOMapper mapper; + + @Override + public long countByCondition(PluginResourceQueryCondition condition) { + return mapper.countByExample(buildExample(condition)); + } + + @Override + public int deleteByCondition(PluginResourceQueryCondition condition) { + return mapper.deleteByExample(buildExample(condition)); + } + + @Override + public int insert(PluginResourceDO record) { + return mapper.insertSelective(insertDate(record)); + } + + @Override + public List selectByCondition(PluginResourceQueryCondition condition) { + return mapper.selectByExample(buildExample(condition)); + } + + @Override + public PluginResourceDO getByCondition(PluginResourceQueryCondition condition) { + List records = selectByCondition(condition); + if (records.size() == 0) { + return null; + } else if (records.size() > 1) { + throw new AppException(AppErrorCode.UNKNOWN_ERROR, + "multiple plugin definition found|%s", JSONObject.toJSONString(condition)); + } else { + return records.get(0); + } + } + + @Override + public int updateByCondition(PluginResourceDO record, PluginResourceQueryCondition condition) { + return mapper.updateByExampleSelective(updateDate(record), buildExample(condition)); + } + + private PluginResourceDOExample buildExample(PluginResourceQueryCondition condition) { + PluginResourceDOExample example = new PluginResourceDOExample(); + PluginResourceDOExample.Criteria criteria = example.createCriteria(); + if (StringUtils.isNotBlank(condition.getPluginName())) { + criteria.andPluginNameEqualTo(condition.getPluginName()); + } + if (StringUtils.isNotBlank(condition.getPluginVersion())) { + criteria.andPluginVersionEqualTo(condition.getPluginVersion()); + } + if (StringUtils.isNotBlank(condition.getClusterId())) { + criteria.andClusterIdEqualTo(condition.getClusterId()); + } + if (StringUtils.isNotBlank(condition.getInstanceStatus())) { + criteria.andInstanceStatusEqualTo(condition.getInstanceStatus()); + } + if (condition.getInstanceRegistered() != null) { + criteria.andInstanceRegisteredEqualTo(condition.getInstanceRegistered()); + } + return example; + } + + private PluginResourceDO insertDate(PluginResourceDO record) { + Date now = DateUtil.now(); + record.setGmtCreate(now); + record.setGmtModified(now); + return record; + } + + private PluginResourceDO updateDate(PluginResourceDO record) { + Date now = DateUtil.now(); + record.setGmtModified(now); + return record; + } +} diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/impl/PluginResourceWorkflowRelRepositoryImpl.java b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/impl/PluginResourceWorkflowRelRepositoryImpl.java new file mode 100644 index 00000000..5ccc0db4 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/impl/PluginResourceWorkflowRelRepositoryImpl.java @@ -0,0 +1,97 @@ +package com.alibaba.tesla.appmanager.plugin.repository.impl; + +import com.alibaba.fastjson.JSONObject; +import com.alibaba.tesla.appmanager.common.exception.AppErrorCode; +import com.alibaba.tesla.appmanager.common.exception.AppException; +import com.alibaba.tesla.appmanager.common.util.DateUtil; +import com.alibaba.tesla.appmanager.plugin.repository.PluginResourceWorkflowRelRepository; +import com.alibaba.tesla.appmanager.plugin.repository.condition.PluginResourceWorkflowRelQueryCondition; +import com.alibaba.tesla.appmanager.plugin.repository.domain.PluginResourceWorkflowRelDO; +import com.alibaba.tesla.appmanager.plugin.repository.domain.PluginResourceWorkflowRelDOExample; +import com.alibaba.tesla.appmanager.plugin.repository.mapper.PluginResourceWorkflowRelDOMapper; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Date; +import java.util.List; + +/** + * Plugin Workflow Rel Repository + * + * @author yaoxing.gyx@alibaba-inc.com + */ +@Service +@Slf4j +public class PluginResourceWorkflowRelRepositoryImpl implements PluginResourceWorkflowRelRepository { + + @Autowired + private PluginResourceWorkflowRelDOMapper mapper; + + @Override + public long countByCondition(PluginResourceWorkflowRelQueryCondition condition) { + return mapper.countByExample(buildExample(condition)); + } + + @Override + public int deleteByCondition(PluginResourceWorkflowRelQueryCondition condition) { + return mapper.deleteByExample(buildExample(condition)); + } + + @Override + public int insert(PluginResourceWorkflowRelDO record) { + return mapper.insertSelective(insertDate(record)); + } + + @Override + public List selectByCondition(PluginResourceWorkflowRelQueryCondition condition) { + return mapper.selectByExample(buildExample(condition)); + } + + @Override + public PluginResourceWorkflowRelDO getByCondition(PluginResourceWorkflowRelQueryCondition condition) { + List records = selectByCondition(condition); + if (records.size() == 0) { + return null; + } else if (records.size() > 1) { + throw new AppException(AppErrorCode.UNKNOWN_ERROR, + "multiple plugin definition found|%s", JSONObject.toJSONString(condition)); + } else { + return records.get(0); + } + } + + @Override + public int updateByCondition(PluginResourceWorkflowRelDO record, PluginResourceWorkflowRelQueryCondition condition) { + return mapper.updateByExampleSelective(updateDate(record), buildExample(condition)); + } + + private PluginResourceWorkflowRelDOExample buildExample(PluginResourceWorkflowRelQueryCondition condition) { + PluginResourceWorkflowRelDOExample example = new PluginResourceWorkflowRelDOExample(); + PluginResourceWorkflowRelDOExample.Criteria criteria = example.createCriteria(); + if (condition.getPluginResourceId() != null && condition.getPluginResourceId() > 0) { + criteria.andPluginResourceIdEqualTo(condition.getPluginResourceId()); + } + if (StringUtils.isNotBlank(condition.getClusterId())) { + criteria.andClusterIdEqualTo(condition.getClusterId()); + } + if (StringUtils.isNotBlank(condition.getWorkflowType())) { + criteria.andWorkflowTypeEqualTo(condition.getWorkflowType()); + } + return example; + } + + private PluginResourceWorkflowRelDO insertDate(PluginResourceWorkflowRelDO record) { + Date now = DateUtil.now(); + record.setGmtCreate(now); + record.setGmtModified(now); + return record; + } + + private PluginResourceWorkflowRelDO updateDate(PluginResourceWorkflowRelDO record) { + Date now = DateUtil.now(); + record.setGmtModified(now); + return record; + } +} diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/impl/PluginTagRepositoryImpl.java b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/impl/PluginTagRepositoryImpl.java new file mode 100644 index 00000000..d11022bb --- /dev/null +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/impl/PluginTagRepositoryImpl.java @@ -0,0 +1,90 @@ +package com.alibaba.tesla.appmanager.plugin.repository.impl; + +import com.alibaba.fastjson.JSONObject; +import com.alibaba.tesla.appmanager.common.exception.AppErrorCode; +import com.alibaba.tesla.appmanager.common.exception.AppException; +import com.alibaba.tesla.appmanager.common.util.DateUtil; +import com.alibaba.tesla.appmanager.plugin.repository.PluginTagRepository; +import com.alibaba.tesla.appmanager.plugin.repository.condition.PluginTagQueryCondition; +import com.alibaba.tesla.appmanager.plugin.repository.domain.PluginTagDO; +import com.alibaba.tesla.appmanager.plugin.repository.domain.PluginTagDOExample; +import com.alibaba.tesla.appmanager.plugin.repository.mapper.PluginTagDOMapper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Date; +import java.util.List; + +/** + * Plugin Tag Repository + * + * @author yaoxing.gyx@alibaba-inc.com + */ +@Service +@Slf4j +public class PluginTagRepositoryImpl implements PluginTagRepository { + + @Autowired + private PluginTagDOMapper mapper; + + @Override + public long countByCondition(PluginTagQueryCondition condition) { + return mapper.countByExample(buildExample(condition)); + } + + @Override + public int deleteByCondition(PluginTagQueryCondition condition) { + return mapper.deleteByExample(buildExample(condition)); + } + + @Override + public int insert(PluginTagDO record) { + return mapper.insertSelective(insertDate(record)); + } + + @Override + public List selectByCondition(PluginTagQueryCondition condition) { + return mapper.selectByExample(buildExample(condition)); + } + + @Override + public PluginTagDO getByCondition(PluginTagQueryCondition condition) { + List records = selectByCondition(condition); + if (records.size() == 0) { + return null; + } else if (records.size() > 1) { + throw new AppException(AppErrorCode.UNKNOWN_ERROR, + "multiple plugin definition found|%s", JSONObject.toJSONString(condition)); + } else { + return records.get(0); + } + } + + @Override + public int updateByCondition(PluginTagDO record, PluginTagQueryCondition condition) { + return mapper.updateByExampleSelective(updateDate(record), buildExample(condition)); + } + + private PluginTagDOExample buildExample(PluginTagQueryCondition condition) { + PluginTagDOExample example = new PluginTagDOExample(); + PluginTagDOExample.Criteria criteria = example.createCriteria(); + if (condition.getPluginId() != null && condition.getPluginId() > 0) { + criteria.andPluginIdEqualTo(condition.getPluginId()); + } + return example; + } + + private PluginTagDO insertDate(PluginTagDO record) { + Date now = DateUtil.now(); + record.setGmtCreate(now); + record.setGmtModified(now); + return record; + } + + private PluginTagDO updateDate(PluginTagDO record) { + Date now = DateUtil.now(); + record.setGmtModified(now); + return record; + } +} diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/mapper/PluginDefinitionDOMapper.java b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/mapper/PluginDefinitionDOMapper.java index ae858495..474ad1ed 100644 --- a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/mapper/PluginDefinitionDOMapper.java +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/mapper/PluginDefinitionDOMapper.java @@ -13,27 +13,13 @@ public interface PluginDefinitionDOMapper { int deleteByExample(PluginDefinitionDOExample example); - int deleteByPrimaryKey(Long id); - - int insert(PluginDefinitionDO record); - int insertSelective(PluginDefinitionDO record); List selectByExampleWithBLOBs(PluginDefinitionDOExample example); List selectByExample(PluginDefinitionDOExample example); - PluginDefinitionDO selectByPrimaryKey(Long id); + List selectGroupByKindNameVersion(PluginDefinitionDOExample example); int updateByExampleSelective(@Param("record") PluginDefinitionDO record, @Param("example") PluginDefinitionDOExample example); - - int updateByExampleWithBLOBs(@Param("record") PluginDefinitionDO record, @Param("example") PluginDefinitionDOExample example); - - int updateByExample(@Param("record") PluginDefinitionDO record, @Param("example") PluginDefinitionDOExample example); - - int updateByPrimaryKeySelective(PluginDefinitionDO record); - - int updateByPrimaryKeyWithBLOBs(PluginDefinitionDO record); - - int updateByPrimaryKey(PluginDefinitionDO record); } \ No newline at end of file diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/mapper/PluginFrontendDOMapper.java b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/mapper/PluginFrontendDOMapper.java index 91e4d600..92107566 100644 --- a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/mapper/PluginFrontendDOMapper.java +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/mapper/PluginFrontendDOMapper.java @@ -13,21 +13,9 @@ public interface PluginFrontendDOMapper { int deleteByExample(PluginFrontendDOExample example); - int deleteByPrimaryKey(Long id); - - int insert(PluginFrontendDO record); - int insertSelective(PluginFrontendDO record); List selectByExample(PluginFrontendDOExample example); - PluginFrontendDO selectByPrimaryKey(Long id); - int updateByExampleSelective(@Param("record") PluginFrontendDO record, @Param("example") PluginFrontendDOExample example); - - int updateByExample(@Param("record") PluginFrontendDO record, @Param("example") PluginFrontendDOExample example); - - int updateByPrimaryKeySelective(PluginFrontendDO record); - - int updateByPrimaryKey(PluginFrontendDO record); } \ No newline at end of file diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/mapper/PluginResourceDOMapper.java b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/mapper/PluginResourceDOMapper.java index 9bba20ae..e5d42fe8 100644 --- a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/mapper/PluginResourceDOMapper.java +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/mapper/PluginResourceDOMapper.java @@ -2,31 +2,20 @@ package com.alibaba.tesla.appmanager.plugin.repository.mapper; import com.alibaba.tesla.appmanager.plugin.repository.domain.PluginResourceDO; import com.alibaba.tesla.appmanager.plugin.repository.domain.PluginResourceDOExample; -import java.util.List; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; +import java.util.List; + @Mapper public interface PluginResourceDOMapper { long countByExample(PluginResourceDOExample example); int deleteByExample(PluginResourceDOExample example); - int deleteByPrimaryKey(Long id); - - int insert(PluginResourceDO record); - int insertSelective(PluginResourceDO record); List selectByExample(PluginResourceDOExample example); - PluginResourceDO selectByPrimaryKey(Long id); - int updateByExampleSelective(@Param("record") PluginResourceDO record, @Param("example") PluginResourceDOExample example); - - int updateByExample(@Param("record") PluginResourceDO record, @Param("example") PluginResourceDOExample example); - - int updateByPrimaryKeySelective(PluginResourceDO record); - - int updateByPrimaryKey(PluginResourceDO record); } \ No newline at end of file diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/mapper/PluginResourceWorkflowRelDOMapper.java b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/mapper/PluginResourceWorkflowRelDOMapper.java index 5d4f47fd..9ae92e55 100644 --- a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/mapper/PluginResourceWorkflowRelDOMapper.java +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/mapper/PluginResourceWorkflowRelDOMapper.java @@ -13,21 +13,9 @@ public interface PluginResourceWorkflowRelDOMapper { int deleteByExample(PluginResourceWorkflowRelDOExample example); - int deleteByPrimaryKey(Long id); - - int insert(PluginResourceWorkflowRelDO record); - int insertSelective(PluginResourceWorkflowRelDO record); List selectByExample(PluginResourceWorkflowRelDOExample example); - PluginResourceWorkflowRelDO selectByPrimaryKey(Long id); - int updateByExampleSelective(@Param("record") PluginResourceWorkflowRelDO record, @Param("example") PluginResourceWorkflowRelDOExample example); - - int updateByExample(@Param("record") PluginResourceWorkflowRelDO record, @Param("example") PluginResourceWorkflowRelDOExample example); - - int updateByPrimaryKeySelective(PluginResourceWorkflowRelDO record); - - int updateByPrimaryKey(PluginResourceWorkflowRelDO record); } \ No newline at end of file diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/mapper/PluginTagDOMapper.java b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/mapper/PluginTagDOMapper.java index 95d972e3..8a486ad5 100644 --- a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/mapper/PluginTagDOMapper.java +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/repository/mapper/PluginTagDOMapper.java @@ -13,21 +13,9 @@ public interface PluginTagDOMapper { int deleteByExample(PluginTagDOExample example); - int deleteByPrimaryKey(Long id); - - int insert(PluginTagDO record); - int insertSelective(PluginTagDO record); List selectByExample(PluginTagDOExample example); - PluginTagDO selectByPrimaryKey(Long id); - int updateByExampleSelective(@Param("record") PluginTagDO record, @Param("example") PluginTagDOExample example); - - int updateByExample(@Param("record") PluginTagDO record, @Param("example") PluginTagDOExample example); - - int updateByPrimaryKeySelective(PluginTagDO record); - - int updateByPrimaryKey(PluginTagDO record); } \ No newline at end of file diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/service/PluginDefinitionService.java b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/service/PluginDefinitionService.java deleted file mode 100644 index 9dfa6798..00000000 --- a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/service/PluginDefinitionService.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.alibaba.tesla.appmanager.plugin.service; - -import com.alibaba.tesla.appmanager.plugin.repository.domain.PluginDefinitionDO; -import org.springframework.web.multipart.MultipartFile; - -import java.io.IOException; - -/** - * Plugin 服务接口 - * - * @author yaoxing.gyx@alibaba-inc.com - */ -public interface PluginDefinitionService { - - /** - * 上传插件 (默认不启用) - * - * @param file API 上传文件 - * @param force 是否强制上传覆盖 - * @return PluginDefinitionDO - */ - PluginDefinitionDO upload(MultipartFile file, boolean force) throws IOException; -} diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/service/PluginFrontendService.java b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/service/PluginFrontendService.java new file mode 100644 index 00000000..79618b28 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/service/PluginFrontendService.java @@ -0,0 +1,39 @@ +package com.alibaba.tesla.appmanager.plugin.service; + +import com.alibaba.tesla.appmanager.domain.schema.PluginDefinitionSchema; +import com.alibaba.tesla.appmanager.plugin.repository.condition.PluginFrontendQueryCondition; +import com.alibaba.tesla.appmanager.plugin.repository.domain.PluginFrontendDO; + +import java.nio.file.Path; + +/** + * Plugin 前端配置相关服务 + * + * @author yaoxing.gyx@alibaba-inc.com + */ +public interface PluginFrontendService { + + /** + * 获取指定的 Plugin Frontend 对象 + * + * @param condition 查询条件 + * @return PluginFrontendDO + */ + PluginFrontendDO get(PluginFrontendQueryCondition condition); + + /** + * 根据 Plugin Definition 更新所有 Frontend 记录 + * + * @param definitionSchema Plugin Definition Schema + * @param pluginDir 插件目录 + */ + void updateByPluginDefinition(PluginDefinitionSchema definitionSchema, Path pluginDir); + + /** + * 删除指定 PluginName + PluginVersion 下的全部 Frontend 资源 + * + * @param pluginName 插件名称 + * @param pluginVersion 插件版本 + */ + void deleteByPlugin(String pluginName, String pluginVersion); +} diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/service/PluginService.java b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/service/PluginService.java new file mode 100644 index 00000000..4d3b4e18 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/service/PluginService.java @@ -0,0 +1,54 @@ +package com.alibaba.tesla.appmanager.plugin.service; + +import com.alibaba.tesla.appmanager.common.pagination.Pagination; +import com.alibaba.tesla.appmanager.domain.req.plugin.PluginDisableReq; +import com.alibaba.tesla.appmanager.domain.req.plugin.PluginEnableReq; +import com.alibaba.tesla.appmanager.plugin.repository.condition.PluginDefinitionQueryCondition; +import com.alibaba.tesla.appmanager.plugin.repository.domain.PluginDefinitionDO; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; + +/** + * Plugin 服务接口 + * + * @author yaoxing.gyx@alibaba-inc.com + */ +public interface PluginService { + + /** + * 获取插件列表 + * + * @param condition 查询插件列表请求 + * @return 插件列表 + */ + Pagination list(PluginDefinitionQueryCondition condition); + + + PluginDefinitionDO get(PluginDefinitionQueryCondition condition); + + /** + * 启用指定插件 + * + * @param request 插件启用请求 + * @return 开启后的 PluginDefinition 对象 + */ + PluginDefinitionDO enable(PluginEnableReq request); + + /** + * 关闭指定插件 + * + * @param request 插件关闭请求 + * @return 关闭后的 PluginDefinition 对象 + */ + PluginDefinitionDO disable(PluginDisableReq request); + + /** + * 上传插件 (默认不启用) + * + * @param file API 上传文件 + * @param force 是否强制上传覆盖 + * @return PluginDefinitionDO + */ + PluginDefinitionDO upload(MultipartFile file, boolean force) throws IOException; +} diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/service/impl/PluginDefinitionServiceImpl.java b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/service/impl/PluginDefinitionServiceImpl.java deleted file mode 100644 index a936dcae..00000000 --- a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/service/impl/PluginDefinitionServiceImpl.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.alibaba.tesla.appmanager.plugin.service.impl; - -import com.alibaba.tesla.appmanager.autoconfig.PackageProperties; -import com.alibaba.tesla.appmanager.common.enums.PluginKindEnum; -import com.alibaba.tesla.appmanager.common.exception.AppErrorCode; -import com.alibaba.tesla.appmanager.common.exception.AppException; -import com.alibaba.tesla.appmanager.common.util.PackageUtil; -import com.alibaba.tesla.appmanager.common.util.SchemaUtil; -import com.alibaba.tesla.appmanager.common.util.ZipUtil; -import com.alibaba.tesla.appmanager.domain.core.StorageFile; -import com.alibaba.tesla.appmanager.domain.schema.PluginDefinitionSchema; -import com.alibaba.tesla.appmanager.plugin.repository.PluginDefinitionRepository; -import com.alibaba.tesla.appmanager.plugin.repository.domain.PluginDefinitionDO; -import com.alibaba.tesla.appmanager.plugin.service.PluginDefinitionService; -import com.alibaba.tesla.appmanager.server.storage.Storage; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.io.FileUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.multipart.MultipartFile; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.List; - -/** - * Plugin 服务 - * - * @author yaoxing.gyx@alibaba-inc.com - */ -@Service -@Slf4j -public class PluginDefinitionServiceImpl implements PluginDefinitionService { - - /** - * Definition Yaml 文件存储路径 - */ - private static final String DEFINITION_FILENAME = "definition.yaml"; - - @Autowired - private PackageProperties packageProperties; - - @Autowired - private PluginDefinitionRepository pluginDefinitionRepository; - - @Autowired - private Storage storage; - - /** - * 上传插件 (默认不启用) - * - * @param file API 上传文件 - * @param force 是否强制上传覆盖 - * @return PluginDefinitionDO - */ - @Override - public PluginDefinitionDO upload(MultipartFile file, boolean force) throws IOException { - Path pluginZipFile = Files.createTempFile("plugin", ".zip"); - Path pluginDir = Files.createTempDirectory("plugin"); - file.transferTo(pluginZipFile.toFile()); - ZipUtil.unzip(pluginZipFile.toFile().getAbsolutePath(), pluginDir.toFile().getAbsolutePath()); - log.info("plugin zip has unzipped to temp directory|dir={}", pluginDir); - - // 读取 definition 信息 - String definitionYaml = FileUtils.readFileToString( - Paths.get(pluginDir.toFile().getAbsolutePath(), DEFINITION_FILENAME).toFile(), - StandardCharsets.UTF_8); - PluginDefinitionSchema definitionSchema = SchemaUtil.toSchema(PluginDefinitionSchema.class, definitionYaml); - PluginKindEnum pluginKind = definitionSchema.getPluginKind(); - String pluginName = definitionSchema.getPluginName(); - String pluginVersion = definitionSchema.getPluginVersion(); - String pluginDescription = definitionSchema.getPluginDescription(); - List pluginTags = definitionSchema.getPluginTags(); - - // 上传当前 plugin 到远端存储 - StorageFile storageFile = uploadPluginHistory(pluginKind, pluginName, pluginVersion, pluginZipFile, force); - - // 写入 DB 记录 - PluginDefinitionDO record = writeDefinitionToDatabase(definitionSchema, pluginKind, pluginName, - pluginDescription, pluginTags, storageFile); - - // 清理现场 - if (!pluginZipFile.toFile().delete()) { - log.error("delete temp plugin zip file failed|pluginZipFile={}", pluginZipFile); - } - return record; - } - - /** - * 写入 Plugin Definition 信息到数据库 - * - * @param definitionSchema Definition Schema - * @param pluginKind 插件类型 - * @param pluginName 插件名称 - * @param pluginDescription 插件描述 - * @param pluginTags 插件 Tags - * @param storageFile 插件存储文件 - * @return PluginDefinitionDO 记录 - */ - @Transactional(rollbackFor = Exception.class) - public PluginDefinitionDO writeDefinitionToDatabase( - PluginDefinitionSchema definitionSchema, PluginKindEnum pluginKind, String pluginName, - String pluginDescription, List pluginTags, StorageFile storageFile) { - return null; - } - - /** - * 上传当前 Plugin Zip 到远端存储 - * - * @param pluginKind 插件类型 - * @param pluginName 插件名称 - * @param pluginVersion 插件版本 - * @param pluginZipFile 实际插件文件 - * @return 存储 StorageFile 文件 - */ - private StorageFile uploadPluginHistory( - PluginKindEnum pluginKind, String pluginName, String pluginVersion, Path pluginZipFile, boolean force) { - String bucketName = packageProperties.getBucketName(); - String objectName = PackageUtil.buildPluginHistoryRemotePath(pluginKind, pluginName, pluginVersion); - if (storage.objectExists(bucketName, objectName) && !force) { - throw new AppException(AppErrorCode.INVALID_USER_ARGS, - String.format("the plugin file already exists and cannot be overwritten|bucketName=%s|" + - "objectName=%s", bucketName, objectName)); - } - storage.putObject(bucketName, objectName, pluginZipFile.toAbsolutePath().toString()); - log.info("plugin zip file has put into storage|pluginKind={}|pluginName={}|pluginVersion={}|bucketName={}|" + - "objectName={}", pluginKind, pluginName, pluginVersion, bucketName, objectName); - return StorageFile.builder() - .bucketName(bucketName) - .objectName(objectName) - .build(); - } -} diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/service/impl/PluginFrontendServiceImpl.java b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/service/impl/PluginFrontendServiceImpl.java new file mode 100644 index 00000000..c9773907 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/service/impl/PluginFrontendServiceImpl.java @@ -0,0 +1,126 @@ +package com.alibaba.tesla.appmanager.plugin.service.impl; + +import com.alibaba.tesla.appmanager.common.constants.PluginConstant; +import com.alibaba.tesla.appmanager.common.enums.PluginKindEnum; +import com.alibaba.tesla.appmanager.common.exception.AppErrorCode; +import com.alibaba.tesla.appmanager.common.exception.AppException; +import com.alibaba.tesla.appmanager.domain.schema.PluginDefinitionSchema; +import com.alibaba.tesla.appmanager.plugin.repository.PluginDefinitionRepository; +import com.alibaba.tesla.appmanager.plugin.repository.PluginFrontendRepository; +import com.alibaba.tesla.appmanager.plugin.repository.condition.PluginDefinitionQueryCondition; +import com.alibaba.tesla.appmanager.plugin.repository.condition.PluginFrontendQueryCondition; +import com.alibaba.tesla.appmanager.plugin.repository.domain.PluginDefinitionDO; +import com.alibaba.tesla.appmanager.plugin.repository.domain.PluginFrontendDO; +import com.alibaba.tesla.appmanager.plugin.service.PluginFrontendService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +@Service +@Slf4j +public class PluginFrontendServiceImpl implements PluginFrontendService { + + @Autowired + private PluginFrontendRepository pluginFrontendRepository; + + @Autowired + private PluginDefinitionRepository pluginDefinitionRepository; + + /** + * 获取指定的 Plugin Frontend 对象 + * + * @param condition 查询条件 + * @return PluginFrontendDO + */ + @Override + public PluginFrontendDO get(PluginFrontendQueryCondition condition) { + if (PluginConstant.PLUGIN_CURRENT_VERSION.equals(condition.getPluginVersion())) { + PluginDefinitionDO currentPlugin = pluginDefinitionRepository.getByCondition( + PluginDefinitionQueryCondition.builder() + .pluginRegistered(true) + .pluginName(condition.getPluginName()) + .build() + ); + if (currentPlugin == null) { + return null; + } + condition.setPluginVersion(currentPlugin.getPluginVersion()); + } + return pluginFrontendRepository.getByCondition(condition); + } + + /** + * 根据 Plugin Definition 更新所有 Frontend 记录 + * + * @param definitionSchema Plugin Definition Schema + * @param pluginDir 插件目录 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void updateByPluginDefinition(PluginDefinitionSchema definitionSchema, Path pluginDir) { + PluginKindEnum pluginKind = definitionSchema.getPluginKind(); + String pluginName = definitionSchema.getPluginName(); + String pluginVersion = definitionSchema.getPluginVersion(); + PluginDefinitionSchema.SchematicFrontend schematic = definitionSchema.getSpec().getSchematic().getFrontend(); + if (schematic == null) { + log.info("no need to import plugin frontend in current plugin|pluginKind={}|pluginName={}|pluginVersion={}", + pluginKind, pluginName, pluginVersion); + return; + } + + int count = pluginFrontendRepository.deleteByCondition(PluginFrontendQueryCondition.builder() + .pluginName(pluginName) + .pluginVersion(pluginVersion) + .build()); + log.info("existing frontend plugin resources have been cleaned up|pluginName={}|pluginVersion={}|count={}", + pluginName, pluginVersion, count); + for (PluginDefinitionSchema.SchematicFrontendFile file : schematic.getFiles()) { + String fileKind = file.getKind(); + String filePath = file.getPath(); + String config; + try { + config = new String(Files.readAllBytes(Paths.get(pluginDir.toFile().toString(), filePath))); + } catch (IOException e) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + "cannot read frontend plugin resource from local plugin zip", e); + } + count = pluginFrontendRepository.insert(PluginFrontendDO.builder() + .pluginName(pluginName) + .pluginVersion(pluginVersion) + .name(fileKind) + .config(config) + .build()); + if (count > 0) { + log.info("frontend plugin resource have been inserted into database|pluginName={}|pluginVersion={}|" + + "name={}|config={}", pluginName, pluginVersion, fileKind, config); + } else { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, String.format("insert frontend plugin " + + "resource into database failed|pluginName=%s|pluginVersion=%s|name=%s|config=%s", + pluginName, pluginVersion, fileKind, config)); + } + } + } + + /** + * 删除指定 PluginName + PluginVersion 下的全部 Frontend 资源 + * + * @param pluginName 插件名称 + * @param pluginVersion 插件版本 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteByPlugin(String pluginName, String pluginVersion) { + int count = pluginFrontendRepository.deleteByCondition(PluginFrontendQueryCondition.builder() + .pluginName(pluginName) + .pluginVersion(pluginVersion) + .build()); + log.info("existing frontend plugin resources have been cleaned up|pluginName={}|pluginVersion={}|count={}", + pluginName, pluginVersion, count); + } +} diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/service/impl/PluginServiceImpl.java b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/service/impl/PluginServiceImpl.java new file mode 100644 index 00000000..f398492a --- /dev/null +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/service/impl/PluginServiceImpl.java @@ -0,0 +1,503 @@ +package com.alibaba.tesla.appmanager.plugin.service.impl; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.tesla.appmanager.api.provider.DefinitionSchemaProvider; +import com.alibaba.tesla.appmanager.api.provider.TraitProvider; +import com.alibaba.tesla.appmanager.autoconfig.PackageProperties; +import com.alibaba.tesla.appmanager.common.constants.DefaultConstant; +import com.alibaba.tesla.appmanager.common.constants.PatternConstant; +import com.alibaba.tesla.appmanager.common.enums.PluginKindEnum; +import com.alibaba.tesla.appmanager.common.exception.AppErrorCode; +import com.alibaba.tesla.appmanager.common.exception.AppException; +import com.alibaba.tesla.appmanager.common.pagination.Pagination; +import com.alibaba.tesla.appmanager.common.util.PackageUtil; +import com.alibaba.tesla.appmanager.common.util.SchemaUtil; +import com.alibaba.tesla.appmanager.common.util.ZipUtil; +import com.alibaba.tesla.appmanager.definition.service.DefinitionSchemaService; +import com.alibaba.tesla.appmanager.domain.core.ScriptIdentifier; +import com.alibaba.tesla.appmanager.domain.core.StorageFile; +import com.alibaba.tesla.appmanager.domain.dto.DefinitionSchemaDTO; +import com.alibaba.tesla.appmanager.domain.req.plugin.PluginDisableReq; +import com.alibaba.tesla.appmanager.domain.req.plugin.PluginEnableReq; +import com.alibaba.tesla.appmanager.domain.schema.PluginDefinitionSchema; +import com.alibaba.tesla.appmanager.domain.schema.TraitDefinition; +import com.alibaba.tesla.appmanager.dynamicscript.repository.condition.DynamicScriptQueryCondition; +import com.alibaba.tesla.appmanager.dynamicscript.service.DynamicScriptService; +import com.alibaba.tesla.appmanager.dynamicscript.util.GroovyUtil; +import com.alibaba.tesla.appmanager.plugin.repository.PluginDefinitionRepository; +import com.alibaba.tesla.appmanager.plugin.repository.PluginTagRepository; +import com.alibaba.tesla.appmanager.plugin.repository.condition.PluginDefinitionQueryCondition; +import com.alibaba.tesla.appmanager.plugin.repository.condition.PluginTagQueryCondition; +import com.alibaba.tesla.appmanager.plugin.repository.domain.PluginDefinitionDO; +import com.alibaba.tesla.appmanager.plugin.repository.domain.PluginTagDO; +import com.alibaba.tesla.appmanager.plugin.service.PluginFrontendService; +import com.alibaba.tesla.appmanager.plugin.service.PluginService; +import com.alibaba.tesla.appmanager.plugin.util.PluginValidator; +import com.alibaba.tesla.appmanager.server.storage.Storage; +import com.alibaba.tesla.appmanager.trait.service.TraitService; +import groovy.lang.GroovyClassLoader; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.List; +import java.util.function.Function; + +/** + * Plugin 服务 + * + * @author yaoxing.gyx@alibaba-inc.com + */ +@Service +@Slf4j +public class PluginServiceImpl implements PluginService { + + /** + * Definition Yaml 文件存储路径 + */ + private static final String DEFINITION_FILENAME = "definition.yaml"; + + @Autowired + private PackageProperties packageProperties; + + @Autowired + private PluginDefinitionRepository pluginDefinitionRepository; + + @Autowired + private PluginTagRepository pluginTagRepository; + + @Autowired + private PluginFrontendService pluginFrontendService; + + @Autowired + private DynamicScriptService dynamicScriptService; + + @Autowired + private Storage storage; + + @Autowired + private DefinitionSchemaProvider definitionSchemaProvider; + + @Autowired + private TraitProvider traitProvider; + + /** + * 获取插件列表 + * + * @param condition 查询插件列表请求 + * @return 插件列表 + */ + @Override + public Pagination list(PluginDefinitionQueryCondition condition) { + List records = pluginDefinitionRepository.selectByCondition(condition); + return Pagination.valueOf(records, Function.identity()); + } + + public PluginDefinitionDO get(PluginDefinitionQueryCondition condition) { + return pluginDefinitionRepository.getByCondition(condition); + } + + /** + * 启用指定插件 + * + * @param request 插件启用请求 + * @return 开启后的 PluginDefinition 对象 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public PluginDefinitionDO enable(PluginEnableReq request) { + String pluginName = request.getPluginName(); + String pluginVersion = request.getPluginVersion(); + + PluginDefinitionQueryCondition definitionCondition = PluginDefinitionQueryCondition.builder() + .pluginName(pluginName) + .pluginVersion(pluginVersion) + .build(); + PluginDefinitionDO definitionDO = pluginDefinitionRepository.getByCondition(definitionCondition); + if (definitionDO == null) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "plugin not found"); + } else if (definitionDO.getPluginRegistered()) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "plugin is already registered"); + } + PluginDefinitionSchema definitionSchema = SchemaUtil.toSchema( + PluginDefinitionSchema.class, definitionDO.getPluginSchema()); + if (!definitionDO.getPluginName().equals(definitionSchema.getPluginName()) + || !definitionDO.getPluginVersion().equals(definitionSchema.getPluginVersion()) + || !definitionDO.getPluginKind().equals(definitionSchema.getPluginKind().toString())) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + "mismatch plugin definition schema, please check it"); + } + + // 注册前端资源 && Groovy + StorageFile storageFile = new StorageFile(definitionDO.getPackagePath()); + Path tmpDir = null; + try { + tmpDir = Files.createTempDirectory("plugin_enable"); + Path pluginZip = tmpDir.resolve("plugin.zip"); + String url = storage.getObjectUrl(storageFile.getBucketName(), storageFile.getObjectName(), + DefaultConstant.DEFAULT_FILE_EXPIRATION); + FileUtils.copyURLToFile(new URL(url), pluginZip.toFile()); + ZipUtil.unzip(pluginZip.toString(), tmpDir.toString()); + FileUtils.deleteQuietly(pluginZip.toFile()); + pluginFrontendService.updateByPluginDefinition(definitionSchema, tmpDir); + loadGroovyScripts(definitionSchema, tmpDir); + } catch (IOException e) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "cannot create temp directory", e); + } finally { + if (tmpDir != null) { + try { + FileUtils.forceDelete(tmpDir.toFile()); + } catch (Exception e) { + log.error("delete temp directory failed|dir={}|exception={}", + tmpDir, ExceptionUtils.getStackTrace(e)); + } + } + } + + // 开启插件 + definitionDO.setPluginRegistered(true); + int count = pluginDefinitionRepository.updateByCondition(definitionDO, definitionCondition); + if (count != 1) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("register plugin failed, cannot update plugin definition|condition=%s", + JSONObject.toJSONString(definitionCondition))); + } + return definitionDO; + } + + /** + * 关闭指定插件 + * + * @param request 插件关闭请求 + * @return 关闭后的 PluginDefinition 对象 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public PluginDefinitionDO disable(PluginDisableReq request) { + String pluginName = request.getPluginName(); + String pluginVersion = request.getPluginVersion(); + + PluginDefinitionQueryCondition definitionCondition = PluginDefinitionQueryCondition.builder() + .pluginName(pluginName) + .pluginVersion(pluginVersion) + .build(); + PluginDefinitionDO definitionDO = pluginDefinitionRepository.getByCondition(definitionCondition); + if (definitionDO == null) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "plugin not found"); + } + + // 删除前端资源 + pluginFrontendService.deleteByPlugin(pluginName, pluginVersion); + + // 取消 Groovy 注册 + PluginDefinitionSchema schema = SchemaUtil.toSchema( + PluginDefinitionSchema.class, definitionDO.getPluginSchema()); + PluginDefinitionSchema.Schematic schematic = schema.getSpec().getSchematic(); + if (schematic != null) { + for (PluginDefinitionSchema.SchematicGroovyFile file : schematic.getGroovy().getFiles()) { + if (request.isIgnoreGroovyFiles()) { + continue; + } + dynamicScriptService.removeScript(DynamicScriptQueryCondition.builder() + .kind(file.getKind()) + .name(file.getName()) + .build()); + } + } + + // 关闭插件 + definitionDO.setPluginRegistered(false); + int count = pluginDefinitionRepository.updateByCondition(definitionDO, definitionCondition); + if (count != 1) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("register plugin failed, cannot update plugin definition|condition=%s", + JSONObject.toJSONString(definitionCondition))); + } + return definitionDO; + } + + /** + * 上传插件 (默认不启用) + * + * @param file API 上传文件 + * @param force 是否强制上传覆盖 + * @return PluginDefinitionDO + */ + @Override + public PluginDefinitionDO upload(MultipartFile file, boolean force) throws IOException { + Path pluginZipFile = Files.createTempFile("plugin", ".zip"); + Path pluginDir = Files.createTempDirectory("plugin"); + file.transferTo(pluginZipFile.toFile()); + ZipUtil.unzip(pluginZipFile.toFile().getAbsolutePath(), pluginDir.toFile().getAbsolutePath()); + log.info("plugin zip has unzipped to temp directory|dir={}", pluginDir); + + // 读取 definition 信息 + String definitionYaml = FileUtils.readFileToString( + Paths.get(pluginDir.toFile().getAbsolutePath(), DEFINITION_FILENAME).toFile(), + StandardCharsets.UTF_8); + PluginDefinitionSchema definitionSchema = SchemaUtil.toSchema(PluginDefinitionSchema.class, definitionYaml); + PluginKindEnum pluginKind = definitionSchema.getPluginKind(); + String pluginName = definitionSchema.getPluginName(); + String pluginVersion = definitionSchema.getPluginVersion(); + String pluginDescription = definitionSchema.getPluginDescription(); + List pluginTags = definitionSchema.getPluginTags(); + + // 校验 definition 名称信息 + if (!PluginValidator.validateName(pluginName)) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "invalid plugin name"); + } + + // 上传当前 plugin 到远端存储 + StorageFile storageFile = uploadPluginHistoryToStorage(pluginKind, pluginName, + pluginVersion, pluginZipFile, force); + + // 写入 DB 记录 + PluginDefinitionDO record = update(definitionSchema, pluginKind, pluginName, pluginVersion, + pluginDescription, pluginTags, storageFile); + + // 清理现场 + try { + FileUtils.forceDelete(pluginZipFile.toFile()); + } catch (Exception e) { + log.error("delete temp plugin zip file failed|pluginZipFile={}|exception={}", + pluginZipFile, ExceptionUtils.getStackTrace(e)); + } + return record; + } + + /** + * 插入 Plugin Definition 信息到数据库 + * + * @param definitionSchema Definition Schema + * @param pluginKind 插件类型 + * @param pluginName 插件名称 + * @param pluginVersion 插件版本 + * @param pluginDescription 插件描述 + * @param pluginTags 插件 Tags + * @param storageFile 插件存储文件 + * @return PluginDefinitionDO 记录 + */ + @Transactional(rollbackFor = Exception.class) + public PluginDefinitionDO update( + PluginDefinitionSchema definitionSchema, PluginKindEnum pluginKind, String pluginName, String pluginVersion, + String pluginDescription, List pluginTags, StorageFile storageFile) { + String logSuffix = String.format("pluginKind=%s|pluginName=%s|pluginVersion=%s|pluginTags=%s|packagePath=%s", + pluginKind, pluginName, pluginVersion, JSONArray.toJSONString(pluginTags), storageFile.toPath()); + String pluginSchemaStr = SchemaUtil.toYamlMapStr(definitionSchema); + + PluginDefinitionQueryCondition condition = PluginDefinitionQueryCondition.builder() + .pluginName(pluginName) + .pluginVersion(pluginVersion) + .build(); + PluginDefinitionDO definitionDO = pluginDefinitionRepository.getByCondition(condition); + if (definitionDO == null) { + definitionDO = PluginDefinitionDO.builder() + .pluginKind(pluginKind.toString()) + .pluginName(pluginName) + .pluginVersion(pluginVersion) + .pluginRegistered(false) + .packagePath(storageFile.toPath()) + .pluginDescription(pluginDescription) + .pluginDependencies(JSONArray.toJSONString(new JSONArray())) + .pluginSchema(pluginSchemaStr) + .build(); + int count = pluginDefinitionRepository.insert(definitionDO); + if (count > 0) { + log.info("plugin definition has inserted into database|{}|definitionSchema={}", + logSuffix, pluginSchemaStr); + } else { + log.error("insert plugin definition failed|{}|count=0", logSuffix); + } + } else if (definitionDO.getPluginRegistered()) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "the specified operation cloud not be completed " + + "because the plugin has been successfully registered and enabled"); + } else { + definitionDO.setPluginKind(pluginKind.toString()); + definitionDO.setPluginRegistered(false); + definitionDO.setPackagePath(storageFile.toPath()); + definitionDO.setPluginDescription(pluginDescription); + definitionDO.setPluginDependencies(JSONArray.toJSONString(new JSONArray())); + definitionDO.setPluginSchema(pluginSchemaStr); + int count = pluginDefinitionRepository.updateByCondition(definitionDO, condition); + if (count > 0) { + log.info("plugin definition has updated in database|{}|definitionSchema={}", + logSuffix, pluginSchemaStr); + } else { + log.error("update plugin definition failed|{}|count=0", logSuffix); + } + } + + long pluginId = definitionDO.getId(); + int count = pluginTagRepository.deleteByCondition(PluginTagQueryCondition.builder().pluginId(pluginId).build()); + if (count > 0) { + log.info("plugin tags have been cleaned up before installation|{}|count={}", logSuffix, count); + } + for (String pluginTag : pluginTags) { + count = pluginTagRepository.insert(PluginTagDO.builder() + .pluginId(pluginId) + .tag(pluginTag) + .build()); + if (count > 0) { + log.info("plugin tag has inserted into database|{}|pluginId={}|tag={}", logSuffix, pluginId, pluginTag); + } else { + log.error("insert plugin tag failed|{}|pluginId={}|tag={}|count=0", logSuffix, pluginId, pluginTag); + } + } + return definitionDO; + } + + /** + * 上传当前 Plugin Zip 到远端存储 + * + * @param pluginKind 插件类型 + * @param pluginName 插件名称 + * @param pluginVersion 插件版本 + * @param pluginZipFile 实际插件文件 + * @return 存储 StorageFile 文件 + */ + private StorageFile uploadPluginHistoryToStorage( + PluginKindEnum pluginKind, String pluginName, String pluginVersion, Path pluginZipFile, boolean force) { + String bucketName = packageProperties.getBucketName(); + String objectName = PackageUtil.buildPluginHistoryRemotePath(pluginKind, pluginName, pluginVersion); + if (storage.objectExists(bucketName, objectName) && !force) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("the plugin file already exists and cannot be overwritten|bucketName=%s|" + + "objectName=%s", bucketName, objectName)); + } + storage.putObject(bucketName, objectName, pluginZipFile.toAbsolutePath().toString()); + log.info("plugin zip file has put into storage|pluginKind={}|pluginName={}|pluginVersion={}|bucketName={}|" + + "objectName={}", pluginKind, pluginName, pluginVersion, bucketName, objectName); + return StorageFile.builder() + .bucketName(bucketName) + .objectName(objectName) + .build(); + } + + /** + * 加载全部 Groovy Scripts + * + * @param schema Plugin Definition Schema + * @param pluginDir 插件 Zip 文件本地目录 + */ + private void loadGroovyScripts(PluginDefinitionSchema schema, Path pluginDir) { + PluginKindEnum pluginKind = schema.getPluginKind(); + String pluginName = schema.getPluginName(); + String pluginVersion = schema.getPluginVersion(); + PluginDefinitionSchema.SchematicGroovy schematic = schema.getSpec().getSchematic().getGroovy(); + if (schematic == null) { + log.info("no need to load groovy scripts in current plugin|pluginKind={}|pluginName={}|pluginVersion={}", + pluginKind, pluginName, pluginVersion); + return; + } + if (PluginKindEnum.TRAIT_DEFINITION.equals(pluginKind) && schematic.getFiles().size() != 1) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + "only 1 trait groovy is accepted in TraitDefinition"); + } + + GroovyClassLoader groovyClassLoader = new GroovyClassLoader(); + for (PluginDefinitionSchema.SchematicGroovyFile file : schematic.getFiles()) { + String fileKind = file.getKind(); + String fileName = file.getName(); + String filePath = file.getPath(); + + if (StringUtils.isAnyEmpty(fileKind, filePath)) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "kind/path are required in groovy files"); + } + // trait name 为空时使用插件名称 (仅 1 个) + if (StringUtils.isEmpty(fileName) && PluginKindEnum.TRAIT_DEFINITION.equals(pluginKind)) { + fileName = pluginName; + } else if (StringUtils.isEmpty(fileName)) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "name is required in groovy files"); + } + + String code; + try { + code = new String(Files.readAllBytes(Paths.get(pluginDir.toFile().toString(), filePath))); + } catch (IOException e) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + "cannot read groovy code from local plugin zip", e); + } + + // 校验 Groovy Code 是否合法 + ScriptIdentifier identifier; + try { + Class clazz = groovyClassLoader.parseClass(code); + identifier = GroovyUtil.getScriptIdentifierFromClass(clazz); + } catch (AppException e) { + throw e; + } catch (Exception e) { + throw new AppException(AppErrorCode.GROOVY_ERROR, + String.format("load groovy script failed|kind=%s|name=%s|path=%s", + fileKind, fileName, filePath), e); + } + if (!identifier.getKind().equals(fileKind) || !identifier.getName().equals(fileName)) { + throw new AppException(AppErrorCode.GROOVY_ERROR, + String.format("mismatched kind/name in groovy script|definitionKind=%s|definitionName=%s|" + + "codeKind=%s|codeName=%s", fileKind, fileName, identifier.getKind(), + identifier.getName())); + } + + // 更新到 DB 中 + DynamicScriptQueryCondition condition = DynamicScriptQueryCondition.builder() + .kind(fileKind) + .name(fileName) + .build(); + dynamicScriptService.initScript(condition, identifier.getRevision(), code); + log.info("groovy scripts has updated in dynamic script table|pluginKind={}|pluginName={}|" + + "pluginVersion={}|fileKind={}|fileName={}|filePath={}|code={}", pluginKind, pluginName, + pluginVersion, fileKind, fileName, filePath, code); + + // 针对 Trait 类型,需要进行 Trait 注册 + if (!"TRAIT".equals(fileKind)) { + continue; + } + JSONObject properties = file.getProperties(); + if (properties == null) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + "trait properties in definition cannot be empty"); + } + String runtime = properties.getString("runtime"); + JSONObject definitionSchema = properties.getJSONObject("definitionSchema"); + if (definitionSchema == null) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + "definitionSchema in properties cannot be empty"); + } + String definitionSchemaName = definitionSchema.getString("name"); + JSONObject definitionSchemaJson = definitionSchema.getJSONObject("jsonSchema"); + if (definitionSchemaJson == null) { + definitionSchemaJson = new JSONObject(); + } + definitionSchemaProvider.apply(DefinitionSchemaDTO.builder() + .name(definitionSchemaName) + .jsonSchema(definitionSchemaJson.toJSONString()) + .build(), DefaultConstant.SYSTEM_OPERATOR); + traitProvider.apply(TraitDefinition.builder() + .apiVersion(DefaultConstant.API_VERSION_V1_ALPHA2) + .kind(PluginKindEnum.TRAIT_DEFINITION.toString()) + .metadata(TraitDefinition.MetaData.builder() + .name(fileName) + .build()) + .spec(TraitDefinition.Spec.builder() + .runtime(runtime) + .appliesToWorkloads(List.of("*")) + .definitionRef(TraitDefinition.SpecDefinitionRef.builder() + .name(definitionSchemaName) + .build()) + .build()) + .build(), DefaultConstant.SYSTEM_OPERATOR); + } + } +} diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/util/PluginNameGenerator.java b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/util/PluginNameGenerator.java new file mode 100644 index 00000000..a0175479 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/util/PluginNameGenerator.java @@ -0,0 +1,20 @@ +package com.alibaba.tesla.appmanager.plugin.util; + +/** + * Plugin 名称生成器 + * + * @author yaoxing.gyx@alibaba-inc.com + */ +public class PluginNameGenerator { + + /** + * 生成 Plugin Name + * + * @param pluginNamePrefix 前缀 (合法 DNS 名称) + * @param pluginNameSuffix 后缀 (版本) + * @return Plugin Name + */ + public static String generate(String pluginNamePrefix, String pluginNameSuffix) { + return pluginNamePrefix + "/" + pluginNameSuffix; + } +} diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/util/PluginValidator.java b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/util/PluginValidator.java new file mode 100644 index 00000000..0a85259b --- /dev/null +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/java/com/alibaba/tesla/appmanager/plugin/util/PluginValidator.java @@ -0,0 +1,30 @@ +package com.alibaba.tesla.appmanager.plugin.util; + +import com.alibaba.tesla.appmanager.common.constants.PatternConstant; + +/** + * Plugin 相关校验器 + * + * @author yaoxing.gyx@alibaba-inc.com + */ +public class PluginValidator { + + /** + * 校验 Plugin Name 是否合法 + * + * @param pluginName Plugin Name + * @return true or false + */ + public static boolean validateName(String pluginName) { + String[] array = pluginName.split("/"); + if (array.length != 2) { + return false; + } + String name = array[0]; + String version = array[1]; + if (!name.matches(PatternConstant.DNS_REGEX)) { + return false; + } + return version.matches(PatternConstant.ALPHANUMERIC_REGEX); + } +} diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/resources/mybatis/PluginDefinitionDOMapper.xml b/paas/appmanager/tesla-appmanager-plugin/src/main/resources/mybatis/PluginDefinitionDOMapper.xml index 7a27e814..4988900c 100644 --- a/paas/appmanager/tesla-appmanager-plugin/src/main/resources/mybatis/PluginDefinitionDOMapper.xml +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/resources/mybatis/PluginDefinitionDOMapper.xml @@ -117,20 +117,19 @@ order by id desc - - select + select + + distinct + - , - from am_plugin_definition - where id = #{id,jdbcType=BIGINT} + + + + group by plugin_kind, plugin_name, plugin_version - - - delete from am_plugin_definition - where id = #{id,jdbcType=BIGINT} - delete from am_plugin_definition @@ -138,17 +137,6 @@ - - - insert into am_plugin_definition (gmt_create, gmt_modified, plugin_kind, - plugin_name, plugin_version, plugin_registered, - package_path, plugin_description, plugin_dependencies, - plugin_schema) - values (#{gmtCreate,jdbcType=TIMESTAMP}, #{gmtModified,jdbcType=TIMESTAMP}, #{pluginKind,jdbcType=VARCHAR}, - #{pluginName,jdbcType=VARCHAR}, #{pluginVersion,jdbcType=VARCHAR}, #{pluginRegistered,jdbcType=BOOLEAN}, - #{packagePath,jdbcType=VARCHAR}, #{pluginDescription,jdbcType=LONGVARCHAR}, #{pluginDependencies,jdbcType=LONGVARCHAR}, - #{pluginSchema,jdbcType=LONGVARCHAR}) - insert into am_plugin_definition @@ -266,101 +254,4 @@ - - - update am_plugin_definition - set id = #{record.id,jdbcType=BIGINT}, - gmt_create = #{record.gmtCreate,jdbcType=TIMESTAMP}, - gmt_modified = #{record.gmtModified,jdbcType=TIMESTAMP}, - plugin_kind = #{record.pluginKind,jdbcType=VARCHAR}, - plugin_name = #{record.pluginName,jdbcType=VARCHAR}, - plugin_version = #{record.pluginVersion,jdbcType=VARCHAR}, - plugin_registered = #{record.pluginRegistered,jdbcType=BOOLEAN}, - package_path = #{record.packagePath,jdbcType=VARCHAR}, - plugin_description = #{record.pluginDescription,jdbcType=LONGVARCHAR}, - plugin_dependencies = #{record.pluginDependencies,jdbcType=LONGVARCHAR}, - plugin_schema = #{record.pluginSchema,jdbcType=LONGVARCHAR} - - - - - - - update am_plugin_definition - set id = #{record.id,jdbcType=BIGINT}, - gmt_create = #{record.gmtCreate,jdbcType=TIMESTAMP}, - gmt_modified = #{record.gmtModified,jdbcType=TIMESTAMP}, - plugin_kind = #{record.pluginKind,jdbcType=VARCHAR}, - plugin_name = #{record.pluginName,jdbcType=VARCHAR}, - plugin_version = #{record.pluginVersion,jdbcType=VARCHAR}, - plugin_registered = #{record.pluginRegistered,jdbcType=BOOLEAN}, - package_path = #{record.packagePath,jdbcType=VARCHAR} - - - - - - - update am_plugin_definition - - - gmt_create = #{gmtCreate,jdbcType=TIMESTAMP}, - - - gmt_modified = #{gmtModified,jdbcType=TIMESTAMP}, - - - plugin_kind = #{pluginKind,jdbcType=VARCHAR}, - - - plugin_name = #{pluginName,jdbcType=VARCHAR}, - - - plugin_version = #{pluginVersion,jdbcType=VARCHAR}, - - - plugin_registered = #{pluginRegistered,jdbcType=BOOLEAN}, - - - package_path = #{packagePath,jdbcType=VARCHAR}, - - - plugin_description = #{pluginDescription,jdbcType=LONGVARCHAR}, - - - plugin_dependencies = #{pluginDependencies,jdbcType=LONGVARCHAR}, - - - plugin_schema = #{pluginSchema,jdbcType=LONGVARCHAR}, - - - where id = #{id,jdbcType=BIGINT} - - - - update am_plugin_definition - set gmt_create = #{gmtCreate,jdbcType=TIMESTAMP}, - gmt_modified = #{gmtModified,jdbcType=TIMESTAMP}, - plugin_kind = #{pluginKind,jdbcType=VARCHAR}, - plugin_name = #{pluginName,jdbcType=VARCHAR}, - plugin_version = #{pluginVersion,jdbcType=VARCHAR}, - plugin_registered = #{pluginRegistered,jdbcType=BOOLEAN}, - package_path = #{packagePath,jdbcType=VARCHAR}, - plugin_description = #{pluginDescription,jdbcType=LONGVARCHAR}, - plugin_dependencies = #{pluginDependencies,jdbcType=LONGVARCHAR}, - plugin_schema = #{pluginSchema,jdbcType=LONGVARCHAR} - where id = #{id,jdbcType=BIGINT} - - - - update am_plugin_definition - set gmt_create = #{gmtCreate,jdbcType=TIMESTAMP}, - gmt_modified = #{gmtModified,jdbcType=TIMESTAMP}, - plugin_kind = #{pluginKind,jdbcType=VARCHAR}, - plugin_name = #{pluginName,jdbcType=VARCHAR}, - plugin_version = #{pluginVersion,jdbcType=VARCHAR}, - plugin_registered = #{pluginRegistered,jdbcType=BOOLEAN}, - package_path = #{packagePath,jdbcType=VARCHAR} - where id = #{id,jdbcType=BIGINT} - \ No newline at end of file diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/resources/mybatis/PluginFrontendDOMapper.xml b/paas/appmanager/tesla-appmanager-plugin/src/main/resources/mybatis/PluginFrontendDOMapper.xml index 47079ab9..5244ccd4 100644 --- a/paas/appmanager/tesla-appmanager-plugin/src/main/resources/mybatis/PluginFrontendDOMapper.xml +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/resources/mybatis/PluginFrontendDOMapper.xml @@ -89,18 +89,6 @@ order by id desc - - - - delete from am_plugin_frontend - where id = #{id,jdbcType=BIGINT} - delete from am_plugin_frontend @@ -108,15 +96,6 @@ - - - insert into am_plugin_frontend (gmt_create, gmt_modified, plugin_name, - plugin_version, `name`, config - ) - values (#{gmtCreate,jdbcType=TIMESTAMP}, #{gmtModified,jdbcType=TIMESTAMP}, #{pluginName,jdbcType=VARCHAR}, - #{pluginVersion,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{config,jdbcType=LONGVARCHAR} - ) - insert into am_plugin_frontend @@ -198,54 +177,4 @@ - - - update am_plugin_frontend - set id = #{record.id,jdbcType=BIGINT}, - gmt_create = #{record.gmtCreate,jdbcType=TIMESTAMP}, - gmt_modified = #{record.gmtModified,jdbcType=TIMESTAMP}, - plugin_name = #{record.pluginName,jdbcType=VARCHAR}, - plugin_version = #{record.pluginVersion,jdbcType=VARCHAR}, - `name` = #{record.name,jdbcType=VARCHAR}, - config = #{record.config,jdbcType=LONGVARCHAR} - - - - - - - update am_plugin_frontend - - - gmt_create = #{gmtCreate,jdbcType=TIMESTAMP}, - - - gmt_modified = #{gmtModified,jdbcType=TIMESTAMP}, - - - plugin_name = #{pluginName,jdbcType=VARCHAR}, - - - plugin_version = #{pluginVersion,jdbcType=VARCHAR}, - - - `name` = #{name,jdbcType=VARCHAR}, - - - config = #{config,jdbcType=LONGVARCHAR}, - - - where id = #{id,jdbcType=BIGINT} - - - - update am_plugin_frontend - set gmt_create = #{gmtCreate,jdbcType=TIMESTAMP}, - gmt_modified = #{gmtModified,jdbcType=TIMESTAMP}, - plugin_name = #{pluginName,jdbcType=VARCHAR}, - plugin_version = #{pluginVersion,jdbcType=VARCHAR}, - `name` = #{name,jdbcType=VARCHAR}, - config = #{config,jdbcType=LONGVARCHAR} - where id = #{id,jdbcType=BIGINT} - \ No newline at end of file diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/resources/mybatis/PluginResourceDOMapper.xml b/paas/appmanager/tesla-appmanager-plugin/src/main/resources/mybatis/PluginResourceDOMapper.xml index c052532c..f180973d 100644 --- a/paas/appmanager/tesla-appmanager-plugin/src/main/resources/mybatis/PluginResourceDOMapper.xml +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/resources/mybatis/PluginResourceDOMapper.xml @@ -7,7 +7,7 @@ - + @@ -93,18 +93,6 @@ order by id desc - - - - delete from am_plugin_resource - where id = #{id,jdbcType=BIGINT} - delete from am_plugin_resource @@ -112,17 +100,6 @@ - - - insert into am_plugin_resource (gmt_create, gmt_modified, plugin_name, - plugin_version, cluster_id, instance_status, - instance_error_message, instance_registered, - lock_version) - values (#{gmtCreate,jdbcType=TIMESTAMP}, #{gmtModified,jdbcType=TIMESTAMP}, #{pluginName,jdbcType=BIGINT}, - #{pluginVersion,jdbcType=VARCHAR}, #{clusterId,jdbcType=VARCHAR}, #{instanceStatus,jdbcType=VARCHAR}, - #{instanceErrorMessage,jdbcType=LONGVARCHAR}, #{instanceRegistered,jdbcType=BOOLEAN}, - #{lockVersion,jdbcType=INTEGER}) - insert into am_plugin_resource @@ -163,7 +140,7 @@ #{gmtModified,jdbcType=TIMESTAMP}, - #{pluginName,jdbcType=BIGINT}, + #{pluginName,jdbcType=VARCHAR}, #{pluginVersion,jdbcType=VARCHAR}, @@ -206,7 +183,7 @@ gmt_modified = #{record.gmtModified,jdbcType=TIMESTAMP}, - plugin_name = #{record.pluginName,jdbcType=BIGINT}, + plugin_name = #{record.pluginName,jdbcType=VARCHAR}, plugin_version = #{record.pluginVersion,jdbcType=VARCHAR}, @@ -231,69 +208,4 @@ - - - update am_plugin_resource - set id = #{record.id,jdbcType=BIGINT}, - gmt_create = #{record.gmtCreate,jdbcType=TIMESTAMP}, - gmt_modified = #{record.gmtModified,jdbcType=TIMESTAMP}, - plugin_name = #{record.pluginName,jdbcType=BIGINT}, - plugin_version = #{record.pluginVersion,jdbcType=VARCHAR}, - cluster_id = #{record.clusterId,jdbcType=VARCHAR}, - instance_status = #{record.instanceStatus,jdbcType=VARCHAR}, - instance_error_message = #{record.instanceErrorMessage,jdbcType=LONGVARCHAR}, - instance_registered = #{record.instanceRegistered,jdbcType=BOOLEAN}, - lock_version = #{record.lockVersion,jdbcType=INTEGER} - - - - - - - update am_plugin_resource - - - gmt_create = #{gmtCreate,jdbcType=TIMESTAMP}, - - - gmt_modified = #{gmtModified,jdbcType=TIMESTAMP}, - - - plugin_name = #{pluginName,jdbcType=BIGINT}, - - - plugin_version = #{pluginVersion,jdbcType=VARCHAR}, - - - cluster_id = #{clusterId,jdbcType=VARCHAR}, - - - instance_status = #{instanceStatus,jdbcType=VARCHAR}, - - - instance_error_message = #{instanceErrorMessage,jdbcType=LONGVARCHAR}, - - - instance_registered = #{instanceRegistered,jdbcType=BOOLEAN}, - - - lock_version = #{lockVersion,jdbcType=INTEGER}, - - - where id = #{id,jdbcType=BIGINT} - - - - update am_plugin_resource - set gmt_create = #{gmtCreate,jdbcType=TIMESTAMP}, - gmt_modified = #{gmtModified,jdbcType=TIMESTAMP}, - plugin_name = #{pluginName,jdbcType=BIGINT}, - plugin_version = #{pluginVersion,jdbcType=VARCHAR}, - cluster_id = #{clusterId,jdbcType=VARCHAR}, - instance_status = #{instanceStatus,jdbcType=VARCHAR}, - instance_error_message = #{instanceErrorMessage,jdbcType=LONGVARCHAR}, - instance_registered = #{instanceRegistered,jdbcType=BOOLEAN}, - lock_version = #{lockVersion,jdbcType=INTEGER} - where id = #{id,jdbcType=BIGINT} - \ No newline at end of file diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/resources/mybatis/PluginResourceWorkflowRelDOMapper.xml b/paas/appmanager/tesla-appmanager-plugin/src/main/resources/mybatis/PluginResourceWorkflowRelDOMapper.xml index 765d293d..962ec5a0 100644 --- a/paas/appmanager/tesla-appmanager-plugin/src/main/resources/mybatis/PluginResourceWorkflowRelDOMapper.xml +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/resources/mybatis/PluginResourceWorkflowRelDOMapper.xml @@ -93,18 +93,6 @@ order by id desc - - - - delete from am_plugin_resource_workflow_rel - where id = #{id,jdbcType=BIGINT} - delete from am_plugin_resource_workflow_rel @@ -112,17 +100,6 @@ - - - insert into am_plugin_resource_workflow_rel (gmt_create, gmt_modified, plugin_resource_id, - cluster_id, workflow_type, workflow_id, - workflow_status, workflow_error_message, - lock_version) - values (#{gmtCreate,jdbcType=TIMESTAMP}, #{gmtModified,jdbcType=TIMESTAMP}, #{pluginResourceId,jdbcType=BIGINT}, - #{clusterId,jdbcType=VARCHAR}, #{workflowType,jdbcType=VARCHAR}, #{workflowId,jdbcType=BIGINT}, - #{workflowStatus,jdbcType=VARCHAR}, #{workflowErrorMessage,jdbcType=LONGVARCHAR}, - #{lockVersion,jdbcType=INTEGER}) - insert into am_plugin_resource_workflow_rel @@ -231,69 +208,4 @@ - - - update am_plugin_resource_workflow_rel - set id = #{record.id,jdbcType=BIGINT}, - gmt_create = #{record.gmtCreate,jdbcType=TIMESTAMP}, - gmt_modified = #{record.gmtModified,jdbcType=TIMESTAMP}, - plugin_resource_id = #{record.pluginResourceId,jdbcType=BIGINT}, - cluster_id = #{record.clusterId,jdbcType=VARCHAR}, - workflow_type = #{record.workflowType,jdbcType=VARCHAR}, - workflow_id = #{record.workflowId,jdbcType=BIGINT}, - workflow_status = #{record.workflowStatus,jdbcType=VARCHAR}, - workflow_error_message = #{record.workflowErrorMessage,jdbcType=LONGVARCHAR}, - lock_version = #{record.lockVersion,jdbcType=INTEGER} - - - - - - - update am_plugin_resource_workflow_rel - - - gmt_create = #{gmtCreate,jdbcType=TIMESTAMP}, - - - gmt_modified = #{gmtModified,jdbcType=TIMESTAMP}, - - - plugin_resource_id = #{pluginResourceId,jdbcType=BIGINT}, - - - cluster_id = #{clusterId,jdbcType=VARCHAR}, - - - workflow_type = #{workflowType,jdbcType=VARCHAR}, - - - workflow_id = #{workflowId,jdbcType=BIGINT}, - - - workflow_status = #{workflowStatus,jdbcType=VARCHAR}, - - - workflow_error_message = #{workflowErrorMessage,jdbcType=LONGVARCHAR}, - - - lock_version = #{lockVersion,jdbcType=INTEGER}, - - - where id = #{id,jdbcType=BIGINT} - - - - update am_plugin_resource_workflow_rel - set gmt_create = #{gmtCreate,jdbcType=TIMESTAMP}, - gmt_modified = #{gmtModified,jdbcType=TIMESTAMP}, - plugin_resource_id = #{pluginResourceId,jdbcType=BIGINT}, - cluster_id = #{clusterId,jdbcType=VARCHAR}, - workflow_type = #{workflowType,jdbcType=VARCHAR}, - workflow_id = #{workflowId,jdbcType=BIGINT}, - workflow_status = #{workflowStatus,jdbcType=VARCHAR}, - workflow_error_message = #{workflowErrorMessage,jdbcType=LONGVARCHAR}, - lock_version = #{lockVersion,jdbcType=INTEGER} - where id = #{id,jdbcType=BIGINT} - \ No newline at end of file diff --git a/paas/appmanager/tesla-appmanager-plugin/src/main/resources/mybatis/PluginTagDOMapper.xml b/paas/appmanager/tesla-appmanager-plugin/src/main/resources/mybatis/PluginTagDOMapper.xml index a822a192..57561622 100644 --- a/paas/appmanager/tesla-appmanager-plugin/src/main/resources/mybatis/PluginTagDOMapper.xml +++ b/paas/appmanager/tesla-appmanager-plugin/src/main/resources/mybatis/PluginTagDOMapper.xml @@ -87,18 +87,6 @@ order by id desc - - - - delete from am_plugin_tag - where id = #{id,jdbcType=BIGINT} - delete from am_plugin_tag @@ -106,13 +94,6 @@ - - - insert into am_plugin_tag (gmt_create, gmt_modified, plugin_id, - tag) - values (#{gmtCreate,jdbcType=TIMESTAMP}, #{gmtModified,jdbcType=TIMESTAMP}, #{pluginId,jdbcType=BIGINT}, - #{tag,jdbcType=VARCHAR}) - insert into am_plugin_tag @@ -176,44 +157,4 @@ - - - update am_plugin_tag - set id = #{record.id,jdbcType=BIGINT}, - gmt_create = #{record.gmtCreate,jdbcType=TIMESTAMP}, - gmt_modified = #{record.gmtModified,jdbcType=TIMESTAMP}, - plugin_id = #{record.pluginId,jdbcType=BIGINT}, - tag = #{record.tag,jdbcType=VARCHAR} - - - - - - - update am_plugin_tag - - - gmt_create = #{gmtCreate,jdbcType=TIMESTAMP}, - - - gmt_modified = #{gmtModified,jdbcType=TIMESTAMP}, - - - plugin_id = #{pluginId,jdbcType=BIGINT}, - - - tag = #{tag,jdbcType=VARCHAR}, - - - where id = #{id,jdbcType=BIGINT} - - - - update am_plugin_tag - set gmt_create = #{gmtCreate,jdbcType=TIMESTAMP}, - gmt_modified = #{gmtModified,jdbcType=TIMESTAMP}, - plugin_id = #{pluginId,jdbcType=BIGINT}, - tag = #{tag,jdbcType=VARCHAR} - where id = #{id,jdbcType=BIGINT} - \ No newline at end of file diff --git a/paas/appmanager/tesla-appmanager-plugin/src/test/resources/fixtures/plugins/hello/definition.yaml b/paas/appmanager/tesla-appmanager-plugin/src/test/resources/fixtures/plugins/hello/definition.yaml new file mode 100644 index 00000000..ce411d7b --- /dev/null +++ b/paas/appmanager/tesla-appmanager-plugin/src/test/resources/fixtures/plugins/hello/definition.yaml @@ -0,0 +1,27 @@ +apiVersion: core.oam.dev/v1beta1 +kind: ComponentDefinition +metadata: + name: TestComponent + annotations: + definition.oam.dev/description: "component for test" + definition.oam.dev/version: "1.0.0" + definition.oam.dev/tags: "a=b,c=d" +spec: + workload: + definition: + apiVersion: apps/v1 + kind: Deployment + schematic: + groovy: + files: + - kind: COMPONENT + name: TEST_COMPONENT + path: dynamicscripts/TestComponent.groovy + frontend: + files: + - kind: CREATE + path: frontend/create.json + resources: + files: + - kind: YAML + path: resources/hello.yaml diff --git a/paas/appmanager/tesla-appmanager-plugin/src/test/resources/fixtures/plugins/hello/dynamicscripts/TestComponent.groovy b/paas/appmanager/tesla-appmanager-plugin/src/test/resources/fixtures/plugins/hello/dynamicscripts/TestComponent.groovy new file mode 100644 index 00000000..48323672 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-plugin/src/test/resources/fixtures/plugins/hello/dynamicscripts/TestComponent.groovy @@ -0,0 +1,65 @@ +package dynamicscripts + +import com.alibaba.tesla.appmanager.server.dynamicscript.handler.ComponentHandler + +class AbmHelmComponentHandler implements ComponentHandler { + + /** + * Handler 元信息 + */ + public static final String KIND = "COMPONENT" + public static final String NAME = "TEST_COMPONENT" + public static final Integer REVISION = 0 + + /** + * 获取 `COMPONENT_BUILD` 类型下的映射名称 + * + * @return 示例:`AbmChartDefault` + */ + @Override + String buildScriptName() { + return "AbmHelmComponentDefault" + } + + /** + * 获取 `COMPONENT_DEPLOY` 类型下的映射名称 + * + * @return 示例:`JobDefault` / `HelmDefault` + */ + @Override + String deployScriptName() { + return "AbmHelmComponentDefault" + } + + /** + * 获取 `COMPONENT_DESTROY` 类型下的映射名称 + * + * @return 示例:`HelmDefault` + */ + @Override + String destroyName() { + return "AbmHelmComponentDefault" + } + + /** + * 获取状态监听类型 + * + * @return 返回 `KUBERNETES_INFORMER` 或 `CRON` + */ + @Override + String watchKind() { + return "CRON" + } + + /** + * 如果 `watchKind` 返回 `KUBERNETES_INFORMER`,则对应 `COMPONENT_WATCH_KUBERNETES_INFORMER` 类型下的映射名称 + *

+ * 如果 `watchKind` 返回 `CRON`,则对应 `COMPONENT_WATCH_CRON` 类型下的映射名称 + * + * @return 返回对应类型下的映射名称 + */ + @Override + String watchScriptName() { + return "AbmHelmComponentCron" + } +} diff --git a/paas/appmanager/tesla-appmanager-plugin/src/test/resources/fixtures/plugins/hello/frontend/create.json b/paas/appmanager/tesla-appmanager-plugin/src/test/resources/fixtures/plugins/hello/frontend/create.json new file mode 100644 index 00000000..bbcc15e8 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-plugin/src/test/resources/fixtures/plugins/hello/frontend/create.json @@ -0,0 +1 @@ +{"a": "b"} diff --git a/paas/appmanager/tesla-appmanager-plugin/src/test/resources/fixtures/plugins/hello/resources/hello.yaml b/paas/appmanager/tesla-appmanager-plugin/src/test/resources/fixtures/plugins/hello/resources/hello.yaml new file mode 100644 index 00000000..68bc050a --- /dev/null +++ b/paas/appmanager/tesla-appmanager-plugin/src/test/resources/fixtures/plugins/hello/resources/hello.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: demo +data: + player_initial_lives: "3" diff --git a/paas/appmanager/tesla-appmanager-server/pom.xml b/paas/appmanager/tesla-appmanager-server/pom.xml index 9985c1c5..09798a46 100644 --- a/paas/appmanager/tesla-appmanager-server/pom.xml +++ b/paas/appmanager/tesla-appmanager-server/pom.xml @@ -7,7 +7,7 @@ com.alibaba.tesla tesla-appmanager - 1.0.4-SNAPSHOT + 1.0.5-SNAPSHOT ../pom.xml @@ -87,7 +87,6 @@ com.alibaba.tesla tesla-appmanager-storage - org.springframework.cloud @@ -182,6 +181,12 @@ aliyun-sdk-oss + + + com.aliyun.openservices + aliyun-log + + com.jayway.jsonpath diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/action/impl/deploy/app/ComponentCheckingDeployAppStateAction.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/action/impl/deploy/app/ComponentCheckingDeployAppStateAction.java index c0e3c2e1..704a1f71 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/action/impl/deploy/app/ComponentCheckingDeployAppStateAction.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/action/impl/deploy/app/ComponentCheckingDeployAppStateAction.java @@ -1,5 +1,6 @@ package com.alibaba.tesla.appmanager.server.action.impl.deploy.app; +import com.alibaba.tesla.appmanager.common.enums.ComponentTypeEnum; import com.alibaba.tesla.appmanager.common.enums.DeployAppAttrTypeEnum; import com.alibaba.tesla.appmanager.common.enums.DeployAppEventEnum; import com.alibaba.tesla.appmanager.common.enums.DeployAppStateEnum; @@ -94,15 +95,15 @@ public class ComponentCheckingDeployAppStateAction implements DeployAppStateActi attrMap.get(DeployAppAttrTypeEnum.APP_CONFIGURATION.toString())); for (DeployAppSchema.SpecComponent specComponent : configuration.getSpec().getComponents()) { DeployAppRevisionName revision = DeployAppRevisionName.valueOf(specComponent.getRevisionName()); - if (!revision.getComponentType().isNotAddon() || !revision.isEmptyVersion()) { + if (ComponentTypeEnum.isAddon(revision.getComponentType()) || !revision.isEmptyVersion()) { continue; } - String key = componentKey(revision.getComponentType().toString(), revision.getComponentName()); + String key = componentKey(revision.getComponentType(), revision.getComponentName()); String actualVersion = componentVersionMap.get(key); if (StringUtils.isEmpty(actualVersion)) { throw new AppException(AppErrorCode.INVALID_USER_ARGS, String.format("invalid deploy configuration, cannot find mapping component by componentType %s " + - "and componentName %s", revision.getComponentType().toString(), revision.getComponentName())); + "and componentName %s", revision.getComponentType(), revision.getComponentName())); } String newRevisionName = DeployAppRevisionName.builder() .componentType(revision.getComponentType()) diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/action/impl/deploy/app/ProcessingComponentDeployAppStateAction.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/action/impl/deploy/app/ProcessingComponentDeployAppStateAction.java index 8f03f892..8ef95dc7 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/action/impl/deploy/app/ProcessingComponentDeployAppStateAction.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/action/impl/deploy/app/ProcessingComponentDeployAppStateAction.java @@ -90,11 +90,11 @@ public class ProcessingComponentDeployAppStateAction implements DeployAppStateAc List packageTaskIdList = new ArrayList<>(); for (DeployAppSchema.SpecComponent specComponent : configuration.getSpec().getComponents()) { DeployAppRevisionName revision = DeployAppRevisionName.valueOf(specComponent.getRevisionName()); - if (!revision.getComponentType().isNotAddon() || !revision.isEmptyVersion()) { + if (ComponentTypeEnum.isAddon(revision.getComponentType()) || !revision.isEmptyVersion()) { continue; } - ComponentTypeEnum componentType = revision.getComponentType(); + String componentType = revision.getComponentType(); String componentName = revision.getComponentName(); // 叠加 component 局部参数 @@ -112,7 +112,7 @@ public class ProcessingComponentDeployAppStateAction implements DeployAppStateAc .appId(appId) .namespaceId(container.getNamespaceId()) .stageId(container.getStageId()) - .componentType(componentType.toString()) + .componentType(componentType) .componentName(componentName) .version(DefaultConstant.AUTO_VERSION) .options(options) diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/action/impl/deploy/app/ProcessingDeployAppStateAction.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/action/impl/deploy/app/ProcessingDeployAppStateAction.java index ebba699e..f30354cd 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/action/impl/deploy/app/ProcessingDeployAppStateAction.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/action/impl/deploy/app/ProcessingDeployAppStateAction.java @@ -38,8 +38,8 @@ import com.alibaba.tesla.dag.model.domain.dagnode.DagInstNodeType; import com.alibaba.tesla.dag.services.DagInstService; import com.hubspot.jinjava.Jinjava; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.exception.ExceptionUtils; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; @@ -304,6 +304,13 @@ public class ProcessingDeployAppStateAction implements DeployAppStateAction, App String appInstanceName = configuration.getMetadata().getAnnotations().getAppInstanceName(); for (DeployAppSchema.SpecComponent specComponent : configuration.getSpec().getComponents()) { Jinjava jinjava = JinjaFactory.getJinjava(); + if (specComponent.getClusterId() == null + || specComponent.getNamespaceId() == null + || specComponent.getStageId() == null) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("null name field in component scopes|revisionName=%s", + specComponent.getRevisionName())); + } String componentClusterId = jinjava.render(specComponent.getClusterId(), globalParameters); String componentNamespaceId = jinjava.render(specComponent.getNamespaceId(), globalParameters); String componentStageId = jinjava.render(specComponent.getStageId(), globalParameters); @@ -314,7 +321,7 @@ public class ProcessingDeployAppStateAction implements DeployAppStateAction, App } // 针对 appmeta / developmentmeta 两个特殊的 INTERNAL_ADDON component, 默认不进行应用实例的创建 DeployAppRevisionName revision = DeployAppRevisionName.valueOf(specComponent.getRevisionName()); - if (ComponentTypeEnum.INTERNAL_ADDON.equals(revision.getComponentType()) + if (ComponentTypeEnum.INTERNAL_ADDON.toString().equals(revision.getComponentType()) && ("appmeta".equals(revision.getComponentName()) || "developmentmeta".equals(revision.getComponentName()))) { continue; @@ -331,6 +338,10 @@ public class ProcessingDeployAppStateAction implements DeployAppStateAction, App } // 生成 DAG 参数并启动 + String overwriteParams = attrMap.get(DeployAppAttrTypeEnum.OVERWRITE_PARAMS.toString()); + if (overwriteParams == null) { + overwriteParams = ""; + } JSONObject variables = new JSONObject(); variables.put(DefaultConstant.DAG_TYPE, DagTypeEnum.DEPLOY_APP.toString()); variables.put(AppFlowVariableKey.DEPLOY_ID, deployAppId); @@ -342,6 +353,7 @@ public class ProcessingDeployAppStateAction implements DeployAppStateAction, App variables.put(AppFlowVariableKey.NAMESPACE_ID, order.getNamespaceId()); variables.put(AppFlowVariableKey.STAGE_ID, order.getStageId()); variables.put(AppFlowVariableKey.CONFIGURATION, attrMap.get(DeployAppAttrTypeEnum.APP_CONFIGURATION.toString())); + variables.put(AppFlowVariableKey.OVERWRITE_PARAMS, overwriteParams); variables.put(AppFlowVariableKey.COMPONENT_PACKAGES, JSONArray.toJSONString(componentPackages)); variables.put(AppFlowVariableKey.OWNER_REFERENCE, ownerReferenceStr); variables.put(AppFlowVariableKey.CREATOR, creator); @@ -354,14 +366,14 @@ public class ProcessingDeployAppStateAction implements DeployAppStateAction, App // 启动 Long dagInstId = dagInstService.start(dagName, variables, true); log.info("trigger deploy app dag success|deployAppId={}|appId={}|clusterId={}|namespaceId={}|stageId={}|" + - "dagInstId={}|dagId={}|dagName={}|nodes={}|edges={}", deployAppId, order.getAppId(), - order.getClusterId(), order.getNamespaceId(), order.getStageId(), dagInstId, dagId, dagName, - JSONArray.toJSON(nodes.stream() + "dagInstId={}|dagId={}|dagName={}|nodes={}|edges={}|overwriteParams={}", deployAppId, + order.getAppId(), order.getClusterId(), order.getNamespaceId(), order.getStageId(), dagInstId, + dagId, dagName, JSONArray.toJSON(nodes.stream() .map(DagCreateNode::getNodeId) .collect(Collectors.toList())), JSONArray.toJSON(edges.stream() .map(p -> String.format("%s->%s", p.getSourceNodeId(), p.getTargetNodeId())) - .collect(Collectors.toList()))); + .collect(Collectors.toList())), overwriteParams); order.setDeployProcessId(dagInstId); deployAppService.update(order); return dagInstId; diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/action/impl/deploy/app/WaitingComponentDeployAppStateAction.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/action/impl/deploy/app/WaitingComponentDeployAppStateAction.java index 090ede3c..4887e663 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/action/impl/deploy/app/WaitingComponentDeployAppStateAction.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/action/impl/deploy/app/WaitingComponentDeployAppStateAction.java @@ -4,10 +4,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.alibaba.tesla.appmanager.api.provider.AppPackageProvider; import com.alibaba.tesla.appmanager.common.channel.enums.DeployAppPackageConstant; -import com.alibaba.tesla.appmanager.common.enums.ComponentPackageTaskStateEnum; -import com.alibaba.tesla.appmanager.common.enums.DeployAppAttrTypeEnum; -import com.alibaba.tesla.appmanager.common.enums.DeployAppEventEnum; -import com.alibaba.tesla.appmanager.common.enums.DeployAppStateEnum; +import com.alibaba.tesla.appmanager.common.enums.*; import com.alibaba.tesla.appmanager.common.exception.AppErrorCode; import com.alibaba.tesla.appmanager.common.exception.AppException; import com.alibaba.tesla.appmanager.common.pagination.Pagination; @@ -113,7 +110,7 @@ public class WaitingComponentDeployAppStateAction implements DeployAppStateActio List packageTaskIdList = new ArrayList<>(); for (DeployAppSchema.SpecComponent specComponent : configuration.getSpec().getComponents()) { DeployAppRevisionName revision = DeployAppRevisionName.valueOf(specComponent.getRevisionName()); - if (!revision.getComponentType().isNotAddon() || !revision.isEmptyVersion()) { + if (ComponentTypeEnum.isAddon(revision.getComponentType()) || !revision.isEmptyVersion()) { continue; } @@ -135,10 +132,10 @@ public class WaitingComponentDeployAppStateAction implements DeployAppStateActio componentPackages.forEach(item -> { for (DeployAppSchema.SpecComponent specComponent : configuration.getSpec().getComponents()) { DeployAppRevisionName revision = DeployAppRevisionName.valueOf(specComponent.getRevisionName()); - if (!revision.getComponentType().isNotAddon() || !revision.isEmptyVersion()) { + if (ComponentTypeEnum.isAddon(revision.getComponentType()) || !revision.isEmptyVersion()) { continue; } - if (revision.getComponentType().toString().equals(item.getComponentType()) + if (revision.getComponentType().equals(item.getComponentType()) && revision.getComponentName().equals(item.getComponentName())) { String newRevisionName = DeployAppRevisionName.builder() .componentType(revision.getComponentType()) diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/action/impl/deploy/component/ProcessingDeployComponentStateAction.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/action/impl/deploy/component/ProcessingDeployComponentStateAction.java index b14f8f23..164c66eb 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/action/impl/deploy/component/ProcessingDeployComponentStateAction.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/action/impl/deploy/component/ProcessingDeployComponentStateAction.java @@ -113,7 +113,7 @@ public class ProcessingDeployComponentStateAction implements DeployComponentStat DeployAppRevisionName revisionName = DeployAppRevisionName.valueOf(subOrder.getIdentifier()); ComponentPackageQueryCondition condition = ComponentPackageQueryCondition.builder() .appId(subOrder.getAppId()) - .componentType(revisionName.getComponentType().toString()) + .componentType(revisionName.getComponentType()) .componentName(revisionName.getComponentName()) .packageVersion(revisionName.getVersion()) .withBlobs(false) @@ -161,9 +161,7 @@ public class ProcessingDeployComponentStateAction implements DeployComponentStat String ownerReference = attrMap.get(DeployComponentAttrTypeEnum.OWNER_REFERENCES.toString()); // Groovy 处理类获取,如果获取不到,则走原始 DAG 处理逻辑 - ComponentTypeEnum componentType = Enums - .getIfPresent(ComponentTypeEnum.class, componentPackageDO.getComponentType()).orNull(); - assert componentType != null; + String componentType = componentPackageDO.getComponentType(); String componentName = componentPackageDO.getComponentName(); DeployComponentHandler handler = groovyHandlerFactory.getByComponentType(DeployComponentHandler.class, subOrder.getAppId(), componentType, componentName, ComponentActionEnum.DEPLOY); diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/action/impl/deploy/component/RunningDeployComponentStateAction.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/action/impl/deploy/component/RunningDeployComponentStateAction.java index 9b452cc2..859d3237 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/action/impl/deploy/component/RunningDeployComponentStateAction.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/action/impl/deploy/component/RunningDeployComponentStateAction.java @@ -88,15 +88,13 @@ public class RunningDeployComponentStateAction implements DeployComponentStateAc DeployAppRevisionName revisionName = DeployAppRevisionName.valueOf(subOrder.getIdentifier()); ComponentPackageQueryCondition condition = ComponentPackageQueryCondition.builder() .appId(subOrder.getAppId()) - .componentType(revisionName.getComponentType().toString()) + .componentType(revisionName.getComponentType()) .componentName(revisionName.getComponentName()) .packageVersion(revisionName.getVersion()) .withBlobs(false) .build(); ComponentPackageDO componentPackageDO = componentPackageService.get(condition); - ComponentTypeEnum componentType = Enums - .getIfPresent(ComponentTypeEnum.class, componentPackageDO.getComponentType()).orNull(); - assert componentType != null; + String componentType = componentPackageDO.getComponentType(); String componentName = componentPackageDO.getComponentName(); // 获取 Groovy Handler,如果获取不到,那么走传统部署逻辑 diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/Addon.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/Addon.java index 9dfe5403..d20f9728 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/Addon.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/Addon.java @@ -72,7 +72,7 @@ public interface Addon { * * @return addonType */ - ComponentTypeEnum getAddonType(); + String getAddonType(); /** * 获取当前 Addon Schema 定义 diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/AddonInstanceManagerImpl.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/AddonInstanceManagerImpl.java index 7e06dec8..106adcaa 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/AddonInstanceManagerImpl.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/AddonInstanceManagerImpl.java @@ -64,7 +64,7 @@ public class AddonInstanceManagerImpl implements AddonInstanceManager { Map addonAttrs = request.getAddonAttrs(); // 检查 Addon Instance 是否存在,如果存在直接返回实例 ID - Addon addon = addonManager.getAddon(ComponentTypeEnum.RESOURCE_ADDON, request.getAddonId()); + Addon addon = addonManager.getAddon(ComponentTypeEnum.RESOURCE_ADDON.toString(), request.getAddonId()); AddonInstanceQueryCondition condition = AddonInstanceQueryCondition.builder() .namespaceId(namespaceId) .addonId(addonId) @@ -125,7 +125,7 @@ public class AddonInstanceManagerImpl implements AddonInstanceManager { } // TODO: release 的 addon instance task 类型,要 return 回去 - Addon addon = addonManager.getAddon(ComponentTypeEnum.RESOURCE_ADDON, addonInstance.getAddonId()); + Addon addon = addonManager.getAddon(ComponentTypeEnum.RESOURCE_ADDON.toString(), addonInstance.getAddonId()); addon.release(request); return null; } diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/AddonManager.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/AddonManager.java index b8e9f856..09cf3088 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/AddonManager.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/AddonManager.java @@ -53,7 +53,7 @@ public class AddonManager implements ApplicationListener { * @param addonId Addon ID * @return Addon 对象,如果不存在则抛出异常 */ - public Addon getAddon(ComponentTypeEnum componentType, String addonId) { + public Addon getAddon(String componentType, String addonId) { Addon addon = this.addonMap.get(AddonUtil.combineAddonKey(componentType, addonId)); if (addon == null) { throw new AppException(AppErrorCode.INVALID_USER_ARGS, @@ -92,12 +92,12 @@ public class AddonManager implements ApplicationListener { addonMap.put(key, addon); // 更新当前插件信息到数据库中 - ComponentTypeEnum addonType = addon.getAddonType(); + String addonType = addon.getAddonType(); String addonId = addon.getAddonId(); AddonMetaDO meta = addonMetaRepository.get(addonType, addonId); if (meta == null) { meta = AddonMetaDO.builder() - .addonType(addonType.toString()) + .addonType(addonType) .addonId(addonId) .addonVersion(DefaultConstant.AUTO_VERSION) .addonLabel(addon.getAddonLabel()) @@ -110,7 +110,7 @@ public class AddonManager implements ApplicationListener { } else { // addon version 已废弃 meta.setAddonVersion(DefaultConstant.AUTO_VERSION); - meta.setAddonType(addon.getAddonType().toString()); + meta.setAddonType(addon.getAddonType()); meta.setAddonLabel(addon.getAddonLabel()); meta.setAddonDescription(addon.getAddonDescription()); meta.setAddonSchema(SchemaUtil.toYamlMapStr(addon.getAddonSchema())); diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/inner/Authproxy100InternalAddon.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/inner/Authproxy100InternalAddon.java index 87574e42..e46c0430 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/inner/Authproxy100InternalAddon.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/inner/Authproxy100InternalAddon.java @@ -23,7 +23,7 @@ import javax.annotation.PostConstruct; public class Authproxy100InternalAddon extends BaseAddon { @Getter - private final ComponentTypeEnum addonType = ComponentTypeEnum.INTERNAL_ADDON; + private final String addonType = ComponentTypeEnum.INTERNAL_ADDON.toString(); @Getter private final String addonId = "authproxy"; diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/inner/Check100InternalAddon.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/inner/Check100InternalAddon.java index 1201b17c..2bc3b338 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/inner/Check100InternalAddon.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/inner/Check100InternalAddon.java @@ -23,7 +23,7 @@ import javax.annotation.PostConstruct; public class Check100InternalAddon extends BaseAddon { @Getter - private final ComponentTypeEnum addonType = ComponentTypeEnum.INTERNAL_ADDON; + private final String addonType = ComponentTypeEnum.INTERNAL_ADDON.toString(); @Getter private final String addonId = "check"; diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/inner/Checkmonitor100InternalAddon.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/inner/Checkmonitor100InternalAddon.java index 15939fc9..4c2341b5 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/inner/Checkmonitor100InternalAddon.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/inner/Checkmonitor100InternalAddon.java @@ -23,7 +23,7 @@ import javax.annotation.PostConstruct; public class Checkmonitor100InternalAddon extends BaseAddon { @Getter - private final ComponentTypeEnum addonType = ComponentTypeEnum.INTERNAL_ADDON; + private final String addonType = ComponentTypeEnum.INTERNAL_ADDON.toString(); @Getter private final String addonId = "check_monitor"; diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/inner/Productops100InternalAddon.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/inner/Productops100InternalAddon.java index 54e897d0..cb54fc32 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/inner/Productops100InternalAddon.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/inner/Productops100InternalAddon.java @@ -23,7 +23,7 @@ import javax.annotation.PostConstruct; public class Productops100InternalAddon extends BaseAddon { @Getter - private final ComponentTypeEnum addonType = ComponentTypeEnum.INTERNAL_ADDON; + private final String addonType = ComponentTypeEnum.INTERNAL_ADDON.toString(); @Getter private final String addonId = "productops"; diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/inner/ProductopsV2100InternalAddon.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/inner/ProductopsV2100InternalAddon.java index f538562f..b4f3920c 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/inner/ProductopsV2100InternalAddon.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/inner/ProductopsV2100InternalAddon.java @@ -23,7 +23,7 @@ import javax.annotation.PostConstruct; public class ProductopsV2100InternalAddon extends BaseAddon { @Getter - private final ComponentTypeEnum addonType = ComponentTypeEnum.INTERNAL_ADDON; + private final String addonType = ComponentTypeEnum.INTERNAL_ADDON.toString(); @Getter private final String addonId = "productopsv2"; diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/inner/Taskplatform100InternalAddon.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/inner/Taskplatform100InternalAddon.java index d5f28aa4..965bfa99 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/inner/Taskplatform100InternalAddon.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/inner/Taskplatform100InternalAddon.java @@ -23,7 +23,7 @@ import javax.annotation.PostConstruct; public class Taskplatform100InternalAddon extends BaseAddon { @Getter - private final ComponentTypeEnum addonType = ComponentTypeEnum.INTERNAL_ADDON; + private final String addonType = ComponentTypeEnum.INTERNAL_ADDON.toString(); @Getter private final String addonId = "taskplatform"; diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/inner/TianjiProductops100InternalAddon.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/inner/TianjiProductops100InternalAddon.java index 69571c50..4a1346c6 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/inner/TianjiProductops100InternalAddon.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/inner/TianjiProductops100InternalAddon.java @@ -23,7 +23,7 @@ import javax.annotation.PostConstruct; public class TianjiProductops100InternalAddon extends BaseAddon { @Getter - private final ComponentTypeEnum addonType = ComponentTypeEnum.INTERNAL_ADDON; + private final String addonType = ComponentTypeEnum.INTERNAL_ADDON.toString(); @Getter private final String addonId = "tianji_productops"; diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/inner/Zmn100InternalAddon.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/inner/Zmn100InternalAddon.java index c79e8fff..fbbedbe2 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/inner/Zmn100InternalAddon.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/inner/Zmn100InternalAddon.java @@ -23,7 +23,7 @@ import javax.annotation.PostConstruct; public class Zmn100InternalAddon extends BaseAddon { @Getter - private final ComponentTypeEnum addonType = ComponentTypeEnum.INTERNAL_ADDON; + private final String addonType = ComponentTypeEnum.INTERNAL_ADDON.toString(); @Getter private final String addonId = "zmn"; diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/resources/SystemEnvResourceAddon.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/resources/SystemEnvResourceAddon.java index 06f7f5c5..94d1016f 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/resources/SystemEnvResourceAddon.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/resources/SystemEnvResourceAddon.java @@ -32,7 +32,7 @@ import java.util.Map; public class SystemEnvResourceAddon extends BaseAddon { @Getter - private final ComponentTypeEnum addonType = ComponentTypeEnum.RESOURCE_ADDON; + private final String addonType = ComponentTypeEnum.RESOURCE_ADDON.toString(); @Getter private final String addonId = "system-env"; diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/resources/TerraformResourceAddon.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/resources/TerraformResourceAddon.java index 5a019d1a..8b87a9ec 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/resources/TerraformResourceAddon.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/resources/TerraformResourceAddon.java @@ -43,7 +43,7 @@ import java.util.Map; public class TerraformResourceAddon extends BaseAddon { @Getter - private final ComponentTypeEnum addonType = ComponentTypeEnum.RESOURCE_ADDON; + private final String addonType = ComponentTypeEnum.RESOURCE_ADDON.toString(); @Getter private final String addonId = "terraform"; @@ -72,6 +72,7 @@ public class TerraformResourceAddon extends BaseAddon { " annotations: {}\n" + " name: terraform\n" + " spec:\n" + + " variables: []\n" + " environments: []\n" + " configuration:\n" + " git:\n" + @@ -159,6 +160,22 @@ public class TerraformResourceAddon extends BaseAddon { } } + // 如果存在 variables,那么写入 terraform.tfvars.json 文件 + Map variables = getVariables(spec); + if (variables.size() > 0) { + Path variablePath = Paths.get(gitDir.toString(), "terraform.tfvars.json"); + String variableContent = JSONObject.toJSONString(variables); + try { + Files.writeString(variablePath, variableContent, StandardCharsets.UTF_8); + } catch (IOException e) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("cannot write terraform.tfvars.json content|%s|path=%s|content=%s", + logSuffix, variablePath, variableContent)); + } + log.info("write terraform.tfvars.json succeed|{}|path={}|content={}", + logSuffix, variablePath, variableContent); + } + // 准备环境变量并执行命令 Map environments = getEnvironments(spec); String applyCommand = String.format("cd %s; /app/terraform apply -auto-approve -no-color", gitDir); @@ -220,6 +237,28 @@ public class TerraformResourceAddon extends BaseAddon { return result; } + /** + * 获取 spec 中定义的运行参数 + * + * @param spec Spec + * @return 环境变量 + */ + private Map getVariables(JSONObject spec) { + Map result = new HashMap<>(); + JSONArray specVariables = spec.getJSONArray("variables"); + if (specVariables != null) { + for (JSONObject env : specVariables.toJavaList(JSONObject.class)) { + String name = env.getString("name"); + String value = env.getString("value"); + if (StringUtils.isAnyEmpty(name, value)) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "invalid variables in terraform spec"); + } + result.put(name, value); + } + } + return result; + } + /** * 克隆 Git 仓库到本地目录 * diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/task/dag/AddonInstanceTaskRunnerNode.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/task/dag/AddonInstanceTaskRunnerNode.java index 07158a19..c4ea4508 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/task/dag/AddonInstanceTaskRunnerNode.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/addon/task/dag/AddonInstanceTaskRunnerNode.java @@ -44,7 +44,7 @@ public class AddonInstanceTaskRunnerNode extends AbstractLocalNodeBase { ApplyAddonInstanceReq request = JSONObject.parseObject(requestStr, ApplyAddonInstanceReq.class); // 进行 addon 申请,高耗时操作,禁止一切事务 - Addon addon = addonManager.getAddon(ComponentTypeEnum.RESOURCE_ADDON, request.getAddonId()); + Addon addon = addonManager.getAddon(ComponentTypeEnum.RESOURCE_ADDON.toString(), request.getAddonId()); ApplyAddonRes res = addon.apply(request); ComponentSchema addonSchema = res.getComponentSchema(); String signature = res.getSignature(); diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/assembly/AppComponentDtoConvert.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/assembly/AppComponentDtoConvert.java new file mode 100644 index 00000000..508a57d5 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/assembly/AppComponentDtoConvert.java @@ -0,0 +1,38 @@ +package com.alibaba.tesla.appmanager.server.assembly; + +import com.alibaba.tesla.appmanager.common.assembly.BaseDtoConvert; +import com.alibaba.tesla.appmanager.common.util.ClassUtil; +import com.alibaba.tesla.appmanager.domain.container.DeployConfigTypeId; +import com.alibaba.tesla.appmanager.domain.dto.AppComponentDTO; +import com.alibaba.tesla.appmanager.plugin.repository.domain.PluginDefinitionDO; +import com.alibaba.tesla.appmanager.server.repository.domain.AppComponentDO; +import org.springframework.stereotype.Component; + +/** + * 应用绑定组件 转换器 + * + * @author yaoxing.gyx@alibaba-inc.com + */ +@Component +public class AppComponentDtoConvert extends BaseDtoConvert { + + public AppComponentDtoConvert() { + super(AppComponentDTO.class, AppComponentDO.class); + } + + public AppComponentDTO to(AppComponentDO appComponentDO, PluginDefinitionDO pluginDefinitionDO) { + if (appComponentDO == null) { + return null; + } + + AppComponentDTO result = new AppComponentDTO(); + ClassUtil.copy(appComponentDO, result); + result.setPluginVersion(pluginDefinitionDO.getPluginVersion()); + // 通过当前方法转换的记录,均为 compatible=false + result.setCompatible(false); + // 自动转换当前类型映射的 typeId + DeployConfigTypeId typeId = new DeployConfigTypeId(result.getComponentType(), result.getComponentName()); + result.setTypeId(typeId.toString()); + return result; + } +} diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/AddonController.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/AddonController.java index be378fe6..1145d32a 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/AddonController.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/AddonController.java @@ -8,6 +8,8 @@ import com.alibaba.tesla.appmanager.domain.dto.AddonMetaDTO; import com.alibaba.tesla.appmanager.domain.req.AddonMetaQueryReq; import com.alibaba.tesla.appmanager.domain.req.appaddon.AppAddonSyncReq; import com.alibaba.tesla.common.base.TeslaBaseResult; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @@ -18,6 +20,7 @@ import org.springframework.web.bind.annotation.*; * @author qiuqiang.qq@alibaba-inc.com */ @RequestMapping("/addon") +@Tag(name = "Addon API") @RestController @Slf4j public class AddonController extends AppManagerBaseController { @@ -35,24 +38,25 @@ public class AddonController extends AppManagerBaseController { * @apiParam (GET Parameters) {Number} page 当前页 * @apiParam (GET Parameters) {Number} pageSize 每页大小 */ + @Operation(summary = "查询 Addon 列表") @GetMapping public TeslaBaseResult list(@ModelAttribute AddonMetaQueryReq request) { return buildSucceedResult(addonMetaProvider.list(request)); } - // 新增 Addon + @Operation(summary = "创建 Addon") @PostMapping public TeslaBaseResult save(@RequestBody AddonMetaDTO metaDTO) { return buildSucceedResult(addonMetaProvider.create(metaDTO)); } - // 获取指定 Addon + @Operation(summary = "查询 Addon 详情") @GetMapping("/{id}") public TeslaBaseResult getById(@PathVariable("id") Long id) { return buildSucceedResult(addonMetaProvider.get(id)); } - // 同步全量 addon 绑定关系 + @Operation(summary = "同步全量 Addon 绑定关系") @PutMapping("/sync") public TeslaBaseResult sync(@RequestHeader(value = "X-Biz-App", required = false) String headerBizApp) { BizAppContainer container = BizAppContainer.valueOf(headerBizApp); @@ -66,7 +70,7 @@ public class AddonController extends AppManagerBaseController { return buildSucceedResult(DefaultConstant.EMPTY_OBJ); } - // 更新指定 Addon + @Operation(summary = "更新 Addon") @PutMapping("/{id}") public TeslaBaseResult update(@PathVariable("id") Long id, @RequestBody AddonMetaDTO metaDTO) { metaDTO.setId(id); @@ -74,7 +78,7 @@ public class AddonController extends AppManagerBaseController { return buildSucceedResult(DefaultConstant.EMPTY_OBJ); } - // 删除指定 Addon + @Operation(summary = "删除 Addon") @DeleteMapping("/{id}") public TeslaBaseResult update(@PathVariable("id") Long id) { addonMetaProvider.delete(id); diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/AppAddonController.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/AppAddonController.java index 5b4a838f..546e81c5 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/AppAddonController.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/AppAddonController.java @@ -17,6 +17,7 @@ import com.alibaba.tesla.appmanager.domain.req.AppAddonQueryReq; import com.alibaba.tesla.appmanager.domain.req.AppAddonUpdateReq; import com.alibaba.tesla.appmanager.domain.schema.ComponentSchema; import com.alibaba.tesla.common.base.TeslaBaseResult; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -32,6 +33,7 @@ import java.util.Objects; * * @author qianmo.zm@alibaba-inc.com */ +@Tag(name = "应用关联 Addon API") @RequestMapping("/apps/{appId}/addon") @RestController @Slf4j diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/AppComponentController.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/AppComponentController.java index b5cbd123..86c266ec 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/AppComponentController.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/AppComponentController.java @@ -2,9 +2,18 @@ package com.alibaba.tesla.appmanager.server.controller; import com.alibaba.tesla.appmanager.api.provider.AppComponentProvider; import com.alibaba.tesla.appmanager.auth.controller.AppManagerBaseController; +import com.alibaba.tesla.appmanager.common.constants.DefaultConstant; +import com.alibaba.tesla.appmanager.common.exception.AppErrorCode; +import com.alibaba.tesla.appmanager.common.exception.AppException; import com.alibaba.tesla.appmanager.domain.container.BizAppContainer; +import com.alibaba.tesla.appmanager.domain.dto.AppComponentDTO; +import com.alibaba.tesla.appmanager.domain.req.appcomponent.AppComponentCreateReq; +import com.alibaba.tesla.appmanager.domain.req.appcomponent.AppComponentDeleteReq; import com.alibaba.tesla.appmanager.domain.req.appcomponent.AppComponentQueryReq; +import com.alibaba.tesla.appmanager.domain.req.appcomponent.AppComponentUpdateReq; import com.alibaba.tesla.common.base.TeslaBaseResult; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.oauth2.provider.OAuth2Authentication; @@ -16,6 +25,7 @@ import org.springframework.web.bind.annotation.*; * @author yaoxing.gyx@alibaba-inc.com */ @Slf4j +@Tag(name = "应用关联组件 API") @RequestMapping("/apps/{appId}/components") @RestController public class AppComponentController extends AppManagerBaseController { @@ -23,24 +33,94 @@ public class AppComponentController extends AppManagerBaseController { @Autowired private AppComponentProvider appComponentProvider; - /** - * @api {get} /apps/:appId/components 获取应用绑定的组件列表 - * @apiName GetApplicationComponentList - * @apiGroup 应用关联组件 API - * @apiParam (Path Parameters) {String} appId 应用 ID - */ @GetMapping + @Operation(summary = "获取应用关联的组件列表") public TeslaBaseResult list( @PathVariable String appId, @RequestHeader(value = "X-Biz-App", required = false) String headerBizApp, @ModelAttribute AppComponentQueryReq req, OAuth2Authentication auth) { BizAppContainer container = BizAppContainer.valueOf(headerBizApp); - return buildSucceedResult(appComponentProvider.list(AppComponentQueryReq.builder() - .appId(appId) - .namespaceId(container.getNamespaceId()) - .stageId(container.getStageId()) - .arch(req.getArch()) - .build(), getOperator(auth))); + req.setAppId(appId); + req.setNamespaceId(container.getNamespaceId()); + req.setStageId(container.getStageId()); + return buildSucceedResult(appComponentProvider.list(req, getOperator(auth))); + } + + @PostMapping + @Operation(summary = "创建应用关联的指定组件") + public TeslaBaseResult create( + @PathVariable String appId, + @RequestHeader(value = "X-Biz-App", required = false) String headerBizApp, + @RequestBody AppComponentCreateReq request, + OAuth2Authentication auth) { + BizAppContainer container = BizAppContainer.valueOf(headerBizApp); + request.setAppId(appId); + request.setNamespaceId(container.getNamespaceId()); + request.setStageId(container.getStageId()); + AppComponentDTO result = appComponentProvider.create(request, getOperator(auth)); + return buildSucceedResult(result); + } + + @GetMapping("{appComponentId}") + @Operation(summary = "获取应用关联的指定组件") + public TeslaBaseResult get( + @PathVariable String appId, + @PathVariable Long appComponentId, + @RequestHeader(value = "X-Biz-App", required = false) String headerBizApp, + OAuth2Authentication auth) { + BizAppContainer container = BizAppContainer.valueOf(headerBizApp); + AppComponentDTO result = appComponentProvider.get( + AppComponentQueryReq.builder().id(appComponentId).build(), + getOperator(auth)); + if (!container.getNamespaceId().equals(result.getNamespaceId()) + || !container.getStageId().equals(result.getStageId()) + || !appId.equals(result.getAppId())) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "mismatched appId/namespaceId/stageId"); + } + return buildSucceedResult(result); + } + + @PutMapping("{appComponentId}") + @Operation(summary = "更新应用关联的指定组件") + public TeslaBaseResult update( + @PathVariable String appId, + @PathVariable Long appComponentId, + @RequestHeader(value = "X-Biz-App", required = false) String headerBizApp, + @RequestBody AppComponentUpdateReq request, + OAuth2Authentication auth) { + BizAppContainer container = BizAppContainer.valueOf(headerBizApp); + request.setId(appComponentId); + request.setNamespaceId(container.getNamespaceId()); + request.setStageId(container.getStageId()); + AppComponentDTO result = appComponentProvider.update(request, getOperator(auth)); + return buildSucceedResult(result); + } + + @DeleteMapping("{appComponentId}") + @Operation(summary = "删除应用关联的指定组件") + public TeslaBaseResult delete( + @PathVariable String appId, + @PathVariable Long appComponentId, + @RequestHeader(value = "X-Biz-App", required = false) String headerBizApp, + OAuth2Authentication auth) { + String operator = getOperator(auth); + BizAppContainer container = BizAppContainer.valueOf(headerBizApp); + AppComponentDTO record = appComponentProvider.get(AppComponentQueryReq.builder() + .id(appComponentId) + .build(), operator); + if (record == null) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "cannot find specified app component record"); + } + if (!record.getAppId().equals(appId) + || !record.getNamespaceId().equals(container.getNamespaceId()) + || !record.getStageId().equals(container.getStageId())) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "mismatched appId/namespaceId/stageId"); + } + AppComponentDeleteReq request = AppComponentDeleteReq.builder() + .id(appComponentId) + .build(); + appComponentProvider.delete(request, operator); + return buildSucceedResult(DefaultConstant.EMPTY_OBJ); } } diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/AppComponentPackageController.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/AppComponentPackageController.java index a0061809..42672503 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/AppComponentPackageController.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/AppComponentPackageController.java @@ -5,6 +5,7 @@ import com.alibaba.tesla.appmanager.auth.controller.AppManagerBaseController; import com.alibaba.tesla.appmanager.domain.req.componentpackage.ComponentPackageLatestVersionListReq; import com.alibaba.tesla.appmanager.domain.req.componentpackage.ComponentPackageQueryReq; import com.alibaba.tesla.common.base.TeslaBaseResult; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.oauth2.provider.OAuth2Authentication; @@ -16,6 +17,7 @@ import org.springframework.web.bind.annotation.*; * @author yaoxing.gyx@alibaba-inc.com */ @Slf4j +@Tag(name = "组件包 API") @RequestMapping("/apps/{appId}/component-packages") @RestController public class AppComponentPackageController extends AppManagerBaseController { diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/AppComponentPackageTaskController.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/AppComponentPackageTaskController.java index 525be5f0..1fd033b2 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/AppComponentPackageTaskController.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/AppComponentPackageTaskController.java @@ -13,6 +13,7 @@ import com.alibaba.tesla.appmanager.domain.res.componentpackage.ComponentPackage import com.alibaba.tesla.appmanager.server.event.componentpackage.ComponentPackageTaskStartEvent; import com.alibaba.tesla.common.base.TeslaBaseResult; import com.google.common.collect.ImmutableMap; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -28,6 +29,7 @@ import javax.servlet.http.HttpServletRequest; * @author yaoxing.gyx@alibaba-inc.com */ @Slf4j +@Tag(name = "组件包任务 API") @RequestMapping("/apps/{appId}/component-package-tasks") @RestController public class AppComponentPackageTaskController extends AppManagerBaseController { diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/AppController.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/AppController.java index 10a148d1..d575a689 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/AppController.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/AppController.java @@ -18,6 +18,8 @@ import com.alibaba.tesla.appmanager.domain.res.appmeta.AppGetVersionRes; import com.alibaba.tesla.appmanager.domain.res.apppackage.ApplicationConfigurationGenerateRes; import com.alibaba.tesla.appmanager.domain.res.deployconfig.DeployConfigGenerateRes; import com.alibaba.tesla.common.base.TeslaBaseResult; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -29,6 +31,7 @@ import org.springframework.web.bind.annotation.*; * * @author qianmo.zm@alibaba-inc.com */ +@Tag(name = "应用 API") @RequestMapping("/apps") @RestController @Slf4j @@ -40,26 +43,14 @@ public class AppController extends AppManagerBaseController { @Autowired private DeployConfigProvider deployConfigProvider; - /** - * @api {get} /apps 获取应用列表 - * @apiName GetAppList - * @apiGroup 应用 API - * @apiParam (GET Parameters) {Number} page 当前页 - * @apiParam (GET Parameters) {Number} pageSize 每页大小 - */ + @Operation(summary = "查询应用列表") @GetMapping public TeslaBaseResult list(AppMetaQueryReq request, OAuth2Authentication auth) { Pagination pagination = appMetaProvider.list(request, getOperator(auth), false); return buildSucceedResult(pagination); } - /** - * @api {post} /apps 新增应用 - * @apiName PostApp - * @apiGroup 应用 API - * @apiParam (JSON Body) {String} appId 应用 ID - * @apiParam (JSON Body) {Object} options 应用扩展信息 - */ + @Operation(summary = "创建应用") @PostMapping public TeslaBaseResult create( @RequestBody AppMetaUpdateReq request, @@ -70,12 +61,7 @@ public class AppController extends AppManagerBaseController { return buildSucceedResult(result); } - /** - * @api {get} /apps/:appId 获取指定应用信息 - * @apiName GetApp - * @apiGroup 应用 API - * @apiParam (Path Parameters) {String} appId 应用 ID - */ + @Operation(summary = "查询应用详情") @GetMapping(value = "/{appId}") public TeslaBaseResult get(@PathVariable String appId, OAuth2Authentication auth) { AppMetaDTO result = appMetaProvider.get(appId, getOperator(auth)); @@ -86,25 +72,14 @@ public class AppController extends AppManagerBaseController { return buildSucceedResult(result); } - /** - * @api {get} /apps/:appId/version 获取指定应用的所属版本 v1 or v2 - * @apiName GetApp - * @apiGroup 应用 API - * @apiParam (Path Parameters) {String} appId 应用 ID - */ + @Operation(summary = "查询应用版本 (Frontend)") @GetMapping(value = "/{appId}/version") public TeslaBaseResult getFrontendVersion(@PathVariable String appId, OAuth2Authentication auth) { String version = appMetaProvider.getFrontendVersion(appId, getOperator(auth)); return buildSucceedResult(AppGetVersionRes.builder().version(version).build()); } - /** - * @api {put} /apps/:appId 更新指定应用信息 - * @apiName PutApp - * @apiGroup 应用 API - * @apiParam (Path Parameters) {String} appId 应用 ID - * @apiParam (JSON Body) {Object} options 应用扩展信息 - */ + @Operation(summary = "更新应用详情") @PutMapping(value = "/{appId}") public TeslaBaseResult update( @PathVariable String appId, @@ -117,25 +92,14 @@ public class AppController extends AppManagerBaseController { return buildSucceedResult(result); } - /** - * @api {put} /apps 更新指定应用信息 - * @apiName PutApp - * @apiGroup 应用 API - * @apiParam (Path Parameters) {String} appId 应用 ID - * @apiParam (JSON Body) {Object} options 应用扩展信息 - */ + @Operation(summary = "更新应用详情 (兼容API)") @PutMapping public TeslaBaseResult updateCompatible(@RequestBody AppMetaUpdateReq request, OAuth2Authentication auth) { AppMetaDTO result = appMetaProvider.save(request, getOperator(auth)); return buildSucceedResult(result); } - /** - * @api {delete} /apps/:appId 删除指定应用信息 - * @apiName DeleteApp - * @apiGroup 应用 API - * @apiParam (Path Parameters) {String} appId 应用 ID - */ + @Operation(summary = "删除应用") @DeleteMapping(value = "/{appId}") public TeslaBaseResult delete( @PathVariable String appId, @ModelAttribute AppMetaDeleteReq request, OAuth2Authentication auth) { @@ -152,12 +116,7 @@ public class AppController extends AppManagerBaseController { return buildSucceedResult(result); } - /** - * @api {put} /apps/:appId/application-configurations 更新指定应用的部署信息 - * @apiName PutAppApplicationConfigurations - * @apiGroup 应用 API - * @apiParam (Path Parameters) {String} appId 应用 ID - */ + @Operation(summary = "更新应用部署信息") @PutMapping(value = "/{appId}/application-configurations") public TeslaBaseResult updateApplicationConfigurations( @PathVariable String appId, @@ -172,12 +131,7 @@ public class AppController extends AppManagerBaseController { return buildSucceedResult(deployConfigProvider.applyTemplate(request)); } - /** - * @api {get} /apps/:appId/application-configurations 获取指定应用的部署信息 - * @apiName GetAppApplicationConfigurations - * @apiGroup 应用 API - * @apiParam (Path Parameters) {String} appId 应用 ID - */ + @Operation(summary = "查询应用部署信息") @GetMapping(value = "/{appId}/application-configurations") public TeslaBaseResult getApplicationConfigurations( @PathVariable String appId, @@ -199,12 +153,7 @@ public class AppController extends AppManagerBaseController { .build()); } - - /** - * @api {delete} /apps/:appId/application-configurations 删除指定应用的部署信息 - * @apiName DeleteApplicationConfigurations - * @apiGroup Application Configuration API - */ + @Operation(summary = "删除应用部署信息") @DeleteMapping(value = "/{appId}/application-configurations") public TeslaBaseResult deleteApplicationConfigurations( @PathVariable String appId, diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/AppPackageController.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/AppPackageController.java index 53fcca5b..d911e9f4 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/AppPackageController.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/AppPackageController.java @@ -16,6 +16,7 @@ import com.alibaba.tesla.appmanager.server.repository.condition.AppPackageTagQue import com.alibaba.tesla.appmanager.server.repository.domain.AppPackageTagDO; import com.alibaba.tesla.appmanager.server.service.apppackage.AppPackageTagService; import com.alibaba.tesla.common.base.TeslaBaseResult; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.InputStreamResource; @@ -43,6 +44,7 @@ import java.util.Collections; * @author yaoxing.gyx@alibaba-inc.com */ @Slf4j +@Tag(name = "应用包 API") @RequestMapping("/apps/{appId}/app-packages") @RestController public class AppPackageController extends AppManagerBaseController { diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/AppPackageTaskController.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/AppPackageTaskController.java index 2dc9e2b9..2f8078db 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/AppPackageTaskController.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/AppPackageTaskController.java @@ -21,6 +21,8 @@ import com.alibaba.tesla.appmanager.domain.req.apppackage.ComponentBinder; import com.alibaba.tesla.appmanager.domain.req.componentpackage.ComponentPackageLatestVersionListReq; import com.alibaba.tesla.appmanager.domain.res.apppackage.AppPackageTaskCreateRes; import com.alibaba.tesla.common.base.TeslaBaseResult; +import com.google.common.base.Enums; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -39,6 +41,7 @@ import static com.alibaba.tesla.appmanager.common.constants.DefaultConstant.INTE * @author yaoxing.gyx@alibaba-inc.com */ @Slf4j +@Tag(name = "应用包任务 API") @RequestMapping @RestController public class AppPackageTaskController extends AppManagerBaseController { @@ -167,25 +170,29 @@ public class AppPackageTaskController extends AppManagerBaseController { .build(), operator ); if (CollectionUtils.isEmpty(appComponents)) { - throw new AppException(AppErrorCode.INVALID_USER_ARGS, "missing package component"); + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("missing package component|appId=%s|namespaceId=%s|stageId=%s", + appId, namespaceId, stageId)); } List components = new ArrayList<>(); for (AppComponentDTO appComponent : appComponents) { + String componentType = appComponent.getComponentType(); + // 默认填充 AUTO_VERSION 到 version 字段,在构建时触发版本号自动向前滚动 ComponentBinder componentBinder = ComponentBinder.builder() - .componentType(appComponent.getComponentType()) + .componentType(componentType) .componentName(appComponent.getComponentName()) - .componentLabel(appComponent.getComponentLabel()) - .version(appComponent.getComponentVersion()) + .category(appComponent.getCategory()) + .version(DefaultConstant.AUTO_VERSION) .isDevelop(request.isDevelop()) .build(); - if (appComponent.getComponentType().isKubernetesMicroservice()) { + if (ComponentTypeEnum.K8S_MICROSERVICE.toString().equals(componentType)) { componentBinder.setBranch(DefaultConstant.DEFAULT_REPO_BRANCH); List componentVersionList = componentPackageProvider .latestVersions( ComponentPackageLatestVersionListReq.builder() .appId(appId) - .componentType(appComponent.getComponentType().toString()) + .componentType(appComponent.getComponentType()) .componentName(appComponent.getComponentName()) .build(), operator); @@ -193,13 +200,13 @@ public class AppPackageTaskController extends AppManagerBaseController { return buildClientErrorResult(appComponent.getComponentName() + " 最新版本号缺失"); } componentBinder.setVersion(componentVersionList.get(0).getName()); - } else if (appComponent.getComponentType().isHelm()) { + } else if (ComponentTypeEnum.HELM.toString().equals(componentType)) { componentBinder.setBranch(DefaultConstant.DEFAULT_REPO_BRANCH); List componentVersionList = componentPackageProvider .latestVersions( ComponentPackageLatestVersionListReq.builder() .appId(appId) - .componentType(appComponent.getComponentType().toString()) + .componentType(appComponent.getComponentType()) .componentName(appComponent.getComponentName()) .build(), operator); @@ -213,17 +220,15 @@ public class AppPackageTaskController extends AppManagerBaseController { if (request.isDevelop()) { ComponentBinder developmentMeta = ComponentBinder.builder() - .componentType(ComponentTypeEnum.INTERNAL_ADDON) + .componentType(ComponentTypeEnum.INTERNAL_ADDON.toString()) .componentName(INTERNAL_ADDON_DEVELOPMENT_META) - .componentLabel("Development Meta") .version(DefaultConstant.INIT_VERSION) .build(); components.add(developmentMeta); ComponentBinder appMeta = ComponentBinder.builder() - .componentType(ComponentTypeEnum.INTERNAL_ADDON) + .componentType(ComponentTypeEnum.INTERNAL_ADDON.toString()) .componentName(INTERNAL_ADDON_APP_META) - .componentLabel("App Meta") .version(DefaultConstant.INIT_VERSION) .build(); components.add(appMeta); diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/ApplicationConfigurationController.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/ApplicationConfigurationController.java index 8fb927f8..59e6926f 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/ApplicationConfigurationController.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/ApplicationConfigurationController.java @@ -5,14 +5,17 @@ import com.alibaba.tesla.appmanager.auth.controller.AppManagerBaseController; import com.alibaba.tesla.appmanager.common.constants.DefaultConstant; import com.alibaba.tesla.appmanager.common.exception.AppErrorCode; import com.alibaba.tesla.appmanager.common.exception.AppException; +import com.alibaba.tesla.appmanager.common.pagination.Pagination; import com.alibaba.tesla.appmanager.common.util.SchemaUtil; import com.alibaba.tesla.appmanager.domain.container.BizAppContainer; -import com.alibaba.tesla.appmanager.domain.req.deployconfig.DeployConfigApplyTemplateReq; -import com.alibaba.tesla.appmanager.domain.req.deployconfig.DeployConfigDeleteReq; -import com.alibaba.tesla.appmanager.domain.req.deployconfig.DeployConfigGenerateReq; +import com.alibaba.tesla.appmanager.domain.container.DeployConfigTypeId; +import com.alibaba.tesla.appmanager.domain.dto.DeployConfigDTO; +import com.alibaba.tesla.appmanager.domain.req.deployconfig.*; import com.alibaba.tesla.appmanager.domain.res.apppackage.ApplicationConfigurationGenerateRes; import com.alibaba.tesla.appmanager.domain.res.deployconfig.DeployConfigGenerateRes; import com.alibaba.tesla.common.base.TeslaBaseResult; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -24,6 +27,7 @@ import org.springframework.web.bind.annotation.*; * * @author yaoxing.gyx@alibaba-inc.com */ +@Tag(name = "部署配置 API") @RequestMapping("/application-configurations") @RestController @Slf4j @@ -32,11 +36,7 @@ public class ApplicationConfigurationController extends AppManagerBaseController @Autowired private DeployConfigProvider deployConfigProvider; - /** - * @api {put} /application-configurations 更新全局部署信息 - * @apiName PutApplicationConfigurations - * @apiGroup Application Configuration API - */ + @Operation(summary = "更新全局部署信息") @PutMapping public TeslaBaseResult update( @RequestBody DeployConfigApplyTemplateReq request, @@ -54,11 +54,7 @@ public class ApplicationConfigurationController extends AppManagerBaseController return buildSucceedResult(deployConfigProvider.applyTemplate(request)); } - /** - * @api {get} /application-configurations 获取全局部署信息 - * @apiName GetApplicationConfigurations - * @apiGroup Application Configuration API - */ + @Operation(summary = "查询全局部署信息详情") @GetMapping public TeslaBaseResult get( @ModelAttribute DeployConfigGenerateReq request, @@ -81,13 +77,62 @@ public class ApplicationConfigurationController extends AppManagerBaseController .build()); } - /** - * @api {delete} /application-configurations 获取全局部署信息 - * @apiName GetApplicationConfigurations - * @apiGroup Application Configuration API - */ - @DeleteMapping - public TeslaBaseResult delete( + @Operation(summary = "更新指定类型的部署信息") + @PutMapping("types/{type}") + public TeslaBaseResult upsertByType( + @RequestBody DeployConfigUpsertReq request, + @PathVariable String type, + @RequestHeader(value = "X-Biz-App", required = false) String headerBizApp, + OAuth2Authentication auth) { + if (StringUtils.isEmpty(request.getApiVersion())) { + request.setApiVersion(DefaultConstant.API_VERSION_V1_ALPHA2); + } + if (StringUtils.isEmpty(request.getAppId())) { + request.setAppId(""); + } + DeployConfigTypeId typeIdObj = DeployConfigTypeId.valueOf(request.getTypeId()); + if (!typeIdObj.getType().equals(type)) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "mismatched type " + type); + } + BizAppContainer container = BizAppContainer.valueOf(headerBizApp); + request.setIsolateNamespaceId(container.getNamespaceId()); + request.setIsolateStageId(container.getStageId()); + DeployConfigDTO result = deployConfigProvider.upsert(request); + return buildSucceedResult(result); + } + + @Operation(summary = "查询指定类型的部署信息列表") + @GetMapping("types/{type}") + public TeslaBaseResult listByType( + @ModelAttribute DeployConfigListReq request, + @PathVariable String type, + @RequestHeader(value = "X-Biz-App", required = false) String headerBizApp, + OAuth2Authentication auth) { + if (StringUtils.isEmpty(request.getApiVersion())) { + request.setApiVersion(DefaultConstant.API_VERSION_V1_ALPHA2); + } + if (StringUtils.isEmpty(request.getAppId())) { + request.setAppId(""); + } + String typeId = request.getTypeId(); + if (StringUtils.isEmpty(typeId)) { + typeId = request.getTypeIdPrefix(); + } + DeployConfigTypeId typeIdObj = DeployConfigTypeId.valueOf(typeId); + if (!typeIdObj.getType().equals(type)) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "mismatched type " + type); + } + BizAppContainer container = BizAppContainer.valueOf(headerBizApp); + request.setIsolateNamespaceId(container.getNamespaceId()); + request.setIsolateStageId(container.getStageId()); + Pagination result = deployConfigProvider.list(request); + return buildSucceedResult(result); + } + + @Operation(summary = "删除指定类型的部署信息") + @DeleteMapping("types/{type}") + public TeslaBaseResult deleteByType( + @PathVariable String type, @ModelAttribute DeployConfigDeleteReq request, @RequestHeader(value = "X-Biz-App", required = false) String headerBizApp, OAuth2Authentication auth) { @@ -97,6 +142,10 @@ public class ApplicationConfigurationController extends AppManagerBaseController if (StringUtils.isEmpty(request.getAppId())) { request.setAppId(""); } + DeployConfigTypeId typeIdObj = DeployConfigTypeId.valueOf(request.getTypeId()); + if (!typeIdObj.getType().equals(type)) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "mismatched type " + type); + } BizAppContainer container = BizAppContainer.valueOf(headerBizApp); String namespaceId = container.getNamespaceId(); String stageId = container.getStageId(); @@ -105,4 +154,23 @@ public class ApplicationConfigurationController extends AppManagerBaseController deployConfigProvider.delete(request); return buildSucceedResult(DefaultConstant.EMPTY_OBJ); } + + @Operation(summary = "查询多种类型的部署信息列表") + @GetMapping("types") + public TeslaBaseResult listByType( + @ModelAttribute DeployConfigListReq request, + @RequestHeader(value = "X-Biz-App", required = false) String headerBizApp, + OAuth2Authentication auth) { + if (StringUtils.isEmpty(request.getApiVersion())) { + request.setApiVersion(DefaultConstant.API_VERSION_V1_ALPHA2); + } + if (StringUtils.isEmpty(request.getAppId())) { + request.setAppId(""); + } + BizAppContainer container = BizAppContainer.valueOf(headerBizApp); + request.setIsolateNamespaceId(container.getNamespaceId()); + request.setIsolateStageId(container.getStageId()); + Pagination result = deployConfigProvider.list(request); + return buildSucceedResult(result); + } } diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/ClusterController.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/ClusterController.java index a25659c2..c1c0f30d 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/ClusterController.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/ClusterController.java @@ -7,6 +7,7 @@ import com.alibaba.tesla.appmanager.domain.req.cluster.ClusterCreateReq; import com.alibaba.tesla.appmanager.domain.req.cluster.ClusterQueryReq; import com.alibaba.tesla.appmanager.domain.req.cluster.ClusterUpdateReq; import com.alibaba.tesla.common.base.TeslaBaseResult; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.oauth2.provider.OAuth2Authentication; @@ -23,6 +24,7 @@ import javax.validation.constraints.NotEmpty; * @author yaoxing.gyx@alibaba-inc.com */ @Slf4j +@Tag(name = "集群 API") @RequestMapping("/clusters") @RestController public class ClusterController extends AppManagerBaseController { diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/DeploymentController.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/DeploymentController.java index 698c5ea9..e10ec491 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/DeploymentController.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/DeploymentController.java @@ -10,8 +10,10 @@ import com.alibaba.tesla.appmanager.domain.dto.DeployComponentAttrDTO; import com.alibaba.tesla.appmanager.domain.req.deploy.*; import com.alibaba.tesla.appmanager.domain.res.deploy.DeployAppPackageLaunchRes; import com.alibaba.tesla.common.base.TeslaBaseResult; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang.exception.ExceptionUtils; +import org.apache.commons.lang3.exception.ExceptionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.web.bind.annotation.*; @@ -25,6 +27,7 @@ import java.util.HashMap; * @author yaoxing.gyx@alibaba-inc.com */ @Slf4j +@Tag(name = "部署单 API") @RequestMapping("/deployments") @RestController public class DeploymentController extends AppManagerBaseController { @@ -32,7 +35,7 @@ public class DeploymentController extends AppManagerBaseController { @Autowired private DeployAppProvider deployAppProvider; - // 发起部署 + @Operation(summary = "发起部署") @PostMapping(value = "/launch") @ResponseBody public TeslaBaseResult launch( @@ -49,7 +52,7 @@ public class DeploymentController extends AppManagerBaseController { } } - // 发起部署 + @Operation(summary = "发起快速部署") @PostMapping(value = "/fast-launch") @ResponseBody public TeslaBaseResult fastLaunch(@RequestBody FastDeployAppLaunchReq request, OAuth2Authentication auth) { @@ -63,7 +66,7 @@ public class DeploymentController extends AppManagerBaseController { } } - // 根据过滤条件查询部署单详情 + @Operation(summary = "查询部署单列表") @GetMapping @ResponseBody public TeslaBaseResult list( @@ -73,7 +76,7 @@ public class DeploymentController extends AppManagerBaseController { return buildSucceedResult(response); } - // 重新部署当前部署单 + @Operation(summary = "重新发起指定部署单") @PostMapping("{deployAppId}/replay") @ResponseBody public TeslaBaseResult replay( @@ -92,7 +95,7 @@ public class DeploymentController extends AppManagerBaseController { } } - // 查询指定部署单详情 + @Operation(summary = "查询部署单详情") @GetMapping("{deployAppId}") @ResponseBody public TeslaBaseResult get( @@ -109,7 +112,7 @@ public class DeploymentController extends AppManagerBaseController { return buildSucceedResult(response); } - // 查询指定部署单详情 + @Operation(summary = "查询部署单属性") @GetMapping("{deployAppId}/attributes") @ResponseBody public TeslaBaseResult getAttributes( @@ -122,7 +125,7 @@ public class DeploymentController extends AppManagerBaseController { return buildSucceedResult(response); } - // 查询指定部署单的指定步骤详情 + @Operation(summary = "查询部署单下指定组件属性") @GetMapping("{deployAppId}/components/{deployComponentId}/attributes") @ResponseBody public TeslaBaseResult getComponentAttributes( @@ -137,7 +140,7 @@ public class DeploymentController extends AppManagerBaseController { return buildSucceedResult(response); } - // 重试指定部署单 + @Operation(summary = "重试部署单") @PostMapping("{deployAppId}/retry") @ResponseBody public TeslaBaseResult retry( @@ -149,7 +152,7 @@ public class DeploymentController extends AppManagerBaseController { return buildSucceedResult(new HashMap()); } - // 终止指定部署单 + @Operation(summary = "终止部署单") @PostMapping("{deployAppId}/terminate") @ResponseBody public TeslaBaseResult terminate( diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/FlowManagerController.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/FlowManagerController.java index 4ce07539..f9919dcb 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/FlowManagerController.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/FlowManagerController.java @@ -3,6 +3,7 @@ package com.alibaba.tesla.appmanager.server.controller; import com.alibaba.tesla.appmanager.api.provider.FlowManagerProvider; import com.alibaba.tesla.appmanager.auth.controller.AppManagerBaseController; import com.alibaba.tesla.common.base.TeslaBaseResult; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.oauth2.provider.OAuth2Authentication; @@ -17,6 +18,7 @@ import java.util.HashMap; * @author yaoxing.gyx@alibaba-inc.com */ @Slf4j +@Tag(name = "FlowManager API (Deprecated)") @RequestMapping("/flow-manager") @RestController public class FlowManagerController extends AppManagerBaseController { diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/GlobalAppPackageController.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/GlobalAppPackageController.java index 613c2352..3cde75db 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/GlobalAppPackageController.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/GlobalAppPackageController.java @@ -11,6 +11,7 @@ import com.alibaba.tesla.appmanager.domain.schema.AppPackageSchema; import com.alibaba.tesla.appmanager.server.repository.domain.AppPackageTagDO; import com.alibaba.tesla.appmanager.server.service.apppackage.AppPackageTagService; import com.alibaba.tesla.common.base.TeslaBaseResult; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FileUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -28,6 +29,7 @@ import java.nio.file.Path; import java.nio.file.Paths; @Slf4j +@Tag(name = "全局应用包 API") @RequestMapping("/app-packages") @RestController public class GlobalAppPackageController extends AppManagerBaseController { diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/KubectlController.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/KubectlController.java new file mode 100644 index 00000000..87aafd41 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/KubectlController.java @@ -0,0 +1,90 @@ +package com.alibaba.tesla.appmanager.server.controller; + +import com.alibaba.tesla.appmanager.auth.controller.AppManagerBaseController; +import com.alibaba.tesla.appmanager.domain.req.kubectl.*; +import com.alibaba.tesla.appmanager.kubernetes.sevice.kubectl.KubectlService; +import com.alibaba.tesla.common.base.TeslaBaseResult; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.annotation.*; + +/** + * 原生接口 Controller + * + * @author yaoxing.gyx@alibaba-inc.com + */ +@Slf4j +@Tag(name = "Kube API") +@RequestMapping("/kubectl") +@RestController +public class KubectlController extends AppManagerBaseController { + + @Autowired + private KubectlService kubectlService; + + @GetMapping("namespaces") + public TeslaBaseResult namespaces(@ModelAttribute KubectlListNamespaceReq req, OAuth2Authentication auth) { + return buildSucceedResult(kubectlService.listNamespace(req, getOperator(auth))); + } + + @PostMapping("apply") + public TeslaBaseResult apply( + @RequestBody KubectlApplyReq request, + BindingResult validator, OAuth2Authentication auth) { + if (validator.hasErrors()) { + return buildValidationResult(validator); + } + kubectlService.apply(request, getOperator(auth)); + return buildSucceedResult(null); + } + + @DeleteMapping("clusters/{cluster}/namespaces/{namespace}/deployments/{deploymentName}") + public TeslaBaseResult deleteDeployment( + @PathVariable(value = "cluster") String cluster, + @PathVariable(value = "namespace") String namespace, + @PathVariable(value = "deploymentName") String deploymentName, + OAuth2Authentication auth) { + KubectlDeleteDeploymentReq request = KubectlDeleteDeploymentReq.builder() + .clusterId(cluster) + .namespaceId(namespace) + .deploymentName(deploymentName) + .build(); + kubectlService.deleteDeployment(request, getOperator(auth)); + return buildSucceedResult(null); + } + + @DeleteMapping("clusters/{cluster}/namespaces/{namespace}/statefulsets/{statefulSetName}") + public TeslaBaseResult deleteStatefulSet( + @PathVariable(value = "cluster") String cluster, + @PathVariable(value = "namespace") String namespace, + @PathVariable(value = "statefulSetName") String statefulSetName, + OAuth2Authentication auth) { + KubectlDeleteStatefulSetReq request = KubectlDeleteStatefulSetReq.builder() + .clusterId(cluster) + .namespaceId(namespace) + .statefulSetName(statefulSetName) + .build(); + kubectlService.deleteStatefulSet(request, getOperator(auth)); + return buildSucceedResult(null); + } + + @DeleteMapping("clusters/{cluster}/namespaces/{namespace}/jobs/{jobName}") + public TeslaBaseResult deleteJob( + @PathVariable(value = "cluster") String cluster, + @PathVariable(value = "namespace") String namespace, + @PathVariable(value = "jobName") String jobName, + @ModelAttribute KubectlDeleteJobReq params, + OAuth2Authentication auth) { + KubectlDeleteJobReq request = KubectlDeleteJobReq.builder() + .clusterId(cluster) + .namespaceId(namespace) + .jobName(jobName) + .asPrefix(params.isAsPrefix()) + .build(); + kubectlService.deleteJob(request, getOperator(auth)); + return buildSucceedResult(null); + } +} diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/MaintainerController.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/MaintainerController.java index 172070e9..87fe8d92 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/MaintainerController.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/MaintainerController.java @@ -5,6 +5,7 @@ import com.alibaba.tesla.appmanager.auth.controller.AppManagerBaseController; import com.alibaba.tesla.appmanager.common.constants.DefaultConstant; import com.alibaba.tesla.appmanager.common.util.EnvUtil; import com.alibaba.tesla.common.base.TeslaBaseResult; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; @@ -17,6 +18,7 @@ import org.springframework.web.bind.annotation.RestController; * * @author qiuqiang.qq@alibaba-inc.com */ +@Tag(name = "系统维护 API") @RequestMapping("/maintainer") @RestController @Slf4j diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/MarketController.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/MarketController.java index 7a4b1458..b7d42804 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/MarketController.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/MarketController.java @@ -18,6 +18,7 @@ import com.alibaba.tesla.appmanager.domain.req.market.*; import com.alibaba.tesla.appmanager.domain.schema.AppPackageSchema; import com.alibaba.tesla.appmanager.server.storage.impl.OssStorage; import com.alibaba.tesla.common.base.TeslaBaseResult; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; @@ -45,6 +46,7 @@ import java.util.stream.Collectors; * @author yaoxing.gyx@alibaba-inc.com */ @Slf4j +@Tag(name = "应用市场 API") @RequestMapping("/market") @RestController public class MarketController extends AppManagerBaseController { @@ -260,24 +262,19 @@ public class MarketController extends AppManagerBaseController { File localPackageFile = Files.createTempFile("market", ".zip").toFile(); NetworkUtil.download(downloadUrl, localPackageFile.getAbsolutePath()); - MarketPackageDTO marketPackage = marketProvider.rebuildAppPackage( - localPackageFile, getOperator(auth), request.getAppId(), request.getLocalAppId(), null); - - File marketPackageFile = new File(marketPackage.getPackageLocalPath()); - InputStream marketPackageStream = new FileInputStream(marketPackageFile); + InputStream marketPackageStream = new FileInputStream(localPackageFile); AppPackageImportReq appPackageImportReq = AppPackageImportReq.builder() - .appId(marketPackage.getAppId()) + .appId(request.getAppId()) .packageCreator(getOperator(auth)) - .packageVersion(marketPackage.getPackageVersion()) - .force(true) - .resetVersion(false) + .force(false) + .resetVersion(true) .build(); AppPackageDTO appPackageInfo = appPackageProvider .importPackage(appPackageImportReq, marketPackageStream, getOperator(auth)); AppMetaUpdateReq appMetaUpdateReq = new AppMetaUpdateReq(); - appMetaUpdateReq.setAppId(marketPackage.getAppId()); + appMetaUpdateReq.setAppId(request.getAppId()); if (request.getAppOptions() != null) { appMetaUpdateReq.setOptions(request.getAppOptions()); } diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/NamespaceController.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/NamespaceController.java index e6bf3481..6c43e341 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/NamespaceController.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/NamespaceController.java @@ -7,6 +7,7 @@ import com.alibaba.tesla.appmanager.domain.req.namespace.NamespaceCreateReq; import com.alibaba.tesla.appmanager.domain.req.namespace.NamespaceQueryReq; import com.alibaba.tesla.appmanager.domain.req.namespace.NamespaceUpdateReq; import com.alibaba.tesla.common.base.TeslaBaseResult; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.oauth2.provider.OAuth2Authentication; @@ -23,6 +24,7 @@ import javax.validation.constraints.NotEmpty; * @author yaoxing.gyx@alibaba-inc.com */ @Slf4j +@Tag(name = "Namespace API") @RequestMapping("/namespaces") @RestController public class NamespaceController extends AppManagerBaseController { diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/ProductReleaseController.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/ProductReleaseController.java index 7f7834da..9e363d77 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/ProductReleaseController.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/ProductReleaseController.java @@ -4,6 +4,7 @@ import com.alibaba.tesla.appmanager.auth.controller.AppManagerBaseController; import com.alibaba.tesla.appmanager.common.constants.DefaultConstant; import com.alibaba.tesla.appmanager.server.job.ProductReleaseSchedulerJob; import com.alibaba.tesla.common.base.TeslaBaseResult; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.oauth2.provider.OAuth2Authentication; @@ -16,11 +17,12 @@ import javax.servlet.http.HttpServletRequest; import javax.validation.constraints.NotEmpty; /** - * Namespace 管理 + * 产品发布版本管理 * * @author yaoxing.gyx@alibaba-inc.com */ @Slf4j +@Tag(name = "产品发布版本 API") @RequestMapping("/products/{productId:.+}/releases/{releaseId:.+}") @RestController public class ProductReleaseController extends AppManagerBaseController { diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/RtAppInstanceController.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/RtAppInstanceController.java index d0d1eedf..0a655d76 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/RtAppInstanceController.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/RtAppInstanceController.java @@ -11,6 +11,7 @@ import com.alibaba.tesla.appmanager.domain.req.rtappinstance.RtAppInstanceQueryR import com.alibaba.tesla.appmanager.domain.req.rtappinstance.RtComponentInstanceHistoryQueryReq; import com.alibaba.tesla.appmanager.server.job.OrphanComponentInstanceJob; import com.alibaba.tesla.common.base.TeslaBaseResult; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -25,6 +26,7 @@ import javax.servlet.http.HttpServletRequest; * @author yaoxing.gyx@alibaba-inc.com */ @Slf4j +@Tag(name = "应用实例 API") @RequestMapping("/realtime/app-instances") @RestController public class RtAppInstanceController extends AppManagerBaseController { diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/RtComponentInstanceController.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/RtComponentInstanceController.java index 566dbe71..d994c703 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/RtComponentInstanceController.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/RtComponentInstanceController.java @@ -7,6 +7,7 @@ import com.alibaba.tesla.appmanager.common.pagination.Pagination; import com.alibaba.tesla.appmanager.domain.dto.RtComponentInstanceDTO; import com.alibaba.tesla.appmanager.domain.req.rtcomponentinstance.RtComponentInstanceQueryReq; import com.alibaba.tesla.common.base.TeslaBaseResult; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.oauth2.provider.OAuth2Authentication; @@ -23,6 +24,7 @@ import javax.servlet.http.HttpServletRequest; * @author yaoxing.gyx@alibaba-inc.com */ @Slf4j +@Tag(name = "组件实例 API") @RequestMapping("/realtime/component-instances") @RestController public class RtComponentInstanceController extends AppManagerBaseController { diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/StageController.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/StageController.java index 6242279c..0728fcb8 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/StageController.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/StageController.java @@ -9,6 +9,7 @@ import com.alibaba.tesla.appmanager.domain.req.stage.StageCreateReq; import com.alibaba.tesla.appmanager.domain.req.stage.StageQueryReq; import com.alibaba.tesla.appmanager.domain.req.stage.StageUpdateReq; import com.alibaba.tesla.common.base.TeslaBaseResult; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.oauth2.provider.OAuth2Authentication; @@ -25,6 +26,7 @@ import javax.validation.constraints.NotEmpty; * @author yaoxing.gyx@alibaba-inc.com */ @Slf4j +@Tag(name = "Stage API") @RequestMapping @RestController public class StageController extends AppManagerBaseController { diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/UnitCategoryController.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/UnitCategoryController.java index 5a70666a..a0aae5c4 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/UnitCategoryController.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/UnitCategoryController.java @@ -8,6 +8,7 @@ import com.alibaba.tesla.appmanager.domain.dto.UnitCategoryDTO; import com.alibaba.tesla.appmanager.domain.dto.UnitDTO; import com.alibaba.tesla.appmanager.domain.req.unit.UnitQueryReq; import com.alibaba.tesla.common.base.TeslaBaseResult; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -28,6 +29,7 @@ import java.util.function.Function; * @author yaoxing.gyx@alibaba-inc.com */ @Slf4j +@Tag(name = "单元分类 API") @RequestMapping("/unit-categories") @RestController public class UnitCategoryController extends AppManagerBaseController { diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/UnitController.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/UnitController.java index 30f7ad87..89a08b16 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/UnitController.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/UnitController.java @@ -14,6 +14,7 @@ import com.alibaba.tesla.appmanager.domain.req.unit.UnitQueryReq; import com.alibaba.tesla.appmanager.domain.req.unit.UnitUpdateReq; import com.alibaba.tesla.appmanager.server.service.unit.UnitService; import com.alibaba.tesla.common.base.TeslaBaseResult; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.oauth2.provider.OAuth2Authentication; @@ -30,6 +31,7 @@ import javax.validation.constraints.NotEmpty; * @author yaoxing.gyx@alibaba-inc.com */ @Slf4j +@Tag(name = "单元 API") @RequestMapping("/units") @RestController public class UnitController extends AppManagerBaseController { diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/UserProfileController.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/UserProfileController.java index e2b919e0..1e5873d8 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/UserProfileController.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/controller/UserProfileController.java @@ -5,8 +5,8 @@ import com.alibaba.tesla.appmanager.api.provider.UserProfileProvider; import com.alibaba.tesla.appmanager.auth.controller.AppManagerBaseController; import com.alibaba.tesla.appmanager.domain.dto.UserProfileDTO; import com.alibaba.tesla.common.base.TeslaBaseResult; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.web.bind.annotation.*; @@ -16,6 +16,7 @@ import org.springframework.web.bind.annotation.*; * * @author qianmo.zm@alibaba-inc.com */ +@Tag(name = "用户 API") @RequestMapping("/profile") @RestController @Slf4j diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dag/helper/DeployAppHelper.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dag/helper/DeployAppHelper.java index 29bb2122..ba5449d7 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dag/helper/DeployAppHelper.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dag/helper/DeployAppHelper.java @@ -383,7 +383,11 @@ public class DeployAppHelper { WorkloadResource workload, DeployAppSchema.SpecComponent component, String appId, String componentName) { // namespace String namespaceId = component.getNamespaceId(); - assert !StringUtils.isEmpty(namespaceId); + if (StringUtils.isEmpty(namespaceId)) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("empty namespaceId in scopes, please check your application configuration|" + + "appId=%s|componentName=%s", appId, componentName)); + } workload.getMetadata().setNamespace(namespaceId); // stageId && name diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dag/nodes/DeployAppCreateComponentNode.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dag/nodes/DeployAppCreateComponentNode.java index 42599979..35e71e2a 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dag/nodes/DeployAppCreateComponentNode.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dag/nodes/DeployAppCreateComponentNode.java @@ -104,26 +104,6 @@ public class DeployAppCreateComponentNode extends AbstractLocalNodeBase { WorkloadResource workload = componentSchema.getSpec().getWorkload(); DeployAppHelper.setWorkloadMetaData(workload, componentOptions, appId, revisionName.getComponentName()); DocumentContext workloadContext = JsonPath.parse(JSONObject.toJSONString(workload)); - for (DeployAppSchema.DataInput dataInput : componentOptions.getDataInputs()) { - String key = dataInput.getValueFrom().getDataOutputName(); - Object value = DeployAppHelper.recursiveGetParameter(parameters, Arrays.asList(key.split("\\."))); - for (String toFieldPath : dataInput.getToFieldPaths()) { - try { - workloadContext.set(DefaultConstant.JSONPATH_PREFIX + toFieldPath, value); - log.info("set dataInput value success|key={}|value={}|toFieldPath={}|nodeId={}|" + - "deployAppId={}", key, value, toFieldPath, nodeId, deployAppId); - } catch (PathNotFoundException e) { - log.warn("set dataInput value failed because of path not found|key={}|value={}|toFieldPath={}|" + - "nodeId={}|deployAppId={}|parameters={}", key, value, toFieldPath, - nodeId, deployAppId, parameters.toJSONString()); - } catch (Exception e) { - log.warn("set dataInput value failed|key={}|value={}|toFieldPath={}|nodeId={}|" + - "deployAppId={}|parameters={}|exception={}", key, value, toFieldPath, - nodeId, deployAppId, parameters.toJSONString(), ExceptionUtils.getStackTrace(e)); - throw new AppException(AppErrorCode.INVALID_USER_ARGS, "set dataInput value failed", e); - } - } - } // 将 parameterValues 中声明的变量获取过来,并赋值到 component schema 中对应的字段 for (DeployAppSchema.ParameterValue parameterValue : componentOptions.getParameterValues()) { @@ -150,6 +130,28 @@ public class DeployAppCreateComponentNode extends AbstractLocalNodeBase { } } + // 进行 dataInputs 的变量渲染 + for (DeployAppSchema.DataInput dataInput : componentOptions.getDataInputs()) { + String key = dataInput.getValueFrom().getDataOutputName(); + Object value = DeployAppHelper.recursiveGetParameter(parameters, Arrays.asList(key.split("\\."))); + for (String toFieldPath : dataInput.getToFieldPaths()) { + try { + workloadContext.set(DefaultConstant.JSONPATH_PREFIX + toFieldPath, value); + log.info("set dataInput value success|key={}|value={}|toFieldPath={}|nodeId={}|" + + "deployAppId={}", key, value, toFieldPath, nodeId, deployAppId); + } catch (PathNotFoundException e) { + log.warn("set dataInput value failed because of path not found|key={}|value={}|toFieldPath={}|" + + "nodeId={}|deployAppId={}|parameters={}", key, value, toFieldPath, + nodeId, deployAppId, parameters.toJSONString()); + } catch (Exception e) { + log.warn("set dataInput value failed|key={}|value={}|toFieldPath={}|nodeId={}|" + + "deployAppId={}|parameters={}|exception={}", key, value, toFieldPath, + nodeId, deployAppId, parameters.toJSONString(), ExceptionUtils.getStackTrace(e)); + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "set dataInput value failed", e); + } + } + } + // 获取基本部署目标定位信息 String namespaceId = componentOptions.getNamespaceId(); if (StringUtils.isEmpty(namespaceId)) { @@ -162,7 +164,7 @@ public class DeployAppCreateComponentNode extends AbstractLocalNodeBase { // 检测当前是否已经存在组件实例,存在则获取 componentInstanceId;否则创建对应的组件实例并获取 componentInstanceId RtComponentInstanceQueryCondition componentInstanceCondition = RtComponentInstanceQueryCondition.builder() .appId(globalVariable.getString(AppFlowVariableKey.APP_ID)) - .componentType(revisionName.getComponentType().toString()) + .componentType(revisionName.getComponentType()) .componentName(revisionName.getComponentName()) .clusterId(clusterId) .namespaceId(namespaceId) diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dag/nodes/DeployAppCreateCustomAddonNode.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dag/nodes/DeployAppCreateCustomAddonNode.java index 5d99d943..30c7362c 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dag/nodes/DeployAppCreateCustomAddonNode.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dag/nodes/DeployAppCreateCustomAddonNode.java @@ -80,11 +80,11 @@ public class DeployAppCreateCustomAddonNode extends AbstractLocalNodeBase { } DeployAppRevisionName revisionName = DeployAppRevisionName.valueOf(nodeId); - ComponentTypeEnum componentType = revisionName.getComponentType(); - if (!componentType.equals(ComponentTypeEnum.CUSTOM_ADDON)) { + String componentType = revisionName.getComponentType(); + if (!ComponentTypeEnum.CUSTOM_ADDON.toString().equals(componentType)) { throw new AppException(AppErrorCode.USER_CONFIG_ERROR, String.format("actionName=%s|componentType=%s| componentType is not equals CUSTOM_ADDON!", - "DeployAppCreateCustomAddonNode", componentType.name())); + "DeployAppCreateCustomAddonNode", componentType)); } // 获取当前的 component 及 addonSchema,准备填充参数数据 diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dag/nodes/DeployAppCreateResourceAddonNode.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dag/nodes/DeployAppCreateResourceAddonNode.java index 24e1d84d..3a4a25d1 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dag/nodes/DeployAppCreateResourceAddonNode.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dag/nodes/DeployAppCreateResourceAddonNode.java @@ -71,8 +71,10 @@ public class DeployAppCreateResourceAddonNode extends AbstractLocalNodeBase { String appId = globalVariable.getString(AppFlowVariableKey.APP_ID); assert !StringUtils.isEmpty(nodeId) && !StringUtils.isEmpty(appId); DeployAppRevisionName revisionName = DeployAppRevisionName.valueOf(nodeId); - ComponentTypeEnum componentType = revisionName.getComponentType(); - assert componentType == ComponentTypeEnum.RESOURCE_ADDON; + String componentType = revisionName.getComponentType(); + if (!ComponentTypeEnum.RESOURCE_ADDON.toString().equals(componentType)) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "only resource addon is allowed"); + } // 获取当前的 component 及 addonSchema,准备填充参数数据 DeployAppSchema configuration = SchemaUtil.toSchema(DeployAppSchema.class, @@ -97,7 +99,7 @@ public class DeployAppCreateResourceAddonNode extends AbstractLocalNodeBase { // 获取 addon schema String addonId = revisionName.addonId(); String addonName = revisionName.addonName(); - Addon addon = addonManager.getAddon(ComponentTypeEnum.RESOURCE_ADDON, addonId); + Addon addon = addonManager.getAddon(ComponentTypeEnum.RESOURCE_ADDON.toString(), addonId); if (addon == null) { throw new AppException(AppErrorCode.DEPLOY_ERROR, String.format("cannot find resource addon by addonId %s", addonId)); diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dag/nodes/DeployAppDeciderNode.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dag/nodes/DeployAppDeciderNode.java index bb5cb210..e2ee7cc5 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dag/nodes/DeployAppDeciderNode.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dag/nodes/DeployAppDeciderNode.java @@ -51,7 +51,7 @@ public class DeployAppDeciderNode extends AbstractLocalNodeBase { .output(ImmutableMap.of(AppFlowParamKey.COMPONENT_TYPE, "")) .build(); } - ComponentTypeEnum componentType = revisionContainer.getComponentType(); + String componentType = revisionContainer.getComponentType(); // 获取全局变量,并将其置入到 OVERWRITE_PARAMETER_VALUES (每个 component/addon 节点运行的时候都会还原这份变量数据) JSONObject parameters = globalParams.getJSONObject(AppFlowParamKey.OVERWRITE_PARAMETER_VALUES); @@ -63,10 +63,17 @@ public class DeployAppDeciderNode extends AbstractLocalNodeBase { DeployAppHelper.recursiveSetParameters(parameters, null, Arrays.asList(name.split("\\.")), value, ParameterValueSetPolicy.OVERWRITE_ON_CONFILICT); } + String overwriteParams = globalVariable.getString(AppFlowVariableKey.OVERWRITE_PARAMS); + if (StringUtils.isNotEmpty(overwriteParams)) { + parameters.putAll(JSONObject.parseObject(overwriteParams)); + log.info("overwrite global params in dag|deployAppId={}|componentType={}|nodeId={}|dagInstId={}|" + + "overwriteParams={}|parameters={}", deployAppId, componentType, nodeId, dagInstId, + overwriteParams, parameters.toJSONString()); + } log.info("decider node has finished running|deployAppId={}|componentType={}|nodeId={}|dagInstId={}", - deployAppId, componentType.toString(), nodeId, dagInstId); + deployAppId, componentType, nodeId, dagInstId); return DagInstNodeRunRet.builder() - .output(ImmutableMap.of(AppFlowParamKey.COMPONENT_TYPE, componentType.toString())) + .output(ImmutableMap.of(AppFlowParamKey.COMPONENT_TYPE, componentType)) .build(); } } diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dag/nodes/DeployAppPreNode.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dag/nodes/DeployAppPreNode.java index b6e16c39..3f77bf07 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dag/nodes/DeployAppPreNode.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dag/nodes/DeployAppPreNode.java @@ -47,7 +47,7 @@ public class DeployAppPreNode extends AbstractLocalNodeBase { List componentRevisionList = new ArrayList<>(); for (ComponentPackageDO item : componentPackages) { DeployAppRevisionName revisionName = DeployAppRevisionName.builder() - .componentType(Enums.getIfPresent(ComponentTypeEnum.class, item.getComponentType()).orNull()) + .componentType(item.getComponentType()) .componentName(item.getComponentName()) .version(item.getPackageVersion()) .mirrorFlag(false) diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dag/nodes/DeployAppWaitAddonNode.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dag/nodes/DeployAppWaitAddonNode.java index 72b3e95f..b2bdc944 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dag/nodes/DeployAppWaitAddonNode.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dag/nodes/DeployAppWaitAddonNode.java @@ -69,7 +69,7 @@ public class DeployAppWaitAddonNode extends AbstractLocalNodeBase { // componentType 变量提取 DeployAppRevisionName revisionName = DeployAppRevisionName.valueOf(nodeId); - ComponentTypeEnum componentType = revisionName.getComponentType(); + String componentType = revisionName.getComponentType(); // 寻找 dataOutput 列表,并将对应的变量的值 set 到当前的部署单中 Jinjava jinjava = new Jinjava(); @@ -112,46 +112,42 @@ public class DeployAppWaitAddonNode extends AbstractLocalNodeBase { * @param componentType 组件类型 * @return DataOutput 列表 */ - private List getAddonDataOutputs(ComponentTypeEnum componentType) { + private List getAddonDataOutputs(String componentType) { DeployAppSchema configuration = SchemaUtil.toSchema(DeployAppSchema.class, globalVariable.get(AppFlowVariableKey.CONFIGURATION).toString()); String nodeId = fatherNodeId; assert !StringUtils.isEmpty(nodeId); // 根据 componentType 类型在部署单中寻找对应的 DataOutputs 配置 - switch (componentType) { - case INTERNAL_ADDON: - case RESOURCE_ADDON: - case CUSTOM_ADDON: - case K8S_MICROSERVICE: - case K8S_JOB: { - for (DeployAppSchema.SpecComponent component : configuration.getSpec().getComponents()) { - String componentId = component.getUniqueId(); - if (nodeId.equals(componentId)) { - return component.getDataOutputs(); + if (ComponentTypeEnum.INTERNAL_ADDON.toString().equals(componentType) + || ComponentTypeEnum.RESOURCE_ADDON.toString().equals(componentType) + || ComponentTypeEnum.CUSTOM_ADDON.toString().equals(componentType) + || ComponentTypeEnum.K8S_MICROSERVICE.toString().equals(componentType) + || ComponentTypeEnum.K8S_JOB.toString().equals(componentType)) { + for (DeployAppSchema.SpecComponent component : configuration.getSpec().getComponents()) { + String componentId = component.getUniqueId(); + if (nodeId.equals(componentId)) { + return component.getDataOutputs(); + } + } + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("cannot find specified nodeId %s in components/addons", nodeId)); + } else if (ComponentTypeEnum.TRAIT_ADDON.toString().equals(componentType)) { + for (DeployAppSchema.SpecComponent component : configuration.getSpec().getComponents()) { + String componentId = component.getUniqueId(); + DeployAppRevisionName componentRevision = DeployAppRevisionName.valueOf(componentId); + for (DeployAppSchema.SpecComponentTrait trait : component.getTraits()) { + String traitId = trait.getUniqueId(componentRevision); + if (traitId.equals(nodeId)) { + return trait.getDataOutputs(); } } - throw new AppException(AppErrorCode.INVALID_USER_ARGS, - String.format("cannot find specified nodeId %s in components/addons", nodeId)); } - case TRAIT_ADDON: { - for (DeployAppSchema.SpecComponent component : configuration.getSpec().getComponents()) { - String componentId = component.getUniqueId(); - DeployAppRevisionName componentRevision = DeployAppRevisionName.valueOf(componentId); - for (DeployAppSchema.SpecComponentTrait trait : component.getTraits()) { - String traitId = trait.getUniqueId(componentRevision); - if (traitId.equals(nodeId)) { - return trait.getDataOutputs(); - } - } - } - throw new AppException(AppErrorCode.INVALID_USER_ARGS, - String.format("cannot find specified nodeId %s in traits", nodeId)); - } - default: - throw new AppException(AppErrorCode.INVALID_USER_ARGS, - String.format("invalid componentType %s", componentType.toString())); + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("cannot find specified nodeId %s in traits", nodeId)); } + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("invalid componentType %s", componentType.toString())); } /** diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dag/nodes/DeployAppWaitCustomAddonNode.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dag/nodes/DeployAppWaitCustomAddonNode.java index 40f69a77..c2c3a43a 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dag/nodes/DeployAppWaitCustomAddonNode.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/dag/nodes/DeployAppWaitCustomAddonNode.java @@ -87,7 +87,7 @@ public class DeployAppWaitCustomAddonNode extends AbstractLocalNodeBase { // componentType 变量提取 DeployAppRevisionName revisionName = DeployAppRevisionName.valueOf(nodeId); - ComponentTypeEnum componentType = revisionName.getComponentType(); + String componentType = revisionName.getComponentType(); // 查找 dataOutput 列表,并将对应的变量的值 set 到当前部署单 Jinjava jinjava = new Jinjava(); diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/job/AppPackageFreshJob.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/job/AppPackageFreshJob.java index fa0e5579..6ecca1a6 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/job/AppPackageFreshJob.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/job/AppPackageFreshJob.java @@ -229,7 +229,7 @@ public class AppPackageFreshJob { private static boolean isSame(ComponentPackageTaskDO componentPackageTaskDO, ComponentBinder component) { return StringUtils.equals(componentPackageTaskDO.getComponentName(), component.getComponentName()) - && StringUtils.equals(componentPackageTaskDO.getComponentType(), component.getComponentType().toString()); + && StringUtils.equals(componentPackageTaskDO.getComponentType(), component.getComponentType()); } private static boolean isRunning(String taskStatus) { diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/job/DeploymentStatusSafetyJob.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/job/DeploymentStatusSafetyJob.java index 47733a8c..8306c746 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/job/DeploymentStatusSafetyJob.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/job/DeploymentStatusSafetyJob.java @@ -58,6 +58,7 @@ public class DeploymentStatusSafetyJob { @SchedulerLock(name = "deploymentStatusSafetyJob", lockAtLeastFor = "250s") public void execute() { long limit = systemProperties.getDeploymentMaxRunningSeconds() * 1000; + long waitingLimit = 240 * 1000; long currentTime = System.currentTimeMillis(); for (DeployAppStateEnum status : DEPLOY_APP_WAITING_STATUS_LIST) { DeployAppQueryCondition condition = DeployAppQueryCondition.builder().deployStatus(status).build(); @@ -89,6 +90,24 @@ public class DeploymentStatusSafetyJob { ExceptionUtils.getStackTrace(e)); } } + } else if (DeployAppStateEnum.WAITING.toString().equals(item.getOrder().getDeployStatus()) + && orderTime + waitingLimit < currentTime) { + try { + DeployAppEvent event = new DeployAppEvent(this, DeployAppEventEnum.TRIGGER_UPDATE, deployAppId); + eventPublisher.publishEvent(event); + log.info("action=deployAppStatusSafetyJob|found long waiting deployment order, trigger update|" + + "deployAppId={}|orderTime={}|currentTime={}|order={}", deployAppId, + orderTime, currentTime, JSONObject.toJSONString(item.getOrder())); + } catch (AppException e) { + if (e.getErrorCode().equals(AppErrorCode.LOCKER_VERSION_EXPIRED)) { + log.info("action=deployAppStatusSafetyJob|lock failed on deployment order, skip it|" + + "deployAppId={}", deployAppId); + } else { + log.error("action=deployAppStatusSafetyJob|cannot trigger update on " + + "deployment order, skip|deployAppId={}|exception={}", deployAppId, + ExceptionUtils.getStackTrace(e)); + } + } } } } diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/lib/validator/AppManagerValidateUtil.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/lib/validator/AppManagerValidateUtil.java index 93f3fca7..52d930a0 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/lib/validator/AppManagerValidateUtil.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/lib/validator/AppManagerValidateUtil.java @@ -2,6 +2,7 @@ package com.alibaba.tesla.appmanager.server.lib.validator; import com.alibaba.tesla.appmanager.common.util.ObjectConvertUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -27,4 +28,10 @@ public class AppManagerValidateUtil { throw constraintViolationException; } } + + public void notBlank(String name, String value) { + if (StringUtils.isBlank(value)) { + throw new IllegalArgumentException(String.format("%s should not be blank.", name)); + } + } } diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/listener/ApplicationContextLoadedEventListener.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/listener/ApplicationContextLoadedEventListener.java index 553f132d..4a1d4ee5 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/listener/ApplicationContextLoadedEventListener.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/listener/ApplicationContextLoadedEventListener.java @@ -2,15 +2,16 @@ package com.alibaba.tesla.appmanager.server.listener; import com.alibaba.tesla.appmanager.common.exception.AppErrorCode; import com.alibaba.tesla.appmanager.common.exception.AppException; +import com.alibaba.tesla.appmanager.domain.core.ScriptIdentifier; import com.alibaba.tesla.appmanager.dynamicscript.core.GroovyHandlerFactory; import com.alibaba.tesla.appmanager.dynamicscript.repository.condition.DynamicScriptQueryCondition; import com.alibaba.tesla.appmanager.dynamicscript.service.DynamicScriptService; +import com.alibaba.tesla.appmanager.dynamicscript.util.GroovyUtil; import com.alibaba.tesla.appmanager.server.service.informer.InformerManager; import com.alibaba.tesla.appmanager.spring.event.ApplicationContextLoadedEvent; import groovy.lang.GroovyClassLoader; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationListener; import org.springframework.core.io.ClassPathResource; @@ -19,7 +20,6 @@ import org.springframework.stereotype.Component; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; -import java.lang.reflect.Field; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.Arrays; @@ -39,12 +39,6 @@ public class ApplicationContextLoadedEventListener implements ApplicationListene * 默认加载的 Groovy 文件 */ private final List DEFAULT_GROOVY_SCRIPTS = Arrays.asList( - "/dynamicscripts/DefaultBuildMicroserviceHandler.groovy", - "/dynamicscripts/DefaultDeployMicroserviceHandler.groovy", - "/dynamicscripts/DefaultBuildJobHandler.groovy", - "/dynamicscripts/DefaultDeployJobHandler.groovy", - "/dynamicscripts/HelmBuildMicroserviceHandler.groovy", - "/dynamicscripts/HelmDeployMicroserviceHandler.groovy", "/dynamicscripts/DefaultBuildInternalAddonProductopsHandler.groovy", "/dynamicscripts/DefaultDeployInternalAddonProductopsHandler.groovy", "/dynamicscripts/DefaultBuildInternalAddonDevelopmentMetaHandler.groovy", @@ -61,25 +55,35 @@ public class ApplicationContextLoadedEventListener implements ApplicationListene "/dynamicscripts/TraitHostNetwork.groovy", "/dynamicscripts/TraitSystemEnv.groovy", "/dynamicscripts/TraitNodeSelector.groovy", - "/dynamicscripts/MicroserviceComponentWatchKubernetesInformerHandler.groovy", - "/dynamicscripts/JobComponentWatchKubernetesInformerHandler.groovy", + "/dynamicscripts/TraitSecret.groovy", + "/dynamicscripts/MicroserviceComponentBuildHandler.groovy", + "/dynamicscripts/MicroserviceComponentDeployHandler.groovy", "/dynamicscripts/MicroserviceComponentHandler.groovy", "/dynamicscripts/MicroserviceComponentDestroyHandler.groovy", + "/dynamicscripts/MicroserviceComponentWatchKubernetesInformerHandler.groovy", + "/dynamicscripts/JobComponentBuildHandler.groovy", + "/dynamicscripts/JobComponentDeployHandler.groovy", "/dynamicscripts/JobComponentHandler.groovy", "/dynamicscripts/JobComponentDestroyHandler.groovy", + "/dynamicscripts/JobComponentWatchKubernetesInformerHandler.groovy", "/dynamicscripts/HelmComponentHandler.groovy", + "/dynamicscripts/HelmComponentBuildHandler.groovy", + "/dynamicscripts/HelmComponentDeployHandler.groovy", "/dynamicscripts/HelmComponentDestroyHandler.groovy", + "/dynamicscripts/ScriptComponentHandler.groovy", "/dynamicscripts/ScriptComponentBuildHandler.groovy", "/dynamicscripts/ScriptComponentDeployHandler.groovy", - "/dynamicscripts/ScriptComponentHandler.groovy", "/dynamicscripts/ScriptComponentWatchCronHandler.groovy", "/dynamicscripts/InternalAddonV2ProductopsComponentHandler.groovy", "/dynamicscripts/InternalAddonV2ProductopsComponentDestroyHandler.groovy", "/dynamicscripts/WorkflowDeployHandler.groovy", "/dynamicscripts/WorkflowRemoteDeployHandler.groovy", "/dynamicscripts/WorkflowSuspendHandler.groovy", + "/dynamicscripts/WorkflowApplyComponentsHandler.groovy", + "/dynamicscripts/WorkflowRolloutPromotionHandler.groovy", "/dynamicscripts/PolicyTopologyHandler.groovy", - "/dynamicscripts/PolicyOverrideHandler.groovy" + "/dynamicscripts/PolicyOverrideHandler.groovy", + "/dynamicscripts/CustomStatusGenericResource.groovy" ); private final GroovyClassLoader groovyClassLoader = new GroovyClassLoader(); @@ -125,35 +129,12 @@ public class ApplicationContextLoadedEventListener implements ApplicationListene code = readFileContent(groovyPath); } Class clazz = groovyClassLoader.parseClass(code); - String kind = null, name = null; - Integer revision = null; - for (Field f : clazz.getFields()) { - if (f.getType().equals(String.class) || f.getType().equals(Integer.class)) { - String key = f.getName(); - Object value = f.get(null); - switch (key) { - case "KIND": - kind = (String) value; - break; - case "NAME": - name = (String) value; - break; - case "REVISION": - revision = (Integer) value; - break; - default: - break; - } - } - } - if (StringUtils.isEmpty(kind) || StringUtils.isEmpty(name) || revision == null) { - throw new RuntimeException(String.format("invalid groovy handler %s", groovyPath)); - } + ScriptIdentifier identifier = GroovyUtil.getScriptIdentifierFromClass(clazz); DynamicScriptQueryCondition condition = DynamicScriptQueryCondition.builder() - .kind(kind) - .name(name) + .kind(identifier.getKind()) + .name(identifier.getName()) .build(); - dynamicScriptService.initScript(condition, revision, code); + dynamicScriptService.initScript(condition, identifier.getRevision(), code); } catch (Exception e) { throw new AppException(AppErrorCode.UNKNOWN_ERROR, String.format("cannot initialize default scripts in resources directory: %s", groovyPath), e); diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/provider/impl/AppComponentProviderImpl.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/provider/impl/AppComponentProviderImpl.java index d883da0b..8f6fee02 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/provider/impl/AppComponentProviderImpl.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/provider/impl/AppComponentProviderImpl.java @@ -1,22 +1,48 @@ package com.alibaba.tesla.appmanager.server.provider.impl; +import com.alibaba.fastjson.JSONObject; import com.alibaba.tesla.appmanager.api.provider.AppAddonProvider; import com.alibaba.tesla.appmanager.api.provider.AppComponentProvider; import com.alibaba.tesla.appmanager.api.provider.HelmMetaProvider; import com.alibaba.tesla.appmanager.api.provider.K8sMicroServiceMetaProvider; +import com.alibaba.tesla.appmanager.common.constants.DefaultConstant; import com.alibaba.tesla.appmanager.common.enums.ComponentTypeEnum; +import com.alibaba.tesla.appmanager.common.enums.PluginKindEnum; +import com.alibaba.tesla.appmanager.common.exception.AppErrorCode; +import com.alibaba.tesla.appmanager.common.exception.AppException; +import com.alibaba.tesla.appmanager.common.util.ClassUtil; +import com.alibaba.tesla.appmanager.common.util.SchemaUtil; +import com.alibaba.tesla.appmanager.deployconfig.service.DeployConfigService; +import com.alibaba.tesla.appmanager.deployconfig.util.DeployConfigGenerator; +import com.alibaba.tesla.appmanager.domain.container.DeployConfigTypeId; import com.alibaba.tesla.appmanager.domain.dto.AppComponentDTO; import com.alibaba.tesla.appmanager.domain.req.AppAddonQueryReq; import com.alibaba.tesla.appmanager.domain.req.K8sMicroServiceMetaQueryReq; +import com.alibaba.tesla.appmanager.domain.req.appcomponent.AppComponentCreateReq; +import com.alibaba.tesla.appmanager.domain.req.appcomponent.AppComponentDeleteReq; import com.alibaba.tesla.appmanager.domain.req.appcomponent.AppComponentQueryReq; +import com.alibaba.tesla.appmanager.domain.req.appcomponent.AppComponentUpdateReq; +import com.alibaba.tesla.appmanager.domain.req.deployconfig.DeployConfigDeleteReq; +import com.alibaba.tesla.appmanager.domain.req.deployconfig.DeployConfigUpsertReq; import com.alibaba.tesla.appmanager.domain.req.helm.HelmMetaQueryReq; +import com.alibaba.tesla.appmanager.plugin.repository.condition.PluginDefinitionQueryCondition; +import com.alibaba.tesla.appmanager.plugin.repository.domain.PluginDefinitionDO; +import com.alibaba.tesla.appmanager.plugin.service.PluginService; +import com.alibaba.tesla.appmanager.server.assembly.AppComponentDtoConvert; +import com.alibaba.tesla.appmanager.server.repository.condition.AppComponentQueryCondition; +import com.alibaba.tesla.appmanager.server.repository.domain.AppComponentDO; +import com.alibaba.tesla.appmanager.server.service.appcomponent.AppComponentService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.yaml.snakeyaml.Yaml; -import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; /** * 应用关联组件 Provider @@ -27,6 +53,12 @@ import java.util.List; @Slf4j public class AppComponentProviderImpl implements AppComponentProvider { + @Autowired + private AppComponentService appComponentService; + + @Autowired + private AppComponentDtoConvert appComponentDtoConvert; + @Autowired private K8sMicroServiceMetaProvider k8SMicroServiceMetaProvider; @@ -36,6 +68,190 @@ public class AppComponentProviderImpl implements AppComponentProvider { @Autowired private HelmMetaProvider helmMetaProvider; + @Autowired + private PluginService pluginService; + + @Autowired + private DeployConfigService deployConfigService; + + /** + * 获取指定应用下的指定关联 Component 对象 + * + * @param request 应用组件绑定查询请求 + * @param operator 操作人 + * @return AppComponentDTO + */ + @Override + public AppComponentDTO get(AppComponentQueryReq request, String operator) { + AppComponentQueryCondition condition = new AppComponentQueryCondition(); + ClassUtil.copy(request, condition); + return appComponentDtoConvert.to(appComponentService.get(condition)); + } + + /** + * 创建应用下的关联 Component 绑定 + * + * @param request 创建请求 + * @param operator 操作人 + * @return 绑定后的结果 + */ + @Override + public AppComponentDTO create(AppComponentCreateReq request, String operator) { + String namespaceId = request.getNamespaceId(); + String stageId = request.getStageId(); + String appId = request.getAppId(); + String category = request.getCategory(); + String componentType = request.getComponentType(); + String componentName = request.getComponentName(); + String config = JSONObject.toJSONString(request.getConfig()); + + // 提前检查是否已经存在记录 + AppComponentDO origin = appComponentService.get(AppComponentQueryCondition.builder() + .namespaceId(namespaceId) + .stageId(stageId) + .appId(appId) + .category(category) + .componentType(componentType) + .componentName(componentName) + .build()); + if (origin != null) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "the app component binding record exists"); + } + + AppComponentDO record = AppComponentDO.builder() + .namespaceId(namespaceId) + .stageId(stageId) + .appId(appId) + .category(category) + .componentType(componentType) + .componentName(componentName) + .config(config) + .build(); + int count = appComponentService.create(record); + if (count != 1) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("invalid count when creating app component|count=%d|record=%s", + count, JSONObject.toJSONString(record))); + } + log.info("app component has created|operator={}|id={}|namespaceId={}|stageId={}|appId={}|category={}|" + + "componentType={}|componentName={}|config={}", record.getId(), operator, namespaceId, + stageId, appId, category, componentType, componentName, config); + + DeployConfigGenerator configObject = new DeployConfigGenerator(); + configObject.addRevisionName(componentType, componentName); + configObject.addScope("Namespace", namespaceId); + String typeId = new DeployConfigTypeId(componentType, componentName).toString(); + deployConfigService.update(DeployConfigUpsertReq.builder() + .apiVersion(DefaultConstant.API_VERSION_V1_ALPHA2) + .appId(appId) + .typeId(typeId) + .envId("") + .inherit(false) + .config(configObject.toString()) + .isolateNamespaceId(namespaceId) + .isolateStageId(stageId) + .build()); + + return appComponentDtoConvert.to(appComponentService.get(AppComponentQueryCondition.builder() + .id(record.getId()) + .build())); + } + + /** + * 更新应用下的关联 Component 绑定 + * + * @param request 更新请求 + * @param operator 操作人 + * @return 绑定后的结果 + */ + @Override + public AppComponentDTO update(AppComponentUpdateReq request, String operator) { + String namespaceId = request.getNamespaceId(); + String stageId = request.getStageId(); + String appId = request.getAppId(); + String category = request.getCategory(); + String componentType = request.getComponentType(); + String componentName = request.getComponentName(); + String config = JSONObject.toJSONString(request.getConfig()); + AppComponentQueryCondition condition = AppComponentQueryCondition.builder() + .id(request.getId()) + .build(); + AppComponentDO record = appComponentService.get(condition); + if (record == null) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "cannot find specified app component record"); + } + + record.setConfig(config); + int count = appComponentService.update(record, condition); + if (count != 1) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("invalid count when updating app component|count=%d|record=%s", + count, JSONObject.toJSONString(record))); + } + log.info("app component has updated|operator={}|namespaceId={}|stageId={}|appId={}|category={}|" + + "componentType={}|componentName={}|config={}", operator, namespaceId, stageId, appId, category, + componentType, componentName, config); + + DeployConfigGenerator configObject = new DeployConfigGenerator(); + configObject + .addRevisionName(componentType, componentName) + .addScope("Namespace", namespaceId) + .addDataInputs(request.getConfig().getJSONArray("dataInputs")) + .addDataOutputs(request.getConfig().getJSONArray("dataOutputs")); + String typeId = new DeployConfigTypeId(componentType, componentName).toString(); + deployConfigService.update(DeployConfigUpsertReq.builder() + .apiVersion(DefaultConstant.API_VERSION_V1_ALPHA2) + .appId(appId) + .typeId(typeId) + .envId("") + .inherit(false) + .config(configObject.toString()) + .isolateNamespaceId(namespaceId) + .isolateStageId(stageId) + .build()); + + return appComponentDtoConvert.to(appComponentService.get(condition)); + } + + /** + * 删除指定应用下的指定关联 Component 对象 + * + * @param request 应用组件绑定查询请求 + * @param operator 操作人 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void delete(AppComponentDeleteReq request, String operator) { + AppComponentQueryCondition condition = AppComponentQueryCondition.builder().id(request.getId()).build(); + if (condition.getId() == null || condition.getId() == 0) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "empty app component delete request"); + } + AppComponentDO appComponent = appComponentService.get(condition); + if (appComponent == null) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "the id provided is not exist"); + } + appComponentService.delete(condition); + + // 执行 Deploy Config 删除动作 + String appId = appComponent.getAppId(); + String componentType = appComponent.getComponentType(); + String componentName = appComponent.getComponentName(); + String namespaceId = appComponent.getNamespaceId(); + String stageId = appComponent.getStageId(); + String typeId = new DeployConfigTypeId(componentType, componentName).toString(); + deployConfigService.delete(DeployConfigDeleteReq.builder() + .apiVersion(DefaultConstant.API_VERSION_V1_ALPHA2) + .appId(appId) + .isolateNamespaceId(namespaceId) + .isolateStageId(stageId) + .envId("") + .typeId(typeId) + .build()); + log.info("app component record has deleted|id={}|appId={}|componentType={}|componentName={}|namespaceId={}|" + + "stageId={}|typeId={}", condition.getId(), appId, componentType, componentName, namespaceId, + stageId, typeId); + } + /** * 获取指定 appId 下的所有关联 Component 对象 * @@ -49,9 +265,31 @@ public class AppComponentProviderImpl implements AppComponentProvider { String namespaceId = request.getNamespaceId(); String stageId = request.getStageId(); String arch = request.getArch(); - List result = new ArrayList<>(); + boolean isWithBlobs = request.isWithBlobs(); - // 获取 K8S 微应用组件 + // 获取通用 Component + List appComponents = appComponentService.list(AppComponentQueryCondition.builder() + .appId(appId) + .namespaceId(namespaceId) + .stageId(stageId) + .withBlobs(isWithBlobs) + .build()); + Map pluginMap = pluginService + .list(PluginDefinitionQueryCondition.builder() + .pluginKind(PluginKindEnum.COMPONENT_DEFINITION.toString()) + .pluginRegistered(true) + .build()) + .getItems() + .stream() + .collect(Collectors.toMap(PluginDefinitionDO::getPluginName, Function.identity())); + List result = appComponents.stream() + .filter(item -> pluginMap.containsKey(item.getComponentType())) + .map(item -> appComponentDtoConvert.to(item, pluginMap.get(item.getComponentType()))) + .collect(Collectors.toList()); + log.info("fetch app component records|appId={}|namespaceId={}|stageId={}|size={}", + appId, namespaceId, stageId, result.size()); + + // 获取 K8S 微应用组件 TODO: 迁移到通用 Component K8sMicroServiceMetaQueryReq k8sMicroServiceMetaQueryReq = new K8sMicroServiceMetaQueryReq(); k8sMicroServiceMetaQueryReq.setAppId(appId); k8sMicroServiceMetaQueryReq.setNamespaceId(namespaceId); @@ -62,17 +300,19 @@ public class AppComponentProviderImpl implements AppComponentProvider { .forEach(k8sMicroServiceMetaDTO -> result.add(AppComponentDTO.builder() .id(k8sMicroServiceMetaDTO.getId()) + .compatible(true) .appId(appId) .namespaceId(namespaceId) .stageId(stageId) - .componentName(k8sMicroServiceMetaDTO.getMicroServiceId()) - .componentLabel(k8sMicroServiceMetaDTO.getName()) .componentType(k8sMicroServiceMetaDTO.getComponentType()) + .componentName(k8sMicroServiceMetaDTO.getMicroServiceId()) .build() ) ); + log.info("fetch k8s microservice records|appId={}|namespaceId={}|stageId={}|total={}", + appId, namespaceId, stageId, result.size()); - // 获取 HELM 组件 + // 获取 HELM 组件 TODO: 迁移到通用 Component HelmMetaQueryReq helmMetaQueryReq = new HelmMetaQueryReq(); helmMetaQueryReq.setAppId(appId); helmMetaQueryReq.setNamespaceId(namespaceId); @@ -82,60 +322,64 @@ public class AppComponentProviderImpl implements AppComponentProvider { .forEach(helmMetaDO -> result.add(AppComponentDTO.builder() .id(helmMetaDO.getId()) + .compatible(true) .appId(appId) .namespaceId(namespaceId) .stageId(stageId) .componentName(helmMetaDO.getHelmPackageId()) - .componentLabel(helmMetaDO.getName()) .componentType(helmMetaDO.getComponentType()) .build() ) ); + log.info("fetch helm microservice records|appId={}|namespaceId={}|stageId={}|total={}", + appId, namespaceId, stageId, result.size()); - // 获取 Internal Addon + // 获取 Internal Addon TODO: 迁移到通用 Component AppAddonQueryReq internalAddonQueryReq = new AppAddonQueryReq(); internalAddonQueryReq.setAppId(appId); internalAddonQueryReq.setNamespaceId(namespaceId); internalAddonQueryReq.setStageId(stageId); internalAddonQueryReq.setPagination(false); - internalAddonQueryReq.setAddonTypeList(Collections.singletonList(ComponentTypeEnum.INTERNAL_ADDON)); + internalAddonQueryReq.setAddonTypeList(Collections.singletonList(ComponentTypeEnum.INTERNAL_ADDON.toString())); appAddonProvider.list(internalAddonQueryReq).getItems() .forEach(item -> result.add(AppComponentDTO.builder() .id(item.getId()) + .compatible(true) .appId(appId) .namespaceId(namespaceId) .stageId(stageId) .componentType(item.getAddonType()) .componentName(item.getAddonId()) - .componentVersion(item.getAddonVersion()) - .componentLabel(String.format("%s@%s", item.getAddonId(), item.getName())) .build() ) ); + log.info("fetch internal addon records|appId={}|namespaceId={}|stageId={}|total={}", + appId, namespaceId, stageId, result.size()); - // 获取 Resource Addon + // 获取 Resource Addon TODO: 迁移到通用 Component AppAddonQueryReq resourceAddonQueryReq = new AppAddonQueryReq(); resourceAddonQueryReq.setAppId(appId); resourceAddonQueryReq.setNamespaceId(namespaceId); resourceAddonQueryReq.setStageId(stageId); resourceAddonQueryReq.setPagination(false); - resourceAddonQueryReq.setAddonTypeList(Collections.singletonList(ComponentTypeEnum.RESOURCE_ADDON)); + resourceAddonQueryReq.setAddonTypeList(Collections.singletonList(ComponentTypeEnum.RESOURCE_ADDON.toString())); appAddonProvider.list(resourceAddonQueryReq).getItems() .forEach(item -> result.add(AppComponentDTO.builder() .id(item.getId()) + .compatible(true) .appId(appId) .namespaceId(namespaceId) .stageId(stageId) .componentType(item.getAddonType()) .componentName(String.format("%s@%s", item.getAddonId(), item.getName())) - .componentVersion(item.getAddonVersion()) - .componentLabel(String.format("%s@%s", item.getAddonId(), item.getName())) .build() ) ); + log.info("fetch resource addon records|appId={}|namespaceId={}|stageId={}|total={}", + appId, namespaceId, stageId, result.size()); return result; } } diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/provider/impl/AppPackageProviderImpl.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/provider/impl/AppPackageProviderImpl.java index 0bd89fe8..afbf959c 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/provider/impl/AppPackageProviderImpl.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/provider/impl/AppPackageProviderImpl.java @@ -162,7 +162,7 @@ public class AppPackageProviderImpl implements AppPackageProvider { .pageSize(req.getPageSize()) .withBlobs(req.isWithBlobs()) .build(); - return Pagination.transform(appPackageService.list(condition), item -> appPackageDtoConvert.to(item)); + return Pagination.transform(appPackageService.list(condition), appPackageDtoConvert::to); } /** diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/provider/impl/AppPackageTaskProviderImpl.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/provider/impl/AppPackageTaskProviderImpl.java index dde4e1e2..df45a2b7 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/provider/impl/AppPackageTaskProviderImpl.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/provider/impl/AppPackageTaskProviderImpl.java @@ -89,7 +89,9 @@ public class AppPackageTaskProviderImpl implements AppPackageTaskProvider { packageVersion = checkAppPackageVersion(appId, packageVersion); if (CollectionUtils.isEmpty(request.getComponents())) { - throw new AppException(AppErrorCode.INVALID_USER_ARGS, "missing package component"); + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("missing package component|appId=%s|namespaceId=%s|stageId=%s|packageVersion=%s", + appId, namespaceId, stageId, packageVersion)); } // 获取当前应用的默认部署 YAML @@ -112,11 +114,13 @@ public class AppPackageTaskProviderImpl implements AppPackageTaskProvider { Long appPackageTaskId = appPackageTaskDO.getId(); for (ComponentBinder component : request.getComponents()) { - ComponentTypeEnum componentType = component.getComponentType(); + String componentType = component.getComponentType(); String componentName = component.getComponentName(); // 计算版本,没有提供 version 的情况下 or ADDON 组件类型则变为自动版本 - if (StringUtils.isEmpty(component.getVersion()) || componentType.isAddon()) { + if (StringUtils.isEmpty(component.getVersion()) + || ComponentTypeEnum.RESOURCE_ADDON.toString().equals(componentType) + || ComponentTypeEnum.INTERNAL_ADDON.toString().equals(componentType)) { component.setVersion(DefaultConstant.AUTO_VERSION); } String fullVersion = appPackageTaskService @@ -153,7 +157,7 @@ public class AppPackageTaskProviderImpl implements AppPackageTaskProvider { .appId(appId) .namespaceId(namespaceId) .stageId(stageId) - .componentType(componentType.toString()) + .componentType(componentType) .componentName(componentName) .packageVersion(component.getVersion()) .packageCreator(operator) diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/provider/impl/DeployAppProviderImpl.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/provider/impl/DeployAppProviderImpl.java index 6495b89e..fdb11f1f 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/provider/impl/DeployAppProviderImpl.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/provider/impl/DeployAppProviderImpl.java @@ -8,6 +8,7 @@ import com.alibaba.tesla.appmanager.common.enums.*; import com.alibaba.tesla.appmanager.common.exception.AppErrorCode; import com.alibaba.tesla.appmanager.common.exception.AppException; import com.alibaba.tesla.appmanager.common.pagination.Pagination; +import com.alibaba.tesla.appmanager.common.util.JsonUtil; import com.alibaba.tesla.appmanager.common.util.SchemaUtil; import com.alibaba.tesla.appmanager.domain.dto.*; import com.alibaba.tesla.appmanager.domain.req.apppackage.ApplicationConfigurationGenerateReq; @@ -240,6 +241,10 @@ public class DeployAppProviderImpl implements DeployAppProvider { Map attrMap = new HashMap<>(); String appConfiguration = SchemaUtil.toYamlMapStr(schema); attrMap.put(DeployAppAttrTypeEnum.APP_CONFIGURATION.toString(), appConfiguration); + if (request.getOverwriteParameters() != null) { + attrMap.put(DeployAppAttrTypeEnum.OVERWRITE_PARAMS.toString(), + request.getOverwriteParameters().toJSONString()); + } DeployAppDO record = DeployAppDO.builder() .appPackageId(appPackageId) .packageVersion(packageVersion) @@ -256,6 +261,10 @@ public class DeployAppProviderImpl implements DeployAppProvider { log.info("action=deployAppPackage.launch|deployAppId={}|appPackageId={}|creator={}|" + "appId={}|clusterId={}|namespaceId={}|stageId={}|request={}", deployAppId, appPackageId, creator, appId, clusterId, namespaceId, stageId, JSONObject.toJSONString(schema)); + if (request.getOverwriteParameters() != null) { + log.info("action=deployAppPackage.launchOverwriteParams|deployAppId={}|overwriteParams={}", + deployAppId, request.getOverwriteParameters().toJSONString()); + } // 事件发送 DeployAppEvent event = new DeployAppEvent(this, DeployAppEventEnum.START, deployAppId); @@ -449,7 +458,7 @@ public class DeployAppProviderImpl implements DeployAppProvider { private Schema getSchema(String appId, ComponentBinder componentBinder) { Yaml yaml = SchemaUtil.createYaml(ComponentSchema.class); - if (componentBinder.getComponentType() == ComponentTypeEnum.RESOURCE_ADDON) { + if (Objects.equals(componentBinder.getComponentType(), ComponentTypeEnum.RESOURCE_ADDON.toString())) { AppAddonQueryCondition condition = AppAddonQueryCondition.builder().appId(appId).addonName( componentBinder.getComponentName()).build(); Pagination appAddonDOPage = appAddonService.list(condition); @@ -473,7 +482,7 @@ public class DeployAppProviderImpl implements DeployAppProvider { ComponentPackageQueryCondition condition = ComponentPackageQueryCondition.builder() .appId(appId) .componentName(componentBinder.getComponentName()) - .componentType(componentBinder.getComponentType().toString()) + .componentType(componentBinder.getComponentType()) .withBlobs(true) .packageVersion(componentBinder.getVersion()).build(); @@ -512,7 +521,7 @@ public class DeployAppProviderImpl implements DeployAppProvider { ParameterValue parameterValue = new ParameterValue(); parameterValue.setValue(paramBinderDTO.getParamDefaultValue()); - if (componentBinder.getComponentType() == ComponentTypeEnum.K8S_MICROSERVICE) { + if (Objects.equals(componentBinder.getComponentType(), ComponentTypeEnum.K8S_MICROSERVICE.toString())) { ComponentSchema componentSchema = (ComponentSchema) schema; JSONObject spec = (JSONObject) componentSchema.getSpec().getWorkload().getSpec(); JSONArray envArray = spec.getJSONArray("env"); @@ -523,7 +532,7 @@ public class DeployAppProviderImpl implements DeployAppProvider { break; } } - } else if (componentBinder.getComponentType() == ComponentTypeEnum.RESOURCE_ADDON) { + } else if (Objects.equals(componentBinder.getComponentType(), ComponentTypeEnum.RESOURCE_ADDON.toString())) { ComponentSchema addonSchema = (ComponentSchema) schema; JSONObject spec = (JSONObject) addonSchema.getSpec().getWorkload().getSpec(); for (String key : spec.keySet()) { @@ -581,7 +590,7 @@ public class DeployAppProviderImpl implements DeployAppProvider { } private List getDataOutputList(ComponentBinder componentBinder, Schema schema) { - if (componentBinder.getComponentType() == ComponentTypeEnum.RESOURCE_ADDON) { + if (Objects.equals(componentBinder.getComponentType(), ComponentTypeEnum.RESOURCE_ADDON.toString())) { ComponentSchema addonSchema = (ComponentSchema) schema; return addonSchema.getSpec().getWorkload().getDataOutputs().stream().map(addonDataOutput -> { DataOutput dataOutput = new DataOutput(); @@ -618,7 +627,7 @@ public class DeployAppProviderImpl implements DeployAppProvider { private List getDataInputList(ComponentBinder componentBinder, Schema schema) { List dataInputList = new ArrayList<>(); - if (componentBinder.getComponentType() == ComponentTypeEnum.K8S_MICROSERVICE) { + if (Objects.equals(componentBinder.getComponentType(), ComponentTypeEnum.K8S_MICROSERVICE.toString())) { ComponentSchema componentSchema = (ComponentSchema) schema; for (ParamBinderDTO paramBinderDTO : componentBinder.getParamBinderList()) { if (StringUtils.startsWith(paramBinderDTO.getDataInputName(), "spec.")) { @@ -633,7 +642,7 @@ public class DeployAppProviderImpl implements DeployAppProvider { dataInput.setToFieldPaths(Collections.singletonList(paramBinderDTO.getDataInputName())); dataInputList.add(dataInput); - } else if (paramBinderDTO.getComponentType() == ComponentTypeEnum.RESOURCE_ADDON) { + } else if (ComponentTypeEnum.RESOURCE_ADDON.toString().equals(paramBinderDTO.getComponentType())) { DataInput dataInput = new DataInput(); DataInputValueFrom dataInputValueFrom = new DataInputValueFrom(); diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/provider/impl/MarketProviderImpl.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/provider/impl/MarketProviderImpl.java index 48db69cc..f71055b2 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/provider/impl/MarketProviderImpl.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/provider/impl/MarketProviderImpl.java @@ -332,7 +332,14 @@ public class MarketProviderImpl implements MarketProvider { /** * 将组件包进行重新压缩,并删除组件目录 */ - ZipUtil.zipFiles(component.getAbsolutePath(), Files.walk(componentPath).map(p -> p.toFile()).collect(Collectors.toList())); + Files.list(componentPath).forEach(f -> { + if(f.toFile().isDirectory()){ + ZipUtil.zipDirectory(component.getAbsolutePath(), f.toFile()); + } else { + ZipUtil.zipFile(component.getAbsolutePath(), f.toFile()); + } + }); + FileUtils.deleteDirectory(componentPath.toFile()); } diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/provider/impl/ProductReleaseProviderImpl.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/provider/impl/ProductReleaseProviderImpl.java index 4ecc9cef..c2e729d2 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/provider/impl/ProductReleaseProviderImpl.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/provider/impl/ProductReleaseProviderImpl.java @@ -126,7 +126,7 @@ public class ProductReleaseProviderImpl implements ProductReleaseProvider { JSONObject root = new JSONObject((Map) object); JSONObject options = root.getJSONObject("options"); String componentName = root.getString("componentName"); - ComponentTypeEnum componentType = ComponentTypeEnum.valueOf(root.getString("componentType")); + String componentType = root.getString("componentType"); results.add(ComponentBinder.builder() .componentType(componentType) .componentName(componentName) diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/AddonMetaRepository.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/AddonMetaRepository.java index da9694c9..575ad6c4 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/AddonMetaRepository.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/AddonMetaRepository.java @@ -46,7 +46,7 @@ public interface AddonMetaRepository { * @param addonId Addon ID * @return */ - AddonMetaDO get(ComponentTypeEnum addonType, String addonId); + AddonMetaDO get(String addonType, String addonId); /** * 根据条件查询 diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/AppComponentRepository.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/AppComponentRepository.java new file mode 100644 index 00000000..b683211b --- /dev/null +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/AppComponentRepository.java @@ -0,0 +1,19 @@ +package com.alibaba.tesla.appmanager.server.repository; + +import com.alibaba.tesla.appmanager.server.repository.condition.AppComponentQueryCondition; +import com.alibaba.tesla.appmanager.server.repository.domain.AppComponentDO; + +import java.util.List; + +public interface AppComponentRepository { + + long countByCondition(AppComponentQueryCondition condition); + + int deleteByCondition(AppComponentQueryCondition condition); + + int insert(AppComponentDO record); + + List selectByCondition(AppComponentQueryCondition condition); + + int updateByCondition(AppComponentDO record, AppComponentQueryCondition condition); +} diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/condition/AddonMetaQueryCondition.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/condition/AddonMetaQueryCondition.java index 8ab49193..9b5f9329 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/condition/AddonMetaQueryCondition.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/condition/AddonMetaQueryCondition.java @@ -24,5 +24,5 @@ public class AddonMetaQueryCondition extends BaseCondition { private String addonVersion; - private List addonTypeList; + private List addonTypeList; } diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/condition/AppAddonQueryCondition.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/condition/AppAddonQueryCondition.java index 09f24f7a..0fbe6f98 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/condition/AppAddonQueryCondition.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/condition/AppAddonQueryCondition.java @@ -24,7 +24,7 @@ public class AppAddonQueryCondition extends BaseCondition { private String appId; - private List addonTypeList; + private List addonTypeList; private String addonId; diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/condition/AppComponentQueryCondition.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/condition/AppComponentQueryCondition.java new file mode 100644 index 00000000..f95bfd7f --- /dev/null +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/condition/AppComponentQueryCondition.java @@ -0,0 +1,52 @@ +package com.alibaba.tesla.appmanager.server.repository.condition; + +import com.alibaba.tesla.appmanager.common.BaseCondition; +import com.alibaba.tesla.appmanager.common.enums.ComponentTypeEnum; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 应用组件查询条件 + * + * @author yaoxing.gyx@alibaba-inc.com + */ +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public class AppComponentQueryCondition extends BaseCondition { + + private Long id; + + /** + * 应用 ID + */ + private String appId; + + /** + * 分类 + */ + private String category; + + /** + * 组件类型 + */ + private String componentType; + + /** + * 组件名称 + */ + private String componentName; + + /** + * Namespace ID + */ + private String namespaceId; + + /** + * Stage ID + */ + private String stageId; +} diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/domain/AppAddonDO.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/domain/AppAddonDO.java index f9621ba3..79c740f6 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/domain/AppAddonDO.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/domain/AppAddonDO.java @@ -39,7 +39,7 @@ public class AppAddonDO { /** * 类型(可选 CORE-SERVICE / THIRDPARTY) */ - private ComponentTypeEnum addonType; + private String addonType; /** * 附加组件唯一标识 diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/domain/AppComponentDO.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/domain/AppComponentDO.java new file mode 100644 index 00000000..4b978793 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/domain/AppComponentDO.java @@ -0,0 +1,66 @@ +package com.alibaba.tesla.appmanager.server.repository.domain; + +import java.util.Date; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 应用组件绑定表 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class AppComponentDO { + /** + * ID + */ + private Long id; + + /** + * 创建时间 + */ + private Date gmtCreate; + + /** + * 最后修改时间 + */ + private Date gmtModified; + + /** + * Namespace ID + */ + private String namespaceId; + + /** + * Stage ID + */ + private String stageId; + + /** + * 应用 ID + */ + private String appId; + + /** + * 分类 + */ + private String category; + + /** + * 组件类型 + */ + private String componentType; + + /** + * 组件名称 + */ + private String componentName; + + /** + * 配置内容 + */ + private String config; +} \ No newline at end of file diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/domain/AppComponentDOExample.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/domain/AppComponentDOExample.java new file mode 100644 index 00000000..db8e7599 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/domain/AppComponentDOExample.java @@ -0,0 +1,801 @@ +package com.alibaba.tesla.appmanager.server.repository.domain; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +public class AppComponentDOExample { + protected String orderByClause; + + protected boolean distinct; + + protected List oredCriteria; + + public AppComponentDOExample() { + oredCriteria = new ArrayList<>(); + } + + public void setOrderByClause(String orderByClause) { + this.orderByClause = orderByClause; + } + + public String getOrderByClause() { + return orderByClause; + } + + public void setDistinct(boolean distinct) { + this.distinct = distinct; + } + + public boolean isDistinct() { + return distinct; + } + + public List getOredCriteria() { + return oredCriteria; + } + + public void or(Criteria criteria) { + oredCriteria.add(criteria); + } + + public Criteria or() { + Criteria criteria = createCriteriaInternal(); + oredCriteria.add(criteria); + return criteria; + } + + public Criteria createCriteria() { + Criteria criteria = createCriteriaInternal(); + if (oredCriteria.size() == 0) { + oredCriteria.add(criteria); + } + return criteria; + } + + protected Criteria createCriteriaInternal() { + Criteria criteria = new Criteria(); + return criteria; + } + + public void clear() { + oredCriteria.clear(); + orderByClause = null; + distinct = false; + } + + protected abstract static class GeneratedCriteria { + protected List criteria; + + protected GeneratedCriteria() { + super(); + criteria = new ArrayList<>(); + } + + public boolean isValid() { + return criteria.size() > 0; + } + + public List getAllCriteria() { + return criteria; + } + + public List getCriteria() { + return criteria; + } + + protected void addCriterion(String condition) { + if (condition == null) { + throw new RuntimeException("Value for condition cannot be null"); + } + criteria.add(new Criterion(condition)); + } + + protected void addCriterion(String condition, Object value, String property) { + if (value == null) { + throw new RuntimeException("Value for " + property + " cannot be null"); + } + criteria.add(new Criterion(condition, value)); + } + + protected void addCriterion(String condition, Object value1, Object value2, String property) { + if (value1 == null || value2 == null) { + throw new RuntimeException("Between values for " + property + " cannot be null"); + } + criteria.add(new Criterion(condition, value1, value2)); + } + + public Criteria andIdIsNull() { + addCriterion("id is null"); + return (Criteria) this; + } + + public Criteria andIdIsNotNull() { + addCriterion("id is not null"); + return (Criteria) this; + } + + public Criteria andIdEqualTo(Long value) { + addCriterion("id =", value, "id"); + return (Criteria) this; + } + + public Criteria andIdNotEqualTo(Long value) { + addCriterion("id <>", value, "id"); + return (Criteria) this; + } + + public Criteria andIdGreaterThan(Long value) { + addCriterion("id >", value, "id"); + return (Criteria) this; + } + + public Criteria andIdGreaterThanOrEqualTo(Long value) { + addCriterion("id >=", value, "id"); + return (Criteria) this; + } + + public Criteria andIdLessThan(Long value) { + addCriterion("id <", value, "id"); + return (Criteria) this; + } + + public Criteria andIdLessThanOrEqualTo(Long value) { + addCriterion("id <=", value, "id"); + return (Criteria) this; + } + + public Criteria andIdIn(List values) { + addCriterion("id in", values, "id"); + return (Criteria) this; + } + + public Criteria andIdNotIn(List values) { + addCriterion("id not in", values, "id"); + return (Criteria) this; + } + + public Criteria andIdBetween(Long value1, Long value2) { + addCriterion("id between", value1, value2, "id"); + return (Criteria) this; + } + + public Criteria andIdNotBetween(Long value1, Long value2) { + addCriterion("id not between", value1, value2, "id"); + return (Criteria) this; + } + + public Criteria andGmtCreateIsNull() { + addCriterion("gmt_create is null"); + return (Criteria) this; + } + + public Criteria andGmtCreateIsNotNull() { + addCriterion("gmt_create is not null"); + return (Criteria) this; + } + + public Criteria andGmtCreateEqualTo(Date value) { + addCriterion("gmt_create =", value, "gmtCreate"); + return (Criteria) this; + } + + public Criteria andGmtCreateNotEqualTo(Date value) { + addCriterion("gmt_create <>", value, "gmtCreate"); + return (Criteria) this; + } + + public Criteria andGmtCreateGreaterThan(Date value) { + addCriterion("gmt_create >", value, "gmtCreate"); + return (Criteria) this; + } + + public Criteria andGmtCreateGreaterThanOrEqualTo(Date value) { + addCriterion("gmt_create >=", value, "gmtCreate"); + return (Criteria) this; + } + + public Criteria andGmtCreateLessThan(Date value) { + addCriterion("gmt_create <", value, "gmtCreate"); + return (Criteria) this; + } + + public Criteria andGmtCreateLessThanOrEqualTo(Date value) { + addCriterion("gmt_create <=", value, "gmtCreate"); + return (Criteria) this; + } + + public Criteria andGmtCreateIn(List values) { + addCriterion("gmt_create in", values, "gmtCreate"); + return (Criteria) this; + } + + public Criteria andGmtCreateNotIn(List values) { + addCriterion("gmt_create not in", values, "gmtCreate"); + return (Criteria) this; + } + + public Criteria andGmtCreateBetween(Date value1, Date value2) { + addCriterion("gmt_create between", value1, value2, "gmtCreate"); + return (Criteria) this; + } + + public Criteria andGmtCreateNotBetween(Date value1, Date value2) { + addCriterion("gmt_create not between", value1, value2, "gmtCreate"); + return (Criteria) this; + } + + public Criteria andGmtModifiedIsNull() { + addCriterion("gmt_modified is null"); + return (Criteria) this; + } + + public Criteria andGmtModifiedIsNotNull() { + addCriterion("gmt_modified is not null"); + return (Criteria) this; + } + + public Criteria andGmtModifiedEqualTo(Date value) { + addCriterion("gmt_modified =", value, "gmtModified"); + return (Criteria) this; + } + + public Criteria andGmtModifiedNotEqualTo(Date value) { + addCriterion("gmt_modified <>", value, "gmtModified"); + return (Criteria) this; + } + + public Criteria andGmtModifiedGreaterThan(Date value) { + addCriterion("gmt_modified >", value, "gmtModified"); + return (Criteria) this; + } + + public Criteria andGmtModifiedGreaterThanOrEqualTo(Date value) { + addCriterion("gmt_modified >=", value, "gmtModified"); + return (Criteria) this; + } + + public Criteria andGmtModifiedLessThan(Date value) { + addCriterion("gmt_modified <", value, "gmtModified"); + return (Criteria) this; + } + + public Criteria andGmtModifiedLessThanOrEqualTo(Date value) { + addCriterion("gmt_modified <=", value, "gmtModified"); + return (Criteria) this; + } + + public Criteria andGmtModifiedIn(List values) { + addCriterion("gmt_modified in", values, "gmtModified"); + return (Criteria) this; + } + + public Criteria andGmtModifiedNotIn(List values) { + addCriterion("gmt_modified not in", values, "gmtModified"); + return (Criteria) this; + } + + public Criteria andGmtModifiedBetween(Date value1, Date value2) { + addCriterion("gmt_modified between", value1, value2, "gmtModified"); + return (Criteria) this; + } + + public Criteria andGmtModifiedNotBetween(Date value1, Date value2) { + addCriterion("gmt_modified not between", value1, value2, "gmtModified"); + return (Criteria) this; + } + + public Criteria andNamespaceIdIsNull() { + addCriterion("namespace_id is null"); + return (Criteria) this; + } + + public Criteria andNamespaceIdIsNotNull() { + addCriterion("namespace_id is not null"); + return (Criteria) this; + } + + public Criteria andNamespaceIdEqualTo(String value) { + addCriterion("namespace_id =", value, "namespaceId"); + return (Criteria) this; + } + + public Criteria andNamespaceIdNotEqualTo(String value) { + addCriterion("namespace_id <>", value, "namespaceId"); + return (Criteria) this; + } + + public Criteria andNamespaceIdGreaterThan(String value) { + addCriterion("namespace_id >", value, "namespaceId"); + return (Criteria) this; + } + + public Criteria andNamespaceIdGreaterThanOrEqualTo(String value) { + addCriterion("namespace_id >=", value, "namespaceId"); + return (Criteria) this; + } + + public Criteria andNamespaceIdLessThan(String value) { + addCriterion("namespace_id <", value, "namespaceId"); + return (Criteria) this; + } + + public Criteria andNamespaceIdLessThanOrEqualTo(String value) { + addCriterion("namespace_id <=", value, "namespaceId"); + return (Criteria) this; + } + + public Criteria andNamespaceIdLike(String value) { + addCriterion("namespace_id like", value, "namespaceId"); + return (Criteria) this; + } + + public Criteria andNamespaceIdNotLike(String value) { + addCriterion("namespace_id not like", value, "namespaceId"); + return (Criteria) this; + } + + public Criteria andNamespaceIdIn(List values) { + addCriterion("namespace_id in", values, "namespaceId"); + return (Criteria) this; + } + + public Criteria andNamespaceIdNotIn(List values) { + addCriterion("namespace_id not in", values, "namespaceId"); + return (Criteria) this; + } + + public Criteria andNamespaceIdBetween(String value1, String value2) { + addCriterion("namespace_id between", value1, value2, "namespaceId"); + return (Criteria) this; + } + + public Criteria andNamespaceIdNotBetween(String value1, String value2) { + addCriterion("namespace_id not between", value1, value2, "namespaceId"); + return (Criteria) this; + } + + public Criteria andStageIdIsNull() { + addCriterion("stage_id is null"); + return (Criteria) this; + } + + public Criteria andStageIdIsNotNull() { + addCriterion("stage_id is not null"); + return (Criteria) this; + } + + public Criteria andStageIdEqualTo(String value) { + addCriterion("stage_id =", value, "stageId"); + return (Criteria) this; + } + + public Criteria andStageIdNotEqualTo(String value) { + addCriterion("stage_id <>", value, "stageId"); + return (Criteria) this; + } + + public Criteria andStageIdGreaterThan(String value) { + addCriterion("stage_id >", value, "stageId"); + return (Criteria) this; + } + + public Criteria andStageIdGreaterThanOrEqualTo(String value) { + addCriterion("stage_id >=", value, "stageId"); + return (Criteria) this; + } + + public Criteria andStageIdLessThan(String value) { + addCriterion("stage_id <", value, "stageId"); + return (Criteria) this; + } + + public Criteria andStageIdLessThanOrEqualTo(String value) { + addCriterion("stage_id <=", value, "stageId"); + return (Criteria) this; + } + + public Criteria andStageIdLike(String value) { + addCriterion("stage_id like", value, "stageId"); + return (Criteria) this; + } + + public Criteria andStageIdNotLike(String value) { + addCriterion("stage_id not like", value, "stageId"); + return (Criteria) this; + } + + public Criteria andStageIdIn(List values) { + addCriterion("stage_id in", values, "stageId"); + return (Criteria) this; + } + + public Criteria andStageIdNotIn(List values) { + addCriterion("stage_id not in", values, "stageId"); + return (Criteria) this; + } + + public Criteria andStageIdBetween(String value1, String value2) { + addCriterion("stage_id between", value1, value2, "stageId"); + return (Criteria) this; + } + + public Criteria andStageIdNotBetween(String value1, String value2) { + addCriterion("stage_id not between", value1, value2, "stageId"); + return (Criteria) this; + } + + public Criteria andAppIdIsNull() { + addCriterion("app_id is null"); + return (Criteria) this; + } + + public Criteria andAppIdIsNotNull() { + addCriterion("app_id is not null"); + return (Criteria) this; + } + + public Criteria andAppIdEqualTo(String value) { + addCriterion("app_id =", value, "appId"); + return (Criteria) this; + } + + public Criteria andAppIdNotEqualTo(String value) { + addCriterion("app_id <>", value, "appId"); + return (Criteria) this; + } + + public Criteria andAppIdGreaterThan(String value) { + addCriterion("app_id >", value, "appId"); + return (Criteria) this; + } + + public Criteria andAppIdGreaterThanOrEqualTo(String value) { + addCriterion("app_id >=", value, "appId"); + return (Criteria) this; + } + + public Criteria andAppIdLessThan(String value) { + addCriterion("app_id <", value, "appId"); + return (Criteria) this; + } + + public Criteria andAppIdLessThanOrEqualTo(String value) { + addCriterion("app_id <=", value, "appId"); + return (Criteria) this; + } + + public Criteria andAppIdLike(String value) { + addCriterion("app_id like", value, "appId"); + return (Criteria) this; + } + + public Criteria andAppIdNotLike(String value) { + addCriterion("app_id not like", value, "appId"); + return (Criteria) this; + } + + public Criteria andAppIdIn(List values) { + addCriterion("app_id in", values, "appId"); + return (Criteria) this; + } + + public Criteria andAppIdNotIn(List values) { + addCriterion("app_id not in", values, "appId"); + return (Criteria) this; + } + + public Criteria andAppIdBetween(String value1, String value2) { + addCriterion("app_id between", value1, value2, "appId"); + return (Criteria) this; + } + + public Criteria andAppIdNotBetween(String value1, String value2) { + addCriterion("app_id not between", value1, value2, "appId"); + return (Criteria) this; + } + + public Criteria andCategoryIsNull() { + addCriterion("category is null"); + return (Criteria) this; + } + + public Criteria andCategoryIsNotNull() { + addCriterion("category is not null"); + return (Criteria) this; + } + + public Criteria andCategoryEqualTo(String value) { + addCriterion("category =", value, "category"); + return (Criteria) this; + } + + public Criteria andCategoryNotEqualTo(String value) { + addCriterion("category <>", value, "category"); + return (Criteria) this; + } + + public Criteria andCategoryGreaterThan(String value) { + addCriterion("category >", value, "category"); + return (Criteria) this; + } + + public Criteria andCategoryGreaterThanOrEqualTo(String value) { + addCriterion("category >=", value, "category"); + return (Criteria) this; + } + + public Criteria andCategoryLessThan(String value) { + addCriterion("category <", value, "category"); + return (Criteria) this; + } + + public Criteria andCategoryLessThanOrEqualTo(String value) { + addCriterion("category <=", value, "category"); + return (Criteria) this; + } + + public Criteria andCategoryLike(String value) { + addCriterion("category like", value, "category"); + return (Criteria) this; + } + + public Criteria andCategoryNotLike(String value) { + addCriterion("category not like", value, "category"); + return (Criteria) this; + } + + public Criteria andCategoryIn(List values) { + addCriterion("category in", values, "category"); + return (Criteria) this; + } + + public Criteria andCategoryNotIn(List values) { + addCriterion("category not in", values, "category"); + return (Criteria) this; + } + + public Criteria andCategoryBetween(String value1, String value2) { + addCriterion("category between", value1, value2, "category"); + return (Criteria) this; + } + + public Criteria andCategoryNotBetween(String value1, String value2) { + addCriterion("category not between", value1, value2, "category"); + return (Criteria) this; + } + + public Criteria andComponentTypeIsNull() { + addCriterion("component_type is null"); + return (Criteria) this; + } + + public Criteria andComponentTypeIsNotNull() { + addCriterion("component_type is not null"); + return (Criteria) this; + } + + public Criteria andComponentTypeEqualTo(String value) { + addCriterion("component_type =", value, "componentType"); + return (Criteria) this; + } + + public Criteria andComponentTypeNotEqualTo(String value) { + addCriterion("component_type <>", value, "componentType"); + return (Criteria) this; + } + + public Criteria andComponentTypeGreaterThan(String value) { + addCriterion("component_type >", value, "componentType"); + return (Criteria) this; + } + + public Criteria andComponentTypeGreaterThanOrEqualTo(String value) { + addCriterion("component_type >=", value, "componentType"); + return (Criteria) this; + } + + public Criteria andComponentTypeLessThan(String value) { + addCriterion("component_type <", value, "componentType"); + return (Criteria) this; + } + + public Criteria andComponentTypeLessThanOrEqualTo(String value) { + addCriterion("component_type <=", value, "componentType"); + return (Criteria) this; + } + + public Criteria andComponentTypeLike(String value) { + addCriterion("component_type like", value, "componentType"); + return (Criteria) this; + } + + public Criteria andComponentTypeNotLike(String value) { + addCriterion("component_type not like", value, "componentType"); + return (Criteria) this; + } + + public Criteria andComponentTypeIn(List values) { + addCriterion("component_type in", values, "componentType"); + return (Criteria) this; + } + + public Criteria andComponentTypeNotIn(List values) { + addCriterion("component_type not in", values, "componentType"); + return (Criteria) this; + } + + public Criteria andComponentTypeBetween(String value1, String value2) { + addCriterion("component_type between", value1, value2, "componentType"); + return (Criteria) this; + } + + public Criteria andComponentTypeNotBetween(String value1, String value2) { + addCriterion("component_type not between", value1, value2, "componentType"); + return (Criteria) this; + } + + public Criteria andComponentNameIsNull() { + addCriterion("component_name is null"); + return (Criteria) this; + } + + public Criteria andComponentNameIsNotNull() { + addCriterion("component_name is not null"); + return (Criteria) this; + } + + public Criteria andComponentNameEqualTo(String value) { + addCriterion("component_name =", value, "componentName"); + return (Criteria) this; + } + + public Criteria andComponentNameNotEqualTo(String value) { + addCriterion("component_name <>", value, "componentName"); + return (Criteria) this; + } + + public Criteria andComponentNameGreaterThan(String value) { + addCriterion("component_name >", value, "componentName"); + return (Criteria) this; + } + + public Criteria andComponentNameGreaterThanOrEqualTo(String value) { + addCriterion("component_name >=", value, "componentName"); + return (Criteria) this; + } + + public Criteria andComponentNameLessThan(String value) { + addCriterion("component_name <", value, "componentName"); + return (Criteria) this; + } + + public Criteria andComponentNameLessThanOrEqualTo(String value) { + addCriterion("component_name <=", value, "componentName"); + return (Criteria) this; + } + + public Criteria andComponentNameLike(String value) { + addCriterion("component_name like", value, "componentName"); + return (Criteria) this; + } + + public Criteria andComponentNameNotLike(String value) { + addCriterion("component_name not like", value, "componentName"); + return (Criteria) this; + } + + public Criteria andComponentNameIn(List values) { + addCriterion("component_name in", values, "componentName"); + return (Criteria) this; + } + + public Criteria andComponentNameNotIn(List values) { + addCriterion("component_name not in", values, "componentName"); + return (Criteria) this; + } + + public Criteria andComponentNameBetween(String value1, String value2) { + addCriterion("component_name between", value1, value2, "componentName"); + return (Criteria) this; + } + + public Criteria andComponentNameNotBetween(String value1, String value2) { + addCriterion("component_name not between", value1, value2, "componentName"); + return (Criteria) this; + } + } + + public static class Criteria extends GeneratedCriteria { + + protected Criteria() { + super(); + } + } + + public static class Criterion { + private String condition; + + private Object value; + + private Object secondValue; + + private boolean noValue; + + private boolean singleValue; + + private boolean betweenValue; + + private boolean listValue; + + private String typeHandler; + + public String getCondition() { + return condition; + } + + public Object getValue() { + return value; + } + + public Object getSecondValue() { + return secondValue; + } + + public boolean isNoValue() { + return noValue; + } + + public boolean isSingleValue() { + return singleValue; + } + + public boolean isBetweenValue() { + return betweenValue; + } + + public boolean isListValue() { + return listValue; + } + + public String getTypeHandler() { + return typeHandler; + } + + protected Criterion(String condition) { + super(); + this.condition = condition; + this.typeHandler = null; + this.noValue = true; + } + + protected Criterion(String condition, Object value, String typeHandler) { + super(); + this.condition = condition; + this.value = value; + this.typeHandler = typeHandler; + if (value instanceof List) { + this.listValue = true; + } else { + this.singleValue = true; + } + } + + protected Criterion(String condition, Object value) { + this(condition, value, null); + } + + protected Criterion(String condition, Object value, Object secondValue, String typeHandler) { + super(); + this.condition = condition; + this.value = value; + this.secondValue = secondValue; + this.typeHandler = typeHandler; + this.betweenValue = true; + } + + protected Criterion(String condition, Object value, Object secondValue) { + this(condition, value, secondValue, null); + } + } +} \ No newline at end of file diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/impl/AddonMetaRepositoryImpl.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/impl/AddonMetaRepositoryImpl.java index b9c0c610..c56736d5 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/impl/AddonMetaRepositoryImpl.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/impl/AddonMetaRepositoryImpl.java @@ -49,7 +49,7 @@ public class AddonMetaRepositoryImpl implements AddonMetaRepository { } @Override - public AddonMetaDO get(ComponentTypeEnum addonType, String addonId) { + public AddonMetaDO get(String addonType, String addonId) { AddonMetaQueryCondition condition = AddonMetaQueryCondition.builder() .addonTypeList(Collections.singletonList(addonType)) .addonId(addonId) @@ -97,8 +97,7 @@ public class AddonMetaRepositoryImpl implements AddonMetaRepository { criteria.andAddonVersionEqualTo(condition.getAddonVersion()); } if (CollectionUtils.isNotEmpty(condition.getAddonTypeList())) { - criteria.andAddonTypeIn( - condition.getAddonTypeList().stream().map(Enum::toString).collect(Collectors.toList())); + criteria.andAddonTypeIn(condition.getAddonTypeList()); } return example; } diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/impl/AppAddonRepositoryImpl.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/impl/AppAddonRepositoryImpl.java index 79654530..8a23e18a 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/impl/AppAddonRepositoryImpl.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/impl/AppAddonRepositoryImpl.java @@ -61,10 +61,7 @@ public class AppAddonRepositoryImpl implements AppAddonRepository { criteria.andAppIdEqualTo(condition.getAppId()); } if (CollectionUtils.isNotEmpty(condition.getAddonTypeList())) { - criteria.andAddonTypeIn( - condition.getAddonTypeList().stream() - .map(Enum::toString) - .collect(Collectors.toList())); + criteria.andAddonTypeIn(condition.getAddonTypeList()); } if (StringUtils.isNotEmpty(condition.getAddonId())) { criteria.andAddonIdEqualTo(condition.getAddonId()); diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/impl/AppComponentRepositoryImpl.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/impl/AppComponentRepositoryImpl.java new file mode 100644 index 00000000..41056db4 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/impl/AppComponentRepositoryImpl.java @@ -0,0 +1,98 @@ +package com.alibaba.tesla.appmanager.server.repository.impl; + +import com.alibaba.tesla.appmanager.common.util.DateUtil; +import com.alibaba.tesla.appmanager.server.repository.AppComponentRepository; +import com.alibaba.tesla.appmanager.server.repository.condition.AppComponentQueryCondition; +import com.alibaba.tesla.appmanager.server.repository.domain.AppComponentDO; +import com.alibaba.tesla.appmanager.server.repository.domain.AppComponentDOExample; +import com.alibaba.tesla.appmanager.server.repository.mapper.AppComponentDOMapper; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Date; +import java.util.List; + +/** + * 应用组件绑定 Repository + * + * @author yaoxing.gyx@alibaba-inc.com + */ +@Service +@Slf4j +public class AppComponentRepositoryImpl implements AppComponentRepository { + + @Autowired + private AppComponentDOMapper mapper; + + @Override + public long countByCondition(AppComponentQueryCondition condition) { + return mapper.countByExample(buildExample(condition)); + } + + @Override + public int deleteByCondition(AppComponentQueryCondition condition) { + return mapper.deleteByExample(buildExample(condition)); + } + + @Override + public int insert(AppComponentDO record) { + return mapper.insertSelective(insertDate(record)); + } + + @Override + public List selectByCondition(AppComponentQueryCondition condition) { + AppComponentDOExample example = buildExample(condition); + if (condition.isWithBlobs()) { + return mapper.selectByExampleWithBLOBs(example); + } else { + return mapper.selectByExample(example); + } + } + + @Override + public int updateByCondition(AppComponentDO record, AppComponentQueryCondition condition) { + return mapper.updateByExampleSelective(updateDate(record), buildExample(condition)); + } + + private AppComponentDOExample buildExample(AppComponentQueryCondition condition) { + AppComponentDOExample example = new AppComponentDOExample(); + AppComponentDOExample.Criteria criteria = example.createCriteria(); + if (condition.getId() != null && condition.getId() > 0) { + criteria.andIdEqualTo(condition.getId()); + } + if (StringUtils.isNotBlank(condition.getAppId())) { + criteria.andAppIdEqualTo(condition.getAppId()); + } + if (StringUtils.isNotBlank(condition.getCategory())) { + criteria.andCategoryEqualTo(condition.getCategory()); + } + if (StringUtils.isNotBlank(condition.getComponentType())) { + criteria.andComponentTypeEqualTo(condition.getComponentType()); + } + if (StringUtils.isNotBlank(condition.getComponentName())) { + criteria.andComponentNameEqualTo(condition.getComponentName()); + } + if (StringUtils.isNotBlank(condition.getNamespaceId())) { + criteria.andNamespaceIdEqualTo(condition.getNamespaceId()); + } + if (StringUtils.isNotBlank(condition.getStageId())) { + criteria.andStageIdEqualTo(condition.getStageId()); + } + return example; + } + + private AppComponentDO insertDate(AppComponentDO record) { + Date now = DateUtil.now(); + record.setGmtCreate(now); + record.setGmtModified(now); + return record; + } + + private AppComponentDO updateDate(AppComponentDO record) { + Date now = DateUtil.now(); + record.setGmtModified(now); + return record; + } +} diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/impl/CustomAddonMetaRepositoryImpl.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/impl/CustomAddonMetaRepositoryImpl.java index 7760aa13..5aebc82c 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/impl/CustomAddonMetaRepositoryImpl.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/impl/CustomAddonMetaRepositoryImpl.java @@ -98,9 +98,7 @@ public class CustomAddonMetaRepositoryImpl implements CustomAddonMetaRepository criteria.andAddonVersionEqualTo(condition.getAddonVersion()); } if (org.apache.commons.collections.CollectionUtils.isNotEmpty(condition.getAddonTypeList())) { - criteria.andAddonTypeIn( - condition.getAddonTypeList().stream().map(Enum::toString).collect( - Collectors.toList())); + criteria.andAddonTypeIn(condition.getAddonTypeList()); } return example; } diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/mapper/AppComponentDOMapper.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/mapper/AppComponentDOMapper.java new file mode 100644 index 00000000..96447f34 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/repository/mapper/AppComponentDOMapper.java @@ -0,0 +1,22 @@ +package com.alibaba.tesla.appmanager.server.repository.mapper; + +import com.alibaba.tesla.appmanager.server.repository.domain.AppComponentDO; +import com.alibaba.tesla.appmanager.server.repository.domain.AppComponentDOExample; +import java.util.List; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +@Mapper +public interface AppComponentDOMapper { + long countByExample(AppComponentDOExample example); + + int deleteByExample(AppComponentDOExample example); + + int insertSelective(AppComponentDO record); + + List selectByExampleWithBLOBs(AppComponentDOExample example); + + List selectByExample(AppComponentDOExample example); + + int updateByExampleSelective(@Param("record") AppComponentDO record, @Param("example") AppComponentDOExample example); +} \ No newline at end of file diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/addon/AddonMetaService.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/addon/AddonMetaService.java index 8ff0a924..bdc1b213 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/addon/AddonMetaService.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/addon/AddonMetaService.java @@ -35,7 +35,7 @@ public interface AddonMetaService { * @param addonId Addon ID * @return AddonMetaDO */ - AddonMetaDO get(ComponentTypeEnum addonType, String addonId); + AddonMetaDO get(String addonType, String addonId); /** * 更新指定的 Addon 元信息 diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/addon/impl/AddonMetaServiceImpl.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/addon/impl/AddonMetaServiceImpl.java index 0a3d9a4b..1cf01713 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/addon/impl/AddonMetaServiceImpl.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/addon/impl/AddonMetaServiceImpl.java @@ -51,7 +51,7 @@ public class AddonMetaServiceImpl implements AddonMetaService { * @return AddonMetaDO */ @Override - public AddonMetaDO get(ComponentTypeEnum addonType, String addonId) { + public AddonMetaDO get(String addonType, String addonId) { return addonMetaRepository.get(addonType, addonId); } diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/appaddon/impl/AppAddonServiceImpl.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/appaddon/impl/AppAddonServiceImpl.java index 81cad8fb..f945fe3f 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/appaddon/impl/AppAddonServiceImpl.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/appaddon/impl/AppAddonServiceImpl.java @@ -14,7 +14,7 @@ import com.alibaba.tesla.appmanager.domain.dto.AppAddonDTO; import com.alibaba.tesla.appmanager.domain.req.AppAddonCreateReq; import com.alibaba.tesla.appmanager.domain.req.appaddon.AppAddonSyncReq; import com.alibaba.tesla.appmanager.domain.req.deployconfig.DeployConfigDeleteReq; -import com.alibaba.tesla.appmanager.domain.req.deployconfig.DeployConfigUpdateReq; +import com.alibaba.tesla.appmanager.domain.req.deployconfig.DeployConfigUpsertReq; import com.alibaba.tesla.appmanager.server.assembly.AppAddonDtoConvert; import com.alibaba.tesla.appmanager.server.repository.AppAddonRepository; import com.alibaba.tesla.appmanager.server.repository.condition.AppAddonQueryCondition; @@ -100,11 +100,11 @@ public class AppAddonServiceImpl implements AppAddonService { public AppAddonDO create(AppAddonCreateReq request) { AddonMetaDO addonMetaDO; if (StringUtils.isNotEmpty(request.getAddonType()) && StringUtils.isNotEmpty(request.getAddonId())) { - addonMetaDO = addonMetaService.get(ComponentTypeEnum.parse(request.getAddonType()), request.getAddonId()); + addonMetaDO = addonMetaService.get(request.getAddonType(), request.getAddonId()); } else { addonMetaDO = addonMetaService.get(request.getAddonMetaId()); } - ComponentTypeEnum addonType = ComponentTypeEnum.parse(addonMetaDO.getAddonType()); + String addonType = addonMetaDO.getAddonType(); AppAddonDTO appAddonDTO = AppAddonDTO.builder() .appId(request.getAppId()) .namespaceId(request.getNamespaceId()) @@ -123,7 +123,7 @@ public class AppAddonServiceImpl implements AppAddonService { // 更新 application configuration 绑定关系 String componentName; - if (addonType.isInternalAddon()) { + if (ComponentTypeEnum.INTERNAL_ADDON.toString().equals(addonType)) { componentName = addonMetaDO.getAddonId(); } else { componentName = AddonUtil.combineComponentName(addonMetaDO.getAddonId(), request.getAddonName()); @@ -136,7 +136,7 @@ public class AppAddonServiceImpl implements AppAddonService { requestNamespaceId = EnvUtil.defaultNamespaceId(); requestStageId = EnvUtil.defaultStageId(); } - deployConfigService.update(DeployConfigUpdateReq.builder() + deployConfigService.update(DeployConfigUpsertReq.builder() .apiVersion(DefaultConstant.API_VERSION_V1_ALPHA2) .appId(request.getAppId()) .typeId(typeId) @@ -165,7 +165,7 @@ public class AppAddonServiceImpl implements AppAddonService { } String appId = condition.getAppId(); String componentName; - if (appAddon.getAddonType().isInternalAddon()) { + if (ComponentTypeEnum.INTERNAL_ADDON.toString().equals(appAddon.getAddonType())) { componentName = appAddon.getAddonId(); } else { componentName = AddonUtil.combineComponentName(appAddon.getAddonId(), appAddon.getName()); @@ -197,13 +197,13 @@ public class AppAddonServiceImpl implements AppAddonService { } for (AppAddonDO appAddon : appAddons) { String componentName; - if (appAddon.getAddonType().isInternalAddon()) { + if (ComponentTypeEnum.INTERNAL_ADDON.toString().equals(appAddon.getAddonType())) { componentName = appAddon.getAddonId(); } else { componentName = AddonUtil.combineComponentName(appAddon.getAddonId(), appAddon.getName()); } String typeId = new DeployConfigTypeId(appAddon.getAddonType(), componentName).toString(); - deployConfigService.update(DeployConfigUpdateReq.builder() + deployConfigService.update(DeployConfigUpsertReq.builder() .apiVersion(DefaultConstant.API_VERSION_V1_ALPHA2) .appId(appAddon.getAppId()) .typeId(typeId) diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/appcomponent/AppComponentService.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/appcomponent/AppComponentService.java new file mode 100644 index 00000000..f15aecfd --- /dev/null +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/appcomponent/AppComponentService.java @@ -0,0 +1,55 @@ +package com.alibaba.tesla.appmanager.server.service.appcomponent; + +import com.alibaba.tesla.appmanager.server.repository.condition.AppComponentQueryCondition; +import com.alibaba.tesla.appmanager.server.repository.domain.AppComponentDO; + +import java.util.List; + +/** + * 应用绑定组件服务 + * + * @author yaoxing.gyx@alibaba-inc.com + */ +public interface AppComponentService { + + /** + * 根据条件过滤应用绑定组件 + * + * @param condition 过滤条件 + * @return List + */ + List list(AppComponentQueryCondition condition); + + /** + * 根据条件获取指定的应用绑定组件 + * + * @param condition 查询条件 + * @return List + */ + AppComponentDO get(AppComponentQueryCondition condition); + + /** + * 创建应用绑定组件 + * + * @param record 绑定记录 + * @return 数据库更新数量 + */ + int create(AppComponentDO record); + + /** + * 更新应用绑定组件 + * + * @param record 绑定记录 + * @param condition 查询条件 + * @return 数据库更新数量 + */ + int update(AppComponentDO record, AppComponentQueryCondition condition); + + /** + * 删除应用绑定组件 + * + * @param condition 查询条件 + * @return 数据库更新数量 + */ + int delete(AppComponentQueryCondition condition); +} diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/appcomponent/impl/AppComponentServiceImpl.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/appcomponent/impl/AppComponentServiceImpl.java new file mode 100644 index 00000000..d3b36cd4 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/appcomponent/impl/AppComponentServiceImpl.java @@ -0,0 +1,89 @@ +package com.alibaba.tesla.appmanager.server.service.appcomponent.impl; + +import com.alibaba.fastjson.JSONObject; +import com.alibaba.tesla.appmanager.common.exception.AppErrorCode; +import com.alibaba.tesla.appmanager.common.exception.AppException; +import com.alibaba.tesla.appmanager.server.repository.AppComponentRepository; +import com.alibaba.tesla.appmanager.server.repository.condition.AppComponentQueryCondition; +import com.alibaba.tesla.appmanager.server.repository.domain.AppComponentDO; +import com.alibaba.tesla.appmanager.server.service.appcomponent.AppComponentService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 应用绑定组件服务 + * + * @author yaoxing.gyx@alibaba-inc.com + */ +@Service +@Slf4j +public class AppComponentServiceImpl implements AppComponentService { + + @Autowired + private AppComponentRepository appComponentRepository; + + /** + * 根据条件过滤应用绑定组件 + * + * @param condition 过滤条件 + * @return List + */ + @Override + public List list(AppComponentQueryCondition condition) { + return appComponentRepository.selectByCondition(condition); + } + + /** + * 根据条件获取指定的应用绑定组件 + * + * @param condition 查询条件 + * @return List + */ + @Override + public AppComponentDO get(AppComponentQueryCondition condition) { + condition.setWithBlobs(true); + List records = appComponentRepository.selectByCondition(condition); + if (records.size() == 0) { + return null; + } else { + return records.get(0); + } + } + + /** + * 创建应用绑定组件 + * + * @param record 绑定记录 + * @return 数据库更新数量 + */ + @Override + public int create(AppComponentDO record) { + return appComponentRepository.insert(record); + } + + /** + * 更新应用绑定组件 + * + * @param record 绑定记录 + * @param condition 查询条件 + * @return 数据库更新数量 + */ + @Override + public int update(AppComponentDO record, AppComponentQueryCondition condition) { + return appComponentRepository.updateByCondition(record, condition); + } + + /** + * 删除应用绑定组件 + * + * @param condition 查询条件 + * @return 数据库更新数量 + */ + @Override + public int delete(AppComponentQueryCondition condition) { + return appComponentRepository.deleteByCondition(condition); + } +} diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/appoption/AppOptionConstant.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/appoption/AppOptionConstant.java index 6f03b86a..2dc6bab3 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/appoption/AppOptionConstant.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/appoption/AppOptionConstant.java @@ -47,6 +47,11 @@ public class AppOptionConstant { */ public static final String APP_NAV_LINK = "navLink"; + /** + * 是否在导航中显示 + */ + public static final String APP_IS_SHOW_IN_NAV = "isShowInNav"; + /** * 应用配置 Key 类型映射字典 */ @@ -116,7 +121,7 @@ public class AppOptionConstant { // 是否需要日常环境 put("isNeedDailyEnv", AppOptionTypeEnum.INTEGER); // 是否在导航中显示 - put("isShowInNav", AppOptionTypeEnum.INTEGER); + put(APP_IS_SHOW_IN_NAV, AppOptionTypeEnum.INTEGER); // 是否包含钉钉二维码 put("isHasDingdingQrcode", AppOptionTypeEnum.INTEGER); // 是否包含导航条 diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/appoption/AppOptionService.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/appoption/AppOptionService.java index 824ea0cd..d3156a31 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/appoption/AppOptionService.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/appoption/AppOptionService.java @@ -36,7 +36,16 @@ public interface AppOptionService { * @param appId 应用 ID * @return List of AppOptionDO */ - List getOptions(String appId); + List getOptionsByApp(String appId); + + /** + * 获取指定 key+value 对应的全部 Option 内容 + * + * @param key 配置 Key + * @param value 配置 Value + * @return List of AppOptionDO + */ + List getOptionsByKeyValue(String key, String value); /** * 获取指定应用下的全部 Option 内容 (带缓存, 可能有延迟) diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/appoption/impl/AppOptionServiceImpl.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/appoption/impl/AppOptionServiceImpl.java index d19fbfcc..0fbe5759 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/appoption/impl/AppOptionServiceImpl.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/appoption/impl/AppOptionServiceImpl.java @@ -50,7 +50,7 @@ public class AppOptionServiceImpl implements AppOptionService { @Override @Transactional(rollbackFor = Exception.class) public void init(String appId) { - List currentOptions = getOptions(appId); + List currentOptions = getOptionsByApp(appId); if (currentOptions.size() > 0) { log.info("action=appOptionInit|message=no need to init application options|appId={}|optionSize={}", appId, currentOptions.size()); @@ -81,10 +81,22 @@ public class AppOptionServiceImpl implements AppOptionService { * @return List of AppOptionDO */ @Override - public List getOptions(String appId) { + public List getOptionsByApp(String appId) { return appOptionRepository.selectByCondition(AppOptionQueryCondition.builder().appId(appId).build()); } + /** + * 获取指定 key+value 对应的全部 Option 内容 + * + * @param key 配置 Key + * @param value 配置 Value + * @return List of AppOptionDO + */ + @Override + public List getOptionsByKeyValue(String key, String value) { + return appOptionRepository.selectByCondition(AppOptionQueryCondition.builder().key(key).value(value).build()); + } + /** * 获取指定应用下的全部 Option 内容 (带缓存, 可能有延迟) * @@ -104,7 +116,7 @@ public class AppOptionServiceImpl implements AppOptionService { } } - List options = getOptions(appId); + List options = getOptionsByApp(appId); redisTemplate.opsForValue().set(key, JSONObject.toJSONString(options), 10, TimeUnit.MINUTES); log.info("set cached options|appId={}|options={}", appId, JSONObject.toJSONString(options)); return options; @@ -119,7 +131,7 @@ public class AppOptionServiceImpl implements AppOptionService { @Override public JSONObject getOptionMap(String appId) { JSONObject optionMap = new JSONObject(); - getOptions(appId).forEach(item -> + getOptionsByApp(appId).forEach(item -> optionMap.put(item.getKey(), appOptionTypeManager.get(item.getValueType()).decode(item.getValue()))); return optionMap; } @@ -202,7 +214,7 @@ public class AppOptionServiceImpl implements AppOptionService { log.info("action=appOptionUpdate|message=options have updated|appId={}|deleted={}|updated={}", appId, deleted, updated); } - return getOptions(appId); + return getOptionsByApp(appId); } /** diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/apppackage/AppPackageTaskService.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/apppackage/AppPackageTaskService.java index 0849110f..9cec9c64 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/apppackage/AppPackageTaskService.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/apppackage/AppPackageTaskService.java @@ -56,5 +56,5 @@ public interface AppPackageTaskService { * @return next version */ String getComponentNextVersion( - String appId, ComponentTypeEnum componentType, String componentName, String fullVersion); + String appId, String componentType, String componentName, String fullVersion); } diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/apppackage/impl/AppPackageServiceImpl.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/apppackage/impl/AppPackageServiceImpl.java index 711ee8c7..423c452b 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/apppackage/impl/AppPackageServiceImpl.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/apppackage/impl/AppPackageServiceImpl.java @@ -311,13 +311,12 @@ public class AppPackageServiceImpl implements AppPackageService { List componentPackages) { Set hitRevisionSet = new HashSet<>(); for (ComponentPackageDO componentPackage : componentPackages) { - ComponentTypeEnum componentType = Enums.getIfPresent( - ComponentTypeEnum.class, componentPackage.getComponentType()).orNull(); + String componentType = componentPackage.getComponentType(); String componentName = componentPackage.getComponentName(); String packageOptionStr = componentPackage.getPackageOptions(); - if (componentType == null) { + if (StringUtils.isEmpty(componentType)) { throw new AppException(AppErrorCode.INVALID_USER_ARGS, - String.format("unsupported component type %s", componentPackage.getComponentType())); + String.format("empty component type %s", componentPackage.getComponentType())); } if (StringUtils.isEmpty(packageOptionStr)) { continue; @@ -347,7 +346,7 @@ public class AppPackageServiceImpl implements AppPackageService { // 搜索不到的时候,包里面也没有包含配置的时候,尝试从系统中寻找类型通用配置 if (currentComponent == null && !req.isComponentPackageConfigurationFirst()) { - String typeId = new DeployConfigTypeId(componentType).toString(); + String typeId = new DeployConfigTypeId(componentType, null).toString(); List records = deployConfigService.list(DeployConfigQueryCondition.builder() .apiVersion(DefaultConstant.API_VERSION_V1_ALPHA2) .appId("") @@ -366,80 +365,75 @@ public class AppPackageServiceImpl implements AppPackageService { } // 针对搜索到的 SpecComponent 进行附加工作 - switch (componentType) { - case K8S_MICROSERVICE: - case K8S_JOB: - // parameterValues Binder - JSONArray jsonBinderParameterValues = packageOption.getJSONArray("binderParameterValues"); - if (jsonBinderParameterValues != null) { - List parameterValues = jsonBinderParameterValues - .toJavaList(ParamBinderDTO.class); - for (ParamBinderDTO item : parameterValues) { - String inputName = item.getDataInputName(); + if (ComponentTypeEnum.K8S_MICROSERVICE.toString().equals(componentType) + || ComponentTypeEnum.K8S_JOB.toString().equals(componentType)) {// parameterValues Binder + JSONArray jsonBinderParameterValues = packageOption.getJSONArray("binderParameterValues"); + if (jsonBinderParameterValues != null) { + List parameterValues = jsonBinderParameterValues + .toJavaList(ParamBinderDTO.class); + for (ParamBinderDTO item : parameterValues) { + String inputName = item.getDataInputName(); - // defaultValue 如果存在,第一优先级寻找并填入 (仅当前 ApplicationConfiguration 不存在时) - // 如果存在依赖的组件变量,那么第二优先级填入,目标为 spec.env.$inputName - ComponentTypeEnum dependencyComponentType = item.getComponentType(); - String dependencyComponentName = item.getComponentName(); - String dependencyOutputName = item.getDataOutputName(); - String defaultValue = item.getParamDefaultValue(); - if (StringUtils.isNotEmpty(defaultValue)) { - boolean findFlag = false; - for (DeployAppSchema.ParameterValue componentParameterValue - : currentComponent.getParameterValues()) { - if (componentParameterValue.getName().equals(inputName)) { - findFlag = true; - break; - } + // defaultValue 如果存在,第一优先级寻找并填入 (仅当前 ApplicationConfiguration 不存在时) + // 如果存在依赖的组件变量,那么第二优先级填入,目标为 spec.env.$inputName + String dependencyComponentType = item.getComponentType(); + String dependencyComponentName = item.getComponentName(); + String dependencyOutputName = item.getDataOutputName(); + String defaultValue = item.getParamDefaultValue(); + if (StringUtils.isNotEmpty(defaultValue)) { + boolean findFlag = false; + for (DeployAppSchema.ParameterValue componentParameterValue + : currentComponent.getParameterValues()) { + if (componentParameterValue.getName().equals(inputName)) { + findFlag = true; + break; } - if (!findFlag) { - currentComponent.getParameterValues().add(DeployAppSchema.ParameterValue.builder() - .name(inputName) - .value(defaultValue) - .build()); - } - } else if (dependencyComponentType != null - && StringUtils.isNotEmpty(dependencyComponentName) - && StringUtils.isNotEmpty(dependencyOutputName)) { - String defaultDataOutputName = generateDataOutputName( - dependencyComponentType, dependencyComponentName, dependencyOutputName); - boolean findFlag = false; - for (DeployAppSchema.DataInput componentDataInput : currentComponent.getDataInputs()) { - if (componentDataInput.getValueFrom().getDataOutputName() - .equals(defaultDataOutputName)) { - findFlag = true; - break; - } - } - if (!findFlag) { - currentComponent.getDataInputs().add(DeployAppSchema.DataInput.builder() - .valueFrom(DeployAppSchema.DataInputValueFrom.builder() - .dataOutputName(defaultDataOutputName) - .build()) - .toFieldPaths(Collections.singletonList( - String.format("spec.env.%s", inputName))) - .build()); + } + if (!findFlag) { + currentComponent.getParameterValues().add(DeployAppSchema.ParameterValue.builder() + .name(inputName) + .value(defaultValue) + .build()); + } + } else if (dependencyComponentType != null + && StringUtils.isNotEmpty(dependencyComponentName) + && StringUtils.isNotEmpty(dependencyOutputName)) { + String defaultDataOutputName = generateDataOutputName( + dependencyComponentType, dependencyComponentName, dependencyOutputName); + boolean findFlag = false; + for (DeployAppSchema.DataInput componentDataInput : currentComponent.getDataInputs()) { + if (componentDataInput.getValueFrom().getDataOutputName() + .equals(defaultDataOutputName)) { + findFlag = true; + break; } } + if (!findFlag) { + currentComponent.getDataInputs().add(DeployAppSchema.DataInput.builder() + .valueFrom(DeployAppSchema.DataInputValueFrom.builder() + .dataOutputName(defaultDataOutputName) + .build()) + .toFieldPaths(Collections.singletonList( + String.format("spec.env.%s", inputName))) + .build()); + } } } + } - // dependencies Binder - JSONArray jsonBinderDependencies = packageOption.getJSONArray("binderDependencies"); - if (jsonBinderDependencies != null) { - List dependencies = jsonBinderDependencies.toJavaList(String.class); - // TODO - } + // dependencies Binder + JSONArray jsonBinderDependencies = packageOption.getJSONArray("binderDependencies"); + if (jsonBinderDependencies != null) { + List dependencies = jsonBinderDependencies.toJavaList(String.class); + // TODO + } - // traits Binder - JSONArray jsonBinderTraits = packageOption.getJSONArray("binderTraits"); - if (jsonBinderTraits != null) { - List traits = jsonBinderTraits.toJavaList(TraitBinderDTO.class); - // TODO - } - break; - default: - break; + // traits Binder + JSONArray jsonBinderTraits = packageOption.getJSONArray("binderTraits"); + if (jsonBinderTraits != null) { + List traits = jsonBinderTraits.toJavaList(TraitBinderDTO.class); + // TODO + } } } @@ -448,7 +442,7 @@ public class AppPackageServiceImpl implements AppPackageService { for (DeployAppSchema.SpecComponent component : schema.getSpec().getComponents()) { String revisionName = component.getRevisionName(); DeployAppRevisionName revision = DeployAppRevisionName.valueOf(component.getRevisionName()); - if (!revision.getComponentType().equals(ComponentTypeEnum.RESOURCE_ADDON) + if (!ComponentTypeEnum.RESOURCE_ADDON.toString().equals(revision.getComponentType()) && !hitRevisionSet.contains(revisionName)) { removedRevisionName.add(revisionName); } @@ -468,7 +462,7 @@ public class AppPackageServiceImpl implements AppPackageService { */ private void enrichSpecComponent( ApplicationConfigurationGenerateReq req, DeployAppSchema schema, Set hitRevisionSet, - ComponentTypeEnum componentType, String componentName, DeployAppSchema.SpecComponent currentComponent) { + String componentType, String componentName, DeployAppSchema.SpecComponent currentComponent) { String revisionName = DeployAppRevisionName.builder() .componentType(componentType) .componentName(componentName) @@ -493,7 +487,7 @@ public class AppPackageServiceImpl implements AppPackageService { * @param name 标识 * @return dataOutputName */ - private static String generateDataOutputName(ComponentTypeEnum componentType, String componentName, String name) { + private static String generateDataOutputName(String componentType, String componentName, String name) { return String.format("%s.%s.dataOutputs.%s", componentType, componentName, name); } diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/apppackage/impl/AppPackageTaskServiceImpl.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/apppackage/impl/AppPackageTaskServiceImpl.java index f61e47b3..77e8c2d7 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/apppackage/impl/AppPackageTaskServiceImpl.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/apppackage/impl/AppPackageTaskServiceImpl.java @@ -145,7 +145,7 @@ public class AppPackageTaskServiceImpl implements AppPackageTaskService { */ @Override public String getComponentNextVersion( - String appId, ComponentTypeEnum componentType, String componentName, String fullVersion) { + String appId, String componentType, String componentName, String fullVersion) { if (!StringUtils.equals(fullVersion, DefaultConstant.AUTO_VERSION)) { return fullVersion; } @@ -154,13 +154,13 @@ public class AppPackageTaskServiceImpl implements AppPackageTaskService { ComponentPackageNextVersionRes packageNextVersion = componentPackageService.nextVersion( ComponentPackageNextVersionReq.builder() .appId(appId) - .componentType(componentType.toString()) + .componentType(componentType) .componentName(componentName) .build()); ComponentPackageTaskNextVersionRes taskNextVersion = componentPackageTaskService.nextVersion( ComponentPackageTaskNextVersionReq.builder() .appId(appId) - .componentType(componentType.toString()) + .componentType(componentType) .componentName(componentName) .build()); fullVersion = packageNextVersion.getNextVersion(); diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/componentpackage/KanikoInformerFactory.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/componentpackage/KanikoInformerFactory.java index b2404017..58334760 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/componentpackage/KanikoInformerFactory.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/componentpackage/KanikoInformerFactory.java @@ -72,8 +72,8 @@ public class KanikoInformerFactory implements DisposableBean { apiClientMap.put(DEFAULT_K8S_CLIENT, client); informerFactoryMap.put(DEFAULT_K8S_INFORMER_FACTORY, informerFactory); apiMap.put(DEFAULT_K8S_API, api); - startListenPod(); - log.info("action=K8sClientProviderImpl|| K8sClientProvider init success!"); + // startListenPod(); + log.info("action=KanikoInformerFactory|| K8sClientProvider init success!"); } } diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/componentpackage/impl/ComponentPackageBuilderServiceImpl.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/componentpackage/impl/ComponentPackageBuilderServiceImpl.java index e95fbc06..65579687 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/componentpackage/impl/ComponentPackageBuilderServiceImpl.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/componentpackage/impl/ComponentPackageBuilderServiceImpl.java @@ -25,10 +25,10 @@ import com.alibaba.tesla.appmanager.server.service.componentpackage.ComponentPac import com.alibaba.tesla.appmanager.server.service.componentpackage.handler.BuildComponentHandler; import com.alibaba.tesla.appmanager.server.service.componentpackage.instance.ComponentPackageBase; import com.alibaba.tesla.appmanager.server.storage.Storage; -import com.google.common.base.Enums; import com.google.common.collect.ImmutableMap; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; @@ -69,10 +69,9 @@ public class ComponentPackageBuilderServiceImpl implements ComponentPackageBuild */ @Override public LaunchBuildComponentHandlerRes build(BuildComponentHandlerReq request) throws IOException { - ComponentTypeEnum componentType = Enums - .getIfPresent(ComponentTypeEnum.class, request.getComponentType()).orNull(); - if (componentType == null) { - throw new AppException(AppErrorCode.INVALID_USER_ARGS, "null componentType"); + String componentType = request.getComponentType(); + if (StringUtils.isEmpty(componentType)) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "empty componentType"); } String componentName = request.getComponentName(); @@ -161,9 +160,8 @@ public class ComponentPackageBuilderServiceImpl implements ComponentPackageBuild */ @Override public void kanikoBuild(ComponentPackageTaskDO taskDO) throws Exception { - ComponentTypeEnum componentType = Enums - .getIfPresent(ComponentTypeEnum.class, taskDO.getComponentType()).orNull(); - if (componentType == null) { + String componentType = taskDO.getComponentType(); + if (StringUtils.isEmpty(componentType)) { throw new AppException(AppErrorCode.INVALID_USER_ARGS, "null componentType"); } String componentName = taskDO.getComponentName(); @@ -177,24 +175,19 @@ public class ComponentPackageBuilderServiceImpl implements ComponentPackageBuild .options(JSONObject.parseObject(taskDO.getPackageOptions())) .build(); - switch (componentType) { - case K8S_MICROSERVICE: - case K8S_JOB: { - ComponentPackageBase instance = componentPackageBuilderExecutorManager.getInstance(componentType.name()); - instance.exportComponentPackage(taskDO); - break; + if (ComponentTypeEnum.isMicroserviceOrJob(componentType)) { + ComponentPackageBase instance = componentPackageBuilderExecutorManager.getInstance(componentType); + instance.exportComponentPackage(taskDO); + } else { + BuildComponentHandler handler = groovyHandlerFactory.getByComponentType(BuildComponentHandler.class, + componentHandlerReq.getAppId(), componentType, componentName, ComponentActionEnum.BUILD); + LaunchBuildComponentHandlerRes res; + if (handler == null) { + res = compatibleBuild(componentHandlerReq); + } else { + res = handler.launch(componentHandlerReq); } - default: - BuildComponentHandler handler = groovyHandlerFactory.getByComponentType(BuildComponentHandler.class, - componentHandlerReq.getAppId(), componentType, componentName, ComponentActionEnum.BUILD); - LaunchBuildComponentHandlerRes res; - if (handler == null) { - res = compatibleBuild(componentHandlerReq); - } else { - res = handler.launch(componentHandlerReq); - } - storeAndPublish(taskDO, res); - break; + storeAndPublish(taskDO, res); } } diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/componentpackage/instance/dto/WaitKanikoBuildPod.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/componentpackage/instance/dto/WaitKanikoBuildPod.java new file mode 100644 index 00000000..0433b837 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/componentpackage/instance/dto/WaitKanikoBuildPod.java @@ -0,0 +1,103 @@ +package com.alibaba.tesla.appmanager.server.service.componentpackage.instance.dto; + +import java.util.HashSet; +import java.util.Set; + +import com.alibaba.tesla.appmanager.server.service.componentpackage.instance.constant.PodStatusPhaseEnum; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.util.CollectionUtils; + +/** + * @ClassName: WaitKanikoBuildPod + * @Author: dyj + * @DATE: 2022-08-31 + * @Description: + **/ +@Slf4j +@Data +public class WaitKanikoBuildPod { + + private Set runningPods; + private Set successPods; + private Set failedPods; + private StringBuffer logBuffer; + private Integer accessError; + + public WaitKanikoBuildPod() { + runningPods = new HashSet<>(); + successPods = new HashSet<>(); + failedPods = new HashSet<>(); + logBuffer = new StringBuffer(); + accessError = 0; + } + + public void changeStatus(String pod, PodStatusPhaseEnum status, String logContent) { + log.info("action=changeKanikoPodStatus || pod:{} change to status:{}", pod, status); + switch (status) { + case Succeeded: { + runningPods.remove(pod); + successPods.add(pod); + logBuffer.append(logContent); + break; + } + case Failed: { + runningPods.remove(pod); + failedPods.add(pod); + logBuffer.append(logContent); + break; + } + default: break; + } + } + + public Set addRunning(String pod) { + runningPods.add(pod); + return runningPods; + } + + public void addAccessError() { + accessError+=1; + } + + public String getLog() { + return logBuffer.toString(); + } + + public void appendLog(String message) { + logBuffer.append(message); + } + + public boolean haveSucceed() { + if (CollectionUtils.isEmpty(runningPods) && CollectionUtils.isEmpty(failedPods)) { + return true; + } else { + return false; + } + } + + public boolean haveFailed() { + if (!CollectionUtils.isEmpty(failedPods)) { + return true; + } else { + return false; + } + } + + public Set getAllPods() { + Set res = new HashSet<>(); + res.addAll(runningPods); + res.addAll(failedPods); + res.addAll(successPods); + return res; + } + + @Override + public String toString() { + return String.format("runningPods:%s, successPods:%s, failedPods:%s", runningPods, successPods, failedPods); + } +} diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/componentpackage/instance/impl/K8sJobMicroserviceComponentPackage.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/componentpackage/instance/impl/K8sJobMicroserviceComponentPackage.java index 3e429daf..8d313125 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/componentpackage/instance/impl/K8sJobMicroserviceComponentPackage.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/componentpackage/instance/impl/K8sJobMicroserviceComponentPackage.java @@ -1,5 +1,21 @@ package com.alibaba.tesla.appmanager.server.service.componentpackage.instance.impl; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import javax.annotation.PostConstruct; + import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.alibaba.tesla.appmanager.autoconfig.ImageBuilderProperties; @@ -9,9 +25,17 @@ import com.alibaba.tesla.appmanager.common.enums.AppPackageTaskStatusEnum; import com.alibaba.tesla.appmanager.common.enums.ComponentTypeEnum; import com.alibaba.tesla.appmanager.common.exception.AppErrorCode; import com.alibaba.tesla.appmanager.common.exception.AppException; -import com.alibaba.tesla.appmanager.common.util.*; +import com.alibaba.tesla.appmanager.common.util.CommandUtil; +import com.alibaba.tesla.appmanager.common.util.ExceptionUtil; +import com.alibaba.tesla.appmanager.common.util.FileUtil; +import com.alibaba.tesla.appmanager.common.util.JsonUtil; +import com.alibaba.tesla.appmanager.common.util.KanikoBuildCheckUtil; +import com.alibaba.tesla.appmanager.common.util.PackageUtil; +import com.alibaba.tesla.appmanager.common.util.SchemaUtil; +import com.alibaba.tesla.appmanager.common.util.StringUtil; import com.alibaba.tesla.appmanager.domain.core.StorageFile; -import com.alibaba.tesla.appmanager.server.event.componentpackage.*; +import com.alibaba.tesla.appmanager.server.event.componentpackage.FailedComponentPackageTaskEvent; +import com.alibaba.tesla.appmanager.server.event.componentpackage.SucceedComponentPackageTaskEvent; import com.alibaba.tesla.appmanager.server.event.loader.ComponentPackageLoadEvent; import com.alibaba.tesla.appmanager.server.repository.ComponentPackageRepository; import com.alibaba.tesla.appmanager.server.repository.ComponentPackageTaskRepository; @@ -20,8 +44,12 @@ import com.alibaba.tesla.appmanager.server.repository.domain.ComponentPackageDO; import com.alibaba.tesla.appmanager.server.repository.domain.ComponentPackageTaskDO; import com.alibaba.tesla.appmanager.server.service.componentpackage.KanikoInformerFactory; import com.alibaba.tesla.appmanager.server.service.componentpackage.instance.ComponentPackageBase; +import com.alibaba.tesla.appmanager.server.service.componentpackage.instance.constant.PodStatusPhaseEnum; +import com.alibaba.tesla.appmanager.server.service.componentpackage.instance.dto.WaitKanikoBuildPod; +import com.alibaba.tesla.appmanager.server.service.componentpackage.instance.util.BuildUtil; import com.alibaba.tesla.appmanager.server.service.componentpackage.instance.util.RetryUtil; import com.alibaba.tesla.appmanager.server.storage.Storage; + import com.hubspot.jinjava.Jinjava; import io.kubernetes.client.openapi.ApiException; import io.kubernetes.client.openapi.apis.CoreV1Api; @@ -33,24 +61,15 @@ import net.lingala.zip4j.model.ZipParameters; import org.apache.commons.io.IOUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; -import org.springframework.context.ApplicationListener; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.retry.annotation.EnableRetry; -import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; -import javax.annotation.PostConstruct; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.util.*; - /** * @ClassName: K8sJobMicroserviceComponentPackage * @Author: dyj @@ -61,18 +80,16 @@ import java.util.*; @Service("K8sJobMicroserviceComponentPackage") @Slf4j @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") -public class K8sJobMicroserviceComponentPackage implements ComponentPackageBase, ApplicationListener { - private static final ComponentTypeEnum COMPONENT_TYPE = ComponentTypeEnum.K8S_JOB; +public class K8sJobMicroserviceComponentPackage implements ComponentPackageBase { + private static final String COMPONENT_TYPE = ComponentTypeEnum.K8S_JOB.toString(); private static final String HTTP_PREFIX = "http://"; private static final String HTTPS_PREFIX = "https://"; private static final String VOLUME_PATH = "/app/kaniko/"; private static final String KANIKO_TPL_PATH = "kaniko/kaniko.yaml.tpl"; private static final String TEMPLATE_JOB_FILENAME = "jinja/default_job.tpl"; - private static final HashMap> taskPodMap = new HashMap<>(); - private static final HashMap> succeedPodMap = new HashMap<>(); - private static final HashMap taskTargetDirMap = new HashMap<>(); - private static final HashMap> taskRemoteObjectMap = new HashMap<>(); - private static final String flag = new String(); + private static final Map waitTaskMap = new ConcurrentHashMap<>(); + private static final Map taskTargetDirMap = new ConcurrentHashMap<>(); + private static final Map> taskRemoteObjectMap = new ConcurrentHashMap<>(); private CoreV1Api api; @Autowired @@ -99,7 +116,7 @@ public class K8sJobMicroserviceComponentPackage implements ComponentPackageBase, public void init() { this.api = kanikoInformerFactory.getDefaultApi(); publisher.publishEvent(new ComponentPackageLoadEvent( - this, COMPONENT_TYPE.name(), this.getClass().getSimpleName())); + this, COMPONENT_TYPE, this.getClass().getSimpleName())); } /** @@ -117,23 +134,16 @@ public class K8sJobMicroserviceComponentPackage implements ComponentPackageBase, //1. generate pod name JSONArray containers = loadContainer(packageOptions); - Set podNameSet = new HashSet<>(); for (int index = 0; index < containers.size(); index++) { JSONObject container = containers.getJSONObject(index); KanikoBuildCheckUtil.buildCheck(container.getJSONObject("build")); container.put("image", generateImageName(taskDO, container, Long.toString(tag))); - Object nameOb = JsonUtil.recursiveGetParameter(container, Collections.singletonList("name")); - String containerName = nameOb != null ? nameOb.toString() : "default"; - String podName = genPodName(taskDO.getAppId(), taskDO.getComponentName(), containerName, taskDO.getId(), tag); - podNameSet.add(podName); } //2. generate meta.yaml generateMetaYaml(taskDO, packageOptions, targetFileDir); + taskTargetDirMap.put(taskDO.getId(), targetFileDir); - //3. insert informer - waitBuildPodAndPackage(podNameSet, taskDO, targetFileDir); - - //4. build pod + //3. render pod yaml String podTpl = loadClassPathFile(KANIKO_TPL_PATH); List waitBuildPodList = new LinkedList<>(); Set remoteObjectSet = new HashSet<>(); @@ -142,28 +152,150 @@ public class K8sJobMicroserviceComponentPackage implements ComponentPackageBase, try { String existImage = JsonUtil.recursiveGetString(container, Arrays.asList("build", "useExistImage")); if (!container.getJSONObject("build").getBooleanValue("imagePush") && !StringUtils.isEmpty(existImage)) { - String podName = genPodName(taskDO.getAppId(), taskDO.getComponentName(), existImage, taskDO.getId(), tag); - publisher.publishEvent(new SucceedKanikoPodEvent(this, podName)); + log.info("action=renderBuildPod|| container {} have been exist image:{}", container.getString("name"), existImage); } else { - V1Pod containerBuildPod = genKanikoPod(api, container, podTpl, taskDO, relativePath, tag, remoteObjectSet); + V1Pod containerBuildPod = renderBuildPod(api, container, podTpl, taskDO, relativePath, tag, remoteObjectSet); waitBuildPodList.add(containerBuildPod); } } catch (Exception e) { - log.error("action=genKanikoPod|| can not build {} container image,Message:{} Exception:{}", container.getString("name"), e.getMessage(), e.getCause()); - String podName = genPodName(taskDO.getAppId(), taskDO.getComponentName(), container.getString("name"), - taskDO.getId(), tag); - publisher.publishEvent(new DeleteKanikoPodEvent(this, podName)); - updateDataFailRecord(taskDO.getId(), e.getMessage()); + log.error("action=renderBuildPod|| can not build {} container image,Message:{} Exception:{}", container.getString("name"), e.getMessage(), e.getCause()); + String logContent = String.format("\n====container:%s====\ncan not render container package, Exception:%s", + container.getString("name"), ExceptionUtil.getStackTrace(e)); + taskRemoteObjectMap.put(taskDO.getId(), remoteObjectSet); + setRenderFailed(taskDO.getId(), logContent); + return; } } taskRemoteObjectMap.put(taskDO.getId(), remoteObjectSet); + + //4. start apply pod yaml + log.info("action=start apply kaniko pod|| podList:{}", remoteObjectSet); + WaitKanikoBuildPod waitPod = new WaitKanikoBuildPod(); for (V1Pod v1Pod : waitBuildPodList) { + waitPod.addRunning( v1Pod.getMetadata().getName()); try { api.createNamespacedPod(systemProperties.getK8sNamespace(), v1Pod, null, null, null); } catch (Exception e) { - log.error("action=createPod|| can not create pod {} container image,Message:{} Exception:{}", v1Pod.toString(), e.getMessage(), e.getCause()); - publisher.publishEvent(new DeleteKanikoPodEvent(this, v1Pod.getMetadata().getName())); - updateDataFailRecord(taskDO.getId(), e.getMessage()); + log.error("action=createPod|| can not apply pod yaml:{}, Message:{} Exception:{}", v1Pod.toString(), e.getMessage(), e.getCause()); + String logContent = BuildUtil.genLogContent(v1Pod.getMetadata().getName(), ExceptionUtil.getStackTrace(e)); + waitPod.changeStatus(v1Pod.getMetadata().getName(), PodStatusPhaseEnum.Failed, logContent); + } + } + + //5. insert check status task, after 20s check status! + Thread.sleep(60000); + waitTaskMap.put(taskDO.getId(), waitPod); + } + + private void setRenderFailed(Long taskId, String message) { + ComponentPackageTaskDO taskDO = componentPackageTaskRepository.getByCondition( + ComponentPackageTaskQueryCondition.builder().id(taskId).build()); + if (taskDO.getTaskStatus().equalsIgnoreCase(AppPackageTaskStatusEnum.FAILURE.name())) { + return; + } + taskDO.setTaskLog(message); + componentPackageTaskRepository.updateByCondition(taskDO, ComponentPackageTaskQueryCondition.builder().id(taskDO.getId()).build()); + publisher.publishEvent(new FailedComponentPackageTaskEvent(this, taskId)); + cleanRecord(taskId); + } + + private void setTaskFailed(Long taskId) { + WaitKanikoBuildPod waitPod = waitTaskMap.remove(taskId); + ComponentPackageTaskDO taskDO = componentPackageTaskRepository.getByCondition( + ComponentPackageTaskQueryCondition.builder().id(taskId).build()); + if (taskDO.getTaskStatus().equalsIgnoreCase(AppPackageTaskStatusEnum.FAILURE.name())) { + return; + } + taskDO.setTaskLog(waitPod.getLog()); + componentPackageTaskRepository.updateByCondition(taskDO, ComponentPackageTaskQueryCondition.builder().id(taskDO.getId()).build()); + publisher.publishEvent(new FailedComponentPackageTaskEvent(this, taskId)); + cleanPods(waitPod); + cleanRecord(taskId); + } + + private void cleanPods(WaitKanikoBuildPod waitPod) { + for (String pod : waitPod.getAllPods()) { + try { + api.deleteNamespacedPod(pod, systemProperties.getK8sNamespace(), null, + null, null, null, null, null); + } catch (ApiException e) { + log.warn("action=cleanPods||clean pod:{} error:{}", pod, e.getResponseBody()); + } + } + + } + + private void cleanRecord(Long taskId) { + String targetFileDir = taskTargetDirMap.remove(taskId); + deleteDir(targetFileDir); + Set remoteObjectSet = taskRemoteObjectMap.remove(taskId); + deleteRemoteObject(remoteObjectSet); + } + + private void setTaskSucceed(Long taskId) { + try { + packageComponentZip(taskId); + } catch (IOException e) { + log.error("action=setTaskSucceed || Can not pack component package!",e); + String message = String.format("Can not pack component package, Exception:%s", ExceptionUtil.getStackTrace(e)); + WaitKanikoBuildPod waitPod = waitTaskMap.get(taskId); + waitPod.appendLog(message); + setTaskFailed(taskId); + return; + } + WaitKanikoBuildPod waitPod = waitTaskMap.remove(taskId); + ComponentPackageTaskDO taskDO = componentPackageTaskRepository.getByCondition( + ComponentPackageTaskQueryCondition.builder().id(taskId).build()); + taskDO.setTaskLog(waitPod.getLog()); + componentPackageTaskRepository.updateByCondition(taskDO, ComponentPackageTaskQueryCondition.builder().id(taskDO.getId()).build()); + publisher.publishEvent(new SucceedComponentPackageTaskEvent(this, taskId)); + cleanPods(waitPod); + cleanRecord(taskId); + } + + @Scheduled(fixedDelay = 20*1000) + private void checkTaskStatus() { + HashSet taskIds = new HashSet<>(waitTaskMap.keySet()); + if (CollectionUtils.isEmpty(taskIds)) { + return; + } + for (Long taskId : taskIds) { + WaitKanikoBuildPod waitePod = waitTaskMap.get(taskId); + if (waitePod==null) { + continue; + } else { + if (waitePod.haveFailed()) { + setTaskFailed(taskId); + } else if (waitePod.haveSucceed()) { + setTaskSucceed(taskId); + } else { + if (CollectionUtils.isEmpty(waitePod.getRunningPods())) { + continue; + } + HashSet runningPods = new HashSet<>(waitePod.getRunningPods()); + for (String runningPod : runningPods) { + try { + V1Pod v1Pod = api.readNamespacedPodStatus(runningPod, systemProperties.getK8sNamespace(), null); + String podLog = api.readNamespacedPodLog(runningPod, systemProperties.getK8sNamespace(), + null, null, null, null, null, null, null, null, null); + if (PodStatusPhaseEnum.Failed.name().equalsIgnoreCase(v1Pod.getStatus().getPhase())) { + waitePod.changeStatus(runningPod, PodStatusPhaseEnum.Failed, BuildUtil.genLogContent(runningPod, podLog)); + } else if (PodStatusPhaseEnum.Succeeded.name().equalsIgnoreCase(v1Pod.getStatus().getPhase())) { + waitePod.changeStatus(runningPod, PodStatusPhaseEnum.Succeeded, BuildUtil.genLogContent(runningPod, podLog)); + } + } catch (ApiException e) { + log.warn("action=checkTaskStatus|| can not read pod:{} status!", runningPod, e); + waitePod.addAccessError(); + if (waitePod.getAccessError()>=10) { + String message = String.format("\nCan not read pod:%s status! \nException:%s", runningPod, ExceptionUtil.getStackTrace(e)); + waitePod.appendLog(BuildUtil.genLogContent(runningPod, message)); + setTaskFailed(taskId); + } + break; + } + } + + } } } } @@ -209,7 +341,7 @@ public class K8sJobMicroserviceComponentPackage implements ComponentPackageBase, return destination.concat("/").concat(image); } - private V1Pod genKanikoPod(CoreV1Api api, JSONObject container, String podTpl, + private V1Pod renderBuildPod(CoreV1Api api, JSONObject container, String podTpl, ComponentPackageTaskDO taskDO, String relativePath, long tag, Set remoteObjectSet) throws Exception { Object nameOb = JsonUtil.recursiveGetParameter(container, @@ -378,14 +510,9 @@ public class K8sJobMicroserviceComponentPackage implements ComponentPackageBase, FileUtil.writeStringToFile(targetFileDir + "meta.yaml", metaYamlContent, true); } - private void waitBuildPodAndPackage(Set podNameSet, ComponentPackageTaskDO taskDO, String targetFileDir) { - log.info("actionName=waitBuildImage|| Pod: {}", podNameSet); - taskPodMap.put(taskDO.getId(), podNameSet); - taskTargetDirMap.put(taskDO.getId(), targetFileDir); - } - - private void packageComponentZip(Long taskId, String taskLog, String targetFileDir) throws IOException { + private void packageComponentZip(Long taskId) throws IOException { + String targetFileDir = taskTargetDirMap.get(taskId); ComponentPackageTaskDO taskDO = componentPackageTaskRepository.getByCondition( ComponentPackageTaskQueryCondition.builder().id(taskId).build()); String zipFilePath = targetFileDir + "component_package_task.zip"; @@ -433,26 +560,20 @@ public class K8sJobMicroserviceComponentPackage implements ComponentPackageBase, .build(); taskDO.setPackagePath(storageFile.toPath()); taskDO.setPackageMd5(targetFileMd5); - updateDataSuccessRecord(componentPackageDO, taskDO, taskLog); - log.info("component package task has inserted to db||componentPackageTaskId={}||" + + genComponentPackageRecord(componentPackageDO, taskId); + log.info("component package task has inserted to db||AppPackageTaskId={}||" + "componentPackageId={}||appId={}||componentType={}||componentName={}||version={}||md5={}", taskDO.getAppPackageTaskId(), componentPackageDO.getId(), taskDO.getAppId(), taskDO.getComponentType(), taskDO.getComponentName(), taskDO.getPackageVersion(), targetFileMd5); } - /** - * 事务内更新 Database 记录 - * - * @param componentPackageDO Component Package 记录 - * @param taskDO Component Package Task 记录 - * @param taskLog - */ + @Transactional(rollbackFor = Exception.class) - public void updateDataSuccessRecord(ComponentPackageDO componentPackageDO, ComponentPackageTaskDO taskDO, - String taskLog) { + public void genComponentPackageRecord(ComponentPackageDO componentPackageDO, Long taskId) { componentPackageRepository.insert(componentPackageDO); + ComponentPackageTaskDO taskDO = componentPackageTaskRepository.getByCondition( + ComponentPackageTaskQueryCondition.builder().id(taskId).build()); taskDO.setComponentPackageId(componentPackageDO.getId()); - taskDO.setTaskLog(taskLog); componentPackageTaskRepository.updateByCondition(taskDO, ComponentPackageTaskQueryCondition.builder().id(taskDO.getId()).build()); } @@ -475,17 +596,6 @@ public class K8sJobMicroserviceComponentPackage implements ComponentPackageBase, } } - @Transactional(rollbackFor = Exception.class) - public void updateDataFailRecord(Long taskId, String taskLog) { - ComponentPackageTaskDO taskDO = componentPackageTaskRepository.getByCondition( - ComponentPackageTaskQueryCondition.builder().id(taskId).build()); - if (taskDO.getTaskStatus().equalsIgnoreCase(AppPackageTaskStatusEnum.FAILURE.name())) { - return; - } - taskDO.setTaskLog(taskLog); - componentPackageTaskRepository.updateByCondition(taskDO, ComponentPackageTaskQueryCondition.builder().id(taskDO.getId()).build()); - } - private String genPodName(String appId, String componentName, String containerName, Long taskId, long tag) { StringBuilder podName = new StringBuilder(); podName.append("appmanager-build-").append(appId).append("-") @@ -495,117 +605,4 @@ public class K8sJobMicroserviceComponentPackage implements ComponentPackageBase, .append(tag); return podName.toString(); } - - @Async - @Override - public void onApplicationEvent(KanikoPodEvent event) { - String podName = event.getPodName(); - String[] split = podName.split("-"); - Long taskId = Long.valueOf(split[split.length - 2]); - if (taskPodMap.containsKey(taskId)) { - synchronized (flag) { - switch (event.getCurrentStatus()) { - case SUCCEED: { - if (taskPodMap.containsKey(taskId)) { - if (!succeedPodMap.containsKey(taskId)) { - succeedPodMap.put(taskId, new HashSet<>()); - } - succeedPodMap.get(taskId).add(podName); - if (taskPodMap.get(taskId).size() == succeedPodMap.get(taskId).size()) { - StringBuilder taskLog = new StringBuilder(); - for (String runPod : taskPodMap.get(taskId)) { - try { - String podLog = api.readNamespacedPodLog(runPod, systemProperties.getK8sNamespace(), - null, null, null, null, null, null, null, null, null); - taskLog.append(podName).append("-log:\n").append(podLog).append("\n"); - } catch (ApiException e) { - log.warn("action=KanikoSucceedOp||can not read pod log:{}", runPod); - } - try { - api.deleteNamespacedPod(runPod, systemProperties.getK8sNamespace(), null, - null, null, null, null, null); - } catch (ApiException e) { - log.warn("action=KanikoSucceedOp||clean pod error:{}", e.getResponseBody()); - } - } - try { - taskPodMap.remove(taskId); - log.info("action=clean build task informer:{}", taskId); - succeedPodMap.remove(taskId); - String targetFileDir = taskTargetDirMap.remove(taskId); - packageComponentZip(taskId, taskLog.toString(), targetFileDir); - deleteDir(targetFileDir); - Set remoteObjectSet = taskRemoteObjectMap.remove(taskId); - deleteRemoteObject(remoteObjectSet); - publisher.publishEvent(new SucceedComponentPackageTaskEvent(this, taskId)); - } catch (Exception e) { - log.error("action=waitBuildPodAndPackage|| something wrong when operate package zip!message={}||exception={}", e.getMessage(), e.getCause()); - publisher.publishEvent(new FailedComponentPackageTaskEvent(this, taskId)); - } - } - } - break; - } - case FAILED: { - if (taskPodMap.containsKey(taskId)) { - StringBuilder taskLog = new StringBuilder(); - try { - String podLog = api.readNamespacedPodLog(podName, systemProperties.getK8sNamespace(), - null, null, null, null, null, null, null, null, null); - taskLog.append(podName).append("-log:\n").append(podLog).append("\n"); - } catch (ApiException e) { - log.warn("action=KanikoFailedOp||can not read pod log:{}", podName); - } - for (String runPod : taskPodMap.get(taskId)) { - try { - api.deleteNamespacedPod(runPod, systemProperties.getK8sNamespace(), null, - null, null, null, null, null); - } catch (ApiException e) { - log.warn("action=KanikoFailedOp||clean pod error:{}", e.getResponseBody()); - } - } - try { - taskPodMap.remove(taskId); - log.info("action=clean build task informer:{}", taskId); - succeedPodMap.remove(taskId); - updateDataFailRecord(taskId, taskLog.toString()); - String targetFileDir = taskTargetDirMap.remove(taskId); - deleteDir(targetFileDir); - Set remoteObjectSet = taskRemoteObjectMap.remove(taskId); - deleteRemoteObject(remoteObjectSet); - } finally { - publisher.publishEvent(new FailedComponentPackageTaskEvent(this, taskId)); - } - } - break; - } - case DELETE: { - if (taskPodMap.containsKey(taskId)) { - for (String runPod : taskPodMap.get(taskId)) { - try { - api.deleteNamespacedPod(runPod, systemProperties.getK8sNamespace(), null, - null, null, null, null, null); - } catch (ApiException e) { - log.warn("action=KanikoFailedOp||clean pod error:{}", e.getResponseBody()); - } - } - try { - taskPodMap.remove(taskId); - log.info("action=clean build task informer:{}", taskId); - succeedPodMap.remove(taskId); - String targetFileDir = taskTargetDirMap.remove(taskId); - deleteDir(targetFileDir); - Set remoteObjectSet = taskRemoteObjectMap.remove(taskId); - deleteRemoteObject(remoteObjectSet); - } finally { - publisher.publishEvent(new FailedComponentPackageTaskEvent(this, taskId)); - } - } - break; - } - default: - } - } - } - } } diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/componentpackage/instance/impl/K8sMicroserviceComponenPackage.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/componentpackage/instance/impl/K8sMicroserviceComponenPackage.java index 51c0dc00..0a0f05ff 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/componentpackage/instance/impl/K8sMicroserviceComponenPackage.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/componentpackage/instance/impl/K8sMicroserviceComponenPackage.java @@ -1,5 +1,21 @@ package com.alibaba.tesla.appmanager.server.service.componentpackage.instance.impl; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import javax.annotation.PostConstruct; + import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.alibaba.tesla.appmanager.autoconfig.ImageBuilderProperties; @@ -9,9 +25,17 @@ import com.alibaba.tesla.appmanager.common.enums.AppPackageTaskStatusEnum; import com.alibaba.tesla.appmanager.common.enums.ComponentTypeEnum; import com.alibaba.tesla.appmanager.common.exception.AppErrorCode; import com.alibaba.tesla.appmanager.common.exception.AppException; -import com.alibaba.tesla.appmanager.common.util.*; +import com.alibaba.tesla.appmanager.common.util.CommandUtil; +import com.alibaba.tesla.appmanager.common.util.ExceptionUtil; +import com.alibaba.tesla.appmanager.common.util.FileUtil; +import com.alibaba.tesla.appmanager.common.util.JsonUtil; +import com.alibaba.tesla.appmanager.common.util.KanikoBuildCheckUtil; +import com.alibaba.tesla.appmanager.common.util.PackageUtil; +import com.alibaba.tesla.appmanager.common.util.SchemaUtil; +import com.alibaba.tesla.appmanager.common.util.StringUtil; import com.alibaba.tesla.appmanager.domain.core.StorageFile; -import com.alibaba.tesla.appmanager.server.event.componentpackage.*; +import com.alibaba.tesla.appmanager.server.event.componentpackage.FailedComponentPackageTaskEvent; +import com.alibaba.tesla.appmanager.server.event.componentpackage.SucceedComponentPackageTaskEvent; import com.alibaba.tesla.appmanager.server.event.loader.ComponentPackageLoadEvent; import com.alibaba.tesla.appmanager.server.repository.ComponentPackageRepository; import com.alibaba.tesla.appmanager.server.repository.ComponentPackageTaskRepository; @@ -20,8 +44,12 @@ import com.alibaba.tesla.appmanager.server.repository.domain.ComponentPackageDO; import com.alibaba.tesla.appmanager.server.repository.domain.ComponentPackageTaskDO; import com.alibaba.tesla.appmanager.server.service.componentpackage.KanikoInformerFactory; import com.alibaba.tesla.appmanager.server.service.componentpackage.instance.ComponentPackageBase; +import com.alibaba.tesla.appmanager.server.service.componentpackage.instance.constant.PodStatusPhaseEnum; +import com.alibaba.tesla.appmanager.server.service.componentpackage.instance.dto.WaitKanikoBuildPod; +import com.alibaba.tesla.appmanager.server.service.componentpackage.instance.util.BuildUtil; import com.alibaba.tesla.appmanager.server.service.componentpackage.instance.util.RetryUtil; import com.alibaba.tesla.appmanager.server.storage.Storage; + import com.hubspot.jinjava.Jinjava; import io.kubernetes.client.openapi.ApiException; import io.kubernetes.client.openapi.apis.CoreV1Api; @@ -33,24 +61,15 @@ import net.lingala.zip4j.model.ZipParameters; import org.apache.commons.io.IOUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; -import org.springframework.context.ApplicationListener; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.retry.annotation.EnableRetry; -import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; -import javax.annotation.PostConstruct; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.util.*; - /** * @ClassName: K8sMicroserviceComponenPackage * @Author: dyj @@ -61,19 +80,17 @@ import java.util.*; @Service("K8sMicroserviceComponenPackage") @Slf4j @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") -public class K8sMicroserviceComponenPackage implements ComponentPackageBase, ApplicationListener { - private static final ComponentTypeEnum COMPONENT_TYPE = ComponentTypeEnum.K8S_MICROSERVICE; +public class K8sMicroserviceComponenPackage implements ComponentPackageBase { + private static final String COMPONENT_TYPE = ComponentTypeEnum.K8S_MICROSERVICE.toString(); private static final String HTTP_PREFIX = "http://"; private static final String HTTPS_PREFIX = "https://"; private static final String VOLUME_PATH = "/app/kaniko/"; private static final String KANIKO_TPL_PATH = "kaniko/kaniko.yaml.tpl"; private static final String TEMPLATE_MICROSERVICE_FILENAME = "jinja/default_microservice_%s.tpl"; private static final String DEFAULT_MICROSERVICE_TYPE = "Deployment"; - private static final HashMap> taskPodMap = new HashMap<>(); - private static final HashMap> succeedPodMap = new HashMap<>(); - private static final HashMap taskTargetDirMap = new HashMap<>(); - private static final HashMap> taskRemoteObjectMap = new HashMap<>(); - private static final String flag = new String(); + private static final Map waitTaskMap = new ConcurrentHashMap<>(); + private static final Map taskTargetDirMap = new ConcurrentHashMap<>(); + private static final Map> taskRemoteObjectMap = new ConcurrentHashMap<>(); private CoreV1Api api; @Autowired @@ -100,7 +117,7 @@ public class K8sMicroserviceComponenPackage implements ComponentPackageBase, App public void init() { this.api = kanikoInformerFactory.getDefaultApi(); publisher.publishEvent(new ComponentPackageLoadEvent( - this, COMPONENT_TYPE.name(), this.getClass().getSimpleName())); + this, COMPONENT_TYPE, this.getClass().getSimpleName())); } /** @@ -118,52 +135,167 @@ public class K8sMicroserviceComponenPackage implements ComponentPackageBase, App //1. generate pod name JSONArray containers = loadContainer(packageOptions); - Set podNameSet = new HashSet<>(); for (int index = 0; index < containers.size(); index++) { JSONObject container = containers.getJSONObject(index); KanikoBuildCheckUtil.buildCheck(container.getJSONObject("build")); container.put("image", generateImageName(taskDO, container, Long.toString(tag))); - Object nameOb = JsonUtil.recursiveGetParameter(container, Collections.singletonList("name")); - String containerName = nameOb != null ? nameOb.toString() : "default"; - String podName = genPodName(taskDO.getAppId(), taskDO.getComponentName(), containerName, taskDO.getId(), tag); - podNameSet.add(podName); } //2. generate meta.yaml generateMetaYaml(taskDO, packageOptions, targetFileDir); + taskTargetDirMap.put(taskDO.getId(), targetFileDir); - //3. insert informer - waitBuildPodAndPackage(podNameSet, taskDO, targetFileDir); - - //4. build pod + //3. render pod yaml String podTpl = loadClassPathFile(KANIKO_TPL_PATH); - List waitBuildPodList = new LinkedList<>(); + List waitApplyPodList = new LinkedList<>(); Set remoteObjectSet = new HashSet<>(); for (int index = 0; index < containers.size(); index++) { JSONObject container = containers.getJSONObject(index); try { String existImage = JsonUtil.recursiveGetString(container, Arrays.asList("build", "useExistImage")); if (!container.getJSONObject("build").getBooleanValue("imagePush") && !StringUtils.isEmpty(existImage)) { - String podName = genPodName(taskDO.getAppId(), taskDO.getComponentName(), existImage, taskDO.getId(), tag); - publisher.publishEvent(new SucceedKanikoPodEvent(this, podName)); + log.info("action=renderBuildPod|| container {} have been exist image:{}", container.getString("name"), existImage); } else { - V1Pod containerBuildPod = genKanikoPod(api, container, podTpl, taskDO, relativePath, tag, remoteObjectSet); - waitBuildPodList.add(containerBuildPod); + V1Pod containerBuildPod = renderBuildPod(api, container, podTpl, taskDO, relativePath, tag, remoteObjectSet); + waitApplyPodList.add(containerBuildPod); } } catch (Exception e) { - log.error("action=genKanikoPod|| can not build {} container image,Message:{} Exception:{}", container.getString("name"), e.getMessage(), e.getCause()); - String podName = genPodName(taskDO.getAppId(), taskDO.getComponentName(), container.getString("name"), - taskDO.getId(), tag); - publisher.publishEvent(new DeleteKanikoPodEvent(this, podName)); - updateDataFailRecord(taskDO.getId(), e.getMessage()); + log.error("action=renderBuildPod|| can not build {} container image,Message:{} Exception:{}", container.getString("name"), e.getMessage(), e.getCause()); + String logContent = String.format("\n====container:%s====\ncan not render container package, Exception:%s", + container.getString("name"), ExceptionUtil.getStackTrace(e)); + taskRemoteObjectMap.put(taskDO.getId(), remoteObjectSet); + setRenderFailed(taskDO.getId(), logContent); + return; } - taskRemoteObjectMap.put(taskDO.getId(), remoteObjectSet); - for (V1Pod v1Pod : waitBuildPodList) { - try { - api.createNamespacedPod(systemProperties.getK8sNamespace(), v1Pod, null, null, null); - } catch (Exception e) { - log.error("action=createPod|| can not create pod {} container image,Message:{} Exception:{}", v1Pod.toString(), e.getMessage(), e.getCause()); - publisher.publishEvent(new DeleteKanikoPodEvent(this, v1Pod.getMetadata().getName())); - updateDataFailRecord(taskDO.getId(), e.getMessage()); + } + taskRemoteObjectMap.put(taskDO.getId(), remoteObjectSet); + + //4. start apply pod yaml + log.info("action=start apply kaniko pod|| podList:{}", remoteObjectSet); + WaitKanikoBuildPod waitPod = new WaitKanikoBuildPod(); + for (V1Pod v1Pod : waitApplyPodList) { + waitPod.addRunning( v1Pod.getMetadata().getName()); + try { + api.createNamespacedPod(systemProperties.getK8sNamespace(), v1Pod, null, null, null); + } catch (Exception e) { + log.error("action=createPod|| can not apply pod yaml:{}, Message:{} Exception:{}", v1Pod.toString(), e.getMessage(), e.getCause()); + String logContent = BuildUtil.genLogContent(v1Pod.getMetadata().getName(), ExceptionUtil.getStackTrace(e)); + waitPod.changeStatus(v1Pod.getMetadata().getName(), PodStatusPhaseEnum.Failed, logContent); + } + } + + //5. insert check status task, after 60s check status! + Thread.sleep(60000); + waitTaskMap.put(taskDO.getId(), waitPod); + } + + private void setRenderFailed(Long taskId, String message) { + ComponentPackageTaskDO taskDO = componentPackageTaskRepository.getByCondition( + ComponentPackageTaskQueryCondition.builder().id(taskId).build()); + if (taskDO.getTaskStatus().equalsIgnoreCase(AppPackageTaskStatusEnum.FAILURE.name())) { + return; + } + taskDO.setTaskLog(message); + componentPackageTaskRepository.updateByCondition(taskDO, ComponentPackageTaskQueryCondition.builder().id(taskDO.getId()).build()); + publisher.publishEvent(new FailedComponentPackageTaskEvent(this, taskId)); + cleanRecord(taskId); + } + + private void setTaskFailed(Long taskId) { + WaitKanikoBuildPod waitPod = waitTaskMap.remove(taskId); + ComponentPackageTaskDO taskDO = componentPackageTaskRepository.getByCondition( + ComponentPackageTaskQueryCondition.builder().id(taskId).build()); + if (taskDO.getTaskStatus().equalsIgnoreCase(AppPackageTaskStatusEnum.FAILURE.name())) { + return; + } + taskDO.setTaskLog(waitPod.getLog()); + componentPackageTaskRepository.updateByCondition(taskDO, ComponentPackageTaskQueryCondition.builder().id(taskDO.getId()).build()); + publisher.publishEvent(new FailedComponentPackageTaskEvent(this, taskId)); + cleanPods(waitPod); + cleanRecord(taskId); + } + + private void cleanPods(WaitKanikoBuildPod waitPod) { + for (String pod : waitPod.getAllPods()) { + try { + api.deleteNamespacedPod(pod, systemProperties.getK8sNamespace(), null, + null, null, null, null, null); + } catch (ApiException e) { + log.warn("action=cleanPods||clean pod:{} error:{}", pod, e.getResponseBody()); + } + } + + } + + private void cleanRecord(Long taskId) { + String targetFileDir = taskTargetDirMap.remove(taskId); + deleteDir(targetFileDir); + Set remoteObjectSet = taskRemoteObjectMap.remove(taskId); + deleteRemoteObject(remoteObjectSet); + } + + private void setTaskSucceed(Long taskId) { + try { + packageComponentZip(taskId); + } catch (IOException e) { + log.error("action=setTaskSucceed || Can not pack component package!",e); + String message = String.format("Can not pack component package, Exception:%s", ExceptionUtil.getStackTrace(e)); + WaitKanikoBuildPod waitPod = waitTaskMap.get(taskId); + waitPod.appendLog(message); + setTaskFailed(taskId); + return; + } + WaitKanikoBuildPod waitPod = waitTaskMap.remove(taskId); + ComponentPackageTaskDO taskDO = componentPackageTaskRepository.getByCondition( + ComponentPackageTaskQueryCondition.builder().id(taskId).build()); + taskDO.setTaskLog(waitPod.getLog()); + componentPackageTaskRepository.updateByCondition(taskDO, ComponentPackageTaskQueryCondition.builder().id(taskDO.getId()).build()); + publisher.publishEvent(new SucceedComponentPackageTaskEvent(this, taskId)); + cleanPods(waitPod); + cleanRecord(taskId); + } + + @Scheduled(fixedDelay = 20*1000) + private void checkTaskStatus() { + HashSet taskIds = new HashSet<>(waitTaskMap.keySet()); + if (CollectionUtils.isEmpty(taskIds)) { + return; + } + for (Long taskId : taskIds) { + WaitKanikoBuildPod waitePod = waitTaskMap.get(taskId); + if (waitePod==null) { + continue; + } else { + if (waitePod.haveFailed()) { + setTaskFailed(taskId); + } else if (waitePod.haveSucceed()) { + setTaskSucceed(taskId); + } else { + if (CollectionUtils.isEmpty(waitePod.getRunningPods())) { + continue; + } + HashSet runningPods = new HashSet<>(waitePod.getRunningPods()); + for (String runningPod : runningPods) { + try { + V1Pod v1Pod = api.readNamespacedPodStatus(runningPod, systemProperties.getK8sNamespace(), null); + String podLog = api.readNamespacedPodLog(runningPod, systemProperties.getK8sNamespace(), + null, null, null, null, null, null, null, null, null); + if (PodStatusPhaseEnum.Failed.name().equalsIgnoreCase(v1Pod.getStatus().getPhase())) { + waitePod.changeStatus(runningPod, PodStatusPhaseEnum.Failed, BuildUtil.genLogContent(runningPod, podLog)); + } else if (PodStatusPhaseEnum.Succeeded.name().equalsIgnoreCase(v1Pod.getStatus().getPhase())) { + waitePod.changeStatus(runningPod, PodStatusPhaseEnum.Succeeded, BuildUtil.genLogContent(runningPod, podLog)); + } + } catch (ApiException e) { + log.warn("action=checkTaskStatus|| can not read pod:{} status!", runningPod, e); + waitePod.addAccessError(); + if (waitePod.getAccessError()>=10) { + String message = String.format("\nCan not read pod:%s status! \nException:%s", runningPod, ExceptionUtil.getStackTrace(e)); + waitePod.appendLog(BuildUtil.genLogContent(runningPod, message)); + setTaskFailed(taskId); + } + break; + } + } + } } } @@ -215,7 +347,7 @@ public class K8sMicroserviceComponenPackage implements ComponentPackageBase, App return destination.concat("/").concat(image); } - private V1Pod genKanikoPod(CoreV1Api api, JSONObject container, String podTpl, + private V1Pod renderBuildPod(CoreV1Api api, JSONObject container, String podTpl, ComponentPackageTaskDO taskDO, String relativePath, long tag, Set remoteObjectSet) throws Exception { Object nameOb = JsonUtil.recursiveGetParameter(container, @@ -387,14 +519,9 @@ public class K8sMicroserviceComponenPackage implements ComponentPackageBase, App FileUtil.writeStringToFile(targetFileDir + "meta.yaml", metaYamlContent, true); } - private void waitBuildPodAndPackage(Set podNameSet, ComponentPackageTaskDO taskDO, String targetFileDir) { - log.info("actionName=waitBuildImage|| Pod: {}", podNameSet); - taskPodMap.put(taskDO.getId(), podNameSet); - taskTargetDirMap.put(taskDO.getId(), targetFileDir); - } - - private void packageComponentZip(Long taskId, String taskLog, String targetFileDir) throws IOException { + private void packageComponentZip(Long taskId) throws IOException { + String targetFileDir = taskTargetDirMap.get(taskId); ComponentPackageTaskDO taskDO = componentPackageTaskRepository.getByCondition( ComponentPackageTaskQueryCondition.builder().id(taskId).build()); String zipFilePath = targetFileDir + "component_package_task.zip"; @@ -442,26 +569,19 @@ public class K8sMicroserviceComponenPackage implements ComponentPackageBase, App .build(); taskDO.setPackagePath(storageFile.toPath()); taskDO.setPackageMd5(targetFileMd5); - updateDataSuccessRecord(componentPackageDO, taskDO, taskLog); - log.info("component package task has inserted to db||componentPackageTaskId={}||" + + genComponentPackageRecord(componentPackageDO, taskId); + log.info("component package task has inserted to db||AppPackageTaskId={}||" + "componentPackageId={}||appId={}||componentType={}||componentName={}||version={}||md5={}", taskDO.getAppPackageTaskId(), componentPackageDO.getId(), taskDO.getAppId(), taskDO.getComponentType(), taskDO.getComponentName(), taskDO.getPackageVersion(), targetFileMd5); } - /** - * 事务内更新 Database 记录 - * - * @param componentPackageDO Component Package 记录 - * @param taskDO Component Package Task 记录 - * @param taskLog - */ @Transactional(rollbackFor = Exception.class) - public void updateDataSuccessRecord(ComponentPackageDO componentPackageDO, ComponentPackageTaskDO taskDO, - String taskLog) { + public void genComponentPackageRecord(ComponentPackageDO componentPackageDO, Long taskId) { componentPackageRepository.insert(componentPackageDO); + ComponentPackageTaskDO taskDO = componentPackageTaskRepository.getByCondition( + ComponentPackageTaskQueryCondition.builder().id(taskId).build()); taskDO.setComponentPackageId(componentPackageDO.getId()); - taskDO.setTaskLog(taskLog); componentPackageTaskRepository.updateByCondition(taskDO, ComponentPackageTaskQueryCondition.builder().id(taskDO.getId()).build()); } @@ -484,17 +604,6 @@ public class K8sMicroserviceComponenPackage implements ComponentPackageBase, App } } - @Transactional(rollbackFor = Exception.class) - public void updateDataFailRecord(Long taskId, String taskLog) { - ComponentPackageTaskDO taskDO = componentPackageTaskRepository.getByCondition( - ComponentPackageTaskQueryCondition.builder().id(taskId).build()); - if (taskDO.getTaskStatus().equalsIgnoreCase(AppPackageTaskStatusEnum.FAILURE.name())) { - return; - } - taskDO.setTaskLog(taskLog); - componentPackageTaskRepository.updateByCondition(taskDO, ComponentPackageTaskQueryCondition.builder().id(taskDO.getId()).build()); - } - private String genPodName(String appId, String componentName, String containerName, Long taskId, long tag) { StringBuilder podName = new StringBuilder(); podName.append("appmanager-build-").append(appId).append("-") @@ -504,117 +613,4 @@ public class K8sMicroserviceComponenPackage implements ComponentPackageBase, App .append(tag); return podName.toString(); } - - @Async - @Override - public void onApplicationEvent(KanikoPodEvent event) { - String podName = event.getPodName(); - String[] split = podName.split("-"); - Long taskId = Long.valueOf(split[split.length - 2]); - if (taskPodMap.containsKey(taskId)) { - synchronized (flag) { - switch (event.getCurrentStatus()) { - case SUCCEED: { - if (taskPodMap.containsKey(taskId)) { - if (!succeedPodMap.containsKey(taskId)) { - succeedPodMap.put(taskId, new HashSet<>()); - } - succeedPodMap.get(taskId).add(podName); - if (taskPodMap.get(taskId).size() == succeedPodMap.get(taskId).size()) { - StringBuilder taskLog = new StringBuilder(); - for (String runPod : taskPodMap.get(taskId)) { - try { - String podLog = api.readNamespacedPodLog(runPod, systemProperties.getK8sNamespace(), - null, null, null, null, null, null, null, null, null); - taskLog.append(podName).append("-log:\n").append(podLog).append("\n"); - } catch (ApiException e) { - log.warn("action=KanikoSucceedOp||can not read kaniko pod log:{}", runPod); - } - try { - api.deleteNamespacedPod(runPod, systemProperties.getK8sNamespace(), null, - null, null, null, null, null); - } catch (ApiException e) { - log.warn("action=KanikoSucceedOp||clean pod error:{}", e.getResponseBody()); - } - } - try { - taskPodMap.remove(taskId); - log.info("action=clean build task informer:{}", taskId); - succeedPodMap.remove(taskId); - String targetFileDir = taskTargetDirMap.remove(taskId); - packageComponentZip(taskId, taskLog.toString(), targetFileDir); - deleteDir(targetFileDir); - Set remoteObjectSet = taskRemoteObjectMap.remove(taskId); - deleteRemoteObject(remoteObjectSet); - publisher.publishEvent(new SucceedComponentPackageTaskEvent(this, taskId)); - } catch (Exception e) { - log.error("action=waitBuildPodAndPackage|| something wrong when operate package zip!message={}||exception={}", e.getMessage(), e.getCause()); - publisher.publishEvent(new FailedComponentPackageTaskEvent(this, taskId)); - } - } - } - break; - } - case FAILED: { - if (taskPodMap.containsKey(taskId)) { - StringBuilder taskLog = new StringBuilder(); - try { - String podLog = api.readNamespacedPodLog(podName, systemProperties.getK8sNamespace(), - null, null, null, null, null, null, null, null, null); - taskLog.append(podName).append("-log:\n").append(podLog).append("\n"); - } catch (ApiException e) { - log.warn("action=KanikoFailedOp||can not read pod log:{}", podName); - } - for (String runPod : taskPodMap.get(taskId)) { - try { - api.deleteNamespacedPod(runPod, systemProperties.getK8sNamespace(), null, - null, null, null, null, null); - } catch (ApiException e) { - log.warn("action=KanikoFailedOp||clean pod error:{}", e.getResponseBody()); - } - } - try { - taskPodMap.remove(taskId); - log.info("action=clean build task informer:{}", taskId); - succeedPodMap.remove(taskId); - updateDataFailRecord(taskId, taskLog.toString()); - String targetFileDir = taskTargetDirMap.remove(taskId); - deleteDir(targetFileDir); - Set remoteObjectSet = taskRemoteObjectMap.remove(taskId); - deleteRemoteObject(remoteObjectSet); - } finally { - publisher.publishEvent(new FailedComponentPackageTaskEvent(this, taskId)); - } - } - break; - } - case DELETE: { - if (taskPodMap.containsKey(taskId)) { - for (String runPod : taskPodMap.get(taskId)) { - try { - api.deleteNamespacedPod(runPod, systemProperties.getK8sNamespace(), null, - null, null, null, null, null); - } catch (ApiException e) { - log.warn("action=KanikoFailedOp||clean pod error:{}", e.getResponseBody()); - } - } - try { - taskPodMap.remove(taskId); - log.info("action=clean build task informer:{}", taskId); - succeedPodMap.remove(taskId); - String targetFileDir = taskTargetDirMap.remove(taskId); - deleteDir(targetFileDir); - Set remoteObjectSet = taskRemoteObjectMap.remove(taskId); - deleteRemoteObject(remoteObjectSet); - } finally { - publisher.publishEvent(new FailedComponentPackageTaskEvent(this, taskId)); - } - } - break; - } - default: - } - } - } - } } diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/componentpackage/instance/util/BuildUtil.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/componentpackage/instance/util/BuildUtil.java new file mode 100644 index 00000000..be36f210 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/componentpackage/instance/util/BuildUtil.java @@ -0,0 +1,14 @@ +package com.alibaba.tesla.appmanager.server.service.componentpackage.instance.util; + +/** + * @ClassName: BuildUtil + * @Author: dyj + * @DATE: 2022-08-31 + * @Description: + **/ +public class BuildUtil { + public static String genLogContent(String pod, String message){ + String logContent = String.format("\n====container:%s====\n-log:%s", pod, message); + return logContent; + } +} diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/deploy/impl/DeployAppServiceImpl.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/deploy/impl/DeployAppServiceImpl.java index 283ab5ca..41172718 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/deploy/impl/DeployAppServiceImpl.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/deploy/impl/DeployAppServiceImpl.java @@ -1,9 +1,13 @@ package com.alibaba.tesla.appmanager.server.service.deploy.impl; import com.alibaba.fastjson.JSONObject; +import com.alibaba.tesla.appmanager.common.enums.DeployAppEventEnum; +import com.alibaba.tesla.appmanager.common.enums.DeployAppStateEnum; import com.alibaba.tesla.appmanager.common.exception.AppErrorCode; import com.alibaba.tesla.appmanager.common.exception.AppException; import com.alibaba.tesla.appmanager.common.pagination.Pagination; +import com.alibaba.tesla.appmanager.common.util.DateUtil; +import com.alibaba.tesla.appmanager.server.event.deploy.DeployAppEvent; import com.alibaba.tesla.appmanager.server.repository.DeployAppAttrRepository; import com.alibaba.tesla.appmanager.server.repository.DeployAppRepository; import com.alibaba.tesla.appmanager.server.repository.condition.DeployAppAttrQueryCondition; @@ -14,6 +18,7 @@ import com.alibaba.tesla.appmanager.server.service.deploy.DeployAppService; import com.alibaba.tesla.appmanager.server.service.deploy.business.DeployAppBO; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; @@ -39,6 +44,9 @@ public class DeployAppServiceImpl implements DeployAppService { @Autowired private DeployAppAttrRepository deployAppAttrRepository; + @Autowired + private ApplicationEventPublisher publisher; + /** * 根据部署工单 ID 获取对应的部署工单对象 * @@ -53,6 +61,7 @@ public class DeployAppServiceImpl implements DeployAppService { throw new AppException(AppErrorCode.INVALID_USER_ARGS, String.format("cannot find deploy app order by id %d", deployAppId)); } + if (!withExt) { return DeployAppBO.builder().order(order).build(); } diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/imagebuilder/impl/ImageBuilderServiceImpl.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/imagebuilder/impl/ImageBuilderServiceImpl.java index df9ef903..b58510ba 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/imagebuilder/impl/ImageBuilderServiceImpl.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/imagebuilder/impl/ImageBuilderServiceImpl.java @@ -100,7 +100,7 @@ public class ImageBuilderServiceImpl implements ImageBuilderService { .repoPath(request.getRepoPath()) .ciAccount(request.getCiAccount()) .ciToken(request.getCiToken()) - .keepGitFiles(false) + .keepGitFiles(request.isKeepGitFiles()) .build(), cloneDir); // 渲染 Dockerfile diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/pack/dag/PackAppPackageToStorageNode.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/pack/dag/PackAppPackageToStorageNode.java index d875e19b..42c35d43 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/pack/dag/PackAppPackageToStorageNode.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/pack/dag/PackAppPackageToStorageNode.java @@ -111,8 +111,8 @@ public class PackAppPackageToStorageNode extends AbstractLocalNodeBase { String bucketName = storageFile.getBucketName(); String objectName = storageFile.getObjectName(); String componentUrl = storage.getObjectUrl(bucketName, objectName, DefaultConstant.DEFAULT_FILE_EXPIRATION); - String basename = String.format("%s_%s.zip", - componentPackageDO.getComponentType(), componentPackageDO.getComponentName()); + String basename = PackageUtil.buildComponentPackageZipBasename(componentPackageDO.getComponentType(), + componentPackageDO.getComponentName()); String filename = folder.resolve(basename).toString(); // Component Package 包下载到本地目录中 diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/pack/impl/PackServiceImpl.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/pack/impl/PackServiceImpl.java index 2483b91b..d5937ea4 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/pack/impl/PackServiceImpl.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/pack/impl/PackServiceImpl.java @@ -29,13 +29,12 @@ import com.alibaba.tesla.appmanager.meta.k8smicroservice.util.K8sMicroServiceUti import com.alibaba.tesla.appmanager.server.repository.AppPackageTaskRepository; import com.alibaba.tesla.appmanager.server.repository.ComponentPackageTaskRepository; import com.alibaba.tesla.appmanager.server.repository.condition.AppAddonQueryCondition; +import com.alibaba.tesla.appmanager.server.repository.condition.AppComponentQueryCondition; import com.alibaba.tesla.appmanager.server.repository.condition.AppMetaQueryCondition; import com.alibaba.tesla.appmanager.server.repository.condition.AppPackageTaskQueryCondition; -import com.alibaba.tesla.appmanager.server.repository.domain.AppAddonDO; -import com.alibaba.tesla.appmanager.server.repository.domain.AppMetaDO; -import com.alibaba.tesla.appmanager.server.repository.domain.AppPackageTaskDO; -import com.alibaba.tesla.appmanager.server.repository.domain.ComponentPackageTaskDO; +import com.alibaba.tesla.appmanager.server.repository.domain.*; import com.alibaba.tesla.appmanager.server.service.appaddon.AppAddonService; +import com.alibaba.tesla.appmanager.server.service.appcomponent.AppComponentService; import com.alibaba.tesla.appmanager.server.service.appmeta.AppMetaService; import com.alibaba.tesla.appmanager.server.service.apppackage.AppPackageTaskService; import com.alibaba.tesla.appmanager.server.service.pack.PackService; @@ -72,6 +71,7 @@ public class PackServiceImpl implements PackService { private final AppMetaService appMetaService; private final HelmMetaService helmMetaService; private final SystemProperties systemProperties; + private final AppComponentService appComponentService; public PackServiceImpl( ComponentPackageProvider componentPackageProvider, @@ -79,7 +79,8 @@ public class PackServiceImpl implements PackService { K8sMicroserviceMetaService k8sMicroserviceMetaService, AppPackageTaskRepository appPackageTaskRepository, AppPackageTaskService appPackageTaskService, AppAddonService appAddonService, AppMetaService appMetaService, - HelmMetaService helmMetaService, SystemProperties systemProperties) { + HelmMetaService helmMetaService, SystemProperties systemProperties, + AppComponentService appComponentService) { this.componentPackageProvider = componentPackageProvider; this.componentPackageTaskRepository = componentPackageTaskRepository; this.k8sMicroserviceMetaService = k8sMicroserviceMetaService; @@ -89,6 +90,7 @@ public class PackServiceImpl implements PackService { this.appMetaService = appMetaService; this.helmMetaService = helmMetaService; this.systemProperties = systemProperties; + this.appComponentService = appComponentService; } @Override @@ -123,14 +125,14 @@ public class PackServiceImpl implements PackService { String appId = message.getAppId(); String namespaceId = message.getNamespaceId(); String stageId = message.getStageId(); - ComponentTypeEnum componentType = component.getComponentType(); + String componentType = component.getComponentType(); String componentName = component.getComponentName(); ComponentPackageTaskCreateReq request = ComponentPackageTaskCreateReq.builder() .appId(appId) .namespaceId(namespaceId) .stageId(stageId) .appPackageTaskId(message.getAppPackageTaskId()) - .componentType(componentType.toString()) + .componentType(componentType) .componentName(componentName) .version(component.getVersion()) .build(); @@ -146,7 +148,7 @@ public class PackServiceImpl implements PackService { .appId(appId) .namespaceId(namespaceId) .stageId(stageId) - .componentType(componentType.toString()) + .componentType(componentType) .componentName(componentName) .packageVersion(component.getVersion()) .packageCreator(message.getOperator()) @@ -170,17 +172,19 @@ public class PackServiceImpl implements PackService { String appId = message.getAppId(); String namespaceId = message.getNamespaceId(); String stageId = message.getStageId(); - ComponentTypeEnum componentType = component.getComponentType(); + String category = component.getCategory(); + String componentType = component.getComponentType(); String componentName = component.getComponentName(); Boolean isDevelop = component.getIsDevelop(); JSONObject options = new JSONObject(); if (BooleanUtils.isTrue(component.getUseRawOptions())) { options = component.getOptions(); - } else if (componentType.isKubernetesJob() || componentType.isKubernetesMicroservice()) { + } else if (ComponentTypeEnum.K8S_JOB.toString().equals(componentType) + || ComponentTypeEnum.K8S_MICROSERVICE.toString().equals(componentType)) { options = buildOptions4K8sMicroService( appId, namespaceId, stageId, componentName, component.getBranch()); - } else if (componentType.isResourceAddon()) { + } else if (ComponentTypeEnum.RESOURCE_ADDON.toString().equals(componentType)) { String[] arr = componentName.split("@", 2); if (arr.length != 2) { throw new AppException(AppErrorCode.INVALID_USER_ARGS, @@ -189,10 +193,33 @@ public class PackServiceImpl implements PackService { String addonId = arr[0]; String addonName = arr[1]; options = buildOptions4ResourceAddon(appId, namespaceId, stageId, addonId, addonName); - } else if (componentType.isInternalAddon()) { + } else if (ComponentTypeEnum.INTERNAL_ADDON.toString().equals(componentType)) { options = buildOptions4InternalAddon(appId, namespaceId, stageId, componentName, isDevelop); - } else if (componentType.isHelm()) { + } else if (ComponentTypeEnum.HELM.toString().equals(componentType)) { options = buildOptions4Helm(appId, componentName, component.getBranch()); + } else { + AppComponentQueryCondition queryCondition = AppComponentQueryCondition.builder() + .appId(appId) + .namespaceId(namespaceId) + .stageId(stageId) + .category(category) + .componentType(componentType) + .componentName(componentName) + .build(); + AppComponentDO appComponent = appComponentService.get(queryCondition); + if (appComponent == null) { + log.warn("cannot find app component by condition when generating build options|condition={}", + JSONObject.toJSONString(queryCondition)); + } else { + if (StringUtils.isEmpty(appComponent.getConfig())) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("empty app component config when generating build options|condition=%s", + JSONObject.toJSONString(queryCondition))); + } + options = JSONObject.parseObject(appComponent.getConfig()); + log.info("load build options from app component config|condition={}|options={}", + JSONObject.toJSONString(queryCondition), appComponent.getConfig()); + } } // 存储组件默认部署配置 (可选) diff --git a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/rtappinstance/impl/RtAppInstanceServiceImpl.java b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/rtappinstance/impl/RtAppInstanceServiceImpl.java index df156631..6c05a644 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/rtappinstance/impl/RtAppInstanceServiceImpl.java +++ b/paas/appmanager/tesla-appmanager-server/src/main/java/com/alibaba/tesla/appmanager/server/service/rtappinstance/impl/RtAppInstanceServiceImpl.java @@ -23,10 +23,10 @@ import com.alibaba.tesla.appmanager.server.repository.condition.AppPackageQueryC import com.alibaba.tesla.appmanager.server.repository.condition.RtAppInstanceHistoryQueryCondition; import com.alibaba.tesla.appmanager.server.repository.condition.RtAppInstanceQueryCondition; import com.alibaba.tesla.appmanager.server.repository.condition.RtComponentInstanceQueryCondition; -import com.alibaba.tesla.appmanager.server.repository.domain.AppPackageDO; -import com.alibaba.tesla.appmanager.server.repository.domain.RtAppInstanceDO; -import com.alibaba.tesla.appmanager.server.repository.domain.RtAppInstanceHistoryDO; -import com.alibaba.tesla.appmanager.server.repository.domain.RtComponentInstanceDO; +import com.alibaba.tesla.appmanager.server.repository.domain.*; +import com.alibaba.tesla.appmanager.server.service.appmeta.AppMetaService; +import com.alibaba.tesla.appmanager.server.service.appoption.AppOptionConstant; +import com.alibaba.tesla.appmanager.server.service.appoption.AppOptionService; import com.alibaba.tesla.appmanager.server.service.apppackage.AppPackageService; import com.alibaba.tesla.appmanager.server.service.rtappinstance.RtAppInstanceService; import com.google.common.base.Enums; @@ -44,6 +44,7 @@ import java.time.LocalDateTime; import java.time.ZoneId; import java.util.*; import java.util.function.Function; +import java.util.stream.Collectors; /** * 实时应用实例服务 @@ -75,6 +76,9 @@ public class RtAppInstanceServiceImpl implements RtAppInstanceService { @Autowired private GroovyHandlerFactory groovyHandlerFactory; + @Autowired + private AppOptionService appOptionService; + /** * CRD Context */ @@ -287,6 +291,15 @@ public class RtAppInstanceServiceImpl implements RtAppInstanceService { asyncTriggerStatusUpdate(appInstance.getAppInstanceId()); } } + if ("OXS".equals(System.getenv("CLOUD_TYPE")) && Boolean.TRUE.equals(condition.getVisit())) { + Set navAppSet = appOptionService.getOptionsByKeyValue(AppOptionConstant.APP_IS_SHOW_IN_NAV, "1") + .stream() + .map(AppOptionDO::getAppId) + .collect(Collectors.toSet()); + log.info("the app set satisfied the isShowNav=true condition are {}", + JSONObject.toJSONString(new ArrayList<>(navAppSet))); + result = result.stream().filter(item -> navAppSet.contains(item.getAppId())).collect(Collectors.toList()); + } return Pagination.valueOf(result, Function.identity()); } diff --git a/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/CustomStatusGenericResource.groovy b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/CustomStatusGenericResource.groovy new file mode 100644 index 00000000..8a41bd05 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/CustomStatusGenericResource.groovy @@ -0,0 +1,176 @@ +package dynamicscripts + +import com.alibaba.fastjson.JSONObject +import com.alibaba.tesla.appmanager.common.constants.DefaultConstant +import com.alibaba.tesla.appmanager.common.enums.ComponentInstanceStatusEnum +import com.alibaba.tesla.appmanager.common.enums.DynamicScriptKindEnum +import com.alibaba.tesla.appmanager.common.exception.AppErrorCode +import com.alibaba.tesla.appmanager.common.exception.AppException +import com.alibaba.tesla.appmanager.common.util.ConditionUtil +import com.alibaba.tesla.appmanager.domain.req.rtcomponentinstance.RtComponentInstanceGetStatusReq +import com.alibaba.tesla.appmanager.domain.res.rtcomponentinstance.RtComponentInstanceGetStatusRes +import com.alibaba.tesla.appmanager.server.dynamicscript.handler.ComponentCustomStatusHandler +import com.jayway.jsonpath.DocumentContext +import com.jayway.jsonpath.JsonPath +import com.jayway.jsonpath.PathNotFoundException +import io.fabric8.kubernetes.client.DefaultKubernetesClient +import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext +import org.apache.commons.lang3.StringUtils +import org.apache.commons.lang3.exception.ExceptionUtils +import org.slf4j.Logger +import org.slf4j.LoggerFactory + +/** + * 自定义状态获取脚本: 通用资源 + * + * @author yaoxing.gyx@alibaba-inc.com + */ +class CustomStatusGenericResource implements ComponentCustomStatusHandler { + + private static final String OPERATOR_EXIST = "exist" + private static final String OPERATOR_EQUAL = "equal" + + private static final Logger log = LoggerFactory.getLogger(CustomStatusGenericResource.class) + + /** + * 当前内置 Handler 类型 + */ + public static final String KIND = DynamicScriptKindEnum.CUSTOM_STATUS.toString() + + /** + * 当前内置 Handler 名称 + */ + public static final String NAME = "generic-resource/v1" + + /** + * 当前内置 Handler 版本 + */ + public static final Integer REVISION = 8 + + @Override + RtComponentInstanceGetStatusRes getStatus( + RtComponentInstanceGetStatusReq request, DefaultKubernetesClient client, JSONObject options) { + def logSuffix = String.format("clusterId=%s|namespaceId=%s|stageId=%s|appId=%s|componentType=%s|" + + "componentName=%s|version=%s", request.getClusterId(), request.getNamespaceId(), request.getStageId(), + request.getAppId(), request.getComponentType(), request.getComponentName(), request.getVersion()) + def endStatus = options.getString("endStatus") + if (StringUtils.isEmpty(endStatus)) { + endStatus = ComponentInstanceStatusEnum.COMPLETED.toString() + } + def resources = options.getJSONArray("resources") + if (resources == null) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "cannot find resources in options") + } + + def data = new JSONObject() + for (def resource : resources.toJavaList(JSONObject.class)) { + def definition = resource.getJSONObject("definition") + if (definition == null) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "cannot find definition in resource") + } + def context = new CustomResourceDefinitionContext.Builder() + .withName(definition.getString("name")) + .withGroup(definition.getString("group")) + .withVersion(definition.getString("version")) + .withPlural(definition.getString("plural")) + .withScope(definition.getString("scope")) + .build() + if (StringUtils.isAnyEmpty(context.getName(), context.getGroup(), context.getVersion(), + context.getPlural(), context.getScope())) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("invalid definition in resource|resource=%s", JSONObject.toJSONString(resource))) + } + def namespace = resource.getString("namespace") + def name = resource.getString("name") + def alias = resource.getString("alias") + def conditions = resource.getJSONArray("conditions") + if (StringUtils.isAnyEmpty(namespace, name, alias) || conditions == null || conditions.size() == 0) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("invalid resource configuration in options|resource=%s", + JSONObject.toJSONString(resource))) + } + for (def condition : conditions.toJavaList(JSONObject.class)) { + def path = condition.getString("path") + def operator = condition.getString("operator") + def value = condition.get("value") + if (StringUtils.isAnyEmpty(path, operator)) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("invalid condition in resources|condition=%s", + JSONObject.toJSONString(condition))) + } + def obj = client.customResource(context).inNamespace(namespace).withName(name).get() + if (obj == null) { + return RtComponentInstanceGetStatusRes.builder() + .status(ComponentInstanceStatusEnum.WARNING.toString()) + .conditions(ConditionUtil.singleCondition("CheckResourceExists", "False", + String.format("cannot find resource %s in namespace %s", name, namespace), "")) + .build() + } + DocumentContext objContext = JsonPath.parse(JSONObject.toJSONString(obj)) + def objValue + try { + objValue = objContext.read(DefaultConstant.JSONPATH_PREFIX + path) + } catch (PathNotFoundException ignored) { + objValue = null + } catch (Exception e) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("read by jsonpath failed|obj=%s|path=%s|exception=%s", + JSONObject.toJSONString(obj), path, ExceptionUtils.getStackTrace(e))) + } + switch (operator) { + case OPERATOR_EQUAL: + if (objValue == value) { + data.put(alias, removeUselessResourceFields(obj)) + log.info("script=CustomStatusGenericResource|message=object compare equal|path={}|" + + "operator={}|value={}|namespace={}|name={}|{}", path, operator, value, + namespace, name, logSuffix) + } else { + log.info("script=CustomStatusGenericResource|message=object compare failed|path={}|" + + "operator={}|value={}|objValue={}|namespace={}|name={}|{}", path, operator, + value, objValue, namespace, name, logSuffix) + return RtComponentInstanceGetStatusRes.builder() + .status(ComponentInstanceStatusEnum.WARNING.toString()) + .conditions(ConditionUtil.singleCondition("CheckResourceEqual", "False", + String.format("object compare failed|path=%s|operator=%s|value=%s|" + + "objValue=%s|namespace=%s|name=%s|%s", path, operator, value, + objValue, namespace, name, logSuffix), "")) + .build() + } + break + case OPERATOR_EXIST: + if (objValue != null) { + data.put(alias, removeUselessResourceFields(obj)) + log.info("script=CustomStatusGenericResource|message=object exist|path={}|operator={}|" + + "objValue={}|namespace={}|name={}|{}", path, operator, objValue, namespace, + name, logSuffix) + } else { + log.info("script=CustomStatusGenericResource|message=object not exist|path={}|" + + "operator={}|objValue={}|namespace={}|name={}|{}", + path, operator, objValue, namespace, name, logSuffix) + return RtComponentInstanceGetStatusRes.builder() + .status(ComponentInstanceStatusEnum.WARNING.toString()) + .conditions(ConditionUtil.singleCondition("CheckResourceExist", "False", + String.format("object not exist|path=%s|operator=%s|namespace=%s|" + + "name=%s|%s", path, operator, namespace, name, logSuffix), "")) + .build() + } + break + default: + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "unsupported operator " + operator) + } + } + } + log.info("script=CustomStatusGenericResource|message=all resources compare finished|{}|data={}", + logSuffix, JSONObject.toJSONString(data)) + return RtComponentInstanceGetStatusRes.builder() + .status(endStatus) + .conditions(ConditionUtil.dataOutputCondition(data)) + .build() + } + + private static JSONObject removeUselessResourceFields(Object data) { + def target = JSONObject.parseObject(JSONObject.toJSONString(data)) + target.remove("metadata") + return target + } +} \ No newline at end of file diff --git a/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/DefaultBuildInternalAddonProductopsHandler.groovy b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/DefaultBuildInternalAddonProductopsHandler.groovy index 9ea1dc86..8db03842 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/DefaultBuildInternalAddonProductopsHandler.groovy +++ b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/DefaultBuildInternalAddonProductopsHandler.groovy @@ -36,7 +36,7 @@ import java.nio.file.Paths */ class DefaultInternalAddonProductopsHandler implements BuildComponentHandler { - private static final Logger log = LoggerFactory.getLogger(DefaultBuildJobHandler.class) + private static final Logger log = LoggerFactory.getLogger(DefaultInternalAddonProductopsHandler.class) /** * 当前内置 Handler 类型 @@ -51,7 +51,7 @@ class DefaultInternalAddonProductopsHandler implements BuildComponentHandler { /** * 当前内置 Handler 版本 */ - public static final Integer REVISION = 15 + public static final Integer REVISION = 23 /** * 弹内导出应用需要排除的应用 ID @@ -91,6 +91,7 @@ class DefaultInternalAddonProductopsHandler implements BuildComponentHandler { def stageId = request.getStageId() def version = request.getVersion() def options = request.getOptions() + def logString = new StringBuffer() // 创建当前组件包的临时组装目录,用于存储 meta 信息及构建后的镜像 def packageDir @@ -118,7 +119,11 @@ class DefaultInternalAddonProductopsHandler implements BuildComponentHandler { for (Map.Entry entry : params.entrySet()) { urlBuilder.addQueryParameter(entry.getKey(), entry.getValue()) } - FileUtils.copyURLToFile(new URL(urlBuilder.build().toString()), exportPath.toFile(), 10 * 1000, 60 * 1000) + def actualUrl = urlBuilder.build().toString() + def message = String.format("prepare to download from productops|url=%s\n", actualUrl) + logString.append(message) + log.info(message) + FileUtils.copyURLToFile(new URL(actualUrl), exportPath.toFile(), 10 * 1000, 60 * 1000) } // 解压当前导出文件并清理 @@ -141,8 +146,11 @@ class DefaultInternalAddonProductopsHandler implements BuildComponentHandler { def metaYamlContent = jinjava.render(template, options) def metaYamlFile = Paths.get(packageDir.toString(), "meta.yaml").toFile() FileUtils.writeStringToFile(metaYamlFile, metaYamlContent, StandardCharsets.UTF_8) - log.info("meta yaml config has rendered|appId={}|namespaceId={}|stageId={}|componentType={}|componentName={}|" + - "packageVersion={}", appId, namespaceId, stageId, componentType, componentName, version) + def message = String.format("meta yaml config has rendered|appId=%s|namespaceId=%s|stageId=%s|" + + "componentType=%s|componentName=%s|packageVersion=%s\n", appId, namespaceId, stageId, + componentType, componentName, version) + logString.append(message) + log.info(message) // 将 packageDir 打包为 zip 文件 String zipPath = packageDir.resolve("app_package.zip").toString() @@ -154,17 +162,22 @@ class DefaultInternalAddonProductopsHandler implements BuildComponentHandler { } }) def targetFileMd5 = StringUtil.getMd5Checksum(zipPath) - log.info("zip file has generated|appId={}|namespaceId={}|stageId={}|componentType={}|componentName={}|" + - "packageVersion={}|zipPath={}|md5={}", appId, namespaceId, stageId, componentType, componentName, - version, zipPath, targetFileMd5) + message = String.format("zip file has generated|appId=%s|namespaceId=%s|stageId=%s|componentType=%s|" + + "componentName=%s|packageVersion=%s|zipPath=%s|md5=%s\n", appId, namespaceId, stageId, componentType, + componentName, version, zipPath, targetFileMd5) + logString.append(message) + log.info(message) // 上传导出包到 Storage 中 String bucketName = packageProperties.getBucketName() String remotePath = PackageUtil .buildComponentPackageRemotePath(appId, componentType, componentName, version) storage.putObject(bucketName, remotePath, zipPath) - log.info("component package has uploaded to storage|appId={}|namespaceId={}|stageId={}|bucketName={}|" + - "remotePath={}|localPath={}", appId, namespaceId, stageId, bucketName, remotePath, zipPath) + message = String.format("component package has uploaded to storage|appId=%s|namespaceId=%s|" + + "stageId=%s|bucketName=%s|remotePath=%s|localPath=%s\n", appId, namespaceId, stageId, + bucketName, remotePath, zipPath) + logString.append(message) + log.info(message) // 删除临时数据 (正常流程下) try { @@ -173,7 +186,7 @@ class DefaultInternalAddonProductopsHandler implements BuildComponentHandler { log.warn("cannot delete component package build directory|directory={}", packageDir.toString()) } LaunchBuildComponentHandlerRes res = LaunchBuildComponentHandlerRes.builder() - .logContent("get zip file from productops succeed") + .logContent(logString.toString()) .storageFile(new StorageFile(bucketName, remotePath)) .packageMetaYaml(metaYamlContent) .packageMd5(targetFileMd5) diff --git a/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/DefaultDeployInternalAddonAppBindingHandler.groovy b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/DefaultDeployInternalAddonAppBindingHandler.groovy index 6990c4b6..a4539cc5 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/DefaultDeployInternalAddonAppBindingHandler.groovy +++ b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/DefaultDeployInternalAddonAppBindingHandler.groovy @@ -52,7 +52,7 @@ class DefaultDeployInternalAddonAppBindingHandler implements DeployComponentHand /** * 当前内置 Handler 版本 */ - public static final Integer REVISION = 2 + public static final Integer REVISION = 3 private static final String EXPORT_FILE = "_jiongsi_filename_.json" private static final String ANNOTATIONS_VERSION = "annotations.appmanager.oam.dev/version" @@ -81,9 +81,9 @@ class DefaultDeployInternalAddonAppBindingHandler implements DeployComponentHand // 上报状态 def annotations = (JSONObject) componentSchema.getSpec().getWorkload().getMetadata().getAnnotations() - def version = annotations.getOrDefault(ANNOTATIONS_VERSION, "") - def componentInstanceId = annotations.getOrDefault(ANNOTATIONS_COMPONENT_INSTANCE_ID, "") - def appInstanceName = annotations.getOrDefault(ANNOTATIONS_APP_INSTANCE_NAME, "") + def version = (String) annotations.getOrDefault(ANNOTATIONS_VERSION, "") + def componentInstanceId = (String) annotations.getOrDefault(ANNOTATIONS_COMPONENT_INSTANCE_ID, "") + def appInstanceName = (String) annotations.getOrDefault(ANNOTATIONS_APP_INSTANCE_NAME, "") componentInstanceService.report(ReportRtComponentInstanceStatusReq.builder() .componentInstanceId(componentInstanceId) .appInstanceName(appInstanceName) diff --git a/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/DefaultDeployInternalAddonProductopsHandler.groovy b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/DefaultDeployInternalAddonProductopsHandler.groovy index 588195f1..1e000a1b 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/DefaultDeployInternalAddonProductopsHandler.groovy +++ b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/DefaultDeployInternalAddonProductopsHandler.groovy @@ -54,7 +54,7 @@ class DefaultDeployInternalAddonProductopsHandler implements DeployComponentHand /** * 当前内置 Handler 版本 */ - public static final Integer REVISION = 10 + public static final Integer REVISION = 12 private static final String IMPORT_TMP_FILE = "productops_tmp_import.zip" private static final String ANNOTATIONS_VERSION = "annotations.appmanager.oam.dev/version" @@ -132,9 +132,9 @@ class DefaultDeployInternalAddonProductopsHandler implements DeployComponentHand // 上报状态 def annotations = (JSONObject) componentSchema.getSpec().getWorkload().getMetadata().getAnnotations() - def version = annotations.getOrDefault(ANNOTATIONS_VERSION, "") - def componentInstanceId = annotations.getOrDefault(ANNOTATIONS_COMPONENT_INSTANCE_ID, "") - def appInstanceName = annotations.getOrDefault(ANNOTATIONS_APP_INSTANCE_NAME, "") + def version = (String) annotations.getOrDefault(ANNOTATIONS_VERSION, "") + def componentInstanceId = (String) annotations.getOrDefault(ANNOTATIONS_COMPONENT_INSTANCE_ID, "") + def appInstanceName = (String) annotations.getOrDefault(ANNOTATIONS_APP_INSTANCE_NAME, "") componentInstanceService.report(ReportRtComponentInstanceStatusReq.builder() .componentInstanceId(componentInstanceId) .appInstanceName(appInstanceName) @@ -188,7 +188,12 @@ class DefaultDeployInternalAddonProductopsHandler implements DeployComponentHand def httpClient = HttpClientFactory.getHttpClient() def times = 2 while (true) { - def urlPrefix = String.format("%s/jobs/report_app_tree_structures/%s/start", endpoint, appTreeId) + def urlPrefix + if ("Internal".equals(System.getenv("CLOUD_TYPE"))) { + urlPrefix = String.format("%s/jobs/async_report_app_tree_structures/%s/start", endpoint, appTreeId) + } else { + urlPrefix = String.format("%s/jobs/report_app_tree_structures/%s/start", endpoint, appTreeId) + } def urlBuilder = Objects.requireNonNull(HttpUrl.parse(urlPrefix)).newBuilder() def reqBuilder = new Request.Builder() .url(urlBuilder.build()) @@ -287,48 +292,31 @@ class DefaultDeployInternalAddonProductopsHandler implements DeployComponentHand LaunchDeployComponentHandlerReq request, JSONObject options, String endpoint, String zipPath, String namespaceId, String envId) { def httpClient = HttpClientFactory.getHttpClient() - def times = 2 def cloudType = System.getenv("CLOUD_TYPE") - while (true) { - def urlPrefix = String.format("%s/maintainer/upload", endpoint) - def urlBuilder = Objects.requireNonNull(HttpUrl.parse(urlPrefix)).newBuilder() - def resetVersion = options.getString("resetVersion") - if (resetVersion == null) { - resetVersion = "false" - } - urlBuilder.addQueryParameter("resetVersion", resetVersion) - if (StringUtils.isNotEmpty(namespaceId) - || "OXS" == cloudType - || "ApsaraStack" == cloudType - || "ApsaraStackAgility" == cloudType) { - urlBuilder.addQueryParameter("envId", envId) - } - def body = new MultipartBody.Builder() - .setType(MultipartBody.FORM) - .addFormDataPart("file", IMPORT_TMP_FILE, - RequestBody.create(MediaType.parse("application/octet-stream"), - new File(zipPath))) - .build() - def reqBuilder = new Request.Builder() - .url(urlBuilder.build()) - .post(body) - try { - NetworkUtil.sendRequest(httpClient, reqBuilder, "") - log.info("[app_id.{}] import productops config success", request.getAppId()) - times -= 1 - if (times <= 0) { - break - } - } catch (Exception e) { - if (times <= 0) { - throw e - } else { - log.error("[app_id.{}] import productops config failed, exception={}", - request.getAppId(), ExceptionUtils.getStackTrace(e)) - times -= 1 - } - } + def urlPrefix = String.format("%s/maintainer/upload", endpoint) + def urlBuilder = Objects.requireNonNull(HttpUrl.parse(urlPrefix)).newBuilder() + def resetVersion = options.getString("resetVersion") + if (resetVersion == null) { + resetVersion = "false" } + urlBuilder.addQueryParameter("resetVersion", resetVersion) + if (StringUtils.isNotEmpty(namespaceId) + || "OXS" == cloudType + || "ApsaraStack" == cloudType + || "ApsaraStackAgility" == cloudType) { + urlBuilder.addQueryParameter("envId", envId) + } + def body = new MultipartBody.Builder() + .setType(MultipartBody.FORM) + .addFormDataPart("file", IMPORT_TMP_FILE, + RequestBody.create(MediaType.parse("application/octet-stream"), + new File(zipPath))) + .build() + def reqBuilder = new Request.Builder() + .url(urlBuilder.build()) + .post(body) + NetworkUtil.sendRequest(httpClient, reqBuilder, "") + log.info("[app_id.{}] import productops config success", request.getAppId()) } /** diff --git a/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/HelmBuildMicroserviceHandler.groovy b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/HelmComponentBuildHandler.groovy similarity index 90% rename from paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/HelmBuildMicroserviceHandler.groovy rename to paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/HelmComponentBuildHandler.groovy index 28349ce4..741c6a3f 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/HelmBuildMicroserviceHandler.groovy +++ b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/HelmComponentBuildHandler.groovy @@ -2,16 +2,11 @@ package dynamicscripts import com.alibaba.fastjson.JSONObject import com.alibaba.tesla.appmanager.autoconfig.PackageProperties -import com.alibaba.tesla.appmanager.common.constants.DefaultConstant import com.alibaba.tesla.appmanager.common.enums.DynamicScriptKindEnum import com.alibaba.tesla.appmanager.common.exception.AppErrorCode import com.alibaba.tesla.appmanager.common.exception.AppException import com.alibaba.tesla.appmanager.common.service.GitService -import com.alibaba.tesla.appmanager.common.util.CommandUtil -import com.alibaba.tesla.appmanager.common.util.NetworkUtil -import com.alibaba.tesla.appmanager.common.util.PackageUtil -import com.alibaba.tesla.appmanager.common.util.StringUtil -import com.alibaba.tesla.appmanager.common.util.ZipUtil +import com.alibaba.tesla.appmanager.common.util.* import com.alibaba.tesla.appmanager.domain.core.StorageFile import com.alibaba.tesla.appmanager.domain.req.componentpackage.BuildComponentHandlerReq import com.alibaba.tesla.appmanager.domain.req.git.GitCloneReq @@ -35,28 +30,28 @@ import java.nio.file.Files import java.nio.file.Paths /** - * 默认构建 Microservice Groovy Handler + * 默认构建 Helm Groovy Handler * * @author yaoxing.gyx@alibaba-inc.com */ -class HelmBuildMicroserviceHandler implements BuildComponentHandler { +class HelmComponentBuildHandler implements BuildComponentHandler { - private static final Logger log = LoggerFactory.getLogger(HelmBuildMicroserviceHandler.class) + private static final Logger log = LoggerFactory.getLogger(HelmComponentBuildHandler.class) /** - * 当前内置 Handler 类型 + * 当前脚本类型 (ComponentKindEnum) */ - public static final String KIND = DynamicScriptKindEnum.BUILD_HELM_COMPONENT.toString() + public static final String KIND = DynamicScriptKindEnum.COMPONENT_BUILD.toString() /** - * 当前内置 Handler 名称 + * 当前脚本名称 (指定 SCRIPT_KIND 下唯一) */ - public static final String NAME = DefaultConstant.DEFAULT_GROOVY_HANDLER + public static final String NAME = "HelmDefault" /** * 当前内置 Handler 版本 */ - public static final Integer REVISION = 38 + public static final Integer REVISION = 40 private static final String KEY_HELM_CHART = "helm_chart" diff --git a/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/HelmDeployMicroserviceHandler.groovy b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/HelmComponentDeployHandler.groovy similarity index 97% rename from paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/HelmDeployMicroserviceHandler.groovy rename to paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/HelmComponentDeployHandler.groovy index 7d34a19a..d70cfdcd 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/HelmDeployMicroserviceHandler.groovy +++ b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/HelmComponentDeployHandler.groovy @@ -2,7 +2,6 @@ package dynamicscripts import com.alibaba.fastjson.JSONObject import com.alibaba.tesla.appmanager.autoconfig.SystemProperties -import com.alibaba.tesla.appmanager.common.constants.DefaultConstant import com.alibaba.tesla.appmanager.common.enums.ComponentInstanceStatusEnum import com.alibaba.tesla.appmanager.common.enums.DeployComponentStateEnum import com.alibaba.tesla.appmanager.common.enums.DynamicScriptKindEnum @@ -36,30 +35,30 @@ import java.nio.file.Files import java.nio.file.Paths /** - * 默认构建 Microservice Groovy Handler + * 默认构建 Helm Groovy Handler * * @author yaoxing.gyx@alibaba-inc.com */ -class HelmDeployMicroserviceHandler implements DeployComponentHandler { +class HelmComponentDeployHandler implements DeployComponentHandler { - private static final Logger log = LoggerFactory.getLogger(HelmDeployMicroserviceHandler.class) + private static final Logger log = LoggerFactory.getLogger(HelmComponentDeployHandler.class) private static final String KEY_COMPONENT_PACKAGE_URL = "appmanager_deploy_component_package" /** - * 当前内置 Handler 类型 + * 当前脚本类型 (ComponentKindEnum) */ - public static final String KIND = DynamicScriptKindEnum.DEPLOY_HELM_COMPONENT.toString() + public static final String KIND = DynamicScriptKindEnum.COMPONENT_DEPLOY.toString() /** - * 当前内置 Handler 名称 + * 当前脚本名称 (指定 SCRIPT_KIND 下唯一) */ - public static final String NAME = DefaultConstant.DEFAULT_GROOVY_HANDLER + public static final String NAME = "HelmDefault" /** * 当前内置 Handler 版本 */ - public static final Integer REVISION = 49 + public static final Integer REVISION = 51 private static final String ANNOTATIONS_VERSION = "annotations.appmanager.oam.dev/version" private static final String ANNOTATIONS_COMPONENT_INSTANCE_ID = "annotations.appmanager.oam.dev/componentInstanceId" diff --git a/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/HelmComponentHandler.groovy b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/HelmComponentHandler.groovy index cd5bcb06..ead885f1 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/HelmComponentHandler.groovy +++ b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/HelmComponentHandler.groovy @@ -14,7 +14,7 @@ class HelmComponentHandler implements ComponentHandler { */ public static final String KIND = "COMPONENT" public static final String NAME = "HELM" - public static final Integer REVISION = 1 + public static final Integer REVISION = 2 /** * 获取 `COMPONENT_BUILD` 类型下的映射名称 @@ -53,7 +53,7 @@ class HelmComponentHandler implements ComponentHandler { */ @Override String watchKind() { - return "CRON" + return "" } /** @@ -65,6 +65,6 @@ class HelmComponentHandler implements ComponentHandler { */ @Override String watchScriptName() { - return "HelmCron" + return "" } } diff --git a/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/DefaultBuildJobHandler.groovy b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/JobComponentBuildHandler.groovy similarity index 95% rename from paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/DefaultBuildJobHandler.groovy rename to paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/JobComponentBuildHandler.groovy index 6cdaead6..3144b2fd 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/DefaultBuildJobHandler.groovy +++ b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/JobComponentBuildHandler.groovy @@ -5,7 +5,6 @@ import com.alibaba.fastjson.JSONArray import com.alibaba.fastjson.JSONObject import com.alibaba.fastjson.TypeReference import com.alibaba.tesla.appmanager.autoconfig.PackageProperties -import com.alibaba.tesla.appmanager.common.constants.DefaultConstant import com.alibaba.tesla.appmanager.common.enums.DynamicScriptKindEnum import com.alibaba.tesla.appmanager.common.exception.AppErrorCode import com.alibaba.tesla.appmanager.common.exception.AppException @@ -40,24 +39,24 @@ import java.util.stream.Collectors * * @author yaoxing.gyx@alibaba-inc.com */ -class DefaultBuildJobHandler implements BuildComponentHandler { +class JobComponentBuildHandler implements BuildComponentHandler { - private static final Logger log = LoggerFactory.getLogger(DefaultBuildJobHandler.class) + private static final Logger log = LoggerFactory.getLogger(JobComponentBuildHandler.class) /** - * 当前内置 Handler 类型 + * 当前脚本类型 (ComponentKindEnum) */ - public static final String KIND = DynamicScriptKindEnum.BUILD_JOB_COMPONENT.toString() + public static final String KIND = DynamicScriptKindEnum.COMPONENT_BUILD.toString() /** - * 当前内置 Handler 名称 + * 当前脚本名称 (指定 SCRIPT_KIND 下唯一) */ - public static final String NAME = DefaultConstant.DEFAULT_GROOVY_HANDLER + public static final String NAME = "JobDefault" /** * 当前内置 Handler 版本 */ - public static final Integer REVISION = 13 + public static final Integer REVISION = 16 private static final String TEMPLATE_JOB_FILENAME = "default_job.tpl" @@ -214,6 +213,7 @@ class DefaultBuildJobHandler implements BuildComponentHandler { .imagePush(build.getBooleanValue("imagePush")) .imagePushRegistry(build.getString("imagePushRegistry")) .imagePushUseBranchAsTag(build.getBoolean("imagePushUseBranchAsTag")) + .keepGitFiles(true) .imageName(build.getString("imageName")) .repo(build.getString("repo")) .branch(build.getString("branch")) diff --git a/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/DefaultDeployJobHandler.groovy b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/JobComponentDeployHandler.groovy similarity index 96% rename from paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/DefaultDeployJobHandler.groovy rename to paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/JobComponentDeployHandler.groovy index 9bf168ed..9d9b0851 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/DefaultDeployJobHandler.groovy +++ b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/JobComponentDeployHandler.groovy @@ -3,7 +3,6 @@ package dynamicscripts import com.alibaba.fastjson.JSONArray import com.alibaba.fastjson.JSONObject import com.alibaba.tesla.appmanager.autoconfig.SystemProperties -import com.alibaba.tesla.appmanager.common.constants.DefaultConstant import com.alibaba.tesla.appmanager.common.enums.DeployComponentStateEnum import com.alibaba.tesla.appmanager.common.enums.DynamicScriptKindEnum import com.alibaba.tesla.appmanager.common.exception.AppErrorCode @@ -37,26 +36,26 @@ import java.nio.file.Paths * * @author yaoxing.gyx@alibaba-inc.com */ -class DefaultDeployJobHandler implements DeployComponentHandler { +class JobComponentDeployHandler implements DeployComponentHandler { - private static final Logger log = LoggerFactory.getLogger(DefaultDeployJobHandler.class) + private static final Logger log = LoggerFactory.getLogger(JobComponentDeployHandler.class) private static final String KEY_COMPONENT_PACKAGE_URL = "appmanager_deploy_component_package" /** - * 当前内置 Handler 类型 + * 当前脚本类型 (ComponentKindEnum) */ - public static final String KIND = DynamicScriptKindEnum.DEPLOY_JOB_COMPONENT.toString() + public static final String KIND = DynamicScriptKindEnum.COMPONENT_DEPLOY.toString() /** - * 当前内置 Handler 名称 + * 当前脚本名称 (指定 SCRIPT_KIND 下唯一) */ - public static final String NAME = DefaultConstant.DEFAULT_GROOVY_HANDLER + public static final String NAME = "JobDefault" /** * 当前内置 Handler 版本 */ - public static final Integer REVISION = 10 + public static final Integer REVISION = 12 /** * CRD Context diff --git a/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/DefaultBuildMicroserviceHandler.groovy b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/MicroserviceComponentBuildHandler.groovy similarity index 95% rename from paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/DefaultBuildMicroserviceHandler.groovy rename to paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/MicroserviceComponentBuildHandler.groovy index 9384043b..129c0266 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/DefaultBuildMicroserviceHandler.groovy +++ b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/MicroserviceComponentBuildHandler.groovy @@ -5,7 +5,6 @@ import com.alibaba.fastjson.JSONArray import com.alibaba.fastjson.JSONObject import com.alibaba.fastjson.TypeReference import com.alibaba.tesla.appmanager.autoconfig.PackageProperties -import com.alibaba.tesla.appmanager.common.constants.DefaultConstant import com.alibaba.tesla.appmanager.common.enums.DynamicScriptKindEnum import com.alibaba.tesla.appmanager.common.exception.AppErrorCode import com.alibaba.tesla.appmanager.common.exception.AppException @@ -41,24 +40,24 @@ import java.util.stream.Collectors * * @author yaoxing.gyx@alibaba-inc.com */ -class DefaultBuildMicroserviceHandler implements BuildComponentHandler { +class MicroserviceComponentBuildHandler implements BuildComponentHandler { - private static final Logger log = LoggerFactory.getLogger(DefaultBuildMicroserviceHandler.class) + private static final Logger log = LoggerFactory.getLogger(MicroserviceComponentBuildHandler.class) /** - * 当前内置 Handler 类型 + * 当前脚本类型 (ComponentKindEnum) */ - public static final String KIND = DynamicScriptKindEnum.BUILD_MICROSERVICE_COMPONENT.toString() + public static final String KIND = DynamicScriptKindEnum.COMPONENT_BUILD.toString() /** - * 当前内置 Handler 名称 + * 当前脚本名称 (指定 SCRIPT_KIND 下唯一) */ - public static final String NAME = DefaultConstant.DEFAULT_GROOVY_HANDLER + public static final String NAME = "MicroserviceDefault" /** * 当前内置 Handler 版本 */ - public static final Integer REVISION = 17 + public static final Integer REVISION = 20 private static final String TEMPLATE_MICROSERVICE_FILENAME = "default_microservice_%s.tpl" private static final String DEFAULT_MICROSERVICE_TYPE = "Deployment" @@ -224,6 +223,7 @@ class DefaultBuildMicroserviceHandler implements BuildComponentHandler { .imagePush(build.getBooleanValue("imagePush")) .imagePushRegistry(build.getString("imagePushRegistry")) .imagePushUseBranchAsTag(build.getBoolean("imagePushUseBranchAsTag")) + .keepGitFiles(true) .imageName(build.getString("imageName")) .repo(build.getString("repo")) .branch(build.getString("branch")) diff --git a/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/DefaultDeployMicroserviceHandler.groovy b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/MicroserviceComponentDeployHandler.groovy similarity index 97% rename from paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/DefaultDeployMicroserviceHandler.groovy rename to paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/MicroserviceComponentDeployHandler.groovy index 1bed6234..dd43a1d2 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/DefaultDeployMicroserviceHandler.groovy +++ b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/MicroserviceComponentDeployHandler.groovy @@ -3,7 +3,6 @@ package dynamicscripts import com.alibaba.fastjson.JSONArray import com.alibaba.fastjson.JSONObject import com.alibaba.tesla.appmanager.autoconfig.SystemProperties -import com.alibaba.tesla.appmanager.common.constants.DefaultConstant import com.alibaba.tesla.appmanager.common.enums.DeployComponentStateEnum import com.alibaba.tesla.appmanager.common.enums.DynamicScriptKindEnum import com.alibaba.tesla.appmanager.common.exception.AppErrorCode @@ -22,9 +21,6 @@ import com.alibaba.tesla.appmanager.kubernetes.KubernetesClientFactory import com.alibaba.tesla.appmanager.server.service.deploy.handler.DeployComponentHandler import io.fabric8.kubernetes.api.model.NamespaceBuilder import io.fabric8.kubernetes.api.model.ObjectMetaBuilder -import io.fabric8.kubernetes.api.model.ResourceQuotaBuilder -import io.fabric8.kubernetes.api.model.ResourceQuotaSpec -import io.fabric8.kubernetes.api.model.ResourceQuotaSpecBuilder import io.fabric8.kubernetes.client.KubernetesClientException import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext import org.apache.commons.collections4.CollectionUtils @@ -45,26 +41,26 @@ import java.nio.file.Paths * * @author yaoxing.gyx@alibaba-inc.com */ -class DefaultDeployMicroserviceHandler implements DeployComponentHandler { +class MicroserviceComponentDeployHandler implements DeployComponentHandler { - private static final Logger log = LoggerFactory.getLogger(DefaultDeployMicroserviceHandler.class) + private static final Logger log = LoggerFactory.getLogger(MicroserviceComponentDeployHandler.class) private static final String KEY_COMPONENT_PACKAGE_URL = "appmanager_deploy_component_package" /** - * 当前内置 Handler 类型 + * 当前脚本类型 (ComponentKindEnum) */ - public static final String KIND = DynamicScriptKindEnum.DEPLOY_MICROSERVICE_COMPONENT.toString() + public static final String KIND = DynamicScriptKindEnum.COMPONENT_DEPLOY.toString() /** - * 当前内置 Handler 名称 + * 当前脚本名称 (指定 SCRIPT_KIND 下唯一) */ - public static final String NAME = DefaultConstant.DEFAULT_GROOVY_HANDLER + public static final String NAME = "MicroserviceDefault" /** * 当前内置 Handler 版本 */ - public static final Integer REVISION = 36 + public static final Integer REVISION = 38 /** * CRD Context diff --git a/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/ScriptComponentBuildHandler.groovy b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/ScriptComponentBuildHandler.groovy index 4489e18d..886b19f9 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/ScriptComponentBuildHandler.groovy +++ b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/ScriptComponentBuildHandler.groovy @@ -2,7 +2,6 @@ package dynamicscripts import com.alibaba.fastjson.JSONObject import com.alibaba.tesla.appmanager.autoconfig.PackageProperties -import com.alibaba.tesla.appmanager.common.constants.DefaultConstant import com.alibaba.tesla.appmanager.common.enums.DynamicScriptKindEnum import com.alibaba.tesla.appmanager.common.exception.AppErrorCode import com.alibaba.tesla.appmanager.common.exception.AppException @@ -25,7 +24,6 @@ import org.springframework.core.io.ClassPathResource import java.nio.charset.StandardCharsets import java.nio.file.Files import java.nio.file.Paths - /** * 默认 Script 组件 Groovy Handler * @@ -36,19 +34,19 @@ class ScriptComponentBuildHandler implements BuildComponentHandler { private static final Logger log = LoggerFactory.getLogger(ScriptComponentBuildHandler.class) /** - * 当前内置 Handler 类型 + * 当前脚本类型 (ComponentKindEnum) */ - public static final String KIND = DynamicScriptKindEnum.BUILD_SCRIPT_COMPONENT.toString() + public static final String KIND = DynamicScriptKindEnum.COMPONENT_BUILD.toString() /** - * 当前内置 Handler 名称 + * 当前脚本名称 (指定 SCRIPT_KIND 下唯一) */ - public static final String NAME = DefaultConstant.DEFAULT_GROOVY_HANDLER + public static final String NAME = "ScriptComponentDefault" /** * 当前内置 Handler 版本 */ - public static final Integer REVISION = 0 + public static final Integer REVISION = 1 private static final String TEMPLATE_SCRIPT_FILENAME = "default_script_component.tpl" diff --git a/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/ScriptComponentDeployHandler.groovy b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/ScriptComponentDeployHandler.groovy index 7c300995..f543ae95 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/ScriptComponentDeployHandler.groovy +++ b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/ScriptComponentDeployHandler.groovy @@ -2,7 +2,6 @@ package dynamicscripts import com.alibaba.fastjson.JSONArray import com.alibaba.fastjson.JSONObject -import com.alibaba.tesla.appmanager.common.constants.DefaultConstant import com.alibaba.tesla.appmanager.common.enums.ComponentInstanceStatusEnum import com.alibaba.tesla.appmanager.common.enums.DeployComponentAttrTypeEnum import com.alibaba.tesla.appmanager.common.enums.DeployComponentStateEnum @@ -30,7 +29,6 @@ import org.springframework.beans.factory.annotation.Autowired import java.time.LocalDateTime import java.time.ZoneId - /** * 默认部署 ABM Status Component Groovy Handler * @@ -41,19 +39,19 @@ class ScriptComponentDeployHandler implements DeployComponentHandler { private static final Logger log = LoggerFactory.getLogger(ScriptComponentDeployHandler.class) /** - * 当前内置 Handler 类型 + * 当前脚本类型 (ComponentKindEnum) */ - public static final String KIND = DynamicScriptKindEnum.DEPLOY_SCRIPT_COMPONENT.toString() + public static final String KIND = DynamicScriptKindEnum.COMPONENT_DEPLOY.toString() /** - * 当前内置 Handler 名称 + * 当前脚本名称 (指定 SCRIPT_KIND 下唯一) */ - public static final String NAME = DefaultConstant.DEFAULT_GROOVY_HANDLER + public static final String NAME = "ScriptComponentDefault" /** * 当前内置 Handler 版本 */ - public static final Integer REVISION = 1 + public static final Integer REVISION = 3 /** * 上报状态常量 @@ -188,6 +186,7 @@ class ScriptComponentDeployHandler implements DeployComponentHandler { // 根据状态判定当前是否应该结束 switch (componentInstanceStatus) { + case ComponentInstanceStatusEnum.COMPLETED: case ComponentInstanceStatusEnum.RUNNING: break case ComponentInstanceStatusEnum.PENDING: @@ -221,7 +220,7 @@ class ScriptComponentDeployHandler implements DeployComponentHandler { .build() } def conditionsArray = JSONArray.parseArray(conditions) - def message = String.format("the status of %s is RUNNING now", componentName) + def message = String.format("the status of %s is %s now", componentName, componentInstanceStatus.toString()) for (JSONObject condition : conditionsArray.toJavaList(JSONObject.class)) { if (ConditionUtil.TYPE_DATA_OUTPUTS != condition.getString("type")) { continue diff --git a/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/ScriptComponentWatchCronHandler.groovy b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/ScriptComponentWatchCronHandler.groovy index bb060487..632b7296 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/ScriptComponentWatchCronHandler.groovy +++ b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/ScriptComponentWatchCronHandler.groovy @@ -39,7 +39,7 @@ class ScriptComponentWatchCronHandler implements ComponentWatchCronHandler { */ public static final String KIND = DynamicScriptKindEnum.COMPONENT_WATCH_CRON.toString() public static final String NAME = "ScriptComponentCron" - public static final Integer REVISION = 4 + public static final Integer REVISION = 5 @Autowired private DeployAppService deployAppService @@ -80,6 +80,17 @@ class ScriptComponentWatchCronHandler implements ComponentWatchCronHandler { .deployStatusList(Arrays.asList(DeployComponentStateEnum.RUNNING, DeployComponentStateEnum.PROCESSING, DeployComponentStateEnum.SUCCESS)) .build(), true) + // 针对于第一次部署场景,还没有成功记录,那么允许获取失败的记录 + if (deployComponents.size() == 0) { + deployComponents = deployComponentService.list(DeployComponentQueryCondition.builder() + .appId(request.getAppId()) + .clusterId(request.getClusterId()) + .namespaceId(request.getNamespaceId()) + .stageId(request.getStageId()) + .identifierStartsWith(identifierPrefix) + .pageSize(1) + .build(), true) + } if (deployComponents.size() == 0) { log.warn("current component is not existed|{}", logSuffix) return RtComponentInstanceGetStatusRes.builder() diff --git a/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/TraitSecret.groovy b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/TraitSecret.groovy new file mode 100644 index 00000000..5ec2b9a8 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/TraitSecret.groovy @@ -0,0 +1,401 @@ +package dynamicscripts + +import com.alibaba.fastjson.JSON +import com.alibaba.fastjson.JSONArray +import com.alibaba.fastjson.JSONObject +import com.alibaba.fastjson.TypeReference +import com.alibaba.tesla.appmanager.common.enums.DynamicScriptKindEnum +import com.alibaba.tesla.appmanager.common.exception.AppErrorCode +import com.alibaba.tesla.appmanager.common.exception.AppException +import com.alibaba.tesla.appmanager.domain.core.WorkloadResource +import com.alibaba.tesla.appmanager.domain.req.trait.TraitExecuteReq +import com.alibaba.tesla.appmanager.domain.res.trait.TraitExecuteRes +import com.alibaba.tesla.appmanager.kubernetes.KubernetesClientFactory +import com.alibaba.tesla.appmanager.trait.service.handler.TraitHandler +import com.google.common.collect.ImmutableMap +import io.fabric8.kubernetes.api.model.Secret +import io.fabric8.kubernetes.api.model.SecretBuilder +import io.fabric8.kubernetes.client.DefaultKubernetesClient +import io.fabric8.kubernetes.client.KubernetesClientException +import io.fabric8.kubernetes.client.dsl.Resource +import org.apache.commons.lang3.StringUtils +import org.apache.commons.lang3.exception.ExceptionUtils +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import org.springframework.beans.factory.annotation.Autowired + +import java.nio.charset.StandardCharsets + +/** + * Secret Trait + * + * @author yaoxing.gyx@alibaba-inc.com + */ +class TraitSecret implements TraitHandler { + + private static final Logger log = LoggerFactory.getLogger(TraitSecret.class) + + /** + * 当前内置 Handler 类型 + */ + public static final String KIND = DynamicScriptKindEnum.TRAIT.toString() + + /** + * 当前内置 Handler 名称 + */ + public static final String NAME = "secret.trait.abm.io" + + /** + * 当前内置 Handler 版本 + */ + public static final Integer REVISION = 1 + + @Autowired + private KubernetesClientFactory clientFactory + + /** + * Trait 业务侧逻辑执行 + * + * @param request Trait 输入参数 + * @return Trait 修改后的 Spec 定义 + */ + @Override + TraitExecuteRes execute(TraitExecuteReq request) { + /** + * 1. get metadata from workload + */ + log.info("start execute secret trait {}", request.getSpec().toJSONString()) + + WorkloadResource workloadResource = request.getRef() + String namespace = workloadResource.getMetadata().getNamespace() + JSONObject labels = request.getSpec().getJSONObject("labels") + JSONObject annotations = request.getSpec().getJSONObject("annotations") + request.getSpec().remove("labels") + request.getSpec().remove("annotations") + labels = labels == null ? new JSONObject() : labels + annotations = annotations == null ? new JSONObject() : annotations + + /** + * 2. get k8s cluster info + */ + WorkloadResource workloadRef = request.getRef() + String clusterId = request.getComponent().getClusterId() + if (StringUtils.isEmpty(clusterId)) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("cannot find clusterId in workload labels|workload=%s", + JSONObject.toJSONString(workloadRef))) + } + DefaultKubernetesClient client = clientFactory.get(clusterId) + + /** + * 3. get secrets and apply to k8s cluster + */ + JSONObject secrets = request.getSpec().getJSONObject("secrets") + log.info("start to apply secret in secret trait {}", secrets.toJSONString()) + for (Map.Entry item : secrets.entrySet()) { + String secretName = item.getKey() + Object secretData = item.getValue() + JSONObject secret = generateSecret(namespace, secretName, secretData, labels, annotations) + applySecret(request, client, secret, labels, annotations) + } + + /** + 4. patch targets in values + */ + JSONArray targets = request.getSpec().getJSONArray("targets") + if (targets == null) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "") + } + for (int i = 0; i < targets.size(); i++) { + JSONObject target = targets.getJSONObject(i) + if ("env" == target.getString("type")) { + /** + * containers: + * - name: test-container + * image: k8s.gcr.io/busybox + * command: [ "/bin/sh", "-c", "env" ] + * envFrom: + * - secretRef: + * name: special-config + */ + if (target.getString("secret") == null) { + String errorMessage = String.format("secret key not found %s", target.toJSONString()) + throw new AppException(AppErrorCode.INVALID_USER_ARGS, errorMessage) + } + JSONArray updateDatas = new JSONArray() + updateDatas.add(JSONObject.parseObject(JSONObject.toJSONString(ImmutableMap.of( + "secretRef", ImmutableMap.of( + "name", target.getString("secret")) as Object + ) + ))) + if (target.getString("initContainer") != null) { + updateContainers(request, "initContainer", target.getString("initContainer"), "envFrom", updateDatas) + } else if (target.getString("container") != null) { + updateContainers(request, "container", target.getString("container"), "envFrom", updateDatas) + } else { + String errorMessage = String.format("not found container or initContainer %s", target.toJSONString()) + throw new AppException(AppErrorCode.INVALID_USER_ARGS, errorMessage) + } + } else if ("volumeMount" == target.getString("type")) { + /** + * containers: + * - name: test-container + * image: k8s.gcr.io/busybox + * command: [ "/bin/sh", "-c", "ls /etc/config/" ] + * volumeMounts: + * - name: config-volume + * mountPath: /etc/config + * volumes: + * - name: config-volume + * secret: + * name: special-config + */ + if (target.getString("secret") == null || target.getString("mountPath") == null) { + String errorMessage = String.format("secret or mountPath not found %s", target.toJSONString()) + throw new AppException(AppErrorCode.INVALID_USER_ARGS, errorMessage) + } + JSONArray volumes = new JSONArray() + volumes.add(JSONObject.parseObject(JSONObject.toJSONString(ImmutableMap.of( + "name", target.getString("secret"), + "secret", ImmutableMap.of( + "secretName", target.getString("secret") + ) + )))) + updateVolumes(request, volumes) + JSONArray updateDatas = new JSONArray() + if (StringUtils.isNotEmpty(target.getString("subPath"))) { + updateDatas.add(JSONObject.parseObject(JSONObject.toJSONString(ImmutableMap.of( + "name", target.getString("secret"), + "mountPath", target.getString("mountPath"), + "subPath", target.getString("subPath") + )))) + } else { + updateDatas.add(JSONObject.parseObject(JSONObject.toJSONString(ImmutableMap.of( + "name", target.getString("secret"), + "mountPath", target.getString("mountPath") + )))) + } + if (target.getString("initContainer") != null) { + updateContainers(request, "initContainer", target.getString("initContainer"), "volumeMounts", updateDatas) + } else if (target.getString("container") != null) { + updateContainers(request, "container", target.getString("container"), "volumeMounts", updateDatas) + } else { + String errorMessage = String.format("not found container or initContainer %s", target.toJSONString()) + throw new AppException(AppErrorCode.INVALID_USER_ARGS, errorMessage) + } + } else if ("envValue" == target.getString("type")) { + /** + * containers: + * - name: test-container + * image: k8s.gcr.io/busybox + * command: [ "/bin/sh", "-c", "echo $(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)" ] + * env: + * - name: SPECIAL_LEVEL_KEY + * valueFrom: + * secretKeyRef: + * name: special-config + * key: SPECIAL_LEVEL + */ + JSONArray updateEnvs = new JSONArray() + for (int j = 0; j < target.getJSONArray("values").size(); j++) { + JSONObject v = target.getJSONArray("values").getJSONObject(j) + updateEnvs.add(JSONObject.parseObject(JSONObject.toJSONString(ImmutableMap.of( + "name", v.getString("name"), + "valueFrom", ImmutableMap.of( + "secretKeyRef", ImmutableMap.of( + "name", v.getString("secret"), + "key", v.getString("key") + ) as Object + ) + )))) + } + if (target.getString("initContainer") != null) { + updateContainers(request, "initContainer", target.getString("initContainer"), "env", updateEnvs) + } else if (target.getString("container") != null) { + updateContainers(request, "container", target.getString("container"), "env", updateEnvs) + } else { + String errorMessage = String.format("not found container or initContainer %s", target.toJSONString()) + throw new AppException(AppErrorCode.INVALID_USER_ARGS, errorMessage) + } + } + } + return TraitExecuteRes.builder() + .spec(request.getSpec()) + .build() + } + + /** + * update containers in string + * + * @param type container or initContainer + * @param name + * @param targetKey + * @param updateDatas + * @return + */ + private static void updateContainers(TraitExecuteReq request, String type, String name, String targetKey, JSONArray updateDatas) { + JSONObject workloadSpec = (JSONObject) request.getRef().getSpec() + log.info("secret trait parent workload {}", workloadSpec.toJSONString()) + JSONArray containers + if (workloadSpec.get("cloneSet") != null) { + JSONObject cloneSetSpec = workloadSpec + .getJSONObject("cloneSet") + .getJSONObject("template") + .getJSONObject("spec") + containers = cloneSetSpec.getJSONArray(type + "s") + } else if (workloadSpec.get("advancedStatefulSet") != null) { + JSONObject advancedStatefulSetSpec = workloadSpec + .getJSONObject("advancedStatefulSet") + .getJSONObject("template") + .getJSONObject("spec") + containers = advancedStatefulSetSpec.getJSONArray(type + "s") + } else if ("Deployment" == workloadSpec.getString("kind")) { + containers = workloadSpec.getJSONArray(type + "s") + } else { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "not supported") + } + for (int i = 0; i < containers.size(); i++) { + JSONObject container = containers.getJSONObject(i) + if (!Objects.equals(container.getString("name"), name)) { + log.info("container name not match {} {}", container.getString("name"), name) + continue + } + container.putIfAbsent(targetKey, new JSONArray()) + JSONArray target = container.getJSONArray(targetKey) + for (int j = 0; j < updateDatas.size(); j++) { + JSONObject updateData = updateDatas.getJSONObject(i) + log.info("update container {} {}", target.toJSONString(), updateData.toJSONString()) + target.add(updateData) + } + } + log.info("secret trait parent workload after update {}", workloadSpec.toJSONString()) + } + + /** + * update volumes in string + * + * @param updateDatas + * @return + */ + private static void updateVolumes(TraitExecuteReq request, JSONArray updateDatas) { + JSONObject workloadSpec = (JSONObject) request.getRef().getSpec() + JSONArray volumes + if (workloadSpec.get("cloneSet") != null) { + JSONObject cloneSetSpec = workloadSpec + .getJSONObject("cloneSet") + .getJSONObject("template") + .getJSONObject("spec") + volumes = cloneSetSpec.getJSONArray("volumes") + if (volumes == null) { + cloneSetSpec.put("volumes", new JSONArray()) + volumes = cloneSetSpec.getJSONArray("volumes") + } + } else if (workloadSpec.get("advancedStatefulSet") != null) { + JSONObject advancedStatefulSetSpec = workloadSpec + .getJSONObject("advancedStatefulSet") + .getJSONObject("template") + .getJSONObject("spec") + volumes = advancedStatefulSetSpec.getJSONArray("volumes") + if (volumes == null) { + advancedStatefulSetSpec.put("volumes", new JSONArray()) + volumes = advancedStatefulSetSpec.getJSONArray("volumes") + } + } else { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "not supported") + } + for (int i = 0; i < updateDatas.size(); i++) { + JSONObject updateData = updateDatas.getJSONObject(i) + volumes.add(updateData) + } + } + + /** + * 创建配置文件 Secret + * + * @param namespace 命名空间 + * @param name 标识名称 + * @param data 配置数据 + * @return JSONObject + */ + private static JSONObject generateSecret( + String namespace, String name, Object data, Object labels, Object annotations) { + String secretStr = JSONObject.toJSONString(ImmutableMap.of( + "apiVersion", "v1", + "kind", "Secret", + "metadata", ImmutableMap.of( + "namespace", namespace, + "name", name, + "labels", labels, + "annotations", annotations + ), + "data", data + )) + JSONObject secret = JSONObject.parseObject(secretStr) + return secret + } + + /** + * secret apply k8s cluster + * + * @param client 已经被实例化的k8s连接客户端 + * @param secret 待提交的secret cr对象 + * @param labels + * @param annotations + * @return + */ + private static void applySecret( + TraitExecuteReq request, DefaultKubernetesClient client, JSONObject secret, + JSONObject labels, JSONObject annotations) { + // 应用到集群 + try { + String namespace = request.getComponent().getNamespaceId() + String name = secret.getJSONObject("metadata").getString("name") + Resource resource = client.secrets() + .load(new ByteArrayInputStream(secret.toJSONString().getBytes(StandardCharsets.UTF_8))) + try { + Secret current = client.secrets().inNamespace(namespace).withName(name).get() + if (current == null) { + Secret result = resource.create() + log.info("cr yaml has created in kubernetes|cluster={}|namespace={}|name={}|cr={}" + + "result={}", client, namespace, name, secret.toJSONString(), + JSONObject.toJSONString(result)) + } else { + Map newData = new HashMap<>() + for (Map.Entry entry : secret.getJSONObject("data").entrySet()) { + newData.put(entry.getKey(), String.valueOf(entry.getValue())) + } + JSONObject finalLabels = labels + JSONObject finalAnnotations = annotations + Secret result = client.secrets() + .inNamespace(namespace) + .withName(name) + .edit(s -> new SecretBuilder(s) + .editMetadata() + .withLabels(JSON.parseObject(finalLabels.toJSONString(), new TypeReference>() { + })) + .withAnnotations(JSON.parseObject(finalAnnotations.toJSONString(), new TypeReference>() { + })) + .endMetadata() + .withData(newData) + .build()) + log.info("cr yaml has updated in kubernetes|cluster={}|namespace={}|name={}|labels={}|" + + "annotations={}|newData={}|result={}", client, namespace, name, + JSONObject.toJSONString(labels), JSONObject.toJSONString(annotations), + JSONObject.toJSONString(newData), JSONObject.toJSONString(result)) + } + } catch (KubernetesClientException e) { + if (e.getCode() == 422) { + log.error("service apply failed, exception={}", ExceptionUtils.getStackTrace(e)) + } else { + throw e + } + } + } catch (Exception e) { + String errorMessage = String.format("apply cr yaml to kubernetes failed|cluster=%s|" + + "exception=%s|cr=%s", client, ExceptionUtils.getStackTrace(e), + secret.toJSONString()) + log.error(errorMessage) + throw new AppException(AppErrorCode.INVALID_USER_ARGS, errorMessage) + } + } +} diff --git a/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/WorkflowApplyComponentsHandler.groovy b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/WorkflowApplyComponentsHandler.groovy new file mode 100644 index 00000000..afd48d7c --- /dev/null +++ b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/WorkflowApplyComponentsHandler.groovy @@ -0,0 +1,202 @@ +package dynamicscripts + +import com.alibaba.fastjson.JSONArray +import com.alibaba.fastjson.JSONObject +import com.alibaba.tesla.appmanager.common.constants.WorkflowContextKeyConstant +import com.alibaba.tesla.appmanager.common.enums.DynamicScriptKindEnum +import com.alibaba.tesla.appmanager.common.exception.AppErrorCode +import com.alibaba.tesla.appmanager.common.exception.AppException +import com.alibaba.tesla.appmanager.domain.container.DeployAppRevisionName +import com.alibaba.tesla.appmanager.domain.req.workflow.ExecutePolicyHandlerReq +import com.alibaba.tesla.appmanager.domain.req.workflow.ExecuteWorkflowHandlerReq +import com.alibaba.tesla.appmanager.domain.res.workflow.ExecuteWorkflowHandlerRes +import com.alibaba.tesla.appmanager.domain.schema.DeployAppSchema +import com.alibaba.tesla.appmanager.workflow.dynamicscript.WorkflowHandler +import com.alibaba.tesla.appmanager.workflow.util.WorkflowHandlerUtil +import lombok.extern.slf4j.Slf4j +import org.apache.commons.lang3.SerializationUtils +import org.apache.commons.lang3.StringUtils +import org.slf4j.Logger +import org.slf4j.LoggerFactory + +import java.util.stream.Collectors + +/** + * Workflow 应用组件 Handler + * + * @author yaoxing.gyx@alibaba-inc.com + */ +@Slf4j +class WorkflowApplyComponentsHandler implements WorkflowHandler { + + private static final Logger log = LoggerFactory.getLogger(WorkflowApplyComponentsHandler.class) + + /** + * 当前内置 Handler 类型 + */ + public static final String KIND = DynamicScriptKindEnum.WORKFLOW.toString() + + /** + * 当前内置 Handler 名称 + */ + public static final String NAME = "apply-components" + + /** + * 当前内置 Handler 版本 + */ + public static final Integer REVISION = 4 + + /** + * 执行逻辑 + * @param request Workflow 执行请求 + * @return Workflow 执行结果 + */ + @Override + ExecuteWorkflowHandlerRes execute(ExecuteWorkflowHandlerReq request) throws InterruptedException { + def configuration = request.getConfiguration() + def context = request.getContext() + def properties = request.getTaskProperties() + def policies = properties.getJSONArray("policies") + def components = properties.getJSONArray("components") + def rollout = properties.getJSONObject("rollout") + + // 判断是否有取消执行的标志位,那么直接置为 terminate + if (context.getBooleanValue(WorkflowContextKeyConstant.CANCEL_EXECUTION)) { + def terminateReason = context.getString(WorkflowContextKeyConstant.CANCEL_EXECUTION_REASON) + if (StringUtils.isEmpty(terminateReason)) { + terminateReason = "canceled by user" + } + return ExecuteWorkflowHandlerRes.builder() + .context(context) + .configuration(request.getConfiguration()) + .terminate(true) + .terminateReason(terminateReason) + .build() + } + + if (policies != null && policies.size() > 0) { + for (def policyName : policies.toJavaList(String.class)) { + def policy = WorkflowHandlerUtil.getPolicy(configuration, policyName) + def policyHandler = WorkflowHandlerUtil.getPolicyHandler(policy.getType()) + def policyProperties = policy.getProperties() + def req = ExecutePolicyHandlerReq.builder() + .appId(request.getAppId()) + .instanceId(request.getInstanceId()) + .taskId(request.getTaskId()) + .policyProperties(policyProperties) + .context(context) + .configuration(configuration) + .build() + log.info("preapre to execute policy in workflow task|workflowInstanceId={}|workflowTaskId={}|" + + "appId={}|context={}|configuration={}", request.getInstanceId(), request.getTaskId(), + request.getAppId(), JSONObject.toJSONString(context), JSONObject.toJSONString(configuration)) + def res = policyHandler.execute(req) + if (res.getContext() != null) { + context = res.getContext(); + } + if (res.getConfiguration() != null) { + configuration = res.getConfiguration(); + } + log.info("policy has exeucted in workflow task|workflowInstanceId={}|workflowTaskId={}|appId={}|" + + "context={}|configuration={}", request.getInstanceId(), request.getTaskId(), request.getAppId(), + JSONObject.toJSONString(context), JSONObject.toJSONString(configuration)) + } + } + + // 根据 components 中的配置创建新的局部 Application Configuration + def newConfiguration = generateConfiguration(configuration, components, rollout) + def overwriteParameters = context.getJSONObject(WorkflowContextKeyConstant.DEPLOY_OVERWRITE_PARAMETERS) + def deployAppId = WorkflowHandlerUtil.deploy(newConfiguration, overwriteParameters, request.getCreator()) + log.info("deploy request has applied|workflowInstanceId={}|workflowTaskId={}|appId={}|context={}|" + + "configuration={}", request.getInstanceId(), request.getTaskId(), request.getAppId(), + JSONObject.toJSONString(context), JSONObject.toJSONString(newConfiguration)) + return ExecuteWorkflowHandlerRes.builder() + .deployAppId(deployAppId) + .context(context) + .configuration(newConfiguration) + .build() + } + + /** + * 根据 apply-components 中配置的内容来生成 Configuration + * @param configuration 原始 Configuration + * @param components 要部署的目标组件 + * @param rolloutObj 发布策略 + * @return 重新生成的 Application Configuration + */ + static DeployAppSchema generateConfiguration( + DeployAppSchema configuration, JSONArray components, JSONObject rolloutObj) { + def keySet = new HashSet() + for (def component : components.toJavaList(JSONObject.class)) { + def type = component.getString("type") + def name = component.getString("name") + if (StringUtils.isAnyEmpty(type, name)) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "type/name are required in 'components' field") + } + keySet.add(keyGenerator(type, name)) + } + + // 组装新的 Application Configuration + def newConfiguration = SerializationUtils.clone(configuration) + newConfiguration.getSpec().setComponents(newConfiguration.getSpec().getComponents() + .stream() + .filter(item -> { + def name = DeployAppRevisionName.valueOf(item.getRevisionName()) + return keySet.contains(keyGenerator(name.getComponentType(), name.getComponentName())) + }) + .collect(Collectors.toList())) + // 清理并重建依赖关系 (顺次执行) + def previousComponent = "" + for (def specComponent : newConfiguration.getSpec().getComponents()) { + if (StringUtils.isNotEmpty(previousComponent)) { + specComponent.setDependencies(Arrays.asList(DeployAppSchema.Dependency.builder() + .component(previousComponent) + .build())) + } else { + specComponent.setDependencies(new ArrayList<>()) + previousComponent = dependencyKeyGenerator(specComponent.getRevisionName()) + } + } + + // 如果存在 rollout, 那么放入各个组件的 ComponentSchema 中 + if (rolloutObj == null) { + return newConfiguration + } + def type = rolloutObj.getString("type") + if (type != "partition") { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + "only partition type is supported now|rollout=" + JSONObject.toJSONString(rolloutObj)) + } + for (def specComponent : newConfiguration.getSpec().getComponents()) { + if (specComponent.getParameterValues() == null) { + specComponent.setParameterValues(new ArrayList<>()) + } + specComponent.getParameterValues().add(DeployAppSchema.ParameterValue.builder() + .name("rollout") + .value(rolloutObj) + .toFieldPaths(Arrays.asList("spec.rollout")) + .build()) + } + return newConfiguration + } + + /** + * Key Generator + * @param type 类型 + * @param name 名称 + * @return + */ + static String keyGenerator(String type, String name) { + return String.format("%s_%s", type, name) + } + + /** + * Dependency Key Generator + * @param revisionName Revision Name + * @return + */ + static String dependencyKeyGenerator(String revisionName) { + def revision = DeployAppRevisionName.valueOf(revisionName) + return String.format("%s|%s", revision.getComponentType(), revision.getComponentName()) + } +} diff --git a/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/WorkflowDeployHandler.groovy b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/WorkflowDeployHandler.groovy index 95b7fa06..5cc2f078 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/WorkflowDeployHandler.groovy +++ b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/WorkflowDeployHandler.groovy @@ -34,7 +34,7 @@ class WorkflowDeployHandler implements WorkflowHandler { /** * 当前内置 Handler 版本 */ - public static final Integer REVISION = 3 + public static final Integer REVISION = 4 /** * 执行逻辑 @@ -74,7 +74,7 @@ class WorkflowDeployHandler implements WorkflowHandler { JSONObject.toJSONString(context), JSONObject.toJSONString(configuration)) } } - def deployAppId = WorkflowHandlerUtil.deploy(configuration, request.getCreator()) + def deployAppId = WorkflowHandlerUtil.deploy(configuration, null, request.getCreator()) log.info("deploy request has applied|workflowInstanceId={}|workflowTaskId={}|appId={}|context={}|" + "configuration={}", request.getInstanceId(), request.getTaskId(), request.getAppId(), JSONObject.toJSONString(context), JSONObject.toJSONString(configuration)) diff --git a/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/WorkflowRolloutPromotionHandler.groovy b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/WorkflowRolloutPromotionHandler.groovy new file mode 100644 index 00000000..0e4d5c98 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/WorkflowRolloutPromotionHandler.groovy @@ -0,0 +1,127 @@ +package dynamicscripts + +import com.alibaba.fastjson.JSONObject +import com.alibaba.tesla.appmanager.api.provider.WorkflowInstanceProvider +import com.alibaba.tesla.appmanager.common.constants.WorkflowContextKeyConstant +import com.alibaba.tesla.appmanager.common.enums.DynamicScriptKindEnum +import com.alibaba.tesla.appmanager.common.exception.AppErrorCode +import com.alibaba.tesla.appmanager.common.exception.AppException +import com.alibaba.tesla.appmanager.domain.option.WorkflowInstanceOption +import com.alibaba.tesla.appmanager.domain.req.workflow.ExecuteWorkflowHandlerReq +import com.alibaba.tesla.appmanager.domain.res.workflow.ExecuteWorkflowHandlerRes +import com.alibaba.tesla.appmanager.workflow.dynamicscript.WorkflowHandler +import com.alibaba.tesla.appmanager.workflow.util.WorkflowHandlerUtil +import lombok.extern.slf4j.Slf4j +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import org.springframework.beans.factory.annotation.Autowired + +/** + * Workflow Rollout Promotion Handler + * + * @author yaoxing.gyx@alibaba-inc.com + */ +@Slf4j +class WorkflowRolloutPromotionHandler implements WorkflowHandler { + + private static final Logger log = LoggerFactory.getLogger(WorkflowRolloutPromotionHandler.class) + + /** + * 当前内置 Handler 类型 + */ + public static final String KIND = DynamicScriptKindEnum.WORKFLOW.toString() + + /** + * 当前内置 Handler 名称 + */ + public static final String NAME = "rollout-promotion" + + /** + * 当前内置 Handler 版本 + */ + public static final Integer REVISION = 7 + + @Autowired + private WorkflowInstanceProvider workflowInstanceProvider + + /** + * 执行逻辑 + * @param request Workflow 执行请求 + * @return Workflow 执行结果 + */ + @Override + ExecuteWorkflowHandlerRes execute(ExecuteWorkflowHandlerReq request) throws InterruptedException { + def context = request.getContext() + if (context.getBooleanValue(WorkflowContextKeyConstant.QUIET_MODE)) { + // 安静运行模式下直接继续进行部署 + log.info("continue rollout progress because of quiet mode|workflowInstanceId={}|workflowTaskId={}|" + + "appId={}", request.getInstanceId(), request.getTaskId(), request.getAppId()) + return ExecuteWorkflowHandlerRes.builder() + .context(context) + .configuration(request.getConfiguration()) + .build() + } + + def continueRollout = context.getBoolean("continueRollout") + def rollback = context.getBoolean("rollback") + if (continueRollout == null || rollback == null) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "continueRollout/rollback must be set") + } + + // 不需要回滚时 + if (!rollback) { + if (continueRollout) { + log.info("continue rollout progress|workflowInstanceId={}|workflowTaskId={}|appId={}", + request.getInstanceId(), request.getTaskId(), request.getAppId()) + return ExecuteWorkflowHandlerRes.builder() + .context(context) + .configuration(request.getConfiguration()) + .build() + } else { + log.info("user terminated the current rollout progress|workflowInstanceId={}|workflowTaskId={}|" + + "appId={}", request.getInstanceId(), request.getTaskId(), request.getAppId()) + return ExecuteWorkflowHandlerRes.builder() + .context(context) + .configuration(request.getConfiguration()) + .terminate(true) + .build() + } + } + + // 需要回滚 + if (continueRollout) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "continueRollout must be false if rollback") + } + def appId = request.getAppId() + def targetInstance = workflowInstanceProvider.getLastSuccessInstance(appId, "DEPLOY") + if (targetInstance == null) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("cannot find previous successful workflow instance by app %s. " + + "so rollback current workflow instance is not feasible", appId)); + } + + // 回滚时的 workflow context 设置为安静模式,不需要人工确认 + def rollbackContext = new JSONObject() + rollbackContext.put(WorkflowContextKeyConstant.QUIET_MODE, true) + def rollbackOption = WorkflowInstanceOption.builder() + .category("ROLLBACK") + .creator(request.getCreator()) + .initContext(rollbackContext) + .build() + def rollbackConfiguration = targetInstance.getWorkflowConfiguration() + def rollbackWorkflowInstanceId = WorkflowHandlerUtil + .deployWorkflow(appId, rollbackConfiguration, rollbackOption) + log.info("rollback request has applied|rollbackWorkflowInstanceId={}|workflowInstanceId={}|" + + "workflowTaskId={}|appId={}|rollbackConfiguration={}", rollbackWorkflowInstanceId, + request.getInstanceId(), request.getTaskId(), request.getAppId(), + JSONObject.toJSONString(rollbackConfiguration)) + context.put(WorkflowContextKeyConstant.CANCEL_EXECUTION, true) + context.put(WorkflowContextKeyConstant.CANCEL_EXECUTION_REASON, + String.format("rollback succeed, and current workflow has turned into TERMINATED status")) + return ExecuteWorkflowHandlerRes.builder() + .deployWorkflowInstanceId(rollbackWorkflowInstanceId) + .context(context) + .configuration(request.getConfiguration()) + .build() + } +} diff --git a/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/WorkflowSuspendHandler.groovy b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/WorkflowSuspendHandler.groovy index b784f600..6ce0b41e 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/WorkflowSuspendHandler.groovy +++ b/paas/appmanager/tesla-appmanager-server/src/main/resources/dynamicscripts/WorkflowSuspendHandler.groovy @@ -1,6 +1,6 @@ package dynamicscripts - +import com.alibaba.tesla.appmanager.common.constants.WorkflowContextKeyConstant import com.alibaba.tesla.appmanager.common.enums.DynamicScriptKindEnum import com.alibaba.tesla.appmanager.domain.req.workflow.ExecuteWorkflowHandlerReq import com.alibaba.tesla.appmanager.domain.res.workflow.ExecuteWorkflowHandlerRes @@ -32,7 +32,7 @@ class WorkflowSuspendHandler implements WorkflowHandler { /** * 当前内置 Handler 版本 */ - public static final Integer REVISION = 0 + public static final Integer REVISION = 1 /** * 执行逻辑 @@ -41,10 +41,22 @@ class WorkflowSuspendHandler implements WorkflowHandler { */ @Override ExecuteWorkflowHandlerRes execute(ExecuteWorkflowHandlerReq request) throws InterruptedException { - return ExecuteWorkflowHandlerRes.builder() - .context(request.getContext()) - .configuration(request.getConfiguration()) - .suspend(true) - .build() + def context = request.getContext() + if (context.getBooleanValue(WorkflowContextKeyConstant.QUIET_MODE)) { + // 安静运行模式下不暂停 + log.info("skip suspend becuase of quiet mode|workflowInstanceId={}|workflowTaskId={}|" + + "appId={}", request.getInstanceId(), request.getTaskId(), request.getAppId()) + return ExecuteWorkflowHandlerRes.builder() + .context(context) + .configuration(request.getConfiguration()) + .suspend(false) + .build() + } else { + return ExecuteWorkflowHandlerRes.builder() + .context(context) + .configuration(request.getConfiguration()) + .suspend(true) + .build() + } } } diff --git a/paas/appmanager/tesla-appmanager-server/src/main/resources/jinja/default_abm_helm_component.tpl b/paas/appmanager/tesla-appmanager-server/src/main/resources/jinja/default_abm_helm_component.tpl new file mode 100644 index 00000000..ebe3dde9 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-server/src/main/resources/jinja/default_abm_helm_component.tpl @@ -0,0 +1,46 @@ +apiVersion: core.oam.dev/v1alpha2 +kind: Component +metadata: + name: abm-helm-component-{{ appId }}-{{ componentName }} + annotations: + annotations.appmanager.oam.dev/version: "{{ version }}" + labels: + labels.appmanager.oam.dev/appId: "{{ appId }}" + labels.appmanager.oam.dev/componentName: "{{ componentName }}" + labels.appmanager.oam.dev/stageId: "PLACEHOLDER_STAGE_ID" + labels.appmanager.oam.dev/clusterId: "PLACEHOLDER_CLUSTER_ID" + appId: "{{ appId }}" + componentName: "{{ componentName }}" + stageId: "PLACEHOLDER_STAGE_ID" +spec: + workload: + apiVersion: apps.abm.io/v1 + kind: {{ componentName|title }}Config + metadata: + namespace: "PLACEHOLDER_NAMESPACE_ID" + name: "PLACEHOLDER_NAME" + labels: + labels.appmanager.oam.dev/stageId: "PLACEHOLDER_STAGE_ID" + labels.appmanager.oam.dev/appId: "{{ appId }}" + labels.appmanager.oam.dev/componentName: "{{ componentName }}" + labels.appmanager.oam.dev/clusterId: "PLACEHOLDER_CLUSTER_ID" + labels.appmanager.oam.dev/appInstanceId: "PLACEHOLDER_APP_INSTANCE_ID" + labels.appmanager.oam.dev/appInstanceName: "PLACEHOLDER_APP_INSTANCE_NAME" + labels.appmanager.oam.dev/componentInstanceId: "PLACEHOLDER_COMPONENT_INSTANCE_ID" + stageId: "PLACEHOLDER_STAGE_ID" + appId: "{{ appId }}" + componentName: "{{ componentName }}" + annotations: + annotations.appmanager.oam.dev/deployAppId: "PLACEHOLDER_DEPLOY_APP_ID" + annotations.appmanager.oam.dev/deployComponentId: "PLACEHOLDER_DEPLOY_COMPONENT_ID" + annotations.appmanager.oam.dev/version: "{{ version }}" + annotations.appmanager.oam.dev/appInstanceId: "PLACEHOLDER_APP_INSTANCE_ID" + annotations.appmanager.oam.dev/appInstanceName: "PLACEHOLDER_APP_INSTANCE_NAME" + annotations.appmanager.oam.dev/componentInstanceId: "PLACEHOLDER_COMPONENT_INSTANCE_ID" + spec: + name: "" + base64Kubeconfig: "" + values: {} + valuesTemplateFilename: "" + ignoreCreateNamespace: false + rollout: {} \ No newline at end of file diff --git a/paas/appmanager/tesla-appmanager-server/src/main/resources/kaniko/kaniko.yaml.tpl b/paas/appmanager/tesla-appmanager-server/src/main/resources/kaniko/kaniko.yaml.tpl index ef414ce5..7f186329 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/resources/kaniko/kaniko.yaml.tpl +++ b/paas/appmanager/tesla-appmanager-server/src/main/resources/kaniko/kaniko.yaml.tpl @@ -2,6 +2,8 @@ apiVersion: v1 kind: Pod metadata: name: {{ POD_NAME }} + labels: + appType: build-image spec: tolerations: - effect: NoSchedule @@ -10,6 +12,18 @@ spec: - effect: NoSchedule key: sigma.ali/resource-pool operator: Exists + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + topologyKey: kubernetes.io/hostname + labelSelector: + matchExpressions: + - key: appType + operator: In + values: + - build-image containers: - name: kaniko image: {{ KANIKO_IMAGE }} diff --git a/paas/appmanager/tesla-appmanager-server/src/main/resources/mybatis/AppComponentDOMapper.xml b/paas/appmanager/tesla-appmanager-server/src/main/resources/mybatis/AppComponentDOMapper.xml new file mode 100644 index 00000000..092beb0b --- /dev/null +++ b/paas/appmanager/tesla-appmanager-server/src/main/resources/mybatis/AppComponentDOMapper.xml @@ -0,0 +1,238 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + and ${criterion.condition} + + + and ${criterion.condition} #{criterion.value} + + + and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} + + + and ${criterion.condition} + + #{listItem} + + + + + + + + + + + + + + + + + + + and ${criterion.condition} + + + and ${criterion.condition} #{criterion.value} + + + and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} + + + and ${criterion.condition} + + #{listItem} + + + + + + + + + + + + id, gmt_create, gmt_modified, namespace_id, stage_id, app_id, category, component_type, + component_name + + + + config + + + + + + delete from am_app_component + + + + + + + insert into am_app_component + + + gmt_create, + + + gmt_modified, + + + namespace_id, + + + stage_id, + + + app_id, + + + category, + + + component_type, + + + component_name, + + + config, + + + + + #{gmtCreate,jdbcType=TIMESTAMP}, + + + #{gmtModified,jdbcType=TIMESTAMP}, + + + #{namespaceId,jdbcType=VARCHAR}, + + + #{stageId,jdbcType=VARCHAR}, + + + #{appId,jdbcType=VARCHAR}, + + + #{category,jdbcType=VARCHAR}, + + + #{componentType,jdbcType=VARCHAR}, + + + #{componentName,jdbcType=VARCHAR}, + + + #{config,jdbcType=LONGVARCHAR}, + + + + + + + update am_app_component + + + id = #{record.id,jdbcType=BIGINT}, + + + gmt_create = #{record.gmtCreate,jdbcType=TIMESTAMP}, + + + gmt_modified = #{record.gmtModified,jdbcType=TIMESTAMP}, + + + namespace_id = #{record.namespaceId,jdbcType=VARCHAR}, + + + stage_id = #{record.stageId,jdbcType=VARCHAR}, + + + app_id = #{record.appId,jdbcType=VARCHAR}, + + + category = #{record.category,jdbcType=VARCHAR}, + + + component_type = #{record.componentType,jdbcType=VARCHAR}, + + + component_name = #{record.componentName,jdbcType=VARCHAR}, + + + config = #{record.config,jdbcType=LONGVARCHAR}, + + + + + + + \ No newline at end of file diff --git a/paas/appmanager/tesla-appmanager-server/src/main/resources/mybatis/mybatis-config.xml b/paas/appmanager/tesla-appmanager-server/src/main/resources/mybatis/mybatis-config.xml index 21f489bb..3da871c8 100644 --- a/paas/appmanager/tesla-appmanager-server/src/main/resources/mybatis/mybatis-config.xml +++ b/paas/appmanager/tesla-appmanager-server/src/main/resources/mybatis/mybatis-config.xml @@ -38,6 +38,7 @@ + diff --git a/paas/appmanager/tesla-appmanager-server/src/test/java/com/alibaba/tesla/appmanager/server/e2e/TestWorkflowE2E.java b/paas/appmanager/tesla-appmanager-server/src/test/java/com/alibaba/tesla/appmanager/server/e2e/TestWorkflowE2E.java index af8699d3..0edd8360 100644 --- a/paas/appmanager/tesla-appmanager-server/src/test/java/com/alibaba/tesla/appmanager/server/e2e/TestWorkflowE2E.java +++ b/paas/appmanager/tesla-appmanager-server/src/test/java/com/alibaba/tesla/appmanager/server/e2e/TestWorkflowE2E.java @@ -1,207 +1,222 @@ -//package com.alibaba.tesla.appmanager.server.e2e; -// -//import com.alibaba.fastjson.JSONObject; -//import com.alibaba.tesla.appmanager.api.provider.AppPackageTaskProvider; -//import com.alibaba.tesla.appmanager.api.provider.WorkflowInstanceProvider; -//import com.alibaba.tesla.appmanager.common.enums.AppPackageTaskStatusEnum; -//import com.alibaba.tesla.appmanager.common.enums.ComponentTypeEnum; -//import com.alibaba.tesla.appmanager.common.enums.WorkflowInstanceStateEnum; -//import com.alibaba.tesla.appmanager.common.exception.AppErrorCode; -//import com.alibaba.tesla.appmanager.common.exception.AppException; -//import com.alibaba.tesla.appmanager.domain.dto.AppPackageTaskDTO; -//import com.alibaba.tesla.appmanager.domain.dto.WorkflowInstanceDTO; -//import com.alibaba.tesla.appmanager.domain.option.WorkflowInstanceOption; -//import com.alibaba.tesla.appmanager.domain.req.apppackage.AppPackageTaskCreateReq; -//import com.alibaba.tesla.appmanager.domain.req.apppackage.AppPackageTaskQueryReq; -//import com.alibaba.tesla.appmanager.domain.req.apppackage.ComponentBinder; -//import com.alibaba.tesla.appmanager.domain.res.apppackage.AppPackageTaskCreateRes; -//import com.alibaba.tesla.appmanager.server.TestApplication; -//import com.alibaba.tesla.appmanager.spring.util.FixtureUtil; -//import com.google.common.base.Enums; -//import lombok.extern.slf4j.Slf4j; -//import org.junit.Test; -//import org.junit.runner.RunWith; -//import org.springframework.beans.factory.annotation.Autowired; -//import org.springframework.boot.SpringBootConfiguration; -//import org.springframework.boot.test.context.SpringBootTest; -//import org.springframework.test.context.junit4.SpringRunner; -// -//import java.util.Arrays; -//import java.util.Collections; -// -//import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -// -///** -// * 测试 Microservice 类型全流程 (构建 -> 部署 -> 状态感知) -// * -// * @author yaoxing.gyx@alibaba-inc.com -// */ -//@Slf4j -//@RunWith(SpringRunner.class) -//@SpringBootTest(classes = TestApplication.class) -//@SpringBootConfiguration -//@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") -//public class TestWorkflowE2E { -// -// private static final String OPERATOR = "122592"; -// private static final String APP_ID = "testapp"; -// -// @Autowired -// private AppPackageTaskProvider appPackageTaskProvider; -// -// @Autowired -// private WorkflowInstanceProvider workflowInstanceProvider; -// +package com.alibaba.tesla.appmanager.server.e2e; + +import com.alibaba.fastjson.JSONObject; +import com.alibaba.tesla.appmanager.api.provider.AppPackageTaskProvider; +import com.alibaba.tesla.appmanager.api.provider.WorkflowInstanceProvider; +import com.alibaba.tesla.appmanager.common.enums.AppPackageTaskStatusEnum; +import com.alibaba.tesla.appmanager.common.enums.ComponentTypeEnum; +import com.alibaba.tesla.appmanager.common.enums.WorkflowInstanceStateEnum; +import com.alibaba.tesla.appmanager.common.exception.AppErrorCode; +import com.alibaba.tesla.appmanager.common.exception.AppException; +import com.alibaba.tesla.appmanager.common.util.SchemaUtil; +import com.alibaba.tesla.appmanager.domain.dto.AppPackageTaskDTO; +import com.alibaba.tesla.appmanager.domain.dto.WorkflowInstanceDTO; +import com.alibaba.tesla.appmanager.domain.option.WorkflowInstanceOption; +import com.alibaba.tesla.appmanager.domain.req.apppackage.AppPackageTaskCreateReq; +import com.alibaba.tesla.appmanager.domain.req.apppackage.AppPackageTaskQueryReq; +import com.alibaba.tesla.appmanager.domain.req.apppackage.ComponentBinder; +import com.alibaba.tesla.appmanager.domain.res.apppackage.AppPackageTaskCreateRes; +import com.alibaba.tesla.appmanager.domain.schema.DeployAppSchema; +import com.alibaba.tesla.appmanager.server.TestApplication; +import com.alibaba.tesla.appmanager.spring.util.FixtureUtil; +import com.google.common.base.Enums; +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +/** + * 测试 Microservice 类型全流程 (构建 -> 部署 -> 状态感知) + * + * @author yaoxing.gyx@alibaba-inc.com + */ +@Slf4j +@RunWith(SpringRunner.class) +@SpringBootTest(classes = TestApplication.class) +@SpringBootConfiguration +@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") +public class TestWorkflowE2E { + + private static final String OPERATOR = "122592"; + private static final String APP_ID = "testapp"; + + @Autowired + private AppPackageTaskProvider appPackageTaskProvider; + + @Autowired + private WorkflowInstanceProvider workflowInstanceProvider; + // @Test // public void testMicroservice() throws Exception { // long appPackageId = buildMicroservice(); // launchMicroserviceWorkflow(appPackageId); // } -// + // @Test // public void testAbmKustomize() throws Exception { // launchKustomizeWorkflow(); // } -// -// @Test -// public void testAbmHelm() throws Exception { -// launchHelmWorkflow(); -// } -// -// /** -// * 发起服务部署 -// */ -// private long launchHelmWorkflow() throws Exception { -// String ac = FixtureUtil.getFixture("application_configuration/e2e_workflow_helm.yaml"); -// WorkflowInstanceDTO res = workflowInstanceProvider -// .launch(APP_ID, ac, WorkflowInstanceOption.builder().creator(OPERATOR).build()); -// for (int i = 0; i < 30; i++) { -// WorkflowInstanceDTO result = workflowInstanceProvider.get(res.getId(), true); -// WorkflowInstanceStateEnum status = Enums -// .getIfPresent(WorkflowInstanceStateEnum.class, result.getWorkflowStatus()).orNull(); -// assertThat(status).isNotNull(); -// switch (status) { -// case FAILURE: -// case EXCEPTION: -// case TERMINATED: -// throw new AppException(AppErrorCode.DEPLOY_ERROR, -// String.format("test launch workflow failed||order=%s", JSONObject.toJSONString(result))); -// case SUCCESS: -// return result.getId(); -// default: -// break; -// } -// Thread.sleep(5000); -// } -// throw new AppException(AppErrorCode.UNKNOWN_ERROR, "timeout applying workflow"); -// } -// -// /** -// * 发起服务部署 -// */ -// private long launchKustomizeWorkflow() throws Exception { -// String ac = FixtureUtil.getFixture("application_configuration/e2e_workflow_kustomize.yaml"); -// WorkflowInstanceDTO res = workflowInstanceProvider -// .launch(APP_ID, ac, WorkflowInstanceOption.builder().creator(OPERATOR).build()); -// for (int i = 0; i < 30; i++) { -// WorkflowInstanceDTO result = workflowInstanceProvider.get(res.getId(), true); -// WorkflowInstanceStateEnum status = Enums -// .getIfPresent(WorkflowInstanceStateEnum.class, result.getWorkflowStatus()).orNull(); -// assertThat(status).isNotNull(); -// switch (status) { -// case FAILURE: -// case EXCEPTION: -// case TERMINATED: -// throw new AppException(AppErrorCode.DEPLOY_ERROR, -// String.format("test launch workflow failed||order=%s", JSONObject.toJSONString(result))); -// case SUCCESS: -// return result.getId(); -// default: -// break; -// } -// Thread.sleep(5000); -// } -// throw new AppException(AppErrorCode.UNKNOWN_ERROR, "timeout applying workflow"); -// } -// -// /** -// * 发起服务部署 -// * -// * @return 部署单 ID -// */ -// private long launchMicroserviceWorkflow(long appPackageId) throws Exception { -// String ac = FixtureUtil.getFixture("application_configuration/e2e_workflow_microservice.yaml"); -// ac = ac.replace("PLACEHOLDER_APP_PACKAGE_ID", String.valueOf(appPackageId)); -// WorkflowInstanceDTO res = workflowInstanceProvider -// .launch(APP_ID, ac, WorkflowInstanceOption.builder().creator(OPERATOR).build()); -// for (int i = 0; i < 30; i++) { -// WorkflowInstanceDTO result = workflowInstanceProvider.get(res.getId(), true); -// WorkflowInstanceStateEnum status = Enums -// .getIfPresent(WorkflowInstanceStateEnum.class, result.getWorkflowStatus()).orNull(); -// assertThat(status).isNotNull(); -// switch (status) { -// case FAILURE: -// case EXCEPTION: -// case TERMINATED: -// throw new AppException(AppErrorCode.DEPLOY_ERROR, -// String.format("test launch workflow failed||order=%s", JSONObject.toJSONString(result))); -// case SUCCESS: -// return result.getId(); -// default: -// break; -// } -// Thread.sleep(5000); -// } -// throw new AppException(AppErrorCode.UNKNOWN_ERROR, "timeout applying workflow"); -// } -// -// /** -// * 发起微服务构建 -// * -// * @return 返回构建好的应用包 ID -// */ -// private long buildMicroservice() throws Exception { -// // 发起服务构建 -// String serverOptions = FixtureUtil.getFixture("component_package/component_options_appmanager_python_demo.json"); -// String jobOptions = FixtureUtil.getFixture("component_package/component_options_job_test.json"); -// AppPackageTaskCreateReq request = AppPackageTaskCreateReq.builder() -// .appId(APP_ID) -// .tags(Collections.singletonList("unittest")) -// .components( -// Arrays.asList( -// ComponentBinder.builder() -// .componentType(ComponentTypeEnum.K8S_MICROSERVICE) -// .componentName("server") -// .useRawOptions(true) -// .options(JSONObject.parseObject(serverOptions)) -// .build(), -// ComponentBinder.builder() -// .componentType(ComponentTypeEnum.K8S_JOB) -// .componentName("job") -// .useRawOptions(true) -// .options(JSONObject.parseObject(jobOptions)) -// .build() -// ) -// ) -// .build(); -// AppPackageTaskCreateRes task = appPackageTaskProvider.create(request, OPERATOR); -// -// // 开始任务查询逻辑 -// for (int i = 0; i < 30; i++) { -// AppPackageTaskDTO current = appPackageTaskProvider.get(AppPackageTaskQueryReq.builder() -// .appId(APP_ID) -// .appPackageTaskId(task.getAppPackageTaskId()) -// .build(), OPERATOR); -// AppPackageTaskStatusEnum status = Enums -// .getIfPresent(AppPackageTaskStatusEnum.class, current.getTaskStatus()).orNull(); -// assertThat(status).isNotNull(); -// assertThat(status).isNotEqualTo(AppPackageTaskStatusEnum.FAILURE); -// if (status == AppPackageTaskStatusEnum.SUCCESS) { -// return current.getAppPackageId(); -// } else { -// Thread.sleep(5000); -// } -// } -// throw new AppException(AppErrorCode.UNKNOWN_ERROR, "timeout creating app package"); -// } -//} \ No newline at end of file + + @Test + public void testAbmHelm() throws Exception { + launchHelmWorkflow("application_configuration/e2e_workflow_helm.yaml"); + } + + @Test + public void testApplyComponents() throws Exception { + launchHelmWorkflow("application_configuration/e2e_workflow_apply_components.yaml"); + } + + /** + * 发起服务部署 + */ + private long launchHelmWorkflow(String filename) throws Exception { + String ac = FixtureUtil.getFixture(filename); + DeployAppSchema schema = SchemaUtil.toSchema(DeployAppSchema.class, ac); + schema.getSpec().setParameterValues(new ArrayList<>()); + schema.getSpec().getParameterValues().add(DeployAppSchema.ParameterValue.builder() + .name("KUBECONFIG") + .value(System.getenv("KUBECONFIG")) + .build()); + WorkflowInstanceDTO res = workflowInstanceProvider + .launch(APP_ID, SchemaUtil.toYamlMapStr(schema), + WorkflowInstanceOption.builder().creator(OPERATOR).build()); + for (int i = 0; i < 30; i++) { + WorkflowInstanceDTO result = workflowInstanceProvider.get(res.getId(), true); + WorkflowInstanceStateEnum status = Enums + .getIfPresent(WorkflowInstanceStateEnum.class, result.getWorkflowStatus()).orNull(); + assertThat(status).isNotNull(); + switch (status) { + case FAILURE: + case EXCEPTION: + case TERMINATED: + throw new AppException(AppErrorCode.DEPLOY_ERROR, + String.format("test launch workflow failed||order=%s", JSONObject.toJSONString(result))); + case SUCCESS: + return result.getId(); + default: + break; + } + Thread.sleep(5000); + } + throw new AppException(AppErrorCode.UNKNOWN_ERROR, "timeout applying workflow"); + } + + /** + * 发起服务部署 + */ + private long launchKustomizeWorkflow() throws Exception { + String ac = FixtureUtil.getFixture("application_configuration/e2e_workflow_kustomize.yaml"); + WorkflowInstanceDTO res = workflowInstanceProvider + .launch(APP_ID, ac, WorkflowInstanceOption.builder().creator(OPERATOR).build()); + for (int i = 0; i < 30; i++) { + WorkflowInstanceDTO result = workflowInstanceProvider.get(res.getId(), true); + WorkflowInstanceStateEnum status = Enums + .getIfPresent(WorkflowInstanceStateEnum.class, result.getWorkflowStatus()).orNull(); + assertThat(status).isNotNull(); + switch (status) { + case FAILURE: + case EXCEPTION: + case TERMINATED: + throw new AppException(AppErrorCode.DEPLOY_ERROR, + String.format("test launch workflow failed||order=%s", JSONObject.toJSONString(result))); + case SUCCESS: + return result.getId(); + default: + break; + } + Thread.sleep(5000); + } + throw new AppException(AppErrorCode.UNKNOWN_ERROR, "timeout applying workflow"); + } + + /** + * 发起服务部署 + * + * @return 部署单 ID + */ + private long launchMicroserviceWorkflow(long appPackageId) throws Exception { + String ac = FixtureUtil.getFixture("application_configuration/e2e_workflow_microservice.yaml"); + ac = ac.replace("PLACEHOLDER_APP_PACKAGE_ID", String.valueOf(appPackageId)); + WorkflowInstanceDTO res = workflowInstanceProvider + .launch(APP_ID, ac, WorkflowInstanceOption.builder().creator(OPERATOR).build()); + for (int i = 0; i < 30; i++) { + WorkflowInstanceDTO result = workflowInstanceProvider.get(res.getId(), true); + WorkflowInstanceStateEnum status = Enums + .getIfPresent(WorkflowInstanceStateEnum.class, result.getWorkflowStatus()).orNull(); + assertThat(status).isNotNull(); + switch (status) { + case FAILURE: + case EXCEPTION: + case TERMINATED: + throw new AppException(AppErrorCode.DEPLOY_ERROR, + String.format("test launch workflow failed||order=%s", JSONObject.toJSONString(result))); + case SUCCESS: + return result.getId(); + default: + break; + } + Thread.sleep(5000); + } + throw new AppException(AppErrorCode.UNKNOWN_ERROR, "timeout applying workflow"); + } + + /** + * 发起微服务构建 + * + * @return 返回构建好的应用包 ID + */ + private long buildMicroservice() throws Exception { + // 发起服务构建 + String serverOptions = FixtureUtil.getFixture("component_package/component_options_appmanager_python_demo.json"); + String jobOptions = FixtureUtil.getFixture("component_package/component_options_job_test.json"); + AppPackageTaskCreateReq request = AppPackageTaskCreateReq.builder() + .appId(APP_ID) + .tags(Collections.singletonList("unittest")) + .components( + Arrays.asList( + ComponentBinder.builder() + .componentType(ComponentTypeEnum.K8S_MICROSERVICE.toString()) + .componentName("server") + .useRawOptions(true) + .options(JSONObject.parseObject(serverOptions)) + .build(), + ComponentBinder.builder() + .componentType(ComponentTypeEnum.K8S_JOB.toString()) + .componentName("job") + .useRawOptions(true) + .options(JSONObject.parseObject(jobOptions)) + .build() + ) + ) + .build(); + AppPackageTaskCreateRes task = appPackageTaskProvider.create(request, OPERATOR); + + // 开始任务查询逻辑 + for (int i = 0; i < 30; i++) { + AppPackageTaskDTO current = appPackageTaskProvider.get(AppPackageTaskQueryReq.builder() + .appId(APP_ID) + .appPackageTaskId(task.getAppPackageTaskId()) + .build(), OPERATOR); + AppPackageTaskStatusEnum status = Enums + .getIfPresent(AppPackageTaskStatusEnum.class, current.getTaskStatus()).orNull(); + assertThat(status).isNotNull(); + assertThat(status).isNotEqualTo(AppPackageTaskStatusEnum.FAILURE); + if (status == AppPackageTaskStatusEnum.SUCCESS) { + return current.getAppPackageId(); + } else { + Thread.sleep(5000); + } + } + throw new AppException(AppErrorCode.UNKNOWN_ERROR, "timeout creating app package"); + } +} \ No newline at end of file diff --git a/paas/appmanager/tesla-appmanager-server/src/test/java/com/alibaba/tesla/appmanager/server/e2e/TestWorkflowRolloutE2E.java b/paas/appmanager/tesla-appmanager-server/src/test/java/com/alibaba/tesla/appmanager/server/e2e/TestWorkflowRolloutE2E.java new file mode 100644 index 00000000..c28f8be2 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-server/src/test/java/com/alibaba/tesla/appmanager/server/e2e/TestWorkflowRolloutE2E.java @@ -0,0 +1,245 @@ +package com.alibaba.tesla.appmanager.server.e2e; + +import com.alibaba.fastjson.JSONObject; +import com.alibaba.tesla.appmanager.api.provider.WorkflowInstanceProvider; +import com.alibaba.tesla.appmanager.common.constants.WorkflowContextKeyConstant; +import com.alibaba.tesla.appmanager.common.enums.WorkflowInstanceStateEnum; +import com.alibaba.tesla.appmanager.common.exception.AppErrorCode; +import com.alibaba.tesla.appmanager.common.exception.AppException; +import com.alibaba.tesla.appmanager.common.util.SchemaUtil; +import com.alibaba.tesla.appmanager.domain.dto.WorkflowInstanceDTO; +import com.alibaba.tesla.appmanager.domain.option.WorkflowInstanceOption; +import com.alibaba.tesla.appmanager.domain.schema.DeployAppSchema; +import com.alibaba.tesla.appmanager.kubernetes.KubernetesClientFactory; +import com.alibaba.tesla.appmanager.server.TestApplication; +import com.alibaba.tesla.appmanager.spring.util.FixtureUtil; +import com.google.common.base.Enums; +import io.fabric8.kubernetes.api.model.apps.StatefulSet; +import io.fabric8.kubernetes.client.DefaultKubernetesClient; +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.ArrayList; + +import static org.assertj.core.api.AssertionsForClassTypes.*; + +/** + * 测试 Workflow 组件灰度回滚流程 E2E + * + * @author yaoxing.gyx@alibaba-inc.com + */ +@Slf4j +@RunWith(SpringRunner.class) +@SpringBootTest(classes = TestApplication.class) +@SpringBootConfiguration +@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") +public class TestWorkflowRolloutE2E { + + public static final String APP_ID = "testapp-rollout"; + public static final String OPERATOR = "122592"; + + @Autowired + private WorkflowInstanceProvider workflowInstanceProvider; + + @Autowired + private KubernetesClientFactory kubernetesClientFactory; + + /** + * 测试灰度流程 - 直接确认灰度结果并继续部署到终态 + */ + @Test + public void testContinuous() throws Exception { + WorkflowInstanceDTO res = launch("application_configuration/e2e_workflow_rollout.yaml"); + for (int i = 0; i < 30; i++) { + WorkflowInstanceDTO result = workflowInstanceProvider.get(res.getId(), true); + WorkflowInstanceStateEnum status = Enums + .getIfPresent(WorkflowInstanceStateEnum.class, result.getWorkflowStatus()).orNull(); + assertThat(status).isNotNull(); + switch (status) { + case FAILURE: + case EXCEPTION: + case TERMINATED: + throw new AppException(AppErrorCode.DEPLOY_ERROR, + String.format("test launch workflow failed||order=%s", JSONObject.toJSONString(result))); + case SUSPEND: { + // 确认当前 statefulset 已经被置为 partition==1 + DefaultKubernetesClient client = kubernetesClientFactory.getByKubeConfig(System.getenv("KUBECONFIG")); + StatefulSet sts = client.apps() + .statefulSets() + .inNamespace("abm-daily") + .withName("appmanager-helm-e2e-rollout-helm-demo-chart") + .get(); + Integer partition = sts.getSpec().getUpdateStrategy().getRollingUpdate().getPartition(); + assertThat(partition).isEqualTo(1); + + // 继续 rolling + JSONObject context = new JSONObject(); + context.put("continueRollout", true); + context.put("rollback", false); + workflowInstanceProvider.putContext(res.getId(), context); + log.info("rollout context has put into workflow context|workflowInstanceId={}|context={}", + res.getId(), JSONObject.toJSONString(context)); + workflowInstanceProvider.resume(res.getId()); + break; + } + case SUCCESS: { + // 确认当前 statefulset 已经被置为 partition==0 + DefaultKubernetesClient client = kubernetesClientFactory.getByKubeConfig(System.getenv("KUBECONFIG")); + StatefulSet sts = client.apps() + .statefulSets() + .inNamespace("abm-daily") + .withName("appmanager-helm-e2e-rollout-helm-demo-chart") + .get(); + Integer partition = sts.getSpec().getUpdateStrategy().getRollingUpdate().getPartition(); + assertThat(partition).isEqualTo(0); + return; + } + default: + break; + } + Thread.sleep(5000); + } + } + + /** + * 测试灰度流程 - 直接确认灰度结果并终止当前流程 + */ + @Test + public void testTerminate() throws Exception { + WorkflowInstanceDTO res = launch("application_configuration/e2e_workflow_rollout.yaml"); + for (int i = 0; i < 30; i++) { + WorkflowInstanceDTO result = workflowInstanceProvider.get(res.getId(), true); + WorkflowInstanceStateEnum status = Enums + .getIfPresent(WorkflowInstanceStateEnum.class, result.getWorkflowStatus()).orNull(); + assertThat(status).isNotNull(); + switch (status) { + case FAILURE: + case EXCEPTION: + case SUCCESS: + throw new AppException(AppErrorCode.DEPLOY_ERROR, + String.format("test launch workflow failed||order=%s", JSONObject.toJSONString(result))); + case TERMINATED: { + // 确认当前 statefulset 还是 partition==1 + DefaultKubernetesClient client = kubernetesClientFactory.getByKubeConfig(System.getenv("KUBECONFIG")); + StatefulSet sts = client.apps() + .statefulSets() + .inNamespace("abm-daily") + .withName("appmanager-helm-e2e-rollout-helm-demo-chart") + .get(); + Integer partition = sts.getSpec().getUpdateStrategy().getRollingUpdate().getPartition(); + assertThat(partition).isEqualTo(1); + return; + } + case SUSPEND: { + // 确认当前 statefulset 已经被置为 partition==1 + DefaultKubernetesClient client = kubernetesClientFactory.getByKubeConfig(System.getenv("KUBECONFIG")); + StatefulSet sts = client.apps() + .statefulSets() + .inNamespace("abm-daily") + .withName("appmanager-helm-e2e-rollout-helm-demo-chart") + .get(); + Integer partition = sts.getSpec().getUpdateStrategy().getRollingUpdate().getPartition(); + assertThat(partition).isEqualTo(1); + + // 测试直接终止 + JSONObject context = new JSONObject(); + context.put("continueRollout", false); + context.put("rollback", false); + workflowInstanceProvider.putContext(res.getId(), context); + log.info("rollout context has put into workflow context|workflowInstanceId={}|context={}", + res.getId(), JSONObject.toJSONString(context)); + workflowInstanceProvider.resume(res.getId()); + break; + } + default: + break; + } + Thread.sleep(5000); + } + } + + /** + * 测试灰度流程 - 回滚到上一次成功的部署流程 + */ + @Test + public void testRollback() throws Exception { + // 先做一次成功的部署 + testContinuous(); + + WorkflowInstanceDTO res = launch("application_configuration/e2e_workflow_rollout.yaml"); + for (int i = 0; i < 30; i++) { + WorkflowInstanceDTO result = workflowInstanceProvider.get(res.getId(), true); + WorkflowInstanceStateEnum status = Enums + .getIfPresent(WorkflowInstanceStateEnum.class, result.getWorkflowStatus()).orNull(); + assertThat(status).isNotNull(); + switch (status) { + case FAILURE: + case EXCEPTION: + case SUCCESS: + throw new AppException(AppErrorCode.DEPLOY_ERROR, + String.format("test launch workflow failed||order=%s", JSONObject.toJSONString(result))); + case TERMINATED: { + // 确认当前 statefulset 已经被置为 partition==0 + DefaultKubernetesClient client = kubernetesClientFactory.getByKubeConfig(System.getenv("KUBECONFIG")); + StatefulSet sts = client.apps() + .statefulSets() + .inNamespace("abm-daily") + .withName("appmanager-helm-e2e-rollout-helm-demo-chart") + .get(); + Integer partition = sts.getSpec().getUpdateStrategy().getRollingUpdate().getPartition(); + assertThat(partition).isEqualTo(0); + WorkflowInstanceDTO instance = workflowInstanceProvider.get(res.getId(), true); + assertThat(instance.getWorkflowContext().get(WorkflowContextKeyConstant.CANCEL_EXECUTION)).isEqualTo(true); + return; + } + case SUSPEND: { + // 确认当前 statefulset 已经被置为 partition==1 + DefaultKubernetesClient client = kubernetesClientFactory.getByKubeConfig(System.getenv("KUBECONFIG")); + StatefulSet sts = client.apps() + .statefulSets() + .inNamespace("abm-daily") + .withName("appmanager-helm-e2e-rollout-helm-demo-chart") + .get(); + Integer partition = sts.getSpec().getUpdateStrategy().getRollingUpdate().getPartition(); + assertThat(partition).isEqualTo(1); + + // 执行回滚动作 + JSONObject context = new JSONObject(); + context.put("continueRollout", false); + context.put("rollback", true); + workflowInstanceProvider.putContext(res.getId(), context); + log.info("rollout context has put into workflow context|workflowInstanceId={}|context={}", + res.getId(), JSONObject.toJSONString(context)); + workflowInstanceProvider.resume(res.getId()); + break; + } + default: + break; + } + Thread.sleep(5000); + } + } + + /** + * 发起服务部署 (使用环境变量 KUBECONFIG 进行连接) + */ + private WorkflowInstanceDTO launch(String filename) throws Exception { + String ac = FixtureUtil.getFixture(filename); + DeployAppSchema schema = SchemaUtil.toSchema(DeployAppSchema.class, ac); + schema.getSpec().setParameterValues(new ArrayList<>()); + schema.getSpec().getParameterValues().add(DeployAppSchema.ParameterValue.builder() + .name("KUBECONFIG") + .value(System.getenv("KUBECONFIG")) + .build()); + return workflowInstanceProvider.launch(APP_ID, SchemaUtil.toYamlMapStr(schema), + WorkflowInstanceOption.builder() + .category("DEPLOY") + .creator(OPERATOR) + .build()); + } +} diff --git a/paas/appmanager/tesla-appmanager-server/src/test/java/com/alibaba/tesla/appmanager/server/job/TestBuildStatusSafetyJob.java b/paas/appmanager/tesla-appmanager-server/src/test/java/com/alibaba/tesla/appmanager/server/job/TestBuildStatusSafetyJob.java index e17d2133..7abe5848 100644 --- a/paas/appmanager/tesla-appmanager-server/src/test/java/com/alibaba/tesla/appmanager/server/job/TestBuildStatusSafetyJob.java +++ b/paas/appmanager/tesla-appmanager-server/src/test/java/com/alibaba/tesla/appmanager/server/job/TestBuildStatusSafetyJob.java @@ -35,7 +35,7 @@ public class TestBuildStatusSafetyJob { private static final int BUILD_MAX_RUNNING_SECONDS = 3600; private static final String BUCKET_NAME = "appmanager"; private static final String APP_ID = "testapp"; - private static final ComponentTypeEnum COMPONENT_TYPE = ComponentTypeEnum.K8S_MICROSERVICE; + private static final String COMPONENT_TYPE = ComponentTypeEnum.K8S_MICROSERVICE.toString(); private static final String COMPONENT_NAME = "testserver"; private static final String PACKAGE_CREATOR = "SYSTEM"; private static final String PACKAGE_VERSION = "2.1.1+20220201234212"; diff --git a/paas/appmanager/tesla-appmanager-server/src/test/java/com/alibaba/tesla/appmanager/server/service/pack/TestServicePackDoComponentPackageCreate.java b/paas/appmanager/tesla-appmanager-server/src/test/java/com/alibaba/tesla/appmanager/server/service/pack/TestServicePackDoComponentPackageCreate.java index 0e50557f..d0e157f6 100644 --- a/paas/appmanager/tesla-appmanager-server/src/test/java/com/alibaba/tesla/appmanager/server/service/pack/TestServicePackDoComponentPackageCreate.java +++ b/paas/appmanager/tesla-appmanager-server/src/test/java/com/alibaba/tesla/appmanager/server/service/pack/TestServicePackDoComponentPackageCreate.java @@ -13,6 +13,7 @@ import com.alibaba.tesla.appmanager.meta.k8smicroservice.service.K8sMicroservice import com.alibaba.tesla.appmanager.server.repository.AppPackageTaskRepository; import com.alibaba.tesla.appmanager.server.repository.ComponentPackageTaskRepository; import com.alibaba.tesla.appmanager.server.service.appaddon.AppAddonService; +import com.alibaba.tesla.appmanager.server.service.appcomponent.AppComponentService; import com.alibaba.tesla.appmanager.server.service.appmeta.AppMetaService; import com.alibaba.tesla.appmanager.server.service.apppackage.AppPackageTaskService; import com.alibaba.tesla.appmanager.server.service.pack.impl.PackServiceImpl; @@ -36,7 +37,7 @@ public class TestServicePackDoComponentPackageCreate { private static final String APP_ID = "testapp"; private static final String NAMESPACE_ID = "default"; private static final String STAGE_ID = "pre"; - private static final ComponentTypeEnum COMPONENT_TYPE = ComponentTypeEnum.INTERNAL_ADDON; + private static final String COMPONENT_TYPE = ComponentTypeEnum.INTERNAL_ADDON.toString(); private static final String COMPONENT_NAME = "productops"; private static final String OPERATOR = "SYSTEM"; private static final String PACKAGE_VERSION = "3.5.5+20220201234212"; @@ -69,6 +70,9 @@ public class TestServicePackDoComponentPackageCreate { @Mock private SystemProperties systemProperties; + @Mock + private AppComponentService appComponentService; + private PackService packService; @Before @@ -84,7 +88,8 @@ public class TestServicePackDoComponentPackageCreate { appAddonService, appMetaService, helmMetaService, - systemProperties + systemProperties, + appComponentService )); Mockito.doReturn(new JSONObject()) .when(packService) @@ -101,9 +106,8 @@ public class TestServicePackDoComponentPackageCreate { .stageId(STAGE_ID) .operator(OPERATOR) .component(ComponentBinder.builder() - .componentType(COMPONENT_TYPE) + .componentType(COMPONENT_TYPE.toString()) .componentName(COMPONENT_NAME) - .componentLabel(COMPONENT_NAME) .version(PACKAGE_VERSION) .branch("master") .useRawOptions(false) diff --git a/paas/appmanager/tesla-appmanager-server/src/test/java/com/alibaba/tesla/appmanager/server/util/TestUtilDeployment.java b/paas/appmanager/tesla-appmanager-server/src/test/java/com/alibaba/tesla/appmanager/server/util/TestUtilDeployment.java index c97cf59a..41575a81 100644 --- a/paas/appmanager/tesla-appmanager-server/src/test/java/com/alibaba/tesla/appmanager/server/util/TestUtilDeployment.java +++ b/paas/appmanager/tesla-appmanager-server/src/test/java/com/alibaba/tesla/appmanager/server/util/TestUtilDeployment.java @@ -2,6 +2,7 @@ package com.alibaba.tesla.appmanager.server.util; import com.alibaba.fastjson.JSON; import com.alibaba.tesla.appmanager.common.util.DeploymentUtil; +import com.alibaba.tesla.appmanager.common.util.SchemaUtil; import lombok.extern.slf4j.Slf4j; import org.junit.Test; diff --git a/paas/appmanager/tesla-appmanager-server/src/test/resources/application.properties b/paas/appmanager/tesla-appmanager-server/src/test/resources/application.properties index ddef54bb..85824767 100644 --- a/paas/appmanager/tesla-appmanager-server/src/test/resources/application.properties +++ b/paas/appmanager/tesla-appmanager-server/src/test/resources/application.properties @@ -2,14 +2,15 @@ spring.application.name=tesla-appmanager project.name=${spring.application.name} server.port=7001 spring.main.allow-circular-references=true +spring.mvc.pathmatch.matching-strategy=ant-path-matcher # Alimonitor spring.alimonitor.filter.url-patterns=/query,/command,/file,/plugin # TDDL -spring.datasource.url=jdbc:mysql://mysql:3306/appmanager?useUnicode=true&characterEncoding=utf-8&useSSL=false +spring.datasource.url=jdbc:mysql://${DB_HOST}:${DB_PORT}/${DB_NAME}?useUnicode=true&characterEncoding=utf-8&useSSL=false spring.datasource.driver-class-name=com.mysql.jdbc.Driver -spring.datasource.hikari.jdbc-url=jdbc:mysql://mysql:3306/appmanager?useUnicode=true&characterEncoding=utf-8&useSSL=false -spring.datasource.hikari.username=root -spring.datasource.hikari.password=TeslaAdmin123456 +spring.datasource.hikari.jdbc-url=jdbc:mysql://${DB_HOST}:${DB_PORT}/${DB_NAME}?useUnicode=true&characterEncoding=utf-8&useSSL=false +spring.datasource.hikari.username=${DB_USER} +spring.datasource.hikari.password=${DB_PASSWORD} spring.datasource.hikari.driver-class-name=com.mysql.jdbc.Driver # MyBatis mybatis.config-location=classpath:/mybatis/mybatis-config.xml @@ -22,9 +23,9 @@ management.endpoint.prometheus.enabled=true management.metrics.export.prometheus.enabled=true # Storage - Bucket appmanager.package.driver=minio -appmanager.package.endpoint=minio:9000 -appmanager.package.access-key=super_access_key -appmanager.package.secret-key=super_secret_key +appmanager.package.endpoint=${MINIO_ENDPOINT} +appmanager.package.access-key=${MINIO_ACCESS_ID} +appmanager.package.secret-key=${MINIO_SECRET_KEY} appmanager.package.bucket-name=appmanager appmanager.package.in-unit-test=true # Auth @@ -32,7 +33,7 @@ appmanager.auth.super-access-id=superadmin appmanager.auth.super-access-secret=123456 appmanager.auth.super-client-id=superclient appmanager.auth.super-client-secret=123456 -appmanager.auth.jwt-secret-key=5e6b47fa-f905-4d1f-b1a9-3d8e06065426 +appmanager.auth.jwt-secret-key=test-secret-key # Security spring.security.xss.enabled=false spring.security.json.enabled=false @@ -55,21 +56,21 @@ tesla.dag.localnode.runMaxSize=1000 dag.hot.load.jar.interval.second=2 dag.usage.mode=jar # OSS -dag.hot.load.jar.minio.endpoint=http://minio:9000 -dag.hot.load.jar.minio.accessKeyId=super_access_key -dag.hot.load.jar.minio.accessKeySecret=super_secret_key +dag.hot.load.jar.minio.endpoint=http://${MINIO_ENDPOINT} +dag.hot.load.jar.minio.accessKeyId=${MINIO_ACCESS_ID} +dag.hot.load.jar.minio.accessKeySecret=${MINIO_SECRET_KEY} dag.hot.load.jar.minio.bucket.name=appmanager-dag # redis -spring.redis.host=redis -spring.redis.port=6379 -spring.redis.database=0 -spring.redis.password=bigdatabcc +spring.redis.host=${REDIS_HOST} +spring.redis.port=${REDIS_PORT} +spring.redis.database=${REDIS_DATABASE} +spring.redis.password=${REDIS_PASSWORD} # Redis -appmanager.redis.address=redis://:bigdatabcc@redis:6379/0 +appmanager.redis.address=redis://:${REDIS_PASSWORD}@${REDIS_HOST}:${REDIS_PORT}/${REDIS_DATABASE} # CI -appmanager.image-builder.default-ci-account=${IMAGE_BUILDER_DEFAULT_CI_ACCOUNT:} -appmanager.image-builder.default-ci-token=${IMAGE_BUILDER_DEFAULT_CI_TOKEN:} -appmanager.image-builder.docker-bin=docker +appmanager.image-builder.default-ci-account=${CI_ACCOUNT} +appmanager.image-builder.default-ci-token=${CI_TOKEN} +appmanager.image-builder.docker-bin=${DOCKER_BIN} # env tesla.env=daily # System @@ -98,7 +99,7 @@ appmanager.cron-job.informer-manager-refresh=${CRON_JOB_INFORMER_MANAGER_REFRESH appmanager.cron-job.workflow-remote-deploy-app-refresh=${CRON_JOB_WORKFLOW_REMOTE_DEPLOY_APP_REFRESH:0/20 * * * * *} # Cluster Configuration appmanager.cluster.local=false -appmanager.cluster.docker-daemon=tcp://127.0.0.1:2375 +appmanager.cluster.docker-daemon=tcp://${DOCKER_DAEMON} logging.level.com.alibaba.tesla.dag=ERROR logging.level.job=ERROR logging.level.monitor=ERROR diff --git a/paas/appmanager/tesla-appmanager-server/src/test/resources/fixtures/application_configuration/e2e_workflow_apply_components.yaml b/paas/appmanager/tesla-appmanager-server/src/test/resources/fixtures/application_configuration/e2e_workflow_apply_components.yaml new file mode 100644 index 00000000..bcdacdd6 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-server/src/test/resources/fixtures/application_configuration/e2e_workflow_apply_components.yaml @@ -0,0 +1,73 @@ +apiVersion: core.oam.dev/v1alpha2 +kind: ApplicationConfiguration +metadata: + annotations: + appId: testapp + appInstanceName: "test-app-instance" + name: deploy-workflow +spec: + components: + - revisionName: ABM_HELM|helm-demo-chart@0.0.1@test|_ + policies: + - name: topology-e2e-env + type: topology + properties: + namespace: "abm-daily" + - type: override + name: override-e2e-env + properties: + components: + - revisionName: ABM_HELM|helm-demo-chart@0.0.1@test|_ + dataInputs: + - valueFrom: + dataOutputName: "Global.KUBECONFIG" + toFieldPaths: + - spec.base64Kubeconfig + parameterValues: + - name: name + value: "appmanager-helm-e2e" + toFieldPaths: + - spec.name + - name: ignoreCreateNamespace + value: true + toFieldPaths: + - spec.ignoreCreateNamespace + - name: values + value: + tolerations: + - effect: NoSchedule + key: sigma.ali/is-ecs + operator: Exists + - effect: NoSchedule + key: sigma.ali/resource-pool + operator: Equal + value: sigma_public + resources: + limits: + cpu: "1" + memory: "2Gi" + image: + repository: "reg.docker.alibaba-inc.com/abm-aone/nginx" + tag: "latest" + toFieldPaths: + - spec.values + workflow: + steps: + - type: apply-components + name: deploy-env-e2e-1 + properties: + components: + - type: ABM_HELM + name: helm-demo-chart@0.0.1@test + policies: + - "topology-e2e-env" + - "override-e2e-env" + - type: apply-components + name: deploy-env-e2e-2 + properties: + components: + - type: ABM_HELM + name: helm-demo-chart@0.0.1@test + policies: + - "topology-e2e-env" + - "override-e2e-env" \ No newline at end of file diff --git a/paas/appmanager/tesla-appmanager-server/src/test/resources/fixtures/application_configuration/e2e_workflow_helm.yaml b/paas/appmanager/tesla-appmanager-server/src/test/resources/fixtures/application_configuration/e2e_workflow_helm.yaml index 09f3ed47..d508d238 100644 --- a/paas/appmanager/tesla-appmanager-server/src/test/resources/fixtures/application_configuration/e2e_workflow_helm.yaml +++ b/paas/appmanager/tesla-appmanager-server/src/test/resources/fixtures/application_configuration/e2e_workflow_helm.yaml @@ -6,86 +6,56 @@ metadata: appInstanceName: "test-app-instance" name: deploy-workflow spec: - parameterValues: - - name: "PRE_KUBECONFIG" - value: "" - - name: "PROD_KUBECONFIG" - value: "" components: - revisionName: ABM_HELM|helm-demo-chart@0.0.1@test|_ - - revisionName: SCRIPT|helm-demo-chart|_ - dataOutputs: - - name: testvalue - fieldPath: "spec.dataOutputs.a" - parameterValues: - - name: scriptName - value: "helm-demo-chart-script/v1" - toFieldPaths: - - "spec.scriptName" - dependencies: - - component: ABM_HELM|helm-demo-chart@0.0.1@test policies: - - name: topology-pre-env + - name: topology-e2e-env type: topology properties: - namespace: "pre-env" + namespace: "abm-daily" - type: override - name: override-pre-env + name: override-e2e-env properties: components: - revisionName: ABM_HELM|helm-demo-chart@0.0.1@test|_ dataInputs: - valueFrom: - dataOutputName: "Global.PRE_KUBECONFIG" + dataOutputName: "Global.KUBECONFIG" toFieldPaths: - spec.base64Kubeconfig parameterValues: - name: name - value: "testhelm-pre" + value: "appmanager-helm-e2e" toFieldPaths: - spec.name - - revisionName: SCRIPT|helm-demo-chart|_ - dataInputs: - - valueFrom: - dataOutputName: "Global.PRE_KUBECONFIG" + - name: ignoreCreateNamespace + value: true toFieldPaths: - - spec.base64Kubeconfig - - name: topology-prod-env - type: topology - properties: - namespace: "prod-env" - - type: override - name: override-prod-env - properties: - components: - - revisionName: ABM_HELM|helm-demo-chart@0.0.1@test|_ - dataInputs: - - valueFrom: - dataOutputName: "Global.PROD_KUBECONFIG" + - spec.ignoreCreateNamespace + - name: values + value: + tolerations: + - effect: NoSchedule + key: sigma.ali/is-ecs + operator: Exists + - effect: NoSchedule + key: sigma.ali/resource-pool + operator: Equal + value: sigma_public + resources: + limits: + cpu: "1" + memory: "2Gi" + image: + repository: "reg.docker.alibaba-inc.com/abm-aone/nginx" + tag: "latest" toFieldPaths: - - spec.base64Kubeconfig - parameterValues: - - name: name - value: "testhelm-prod" - toFieldPaths: - - spec.name - - revisionName: SCRIPT|helm-demo-chart|_ - dataInputs: - - valueFrom: - dataOutputName: "Global.PROD_KUBECONFIG" - toFieldPaths: - - spec.base64Kubeconfig + - spec.values workflow: steps: - type: deploy - name: deploy-env-pre + name: deploy-env-e2e properties: policies: - - "topology-pre-env" - - "override-pre-env" - - type: deploy - name: deploy-env-prod - properties: - policies: - - "topology-prod-env" - - "override-prod-env" + - "topology-e2e-env" + - "override-e2e-env" diff --git a/paas/appmanager/tesla-appmanager-server/src/test/resources/fixtures/application_configuration/e2e_workflow_rollout.yaml b/paas/appmanager/tesla-appmanager-server/src/test/resources/fixtures/application_configuration/e2e_workflow_rollout.yaml new file mode 100644 index 00000000..791267b9 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-server/src/test/resources/fixtures/application_configuration/e2e_workflow_rollout.yaml @@ -0,0 +1,79 @@ +apiVersion: core.oam.dev/v1alpha2 +kind: ApplicationConfiguration +metadata: + annotations: + appId: testapp + appInstanceName: "test-app-instance" + name: deploy-workflow +spec: + components: + - revisionName: ABM_HELM|helm-demo-chart@0.0.3@test|_ + policies: + - name: topology-e2e-env + type: topology + properties: + namespace: "abm-daily" + - type: override + name: override-e2e-env + properties: + components: + - revisionName: ABM_HELM|helm-demo-chart@0.0.3@test|_ + dataInputs: + - valueFrom: + dataOutputName: "Global.KUBECONFIG" + toFieldPaths: + - spec.base64Kubeconfig + parameterValues: + - name: name + value: "appmanager-helm-e2e-rollout" + toFieldPaths: + - spec.name + - name: ignoreCreateNamespace + value: true + toFieldPaths: + - spec.ignoreCreateNamespace + - name: values + value: + tolerations: + - effect: NoSchedule + key: sigma.ali/is-ecs + operator: Exists + - effect: NoSchedule + key: sigma.ali/resource-pool + operator: Equal + value: sigma_public + resources: + limits: + cpu: "0.5" + memory: "1Gi" + image: + repository: "reg.docker.alibaba-inc.com/abm-aone/nginx" + tag: "latest" + replicaCount: 3 + toFieldPaths: + - spec.values + workflow: + steps: + - type: apply-components + properties: + policies: + - topology-e2e-env + - override-e2e-env + components: + - type: ABM_HELM + name: helm-demo-chart@0.0.3@test + rollout: + type: partition + properties: + partition: "1" + name: "abmRolloutPartition" + - type: suspend # 此处将整个 workflow 置为暂停状态,这个时候需要外部通过 PUT /workflow/{instanceId}/context 来进一步设置变量,参考下面的说明 + - type: rollout-promotion # 此处根据外界设置的 context 中的 continueRollout / rollback 决定是怎么走 (三种类型) + - type: apply-components # 如果上一步决定了继续向下执行的话,那么会继续正常部署 + properties: + policies: + - topology-e2e-env + - override-e2e-env + components: + - type: ABM_HELM + name: helm-demo-chart@0.0.3@test diff --git a/paas/appmanager/tesla-appmanager-server/src/test/resources/logback-spring.xml b/paas/appmanager/tesla-appmanager-server/src/test/resources/logback-spring.xml index 2dc7a13b..7319ba14 100644 --- a/paas/appmanager/tesla-appmanager-server/src/test/resources/logback-spring.xml +++ b/paas/appmanager/tesla-appmanager-server/src/test/resources/logback-spring.xml @@ -11,6 +11,16 @@ + + + + + + + + + + diff --git a/paas/appmanager/tesla-appmanager-spring/pom.xml b/paas/appmanager/tesla-appmanager-spring/pom.xml index 15afed39..6e6ac497 100644 --- a/paas/appmanager/tesla-appmanager-spring/pom.xml +++ b/paas/appmanager/tesla-appmanager-spring/pom.xml @@ -7,7 +7,7 @@ com.alibaba.tesla tesla-appmanager - 1.0.4-SNAPSHOT + 1.0.5-SNAPSHOT ../pom.xml @@ -23,6 +23,14 @@ org.springframework.boot spring-boot-starter-data-redis + + com.github.xiaoymin + knife4j-springdoc-ui + + + org.springdoc + springdoc-openapi-ui + org.projectlombok lombok diff --git a/paas/appmanager/tesla-appmanager-spring/src/main/java/com/alibaba/tesla/appmanager/spring/config/Knife4jConfig.java b/paas/appmanager/tesla-appmanager-spring/src/main/java/com/alibaba/tesla/appmanager/spring/config/Knife4jConfig.java new file mode 100644 index 00000000..a2a23bd2 --- /dev/null +++ b/paas/appmanager/tesla-appmanager-spring/src/main/java/com/alibaba/tesla/appmanager/spring/config/Knife4jConfig.java @@ -0,0 +1,30 @@ +package com.alibaba.tesla.appmanager.spring.config; + +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Info; +import org.springdoc.core.GroupedOpenApi; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class Knife4jConfig { + + @Bean + public GroupedOpenApi userApi(){ + String[] paths = { "/**" }; + String[] packagedToMatch = { "com.alibaba.tesla.appmanager" }; + return GroupedOpenApi.builder() + .group("AppManager") + .pathsToMatch(paths) + .packagesToScan(packagedToMatch).build(); + } + @Bean + public OpenAPI customOpenAPI() { + return new OpenAPI() + .info(new Info() + .title("AppManager API") + .version("1.0") + .description("AppManager API") + .termsOfService("https://github.com/alibaba/SREWorks")); + } +} \ No newline at end of file diff --git a/paas/appmanager/tesla-appmanager-spring/src/main/java/com/alibaba/tesla/appmanager/spring/config/AppManagerWebConfig.java b/paas/appmanager/tesla-appmanager-spring/src/main/java/com/alibaba/tesla/appmanager/spring/config/OctetStreamHttpMessageConverter.java similarity index 63% rename from paas/appmanager/tesla-appmanager-spring/src/main/java/com/alibaba/tesla/appmanager/spring/config/AppManagerWebConfig.java rename to paas/appmanager/tesla-appmanager-spring/src/main/java/com/alibaba/tesla/appmanager/spring/config/OctetStreamHttpMessageConverter.java index bc835147..36268e2f 100644 --- a/paas/appmanager/tesla-appmanager-spring/src/main/java/com/alibaba/tesla/appmanager/spring/config/AppManagerWebConfig.java +++ b/paas/appmanager/tesla-appmanager-spring/src/main/java/com/alibaba/tesla/appmanager/spring/config/OctetStreamHttpMessageConverter.java @@ -1,32 +1,31 @@ package com.alibaba.tesla.appmanager.spring.config; import lombok.extern.slf4j.Slf4j; -import org.apache.tomcat.util.http.fileupload.IOUtils; +import org.apache.commons.io.IOUtils; +import org.springframework.boot.autoconfigure.http.HttpMessageConverters; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpOutputMessage; import org.springframework.http.MediaType; import org.springframework.http.converter.AbstractHttpMessageConverter; -import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.http.converter.HttpMessageNotWritableException; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; import java.io.IOException; import java.io.InputStream; -import java.util.List; @Configuration @Slf4j -class AppManagerWebConfig extends WebMvcConfigurationSupport { +class OctetStreamHttpMessageConverter { /** * 增加 Message 转换器,为流式处理文件提供支持 */ - @Override - protected void configureMessageConverters(List> converters) { - super.addDefaultHttpMessageConverters(converters); - converters.add(new AbstractHttpMessageConverter(MediaType.APPLICATION_OCTET_STREAM) { + @Bean + public HttpMessageConverters octetStreamConverter() { + AbstractHttpMessageConverter converter + = new AbstractHttpMessageConverter<>(MediaType.APPLICATION_OCTET_STREAM) { @Override protected boolean supports(Class clazz) { return InputStream.class.isAssignableFrom(clazz); @@ -34,16 +33,16 @@ class AppManagerWebConfig extends WebMvcConfigurationSupport { @Override protected InputStream readInternal(Class clazz, HttpInputMessage inputMessage) throws - IOException, HttpMessageNotReadableException { + IOException, HttpMessageNotReadableException { return inputMessage.getBody(); } @Override protected void writeInternal(InputStream inputStream, HttpOutputMessage outputMessage) throws IOException, - HttpMessageNotWritableException { + HttpMessageNotWritableException { IOUtils.copy(inputStream, outputMessage.getBody()); } - }); - super.configureMessageConverters(converters); + }; + return new HttpMessageConverters(converter); } } \ No newline at end of file diff --git a/paas/appmanager/tesla-appmanager-start-standalone/pom.xml b/paas/appmanager/tesla-appmanager-start-standalone/pom.xml index c64c8e1a..237d7dcc 100644 --- a/paas/appmanager/tesla-appmanager-start-standalone/pom.xml +++ b/paas/appmanager/tesla-appmanager-start-standalone/pom.xml @@ -5,7 +5,7 @@ tesla-appmanager com.alibaba.tesla - 1.0.4-SNAPSHOT + 1.0.5-SNAPSHOT ../pom.xml 4.0.0 @@ -125,6 +125,7 @@ maven-dependency-plugin + package unpack diff --git a/paas/appmanager/tesla-appmanager-start-standalone/src/main/resources/application-docker.properties b/paas/appmanager/tesla-appmanager-start-standalone/src/main/resources/application-docker.properties index c52f0686..bfbd3a3b 100644 --- a/paas/appmanager/tesla-appmanager-start-standalone/src/main/resources/application-docker.properties +++ b/paas/appmanager/tesla-appmanager-start-standalone/src/main/resources/application-docker.properties @@ -2,6 +2,7 @@ project.name=abm-${STAGE_ID:unknown}-appmanager-oxs spring.application.name=abm-${STAGE_ID:unknown}-appmanager-oxs server.port=7001 spring.main.allow-circular-references=true +spring.mvc.pathmatch.matching-strategy=ant-path-matcher # Alimonitor spring.alimonitor.filter.url-patterns=/query,/command,/file,/plugin # TDDL @@ -125,6 +126,7 @@ appmanager.image-builder.default-ci-account=${IMAGE_BUILDER_DEFAULT_CI_ACCOUNT:} appmanager.image-builder.default-ci-token=${IMAGE_BUILDER_DEFAULT_CI_TOKEN:} appmanager.image-builder.arm-remote-daemon=${ARM_DOCKER_HOST:} # System Configuration +appmanager.system.enable-openapi-ui=${ENABLE_OPENAPI_UI:false} appmanager.system.env-id=${ABM_CLUSTER} appmanager.system.enable-kaniko=${ENABLE_KANIKO:false} appmanager.system.enable-worker=${ENABLE_WORKER:true} diff --git a/paas/appmanager/tesla-appmanager-storage/pom.xml b/paas/appmanager/tesla-appmanager-storage/pom.xml index c2b49284..b3c358b5 100644 --- a/paas/appmanager/tesla-appmanager-storage/pom.xml +++ b/paas/appmanager/tesla-appmanager-storage/pom.xml @@ -5,7 +5,8 @@ tesla-appmanager com.alibaba.tesla - 1.0.4-SNAPSHOT + 1.0.5-SNAPSHOT + ../pom.xml 4.0.0 diff --git a/paas/appmanager/tesla-appmanager-trait/pom.xml b/paas/appmanager/tesla-appmanager-trait/pom.xml index 2b87f4da..2e2e7210 100644 --- a/paas/appmanager/tesla-appmanager-trait/pom.xml +++ b/paas/appmanager/tesla-appmanager-trait/pom.xml @@ -7,7 +7,8 @@ com.alibaba.tesla tesla-appmanager - 1.0.4-SNAPSHOT + 1.0.5-SNAPSHOT + ../pom.xml tesla-appmanager-trait diff --git a/paas/appmanager/tesla-appmanager-trait/src/main/java/com/alibaba/tesla/appmanager/trait/api/TraitProviderImpl.java b/paas/appmanager/tesla-appmanager-trait/src/main/java/com/alibaba/tesla/appmanager/trait/api/TraitProviderImpl.java index 50c92113..277aad95 100644 --- a/paas/appmanager/tesla-appmanager-trait/src/main/java/com/alibaba/tesla/appmanager/trait/api/TraitProviderImpl.java +++ b/paas/appmanager/tesla-appmanager-trait/src/main/java/com/alibaba/tesla/appmanager/trait/api/TraitProviderImpl.java @@ -57,22 +57,33 @@ public class TraitProviderImpl implements TraitProvider { @Override public TraitDTO get(TraitQueryReq request, String operator) { TraitQueryCondition condition = TraitQueryCondition.builder() - .name(request.getName()) - .withBlobs(true) - .build(); + .name(request.getName()) + .withBlobs(true) + .build(); TraitDO result = traitService.get(condition, operator); return traitDtoConvert.to(result); } /** * 向系统中新增或更新一个 Trait - * @param request 记录的值 + * + * @param request 记录的值 * @param operator 操作人 */ @Override public void apply(String request, String operator) { TraitDefinition traitDefinition = SchemaUtil.toSchema(TraitDefinition.class, request); + apply(traitDefinition, operator); + } + /** + * 向系统中新增或更新一个 Trait + * + * @param traitDefinition TraitDefinition + * @param operator 操作人 + */ + @Override + public void apply(TraitDefinition traitDefinition, String operator) { // className 仅在 plugins 模型下可用,新 groovy 形式 trait 不需要该内容 String className = traitDefinition.getSpec().getClassName(); if (StringUtils.isEmpty(className)) { @@ -80,11 +91,11 @@ public class TraitProviderImpl implements TraitProvider { } TraitDO traitDO = TraitDO.builder() - .name(traitDefinition.getMetadata().getName()) - .className(className) - .definitionRef(traitDefinition.getSpec().getDefinitionRef().getName()) - .traitDefinition(request) - .build(); + .name(traitDefinition.getMetadata().getName()) + .className(className) + .definitionRef(traitDefinition.getSpec().getDefinitionRef().getName()) + .traitDefinition(SchemaUtil.toYamlMapStr(traitDefinition)) + .build(); traitService.apply(traitDO, operator); } @@ -98,8 +109,8 @@ public class TraitProviderImpl implements TraitProvider { @Override public int delete(TraitQueryReq request, String operator) { TraitQueryCondition condition = TraitQueryCondition.builder() - .name(request.getName()) - .build(); + .name(request.getName()) + .build(); return traitService.delete(condition, operator); } @@ -117,8 +128,8 @@ public class TraitProviderImpl implements TraitProvider { /** * 调用指定 Trait 的 reconcile 过程 * - * @param name Trait 唯一名称 - * @param object Reconcile Object + * @param name Trait 唯一名称 + * @param object Reconcile Object * @param properties Reconcile Properties */ @Override diff --git a/paas/appmanager/tesla-appmanager-trait/src/main/java/com/alibaba/tesla/appmanager/trait/controller/TraitController.java b/paas/appmanager/tesla-appmanager-trait/src/main/java/com/alibaba/tesla/appmanager/trait/controller/TraitController.java index 8ffae966..5789bb7d 100644 --- a/paas/appmanager/tesla-appmanager-trait/src/main/java/com/alibaba/tesla/appmanager/trait/controller/TraitController.java +++ b/paas/appmanager/tesla-appmanager-trait/src/main/java/com/alibaba/tesla/appmanager/trait/controller/TraitController.java @@ -8,6 +8,7 @@ import com.alibaba.tesla.appmanager.domain.req.trait.TraitQueryReq; import com.alibaba.tesla.appmanager.domain.req.trait.TraitReconcileReq; import com.alibaba.tesla.common.base.TeslaBaseResult; import com.alibaba.tesla.web.controller.BaseController; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -21,6 +22,7 @@ import java.util.HashMap; * @author yaoxing.gyx@alibaba-inc.com */ @Slf4j +@Tag(name = "Trait API") @RequestMapping("/traits") @RestController public class TraitController extends BaseController { diff --git a/paas/appmanager/tesla-appmanager-trait/src/main/java/com/alibaba/tesla/appmanager/trait/plugin/IlogtailTrait.java b/paas/appmanager/tesla-appmanager-trait/src/main/java/com/alibaba/tesla/appmanager/trait/plugin/IlogtailTrait.java index 2df2bd71..84d32a7f 100644 --- a/paas/appmanager/tesla-appmanager-trait/src/main/java/com/alibaba/tesla/appmanager/trait/plugin/IlogtailTrait.java +++ b/paas/appmanager/tesla-appmanager-trait/src/main/java/com/alibaba/tesla/appmanager/trait/plugin/IlogtailTrait.java @@ -23,7 +23,7 @@ public class IlogtailTrait extends BaseTrait { */ private static final String ILOGTAIL_CONTAINER = "{\n" + " \"name\": \"logtail\",\n" + - " \"image\": \"reg.docker.alibaba-inc.com/abm-aone/logtail:v1.0.27.0-7052198-aliyun\",\n" + + " \"image\": \"reg.docker.alibaba-inc.com/abm-aone/logtail:v1.1.1.0-ca91de7-aliyun\",\n" + " \"imagePullPolicy\": \"IfNotPresent\",\n" + " \"command\": [\n" + " \"sh\",\n" + @@ -46,8 +46,8 @@ public class IlogtailTrait extends BaseTrait { " \"cpu\": \"30m\"\n" + " },\n" + " \"limits\": {\n" + - " \"memory\": \"512Mi\",\n" + - " \"cpu\": \"100m\"\n" + + " \"memory\": \"2048Mi\",\n" + + " \"cpu\": \"500m\"\n" + " }\n" + " },\n" + " \"env\": [\n" + diff --git a/paas/appmanager/tesla-appmanager-trait/src/main/java/com/alibaba/tesla/appmanager/trait/plugin/ResourceLimitTrait.java b/paas/appmanager/tesla-appmanager-trait/src/main/java/com/alibaba/tesla/appmanager/trait/plugin/ResourceLimitTrait.java index a29dd168..78a14077 100644 --- a/paas/appmanager/tesla-appmanager-trait/src/main/java/com/alibaba/tesla/appmanager/trait/plugin/ResourceLimitTrait.java +++ b/paas/appmanager/tesla-appmanager-trait/src/main/java/com/alibaba/tesla/appmanager/trait/plugin/ResourceLimitTrait.java @@ -59,6 +59,20 @@ public class ResourceLimitTrait extends BaseTrait { limits.put("cpu", String.format("%dm", cpuInt)); } } + JSONObject requests = resources.getJSONObject("requests"); + if (requests != null) { + String cpu = requests.getString("cpu"); + if (!StringUtils.isEmpty(cpu)) { + int cpuInt; + if (cpu.endsWith("m")) { + cpuInt = Integer.parseInt(cpu.substring(0, cpu.length() - 1)); + } else { + cpuInt = Integer.parseInt(cpu) * 1000; + } + cpuInt /= 6; + requests.put("cpu", String.format("%dm", cpuInt)); + } + } } JSONObject workloadSpec = (JSONObject) getWorkloadRef().getSpec(); @@ -101,6 +115,13 @@ public class ResourceLimitTrait extends BaseTrait { for (int i = 0; i < containers.size(); i++) { JSONObject container = containers.getJSONObject(i); container.put("resources", resources); + JSONObject requests = resources.getJSONObject("requests"); + if (requests == null && resources.getJSONObject("limits") != null) { + JSONObject obj = JSONObject.parseObject(resources.getJSONObject("limits").toJSONString()); + container.getJSONObject("resources").put("requests", obj); + log.info("copy resources limits to requests|resources={}", + container.getJSONObject("resources").toJSONString()); + } } } } diff --git a/paas/appmanager/tesla-appmanager-trait/src/main/java/com/alibaba/tesla/appmanager/trait/plugin/ServiceTrait.java b/paas/appmanager/tesla-appmanager-trait/src/main/java/com/alibaba/tesla/appmanager/trait/plugin/ServiceTrait.java index 5df00eba..38b9a046 100644 --- a/paas/appmanager/tesla-appmanager-trait/src/main/java/com/alibaba/tesla/appmanager/trait/plugin/ServiceTrait.java +++ b/paas/appmanager/tesla-appmanager-trait/src/main/java/com/alibaba/tesla/appmanager/trait/plugin/ServiceTrait.java @@ -118,6 +118,8 @@ public class ServiceTrait extends BaseTrait { try { ServiceResource resource = client.services() .load(new ByteArrayInputStream(cr.toJSONString().getBytes(StandardCharsets.UTF_8))); + log.info("prepare to apply service cr|cluster={}|namespace={}|name={}|cr={}", + clusterId, namespace, name, cr.toJSONString()); try { Service current = client.services().inNamespace(namespace).withName(name).get(); if (current == null) { diff --git a/paas/appmanager/tesla-appmanager-workflow/pom.xml b/paas/appmanager/tesla-appmanager-workflow/pom.xml index 794d5ed1..0d4d0d07 100644 --- a/paas/appmanager/tesla-appmanager-workflow/pom.xml +++ b/paas/appmanager/tesla-appmanager-workflow/pom.xml @@ -5,7 +5,8 @@ tesla-appmanager com.alibaba.tesla - 1.0.4-SNAPSHOT + 1.0.5-SNAPSHOT + ../pom.xml 4.0.0 @@ -82,5 +83,9 @@ junit test + + com.jayway.jsonpath + json-path + \ No newline at end of file diff --git a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/action/impl/workflowinstance/PreprocessingWorkflowInstanceStateAction.java b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/action/impl/workflowinstance/PreprocessingWorkflowInstanceStateAction.java index e43e82b0..cc1dcd87 100644 --- a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/action/impl/workflowinstance/PreprocessingWorkflowInstanceStateAction.java +++ b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/action/impl/workflowinstance/PreprocessingWorkflowInstanceStateAction.java @@ -83,10 +83,14 @@ public class PreprocessingWorkflowInstanceStateAction implements WorkflowInstanc "firstTask={}", appId, workflowInstanceId, JSONObject.toJSONString(firstTask)); // 创建一个空的快照到第一个 task 上 + JSONObject context = new JSONObject(); + if (options.getInitContext() != null) { + context.putAll(options.getInitContext()); + } WorkflowSnapshotDO snapshot = workflowSnapshotService.update(UpdateWorkflowSnapshotReq.builder() .workflowInstanceId(firstTask.getWorkflowInstanceId()) .workflowTaskId(firstTask.getId()) - .context(new JSONObject()) + .context(context) .build()); log.info("workflow snapshot has created|workflowInstanceId={}|workflowTaskId={}|workflowSnapshotId={}|" + "context={}", snapshot.getWorkflowInstanceId(), snapshot.getWorkflowTaskId(), @@ -130,6 +134,8 @@ public class PreprocessingWorkflowInstanceStateAction implements WorkflowInstanc checkWorkflowTypeExists(workflowType); WorkflowStageEnum workflowStage = WorkflowStageEnum.fromString(currentStep.getStage()); JSONObject workflowProperties = currentStep.getProperties(); + JSONArray outputs = currentStep.getOutputs(); + JSONArray inputs = currentStep.getInputs(); // 根据 workflow stage 进行前置渲染 switch (workflowStage) { @@ -156,6 +162,8 @@ public class PreprocessingWorkflowInstanceStateAction implements WorkflowInstanc .taskStage(workflowStage.toString()) .taskProperties(JSONObject.toJSONString(workflowProperties)) .taskStatus(taskStatus) + .taskOutputs(JSONObject.toJSONString(outputs)) + .taskInputs(JSONObject.toJSONString(inputs)) .build(); WorkflowTaskDO task = workflowTaskService.create(record); log.info("action=createWorkflowTask|workflowInstanceId={}|appId={}|taskType={}|taskStage={}|" + diff --git a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/action/impl/workflowinstance/SuccessWorkflowInstanceStateAction.java b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/action/impl/workflowinstance/SuccessWorkflowInstanceStateAction.java index 7380a9a8..654bfc8f 100644 --- a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/action/impl/workflowinstance/SuccessWorkflowInstanceStateAction.java +++ b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/action/impl/workflowinstance/SuccessWorkflowInstanceStateAction.java @@ -1,7 +1,13 @@ package com.alibaba.tesla.appmanager.workflow.action.impl.workflowinstance; +import com.alibaba.tesla.appmanager.api.provider.WorkflowTaskProvider; import com.alibaba.tesla.appmanager.common.enums.WorkflowInstanceStateEnum; +import com.alibaba.tesla.appmanager.common.enums.WorkflowTaskEventEnum; +import com.alibaba.tesla.appmanager.common.pagination.Pagination; +import com.alibaba.tesla.appmanager.domain.dto.WorkflowTaskDTO; +import com.alibaba.tesla.appmanager.domain.req.workflow.WorkflowTaskListReq; import com.alibaba.tesla.appmanager.workflow.action.WorkflowInstanceStateAction; +import com.alibaba.tesla.appmanager.workflow.event.WorkflowTaskEvent; import com.alibaba.tesla.appmanager.workflow.event.loader.WorkflowInstanceStateActionLoadedEvent; import com.alibaba.tesla.appmanager.workflow.repository.domain.WorkflowInstanceDO; import lombok.extern.slf4j.Slf4j; @@ -20,6 +26,9 @@ public class SuccessWorkflowInstanceStateAction implements WorkflowInstanceState @Autowired private ApplicationEventPublisher publisher; + @Autowired + private WorkflowTaskProvider workflowTaskProvider; + @Override public void run(ApplicationArguments args) throws Exception { publisher.publishEvent(new WorkflowInstanceStateActionLoadedEvent( @@ -35,5 +44,22 @@ public class SuccessWorkflowInstanceStateAction implements WorkflowInstanceState public void run(WorkflowInstanceDO instance) { log.info("the current workflow instance has entered the SUCCESS state|workflowInstanceId={}|appId={}", instance.getId(), instance.getAppId()); + + // 如果 workflow 中存在关联项,那么发送事件,触发工作流继续进行 + WorkflowTaskListReq req = WorkflowTaskListReq.builder() + .deployWorkflowInstanceId(instance.getId()) + .build(); + Pagination workflowTasks = workflowTaskProvider.list(req); + if (workflowTasks.getItems().size() == 0) { + log.info("no associated workflow tasks found, skip|deployWorkflowInstanceId={}", instance.getId()); + return; + } + + for (WorkflowTaskDTO item : workflowTasks.getItems()) { + log.info("find associated workflow task, publish TRIGGER_UPDATE to it|workflowInstanceId={}|" + + "workflowTaskId={}|deployWorkflowInstanceId={}|deployWorkflowInstanceStatus={}", + item.getWorkflowInstanceId(), item.getId(), instance.getId(), instance.getWorkflowStatus()); + publisher.publishEvent(new WorkflowTaskEvent(this, WorkflowTaskEventEnum.TRIGGER_UPDATE, item)); + } } } diff --git a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/action/impl/workflowtask/TerminatedWorkflowTaskStateAction.java b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/action/impl/workflowtask/TerminatedWorkflowTaskStateAction.java index ea314873..4943dc6b 100644 --- a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/action/impl/workflowtask/TerminatedWorkflowTaskStateAction.java +++ b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/action/impl/workflowtask/TerminatedWorkflowTaskStateAction.java @@ -7,6 +7,7 @@ import com.alibaba.tesla.appmanager.workflow.repository.domain.WorkflowInstanceD import com.alibaba.tesla.appmanager.workflow.repository.domain.WorkflowTaskDO; import com.alibaba.tesla.appmanager.workflow.service.WorkflowInstanceService; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; @@ -41,6 +42,10 @@ public class TerminatedWorkflowTaskStateAction implements WorkflowTaskStateActio log.info("the current workflow task enters the TERMINATED state|workflowInstanceId={}|workflowTaskId={}", task.getWorkflowInstanceId(), task.getId()); WorkflowInstanceDO instance = workflowInstanceService.get(task.getWorkflowInstanceId(), true); - workflowInstanceService.triggerOpTerminate(instance, "terminated"); + if (StringUtils.isNotEmpty(task.getTaskErrorMessage())) { + workflowInstanceService.triggerOpTerminate(instance, task.getTaskErrorMessage()); + } else { + workflowInstanceService.triggerOpTerminate(instance, "terminated"); + } } } diff --git a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/action/impl/workflowtask/WaitingWorkflowTaskStateAction.java b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/action/impl/workflowtask/WaitingWorkflowTaskStateAction.java index 127163c3..0af0e8bb 100644 --- a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/action/impl/workflowtask/WaitingWorkflowTaskStateAction.java +++ b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/action/impl/workflowtask/WaitingWorkflowTaskStateAction.java @@ -1,20 +1,28 @@ package com.alibaba.tesla.appmanager.workflow.action.impl.workflowtask; +import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.alibaba.tesla.appmanager.api.provider.DeployAppProvider; import com.alibaba.tesla.appmanager.api.provider.UnitProvider; +import com.alibaba.tesla.appmanager.common.constants.AppFlowParamKey; import com.alibaba.tesla.appmanager.common.constants.DefaultConstant; -import com.alibaba.tesla.appmanager.common.enums.DeployAppStateEnum; -import com.alibaba.tesla.appmanager.common.enums.WorkflowTaskEventEnum; -import com.alibaba.tesla.appmanager.common.enums.WorkflowTaskStateEnum; +import com.alibaba.tesla.appmanager.common.constants.WorkflowContextKeyConstant; +import com.alibaba.tesla.appmanager.common.enums.*; import com.alibaba.tesla.appmanager.common.exception.AppErrorCode; import com.alibaba.tesla.appmanager.common.exception.AppException; +import com.alibaba.tesla.appmanager.domain.dto.DeployAppAttrDTO; import com.alibaba.tesla.appmanager.domain.dto.DeployAppDTO; +import com.alibaba.tesla.appmanager.domain.req.UpdateWorkflowSnapshotReq; +import com.alibaba.tesla.appmanager.domain.req.deploy.DeployAppGetAttrReq; import com.alibaba.tesla.appmanager.domain.req.deploy.DeployAppGetReq; import com.alibaba.tesla.appmanager.workflow.action.WorkflowTaskStateAction; import com.alibaba.tesla.appmanager.workflow.event.WorkflowTaskEvent; import com.alibaba.tesla.appmanager.workflow.event.loader.WorkflowTaskStateActionLoadedEvent; +import com.alibaba.tesla.appmanager.workflow.repository.condition.WorkflowSnapshotQueryCondition; +import com.alibaba.tesla.appmanager.workflow.repository.domain.WorkflowInstanceDO; import com.alibaba.tesla.appmanager.workflow.repository.domain.WorkflowTaskDO; +import com.alibaba.tesla.appmanager.workflow.service.WorkflowInstanceService; +import com.alibaba.tesla.appmanager.workflow.service.WorkflowSnapshotService; import com.google.common.base.Enums; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -22,8 +30,12 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.context.ApplicationEventPublisher; +import com.jayway.jsonpath.DocumentContext; +import com.jayway.jsonpath.JsonPath; import org.springframework.stereotype.Service; +import javax.ws.rs.HEAD; + @Slf4j @Service("WaitingWorkflowTaskStateAction") public class WaitingWorkflowTaskStateAction implements WorkflowTaskStateAction, ApplicationRunner { @@ -39,6 +51,12 @@ public class WaitingWorkflowTaskStateAction implements WorkflowTaskStateAction, @Autowired private UnitProvider unitProvider; + @Autowired + private WorkflowSnapshotService workflowSnapshotService; + + @Autowired + private WorkflowInstanceService workflowInstanceService; + @Override public void run(ApplicationArguments args) throws Exception { publisher.publishEvent(new WorkflowTaskStateActionLoadedEvent( @@ -47,79 +65,223 @@ public class WaitingWorkflowTaskStateAction implements WorkflowTaskStateAction, /** * 自身处理逻辑 - * + *

* 注意此处 WAITING 的事件由 DeployAppService 在完成时主动触发 * * @param task Workflow 实例 */ @Override public void run(WorkflowTaskDO task) { + Long deployWorkflowInstanceId = task.getDeployWorkflowInstanceId(); Long deployAppId = task.getDeployAppId(); String deployAppUnitId = task.getDeployAppUnitId(); String deployAppNamespaceId = task.getDeployAppNamespaceId(); String deployAppStageId = task.getDeployAppStageId(); - if (deployAppId == null || deployAppId == 0) { + + // 增加需要 deliver 到后续节点的参数内容 + enrichContextByDeliverParameterValues(task); + + if (deployAppId != null && deployAppId > 0) { + DeployAppGetReq request = DeployAppGetReq.builder().deployAppId(deployAppId).build(); + DeployAppDTO deployApp; + if (StringUtils.isNotEmpty(deployAppUnitId) + || StringUtils.isNotEmpty(deployAppNamespaceId) + || StringUtils.isNotEmpty(deployAppStageId)) { + JSONObject response = unitProvider.getDeployment(deployAppUnitId, + DeployAppGetReq.builder().deployAppId(deployAppId).build()); + deployApp = response.toJavaObject(DeployAppDTO.class); + } else { + deployApp = deployAppProvider.get(request, DefaultConstant.SYSTEM_OPERATOR); + } + DeployAppStateEnum deployStatus = Enums + .getIfPresent(DeployAppStateEnum.class, deployApp.getDeployStatus()).orNull(); + if (deployStatus == null) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("invalid deploy app status %s for deployment %d", + deployApp.getDeployStatus(), deployAppId)); + } + switch (deployStatus) { + case SUCCESS: + log.info("the deployment has been completed, and the workflow task has ended waiting|" + + "workflowInstanceId={}|workflowTaskId={}|deployAppId={}|deployStatus={}", + task.getWorkflowInstanceId(), task.getId(), deployApp.getId(), + deployApp.getDeployStatus()); + task.setTaskStatus(WorkflowTaskStateEnum.SUCCESS.toString()); + task.setTaskErrorMessage(""); + enrichContextByOverwriteParameterValues(task); + publisher.publishEvent(new WorkflowTaskEvent(this, WorkflowTaskEventEnum.WAITING_FINISHED, task)); + break; + case FAILURE: + case WAIT_FOR_OP: + log.warn("the deployment has been completed, but reached FAILURE/WAIT_FOR_OP status, and the workflow" + + "task has ended waiting|workflowInstanceId={}|workflowTaskId={}|deployAppId={}|" + + "deployStatus={}|errorMessage={}", task.getWorkflowInstanceId(), task.getId(), + deployApp.getId(), deployApp.getDeployStatus(), deployApp.getDeployErrorMessage()); + task.setTaskStatus(WorkflowTaskStateEnum.FAILURE.toString()); + task.setTaskErrorMessage(deployApp.getDeployErrorMessage()); + publisher.publishEvent(new WorkflowTaskEvent(this, WorkflowTaskEventEnum.WAITING_FAILED, task)); + break; + case EXCEPTION: + log.error("the deployment has been completed, but reached EXCEPTION status, and the workflow" + + "task has ended waiting|workflowInstanceId={}|workflowTaskId={}|deployAppId={}|" + + "deployStatus={}|errorMessage={}", task.getWorkflowInstanceId(), task.getId(), + deployApp.getId(), deployApp.getDeployStatus(), deployApp.getDeployErrorMessage()); + task.setTaskStatus(WorkflowTaskStateEnum.EXCEPTION.toString()); + task.setTaskErrorMessage(deployApp.getDeployErrorMessage()); + publisher.publishEvent(new WorkflowTaskEvent(this, + WorkflowTaskEventEnum.WAITING_UNKNOWN_ERROR, task)); + break; + default: + // 不需要触发事件,会由 DeployApp 侧自行在终态时再次触发 + log.info("the deployment is running now, and the workflow task need to continue to wait|" + + "workflowInstanceId={}|workflowTaskId={}|deployAppId={}|deployStatus={}", + task.getWorkflowInstanceId(), task.getId(), deployApp.getId(), + deployApp.getDeployStatus()); + break; + } + } else if (deployWorkflowInstanceId != null && deployWorkflowInstanceId > 0) { + WorkflowInstanceDO deployWorkflowInstance = workflowInstanceService.get(deployWorkflowInstanceId, false); + if (deployWorkflowInstance == null) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("invalid deployWorkflowInstanceId returned by workflow task|" + + "deployWorkflowInstanceId=%d", deployWorkflowInstanceId)); + } + WorkflowInstanceStateEnum status = Enums.getIfPresent(WorkflowInstanceStateEnum.class, + deployWorkflowInstance.getWorkflowStatus()).orNull(); + if (status == null) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("invalid deploy workflow status %s for workflow %d", + deployWorkflowInstance.getWorkflowStatus(), deployWorkflowInstanceId)); + } + switch (status) { + case SUCCESS: + log.info("the deploy-workflow has been completed, and the workflow task has ended waiting|" + + "workflowInstanceId={}|workflowTaskId={}|newWorkflowInstanceId={}|" + + "newWorkflowInstanceStatus={}", task.getWorkflowInstanceId(), task.getId(), + deployWorkflowInstance.getId(), deployWorkflowInstance.getWorkflowStatus()); + task.setTaskStatus(WorkflowTaskStateEnum.SUCCESS.toString()); + task.setTaskErrorMessage(""); + publisher.publishEvent(new WorkflowTaskEvent(this, WorkflowTaskEventEnum.WAITING_FINISHED, task)); + break; + case FAILURE: + log.warn("the deploy-workflow has been completed, but reached FAILURE/WAIT_FOR_OP status, " + + "and the workflowtask has ended waiting|workflowInstanceId={}|workflowTaskId={}|" + + "newWorkflowInstanceId={}|newWorkflowInstanceStatus={}|errorMessage={}", + task.getWorkflowInstanceId(), task.getId(), deployWorkflowInstance.getId(), + deployWorkflowInstance.getWorkflowStatus(), + deployWorkflowInstance.getWorkflowErrorMessage()); + task.setTaskStatus(WorkflowTaskStateEnum.FAILURE.toString()); + task.setTaskErrorMessage(deployWorkflowInstance.getWorkflowErrorMessage()); + publisher.publishEvent(new WorkflowTaskEvent(this, WorkflowTaskEventEnum.WAITING_FAILED, task)); + break; + case SUSPEND: + case TERMINATED: + case EXCEPTION: + log.error("the deploy-workflow has been completed, but reached EXCEPTION status, and the workflow" + + "task has ended waiting|workflowInstanceId={}|workflowTaskId={}|" + + "newWorkflowInstanceId={}|newWorkflowInstanceStatus={}|errorMessage={}", + task.getWorkflowInstanceId(), task.getId(), deployWorkflowInstance.getId(), + deployWorkflowInstance.getWorkflowStatus(), + deployWorkflowInstance.getWorkflowErrorMessage()); + task.setTaskStatus(WorkflowTaskStateEnum.EXCEPTION.toString()); + task.setTaskErrorMessage(deployWorkflowInstance.getWorkflowErrorMessage()); + publisher.publishEvent(new WorkflowTaskEvent(this, + WorkflowTaskEventEnum.WAITING_UNKNOWN_ERROR, task)); + break; + default: + // 不需要触发事件,会由 Workflow 侧自行在终态时再次触发 + log.info("the deploy-workflow is running now, and the workflow task need to continue to wait|" + + "workflowInstanceId={}|workflowTaskId={}|newWorkflowInstanceId={}|" + + "newWorkflowInstanceStatus={}", task.getWorkflowInstanceId(), + task.getId(), deployWorkflowInstance.getId(), deployWorkflowInstance.getWorkflowStatus()); + break; + } + } else { log.info("skip workflow task waiting process|workflowInstanceId={}|workflowTaskId={}|taskStatus={}", task.getWorkflowInstanceId(), task.getId(), task.getTaskStatus()); publisher.publishEvent(new WorkflowTaskEvent(this, WorkflowTaskEventEnum.WAITING_FINISHED, task)); + } + } + + /** + * 将当前 workflow task 对应的 context 附加 deploy app 对应的 GLOBAL_PARAMS 中的 overwriteParameterValues 内容 + * + * @param task Workflow Task + */ + private void enrichContextByOverwriteParameterValues(WorkflowTaskDO task) { + Long deployAppId = task.getDeployAppId(); + if (StringUtils.isNotEmpty(task.getDeployAppUnitId()) + || StringUtils.isNotEmpty(task.getDeployAppNamespaceId()) + || StringUtils.isNotEmpty(task.getDeployAppStageId())) { return; } - DeployAppGetReq request = DeployAppGetReq.builder().deployAppId(deployAppId).build(); - DeployAppDTO deployApp; - if (StringUtils.isNotEmpty(deployAppUnitId) - || StringUtils.isNotEmpty(deployAppNamespaceId) - || StringUtils.isNotEmpty(deployAppStageId)) { - JSONObject response = unitProvider.getDeployment(deployAppUnitId, - DeployAppGetReq.builder().deployAppId(deployAppId).build()); - deployApp = response.toJavaObject(DeployAppDTO.class); - } else { - deployApp = deployAppProvider.get(request, DefaultConstant.SYSTEM_OPERATOR); - } - DeployAppStateEnum deployStatus = Enums - .getIfPresent(DeployAppStateEnum.class, deployApp.getDeployStatus()).orNull(); - if (deployStatus == null) { + String logSuffix = String.format("workflowInstanceId=%d|workflowTaskId=%d|deployAppId=%d", + task.getWorkflowInstanceId(), task.getId(), deployAppId); + log.info("prepare to enrich context by overwrite parameter values|{}", logSuffix); + DeployAppAttrDTO deployApp = deployAppProvider.getAttr(DeployAppGetAttrReq.builder() + .deployAppId(deployAppId) + .build(), DefaultConstant.SYSTEM_OPERATOR); + if (deployApp == null || deployApp.getAttrMap() == null) { throw new AppException(AppErrorCode.INVALID_USER_ARGS, - String.format("invalid deploy app status %s for deployment %d", - deployApp.getDeployStatus(), deployAppId)); + String.format("cannot find attrMap in deploy app|%s", logSuffix)); } - switch (deployStatus) { - case SUCCESS: - log.info("the deployment has been completed, and the workflow task has ended waiting|" + - "workflowInstanceId={}|workflowTaskId={}|deployAppId={}|deployStatus={}", - task.getWorkflowInstanceId(), task.getId(), deployApp.getId(), - deployApp.getDeployStatus()); - task.setTaskStatus(WorkflowTaskStateEnum.SUCCESS.toString()); - task.setTaskErrorMessage(""); - publisher.publishEvent(new WorkflowTaskEvent(this, WorkflowTaskEventEnum.WAITING_FINISHED, task)); - break; - case FAILURE: - case WAIT_FOR_OP: - log.warn("the deployment has been completed, but reached FAILURE/WAIT_FOR_OP status, and the workflow" + - "task has ended waiting|workflowInstanceId={}|workflowTaskId={}|deployAppId={}|" + - "deployStatus={}|errorMessage={}", task.getWorkflowInstanceId(), task.getId(), - deployApp.getId(), deployApp.getDeployStatus(), deployApp.getDeployErrorMessage()); - task.setTaskStatus(WorkflowTaskStateEnum.FAILURE.toString()); - task.setTaskErrorMessage(deployApp.getDeployErrorMessage()); - publisher.publishEvent(new WorkflowTaskEvent(this, WorkflowTaskEventEnum.WAITING_FAILED, task)); - break; - case EXCEPTION: - log.error("the deployment has been completed, but reached EXCEPTION status, and the workflow" + - "task has ended waiting|workflowInstanceId={}|workflowTaskId={}|deployAppId={}|" + - "deployStatus={}|errorMessage={}", task.getWorkflowInstanceId(), task.getId(), - deployApp.getId(), deployApp.getDeployStatus(), deployApp.getDeployErrorMessage()); - task.setTaskStatus(WorkflowTaskStateEnum.EXCEPTION.toString()); - task.setTaskErrorMessage(deployApp.getDeployErrorMessage()); - publisher.publishEvent(new WorkflowTaskEvent(this, - WorkflowTaskEventEnum.WAITING_UNKNOWN_ERROR, task)); - break; - default: - // 不需要触发事件,会由 DeployApp 侧自行在终态时再次触发 - log.info("the deployment is running now, and the workflow task need to continue to wait|" + - "workflowInstanceId={}|workflowTaskId={}|deployAppId={}|deployStatus={}", - task.getWorkflowInstanceId(), task.getId(), deployApp.getId(), - deployApp.getDeployStatus()); - break; + + String globalParams = deployApp.getAttrMap().get(DeployAppAttrTypeEnum.GLOBAL_PARAMS.toString()); + if (StringUtils.isEmpty(globalParams)) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("cannot find globalParams in deploy app attr|%s", logSuffix)); } + JSONObject parameters = JSONObject.parseObject(globalParams) + .getJSONObject(AppFlowParamKey.OVERWRITE_PARAMETER_VALUES); + if (parameters.size() == 0) { + log.info("no overwrite parameter values found in workflow task|{}", logSuffix); + return; + } + + // 覆写 workflow task 的 context 并重新写回数据库 + JSONObject context = workflowSnapshotService.getContext(task.getWorkflowInstanceId(), task.getId()); + context.putIfAbsent(WorkflowContextKeyConstant.DEPLOY_OVERWRITE_PARAMETERS, new JSONObject()); + context.getJSONObject(WorkflowContextKeyConstant.DEPLOY_OVERWRITE_PARAMETERS).putAll(parameters); + workflowSnapshotService.update(UpdateWorkflowSnapshotReq.builder() + .workflowTaskId(task.getId()) + .workflowInstanceId(task.getWorkflowInstanceId()) + .context(context) + .build()); + log.info("workflow context has been enriched by overwrite parameter values|{}|parameters={}", + logSuffix, parameters.toJSONString()); + } + + /** + * 将当前 workflow task 对应的 context 附加 deploy app 对应的 GLOBAL_PARAMS 中的 DeliverParameterValues 内容 + * + * @param task Workflow Task + */ + private void enrichContextByDeliverParameterValues(WorkflowTaskDO task) { + Long deployAppId = task.getDeployAppId(); + String taskOutputs = task.getTaskOutputs(); + JSONArray outputs = JSONObject.parseArray(taskOutputs); + JSONObject deliverValue = new JSONObject(); + String logSuffix = String.format("workflowInstanceId=%d|workflowTaskId=%d|deployAppId=%d", + task.getWorkflowInstanceId(), task.getId(), deployAppId); + log.info("prepare to enrich context by deliver parameter values|{}", logSuffix); + JSONObject context = workflowSnapshotService.getContext(task.getWorkflowInstanceId(), task.getId()); + DocumentContext contextStr = JsonPath.parse(JSONObject.toJSONString(context)); + for (int i = 0; i < outputs.size(); i++) { + JSONObject output = outputs.getJSONObject(i); + deliverValue.put(output.getString("name"), + contextStr.read(DefaultConstant.JSONPATH_PREFIX + output.getString("valueFrom"))); + } + + // 覆写 workflow task 的 context 并重新写回数据库 + context.putIfAbsent(WorkflowContextKeyConstant.DEPLOY_DELIVER_PARAMETERS, new JSONObject()); + context.getJSONObject(WorkflowContextKeyConstant.DEPLOY_DELIVER_PARAMETERS).putAll(deliverValue); + workflowSnapshotService.update(UpdateWorkflowSnapshotReq.builder() + .workflowTaskId(task.getId()) + .workflowInstanceId(task.getWorkflowInstanceId()) + .context(context) + .build()); + log.info("workflow context has been enriched by deliver|{}|context={}|deliverValue={}|", + logSuffix, context.toJSONString(), deliverValue); } } diff --git a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/api/WorkflowInstanceProviderImpl.java b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/api/WorkflowInstanceProviderImpl.java index 3170f139..63c52f0c 100644 --- a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/api/WorkflowInstanceProviderImpl.java +++ b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/api/WorkflowInstanceProviderImpl.java @@ -1,5 +1,6 @@ package com.alibaba.tesla.appmanager.workflow.api; +import com.alibaba.fastjson.JSONObject; import com.alibaba.tesla.appmanager.api.provider.WorkflowInstanceProvider; import com.alibaba.tesla.appmanager.common.pagination.Pagination; import com.alibaba.tesla.appmanager.domain.dto.WorkflowInstanceDTO; @@ -10,6 +11,7 @@ import com.alibaba.tesla.appmanager.workflow.repository.condition.WorkflowInstan import com.alibaba.tesla.appmanager.workflow.repository.domain.WorkflowInstanceDO; import com.alibaba.tesla.appmanager.workflow.service.WorkflowInstanceService; import com.alibaba.tesla.appmanager.domain.res.workflow.WorkflowInstanceOperationRes; +import com.alibaba.tesla.appmanager.workflow.service.WorkflowSnapshotService; import com.alibaba.tesla.appmanager.workflow.service.pubsub.WorkflowInstanceOperationCommand; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -27,6 +29,9 @@ public class WorkflowInstanceProviderImpl implements WorkflowInstanceProvider { @Autowired private WorkflowInstanceService workflowInstanceService; + @Autowired + private WorkflowSnapshotService workflowSnapshotService; + @Autowired private WorkflowInstanceDtoConvert convert; @@ -40,7 +45,9 @@ public class WorkflowInstanceProviderImpl implements WorkflowInstanceProvider { @Override public WorkflowInstanceDTO get(Long workflowInstanceId, boolean withExt) { WorkflowInstanceDO instance = workflowInstanceService.get(workflowInstanceId, withExt); - return convert.to(instance); + WorkflowInstanceDTO result = convert.to(instance); + result.setWorkflowContext(workflowSnapshotService.getContext(workflowInstanceId)); + return result; } /** @@ -61,6 +68,30 @@ public class WorkflowInstanceProviderImpl implements WorkflowInstanceProvider { return Pagination.transform(result, item -> convert.to(item)); } + /** + * 覆写 Context 到指定 Workflow 实例 + * + * @param workflowInstanceId Workflow 实例 ID + * @param context Context JSONObject + */ + @Override + public void putContext(Long workflowInstanceId, JSONObject context) { + workflowInstanceService.putContext(workflowInstanceId, context); + } + + /** + * 获取指定应用指定 category 的最后一个 SUCCESS 状态的 Workflow 实例 + * + * @param appId 应用 ID + * @param category 分类 + * @return WorkflowInstanceDTO + */ + @Override + public WorkflowInstanceDTO getLastSuccessInstance(String appId, String category) { + WorkflowInstanceDO instance = workflowInstanceService.getLastSuccessInstance(appId, category); + return convert.to(instance); + } + /** * 启动一个 Workflow 实例 * @@ -76,7 +107,7 @@ public class WorkflowInstanceProviderImpl implements WorkflowInstanceProvider { } /** - * 恢复处于 SUSPEND 状态的 Workflow 实例 + * 唤醒处于 SUSPEND 状态的 Workflow 实例 * * @param workflowInstanceId Workflow 实例 ID * @return 执行结果 diff --git a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/api/WorkflowTaskProviderImpl.java b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/api/WorkflowTaskProviderImpl.java index a0a5f48c..66ba2fee 100644 --- a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/api/WorkflowTaskProviderImpl.java +++ b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/api/WorkflowTaskProviderImpl.java @@ -58,6 +58,7 @@ public class WorkflowTaskProviderImpl implements WorkflowTaskProvider { .taskType(request.getTaskType()) .taskStatus(request.getTaskStatus()) .deployAppId(request.getDeployAppId()) + .deployWorkflowInstanceId(request.getDeployWorkflowInstanceId()) .build()); return Pagination.transform(tasks, item -> convert.to(item)); } diff --git a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/controller/WorkflowController.java b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/controller/WorkflowController.java index 7a47d642..c7cfb4ba 100644 --- a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/controller/WorkflowController.java +++ b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/controller/WorkflowController.java @@ -3,13 +3,16 @@ package com.alibaba.tesla.appmanager.workflow.controller; import com.alibaba.tesla.appmanager.api.provider.WorkflowInstanceProvider; import com.alibaba.tesla.appmanager.api.provider.WorkflowTaskProvider; import com.alibaba.tesla.appmanager.auth.controller.AppManagerBaseController; +import com.alibaba.tesla.appmanager.common.constants.DefaultConstant; import com.alibaba.tesla.appmanager.common.pagination.Pagination; import com.alibaba.tesla.appmanager.domain.dto.WorkflowInstanceDTO; import com.alibaba.tesla.appmanager.domain.dto.WorkflowTaskDTO; import com.alibaba.tesla.appmanager.domain.option.WorkflowInstanceOption; -import com.alibaba.tesla.appmanager.domain.req.workflow.WorkflowInstanceListReq; -import com.alibaba.tesla.appmanager.domain.req.workflow.WorkflowTaskListReq; +import com.alibaba.tesla.appmanager.domain.req.workflow.*; +import com.alibaba.tesla.appmanager.domain.res.workflow.WorkflowInstanceOperationRes; import com.alibaba.tesla.common.base.TeslaBaseResult; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; @@ -23,6 +26,7 @@ import org.springframework.web.bind.annotation.*; * @author yaoxing.gyx@alibaba-inc.com */ @Slf4j +@Tag(name = "工作流 API") @RequestMapping("/workflow") @RestController public class WorkflowController extends AppManagerBaseController { @@ -33,13 +37,15 @@ public class WorkflowController extends AppManagerBaseController { @Autowired private WorkflowTaskProvider workflowTaskProvider; - // 发起部署 + @Operation(summary = "发起 Workflow") @PostMapping(value = "/launch") @ResponseBody public TeslaBaseResult launch( @RequestParam("appId") String appId, + @RequestParam("category") String category, @RequestBody String body, OAuth2Authentication auth) { WorkflowInstanceOption options = WorkflowInstanceOption.builder() + .category(category) .creator(getOperator(auth)) .build(); try { @@ -51,7 +57,7 @@ public class WorkflowController extends AppManagerBaseController { } } - // 根据过滤条件查询 Workflow Instance 列表 + @Operation(summary = "查询 Workflow Instance 列表") @GetMapping @ResponseBody public TeslaBaseResult list( @@ -61,7 +67,7 @@ public class WorkflowController extends AppManagerBaseController { return buildSucceedResult(response); } - // 查询指定 Workflow Instance 详情 + @Operation(summary = "查询 Workflow Instance 详情") @GetMapping("{instanceId}") @ResponseBody public TeslaBaseResult get( @@ -71,7 +77,67 @@ public class WorkflowController extends AppManagerBaseController { return buildSucceedResult(response); } - // 根据过滤条件查询 Workflow Task 列表 + @Operation(summary = "设置 Workflow Instance Context", description = "用于覆写 Workflow 实例中的 Context") + @PutMapping("{instanceId}/context") + @ResponseBody + public TeslaBaseResult putContext( + @PathVariable("instanceId") Long instanceId, + @RequestBody WorkflowPutContextReq request, + OAuth2Authentication auth + ) throws Exception { + workflowInstanceProvider.putContext(instanceId, request.getContext()); + return buildSucceedResult(DefaultConstant.EMPTY_OBJ); + } + + @Operation(summary = "唤醒 Workflow Instance", description = "用于唤醒处于 SUSPEND 状态的 Workflow 实例") + @PutMapping("{instanceId}/resume") + @ResponseBody + public TeslaBaseResult resume( + @PathVariable("instanceId") Long instanceId, OAuth2Authentication auth + ) throws Exception { + WorkflowInstanceOperationRes response = workflowInstanceProvider.resume(instanceId); + return buildSucceedResult(response); + } + + @Operation(summary = "终止 Workflow Instance", + description = "终止当前 Workflow 实例,并下发 InterruptedException 到 Task 侧") + @PutMapping("{instanceId}/terminate") + @ResponseBody + public TeslaBaseResult terminate( + @PathVariable("instanceId") Long instanceId, OAuth2Authentication auth + ) throws Exception { + WorkflowInstanceOperationRes response = workflowInstanceProvider.terminate(instanceId); + return buildSucceedResult(response); + } + + @Operation(summary = "重试 Workflow Instance", + description = "重试当前已经到达终态的 Workflow 实例 (SUCCESS/FAILURE/EXCEPTION/TERMINATED)," + + "注意该方法将会从第一个节点开始,使用原始参数重新运行一遍当前 Workflow 实例") + @PutMapping("{instanceId}/retry") + @ResponseBody + public TeslaBaseResult retry( + @PathVariable("instanceId") Long instanceId, OAuth2Authentication auth + ) throws Exception { + WorkflowInstanceOperationRes response = workflowInstanceProvider.retry(instanceId); + return buildSucceedResult(response); + } + + @Operation(summary = "重试 Workflow Instance (自定义起始 Task)", + description = "重试当前已经到达终态的 Workflow 实例 (SUCCESS/FAILURE/EXCEPTION/TERMINATED)," + + "注意该方法从指定 taskId 开始进行重试,即重新运行 taskId 及之后的所有 WorkflowInstance 任务," + + "该方法会获取 taskId 对应的快照内容,以此为输入进行重试") + @PutMapping("{instanceId}/retryFromTask") + @ResponseBody + public TeslaBaseResult retryFromTask( + @PathVariable("instanceId") Long instanceId, + @RequestParam("taskId") Long taskId, + OAuth2Authentication auth + ) throws Exception { + WorkflowInstanceDTO response = workflowInstanceProvider.retryFromTask(instanceId, taskId); + return buildSucceedResult(response); + } + + @Operation(summary = "查询 Workflow Task 列表") @GetMapping("{instanceId}/tasks") @ResponseBody public TeslaBaseResult listTask( @@ -90,7 +156,7 @@ public class WorkflowController extends AppManagerBaseController { return buildSucceedResult(response); } - // 查询指定 Workflow Task 详情 + @Operation(summary = "查询 Workflow Task 详情") @GetMapping("{instanceId}/tasks/{taskId}") @ResponseBody public TeslaBaseResult getTask( @@ -101,4 +167,32 @@ public class WorkflowController extends AppManagerBaseController { WorkflowTaskDTO response = workflowTaskProvider.get(taskId, true); return buildSucceedResult(response); } + + @Operation(summary = "终止 Workflow Task", + description = "终止指定 Workflow 任务 (x -> TERMINATED)") + @PutMapping("{instanceId}/tasks/{taskId}/terminate") + @ResponseBody + public TeslaBaseResult terminateTask( + @PathVariable("instanceId") Long instanceId, + @PathVariable("taskId") Long taskId, + @RequestBody WorkflowTaskTerminateReq request, + OAuth2Authentication auth + ) throws Exception { + workflowTaskProvider.terminate(taskId, request.getExtMessage()); + return buildSucceedResult(DefaultConstant.EMPTY_OBJ); + } + + @Operation(summary = "暂停 Workflow Task", + description = "暂停指定 Workflow 任务 (RUNNING -> RUNNING_SUSPEND / WAITING -> WAITING_SUSPEND)") + @PutMapping("{instanceId}/tasks/{taskId}/suspend") + @ResponseBody + public TeslaBaseResult suspendTask( + @PathVariable("instanceId") Long instanceId, + @PathVariable("taskId") Long taskId, + @RequestBody WorkflowTaskSuspendReq request, + OAuth2Authentication auth + ) throws Exception { + workflowTaskProvider.suspend(taskId, request.getExtMessage()); + return buildSucceedResult(DefaultConstant.EMPTY_OBJ); + } } \ No newline at end of file diff --git a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/listener/WorkflowTaskEventListener.java b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/listener/WorkflowTaskEventListener.java index f1a02a3c..ee27db59 100644 --- a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/listener/WorkflowTaskEventListener.java +++ b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/listener/WorkflowTaskEventListener.java @@ -79,6 +79,10 @@ public class WorkflowTaskEventListener implements ApplicationListener 0) { + task.setDeployWorkflowInstanceId(event.getTask().getDeployWorkflowInstanceId()); + logSuffix += String.format("|deployWorkflowInstanceId=%d", event.getTask().getDeployWorkflowInstanceId()); + } try { workflowTaskService.update(task); } catch (AppException e) { @@ -101,7 +105,7 @@ public class WorkflowTaskEventListener implements ApplicationListener", value, "category"); + return (Criteria) this; + } + + public Criteria andCategoryGreaterThan(String value) { + addCriterion("category >", value, "category"); + return (Criteria) this; + } + + public Criteria andCategoryGreaterThanOrEqualTo(String value) { + addCriterion("category >=", value, "category"); + return (Criteria) this; + } + + public Criteria andCategoryLessThan(String value) { + addCriterion("category <", value, "category"); + return (Criteria) this; + } + + public Criteria andCategoryLessThanOrEqualTo(String value) { + addCriterion("category <=", value, "category"); + return (Criteria) this; + } + + public Criteria andCategoryLike(String value) { + addCriterion("category like", value, "category"); + return (Criteria) this; + } + + public Criteria andCategoryNotLike(String value) { + addCriterion("category not like", value, "category"); + return (Criteria) this; + } + + public Criteria andCategoryIn(List values) { + addCriterion("category in", values, "category"); + return (Criteria) this; + } + + public Criteria andCategoryNotIn(List values) { + addCriterion("category not in", values, "category"); + return (Criteria) this; + } + + public Criteria andCategoryBetween(String value1, String value2) { + addCriterion("category between", value1, value2, "category"); + return (Criteria) this; + } + + public Criteria andCategoryNotBetween(String value1, String value2) { + addCriterion("category not between", value1, value2, "category"); + return (Criteria) this; + } + public Criteria andGmtStartIsNull() { addCriterion("gmt_start is null"); return (Criteria) this; diff --git a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/repository/domain/WorkflowTaskDO.java b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/repository/domain/WorkflowTaskDO.java index ba26ca54..d205b666 100644 --- a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/repository/domain/WorkflowTaskDO.java +++ b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/repository/domain/WorkflowTaskDO.java @@ -1,16 +1,19 @@ package com.alibaba.tesla.appmanager.workflow.repository.domain; +import java.util.Date; import lombok.AllArgsConstructor; import lombok.Builder; -import lombok.Data; +import lombok.Getter; import lombok.NoArgsConstructor; - -import java.util.Date; +import lombok.Setter; +import lombok.ToString; /** * Workflow 任务表 */ -@Data +@Getter +@Setter +@ToString @Builder @AllArgsConstructor @NoArgsConstructor @@ -66,7 +69,7 @@ public class WorkflowTaskDO { private String taskStatus; /** - * 部署单 ID + * 发起的新 DeployApp ID */ private Long deployAppId; @@ -75,17 +78,41 @@ public class WorkflowTaskDO { */ private Integer lockVersion; + /** + * 发起的新 DeployApp ID 归属单元 + */ private String deployAppUnitId; + /** + * 发起的新 DeployApp ID 归属 Namespace + */ private String deployAppNamespaceId; + /** + * 发起的新 DeployApp ID 归属 Stage + */ private String deployAppStageId; + /** + * 发起的新 WorkflowInstance ID + */ + private Long deployWorkflowInstanceId; + /** * Workflow 任务节点属性 (JSONObject 字符串) */ private String taskProperties; + /** + * Workflow 任务Outputs数组 (JSONArray 字符串) + */ + private String taskOutputs; + + /** + * Workflow 任务Inputs数组 (JSONArray 字符串) + */ + private String taskInputs; + /** * Workflow 任务节点执行出错信息 (仅 task_status==EXCEPTIOIN 下存在) */ diff --git a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/repository/domain/WorkflowTaskDOExample.java b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/repository/domain/WorkflowTaskDOExample.java index 1a35a399..31d6a6f6 100644 --- a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/repository/domain/WorkflowTaskDOExample.java +++ b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/repository/domain/WorkflowTaskDOExample.java @@ -1074,6 +1074,66 @@ public class WorkflowTaskDOExample { addCriterion("deploy_app_stage_id not between", value1, value2, "deployAppStageId"); return (Criteria) this; } + + public Criteria andDeployWorkflowInstanceIdIsNull() { + addCriterion("deploy_workflow_instance_id is null"); + return (Criteria) this; + } + + public Criteria andDeployWorkflowInstanceIdIsNotNull() { + addCriterion("deploy_workflow_instance_id is not null"); + return (Criteria) this; + } + + public Criteria andDeployWorkflowInstanceIdEqualTo(Long value) { + addCriterion("deploy_workflow_instance_id =", value, "deployWorkflowInstanceId"); + return (Criteria) this; + } + + public Criteria andDeployWorkflowInstanceIdNotEqualTo(Long value) { + addCriterion("deploy_workflow_instance_id <>", value, "deployWorkflowInstanceId"); + return (Criteria) this; + } + + public Criteria andDeployWorkflowInstanceIdGreaterThan(Long value) { + addCriterion("deploy_workflow_instance_id >", value, "deployWorkflowInstanceId"); + return (Criteria) this; + } + + public Criteria andDeployWorkflowInstanceIdGreaterThanOrEqualTo(Long value) { + addCriterion("deploy_workflow_instance_id >=", value, "deployWorkflowInstanceId"); + return (Criteria) this; + } + + public Criteria andDeployWorkflowInstanceIdLessThan(Long value) { + addCriterion("deploy_workflow_instance_id <", value, "deployWorkflowInstanceId"); + return (Criteria) this; + } + + public Criteria andDeployWorkflowInstanceIdLessThanOrEqualTo(Long value) { + addCriterion("deploy_workflow_instance_id <=", value, "deployWorkflowInstanceId"); + return (Criteria) this; + } + + public Criteria andDeployWorkflowInstanceIdIn(List values) { + addCriterion("deploy_workflow_instance_id in", values, "deployWorkflowInstanceId"); + return (Criteria) this; + } + + public Criteria andDeployWorkflowInstanceIdNotIn(List values) { + addCriterion("deploy_workflow_instance_id not in", values, "deployWorkflowInstanceId"); + return (Criteria) this; + } + + public Criteria andDeployWorkflowInstanceIdBetween(Long value1, Long value2) { + addCriterion("deploy_workflow_instance_id between", value1, value2, "deployWorkflowInstanceId"); + return (Criteria) this; + } + + public Criteria andDeployWorkflowInstanceIdNotBetween(Long value1, Long value2) { + addCriterion("deploy_workflow_instance_id not between", value1, value2, "deployWorkflowInstanceId"); + return (Criteria) this; + } } public static class Criteria extends GeneratedCriteria { diff --git a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/repository/impl/WorkflowInstanceRepositoryImpl.java b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/repository/impl/WorkflowInstanceRepositoryImpl.java index c38443bb..023bd559 100644 --- a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/repository/impl/WorkflowInstanceRepositoryImpl.java +++ b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/repository/impl/WorkflowInstanceRepositoryImpl.java @@ -79,6 +79,9 @@ public class WorkflowInstanceRepositoryImpl implements WorkflowInstanceRepositor if (StringUtils.isNotBlank(condition.getAppId())) { criteria.andAppIdEqualTo(condition.getAppId()); } + if (StringUtils.isNotBlank(condition.getCategory())) { + criteria.andCategoryEqualTo(condition.getCategory()); + } if (StringUtils.isNotBlank(condition.getWorkflowStatus())) { criteria.andWorkflowStatusEqualTo(condition.getWorkflowStatus()); } diff --git a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/repository/impl/WorkflowTaskRepositoryImpl.java b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/repository/impl/WorkflowTaskRepositoryImpl.java index deba1a17..0fe3d9d5 100644 --- a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/repository/impl/WorkflowTaskRepositoryImpl.java +++ b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/repository/impl/WorkflowTaskRepositoryImpl.java @@ -124,6 +124,9 @@ public class WorkflowTaskRepositoryImpl implements WorkflowTaskRepository { if (StringUtils.isNotEmpty(condition.getDeployAppStageId())) { criteria.andDeployAppStageIdEqualTo(condition.getDeployAppStageId()); } + if (condition.getDeployWorkflowInstanceId() != null && condition.getDeployWorkflowInstanceId() > 0) { + criteria.andDeployWorkflowInstanceIdEqualTo(condition.getDeployWorkflowInstanceId()); + } return example; } diff --git a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/repository/mapper/WorkflowInstanceDOMapper.java b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/repository/mapper/WorkflowInstanceDOMapper.java index 2161addd..9b2cf687 100644 --- a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/repository/mapper/WorkflowInstanceDOMapper.java +++ b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/repository/mapper/WorkflowInstanceDOMapper.java @@ -2,11 +2,10 @@ package com.alibaba.tesla.appmanager.workflow.repository.mapper; import com.alibaba.tesla.appmanager.workflow.repository.domain.WorkflowInstanceDO; import com.alibaba.tesla.appmanager.workflow.repository.domain.WorkflowInstanceDOExample; +import java.util.List; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; -import java.util.List; - @Mapper public interface WorkflowInstanceDOMapper { long countByExample(WorkflowInstanceDOExample example); diff --git a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/repository/mapper/WorkflowTaskDOMapper.java b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/repository/mapper/WorkflowTaskDOMapper.java index 17fb2455..dc02c9eb 100644 --- a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/repository/mapper/WorkflowTaskDOMapper.java +++ b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/repository/mapper/WorkflowTaskDOMapper.java @@ -2,11 +2,10 @@ package com.alibaba.tesla.appmanager.workflow.repository.mapper; import com.alibaba.tesla.appmanager.workflow.repository.domain.WorkflowTaskDO; import com.alibaba.tesla.appmanager.workflow.repository.domain.WorkflowTaskDOExample; +import java.util.List; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; -import java.util.List; - @Mapper public interface WorkflowTaskDOMapper { long countByExample(WorkflowTaskDOExample example); diff --git a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/service/WorkflowInstanceService.java b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/service/WorkflowInstanceService.java index c10f416f..fb49dafa 100644 --- a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/service/WorkflowInstanceService.java +++ b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/service/WorkflowInstanceService.java @@ -1,6 +1,8 @@ package com.alibaba.tesla.appmanager.workflow.service; +import com.alibaba.fastjson.JSONObject; import com.alibaba.tesla.appmanager.common.pagination.Pagination; +import com.alibaba.tesla.appmanager.domain.dto.WorkflowInstanceDTO; import com.alibaba.tesla.appmanager.domain.option.WorkflowInstanceOption; import com.alibaba.tesla.appmanager.workflow.repository.condition.WorkflowInstanceQueryCondition; import com.alibaba.tesla.appmanager.workflow.repository.domain.WorkflowInstanceDO; @@ -30,6 +32,14 @@ public interface WorkflowInstanceService { */ Pagination list(WorkflowInstanceQueryCondition condition); + /** + * 覆写 Context 到指定 Workflow 实例 + * + * @param workflowInstanceId Workflow 实例 ID + * @param context Context JSONObject + */ + void putContext(Long workflowInstanceId, JSONObject context); + /** * 启动一个 Workflow 实例 * @@ -149,4 +159,13 @@ public interface WorkflowInstanceService { * @return 更新状态后的 Workflow 实例 */ WorkflowInstanceDO localRetryFromTask(Long workflowInstanceId, Long workflowTaskId); + + /** + * 获取指定应用指定 category 的最后一个 SUCCESS 状态的 Workflow 实例 + * + * @param appId 应用 ID + * @param category 分类 + * @return WorkflowInstanceDO + */ + WorkflowInstanceDO getLastSuccessInstance(String appId, String category); } diff --git a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/service/WorkflowSnapshotService.java b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/service/WorkflowSnapshotService.java index 997305a0..46218f69 100644 --- a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/service/WorkflowSnapshotService.java +++ b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/service/WorkflowSnapshotService.java @@ -1,5 +1,6 @@ package com.alibaba.tesla.appmanager.workflow.service; +import com.alibaba.fastjson.JSONObject; import com.alibaba.tesla.appmanager.common.pagination.Pagination; import com.alibaba.tesla.appmanager.domain.req.UpdateWorkflowSnapshotReq; import com.alibaba.tesla.appmanager.domain.req.DeleteWorkflowSnapshotReq; @@ -29,6 +30,15 @@ public interface WorkflowSnapshotService { */ Pagination list(WorkflowSnapshotQueryCondition condition); + /** + * 对指定的 Workflow 实例 put context 对象,进行 Merge + * + * @param workflowInstanceId Workflow 实例 ID + * @param context Context 对象 (JSONObject) + * @return 更新后的指定 workflow task 对应的 workflow snapshot 对象 + */ + WorkflowSnapshotDO putContext(Long workflowInstanceId, JSONObject context); + /** * 更新一个 Workflow 快照 * @@ -44,4 +54,21 @@ public interface WorkflowSnapshotService { * @return 删除数量 */ int delete(DeleteWorkflowSnapshotReq request); + + /** + * 获取指定 Workflow Task 对应的 Context JSON Object 对象 + * + * @param workflowInstanceId Workflow 实例 ID + * @param workflowTaskId Workflow 任务 ID + * @return Context JSONObject + */ + JSONObject getContext(Long workflowInstanceId, Long workflowTaskId); + + /** + * 获取指定 Workflow Instance 对应的 Context JSON Object 对象 + * + * @param workflowInstanceId Workflow 实例 ID + * @return Context JSONObject + */ + JSONObject getContext(Long workflowInstanceId); } diff --git a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/service/impl/WorkflowInstanceServiceImpl.java b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/service/impl/WorkflowInstanceServiceImpl.java index a8436d36..96b57cba 100644 --- a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/service/impl/WorkflowInstanceServiceImpl.java +++ b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/service/impl/WorkflowInstanceServiceImpl.java @@ -1,6 +1,7 @@ package com.alibaba.tesla.appmanager.workflow.service.impl; import com.alibaba.fastjson.JSONObject; +import com.alibaba.tesla.appmanager.common.constants.DefaultConstant; import com.alibaba.tesla.appmanager.common.constants.WorkflowConstant; import com.alibaba.tesla.appmanager.common.enums.WorkflowInstanceEventEnum; import com.alibaba.tesla.appmanager.common.enums.WorkflowInstanceStateEnum; @@ -10,6 +11,7 @@ import com.alibaba.tesla.appmanager.common.exception.AppErrorCode; import com.alibaba.tesla.appmanager.common.exception.AppException; import com.alibaba.tesla.appmanager.common.pagination.Pagination; import com.alibaba.tesla.appmanager.common.util.SchemaUtil; +import com.alibaba.tesla.appmanager.domain.dto.WorkflowInstanceDTO; import com.alibaba.tesla.appmanager.domain.option.WorkflowInstanceOption; import com.alibaba.tesla.appmanager.domain.req.UpdateWorkflowSnapshotReq; import com.alibaba.tesla.appmanager.domain.res.workflow.WorkflowInstanceOperationRes; @@ -104,6 +106,17 @@ public class WorkflowInstanceServiceImpl implements WorkflowInstanceService { return Pagination.valueOf(result, Function.identity()); } + /** + * 覆写 Context 到指定 Workflow 实例 + * + * @param workflowInstanceId Workflow 实例 ID + * @param context Context JSONObject + */ + @Override + public void putContext(Long workflowInstanceId, JSONObject context) { + workflowSnapshotService.putContext(workflowInstanceId, context); + } + /** * 启动一个 Workflow 实例 * @@ -118,9 +131,14 @@ public class WorkflowInstanceServiceImpl implements WorkflowInstanceService { String configurationSha256 = DigestUtils.sha256Hex(configuration); DeployAppSchema configurationSchema = SchemaUtil.toSchema(DeployAppSchema.class, configuration); enrichConfigurationSchema(configurationSchema); + String category = options.getCategory(); String creator = options.getCreator(); + if (StringUtils.isEmpty(category)) { + category = DefaultConstant.WORKFLOW_CATEGORY; + } WorkflowInstanceDO record = WorkflowInstanceDO.builder() .appId(appId) + .category(category) .workflowStatus(WorkflowInstanceStateEnum.PENDING.toString()) .workflowConfiguration(SchemaUtil.toYamlMapStr(configurationSchema)) .workflowSha256(configurationSha256) @@ -146,8 +164,9 @@ public class WorkflowInstanceServiceImpl implements WorkflowInstanceService { */ @Override public void update(WorkflowInstanceDO workflow) { - log.info("action=updateWorkflowInstance|workflowInstanceId={}|appId={}|status={}|creator={}", workflow.getId(), - workflow.getAppId(), workflow.getWorkflowStatus(), workflow.getWorkflowCreator()); + log.info("action=updateWorkflowInstance|workflowInstanceId={}|appId={}|category={}|status={}|creator={}", + workflow.getId(), workflow.getAppId(), workflow.getCategory(), workflow.getWorkflowStatus(), + workflow.getWorkflowCreator()); int count = workflowInstanceRepository.updateByPrimaryKey(workflow); if (count == 0) { throw new AppException(AppErrorCode.LOCKER_VERSION_EXPIRED); @@ -217,7 +236,8 @@ public class WorkflowInstanceServiceImpl implements WorkflowInstanceService { public void triggerProcessFailed(WorkflowInstanceDO instance, String errorMessage) { instance.setWorkflowErrorMessage(errorMessage); log.info("the current workflow instance is triggered by a failure event|workflowInstanceId={}|appId={}|" + - "errorMessage={}", instance.getId(), instance.getAppId(), errorMessage); + "category={}|errorMessage={}", instance.getId(), instance.getAppId(), instance.getCategory(), + errorMessage); publisher.publishEvent(new WorkflowInstanceEvent(this, WorkflowInstanceEventEnum.PROCESS_FAILED, instance)); } @@ -232,7 +252,8 @@ public class WorkflowInstanceServiceImpl implements WorkflowInstanceService { public void triggerProcessUnknownError(WorkflowInstanceDO instance, String errorMessage) { instance.setWorkflowErrorMessage(errorMessage); log.warn("the current workflow instance is triggered by an exception event|workflowInstanceId={}|appId={}|" + - "errorMessage={}", instance.getId(), instance.getAppId(), errorMessage); + "category={}|errorMessage={}", instance.getId(), instance.getAppId(), instance.getCategory(), + errorMessage); publisher.publishEvent(new WorkflowInstanceEvent(this, WorkflowInstanceEventEnum.PROCESS_UNKNOWN_ERROR, instance)); } @@ -260,7 +281,8 @@ public class WorkflowInstanceServiceImpl implements WorkflowInstanceService { public void triggerOpTerminate(WorkflowInstanceDO instance, String errorMessage) { instance.setWorkflowErrorMessage(errorMessage); log.info("the current workflow instance is triggered by OP_TERMINATE|workflowInstanceId={}|appId={}|" + - "errorMessage={}", instance.getId(), instance.getAppId(), errorMessage); + "category={}|errorMessage={}", instance.getId(), instance.getAppId(), instance.getCategory(), + errorMessage); publisher.publishEvent(new WorkflowInstanceEvent(this, WorkflowInstanceEventEnum.OP_TERMINATE, instance)); } @@ -271,8 +293,8 @@ public class WorkflowInstanceServiceImpl implements WorkflowInstanceService { */ @Override public void triggerPause(WorkflowInstanceDO instance) { - log.info("the current workflow instance is triggered by PAUSE|workflowInstanceId={}|appId={}", - instance.getId(), instance.getAppId()); + log.info("the current workflow instance is triggered by PAUSE|workflowInstanceId={}|appId={}|category={}", + instance.getId(), instance.getAppId(), instance.getCategory()); publisher.publishEvent(new WorkflowInstanceEvent(this, WorkflowInstanceEventEnum.PAUSE, instance)); } @@ -453,7 +475,9 @@ public class WorkflowInstanceServiceImpl implements WorkflowInstanceService { Long workflowInstanceId = instance.getId(); String appId = instance.getAppId(); - log.info("prepare to resume the workflow instance|workflowInstanceId={}|appId={}", workflowInstanceId, appId); + String category = instance.getCategory(); + log.info("prepare to resume the workflow instance|workflowInstanceId={}|appId={}|category={}", + workflowInstanceId, appId, category); // 发送 RESUME 事件到 workflow instance publisher.publishEvent(new WorkflowInstanceEvent(this, WorkflowInstanceEventEnum.RESUME, instance)); @@ -520,6 +544,30 @@ public class WorkflowInstanceServiceImpl implements WorkflowInstanceService { return null; } + /** + * 获取指定应用指定 category 的最后一个 SUCCESS 状态的 Workflow 实例 + * + * @param appId 应用 ID + * @param category 分类 + * @return WorkflowInstanceDO + */ + @Override + public WorkflowInstanceDO getLastSuccessInstance(String appId, String category) { + WorkflowInstanceQueryCondition condition = WorkflowInstanceQueryCondition.builder() + .appId(appId) + .category(category) + .workflowStatus(WorkflowInstanceStateEnum.SUCCESS.toString()) + .pageSize(1) + .withBlobs(true) + .build(); + List results = workflowInstanceRepository.selectByCondition(condition); + if (results.size() == 0) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("cannot find last succeed workflow instance|appId=%s|category=%s", appId, category)); + } + return results.get(0); + } + /** * 丰富 configuration schema 内容,如果默认不存在任何 workflow task,那么默认填充 * diff --git a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/service/impl/WorkflowSnapshotServiceImpl.java b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/service/impl/WorkflowSnapshotServiceImpl.java index 3148b2aa..cc8daa15 100644 --- a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/service/impl/WorkflowSnapshotServiceImpl.java +++ b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/service/impl/WorkflowSnapshotServiceImpl.java @@ -12,6 +12,8 @@ import com.alibaba.tesla.appmanager.workflow.repository.condition.WorkflowSnapsh import com.alibaba.tesla.appmanager.workflow.repository.domain.WorkflowSnapshotDO; import com.alibaba.tesla.appmanager.workflow.service.WorkflowSnapshotService; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.exception.ExceptionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -56,6 +58,48 @@ public class WorkflowSnapshotServiceImpl implements WorkflowSnapshotService { return Pagination.valueOf(result, Function.identity()); } + /** + * 对指定的 Workflow 实例 put context 对象,进行 Merge + * + * @param workflowInstanceId Workflow 实例 ID + * @param context Context 对象 (JSONObject) + * @return 更新后的指定 workflow task 对应的 workflow snapshot 对象 + */ + @Override + public WorkflowSnapshotDO putContext(Long workflowInstanceId, JSONObject context) { + if (context == null || context.size() == 0) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, "null context to be set"); + } + List result = workflowSnapshotRepository + .selectByCondition(WorkflowSnapshotQueryCondition.builder() + .instanceId(workflowInstanceId) + .build()); + if (result.size() == 0) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("cannot find workflow snapshot|workflowInstanceId=%d", workflowInstanceId)); + } + WorkflowSnapshotDO record = result.get(0); + String dbContextStr = record.getSnapshotContext(); + if (StringUtils.isEmpty(dbContextStr)) { + throw new AppException(AppErrorCode.UNKNOWN_ERROR, + String.format("unknown error, the workflow snapshot context is empty|snapshot=%s", + JSONObject.toJSONString(record))); + } + JSONObject dbContext = JSONObject.parseObject(dbContextStr); + dbContext.putAll(context); + record.setSnapshotContext(JSONObject.toJSONString(dbContext)); + int count = workflowSnapshotRepository.updateByCondition(record, WorkflowSnapshotQueryCondition.builder() + .instanceId(record.getWorkflowInstanceId()) + .taskId(record.getWorkflowTaskId()) + .build()); + if (count != 1) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("cannot update workflow snapshot when put user custom context|count=%d|record=%s", + count, JSONObject.toJSONString(record))); + } + return record; + } + /** * 更新一个 Workflow 快照 * @@ -87,7 +131,9 @@ public class WorkflowSnapshotServiceImpl implements WorkflowSnapshotService { } else { record = snapshots.getItems().get(0); record.setSnapshotContext(JSONObject.toJSONString(request.getContext())); - record.setSnapshotTask(SchemaUtil.toYamlMapStr(request.getConfiguration())); + if (request.getConfiguration() != null) { + record.setSnapshotTask(SchemaUtil.toYamlMapStr(request.getConfiguration())); + } record.setSnapshotWorkflow(null); workflowSnapshotRepository.updateByCondition(record, condition); } @@ -111,4 +157,67 @@ public class WorkflowSnapshotServiceImpl implements WorkflowSnapshotService { .build(); return workflowSnapshotRepository.deleteByCondition(condition); } + + /** + * 获取指定 Workflow Task 对应的 Context JSON Object 对象 + * + * @param workflowInstanceId Workflow 实例 ID + * @param workflowTaskId Workflow 任务 ID + * @return Context JSONObject (不存在时报错) + */ + @Override + public JSONObject getContext(Long workflowInstanceId, Long workflowTaskId) { + Pagination snapshots = list(WorkflowSnapshotQueryCondition.builder() + .instanceId(workflowInstanceId) + .taskId(workflowTaskId) + .build()); + if (snapshots.getItems().size() != 1) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("cannot find related workflow snapshot|workflowInstanceId=%d|workflowTaskId=%d|" + + "size=%d", workflowInstanceId, workflowTaskId, snapshots.getItems().size())); + } + String snapshotContextStr = snapshots.getItems().get(0).getSnapshotContext(); + if (StringUtils.isEmpty(snapshotContextStr)) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("empty workflow snapshot context|workflowInstanceId=%d|workflowTaskId=%d", + workflowInstanceId, workflowTaskId)); + } + try { + return JSONObject.parseObject(snapshotContextStr); + } catch (Exception e) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("cannot parse workflow snapshot context to json object|workflowInstanceId=%d|" + + "workflowTaskId=%d|contextStr=%s|exception=%s", workflowInstanceId, workflowTaskId, + snapshotContextStr, ExceptionUtils.getStackTrace(e))); + } + } + + /** + * 获取指定 Workflow Instance 对应的 Context JSON Object 对象 + * + * @param workflowInstanceId Workflow 实例 ID + * @return Context JSONObject (不存在时返回 null) + */ + @Override + public JSONObject getContext(Long workflowInstanceId) { + Pagination snapshots = list(WorkflowSnapshotQueryCondition.builder() + .instanceId(workflowInstanceId) + .build()); + if (snapshots.getItems().size() == 0) { + return null; + } + String snapshotContextStr = snapshots.getItems().get(0).getSnapshotContext(); + if (StringUtils.isEmpty(snapshotContextStr)) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("empty workflow snapshot context|workflowInstanceId=%d", workflowInstanceId)); + } + try { + return JSONObject.parseObject(snapshotContextStr); + } catch (Exception e) { + throw new AppException(AppErrorCode.INVALID_USER_ARGS, + String.format("cannot parse workflow snapshot context to json object|workflowInstanceId=%d|" + + "contextStr=%s|exception=%s", workflowInstanceId, snapshotContextStr, + ExceptionUtils.getStackTrace(e))); + } + } } diff --git a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/service/impl/WorkflowTaskServiceImpl.java b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/service/impl/WorkflowTaskServiceImpl.java index d4199375..1ed27bc1 100644 --- a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/service/impl/WorkflowTaskServiceImpl.java +++ b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/service/impl/WorkflowTaskServiceImpl.java @@ -1,7 +1,10 @@ package com.alibaba.tesla.appmanager.workflow.service.impl; +import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.alibaba.tesla.appmanager.autoconfig.ThreadPoolProperties; +import com.alibaba.tesla.appmanager.common.constants.DefaultConstant; +import com.alibaba.tesla.appmanager.common.constants.WorkflowContextKeyConstant; import com.alibaba.tesla.appmanager.common.enums.DynamicScriptKindEnum; import com.alibaba.tesla.appmanager.common.enums.WorkflowTaskStateEnum; import com.alibaba.tesla.appmanager.common.exception.AppErrorCode; @@ -23,11 +26,16 @@ import com.alibaba.tesla.appmanager.workflow.service.WorkflowSnapshotService; import com.alibaba.tesla.appmanager.workflow.service.WorkflowTaskService; import com.alibaba.tesla.appmanager.workflow.service.thread.ExecuteWorkflowTaskResult; import com.alibaba.tesla.appmanager.workflow.service.thread.ExecuteWorkflowTaskWaitingObject; +import com.jayway.jsonpath.DocumentContext; +import com.jayway.jsonpath.JsonPath; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.exception.ExceptionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; +import java.util.HashMap; import java.util.List; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; @@ -154,7 +162,6 @@ public class WorkflowTaskServiceImpl implements WorkflowTaskService { throw new AppException(AppErrorCode.NOT_READY, "system not ready"); } } - DeployAppSchema configuration = SchemaUtil.toSchema(DeployAppSchema.class, instance.getWorkflowConfiguration()); ExecuteWorkflowTaskWaitingObject waitingObject = ExecuteWorkflowTaskWaitingObject.create(task.getId()); threadPoolExecutor.submit(() -> { @@ -176,9 +183,10 @@ public class WorkflowTaskServiceImpl implements WorkflowTaskService { .taskId(task.getId()) .taskType(task.getTaskType()) .taskStage(task.getTaskStage()) - .taskProperties(JSONObject.parseObject(task.getTaskProperties())) + .taskProperties(plugTaskProperties(task, context)) .context(context) .configuration(configuration) + .creator(instance.getWorkflowCreator()) .build(); ExecuteWorkflowHandlerRes res; try { @@ -189,7 +197,11 @@ public class WorkflowTaskServiceImpl implements WorkflowTaskService { } catch (Throwable e) { ExecuteWorkflowTaskWaitingObject.triggerFinished( task.getId(), - ExecuteWorkflowTaskResult.builder().task(task).success(false).extMessage(e.toString()).build()); + ExecuteWorkflowTaskResult.builder() + .task(task) + .success(false) + .extMessage(ExceptionUtils.getStackTrace(e)) + .build()); return; } ExecuteWorkflowTaskWaitingObject.triggerFinished( @@ -212,7 +224,8 @@ public class WorkflowTaskServiceImpl implements WorkflowTaskService { } }, 5, TimeUnit.SECONDS); } catch (InterruptedException e) { - return markAbnormalWorkflowTask(task.getId(), WorkflowTaskStateEnum.EXCEPTION, e.toString()); + return markAbnormalWorkflowTask(task.getId(), WorkflowTaskStateEnum.EXCEPTION, + ExceptionUtils.getStackTrace(e)); } // 如果被终止或未运行成功,保存错误信息到 workflow task 中 @@ -227,18 +240,26 @@ public class WorkflowTaskServiceImpl implements WorkflowTaskService { // 创建返回结果;如果 workflow task 节点主动触发 suspend,那么直接触发进入 WAITING_SUSPEND ExecuteWorkflowHandlerRes output = result.getOutput(); WorkflowTaskDO returnedTask = get(task.getId(), true); + returnedTask.setTaskErrorMessage(""); if (output.isSuspend()) { returnedTask.setTaskStatus(WorkflowTaskStateEnum.WAITING_SUSPEND.toString()); + } else if (output.isTerminate()) { + returnedTask.setTaskStatus(WorkflowTaskStateEnum.TERMINATED.toString()); + if (StringUtils.isNotEmpty(output.getTerminateReason())) { + returnedTask.setTaskErrorMessage(output.getTerminateReason()); + } } else { returnedTask.setTaskStatus(WorkflowTaskStateEnum.SUCCESS.toString()); } - returnedTask.setTaskErrorMessage(""); if (output.getDeployAppId() != null && output.getDeployAppId() > 0) { returnedTask.setDeployAppId(output.getDeployAppId()); returnedTask.setDeployAppUnitId(output.getDeployAppUnitId()); returnedTask.setDeployAppNamespaceId(output.getDeployAppNamespaceId()); returnedTask.setDeployAppStageId(output.getDeployAppStageId()); } + if (output.getDeployWorkflowInstanceId() != null && output.getDeployWorkflowInstanceId() > 0) { + returnedTask.setDeployWorkflowInstanceId(output.getDeployWorkflowInstanceId()); + } // 保存 Workflow 快照 WorkflowSnapshotDO snapshot = workflowSnapshotService.update(UpdateWorkflowSnapshotReq.builder() @@ -289,4 +310,51 @@ public class WorkflowTaskServiceImpl implements WorkflowTaskService { task.setTaskErrorMessage(errorMessage); return task; } + + + /** + * 提取inputs参数,补充taskProperties + * + * @param task Workflow 任务 + * @param context 上下文 + */ + private JSONObject plugTaskProperties(WorkflowTaskDO task, JSONObject context) { + JSONObject taskProperties = JSONObject.parseObject(task.getTaskProperties()); + String taskInputs = task.getTaskInputs(); + if (StringUtils.isEmpty(taskInputs)) { + return taskProperties; + } + JSONArray inputs = JSONObject.parseArray(taskInputs); + if (inputs.size() == 0) { + return taskProperties; + } + JSONObject deliverData = context.getJSONObject(WorkflowContextKeyConstant.DEPLOY_DELIVER_PARAMETERS); + if (deliverData == null) { + return taskProperties; + } + + DocumentContext propertiesContext = JsonPath.parse(task.getTaskProperties()); + for (int i = 0; i < inputs.size(); i++) { + JSONObject input = inputs.getJSONObject(i); + String parameterKey = input.getString("parameterKey"); + int splitIndex = parameterKey.lastIndexOf("."); + if (splitIndex == -1) { + propertiesContext.set(DefaultConstant.JSONPATH_PREFIX + parameterKey, + deliverData.get(input.getString("from"))); + continue; + } + String inputPrefix = parameterKey.substring(0, splitIndex); + String inputSuffix = parameterKey.substring(splitIndex + 1); + HashMap prevJsonObject = propertiesContext + .read(DefaultConstant.JSONPATH_PREFIX + inputPrefix); + prevJsonObject.put(inputSuffix, deliverData.get(input.getString("from"))); + String currentValue = JSONObject.toJSONString(prevJsonObject); + propertiesContext.set(DefaultConstant.JSONPATH_PREFIX + inputPrefix, currentValue); + } + taskProperties = JSONObject.parseObject(propertiesContext.jsonString()); + log.info("plug task properties succeed|workflowTaskId={}|workflowInstanceId={}|deliverData={}|" + + "taskProperties={}", task.getId(), task.getWorkflowInstanceId(), deliverData.toJSONString(), + taskProperties.toJSONString()); + return taskProperties; + } } diff --git a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/util/WorkflowHandlerUtil.java b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/util/WorkflowHandlerUtil.java index 68a384b4..bed98ae8 100644 --- a/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/util/WorkflowHandlerUtil.java +++ b/paas/appmanager/tesla-appmanager-workflow/src/main/java/com/alibaba/tesla/appmanager/workflow/util/WorkflowHandlerUtil.java @@ -3,10 +3,13 @@ package com.alibaba.tesla.appmanager.workflow.util; import com.alibaba.fastjson.JSONObject; import com.alibaba.tesla.appmanager.api.provider.DeployAppProvider; import com.alibaba.tesla.appmanager.api.provider.UnitProvider; +import com.alibaba.tesla.appmanager.api.provider.WorkflowInstanceProvider; import com.alibaba.tesla.appmanager.common.enums.DynamicScriptKindEnum; import com.alibaba.tesla.appmanager.common.exception.AppErrorCode; import com.alibaba.tesla.appmanager.common.exception.AppException; import com.alibaba.tesla.appmanager.common.util.SchemaUtil; +import com.alibaba.tesla.appmanager.domain.dto.WorkflowInstanceDTO; +import com.alibaba.tesla.appmanager.domain.option.WorkflowInstanceOption; import com.alibaba.tesla.appmanager.domain.req.deploy.DeployAppLaunchReq; import com.alibaba.tesla.appmanager.domain.res.deploy.DeployAppPackageLaunchRes; import com.alibaba.tesla.appmanager.domain.schema.DeployAppSchema; @@ -61,20 +64,39 @@ public class WorkflowHandlerUtil { String.format("cannot find policy properties by policyName %s", policyName)); } + /** + * 执行部署 Workflow,并返回 Workflow Instance ID + * + * @param appId 应用 ID + * @param configuration Workflow 配置 + * @param option Workflow 发起选项 + * @return Workflow Instance ID + */ + public static Long deployWorkflow(String appId, String configuration, WorkflowInstanceOption option) { + WorkflowInstanceProvider workflowInstanceProvider = BeanUtil.getBean(WorkflowInstanceProvider.class); + if (workflowInstanceProvider == null) { + throw new AppException(AppErrorCode.UNKNOWN_ERROR, "cannot find WorkflowInstanceProvider bean"); + } + WorkflowInstanceDTO instance = workflowInstanceProvider.launch(appId, configuration, option); + return instance.getId(); + } + /** * 执行部署,并返回部署单 ID * - * @param configuration 部署配置文件 - * @param creator 创建者 + * @param configuration 部署配置文件 + * @param overwriteParameters 覆盖全局参数 (可为 null) + * @param creator 创建者 * @return 部署单 ID */ - public static Long deploy(DeployAppSchema configuration, String creator) { + public static Long deploy(DeployAppSchema configuration, JSONObject overwriteParameters, String creator) { DeployAppProvider deployAppProvider = BeanUtil.getBean(DeployAppProvider.class); if (deployAppProvider == null) { throw new AppException(AppErrorCode.UNKNOWN_ERROR, "cannot find DeployAppProvider bean"); } DeployAppLaunchReq req = DeployAppLaunchReq.builder() .configuration(SchemaUtil.toYamlMapStr(configuration)) + .overwriteParameters(overwriteParameters) .build(); DeployAppPackageLaunchRes res = deployAppProvider.launch(req, creator); return res.getDeployAppId(); diff --git a/paas/appmanager/tesla-appmanager-workflow/src/main/resources/mybatis/WorkflowInstanceDOMapper.xml b/paas/appmanager/tesla-appmanager-workflow/src/main/resources/mybatis/WorkflowInstanceDOMapper.xml index 2d2dfae2..7c482352 100644 --- a/paas/appmanager/tesla-appmanager-workflow/src/main/resources/mybatis/WorkflowInstanceDOMapper.xml +++ b/paas/appmanager/tesla-appmanager-workflow/src/main/resources/mybatis/WorkflowInstanceDOMapper.xml @@ -8,6 +8,7 @@ + @@ -85,8 +86,8 @@ - id, gmt_create, gmt_modified, app_id, gmt_start, gmt_end, workflow_status, workflow_sha256, - workflow_creator, lock_version, client_host + id, gmt_create, gmt_modified, app_id, category, gmt_start, gmt_end, workflow_status, + workflow_sha256, workflow_creator, lock_version, client_host @@ -140,6 +141,9 @@ app_id, + + category, + gmt_start, @@ -181,6 +185,9 @@ #{appId,jdbcType=VARCHAR}, + + #{category,jdbcType=VARCHAR}, + #{gmtStart,jdbcType=TIMESTAMP}, diff --git a/paas/appmanager/tesla-appmanager-workflow/src/main/resources/mybatis/WorkflowTaskDOMapper.xml b/paas/appmanager/tesla-appmanager-workflow/src/main/resources/mybatis/WorkflowTaskDOMapper.xml index 9ba0f5eb..43fba6f3 100644 --- a/paas/appmanager/tesla-appmanager-workflow/src/main/resources/mybatis/WorkflowTaskDOMapper.xml +++ b/paas/appmanager/tesla-appmanager-workflow/src/main/resources/mybatis/WorkflowTaskDOMapper.xml @@ -19,11 +19,14 @@ + + + @@ -90,11 +93,11 @@ id, gmt_create, gmt_modified, workflow_instance_id, app_id, gmt_start, gmt_end, task_type, task_stage, task_status, deploy_app_id, lock_version, deploy_app_unit_id, deploy_app_namespace_id, - deploy_app_stage_id + deploy_app_stage_id, deploy_workflow_instance_id - task_properties, task_error_message + task_properties, task_outputs, task_inputs, task_error_message