xiangzihao
3 years ago
committed by
GitHub
17 changed files with 521 additions and 39 deletions
@ -0,0 +1,119 @@ |
|||||||
|
/* |
||||||
|
* 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.e2e.cases; |
||||||
|
|
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.e2e.core.DolphinScheduler; |
||||||
|
import org.apache.dolphinscheduler.e2e.pages.LoginPage; |
||||||
|
import org.apache.dolphinscheduler.e2e.pages.resource.FileManagePage; |
||||||
|
import org.apache.dolphinscheduler.e2e.pages.resource.ResourcePage; |
||||||
|
import org.apache.dolphinscheduler.e2e.pages.security.SecurityPage; |
||||||
|
import org.apache.dolphinscheduler.e2e.pages.security.TenantPage; |
||||||
|
import org.apache.dolphinscheduler.e2e.pages.security.UserPage; |
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeAll; |
||||||
|
import org.junit.jupiter.api.Order; |
||||||
|
import org.junit.jupiter.api.Test; |
||||||
|
import org.openqa.selenium.By; |
||||||
|
import org.openqa.selenium.WebElement; |
||||||
|
import org.openqa.selenium.remote.RemoteWebDriver; |
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat; |
||||||
|
import static org.awaitility.Awaitility.await; |
||||||
|
|
||||||
|
@DolphinScheduler(composeFiles = "docker/file-manage/docker-compose.yaml") |
||||||
|
public class FileManageE2ETest { |
||||||
|
private static RemoteWebDriver browser; |
||||||
|
|
||||||
|
private static final String tenant = System.getProperty("user.name"); |
||||||
|
|
||||||
|
private static final String user = "admin"; |
||||||
|
|
||||||
|
private static final String password = "dolphinscheduler123"; |
||||||
|
|
||||||
|
private static final String email = "admin@gmail.com"; |
||||||
|
|
||||||
|
private static final String phone = "15800000000"; |
||||||
|
|
||||||
|
private static final String testDiretoryName = "test_directory"; |
||||||
|
|
||||||
|
@BeforeAll |
||||||
|
public static void setup() { |
||||||
|
TenantPage tenantPage = new LoginPage(browser) |
||||||
|
.login(user, password) |
||||||
|
.create(tenant); |
||||||
|
|
||||||
|
await().untilAsserted(() -> assertThat(tenantPage.tenantList()) |
||||||
|
.as("Tenant list should contain newly-created tenant") |
||||||
|
.extracting(WebElement::getText) |
||||||
|
.anyMatch(it -> it.contains(tenant))); |
||||||
|
|
||||||
|
tenantPage.goToNav(SecurityPage.class) |
||||||
|
.goToTab(UserPage.class) |
||||||
|
.update(user, user, password, email, phone) |
||||||
|
.goToNav(ResourcePage.class) |
||||||
|
.goToTab(FileManagePage.class); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
@Order(10) |
||||||
|
void testCreateDirectory() { |
||||||
|
final FileManagePage page = new FileManagePage(browser); |
||||||
|
|
||||||
|
page.createDirectory(testDiretoryName, "test_desc"); |
||||||
|
|
||||||
|
await().untilAsserted(() -> assertThat(page.fileList()) |
||||||
|
.as("File list should contain newly-created file") |
||||||
|
.extracting(WebElement::getText) |
||||||
|
.anyMatch(it -> it.contains(testDiretoryName))); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
@Order(20) |
||||||
|
void testCreateDuplicateDirectory() { |
||||||
|
final FileManagePage page = new FileManagePage(browser); |
||||||
|
|
||||||
|
page.createDirectory(testDiretoryName, "test_desc"); |
||||||
|
|
||||||
|
await().untilAsserted(() -> assertThat(browser.findElement(By.tagName("body")).getText()) |
||||||
|
.contains("resource already exists") |
||||||
|
); |
||||||
|
|
||||||
|
page.createDirectoryBox().buttonCancel().click(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
@Order(30) |
||||||
|
void testDeleteDirectory() { |
||||||
|
final FileManagePage page = new FileManagePage(browser); |
||||||
|
|
||||||
|
page.delete(testDiretoryName); |
||||||
|
|
||||||
|
await().untilAsserted(() -> { |
||||||
|
browser.navigate().refresh(); |
||||||
|
|
||||||
|
assertThat( |
||||||
|
page.fileList() |
||||||
|
).noneMatch( |
||||||
|
it -> it.getText().contains(testDiretoryName) |
||||||
|
); |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,111 @@ |
|||||||
|
/* |
||||||
|
* 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.e2e.pages.resource; |
||||||
|
|
||||||
|
import lombok.Getter; |
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage; |
||||||
|
import org.apache.dolphinscheduler.e2e.pages.security.TenantPage; |
||||||
|
|
||||||
|
import org.openqa.selenium.By; |
||||||
|
import org.openqa.selenium.WebElement; |
||||||
|
import org.openqa.selenium.remote.RemoteWebDriver; |
||||||
|
import org.openqa.selenium.support.FindBy; |
||||||
|
import org.openqa.selenium.support.FindBys; |
||||||
|
import org.openqa.selenium.support.PageFactory; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
|
||||||
|
@Getter |
||||||
|
public class FileManagePage extends NavBarPage implements ResourcePage.Tab { |
||||||
|
@FindBy(id = "btnCreateDirectory") |
||||||
|
private WebElement buttonCreateDirectory; |
||||||
|
|
||||||
|
private final CreateDirectoryBox createDirectoryBox; |
||||||
|
|
||||||
|
@FindBy(className = "items") |
||||||
|
private List<WebElement> fileList; |
||||||
|
|
||||||
|
@FindBy(id = "delete") |
||||||
|
private WebElement buttonDelete; |
||||||
|
|
||||||
|
@FindBys({ |
||||||
|
@FindBy(className = "el-popconfirm"), |
||||||
|
@FindBy(className = "el-button--primary"), |
||||||
|
}) |
||||||
|
private List<WebElement> buttonConfirm; |
||||||
|
|
||||||
|
public FileManagePage(RemoteWebDriver driver) { |
||||||
|
super(driver); |
||||||
|
|
||||||
|
createDirectoryBox = new CreateDirectoryBox(); |
||||||
|
} |
||||||
|
|
||||||
|
public FileManagePage createDirectory(String name, String description) { |
||||||
|
buttonCreateDirectory().click(); |
||||||
|
|
||||||
|
createDirectoryBox().inputDirectoryName().sendKeys(name); |
||||||
|
createDirectoryBox().inputDescription().sendKeys(description); |
||||||
|
createDirectoryBox().buttonSubmit().click(); |
||||||
|
|
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public FileManagePage delete(String name) { |
||||||
|
fileList() |
||||||
|
.stream() |
||||||
|
.filter(it -> it.getText().contains(name)) |
||||||
|
.flatMap(it -> it.findElements(By.id("delete")).stream()) |
||||||
|
.filter(WebElement::isDisplayed) |
||||||
|
.findFirst() |
||||||
|
.orElseThrow(() -> new RuntimeException("No delete button in file manage list")) |
||||||
|
.click(); |
||||||
|
|
||||||
|
buttonConfirm() |
||||||
|
.stream() |
||||||
|
.filter(WebElement::isDisplayed) |
||||||
|
.findFirst() |
||||||
|
.orElseThrow(() -> new RuntimeException("No confirm button when deleting")) |
||||||
|
.click(); |
||||||
|
|
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
@Getter |
||||||
|
public class CreateDirectoryBox { |
||||||
|
CreateDirectoryBox() { |
||||||
|
PageFactory.initElements(driver, this); |
||||||
|
} |
||||||
|
|
||||||
|
@FindBy(id = "inputDirectoryName") |
||||||
|
private WebElement inputDirectoryName; |
||||||
|
|
||||||
|
@FindBy(id = "inputDescription") |
||||||
|
private WebElement inputDescription; |
||||||
|
|
||||||
|
@FindBy(id = "btnSubmit") |
||||||
|
private WebElement buttonSubmit; |
||||||
|
|
||||||
|
@FindBy(id = "btnCancel") |
||||||
|
private WebElement buttonCancel; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,53 @@ |
|||||||
|
/* |
||||||
|
* 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.e2e.pages.resource; |
||||||
|
|
||||||
|
import lombok.Getter; |
||||||
|
import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage; |
||||||
|
import org.apache.dolphinscheduler.e2e.pages.security.TenantPage; |
||||||
|
import org.openqa.selenium.JavascriptExecutor; |
||||||
|
import org.openqa.selenium.WebElement; |
||||||
|
import org.openqa.selenium.remote.RemoteWebDriver; |
||||||
|
import org.openqa.selenium.support.FindBy; |
||||||
|
import org.openqa.selenium.support.ui.ExpectedConditions; |
||||||
|
import org.openqa.selenium.support.ui.WebDriverWait; |
||||||
|
|
||||||
|
|
||||||
|
@Getter |
||||||
|
public class ResourcePage extends NavBarPage implements NavBarPage.NavBarItem { |
||||||
|
@FindBy(className = "tab-file-manage") |
||||||
|
private WebElement fileMagageManage; |
||||||
|
|
||||||
|
public ResourcePage(RemoteWebDriver driver) { |
||||||
|
super(driver); |
||||||
|
} |
||||||
|
|
||||||
|
public <T extends ResourcePage.Tab> T goToTab(Class<T> tab) { |
||||||
|
if (tab == FileManagePage.class) { |
||||||
|
WebElement fileMagageManageElement = new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(fileMagageManage)); |
||||||
|
fileMagageManageElement.click(); |
||||||
|
return tab.cast(new FileManagePage(driver)); |
||||||
|
} |
||||||
|
throw new UnsupportedOperationException("Unknown tab: " + tab.getName()); |
||||||
|
} |
||||||
|
|
||||||
|
public interface Tab { |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,94 @@ |
|||||||
|
# |
||||||
|
# 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=HDFS |
||||||
|
|
||||||
|
# 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=hdfs://hdfs:8020 |
||||||
|
|
||||||
|
# if resource.storage.type=S3, s3 endpoint |
||||||
|
fs.s3a.endpoint=http://192.168.xx.xx:9010 |
||||||
|
|
||||||
|
# if resource.storage.type=S3, s3 access key |
||||||
|
fs.s3a.access.key=A3DXS30FO22544RE |
||||||
|
|
||||||
|
# if resource.storage.type=S3, s3 secret key |
||||||
|
fs.s3a.secret.key=OloCLq3n+8+sdPHUhJ21XrSxTC+JK |
||||||
|
|
||||||
|
# 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=env/dolphinscheduler_env.sh |
||||||
|
|
||||||
|
# development state |
||||||
|
development.state=false |
||||||
|
|
||||||
|
# rpc port |
||||||
|
alert.rpc.port=50052 |
@ -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: "2.1" |
||||||
|
|
||||||
|
services: |
||||||
|
dolphinscheduler: |
||||||
|
image: apache/dolphinscheduler-standalone-server:ci |
||||||
|
environment: |
||||||
|
MASTER_MAX_CPU_LOAD_AVG: 100 |
||||||
|
WORKER_TENANT_AUTO_CREATE: 'true' |
||||||
|
expose: |
||||||
|
- 12345 |
||||||
|
networks: |
||||||
|
- e2e |
||||||
|
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: |
||||||
|
hdfs: |
||||||
|
condition: service_healthy |
||||||
|
hdfs: |
||||||
|
image: mdouchement/hdfs:latest |
||||||
|
hostname: hdfs |
||||||
|
tty: true |
||||||
|
stdin_open: true |
||||||
|
expose: |
||||||
|
- 8020 |
||||||
|
networks: |
||||||
|
- e2e |
||||||
|
healthcheck: |
||||||
|
test: [ "CMD", "curl", "http://localhost:50070" ] |
||||||
|
interval: 5s |
||||||
|
timeout: 120s |
||||||
|
retries: 120 |
||||||
|
|
||||||
|
networks: |
||||||
|
e2e: |
Loading…
Reference in new issue