Browse Source
* add feature_10411 * add feature_10411 * update README.md * fix README.md deadlink * fix error log output * fix comment3.1.0-release
xiangzihao
2 years ago
committed by
GitHub
30 changed files with 2220 additions and 0 deletions
@ -0,0 +1,139 @@
|
||||
# |
||||
# Licensed to the Apache Software Foundation (ASF) under one or more |
||||
# contributor license agreements. See the NOTICE file distributed with |
||||
# this work for additional information regarding copyright ownership. |
||||
# The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
# (the "License"); you may not use this file except in compliance with |
||||
# the License. You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
# |
||||
|
||||
on: |
||||
pull_request: |
||||
push: |
||||
branches: |
||||
- dev |
||||
|
||||
name: API-Test |
||||
|
||||
concurrency: |
||||
group: api-test-${{ github.event.pull_request.number || github.ref }} |
||||
cancel-in-progress: true |
||||
|
||||
|
||||
jobs: |
||||
paths-filter: |
||||
name: API-Test-Path-Filter |
||||
runs-on: ubuntu-latest |
||||
outputs: |
||||
not-ignore: ${{ steps.filter.outputs.not-ignore }} |
||||
steps: |
||||
- uses: actions/checkout@v2 |
||||
- uses: dorny/paths-filter@b2feaf19c27470162a626bd6fa8438ae5b263721 |
||||
id: filter |
||||
with: |
||||
filters: | |
||||
not-ignore: |
||||
- '!(docs/**)' |
||||
build: |
||||
name: API-Test-Build |
||||
needs: paths-filter |
||||
if: ${{ (needs.paths-filter.outputs.not-ignore == 'true') || (github.event_name == 'push') }} |
||||
runs-on: ubuntu-latest |
||||
timeout-minutes: 20 |
||||
steps: |
||||
- uses: actions/checkout@v2 |
||||
with: |
||||
submodules: true |
||||
- name: Sanity Check |
||||
uses: ./.github/actions/sanity-check |
||||
- name: Cache local Maven repository |
||||
uses: actions/cache@v3 |
||||
with: |
||||
path: ~/.m2/repository |
||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} |
||||
restore-keys: ${{ runner.os }}-maven- |
||||
- name: Build Image |
||||
run: | |
||||
./mvnw -B clean install \ |
||||
-Dmaven.test.skip \ |
||||
-Dmaven.javadoc.skip \ |
||||
-Dmaven.checkstyle.skip \ |
||||
-Pdocker,release -Ddocker.tag=ci \ |
||||
-pl dolphinscheduler-standalone-server -am |
||||
- name: Export Docker Images |
||||
run: | |
||||
docker save apache/dolphinscheduler-standalone-server:ci -o /tmp/standalone-image.tar \ |
||||
&& du -sh /tmp/standalone-image.tar |
||||
- uses: actions/upload-artifact@v2 |
||||
name: Upload Docker Images |
||||
with: |
||||
name: standalone-image |
||||
path: /tmp/standalone-image.tar |
||||
retention-days: 1 |
||||
api-test: |
||||
name: ${{ matrix.case.name }} |
||||
needs: build |
||||
runs-on: ubuntu-latest |
||||
timeout-minutes: 30 |
||||
strategy: |
||||
matrix: |
||||
case: |
||||
- name: Tenant |
||||
class: org.apache.dolphinscheduler.api.test.cases.TenantAPITest |
||||
env: |
||||
RECORDING_PATH: /tmp/recording-${{ matrix.case.name }} |
||||
steps: |
||||
- uses: actions/checkout@v2 |
||||
with: |
||||
submodules: true |
||||
- name: Cache local Maven repository |
||||
uses: actions/cache@v3 |
||||
with: |
||||
path: ~/.m2/repository |
||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} |
||||
restore-keys: ${{ runner.os }}-maven- |
||||
- uses: actions/download-artifact@v2 |
||||
name: Download Docker Images |
||||
with: |
||||
name: standalone-image |
||||
path: /tmp |
||||
- name: Load Docker Images |
||||
run: | |
||||
docker load -i /tmp/standalone-image.tar |
||||
- name: Run Test |
||||
run: | |
||||
./mvnw -B -f dolphinscheduler-api-test/pom.xml -am \ |
||||
-DfailIfNoTests=false \ |
||||
-Dtest=${{ matrix.case.class }} test |
||||
- uses: actions/upload-artifact@v2 |
||||
if: always() |
||||
name: Upload Recording |
||||
with: |
||||
name: recording-${{ matrix.case.name }} |
||||
path: ${{ env.RECORDING_PATH }} |
||||
retention-days: 1 |
||||
result: |
||||
name: API-Test-Result |
||||
runs-on: ubuntu-latest |
||||
timeout-minutes: 30 |
||||
needs: [ api-test, paths-filter ] |
||||
if: always() |
||||
steps: |
||||
- name: Status |
||||
run: | |
||||
if [[ ${{ needs.paths-filter.outputs.not-ignore }} == 'false' && ${{ github.event_name }} == 'pull_request' ]]; then |
||||
echo "Skip API Test!" |
||||
exit 0 |
||||
fi |
||||
if [[ ${{ needs.api-test.result }} != 'success' ]]; then |
||||
echo "API test Failed!" |
||||
exit -1 |
||||
fi |
@ -0,0 +1,44 @@
|
||||
# DolphinScheduler Backend API Test |
||||
|
||||
## Page Object Model |
||||
|
||||
DolphinScheduler API test respects |
||||
the [Page Object Model (POM)](https://www.selenium.dev/documentation/guidelines/page_object_models/) design pattern. |
||||
Every page of DolphinScheduler's api is abstracted into a class for better maintainability. |
||||
|
||||
### Example |
||||
|
||||
The login page's api is abstracted |
||||
as [`LoginPage`](dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api.test/pages/LoginPage.java), with the |
||||
following fields, |
||||
|
||||
```java |
||||
public HttpResponse login(String username, String password) { |
||||
Map<String, Object> params = new HashMap<>(); |
||||
|
||||
params.put("userName", username); |
||||
params.put("userPassword", password); |
||||
|
||||
RequestClient requestClient = new RequestClient(); |
||||
|
||||
return requestClient.post("/login", null, params); |
||||
} |
||||
``` |
||||
|
||||
where `userName`, `userPassword` are the main elements on UI that we are interested in. |
||||
|
||||
## Test Environment Setup |
||||
|
||||
DolphinScheduler API test uses [testcontainers](https://www.testcontainers.org) to set up the testing |
||||
environment, with docker compose. |
||||
|
||||
Typically, every test case needs one or more `docker-compose.yaml` files to set up all needed components, and expose the |
||||
DolphinScheduler UI port for testing. You can use `@DolphinScheduler(composeFiles = "")` and pass |
||||
the `docker-compose.yaml` files to automatically set up the environment in the test class. |
||||
|
||||
```java |
||||
|
||||
@DolphinScheduler(composeFiles = "docker/tenant/docker-compose.yaml") |
||||
class TenantAPITest { |
||||
} |
||||
``` |
@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!-- |
||||
~ Licensed to Apache Software Foundation (ASF) under one or more contributor |
||||
~ license agreements. See the NOTICE file distributed with |
||||
~ this work for additional information regarding copyright |
||||
~ ownership. Apache Software Foundation (ASF) licenses this file to you under |
||||
~ the Apache License, Version 2.0 (the "License"); you may |
||||
~ not use this file except in compliance with the License. |
||||
~ You may obtain a copy of the License at |
||||
~ |
||||
~ http://www.apache.org/licenses/LICENSE-2.0 |
||||
~ |
||||
~ Unless required by applicable law or agreed to in writing, |
||||
~ software distributed under the License is distributed on an |
||||
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
||||
~ KIND, either express or implied. See the License for the |
||||
~ specific language governing permissions and limitations |
||||
~ under the License. |
||||
--> |
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" |
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||
<parent> |
||||
<artifactId>dolphinscheduler-api-test</artifactId> |
||||
<groupId>org.apache.dolphinscheduler</groupId> |
||||
<version>1.0-SNAPSHOT</version> |
||||
</parent> |
||||
<modelVersion>4.0.0</modelVersion> |
||||
|
||||
<artifactId>dolphinscheduler-api-test-case</artifactId> |
||||
|
||||
<dependencies> |
||||
<dependency> |
||||
<groupId>org.apache.dolphinscheduler</groupId> |
||||
<artifactId>dolphinscheduler-api-test-core</artifactId> |
||||
<version>${project.version}</version> |
||||
</dependency> |
||||
</dependencies> |
||||
</project> |
@ -0,0 +1,113 @@
|
||||
/* |
||||
* Licensed to Apache Software Foundation (ASF) under one or more contributor |
||||
* license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright |
||||
* ownership. Apache Software Foundation (ASF) licenses this file to you under |
||||
* the Apache License, Version 2.0 (the "License"); you may |
||||
* not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, |
||||
* software distributed under the License is distributed on an |
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
||||
* KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations |
||||
* under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.api.test.cases; |
||||
|
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.apache.dolphinscheduler.api.test.core.DolphinScheduler; |
||||
import org.apache.dolphinscheduler.api.test.entity.HttpResponse; |
||||
import org.apache.dolphinscheduler.api.test.entity.LoginResponseData; |
||||
import org.apache.dolphinscheduler.api.test.entity.TenantListPagingResponseData; |
||||
import org.apache.dolphinscheduler.api.test.entity.TenantListPagingResponseTotalList; |
||||
import org.apache.dolphinscheduler.api.test.pages.LoginPage; |
||||
import org.apache.dolphinscheduler.api.test.pages.security.TenantPage; |
||||
import org.apache.dolphinscheduler.api.test.utils.JSONUtils; |
||||
import org.junit.jupiter.api.AfterAll; |
||||
import org.junit.jupiter.api.Assertions; |
||||
import org.junit.jupiter.api.BeforeAll; |
||||
import org.junit.jupiter.api.Order; |
||||
import org.junit.jupiter.api.Test; |
||||
|
||||
|
||||
@DolphinScheduler(composeFiles = "docker/basic/docker-compose.yaml") |
||||
@Slf4j |
||||
public class TenantAPITest { |
||||
private static final String tenant = System.getProperty("user.name"); |
||||
|
||||
private static final String user = "admin"; |
||||
|
||||
private static final String password = "dolphinscheduler123"; |
||||
|
||||
private static String sessionId = null; |
||||
|
||||
private static Integer existTenantId = null; |
||||
|
||||
@BeforeAll |
||||
public static void setup() { |
||||
LoginPage loginPage = new LoginPage(); |
||||
HttpResponse loginHttpResponse = loginPage.login(user, password); |
||||
|
||||
sessionId = JSONUtils.convertValue(loginHttpResponse.body().data(), LoginResponseData.class).sessionId(); |
||||
} |
||||
|
||||
@AfterAll |
||||
public static void cleanup() { |
||||
LOGGER.info("success cleanup"); |
||||
} |
||||
|
||||
@Test |
||||
@Order(1) |
||||
public void testCreateTenant() { |
||||
TenantPage tenantPage = new TenantPage(); |
||||
|
||||
HttpResponse createTenantHttpResponse = tenantPage.createTenant(sessionId, tenant, 1, ""); |
||||
|
||||
Assertions.assertTrue(createTenantHttpResponse.body().success()); |
||||
} |
||||
|
||||
@Test |
||||
@Order(2) |
||||
public void testDuplicateCreateTenant() { |
||||
TenantPage tenantPage = new TenantPage(); |
||||
|
||||
HttpResponse createTenantHttpResponse = tenantPage.createTenant(sessionId, tenant, 1, ""); |
||||
|
||||
Assertions.assertFalse(createTenantHttpResponse.body().success()); |
||||
} |
||||
|
||||
@Test |
||||
@Order(5) |
||||
public void testGetTenantListPaging() { |
||||
TenantPage tenantPage = new TenantPage(); |
||||
|
||||
HttpResponse createTenantHttpResponse = tenantPage.getTenantListPaging(sessionId, 1, 10, ""); |
||||
boolean result = false; |
||||
|
||||
for (TenantListPagingResponseTotalList tenantListPagingResponseTotalList : JSONUtils.convertValue(createTenantHttpResponse.body().data(), TenantListPagingResponseData.class).totalList()) { |
||||
if (tenantListPagingResponseTotalList.tenantCode().equals(tenant)) { |
||||
result = true; |
||||
existTenantId = tenantListPagingResponseTotalList.id(); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
Assertions.assertTrue(createTenantHttpResponse.body().success()); |
||||
Assertions.assertTrue(result); |
||||
} |
||||
|
||||
@Test |
||||
@Order(10) |
||||
public void testDeleteTenant() { |
||||
TenantPage tenantPage = new TenantPage(); |
||||
|
||||
HttpResponse deleteTenantHttpResponse = tenantPage.deleteTenant(sessionId, existTenantId); |
||||
|
||||
Assertions.assertTrue(deleteTenantHttpResponse.body().success()); |
||||
} |
||||
} |
@ -0,0 +1,34 @@
|
||||
/* |
||||
* Licensed to Apache Software Foundation (ASF) under one or more contributor |
||||
* license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright |
||||
* ownership. Apache Software Foundation (ASF) licenses this file to you under |
||||
* the Apache License, Version 2.0 (the "License"); you may |
||||
* not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, |
||||
* software distributed under the License is distributed on an |
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
||||
* KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations |
||||
* under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.api.test.entity; |
||||
|
||||
import lombok.AllArgsConstructor; |
||||
import lombok.Data; |
||||
import lombok.NoArgsConstructor; |
||||
|
||||
@AllArgsConstructor |
||||
@NoArgsConstructor |
||||
@Data |
||||
public class HttpResponse { |
||||
|
||||
private int statusCode; |
||||
|
||||
private HttpResponseBody body; |
||||
} |
@ -0,0 +1,40 @@
|
||||
/* |
||||
* Licensed to Apache Software Foundation (ASF) under one or more contributor |
||||
* license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright |
||||
* ownership. Apache Software Foundation (ASF) licenses this file to you under |
||||
* the Apache License, Version 2.0 (the "License"); you may |
||||
* not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, |
||||
* software distributed under the License is distributed on an |
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
||||
* KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations |
||||
* under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.api.test.entity; |
||||
|
||||
import lombok.AllArgsConstructor; |
||||
import lombok.Data; |
||||
import lombok.NoArgsConstructor; |
||||
|
||||
@AllArgsConstructor |
||||
@NoArgsConstructor |
||||
@Data |
||||
public class HttpResponseBody { |
||||
|
||||
private Integer code; |
||||
|
||||
private String msg; |
||||
|
||||
private Object data; |
||||
|
||||
private Boolean failed; |
||||
|
||||
private Boolean success; |
||||
} |
@ -0,0 +1,32 @@
|
||||
/* |
||||
* Licensed to Apache Software Foundation (ASF) under one or more contributor |
||||
* license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright |
||||
* ownership. Apache Software Foundation (ASF) licenses this file to you under |
||||
* the Apache License, Version 2.0 (the "License"); you may |
||||
* not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, |
||||
* software distributed under the License is distributed on an |
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
||||
* KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations |
||||
* under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.api.test.entity; |
||||
|
||||
import lombok.AllArgsConstructor; |
||||
import lombok.Data; |
||||
import lombok.NoArgsConstructor; |
||||
|
||||
@AllArgsConstructor |
||||
@NoArgsConstructor |
||||
@Data |
||||
public class LoginResponseData { |
||||
|
||||
private String sessionId; |
||||
} |
@ -0,0 +1,43 @@
|
||||
/* |
||||
* Licensed to Apache Software Foundation (ASF) under one or more contributor |
||||
* license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright |
||||
* ownership. Apache Software Foundation (ASF) licenses this file to you under |
||||
* the Apache License, Version 2.0 (the "License"); you may |
||||
* not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, |
||||
* software distributed under the License is distributed on an |
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
||||
* KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations |
||||
* under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.api.test.entity; |
||||
|
||||
import lombok.AllArgsConstructor; |
||||
import lombok.Data; |
||||
import lombok.NoArgsConstructor; |
||||
|
||||
import java.util.List; |
||||
|
||||
@AllArgsConstructor |
||||
@NoArgsConstructor |
||||
@Data |
||||
public class TenantListPagingResponseData { |
||||
private Integer currentPage; |
||||
|
||||
private Integer pageSize; |
||||
|
||||
private Integer start; |
||||
|
||||
private Integer total; |
||||
|
||||
private List<TenantListPagingResponseTotalList> totalList; |
||||
|
||||
private Integer totalPage; |
||||
} |
@ -0,0 +1,47 @@
|
||||
/* |
||||
* Licensed to Apache Software Foundation (ASF) under one or more contributor |
||||
* license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright |
||||
* ownership. Apache Software Foundation (ASF) licenses this file to you under |
||||
* the Apache License, Version 2.0 (the "License"); you may |
||||
* not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, |
||||
* software distributed under the License is distributed on an |
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
||||
* KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations |
||||
* under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.api.test.entity; |
||||
|
||||
import lombok.AllArgsConstructor; |
||||
import lombok.Data; |
||||
import lombok.NoArgsConstructor; |
||||
|
||||
import java.util.Date; |
||||
|
||||
@AllArgsConstructor |
||||
@NoArgsConstructor |
||||
@Data |
||||
public class TenantListPagingResponseTotalList { |
||||
private Date createTime; |
||||
|
||||
private Date updateTime; |
||||
|
||||
private String description; |
||||
|
||||
private Integer id; |
||||
|
||||
private String queue; |
||||
|
||||
private Integer queueId; |
||||
|
||||
private String queueName; |
||||
|
||||
private String tenantCode; |
||||
} |
@ -0,0 +1,40 @@
|
||||
/* |
||||
* Licensed to Apache Software Foundation (ASF) under one or more contributor |
||||
* license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright |
||||
* ownership. Apache Software Foundation (ASF) licenses this file to you under |
||||
* the Apache License, Version 2.0 (the "License"); you may |
||||
* not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, |
||||
* software distributed under the License is distributed on an |
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
||||
* KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations |
||||
* under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.api.test.pages; |
||||
|
||||
|
||||
import org.apache.dolphinscheduler.api.test.entity.HttpResponse; |
||||
import org.apache.dolphinscheduler.api.test.utils.RequestClient; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
public final class LoginPage { |
||||
public HttpResponse login(String username, String password) { |
||||
Map<String, Object> params = new HashMap<>(); |
||||
|
||||
params.put("userName", username); |
||||
params.put("userPassword", password); |
||||
|
||||
RequestClient requestClient = new RequestClient(); |
||||
|
||||
return requestClient.post("/login", null, params); |
||||
} |
||||
} |
@ -0,0 +1,67 @@
|
||||
/* |
||||
* Licensed to Apache Software Foundation (ASF) under one or more contributor |
||||
* license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright |
||||
* ownership. Apache Software Foundation (ASF) licenses this file to you under |
||||
* the Apache License, Version 2.0 (the "License"); you may |
||||
* not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, |
||||
* software distributed under the License is distributed on an |
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
||||
* KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations |
||||
* under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.api.test.pages.security; |
||||
|
||||
|
||||
import org.apache.dolphinscheduler.api.test.core.Constants; |
||||
import org.apache.dolphinscheduler.api.test.entity.HttpResponse; |
||||
import org.apache.dolphinscheduler.api.test.utils.RequestClient; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
public final class TenantPage { |
||||
public HttpResponse createTenant(String sessionId, String tenant, Integer queueId, String description) { |
||||
Map<String, Object> params = new HashMap<>(); |
||||
params.put("tenantCode", tenant); |
||||
params.put("queueId", queueId); |
||||
params.put("description", description); |
||||
|
||||
Map<String, String> headers = new HashMap<>(); |
||||
headers.put(Constants.SESSION_ID_KEY, sessionId); |
||||
|
||||
RequestClient requestClient = new RequestClient(); |
||||
|
||||
return requestClient.post("/tenants", headers, params); |
||||
} |
||||
|
||||
public HttpResponse getTenantListPaging(String sessionId, Integer pageNo, Integer pageSize, String searchVal) { |
||||
Map<String, String> headers = new HashMap<>(); |
||||
headers.put(Constants.SESSION_ID_KEY, sessionId); |
||||
|
||||
Map<String, Object> params = new HashMap<>(); |
||||
params.put("pageSize", pageSize); |
||||
params.put("pageNo", pageNo); |
||||
params.put("searchVal", searchVal); |
||||
|
||||
RequestClient requestClient = new RequestClient(); |
||||
|
||||
return requestClient.get("/tenants/", headers, params); |
||||
} |
||||
|
||||
public HttpResponse deleteTenant(String sessionId, Integer tenantId) { |
||||
Map<String, String> headers = new HashMap<>(); |
||||
headers.put(Constants.SESSION_ID_KEY, sessionId); |
||||
|
||||
RequestClient requestClient = new RequestClient(); |
||||
|
||||
return requestClient.delete(String.format("/tenants/%s", tenantId), headers, null); |
||||
} |
||||
} |
@ -0,0 +1,384 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.api.test.utils; |
||||
import static java.nio.charset.StandardCharsets.UTF_8; |
||||
|
||||
import static com.fasterxml.jackson.databind.DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT; |
||||
import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES; |
||||
import static com.fasterxml.jackson.databind.DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL; |
||||
import static com.fasterxml.jackson.databind.MapperFeature.REQUIRE_SETTERS_FOR_GETTERS; |
||||
|
||||
import java.io.IOException; |
||||
import java.text.SimpleDateFormat; |
||||
import java.util.ArrayList; |
||||
import java.util.Collections; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.Objects; |
||||
import java.util.TimeZone; |
||||
|
||||
import org.apache.dolphinscheduler.api.test.core.Constants; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator; |
||||
import com.fasterxml.jackson.core.JsonParser; |
||||
import com.fasterxml.jackson.core.JsonProcessingException; |
||||
import com.fasterxml.jackson.core.type.TypeReference; |
||||
import com.fasterxml.jackson.databind.DeserializationContext; |
||||
import com.fasterxml.jackson.databind.JsonDeserializer; |
||||
import com.fasterxml.jackson.databind.JsonNode; |
||||
import com.fasterxml.jackson.databind.JsonSerializer; |
||||
import com.fasterxml.jackson.databind.ObjectMapper; |
||||
import com.fasterxml.jackson.databind.ObjectWriter; |
||||
import com.fasterxml.jackson.databind.SerializationFeature; |
||||
import com.fasterxml.jackson.databind.SerializerProvider; |
||||
import com.fasterxml.jackson.databind.node.ArrayNode; |
||||
import com.fasterxml.jackson.databind.node.ObjectNode; |
||||
import com.fasterxml.jackson.databind.node.TextNode; |
||||
import com.fasterxml.jackson.databind.type.CollectionType; |
||||
import org.testcontainers.shaded.org.apache.commons.lang.StringUtils; |
||||
|
||||
/** |
||||
* json utils |
||||
*/ |
||||
public class JSONUtils { |
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(JSONUtils.class); |
||||
|
||||
static { |
||||
logger.info("init timezone: {}",TimeZone.getDefault()); |
||||
} |
||||
|
||||
/** |
||||
* can use static singleton, inject: just make sure to reuse! |
||||
*/ |
||||
private static final ObjectMapper objectMapper = new ObjectMapper() |
||||
.configure(FAIL_ON_UNKNOWN_PROPERTIES, false) |
||||
.configure(ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT, true) |
||||
.configure(READ_UNKNOWN_ENUM_VALUES_AS_NULL, true) |
||||
.configure(REQUIRE_SETTERS_FOR_GETTERS, true) |
||||
.setTimeZone(TimeZone.getDefault()) |
||||
.setDateFormat(new SimpleDateFormat(Constants.YYYY_MM_DD_HH_MM_SS)); |
||||
|
||||
private JSONUtils() { |
||||
throw new UnsupportedOperationException("Construct JSONUtils"); |
||||
} |
||||
|
||||
public static ArrayNode createArrayNode() { |
||||
return objectMapper.createArrayNode(); |
||||
} |
||||
|
||||
public static ObjectNode createObjectNode() { |
||||
return objectMapper.createObjectNode(); |
||||
} |
||||
|
||||
public static JsonNode toJsonNode(Object obj) { |
||||
return objectMapper.valueToTree(obj); |
||||
} |
||||
|
||||
/** |
||||
* json representation of object |
||||
* |
||||
* @param object object |
||||
* @param feature feature |
||||
* @return object to json string |
||||
*/ |
||||
public static String toJsonString(Object object, SerializationFeature feature) { |
||||
try { |
||||
ObjectWriter writer = objectMapper.writer(feature); |
||||
return writer.writeValueAsString(object); |
||||
} catch (Exception e) { |
||||
logger.error("object to json exception!", e); |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* This method deserializes the specified Json into an object of the specified class. It is not |
||||
* suitable to use if the specified class is a generic type since it will not have the generic |
||||
* type information because of the Type Erasure feature of Java. Therefore, this method should not |
||||
* be used if the desired type is a generic type. Note that this method works fine if the any of |
||||
* the fields of the specified object are generics, just the object itself should not be a |
||||
* generic type. |
||||
* |
||||
* @param json the string from which the object is to be deserialized |
||||
* @param clazz the class of T |
||||
* @param <T> T |
||||
* @return an object of type T from the string |
||||
* classOfT |
||||
*/ |
||||
public static <T> T parseObject(String json, Class<T> clazz) { |
||||
if (StringUtils.isEmpty(json)) { |
||||
return null; |
||||
} |
||||
|
||||
try { |
||||
return objectMapper.readValue(json, clazz); |
||||
} catch (Exception e) { |
||||
logger.error("parse object exception!", e); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* deserialize |
||||
* |
||||
* @param src byte array |
||||
* @param clazz class
|
||||
* @param <T> deserialize type |
||||
* @return deserialize type |
||||
*/ |
||||
public static <T> T parseObject(byte[] src, Class<T> clazz) { |
||||
if (src == null) { |
||||
return null; |
||||
} |
||||
String json = new String(src, UTF_8); |
||||
return parseObject(json, clazz); |
||||
} |
||||
|
||||
/** |
||||
* json to list |
||||
* |
||||
* @param json json string |
||||
* @param clazz class
|
||||
* @param <T> T |
||||
* @return list |
||||
*/ |
||||
public static <T> List<T> toList(String json, Class<T> clazz) { |
||||
if (StringUtils.isEmpty(json)) { |
||||
return Collections.emptyList(); |
||||
} |
||||
|
||||
try { |
||||
CollectionType listType = objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, clazz); |
||||
return objectMapper.readValue(json, listType); |
||||
} catch (Exception e) { |
||||
logger.error("parse list exception!", e); |
||||
} |
||||
|
||||
return Collections.emptyList(); |
||||
} |
||||
|
||||
/** |
||||
* check json object valid |
||||
* |
||||
* @param json json |
||||
* @return true if valid |
||||
*/ |
||||
public static boolean checkJsonValid(String json) { |
||||
|
||||
if (StringUtils.isEmpty(json)) { |
||||
return false; |
||||
} |
||||
|
||||
try { |
||||
objectMapper.readTree(json); |
||||
return true; |
||||
} catch (IOException e) { |
||||
logger.error("check json object valid exception!", e); |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Method for finding a JSON Object field with specified name in this |
||||
* node or its child nodes, and returning value it has. |
||||
* If no matching field is found in this node or its descendants, returns null. |
||||
* |
||||
* @param jsonNode json node |
||||
* @param fieldName Name of field to look for |
||||
* @return Value of first matching node found, if any; null if none |
||||
*/ |
||||
public static String findValue(JsonNode jsonNode, String fieldName) { |
||||
JsonNode node = jsonNode.findValue(fieldName); |
||||
|
||||
if (node == null) { |
||||
return null; |
||||
} |
||||
|
||||
return node.asText(); |
||||
} |
||||
|
||||
/** |
||||
* json to map |
||||
* {@link #toMap(String, Class, Class)} |
||||
* |
||||
* @param json json |
||||
* @return json to map |
||||
*/ |
||||
public static Map<String, String> toMap(String json) { |
||||
return parseObject(json, new TypeReference<Map<String, String>>() {}); |
||||
} |
||||
|
||||
/** |
||||
* json to map |
||||
* |
||||
* @param json json |
||||
* @param classK classK |
||||
* @param classV classV |
||||
* @param <K> K |
||||
* @param <V> V |
||||
* @return to map |
||||
*/ |
||||
public static <K, V> Map<K, V> toMap(String json, Class<K> classK, Class<V> classV) { |
||||
if (StringUtils.isEmpty(json)) { |
||||
return Collections.emptyMap(); |
||||
} |
||||
|
||||
try { |
||||
return objectMapper.readValue(json, new TypeReference<Map<K, V>>() { |
||||
}); |
||||
} catch (Exception e) { |
||||
logger.error("json to map exception!", e); |
||||
} |
||||
|
||||
return Collections.emptyMap(); |
||||
} |
||||
|
||||
/** |
||||
* from the key-value generated json to get the str value no matter the real type of value |
||||
* @param json the json str |
||||
* @param nodeName key |
||||
* @return the str value of key |
||||
*/ |
||||
public static String getNodeString(String json, String nodeName) { |
||||
try { |
||||
JsonNode rootNode = objectMapper.readTree(json); |
||||
JsonNode jsonNode = rootNode.findValue(nodeName); |
||||
if (Objects.isNull(jsonNode)) { |
||||
return ""; |
||||
} |
||||
return jsonNode.isTextual() ? jsonNode.asText() : jsonNode.toString(); |
||||
} catch (JsonProcessingException e) { |
||||
return ""; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* json to object |
||||
* |
||||
* @param json json string |
||||
* @param type type reference |
||||
* @param <T> |
||||
* @return return parse object |
||||
*/ |
||||
public static <T> T parseObject(String json, TypeReference<T> type) { |
||||
if (StringUtils.isEmpty(json)) { |
||||
return null; |
||||
} |
||||
|
||||
try { |
||||
return objectMapper.readValue(json, type); |
||||
} catch (Exception e) { |
||||
logger.error("json to map exception!", e); |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* object to json string |
||||
* |
||||
* @param object object |
||||
* @return json string |
||||
*/ |
||||
public static String toJsonString(Object object) { |
||||
try { |
||||
return objectMapper.writeValueAsString(object); |
||||
} catch (Exception e) { |
||||
throw new RuntimeException("Object json deserialization exception.", e); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* serialize to json byte |
||||
* |
||||
* @param obj object |
||||
* @param <T> object type |
||||
* @return byte array |
||||
*/ |
||||
public static <T> byte[] toJsonByteArray(T obj) { |
||||
if (obj == null) { |
||||
return null; |
||||
} |
||||
String json = ""; |
||||
try { |
||||
json = toJsonString(obj); |
||||
} catch (Exception e) { |
||||
logger.error("json serialize exception.", e); |
||||
} |
||||
|
||||
return json.getBytes(UTF_8); |
||||
} |
||||
|
||||
public static ObjectNode parseObject(String text) { |
||||
try { |
||||
if (text.isEmpty()) { |
||||
return parseObject(text, ObjectNode.class); |
||||
} else { |
||||
return (ObjectNode) objectMapper.readTree(text); |
||||
} |
||||
} catch (Exception e) { |
||||
throw new RuntimeException("String json deserialization exception.", e); |
||||
} |
||||
} |
||||
|
||||
public static ArrayNode parseArray(String text) { |
||||
try { |
||||
return (ArrayNode) objectMapper.readTree(text); |
||||
} catch (Exception e) { |
||||
throw new RuntimeException("Json deserialization exception.", e); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* json serializer |
||||
*/ |
||||
public static class JsonDataSerializer extends JsonSerializer<String> { |
||||
|
||||
@Override |
||||
public void serialize(String value, JsonGenerator gen, SerializerProvider provider) throws IOException { |
||||
gen.writeRawValue(value); |
||||
} |
||||
|
||||
} |
||||
|
||||
/** |
||||
* json data deserializer |
||||
*/ |
||||
public static class JsonDataDeserializer extends JsonDeserializer<String> { |
||||
|
||||
@Override |
||||
public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { |
||||
JsonNode node = p.getCodec().readTree(p); |
||||
if (node instanceof TextNode) { |
||||
return node.asText(); |
||||
} else { |
||||
return node.toString(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
public static <T> T convertValue(Object value, Class<T> targetType) { |
||||
return objectMapper.convertValue(value, targetType); |
||||
} |
||||
} |
@ -0,0 +1,171 @@
|
||||
/* |
||||
* Licensed to Apache Software Foundation (ASF) under one or more contributor |
||||
* license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright |
||||
* ownership. Apache Software Foundation (ASF) licenses this file to you under |
||||
* the Apache License, Version 2.0 (the "License"); you may |
||||
* not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, |
||||
* software distributed under the License is distributed on an |
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
||||
* KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations |
||||
* under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.api.test.utils; |
||||
|
||||
import lombok.SneakyThrows; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.apache.dolphinscheduler.api.test.core.Constants; |
||||
import org.apache.dolphinscheduler.api.test.entity.HttpResponse; |
||||
import org.apache.dolphinscheduler.api.test.entity.HttpResponseBody; |
||||
import org.testcontainers.shaded.okhttp3.FormBody; |
||||
import org.testcontainers.shaded.okhttp3.Headers; |
||||
import org.testcontainers.shaded.okhttp3.MediaType; |
||||
import org.testcontainers.shaded.okhttp3.OkHttpClient; |
||||
import org.testcontainers.shaded.okhttp3.Request; |
||||
import org.testcontainers.shaded.okhttp3.RequestBody; |
||||
import org.testcontainers.shaded.okhttp3.Response; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
import java.util.Objects; |
||||
|
||||
@Slf4j |
||||
public class RequestClient { |
||||
|
||||
private OkHttpClient httpClient = null; |
||||
|
||||
public RequestClient() { |
||||
this.httpClient = new OkHttpClient(); |
||||
} |
||||
|
||||
@SneakyThrows |
||||
public HttpResponse get(String url, Map<String, String> headers, Map<String, Object> params) { |
||||
String requestUrl = String.format("%s%s%s", Constants.DOLPHINSCHEDULER_API_URL, url, getParams(params)); |
||||
|
||||
Headers headersBuilder = new Headers.Builder().build(); |
||||
if (headers != null) { |
||||
headersBuilder = Headers.of(headers); |
||||
} |
||||
|
||||
LOGGER.info("GET request to {}, Headers: {}", requestUrl, headersBuilder); |
||||
Request request = new Request.Builder() |
||||
.url(requestUrl) |
||||
.headers(headersBuilder) |
||||
.get() |
||||
.build(); |
||||
|
||||
Response response = this.httpClient.newCall(request).execute(); |
||||
|
||||
HttpResponseBody responseData = null; |
||||
int responseCode = response.code(); |
||||
if (response.body() != null) { |
||||
responseData = JSONUtils.parseObject(response.body().string(), HttpResponseBody.class); |
||||
} |
||||
response.close(); |
||||
|
||||
HttpResponse httpResponse = new HttpResponse(responseCode, responseData); |
||||
|
||||
LOGGER.info("GET response: {}", httpResponse); |
||||
|
||||
return httpResponse; |
||||
} |
||||
|
||||
public static String getParams(Map<String, Object> params) { |
||||
StringBuilder sb = new StringBuilder(Constants.QUESTION_MARK); |
||||
if (params.size() > 0) { |
||||
for (Map.Entry<String, Object> item : params.entrySet()) { |
||||
Object value = item.getValue(); |
||||
if (Objects.nonNull(value)) { |
||||
sb.append(Constants.AND_MARK); |
||||
sb.append(item.getKey()); |
||||
sb.append(Constants.EQUAL_MARK); |
||||
sb.append(value); |
||||
} |
||||
} |
||||
return sb.toString(); |
||||
} else { |
||||
return ""; |
||||
} |
||||
} |
||||
|
||||
@SneakyThrows |
||||
public HttpResponse post(String url, Map<String, String> headers, Map<String, Object> params) { |
||||
if (headers == null) { |
||||
headers = new HashMap<>(); |
||||
} |
||||
|
||||
String requestUrl = String.format("%s%s", Constants.DOLPHINSCHEDULER_API_URL, url); |
||||
|
||||
headers.put("Content-Type", Constants.REQUEST_CONTENT_TYPE); |
||||
|
||||
Headers headersBuilder = Headers.of(headers); |
||||
|
||||
RequestBody requestBody = FormBody.create(MediaType.parse(Constants.REQUEST_CONTENT_TYPE), getParams(params)); |
||||
|
||||
LOGGER.info("POST request to {}, Headers: {}, Params: {}", requestUrl, headersBuilder, params); |
||||
Request request = new Request.Builder() |
||||
.headers(headersBuilder) |
||||
.url(requestUrl) |
||||
.post(requestBody) |
||||
.build(); |
||||
|
||||
Response response = this.httpClient.newCall(request).execute(); |
||||
|
||||
|
||||
int responseCode = response.code(); |
||||
HttpResponseBody responseData = null; |
||||
if (response.body() != null) { |
||||
responseData = JSONUtils.parseObject(response.body().string(), HttpResponseBody.class); |
||||
} |
||||
response.close(); |
||||
|
||||
HttpResponse httpResponse = new HttpResponse(responseCode, responseData); |
||||
|
||||
LOGGER.info("POST response: {}", httpResponse); |
||||
|
||||
return httpResponse; |
||||
} |
||||
|
||||
@SneakyThrows |
||||
public HttpResponse delete(String url, Map<String, String> headers, Map<String, Object> params) { |
||||
if (headers == null) { |
||||
headers = new HashMap<>(); |
||||
} |
||||
|
||||
String requestUrl = String.format("%s%s", Constants.DOLPHINSCHEDULER_API_URL, url); |
||||
|
||||
headers.put("Content-Type", Constants.REQUEST_CONTENT_TYPE); |
||||
|
||||
Headers headersBuilder = Headers.of(headers); |
||||
|
||||
LOGGER.info("DELETE request to {}, Headers: {}, Params: {}", requestUrl, headersBuilder, params); |
||||
Request request = new Request.Builder() |
||||
.headers(headersBuilder) |
||||
.url(requestUrl) |
||||
.delete() |
||||
.build(); |
||||
|
||||
Response response = this.httpClient.newCall(request).execute(); |
||||
|
||||
|
||||
int responseCode = response.code(); |
||||
HttpResponseBody responseData = null; |
||||
if (response.body() != null) { |
||||
responseData = JSONUtils.parseObject(response.body().string(), HttpResponseBody.class); |
||||
} |
||||
response.close(); |
||||
|
||||
HttpResponse httpResponse = new HttpResponse(responseCode, responseData); |
||||
|
||||
LOGGER.info("DELETE response: {}", httpResponse); |
||||
|
||||
return httpResponse; |
||||
} |
||||
} |
@ -0,0 +1,37 @@
|
||||
# |
||||
# Licensed to the Apache Software Foundation (ASF) under one or more |
||||
# contributor license agreements. See the NOTICE file distributed with |
||||
# this work for additional information regarding copyright ownership. |
||||
# The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
# (the "License"); you may not use this file except in compliance with |
||||
# the License. You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
# |
||||
|
||||
version: "3.8" |
||||
|
||||
services: |
||||
dolphinscheduler: |
||||
image: apache/dolphinscheduler-standalone-server:ci |
||||
environment: |
||||
MASTER_MAX_CPU_LOAD_AVG: 100 |
||||
WORKER_TENANT_AUTO_CREATE: 'true' |
||||
ports: |
||||
- "12345:12345" |
||||
networks: |
||||
- api-test |
||||
healthcheck: |
||||
test: [ "CMD", "curl", "http://localhost:12345/actuator/health" ] |
||||
interval: 5s |
||||
timeout: 60s |
||||
retries: 120 |
||||
|
||||
networks: |
||||
api-test: |
@ -0,0 +1,61 @@
|
||||
# |
||||
# Licensed to the Apache Software Foundation (ASF) under one or more |
||||
# contributor license agreements. See the NOTICE file distributed with |
||||
# this work for additional information regarding copyright ownership. |
||||
# The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
# (the "License"); you may not use this file except in compliance with |
||||
# the License. You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
# |
||||
|
||||
version: "3.8" |
||||
|
||||
services: |
||||
dolphinscheduler: |
||||
image: apache/dolphinscheduler-standalone-server:ci |
||||
environment: |
||||
MASTER_MAX_CPU_LOAD_AVG: 100 |
||||
WORKER_TENANT_AUTO_CREATE: 'true' |
||||
ports: |
||||
- "12345:12345" |
||||
networks: |
||||
- api-test |
||||
healthcheck: |
||||
test: [ "CMD", "curl", "http://localhost:12345/actuator/health" ] |
||||
interval: 5s |
||||
timeout: 60s |
||||
retries: 120 |
||||
depends_on: |
||||
clickhouse: |
||||
condition: service_healthy |
||||
clickhouse: |
||||
image: yandex/clickhouse-server:21.12.3.32 |
||||
environment: |
||||
- CLICKHOUSE_DB=ch_test |
||||
- CLICKHOUSE_USER=ch_test |
||||
- CLICKHOUSE_PASSWORD=ch_test |
||||
ulimits: |
||||
nofile: |
||||
soft: 262144 |
||||
hard: 262144 |
||||
expose: |
||||
- 8123 |
||||
mem_limit: 3G |
||||
mem_reservation: 1G |
||||
networks: |
||||
- e2e |
||||
healthcheck: |
||||
test: ["CMD", "wget", "--spider", "-q", "localhost:8123/ping"] |
||||
interval: 5s |
||||
timeout: 60s |
||||
retries: 120 |
||||
|
||||
networks: |
||||
api-test: |
@ -0,0 +1,117 @@
|
||||
# |
||||
# Licensed to the Apache Software Foundation (ASF) under one or more |
||||
# contributor license agreements. See the NOTICE file distributed with |
||||
# this work for additional information regarding copyright ownership. |
||||
# The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
# (the "License"); you may not use this file except in compliance with |
||||
# the License. You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
# |
||||
|
||||
version: "3.8" |
||||
|
||||
services: |
||||
dolphinscheduler: |
||||
image: apache/dolphinscheduler-standalone-server:ci |
||||
environment: |
||||
MASTER_MAX_CPU_LOAD_AVG: 100 |
||||
WORKER_TENANT_AUTO_CREATE: 'true' |
||||
ports: |
||||
- "12345:12345" |
||||
networks: |
||||
- api-test |
||||
healthcheck: |
||||
test: [ "CMD", "curl", "http://localhost:12345/actuator/health" ] |
||||
interval: 5s |
||||
timeout: 60s |
||||
retries: 120 |
||||
depends_on: |
||||
hive-server: |
||||
condition: service_healthy |
||||
namenode: |
||||
image: bde2020/hadoop-namenode:2.0.0-hadoop2.7.4-java8 |
||||
environment: |
||||
- CLUSTER_NAME=test |
||||
env_file: |
||||
- ./hadoop-hive.env |
||||
networks: |
||||
- e2e |
||||
expose: |
||||
- "50070" |
||||
healthcheck: |
||||
test: [ "CMD", "curl", "http://localhost:50070/" ] |
||||
interval: 5s |
||||
timeout: 60s |
||||
retries: 120 |
||||
datanode: |
||||
image: bde2020/hadoop-datanode:2.0.0-hadoop2.7.4-java8 |
||||
env_file: |
||||
- ./hadoop-hive.env |
||||
environment: |
||||
SERVICE_PRECONDITION: "namenode:50070" |
||||
networks: |
||||
- e2e |
||||
expose: |
||||
- "50075" |
||||
healthcheck: |
||||
test: [ "CMD", "curl", "http://localhost:50075" ] |
||||
interval: 5s |
||||
timeout: 60s |
||||
retries: 120 |
||||
hive-server: |
||||
image: bde2020/hive:2.3.2-postgresql-metastore |
||||
env_file: |
||||
- ./hadoop-hive.env |
||||
networks: |
||||
- e2e |
||||
environment: |
||||
HIVE_CORE_CONF_javax_jdo_option_ConnectionURL: "jdbc:postgresql://hive-metastore/metastore" |
||||
SERVICE_PRECONDITION: "hive-metastore:9083" |
||||
expose: |
||||
- "10000" |
||||
depends_on: |
||||
datanode: |
||||
condition: service_healthy |
||||
namenode: |
||||
condition: service_healthy |
||||
healthcheck: |
||||
test: beeline -u "jdbc:hive2://127.0.0.1:10000/default" -n health_check -e "show databases;" |
||||
interval: 5s |
||||
timeout: 60s |
||||
retries: 120 |
||||
hive-metastore: |
||||
image: bde2020/hive:2.3.2-postgresql-metastore |
||||
env_file: |
||||
- ./hadoop-hive.env |
||||
command: /opt/hive/bin/hive --service metastore |
||||
networks: |
||||
- e2e |
||||
environment: |
||||
SERVICE_PRECONDITION: "namenode:50070 datanode:50075 hive-metastore-postgresql:5432" |
||||
expose: |
||||
- "9083" |
||||
depends_on: |
||||
hive-metastore-postgresql: |
||||
condition: service_healthy |
||||
hive-metastore-postgresql: |
||||
image: bde2020/hive-metastore-postgresql:2.3.0 |
||||
networks: |
||||
- e2e |
||||
expose: |
||||
- "5432" |
||||
healthcheck: |
||||
test: ["CMD-SHELL", "pg_isready -U postgres"] |
||||
interval: 5s |
||||
timeout: 60s |
||||
retries: 120 |
||||
|
||||
|
||||
networks: |
||||
api-test: |
@ -0,0 +1,50 @@
|
||||
# |
||||
# Licensed to the Apache Software Foundation (ASF) under one or more |
||||
# contributor license agreements. See the NOTICE file distributed with |
||||
# this work for additional information regarding copyright ownership. |
||||
# The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
# (the "License"); you may not use this file except in compliance with |
||||
# the License. You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
# |
||||
|
||||
HIVE_SITE_CONF_javax_jdo_option_ConnectionURL=jdbc:postgresql://hive-metastore-postgresql/metastore |
||||
HIVE_SITE_CONF_javax_jdo_option_ConnectionDriverName=org.postgresql.Driver |
||||
HIVE_SITE_CONF_javax_jdo_option_ConnectionUserName=hive |
||||
HIVE_SITE_CONF_javax_jdo_option_ConnectionPassword=hive |
||||
HIVE_SITE_CONF_datanucleus_autoCreateSchema=false |
||||
HIVE_SITE_CONF_hive_metastore_uris=thrift://hive-metastore:9083 |
||||
HDFS_CONF_dfs_namenode_datanode_registration_ip___hostname___check=false |
||||
HIVE_SITE_CONF_hive_server2_thrift_bind_host=0.0.0.0 |
||||
HIVE_SITE_CONF_hive_server2_thrift_port=10000 |
||||
|
||||
CORE_CONF_fs_defaultFS=hdfs://namenode:8020 |
||||
CORE_CONF_hadoop_http_staticuser_user=root |
||||
CORE_CONF_hadoop_proxyuser_hue_hosts=* |
||||
CORE_CONF_hadoop_proxyuser_hue_groups=* |
||||
CORE_CONF_hadoop_proxyuser_hive_hosts=* |
||||
|
||||
HDFS_CONF_dfs_webhdfs_enabled=true |
||||
HDFS_CONF_dfs_permissions_enabled=false |
||||
|
||||
YARN_CONF_yarn_log___aggregation___enable=true |
||||
YARN_CONF_yarn_resourcemanager_recovery_enabled=true |
||||
YARN_CONF_yarn_resourcemanager_store_class=org.apache.hadoop.yarn.server.resourcemanager.recovery.FileSystemRMStateStore |
||||
YARN_CONF_yarn_resourcemanager_fs_state___store_uri=/rmstate |
||||
YARN_CONF_yarn_nodemanager_remote___app___log___dir=/app-logs |
||||
YARN_CONF_yarn_log_server_url=http://historyserver:8188/applicationhistory/logs/ |
||||
YARN_CONF_yarn_timeline___service_enabled=true |
||||
YARN_CONF_yarn_timeline___service_generic___application___history_enabled=true |
||||
YARN_CONF_yarn_resourcemanager_system___metrics___publisher_enabled=true |
||||
YARN_CONF_yarn_resourcemanager_hostname=resourcemanager |
||||
YARN_CONF_yarn_timeline___service_hostname=historyserver |
||||
YARN_CONF_yarn_resourcemanager_address=resourcemanager:8032 |
||||
YARN_CONF_yarn_resourcemanager_scheduler_address=resourcemanager:8030 |
||||
YARN_CONF_yarn_resourcemanager_resource__tracker_address=resourcemanager:8031 |
@ -0,0 +1,56 @@
|
||||
# |
||||
# Licensed to the Apache Software Foundation (ASF) under one or more |
||||
# contributor license agreements. See the NOTICE file distributed with |
||||
# this work for additional information regarding copyright ownership. |
||||
# The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
# (the "License"); you may not use this file except in compliance with |
||||
# the License. You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
# |
||||
|
||||
version: "3.8" |
||||
|
||||
services: |
||||
dolphinscheduler: |
||||
image: apache/dolphinscheduler-standalone-server:ci |
||||
environment: |
||||
MASTER_MAX_CPU_LOAD_AVG: 100 |
||||
WORKER_TENANT_AUTO_CREATE: 'true' |
||||
ports: |
||||
- "12345:12345" |
||||
networks: |
||||
- api-test |
||||
volumes: |
||||
- ./download-mysql.sh:/tmp/download-mysql.sh |
||||
entrypoint: [ 'bash', '-c', '/bin/bash /tmp/download-mysql.sh && /opt/dolphinscheduler/bin/start.sh && tail -f /dev/null' ] |
||||
healthcheck: |
||||
test: [ "CMD", "curl", "http://localhost:12345/actuator/health" ] |
||||
interval: 5s |
||||
timeout: 60s |
||||
retries: 120 |
||||
depends_on: |
||||
mysql: |
||||
condition: service_healthy |
||||
mysql: |
||||
image: mysql:5.7.36 |
||||
command: --default-authentication-plugin=mysql_native_password |
||||
restart: always |
||||
environment: |
||||
MYSQL_ROOT_PASSWORD: 123456 |
||||
expose: |
||||
- 3306 |
||||
healthcheck: |
||||
test: mysqladmin ping -h 127.0.0.1 -u root --password=$$MYSQL_ROOT_PASSWORD |
||||
interval: 5s |
||||
timeout: 60s |
||||
retries: 120 |
||||
|
||||
networks: |
||||
api-test: |
@ -0,0 +1,27 @@
|
||||
# |
||||
# Licensed to the Apache Software Foundation (ASF) under one or more |
||||
# contributor license agreements. See the NOTICE file distributed with |
||||
# this work for additional information regarding copyright ownership. |
||||
# The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
# (the "License"); you may not use this file except in compliance with |
||||
# the License. You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
# |
||||
|
||||
set -ex |
||||
|
||||
DS_HOME=/opt/dolphinscheduler/libs/standalone-server |
||||
MYSQL_URL="https://repo.maven.apache.org/maven2/mysql/mysql-connector-java/8.0.16/mysql-connector-java-8.0.16.jar" |
||||
MYSQL_DRIVER="mysql-connector-java-8.0.16.jar" |
||||
|
||||
if ! curl -Lo "${DS_HOME}/${MYSQL_DRIVER}" ${MYSQL_URL}; then |
||||
echo "Fail to download ${MYSQL_DRIVER}." |
||||
exit 1 |
||||
fi |
@ -0,0 +1,54 @@
|
||||
# |
||||
# Licensed to the Apache Software Foundation (ASF) under one or more |
||||
# contributor license agreements. See the NOTICE file distributed with |
||||
# this work for additional information regarding copyright ownership. |
||||
# The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
# (the "License"); you may not use this file except in compliance with |
||||
# the License. You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
# |
||||
|
||||
version: "3.8" |
||||
|
||||
services: |
||||
dolphinscheduler: |
||||
image: apache/dolphinscheduler-standalone-server:ci |
||||
environment: |
||||
MASTER_MAX_CPU_LOAD_AVG: 100 |
||||
WORKER_TENANT_AUTO_CREATE: 'true' |
||||
ports: |
||||
- "12345:12345" |
||||
networks: |
||||
- api-test |
||||
healthcheck: |
||||
test: [ "CMD", "curl", "http://localhost:12345/actuator/health" ] |
||||
interval: 5s |
||||
timeout: 60s |
||||
retries: 120 |
||||
depends_on: |
||||
postgres: |
||||
condition: service_healthy |
||||
postgres: |
||||
image: postgres:14.1 |
||||
restart: always |
||||
environment: |
||||
POSTGRES_PASSWORD: postgres |
||||
networks: |
||||
- e2e |
||||
expose: |
||||
- 5432 |
||||
healthcheck: |
||||
test: ["CMD-SHELL", "pg_isready -U postgres"] |
||||
interval: 5s |
||||
timeout: 60s |
||||
retries: 120 |
||||
|
||||
networks: |
||||
api-test: |
@ -0,0 +1,51 @@
|
||||
# |
||||
# Licensed to the Apache Software Foundation (ASF) under one or more |
||||
# contributor license agreements. See the NOTICE file distributed with |
||||
# this work for additional information regarding copyright ownership. |
||||
# The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
# (the "License"); you may not use this file except in compliance with |
||||
# the License. You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
# |
||||
|
||||
version: "3.8" |
||||
|
||||
services: |
||||
dolphinscheduler: |
||||
image: apache/dolphinscheduler-standalone-server:ci |
||||
environment: |
||||
MASTER_MAX_CPU_LOAD_AVG: 100 |
||||
WORKER_TENANT_AUTO_CREATE: 'true' |
||||
ports: |
||||
- "12345:12345" |
||||
networks: |
||||
- api-test |
||||
healthcheck: |
||||
test: [ "CMD", "curl", "http://localhost:12345/actuator/health" ] |
||||
interval: 5s |
||||
timeout: 60s |
||||
retries: 120 |
||||
depends_on: |
||||
sqlserver: |
||||
condition: service_healthy |
||||
sqlserver: |
||||
image: alexk002/sqlserver2019_demo:1 |
||||
expose: |
||||
- 1433 |
||||
networks: |
||||
- e2e |
||||
healthcheck: |
||||
test: /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P OcP2020123 -Q "SELECT 1" |
||||
interval: 5s |
||||
timeout: 60s |
||||
retries: 120 |
||||
|
||||
networks: |
||||
api-test: |
@ -0,0 +1,90 @@
|
||||
# |
||||
# Licensed to the Apache Software Foundation (ASF) under one or more |
||||
# contributor license agreements. See the NOTICE file distributed with |
||||
# this work for additional information regarding copyright ownership. |
||||
# The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
# (the "License"); you may not use this file except in compliance with |
||||
# the License. You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
# |
||||
|
||||
# user data local directory path, please make sure the directory exists and have read write permissions |
||||
data.basedir.path=/tmp/dolphinscheduler |
||||
|
||||
# resource storage type: HDFS, S3, NONE |
||||
resource.storage.type=S3 |
||||
|
||||
# resource store on HDFS/S3 path, resource file will store to this hadoop hdfs path, self configuration, please make sure the directory exists on hdfs and have read write permissions. "/dolphinscheduler" is recommended |
||||
resource.upload.path=/dolphinscheduler |
||||
|
||||
# whether to startup kerberos |
||||
hadoop.security.authentication.startup.state=false |
||||
|
||||
# java.security.krb5.conf path |
||||
java.security.krb5.conf.path=/opt/krb5.conf |
||||
|
||||
# login user from keytab username |
||||
login.user.keytab.username=hdfs-mycluster@ESZ.COM |
||||
|
||||
# login user from keytab path |
||||
login.user.keytab.path=/opt/hdfs.headless.keytab |
||||
|
||||
# kerberos expire time, the unit is hour |
||||
kerberos.expire.time=2 |
||||
|
||||
# resource view suffixs |
||||
#resource.view.suffixs=txt,log,sh,bat,conf,cfg,py,java,sql,xml,hql,properties,json,yml,yaml,ini,js |
||||
|
||||
# if resource.storage.type=HDFS, the user must have the permission to create directories under the HDFS root path |
||||
hdfs.root.user=hdfs |
||||
|
||||
# if resource.storage.type=S3, the value like: s3a://dolphinscheduler; if resource.storage.type=HDFS and namenode HA is enabled, you need to copy core-site.xml and hdfs-site.xml to conf dir |
||||
fs.defaultFS=s3a://dolphinscheduler |
||||
|
||||
|
||||
# resourcemanager port, the default value is 8088 if not specified |
||||
resource.manager.httpaddress.port=8088 |
||||
|
||||
# if resourcemanager HA is enabled, please set the HA IPs; if resourcemanager is single, keep this value empty |
||||
yarn.resourcemanager.ha.rm.ids=192.168.xx.xx,192.168.xx.xx |
||||
|
||||
# if resourcemanager HA is enabled or not use resourcemanager, please keep the default value; If resourcemanager is single, you only need to replace ds1 to actual resourcemanager hostname |
||||
yarn.application.status.address=http://ds1:%s/ws/v1/cluster/apps/%s |
||||
|
||||
# job history status url when application number threshold is reached(default 10000, maybe it was set to 1000) |
||||
yarn.job.history.status.address=http://ds1:19888/ws/v1/history/mapreduce/jobs/%s |
||||
|
||||
# datasource encryption enable |
||||
datasource.encryption.enable=false |
||||
|
||||
# datasource encryption salt |
||||
datasource.encryption.salt=!@#$%^&* |
||||
|
||||
# use sudo or not, if set true, executing user is tenant user and deploy user needs sudo permissions; if set false, executing user is the deploy user and doesn't need sudo permissions |
||||
sudo.enable=true |
||||
|
||||
# network interface preferred like eth0, default: empty |
||||
#dolphin.scheduler.network.interface.preferred= |
||||
|
||||
# network IP gets priority, default: inner outer |
||||
#dolphin.scheduler.network.priority.strategy=default |
||||
# system env path |
||||
#dolphinscheduler.env.path=dolphinscheduler_env.sh |
||||
# development state |
||||
development.state=false |
||||
# rpc port |
||||
alert.rpc.port=50052 |
||||
aws.access.key.id=accessKey123 |
||||
aws.secret.access.key=secretKey123 |
||||
aws.region=us-east-1 |
||||
aws.endpoint=http://s3:9000 |
||||
|
||||
# Task resource limit state |
||||
task.resource.limit.state=false |
@ -0,0 +1,78 @@
|
||||
# |
||||
# Licensed to the Apache Software Foundation (ASF) under one or more |
||||
# contributor license agreements. See the NOTICE file distributed with |
||||
# this work for additional information regarding copyright ownership. |
||||
# The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
# (the "License"); you may not use this file except in compliance with |
||||
# the License. You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
# |
||||
|
||||
version: "3.8" |
||||
|
||||
services: |
||||
dolphinscheduler: |
||||
image: apache/dolphinscheduler-standalone-server:ci |
||||
environment: |
||||
MASTER_MAX_CPU_LOAD_AVG: 100 |
||||
WORKER_TENANT_AUTO_CREATE: 'true' |
||||
ports: |
||||
- "12345:12345" |
||||
networks: |
||||
- api-test |
||||
healthcheck: |
||||
test: [ "CMD", "curl", "http://localhost:12345/actuator/health" ] |
||||
interval: 5s |
||||
timeout: 60s |
||||
retries: 120 |
||||
volumes: |
||||
- ./common.properties:/opt/dolphinscheduler/conf/common.properties |
||||
depends_on: |
||||
s3: |
||||
condition: service_healthy |
||||
mc: |
||||
condition: service_completed_successfully |
||||
s3: |
||||
image: minio/minio:RELEASE.2022-01-25T19-56-04Z |
||||
hostname: s3 |
||||
tty: true |
||||
stdin_open: true |
||||
command: server /data --console-address ":9001" |
||||
ports: |
||||
- 9000:9000 |
||||
networks: |
||||
- e2e |
||||
environment: |
||||
MINIO_ROOT_USER: accessKey123 |
||||
MINIO_ROOT_PASSWORD: secretKey123 |
||||
healthcheck: |
||||
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"] |
||||
interval: 5s |
||||
timeout: 120s |
||||
retries: 120 |
||||
mc: |
||||
image: minio/mc:RELEASE.2022-01-07T06-01-38Z |
||||
entrypoint: bash |
||||
networks: |
||||
- e2e |
||||
command: |
||||
- -c |
||||
- mc alias set s3 http://s3:9000 accessKey123 secretKey123 && mc mb s3/dolphinscheduler |
||||
depends_on: |
||||
s3: |
||||
condition: service_healthy |
||||
|
||||
networks: |
||||
api-test: |
||||
driver: bridge |
||||
ipam: |
||||
config: |
||||
- subnet: 10.1.0.0/24 |
||||
gateway: 10.1.0.1 |
@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!-- |
||||
~ Licensed to Apache Software Foundation (ASF) under one or more contributor |
||||
~ license agreements. See the NOTICE file distributed with |
||||
~ this work for additional information regarding copyright |
||||
~ ownership. Apache Software Foundation (ASF) licenses this file to you under |
||||
~ the Apache License, Version 2.0 (the "License"); you may |
||||
~ not use this file except in compliance with the License. |
||||
~ You may obtain a copy of the License at |
||||
~ |
||||
~ http://www.apache.org/licenses/LICENSE-2.0 |
||||
~ |
||||
~ Unless required by applicable law or agreed to in writing, |
||||
~ software distributed under the License is distributed on an |
||||
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
||||
~ KIND, either express or implied. See the License for the |
||||
~ specific language governing permissions and limitations |
||||
~ under the License. |
||||
--> |
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" |
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||
<parent> |
||||
<artifactId>dolphinscheduler-api-test</artifactId> |
||||
<groupId>org.apache.dolphinscheduler</groupId> |
||||
<version>1.0-SNAPSHOT</version> |
||||
</parent> |
||||
<modelVersion>4.0.0</modelVersion> |
||||
|
||||
<artifactId>dolphinscheduler-api-test-core</artifactId> |
||||
</project> |
@ -0,0 +1,58 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.api.test.core; |
||||
|
||||
import lombok.experimental.UtilityClass; |
||||
|
||||
import java.nio.file.Path; |
||||
import java.nio.file.Paths; |
||||
|
||||
@UtilityClass |
||||
public final class Constants { |
||||
|
||||
/** |
||||
* backend api url |
||||
*/ |
||||
public static final String DOLPHINSCHEDULER_API_URL = "http://0.0.0.0:12345/dolphinscheduler"; |
||||
|
||||
/** |
||||
* backend api request header's content type |
||||
*/ |
||||
public static final String REQUEST_CONTENT_TYPE = "application/x-www-form-urlencoded"; |
||||
|
||||
/** |
||||
* header's session id's key |
||||
*/ |
||||
public static final String SESSION_ID_KEY = "sessionId"; |
||||
|
||||
/** |
||||
* simple date format |
||||
*/ |
||||
public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"; |
||||
|
||||
/** |
||||
* docker compose default healthy timeout |
||||
*/ |
||||
public static final Integer DOCKER_COMPOSE_DEFAULT_TIMEOUT = 180; |
||||
|
||||
public static final String QUESTION_MARK = "?"; |
||||
|
||||
public static final String EQUAL_MARK = "="; |
||||
|
||||
public static final String AND_MARK = "&"; |
||||
} |
@ -0,0 +1,41 @@
|
||||
/* |
||||
* Licensed to Apache Software Foundation (ASF) under one or more contributor |
||||
* license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright |
||||
* ownership. Apache Software Foundation (ASF) licenses this file to you under |
||||
* the Apache License, Version 2.0 (the "License"); you may |
||||
* not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, |
||||
* software distributed under the License is distributed on an |
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
||||
* KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations |
||||
* under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.api.test.core; |
||||
|
||||
import java.lang.annotation.ElementType; |
||||
import java.lang.annotation.Inherited; |
||||
import java.lang.annotation.Retention; |
||||
import java.lang.annotation.RetentionPolicy; |
||||
import java.lang.annotation.Target; |
||||
|
||||
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; |
||||
import org.junit.jupiter.api.TestMethodOrder; |
||||
import org.junit.jupiter.api.extension.ExtendWith; |
||||
import org.testcontainers.junit.jupiter.Testcontainers; |
||||
|
||||
@Inherited |
||||
@Testcontainers |
||||
@Target(ElementType.TYPE) |
||||
@Retention(RetentionPolicy.RUNTIME) |
||||
@TestMethodOrder(OrderAnnotation.class) |
||||
@ExtendWith(DolphinSchedulerExtension.class) |
||||
public @interface DolphinScheduler { |
||||
String[] composeFiles(); |
||||
} |
@ -0,0 +1,80 @@
|
||||
/* |
||||
* Licensed to Apache Software Foundation (ASF) under one or more contributor |
||||
* license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright |
||||
* ownership. Apache Software Foundation (ASF) licenses this file to you under |
||||
* the Apache License, Version 2.0 (the "License"); you may |
||||
* not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, |
||||
* software distributed under the License is distributed on an |
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
||||
* KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations |
||||
* under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.api.test.core; |
||||
|
||||
import java.io.File; |
||||
import java.net.URL; |
||||
import java.time.Duration; |
||||
import java.util.List; |
||||
import java.util.Objects; |
||||
import java.util.stream.Collectors; |
||||
import java.util.stream.Stream; |
||||
|
||||
import lombok.SneakyThrows; |
||||
import org.junit.jupiter.api.extension.AfterAllCallback; |
||||
import org.junit.jupiter.api.extension.BeforeAllCallback; |
||||
import org.junit.jupiter.api.extension.ExtensionContext; |
||||
import org.testcontainers.containers.DockerComposeContainer; |
||||
import org.testcontainers.containers.wait.strategy.Wait; |
||||
|
||||
import lombok.extern.slf4j.Slf4j; |
||||
|
||||
@Slf4j |
||||
final class DolphinSchedulerExtension implements BeforeAllCallback, AfterAllCallback { |
||||
private final boolean LOCAL_MODE = Objects.equals(System.getProperty("local"), "true"); |
||||
|
||||
private final String SERVICE_NAME = "dolphinscheduler_1"; |
||||
|
||||
private DockerComposeContainer<?> compose; |
||||
|
||||
@Override |
||||
public void beforeAll(ExtensionContext context) { |
||||
if (!LOCAL_MODE) { |
||||
compose = createDockerCompose(context); |
||||
compose.start(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void afterAll(ExtensionContext context) { |
||||
if (compose != null) { |
||||
compose.stop(); |
||||
} |
||||
} |
||||
|
||||
private DockerComposeContainer<?> createDockerCompose(ExtensionContext context) { |
||||
final Class<?> clazz = context.getRequiredTestClass(); |
||||
final DolphinScheduler annotation = clazz.getAnnotation(DolphinScheduler.class); |
||||
final List<File> files = Stream.of(annotation.composeFiles()) |
||||
.map(it -> DolphinScheduler.class.getClassLoader().getResource(it)) |
||||
.filter(Objects::nonNull) |
||||
.map(URL::getPath) |
||||
.map(File::new) |
||||
.collect(Collectors.toList()); |
||||
|
||||
compose = new DockerComposeContainer<>(files) |
||||
.withPull(true) |
||||
.withTailChildContainers(true) |
||||
.withLogConsumer(SERVICE_NAME, outputFrame -> LOGGER.info(outputFrame.getUtf8String())) |
||||
.waitingFor(SERVICE_NAME, Wait.forHealthcheck().withStartupTimeout(Duration.ofSeconds(Constants.DOCKER_COMPOSE_DEFAULT_TIMEOUT))); |
||||
|
||||
return compose; |
||||
} |
||||
} |
@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!-- |
||||
~ Licensed to the Apache Software Foundation (ASF) under one or more |
||||
~ contributor license agreements. See the NOTICE file distributed with |
||||
~ this work for additional information regarding copyright ownership. |
||||
~ The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
~ (the "License"); you may not use this file except in compliance with |
||||
~ the License. You may obtain a copy of the License at |
||||
~ |
||||
~ http://www.apache.org/licenses/LICENSE-2.0 |
||||
~ |
||||
~ Unless required by applicable law or agreed to in writing, software |
||||
~ distributed under the License is distributed on an "AS IS" BASIS, |
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
~ See the License for the specific language governing permissions and |
||||
~ limitations under the License. |
||||
~ |
||||
--> |
||||
|
||||
<Configuration status="DEBUG"> |
||||
<Appenders> |
||||
<Console name="Console" target="SYSTEM_OUT"> |
||||
<PatternLayout charset="UTF-8" pattern="%d %c %L [%t] %-5p %x - %m%n"/> |
||||
</Console> |
||||
</Appenders> |
||||
<Loggers> |
||||
<Root level="INFO"> |
||||
<AppenderRef ref="Console"/> |
||||
</Root> |
||||
</Loggers> |
||||
</Configuration> |
@ -0,0 +1,21 @@
|
||||
# |
||||
# Licensed to the Apache Software Foundation (ASF) under one or more |
||||
# contributor license agreements. See the NOTICE file distributed with |
||||
# this work for additional information regarding copyright ownership. |
||||
# The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
# (the "License"); you may not use this file except in compliance with |
||||
# the License. You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
# |
||||
|
||||
lombok.accessors.fluent=true |
||||
lombok.log.fieldname=LOGGER |
||||
lombok.accessors.fluent=true |
||||
lombok.anyConstructor.addConstructorProperties=true |
@ -0,0 +1,142 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!-- |
||||
~ Licensed to the Apache Software Foundation (ASF) under one or more |
||||
~ contributor license agreements. See the NOTICE file distributed with |
||||
~ this work for additional information regarding copyright ownership. |
||||
~ The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
~ (the "License"); you may not use this file except in compliance with |
||||
~ the License. You may obtain a copy of the License at |
||||
~ |
||||
~ http://www.apache.org/licenses/LICENSE-2.0 |
||||
~ |
||||
~ Unless required by applicable law or agreed to in writing, software |
||||
~ distributed under the License is distributed on an "AS IS" BASIS, |
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
~ See the License for the specific language governing permissions and |
||||
~ limitations under the License. |
||||
--> |
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" |
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||
<modelVersion>4.0.0</modelVersion> |
||||
|
||||
<groupId>org.apache.dolphinscheduler</groupId> |
||||
<artifactId>dolphinscheduler-api-test</artifactId> |
||||
<packaging>pom</packaging> |
||||
<version>1.0-SNAPSHOT</version> |
||||
|
||||
<modules> |
||||
<module>dolphinscheduler-api-test-core</module> |
||||
<module>dolphinscheduler-api-test-case</module> |
||||
</modules> |
||||
|
||||
<properties> |
||||
<maven.compiler.source>8</maven.compiler.source> |
||||
<maven.compiler.target>8</maven.compiler.target> |
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
||||
|
||||
<junit.version>5.7.2</junit.version> |
||||
<selenium.version>3.141.59</selenium.version> |
||||
<lombok.version>1.18.24</lombok.version> |
||||
<assertj-core.version>3.23.1</assertj-core.version> |
||||
<awaitility.version>4.1.0</awaitility.version> |
||||
<kotlin.version>1.5.30</kotlin.version> |
||||
<slf4j-api.version>1.7.36</slf4j-api.version> |
||||
<log4j-slf4j-impl.version>2.17.2</log4j-slf4j-impl.version> |
||||
<guava.version>31.0.1-jre</guava.version> |
||||
<jackson.version>2.13.2</jackson.version> |
||||
</properties> |
||||
|
||||
<dependencies> |
||||
<dependency> |
||||
<groupId>org.slf4j</groupId> |
||||
<artifactId>slf4j-api</artifactId> |
||||
<version>${slf4j-api.version}</version> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.apache.logging.log4j</groupId> |
||||
<artifactId>log4j-slf4j-impl</artifactId> |
||||
<version>${log4j-slf4j-impl.version}</version> |
||||
</dependency> |
||||
|
||||
<dependency> |
||||
<groupId>org.junit.jupiter</groupId> |
||||
<artifactId>junit-jupiter</artifactId> |
||||
</dependency> |
||||
|
||||
<dependency> |
||||
<groupId>org.testcontainers</groupId> |
||||
<artifactId>testcontainers</artifactId> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.testcontainers</groupId> |
||||
<artifactId>junit-jupiter</artifactId> |
||||
</dependency> |
||||
|
||||
<dependency> |
||||
<groupId>org.assertj</groupId> |
||||
<artifactId>assertj-core</artifactId> |
||||
<version>${assertj-core.version}</version> |
||||
<scope>test</scope> |
||||
</dependency> |
||||
|
||||
<dependency> |
||||
<groupId>org.projectlombok</groupId> |
||||
<artifactId>lombok</artifactId> |
||||
<version>${lombok.version}</version> |
||||
<scope>provided</scope> |
||||
</dependency> |
||||
|
||||
<dependency> |
||||
<groupId>com.fasterxml.jackson.core</groupId> |
||||
<artifactId>jackson-annotations</artifactId> |
||||
<version>${jackson.version}</version> |
||||
</dependency> |
||||
|
||||
<dependency> |
||||
<groupId>com.fasterxml.jackson.core</groupId> |
||||
<artifactId>jackson-databind</artifactId> |
||||
<version>${jackson.version}</version> |
||||
</dependency> |
||||
|
||||
<dependency> |
||||
<groupId>com.fasterxml.jackson.core</groupId> |
||||
<artifactId>jackson-core</artifactId> |
||||
<version>${jackson.version}</version> |
||||
</dependency> |
||||
</dependencies> |
||||
|
||||
<dependencyManagement> |
||||
<dependencies> |
||||
<dependency> |
||||
<groupId>com.google.guava</groupId> |
||||
<artifactId>guava</artifactId> |
||||
<version>${guava.version}</version> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.junit</groupId> |
||||
<artifactId>junit-bom</artifactId> |
||||
<version>${junit.version}</version> |
||||
<scope>import</scope> |
||||
<type>pom</type> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.testcontainers</groupId> |
||||
<artifactId>testcontainers-bom</artifactId> |
||||
<version>1.16.3</version> |
||||
<scope>import</scope> |
||||
<type>pom</type> |
||||
</dependency> |
||||
</dependencies> |
||||
</dependencyManagement> |
||||
|
||||
<build> |
||||
<plugins> |
||||
<plugin> |
||||
<groupId>org.apache.maven.plugins</groupId> |
||||
<artifactId>maven-surefire-plugin</artifactId> |
||||
<version>2.22.2</version> |
||||
</plugin> |
||||
</plugins> |
||||
</build> |
||||
</project> |
Loading…
Reference in new issue