diff --git a/.github/workflows/maven-build.yml b/.github/workflows/maven-build.yml index b3141dfc8d9..079baa79e51 100644 --- a/.github/workflows/maven-build.yml +++ b/.github/workflows/maven-build.yml @@ -22,3 +22,19 @@ jobs: java-version: 11 - name: Build with Maven run: mvn clean -B package --file pom.xml + - name: Build Image + env: + IMAGE_PUSH: false + IMAGE_LOAD: true + IMAGE_PLATFORM: linux/amd64 + run: | + docker buildx create --use --name mybuilder --driver docker-container + docker buildx use mybuilder + + ./script/docker/server/build.sh + - name: Run E2E + run: | + sudo curl -L https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose + sudo chmod u+x /usr/local/bin/docker-compose + + cd e2e && ./start.sh diff --git a/.gitpod.yml b/.gitpod.yml new file mode 100644 index 00000000000..9828af3c206 --- /dev/null +++ b/.gitpod.yml @@ -0,0 +1,8 @@ +# This configuration file was automatically generated by Gitpod. +# Please adjust to your needs (see https://www.gitpod.io/docs/introduction/learn-gitpod/gitpod-yaml) +# and commit this file to your remote git repository to share the goodness with others. + +# Learn more from ready-to-use templates: https://www.gitpod.io/docs/introduction/getting-started/quickstart + +tasks: + - init: mvn install -DskipTests=false diff --git a/README.md b/README.md index 03d86972405..464e615e731 100644 --- a/README.md +++ b/README.md @@ -431,7 +431,7 @@ WeChat Group : Add friend `tan-cloud`, and will invite you to the group. - [Jpom](https://gitee.com/dromara/Jpom) : 简而轻的低侵入式在线构建、自动部署、日常运维、项目监控软件 - [ArgusDBM](https://github.com/zmops/ArgusDBM) : 开源数据库一体化监控平台,致力于监控所有数据库 - [WangMarket](http://www.wang.market/) : 开源 SAAS 云建站系统 - +- [API Testing](https://github.com/LinuxSuRen/api-testing):轻量级、可扩展的接口开发、测试工具 ##### Sponsor diff --git a/README_CN.md b/README_CN.md index 5b171897979..a5444271221 100644 --- a/README_CN.md +++ b/README_CN.md @@ -436,6 +436,7 @@ HertzBeat 赫兹跳动是 [Dromara开源社区](https://dromara.org/) 下顶级 - [Jpom](https://gitee.com/dromara/Jpom) : 简而轻的低侵入式在线构建、自动部署、日常运维、项目监控软件 - [ArgusDBM](https://github.com/zmops/ArgusDBM) : 开源数据库一体化监控平台,致力于监控所有数据库 - [WangMarket](http://www.wang.market/) : 开源 SAAS 云建站系统 +- [API Testing](https://github.com/LinuxSuRen/api-testing):轻量级、可扩展的接口开发、测试工具 ##### 赞助 diff --git a/e2e/Dockerfile b/e2e/Dockerfile new file mode 100644 index 00000000000..4e0ea4f2458 --- /dev/null +++ b/e2e/Dockerfile @@ -0,0 +1,6 @@ +FROM ghcr.io/linuxsuren/api-testing:master + +WORKDIR /workspace +COPY . . + +CMD [ "/workspace/entrypoint.sh" ] diff --git a/e2e/Makefile b/e2e/Makefile new file mode 100644 index 00000000000..6360b5d7238 --- /dev/null +++ b/e2e/Makefile @@ -0,0 +1,2 @@ +demo: + docker compose up hertzbeat diff --git a/e2e/RADME.md b/e2e/RADME.md new file mode 100644 index 00000000000..b4d7a1bc39f --- /dev/null +++ b/e2e/RADME.md @@ -0,0 +1,14 @@ +Please add the corresponding e2e (aka end-to-end) test cases if you add or update APIs. + +## How to work +* Start and watch the [docker-compose](https://docs.docker.com/compose/) via [the script](start.sh) +* Run the e2e testing via [api-testing](https://github.com/LinuxSuRen/api-testing) + * It will run the test cases from top to bottom + * You can add the necessary asserts to it + +## Run locally +Please follow these steps if you want to run the e2e testing locally. + +> Please make sure you have installed docker-compose v2 + +* Change the directory to `e2e`, then execute `./start.sh` diff --git a/e2e/compose.yaml b/e2e/compose.yaml new file mode 100644 index 00000000000..0e43f555e18 --- /dev/null +++ b/e2e/compose.yaml @@ -0,0 +1,24 @@ +version: '3.1' +services: + testing: + build: + context: . + environment: + SERVER: http://hertzbeat:1157 + depends_on: + hertzbeat: + condition: service_healthy + links: + - hertzbeat + hertzbeat: + image: tancloud/hertzbeat + ports: + - 1157:1157 + environment: + ALLOW_NONE_AUTHENTICATION: "yes" + healthcheck: + test: ["CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/1157"] + interval: 3s + timeout: 60s + retries: 10 + start_period: 3s diff --git a/e2e/data/monitor-http.json b/e2e/data/monitor-http.json new file mode 100644 index 00000000000..06fd46b9a67 --- /dev/null +++ b/e2e/data/monitor-http.json @@ -0,0 +1,80 @@ + +{ + "detected": false, + "collector": "", + "monitor": { + "intervals": 60, + "tags": [], + "app": "api", + "host": "127.0.0.1", + "name": "{{.param.monitorHTTP}}" + }, + "params": [ + { + "field": "host", + "type": 1, + "value": "127.0.0.1" + }, + { + "field": "port", + "type": 0, + "value": 80 + }, + { + "field": "method", + "type": 1, + "value": "GET" + }, + { + "field": "uri", + "type": 1, + "value": "" + }, + { + "field": "ssl", + "type": 1, + "value": false + }, + { + "field": "headers", + "type": 3 + }, + { + "field": "params", + "type": 3 + }, + { + "field": "timeout", + "type": 0 + }, + { + "field": "contentType", + "type": 1 + }, + { + "field": "payload", + "type": 1 + }, + { + "field": "authType", + "type": 1 + }, + { + "field": "username", + "type": 1 + }, + { + "field": "password", + "type": 1 + }, + { + "field": "keyword", + "type": 1 + }, + { + "field": "successCode", + "type": 4, + "value": "200, 201" + } + ] +} diff --git a/e2e/entrypoint.sh b/e2e/entrypoint.sh new file mode 100755 index 00000000000..205c5fc746d --- /dev/null +++ b/e2e/entrypoint.sh @@ -0,0 +1,4 @@ +#!/bin/bash +set -e + +atest run -p testsuite.yaml --report md diff --git a/e2e/start.sh b/e2e/start.sh new file mode 100755 index 00000000000..0df1b059295 --- /dev/null +++ b/e2e/start.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +file=$1 +if [ "$file" == "" ] +then + file=compose.yaml +fi + +docker-compose version +docker-compose -f "$file" up --build -d + +while true +do + docker-compose -f "$file" ps | grep testing + if [ $? -eq 1 ] + then + code=-1 + docker-compose -f "$file" logs | grep e2e-testing + docker-compose -f "$file" logs | grep e2e-testing | grep Usage + if [ $? -eq 1 ] + then + code=0 + echo "successed" + fi + + docker-compose -f "$file" down + set -e + exit $code + fi + sleep 1 +done diff --git a/e2e/testsuite.yaml b/e2e/testsuite.yaml new file mode 100644 index 00000000000..ec6b92e5e68 --- /dev/null +++ b/e2e/testsuite.yaml @@ -0,0 +1,222 @@ +#!api-testing +# yaml-language-server: $schema=https://linuxsuren.github.io/api-testing/api-testing-schema.json +name: hertzbeat +api: | + {{default "http://localhost:1157" (env "SERVER")}} +param: + monitorHTTP: "{{randAlpha 6}}" + tagName: "{{randAlpha 3}}" +items: +- name: login + request: + api: /api/account/auth/form + method: POST + header: + Content-type: application/json + body: | + { + "type": 0, + "identifier": "admin", + "credential": "hertzbeat" + } + expect: + bodyFieldsExpect: + code: "0" +- name: login-missing-content-type + request: + api: /api/account/auth/form + method: POST + body: | + { + "type": 0, + "identifier": "admin", + "credential": "hertzbeat" + } + expect: + statusCode: 409 +- name: missing-auth-header + request: + api: /api/monitors + expect: + statusCode: 401 +- name: monitorList + request: + api: /api/monitors?pageIndex=0&pageSize=8 + header: + Authorization: Bearer {{.login.data.token}} + expect: + bodyFieldsExpect: + code: 0 +- name: createHTTPMonitor + request: + api: /api/monitor + method: POST + header: + Authorization: Bearer {{.login.data.token}} + Content-type: application/json + bodyFromFile: data/monitor-http.json +- name: listHTTPMonitor + request: + api: /api/monitors + query: + pageIndex: 0 + pageSize: 8 + app: api + header: + Authorization: Bearer {{.login.data.token}} +- name: cancelHTTPMonitor + request: + api: /api/monitors/manage + query: + ids: "{{(index .listHTTPMonitor.data.content 0).id}}" + type: JSON + method: DELETE + header: + Authorization: Bearer {{.login.data.token}} +- name: deleteHTTPMonitor + request: + api: /api/monitors + query: + ids: "{{(index .listHTTPMonitor.data.content 0).id}}" + method: DELETE + header: + Authorization: Bearer {{.login.data.token}} +- name: listAlertDefines + request: + api: /api/alert/defines + header: + Authorization: Bearer {{.login.data.token}} +- name: deleteAlertDefine + request: + api: /api/alert/defines + query: + ids: "{{(index .listAlertDefine.data.content 0).id}}" + method: DELETE + header: + Authorization: Bearer {{.login.data.token}} +- name: listAlertConverges + request: + api: /api/alert/converges + header: + Authorization: Bearer {{.login.data.token}} +- name: listAlertSilences + request: + api: /api/alert/silences + header: + Authorization: Bearer {{.login.data.token}} +- name: listAlerts + request: + api: /api/alerts + header: + Authorization: Bearer {{.login.data.token}} +- name: listReceivers + request: + api: /api/notice/receivers + header: + Authorization: Bearer {{.login.data.token}} +- name: listRules + request: + api: /api/notice/rules + header: + Authorization: Bearer {{.login.data.token}} +- name: listTemplates + request: + api: /api/notice/templates + header: + Authorization: Bearer {{.login.data.token}} +- name: listCollectors + request: + api: /api/collector + header: + Authorization: Bearer {{.login.data.token}} + +## Tag +- name: createTag + request: + api: /api/tag + method: POST + header: + Authorization: Bearer {{.login.data.token}} + Content-type: application/json + body: | + [ + { + "color": "#ff4081", + "name": "{{.param.tagName}}" + } + ] +- name: listTags + request: + api: /api/tag + header: + Authorization: Bearer {{.login.data.token}} +- name: updateTag + request: + api: /api/tag + method: PUT + header: + Authorization: Bearer {{.login.data.token}} + Content-type: application/json + body: | + { + "id": {{(index .listTags.data.content 0).id}}, + "name": "{{randAlpha 3}}", + "value": "{{randAlpha 3}}", + "color": "#ff4081", + "type": 1, + "creator": "admin", + "modifier": "admin" + } + expect: + bodyFieldsExpect: + code: "0" +- name: deleteTag + request: + api: /api/tag + query: + ids: "{{(index .listTags.data.content 0).id}}" + method: DELETE + header: + Authorization: Bearer {{.login.data.token}} + +## Config +- name: getConfigEmail + request: + api: /api/config/email + header: + Authorization: Bearer {{.login.data.token}} +- name: getConfigSystem + request: + api: /api/config/system + header: + Authorization: Bearer {{.login.data.token}} +- name: updateSystem + request: + api: /api/config/system + method: POST + body: | + { + "timeZoneId": "Asia/Shanghai", + "locale": "en_US", + "theme": null + } + header: + Authorization: Bearer {{.login.data.token}} + Content-type: application/json +- name: getConfigOSS + request: + api: /api/config/oss + header: + Authorization: Bearer {{.login.data.token}} +- name: updateOSS + request: + api: /api/config/oss + method: POST + body: | + { + "type": "FILE", + "config": {} + } + header: + Authorization: Bearer {{.login.data.token}} + Content-type: application/json diff --git a/script/docker/server/build.sh b/script/docker/server/build.sh old mode 100644 new mode 100755 index edf125118b2..a2dca654585 --- a/script/docker/server/build.sh +++ b/script/docker/server/build.sh @@ -31,7 +31,7 @@ fi # 编译上下文目录 CONTEXT_DIR=`pwd` -COMMAND="docker buildx build --platform linux/arm64,linux/amd64 -t tancloud/hertzbeat:v$VERSION -f $CURRENT_DIR/Dockerfile $CONTEXT_DIR --build-arg VERSION="$VERSION" --push" +COMMAND="docker buildx build --platform ${IMAGE_PLATFORM:-linux/arm64,linux/amd64} -t tancloud/hertzbeat:v$VERSION -f $CURRENT_DIR/Dockerfile $CONTEXT_DIR --build-arg VERSION="$VERSION" --push=${IMAGE_PUSH:-true} --load=${IMAGE_LOAD:-false}" #COMMAND="docker buildx build --platform linux/arm64,linux/amd64 -t tancloud/hertzbeat:latest -f $CURRENT_DIR/Dockerfile $CONTEXT_DIR --build-arg VERSION="$VERSION" --push" @@ -46,5 +46,6 @@ COMMAND="docker buildx build --platform linux/arm64,linux/amd64 -t tancloud/hert echo "$COMMAND" $COMMAND +docker tag tancloud/hertzbeat:v$VERSION tancloud/hertzbeat #docker build -t tancloud/hertzbeat:latest -f $CURRENT_DIR/Dockerfile $CONTEXT_DIR --build-arg VERSION="$VERSION"