未验证 提交 4a373454 编写于 作者: E Eric Gao 提交者: GitHub

[Feature][Task Plugin] Support hive cli task plugin (#11651)

* Add hive cli task plugin

* Add docs for hive-cli task plugin

* Fix hive-cli task related front-end nits and checkstyle

* Fix exception handling logic
上级 71eeab3d
...@@ -161,6 +161,10 @@ export default { ...@@ -161,6 +161,10 @@ export default {
title: 'Jupyter', title: 'Jupyter',
link: '/en-us/docs/dev/user_doc/guide/task/jupyter.html', link: '/en-us/docs/dev/user_doc/guide/task/jupyter.html',
}, },
{
title: 'Hive CLI',
link: '/en-us/docs/dev/user_doc/guide/task/hive-cli.html',
},
{ {
title: 'Kubernetes', title: 'Kubernetes',
link: '/en-us/docs/dev/user_doc/guide/task/kubernetes.html', link: '/en-us/docs/dev/user_doc/guide/task/kubernetes.html',
...@@ -781,6 +785,10 @@ export default { ...@@ -781,6 +785,10 @@ export default {
title: 'Jupyter', title: 'Jupyter',
link: '/zh-cn/docs/dev/user_doc/guide/task/jupyter.html', link: '/zh-cn/docs/dev/user_doc/guide/task/jupyter.html',
}, },
{
title: 'Hive CLI',
link: '/zh-cn/docs/dev/user_doc/guide/task/hive-cli.html',
},
{ {
title: 'Kubernetes', title: 'Kubernetes',
link: '/zh-cn/docs/dev/user_doc/guide/task/kubernetes.html', link: '/zh-cn/docs/dev/user_doc/guide/task/kubernetes.html',
......
# Hive CLI
## Overview
Use `Hive Cli Task` to create a `Hive Cli` type task and execute hive SQL from scripts or files.
The workers run `hive -e` to execute hive sql from scripts or `hive -f` to execute from files in `Resource Center`.
## Hive CLI Task vs SQL Task With Hive Datasource
In DolphinScheduler, we have both `Hive CLI Task` and `SQL Task With Hive Datasource` for different scenarios.
You could choose between these two based on your needs.
- The `Hive CLI` task plugin connects directly to `HDFS` and the `Hive Metastore` for hive task executions,
which requires your workers to have access to those services, such as related `Hive` libs, `Hive` and `HDFS` configuration files.
However, `Hive CLI Task` provides better stability for scheduling in production.
- `SQL Task With Hive Datasource` does not require access to `Hive` libs, `Hive` and
`HDFS` configuration files and supports `Kerberos` for authentication. However, you may encounter `HiveServer2` failures
if your hive sql task scheduling puts significant pressure on it.
## Create Task
- Click `Project Management-Project Name-Workflow Definition`, and click the `Create Workflow` button to enter the DAG editing page.
- Drag <img src="../../../../img/tasks/icons/hivecli.png" width="15"/> from the toolbar to the canvas.
## Task Parameters
| **Parameter** | **Description** |
|------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Node Name | The name of the task. Node names within the same workflow must be unique. |
| Run Flag | Indicating whether to schedule the task. If you do not need to execute the task, you can turn on the `Prohibition execution` switch. |
| Description | Describing the function of this node. |
| Task Priority | When the number of the worker threads is insufficient, the worker executes task according to the priority. When two tasks have the same priority, the worker will execute them in `first come first served` fashion. |
| Worker Group | Machines which execute the tasks. If you choose `default`, scheduler will send the task to a random worker. |
| Task Group Name | Resource group of tasks. It will not take effect if not configured. |
| Environment Name | Environment to execute the task. |
| Number of Failed Retries | The number of task retries for failures. You could select it by drop-down menu or fill it manually. |
| Failure Retry Interval | Interval of task retries for failures. You could select it by drop-down menu or fill it manually. |
| CPU Quota | Assign the specified CPU time quota to the task executed. Takes a percentage value. Default -1 means unlimited. For example, the full CPU load of one core is 100%, and that of 16 cores is 1600%. You could configure it by [task.resource.limit.state](../../architecture/configuration.md). |
| Max Memory | Assign the specified max memory to the task executed. Exceeding this limit will trigger oom to be killed and will not automatically retry. Takes an MB value. Default -1 means unlimited. You could configure it by [task.resource.limit.state](../../architecture/configuration.md). |
| Timeout Alarm | Alarm for task timeout. When the task exceeds the "timeout threshold", an alarm email will send. |
| Hive Cli Task Execution Type | The type of hive cli task execution, choose either `FROM_SCRIPT` or `FROM_FILE`. |
| Hive SQL Script | If you choose `FROM_SCRIPT` for `Hive Cli Task Execution Type`, you need to fill in your SQL script. |
| Hive Cli Options | Extra options for hive cli, such as `--verbose` |
| Resources | If you choose `FROM_FILE` for `Hive Cli Task Execution Type`, you need to select your SQL file. |
## Task Example
### Hive Cli Task Example
This example below illustrates how to create a `Hive CLI` task node and execute hive SQL from script:
![demo-hive-cli-from-script](../../../../img/tasks/demo/hive_cli_from_script.png)
This example below illustrates how to create a `Hive CLI` task node and execute hive SQL from file:
![demo-hive-cli-from-file](../../../../img/tasks/demo/hive_cli_from_file.png)
# Hive CLI
## 综述
使用`Hive Cli任务插件`创建`Hive Cli`类型的任务执行SQL脚本语句或者SQL任务文件。
执行任务的worker会通过`hive -e`命令执行hive SQL脚本语句或者通过`hive -f`命令执行`资源中心`中的hive SQL文件。
## Hive CLI任务 VS 连接Hive数据源的SQL任务
在DolphinScheduler中,我们有`Hive CLI任务插件``使用Hive数据源的SQL插件`提供用户在不同场景下使用,您可以根据需要进行选择。
- `Hive CLI任务插件`直接连接`HDFS``Hive Metastore`来执行hive类型的任务,所以需要能够访问到对应的服务。
执行任务的worker节点需要有相应的`Hive` jar包以及`Hive``HDFS`的配置文件。
但是在生产调度中,`Hive CLI任务插件`能够提供更可靠的稳定性。
- `使用Hive数据源的SQL插件`不需要您在worker节点上有相应的`Hive` jar包以及`Hive``HDFS`的配置文件,而且支持 `Kerberos`认证。
但是在生产调度中,若调度压力很大,使用这种方式可能会遇到`HiveServer2`服务过载失败等问题。
## 创建任务
- 点击项目管理-项目名称-工作流定义,点击"创建工作流"按钮,进入DAG编辑页面。
- 工具栏中拖动 <img src="../../../../img/tasks/icons/hivecli.png" width="15"/> 到画板中,即可完成创建。
## 任务参数
- 前置任务:选择当前任务的前置任务,会将被选择的前置任务设置为当前任务的上游。
| **任务参数** | **描述** |
|---------------|-------------------------------------------------------------------------------------------------------------------------------------|
| 任务名称 | 设置任务的名称。一个工作流定义中的节点名称是唯一的。 |
| 运行标志 | 标识这个节点是否需要正常调度,如果不需要执行,可以打开禁止执行开关。 |
| 描述 | 描述该节点的功能。 |
| 任务优先级 | worker线程数不足时,根据优先级从高到低依次执行,优先级一样时根据先进先出原则执行。 |
| Worker分组 | 任务分配给worker组的机器机执行,选择Default,会随机选择一台worker机执行。 |
| 任务组名称 | 任务资源组,如果没有配置的话就不会生效。 |
| 环境名称 | 配置任务执行的环境。 |
| 失败重试次数 | 任务失败重新提交的次数,支持下拉和手填。 |
| 失败重试间隔 | 任务失败重新提交任务的时间间隔,支持下拉和手填。 |
| CPU 配额 | 为执行的任务分配指定的CPU时间配额,单位百分比,默认-1代表不限制,例如1个核心的CPU满载是100%,16个核心的是1600%。 [task.resource.limit.state](../../architecture/configuration.md) |
| 最大内存 | 为执行的任务分配指定的内存大小,超过会触发OOM被Kill同时不会进行自动重试,单位MB,默认-1代表不限制。这个功能由 [task.resource.limit.state](../../architecture/configuration.md) 控制。 |
| 超时告警 | 勾选超时告警、超时失败,当任务超过"超时时长"后,会发送告警邮件并且任务执行失败.这个功能由 [task.resource.limit.state](../../architecture/configuration.md) 控制。 |
| Hive Cli 任务类型 | Hive Cli任务执行方式,可以选择`FROM_SCRIPT`或者`FROM_FILE`。 |
| Hive SQL 脚本 | 手动填入您的Hive SQL脚本语句。 |
| Hive Cli 选项 | Hive Cli的其他选项,如`--verbose`。 |
| 资源 | 如果您选择`FROM_FILE`作为Hive Cli任务类型,您需要在资源中选择Hive SQL文件。 |
## 任务样例
### Hive CLI任务样例
下面的样例演示了如何使用`Hive CLI`任务节点执行Hive SQL脚本语句:
![demo-hive-cli-from-script](../../../../img/tasks/demo/hive_cli_from_script.png)
下面的样例演示了如何使用`Hive CLI`任务节点从资源中心的Hive SQL
![demo-hive-cli-from-file](../../../../img/tasks/demo/hive_cli_from_file.png)
...@@ -15,15 +15,14 @@ ...@@ -15,15 +15,14 @@
~ See the License for the specific language governing permissions and ~ See the License for the specific language governing permissions and
~ limitations under the License. ~ limitations under the License.
--> -->
<project xmlns="http://maven.apache.org/POM/4.0.0" <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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"> 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>
<parent> <parent>
<artifactId>dolphinscheduler-task-plugin</artifactId>
<groupId>org.apache.dolphinscheduler</groupId> <groupId>org.apache.dolphinscheduler</groupId>
<artifactId>dolphinscheduler-task-plugin</artifactId>
<version>dev-SNAPSHOT</version> <version>dev-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dolphinscheduler-task-all</artifactId> <artifactId>dolphinscheduler-task-all</artifactId>
...@@ -201,6 +200,12 @@ ...@@ -201,6 +200,12 @@
<artifactId>dolphinscheduler-task-pytorch</artifactId> <artifactId>dolphinscheduler-task-pytorch</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.apache.dolphinscheduler</groupId>
<artifactId>dolphinscheduler-task-hivecli</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies> </dependencies>
</project> </project>
<?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>
<parent>
<groupId>org.apache.dolphinscheduler</groupId>
<artifactId>dolphinscheduler-task-plugin</artifactId>
<version>dev-SNAPSHOT</version>
</parent>
<artifactId>dolphinscheduler-task-hivecli</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.apache.dolphinscheduler</groupId>
<artifactId>dolphinscheduler-spi</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dolphinscheduler</groupId>
<artifactId>dolphinscheduler-task-api</artifactId>
</dependency>
</dependencies>
</project>
/*
* 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.plugin.task.hivecli;
import lombok.experimental.UtilityClass;
@UtilityClass
public class HiveCliConstants {
public static final String TYPE_SCRIPT = "SCRIPT";
public static final String TYPE_FILE = "FILE";
public static final String HIVE_CLI_EXECUTE_FILE = "hive -f";
public static final String HIVE_CLI_EXECUTE_SCRIPT = "hive -e \"%s\"";
}
/*
* 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.plugin.task.hivecli;
import org.apache.dolphinscheduler.plugin.task.api.model.ResourceInfo;
import org.apache.dolphinscheduler.plugin.task.api.parameters.AbstractParameters;
import org.apache.dolphinscheduler.spi.utils.StringUtils;
import java.util.List;
import lombok.Data;
@Data
public class HiveCliParameters extends AbstractParameters {
private String hiveSqlScript;
private String hiveCliTaskExecutionType;
private String hiveCliOptions;
private List<ResourceInfo> resourceList;
@Override
public boolean checkParameters() {
if (!StringUtils.isNotEmpty(hiveCliTaskExecutionType)) {
return false;
}
if (HiveCliConstants.TYPE_SCRIPT.equals(hiveCliTaskExecutionType)) {
return StringUtils.isNotEmpty(hiveSqlScript);
} else if (HiveCliConstants.TYPE_FILE.equals(hiveCliTaskExecutionType)) {
return (resourceList != null) && (resourceList.size() > 0);
} else {
return false;
}
}
@Override
public List<ResourceInfo> getResourceFilesList() {
return this.resourceList;
}
}
/*
* 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.plugin.task.hivecli;
import static org.apache.dolphinscheduler.plugin.task.api.TaskConstants.EXIT_CODE_FAILURE;
import org.apache.dolphinscheduler.plugin.task.api.AbstractTaskExecutor;
import org.apache.dolphinscheduler.plugin.task.api.ShellCommandExecutor;
import org.apache.dolphinscheduler.plugin.task.api.TaskException;
import org.apache.dolphinscheduler.plugin.task.api.TaskExecutionContext;
import org.apache.dolphinscheduler.plugin.task.api.model.Property;
import org.apache.dolphinscheduler.plugin.task.api.model.ResourceInfo;
import org.apache.dolphinscheduler.plugin.task.api.model.TaskResponse;
import org.apache.dolphinscheduler.plugin.task.api.parameters.AbstractParameters;
import org.apache.dolphinscheduler.plugin.task.api.parser.ParamUtils;
import org.apache.dolphinscheduler.plugin.task.api.parser.ParameterUtils;
import org.apache.dolphinscheduler.spi.utils.JSONUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class HiveCliTask extends AbstractTaskExecutor {
private HiveCliParameters hiveCliParameters;
private final ShellCommandExecutor shellCommandExecutor;
private final TaskExecutionContext taskExecutionContext;
public HiveCliTask(TaskExecutionContext taskExecutionContext) {
super(taskExecutionContext);
this.taskExecutionContext = taskExecutionContext;
this.shellCommandExecutor = new ShellCommandExecutor(this::logHandle,
taskExecutionContext,
logger);
}
@Override
public void init() {
logger.info("hiveCli task params {}", taskExecutionContext.getTaskParams());
hiveCliParameters = JSONUtils.parseObject(taskExecutionContext.getTaskParams(), HiveCliParameters.class);
if (!hiveCliParameters.checkParameters()) {
throw new TaskException("hiveCli task params is not valid");
}
}
@Override
public void handle() throws TaskException {
try {
final TaskResponse taskResponse = shellCommandExecutor.run(buildCommand());
setExitStatusCode(taskResponse.getExitStatusCode());
setAppIds(taskResponse.getAppIds());
setProcessId(taskResponse.getProcessId());
setVarPool(shellCommandExecutor.getVarPool());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
logger.error("The current HiveCLI Task has been interrupted", e);
setExitStatusCode(EXIT_CODE_FAILURE);
throw new TaskException("The current HiveCLI Task has been interrupted", e);
} catch (Exception e) {
logger.error("hiveCli task failure", e);
setExitStatusCode(EXIT_CODE_FAILURE);
throw new TaskException("run hiveCli task error", e);
}
}
protected String buildCommand() {
final List<String> args = new ArrayList<>();
final String type = hiveCliParameters.getHiveCliTaskExecutionType();
// TODO: make sure type is not unknown
if (HiveCliConstants.TYPE_FILE.equals(type)) {
args.add(HiveCliConstants.HIVE_CLI_EXECUTE_FILE);
final List<ResourceInfo> resourceInfos = hiveCliParameters.getResourceList();
if (resourceInfos.size() > 1) {
logger.warn("more than 1 files detected, use the first one by default");
}
args.add(StringUtils.stripStart(resourceInfos.get(0).getResourceName(), "/"));
} else {
final String script = hiveCliParameters.getHiveSqlScript();
args.add(String.format(HiveCliConstants.HIVE_CLI_EXECUTE_SCRIPT, script));
}
final String hiveCliOptions = hiveCliParameters.getHiveCliOptions();
if (StringUtils.isNotEmpty(hiveCliOptions)) {
args.add(hiveCliOptions);
}
final Map<String, Property> paramsMap = taskExecutionContext.getPrepareParamsMap();
final String command =
ParameterUtils.convertParameterPlaceholders(String.join(" ", args), ParamUtils.convert(paramsMap));
logger.info("hiveCli task command: {}", command);
return command;
}
@Override
public AbstractParameters getParameters() {
return hiveCliParameters;
}
@Override
public void cancelApplication(boolean cancelApplication) throws Exception {
shellCommandExecutor.cancelApplication();
}
}
/*
* 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.plugin.task.hivecli;
import org.apache.dolphinscheduler.plugin.task.api.AbstractTask;
import org.apache.dolphinscheduler.plugin.task.api.TaskChannel;
import org.apache.dolphinscheduler.plugin.task.api.TaskExecutionContext;
import org.apache.dolphinscheduler.plugin.task.api.parameters.AbstractParameters;
import org.apache.dolphinscheduler.plugin.task.api.parameters.ParametersNode;
import org.apache.dolphinscheduler.plugin.task.api.parameters.resource.ResourceParametersHelper;
import org.apache.dolphinscheduler.spi.utils.JSONUtils;
public class HiveCliTaskChannel implements TaskChannel {
@Override
public void cancelApplication(boolean status) {
}
@Override
public AbstractTask createTask(TaskExecutionContext taskExecutionContext) {
return new HiveCliTask(taskExecutionContext);
}
@Override
public AbstractParameters parseParameters(ParametersNode parametersNode) {
return JSONUtils.parseObject(parametersNode.getTaskParams(), HiveCliParameters.class);
}
@Override
public ResourceParametersHelper getResources(String parameters) {
return null;
}
}
/*
* 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.plugin.task.hivecli;
import org.apache.dolphinscheduler.plugin.task.api.TaskChannel;
import org.apache.dolphinscheduler.plugin.task.api.TaskChannelFactory;
import org.apache.dolphinscheduler.spi.params.base.PluginParams;
import java.util.List;
import com.google.auto.service.AutoService;
@AutoService(TaskChannelFactory.class)
public class HiveCliTaskChannelFactory implements TaskChannelFactory {
@Override
public TaskChannel create() {
return new HiveCliTaskChannel();
}
@Override
public String getName() {
return "HIVECLI";
}
@Override
public List<PluginParams> getParams() {
return null;
}
}
/*
* 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.plugin.task.hivecli;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import org.apache.dolphinscheduler.plugin.task.api.TaskExecutionContext;
import org.apache.dolphinscheduler.plugin.task.api.model.ResourceInfo;
import org.apache.dolphinscheduler.spi.utils.JSONUtils;
import java.util.ArrayList;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class HiveCliTaskTest {
public static final String EXPECTED_HIVE_CLI_TASK_EXECUTE_FROM_SCRIPT_COMMAND =
"hive -e \"SHOW DATABASES;\"";
public static final String EXPECTED_HIVE_CLI_TASK_EXECUTE_FROM_FILE_COMMAND =
"hive -f sql_tasks/hive_task.sql";
public static final String EXPECTED_HIVE_CLI_TASK_EXECUTE_WITH_OPTIONS =
"hive -e \"SHOW DATABASES;\" --verbose";
@Test
public void hiveCliTaskExecuteSqlFromScript() throws Exception {
String hiveCliTaskParameters = buildHiveCliTaskExecuteSqlFromScriptParameters();
HiveCliTask hiveCliTask = prepareHiveCliTaskForTest(hiveCliTaskParameters);
hiveCliTask.init();
Assert.assertEquals(hiveCliTask.buildCommand(), EXPECTED_HIVE_CLI_TASK_EXECUTE_FROM_SCRIPT_COMMAND);
}
@Test
public void hiveCliTaskExecuteSqlFromFile() throws Exception {
String hiveCliTaskParameters = buildHiveCliTaskExecuteSqlFromFileParameters();
HiveCliTask hiveCliTask = prepareHiveCliTaskForTest(hiveCliTaskParameters);
hiveCliTask.init();
Assert.assertEquals(hiveCliTask.buildCommand(), EXPECTED_HIVE_CLI_TASK_EXECUTE_FROM_FILE_COMMAND);
}
@Test
public void hiveCliTaskExecuteWithOptions() throws Exception {
String hiveCliTaskParameters = buildHiveCliTaskExecuteWithOptionsParameters();
HiveCliTask hiveCliTask = prepareHiveCliTaskForTest(hiveCliTaskParameters);
hiveCliTask.init();
Assert.assertEquals(hiveCliTask.buildCommand(), EXPECTED_HIVE_CLI_TASK_EXECUTE_WITH_OPTIONS);
}
private HiveCliTask prepareHiveCliTaskForTest(final String hiveCliTaskParameters) {
TaskExecutionContext taskExecutionContext = Mockito.mock(TaskExecutionContext.class);
when(taskExecutionContext.getTaskParams()).thenReturn(hiveCliTaskParameters);
HiveCliTask hiveCliTask = spy(new HiveCliTask(taskExecutionContext));
return hiveCliTask;
}
private String buildHiveCliTaskExecuteSqlFromScriptParameters() {
final HiveCliParameters hiveCliParameters = new HiveCliParameters();
hiveCliParameters.setHiveCliTaskExecutionType("SCRIPT");
hiveCliParameters.setHiveSqlScript("SHOW DATABASES;");
return JSONUtils.toJsonString(hiveCliParameters);
}
private String buildHiveCliTaskExecuteSqlFromFileParameters() {
final HiveCliParameters hiveCliParameters = new HiveCliParameters();
hiveCliParameters.setHiveCliTaskExecutionType("FILE");
List<ResourceInfo> resources = new ArrayList<>();
ResourceInfo sqlResource = new ResourceInfo();
sqlResource.setResourceName("/sql_tasks/hive_task.sql");
resources.add(sqlResource);
hiveCliParameters.setResourceList(resources);
return JSONUtils.toJsonString(hiveCliParameters);
}
private String buildHiveCliTaskExecuteWithOptionsParameters() {
final HiveCliParameters hiveCliParameters = new HiveCliParameters();
hiveCliParameters.setHiveCliTaskExecutionType("SCRIPT");
hiveCliParameters.setHiveSqlScript("SHOW DATABASES;");
hiveCliParameters.setHiveCliOptions("--verbose");
return JSONUtils.toJsonString(hiveCliParameters);
}
}
...@@ -15,15 +15,14 @@ ...@@ -15,15 +15,14 @@
~ See the License for the specific language governing permissions and ~ See the License for the specific language governing permissions and
~ limitations under the License. ~ limitations under the License.
--> -->
<project xmlns="http://maven.apache.org/POM/4.0.0" <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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"> 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>
<parent> <parent>
<artifactId>dolphinscheduler</artifactId>
<groupId>org.apache.dolphinscheduler</groupId> <groupId>org.apache.dolphinscheduler</groupId>
<artifactId>dolphinscheduler</artifactId>
<version>dev-SNAPSHOT</version> <version>dev-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dolphinscheduler-task-plugin</artifactId> <artifactId>dolphinscheduler-task-plugin</artifactId>
<packaging>pom</packaging> <packaging>pom</packaging>
...@@ -61,6 +60,7 @@ ...@@ -61,6 +60,7 @@
<module>dolphinscheduler-task-chunjun</module> <module>dolphinscheduler-task-chunjun</module>
<module>dolphinscheduler-task-flink-stream</module> <module>dolphinscheduler-task-flink-stream</module>
<module>dolphinscheduler-task-pytorch</module> <module>dolphinscheduler-task-pytorch</module>
<module>dolphinscheduler-task-hivecli</module>
</modules> </modules>
<dependencyManagement> <dependencyManagement>
......
...@@ -341,7 +341,9 @@ export function useDataList() { ...@@ -341,7 +341,9 @@ export function useDataList() {
label: t('user_dropdown.password'), label: t('user_dropdown.password'),
key: 'password', key: 'password',
icon: renderIcon(KeyOutlined), icon: renderIcon(KeyOutlined),
disabled: (userStore.getUserInfo as UserInfoRes).securityConfigType !== 'PASSWORD' disabled:
(userStore.getUserInfo as UserInfoRes).securityConfigType !==
'PASSWORD'
}, },
{ {
label: t('user_dropdown.logout'), label: t('user_dropdown.logout'),
......
...@@ -646,11 +646,20 @@ export default { ...@@ -646,11 +646,20 @@ export default {
zeppelin_paragraph_id_tips: zeppelin_paragraph_id_tips:
'Please enter the paragraph id of your zeppelin paragraph', 'Please enter the paragraph id of your zeppelin paragraph',
zeppelin_parameters: 'parameters', zeppelin_parameters: 'parameters',
zeppelin_parameters_tips: 'Please enter the parameters for zeppelin dynamic form', zeppelin_parameters_tips:
'Please enter the parameters for zeppelin dynamic form',
zeppelin_rest_endpoint: 'zeppelinRestEndpoint', zeppelin_rest_endpoint: 'zeppelinRestEndpoint',
zeppelin_rest_endpoint_tips: 'Please enter the rest endpoint of your Zeppelin server', zeppelin_rest_endpoint_tips:
zeppelin_production_note_directory: 'Directory for cloned zeppelin note in production mode', 'Please enter the rest endpoint of your Zeppelin server',
zeppelin_production_note_directory_tips: 'Please enter the production note directory to enable production mode', zeppelin_production_note_directory:
'Directory for cloned zeppelin note in production mode',
zeppelin_production_note_directory_tips:
'Please enter the production note directory to enable production mode',
hive_cli_task_execution_type: 'Hive Cli Task Execution Type',
hive_sql_script: 'Hive SQL Script',
hive_cli_options: 'Hive Cli Options',
hive_cli_options_tips:
'Please enter the options for hive cli, e.g. --verbose',
jupyter_conda_env_name: 'condaEnvName', jupyter_conda_env_name: 'condaEnvName',
jupyter_conda_env_name_tips: jupyter_conda_env_name_tips:
'Please enter the conda environment name of papermill', 'Please enter the conda environment name of papermill',
...@@ -764,6 +773,7 @@ export default { ...@@ -764,6 +773,7 @@ export default {
pytorch_python_env_tool: 'Python Environment Manager Tool', pytorch_python_env_tool: 'Python Environment Manager Tool',
pytorch_requirements: 'Requirement File', pytorch_requirements: 'Requirement File',
pytorch_conda_python_version: 'Python Version', pytorch_conda_python_version: 'Python Version',
pytorch_conda_python_version_tips: 'Please enter the version number, such as 3.6, 3.7, 3.x' pytorch_conda_python_version_tips:
'Please enter the version number, such as 3.6, 3.7, 3.x'
} }
} }
...@@ -638,12 +638,17 @@ export default { ...@@ -638,12 +638,17 @@ export default {
zeppelin_note_id_tips: '请输入zeppelin note id', zeppelin_note_id_tips: '请输入zeppelin note id',
zeppelin_paragraph_id: 'zeppelinParagraphId', zeppelin_paragraph_id: 'zeppelinParagraphId',
zeppelin_production_note_directory: '生产模式下存放克隆note的目录', zeppelin_production_note_directory: '生产模式下存放克隆note的目录',
zeppelin_production_note_directory_tips: '请输入生产环境note目录以启用生产模式', zeppelin_production_note_directory_tips:
'请输入生产环境note目录以启用生产模式',
zeppelin_paragraph_id_tips: '请输入zeppelin paragraph id', zeppelin_paragraph_id_tips: '请输入zeppelin paragraph id',
zeppelin_parameters: 'parameters', zeppelin_parameters: 'parameters',
zeppelin_parameters_tips: '请输入zeppelin dynamic form参数', zeppelin_parameters_tips: '请输入zeppelin dynamic form参数',
zeppelin_rest_endpoint: 'zeppelinRestEndpoint', zeppelin_rest_endpoint: 'zeppelinRestEndpoint',
zeppelin_rest_endpoint_tips: '请输入zeppelin server的rest endpoint', zeppelin_rest_endpoint_tips: '请输入zeppelin server的rest endpoint',
hive_cli_task_execution_type: 'Hive Cli 任务类型',
hive_sql_script: 'Hive SQL 脚本',
hive_cli_options: 'Hive Cli 选项',
hive_cli_options_tips: '请输入您的Hive Cli选项,如--verbose等',
jupyter_conda_env_name: 'condaEnvName', jupyter_conda_env_name: 'condaEnvName',
jupyter_conda_env_name_tips: '请输入papermill所在的conda环境名', jupyter_conda_env_name_tips: '请输入papermill所在的conda环境名',
jupyter_input_note_path: 'inputNotePath', jupyter_input_note_path: 'inputNotePath',
......
...@@ -15,7 +15,13 @@ ...@@ -15,7 +15,13 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineComponent, getCurrentInstance, onMounted, ref, toRefs } from 'vue' import {
defineComponent,
getCurrentInstance,
onMounted,
ref,
toRefs
} from 'vue'
import { import {
NSpace, NSpace,
NInput, NInput,
......
...@@ -15,7 +15,13 @@ ...@@ -15,7 +15,13 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineComponent, getCurrentInstance, onMounted, toRefs, watch } from 'vue' import {
defineComponent,
getCurrentInstance,
onMounted,
toRefs,
watch
} from 'vue'
import { import {
NSpace, NSpace,
NInput, NInput,
...@@ -24,7 +30,7 @@ import { ...@@ -24,7 +30,7 @@ import {
NButton, NButton,
NIcon, NIcon,
NDataTable, NDataTable,
NPagination, NPagination
} from 'naive-ui' } from 'naive-ui'
import { SearchOutlined } from '@vicons/antd' import { SearchOutlined } from '@vicons/antd'
import { useTable } from './use-table' import { useTable } from './use-table'
......
...@@ -30,9 +30,9 @@ import type { ...@@ -30,9 +30,9 @@ import type {
ResultListRes ResultListRes
} from '@/service/modules/data-quality/types' } from '@/service/modules/data-quality/types'
import { parseTime } from '@/common/common' import { parseTime } from '@/common/common'
import ButtonLink from "@/components/button-link"; import ButtonLink from '@/components/button-link'
import { NEllipsis, NTag } from "naive-ui"; import { NEllipsis, NTag } from 'naive-ui'
import { useRouter } from "vue-router"; import { useRouter } from 'vue-router'
export function useTable() { export function useTable() {
const { t } = useI18n() const { t } = useI18n()
...@@ -76,7 +76,10 @@ export function useTable() { ...@@ -76,7 +76,10 @@ export function useTable() {
onClick: () => onClick: () =>
void router.push({ void router.push({
name: 'workflow-instance-detail', name: 'workflow-instance-detail',
params: { projectCode: row.projectCode, id: row.processInstanceId }, params: {
projectCode: row.projectCode,
id: row.processInstanceId
},
query: { code: row.processDefinitionCode } query: { code: row.processDefinitionCode }
}) })
}, },
......
...@@ -15,7 +15,13 @@ ...@@ -15,7 +15,13 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineComponent, getCurrentInstance, PropType, toRefs, watch } from 'vue' import {
defineComponent,
getCurrentInstance,
PropType,
toRefs,
watch
} from 'vue'
import { import {
NButton, NButton,
NSpin, NSpin,
...@@ -91,10 +97,10 @@ const DetailModal = defineComponent({ ...@@ -91,10 +97,10 @@ const DetailModal = defineComponent({
async () => { async () => {
props.show && props.show &&
state.detailForm.type && state.detailForm.type &&
await changeType( (await changeType(
state.detailForm.type, state.detailForm.type,
datasourceType[state.detailForm.type] datasourceType[state.detailForm.type]
) ))
props.show && props.id && setFieldsValue(await queryById(props.id)) props.show && props.id && setFieldsValue(await queryById(props.id))
} }
) )
......
...@@ -15,7 +15,14 @@ ...@@ -15,7 +15,14 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineComponent, getCurrentInstance, onMounted, ref, toRefs, watch } from 'vue' import {
defineComponent,
getCurrentInstance,
onMounted,
ref,
toRefs,
watch
} from 'vue'
import { import {
NButton, NButton,
NInput, NInput,
...@@ -113,10 +120,7 @@ const list = defineComponent({ ...@@ -113,10 +120,7 @@ const list = defineComponent({
> >
{t('datasource.create_datasource')} {t('datasource.create_datasource')}
</NButton> </NButton>
<NSpace <NSpace justify='end' wrap={false}>
justify='end'
wrap={false}
>
<NInput <NInput
allowInput={this.trim} allowInput={this.trim}
v-model={[this.searchVal, 'value']} v-model={[this.searchVal, 'value']}
......
...@@ -51,7 +51,14 @@ const login = defineComponent({ ...@@ -51,7 +51,14 @@ const login = defineComponent({
cookies.set('language', localesStore.getLocales, { path: '/' }) cookies.set('language', localesStore.getLocales, { path: '/' })
return { t, handleChange, handleLogin, ...toRefs(state), localesStore, trim } return {
t,
handleChange,
handleLogin,
...toRefs(state),
localesStore,
trim
}
}, },
render() { render() {
return ( return (
......
...@@ -15,7 +15,13 @@ ...@@ -15,7 +15,13 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineComponent, getCurrentInstance, onMounted, toRefs, watch } from 'vue' import {
defineComponent,
getCurrentInstance,
onMounted,
toRefs,
watch
} from 'vue'
import { import {
NSpace, NSpace,
NInput, NInput,
......
...@@ -15,7 +15,13 @@ ...@@ -15,7 +15,13 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineComponent, getCurrentInstance, onMounted, ref, toRefs } from 'vue' import {
defineComponent,
getCurrentInstance,
onMounted,
ref,
toRefs
} from 'vue'
import { useForm } from './use-form' import { useForm } from './use-form'
import { NButton, NForm, NFormItem, NInput } from 'naive-ui' import { NButton, NForm, NFormItem, NInput } from 'naive-ui'
import { useUserinfo } from './use-userinfo' import { useUserinfo } from './use-userinfo'
......
...@@ -15,7 +15,13 @@ ...@@ -15,7 +15,13 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineComponent, getCurrentInstance, PropType, toRefs, watch } from 'vue' import {
defineComponent,
getCurrentInstance,
PropType,
toRefs,
watch
} from 'vue'
import { NForm, NFormItem, NInput } from 'naive-ui' import { NForm, NFormItem, NInput } from 'naive-ui'
import { useForm } from './use-form' import { useForm } from './use-form'
import Modal from '@/components/modal' import Modal from '@/components/modal'
...@@ -90,7 +96,7 @@ const ProjectModal = defineComponent({ ...@@ -90,7 +96,7 @@ const ProjectModal = defineComponent({
} }
) )
return { ...toRefs(variables), t, cancelModal, confirmModal, trim} return { ...toRefs(variables), t, cancelModal, confirmModal, trim }
}, },
render() { render() {
const { t } = this const { t } = this
......
...@@ -24,7 +24,13 @@ import { ...@@ -24,7 +24,13 @@ import {
NPagination, NPagination,
NSpace NSpace
} from 'naive-ui' } from 'naive-ui'
import { defineComponent, getCurrentInstance, onMounted, toRefs, watch } from 'vue' import {
defineComponent,
getCurrentInstance,
onMounted,
toRefs,
watch
} from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { useTable } from './use-table' import { useTable } from './use-table'
import Card from '@/components/card' import Card from '@/components/card'
......
...@@ -77,3 +77,4 @@ export { useSagemaker } from './use-sagemaker' ...@@ -77,3 +77,4 @@ export { useSagemaker } from './use-sagemaker'
export { useChunjun } from './use-chunjun' export { useChunjun } from './use-chunjun'
export { useChunjunDeployMode } from './use-chunjun-deploy-mode' export { useChunjunDeployMode } from './use-chunjun-deploy-mode'
export { usePytorch } from './use-pytorch' export { usePytorch } from './use-pytorch'
export { useHiveCli } from './use-hive-cli'
...@@ -17,14 +17,18 @@ ...@@ -17,14 +17,18 @@
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { useCustomParams } from '.' import { useCustomParams } from '.'
import type { IJsonItem } from '../types' import type { IJsonItem } from '../types'
import {computed} from "vue"; import { computed } from 'vue'
export function useEmr(model: { [field: string]: any }): IJsonItem[] { export function useEmr(model: { [field: string]: any }): IJsonItem[] {
const { t } = useI18n() const { t } = useI18n()
const jobFlowDefineJsonSpan = computed(() => (model.programType === 'RUN_JOB_FLOW' ? 24 : 0)) const jobFlowDefineJsonSpan = computed(() =>
model.programType === 'RUN_JOB_FLOW' ? 24 : 0
)
const stepsDefineJsonSpan = computed(() => (model.programType === 'ADD_JOB_FLOW_STEPS' ? 24 : 0)) const stepsDefineJsonSpan = computed(() =>
model.programType === 'ADD_JOB_FLOW_STEPS' ? 24 : 0
)
return [ return [
{ {
......
/*
* 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.
*/
import { useI18n } from 'vue-i18n'
import { useCustomParams, useResources } from '.'
import type { IJsonItem } from '../types'
export function useHiveCli(model: { [field: string]: any }): IJsonItem[] {
const { t } = useI18n()
return [
{
type: 'select',
field: 'hiveCliTaskExecutionType',
span: 12,
name: t('project.node.hive_cli_task_execution_type'),
options: HIVE_CLI_TASK_EXECUTION_TYPES
},
{
type: 'editor',
field: 'hiveSqlScript',
name: t('project.node.hive_sql_script'),
props: {
language: 'sql'
}
},
{
type: 'input',
field: 'hiveCliOptions',
name: t('project.node.hive_cli_options'),
props: {
placeholder: t('project.node.hive_cli_options_tips')
}
},
useResources(),
...useCustomParams({ model, field: 'localParams', isSimple: false })
]
}
export const HIVE_CLI_TASK_EXECUTION_TYPES = [
{
label: 'FROM_SCRIPT',
value: 'SCRIPT'
},
{
label: 'FROM_FILE',
value: 'FILE'
}
]
...@@ -47,8 +47,8 @@ export function useMlflowModels(model: { [field: string]: any }): IJsonItem[] { ...@@ -47,8 +47,8 @@ export function useMlflowModels(model: { [field: string]: any }): IJsonItem[] {
watch( watch(
() => [model.deployType], () => [model.deployType],
() => { () => {
cpuLimitSpan.value = model.deployType === "DOCKER COMPOSE" ? 12 : 0 cpuLimitSpan.value = model.deployType === 'DOCKER COMPOSE' ? 12 : 0
memoryLimitSpan.value = model.deployType === "DOCKER COMPOSE" ? 12 : 0 memoryLimitSpan.value = model.deployType === 'DOCKER COMPOSE' ? 12 : 0
} }
) )
......
...@@ -46,7 +46,8 @@ export function usePytorch(model: { [field: string]: any }): IJsonItem[] { ...@@ -46,7 +46,8 @@ export function usePytorch(model: { [field: string]: any }): IJsonItem[] {
isCreateEnvironmentSpan.value = model.otherParams ? 12 : 0 isCreateEnvironmentSpan.value = model.otherParams ? 12 : 0
pythonPathSpan.value = model.otherParams ? 24 : 0 pythonPathSpan.value = model.otherParams ? 24 : 0
pythonEnvToolSpan.value = model.showCreateEnvironment ? 12 : 0 pythonEnvToolSpan.value = model.showCreateEnvironment ? 12 : 0
pythonCommandSpan.value = ~model.showCreateEnvironment & model.otherParams ? 12 : 0 pythonCommandSpan.value =
~model.showCreateEnvironment & model.otherParams ? 12 : 0
requirementsSpan.value = model.showCreateEnvironment ? 24 : 0 requirementsSpan.value = model.showCreateEnvironment ? 24 : 0
condaPythonVersionSpan.value = model.showCreateConda ? 24 : 0 condaPythonVersionSpan.value = model.showCreateConda ? 24 : 0
} }
......
...@@ -29,7 +29,7 @@ export function useResourceLimit(): IJsonItem[] { ...@@ -29,7 +29,7 @@ export function useResourceLimit(): IJsonItem[] {
slots: { slots: {
suffix: () => '%' suffix: () => '%'
}, },
props: {min: -1} props: { min: -1 }
}, },
{ {
type: 'input-number', type: 'input-number',
...@@ -39,7 +39,7 @@ export function useResourceLimit(): IJsonItem[] { ...@@ -39,7 +39,7 @@ export function useResourceLimit(): IJsonItem[] {
slots: { slots: {
suffix: () => t('project.node.mb') suffix: () => t('project.node.mb')
}, },
props: {min: -1} props: { min: -1 }
} }
] ]
} }
...@@ -18,12 +18,11 @@ import type { IJsonItem } from '../types' ...@@ -18,12 +18,11 @@ import type { IJsonItem } from '../types'
import { useCustomParams } from '.' import { useCustomParams } from '.'
export function useSagemaker(model: { [field: string]: any }): IJsonItem[] { export function useSagemaker(model: { [field: string]: any }): IJsonItem[] {
return [ return [
{ {
type: 'editor', type: 'editor',
field: 'sagemakerRequestJson', field: 'sagemakerRequestJson',
name: "SagemakerRequestJson", name: 'SagemakerRequestJson',
props: { props: {
language: 'json' language: 'json'
}, },
......
...@@ -421,6 +421,12 @@ export function formatParams(data: INodeData): { ...@@ -421,6 +421,12 @@ export function formatParams(data: INodeData): {
taskParams.targetJobName = data.targetJobName taskParams.targetJobName = data.targetJobName
} }
if (data.taskType === 'HIVECLI') {
taskParams.hiveCliTaskExecutionType = data.hiveCliTaskExecutionType
taskParams.hiveSqlScript = data.hiveSqlScript
taskParams.hiveCliOptions = data.hiveCliOptions
}
let timeoutNotifyStrategy = '' let timeoutNotifyStrategy = ''
if (data.timeoutNotifyStrategy) { if (data.timeoutNotifyStrategy) {
if (data.timeoutNotifyStrategy.length === 1) { if (data.timeoutNotifyStrategy.length === 1) {
...@@ -658,5 +664,6 @@ export function formatModel(data: ITaskData) { ...@@ -658,5 +664,6 @@ export function formatModel(data: ITaskData) {
if (data.taskParams?.jobType) { if (data.taskParams?.jobType) {
params.isCustomTask = data.taskParams.jobType === 'CUSTOM' params.isCustomTask = data.taskParams.jobType === 'CUSTOM'
} }
return params return params
} }
...@@ -44,6 +44,7 @@ import { useDinky } from './use-dinky' ...@@ -44,6 +44,7 @@ import { useDinky } from './use-dinky'
import { userSagemaker } from './use-sagemaker' import { userSagemaker } from './use-sagemaker'
import { useChunjun } from './use-chunjun' import { useChunjun } from './use-chunjun'
import { usePytorch } from './use-pytorch' import { usePytorch } from './use-pytorch'
import { useHiveCli } from './use-hive-cli'
export default { export default {
SHELL: useShell, SHELL: useShell,
...@@ -74,5 +75,6 @@ export default { ...@@ -74,5 +75,6 @@ export default {
SAGEMAKER: userSagemaker, SAGEMAKER: userSagemaker,
CHUNJUN: useChunjun, CHUNJUN: useChunjun,
FLINK_STREAM: useFlinkStream, FLINK_STREAM: useFlinkStream,
PYTORCH: usePytorch PYTORCH: usePytorch,
HIVECLI: useHiveCli
} }
/*
* 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.
*/
import { reactive } from 'vue'
import * as Fields from '../fields/index'
import type { IJsonItem, INodeData, ITaskData } from '../types'
export function useHiveCli({
projectCode,
from = 0,
readonly,
data
}: {
projectCode: number
from?: number
readonly?: boolean
data?: ITaskData
}) {
const model = reactive({
name: '',
taskType: 'HIVECLI',
flag: 'YES',
description: '',
timeoutFlag: false,
localParams: [],
environmentCode: null,
failRetryInterval: 1,
failRetryTimes: 0,
workerGroup: 'default',
delayTime: 0,
timeout: 30
} as INodeData)
let extra: IJsonItem[] = []
if (from === 1) {
extra = [
Fields.useTaskType(model, readonly),
Fields.useProcessName({
model,
projectCode,
isCreate: !data?.id,
from,
processName: data?.processName
})
]
}
return {
json: [
Fields.useName(from),
...extra,
Fields.useRunFlag(),
Fields.useDescription(),
Fields.useTaskPriority(),
Fields.useWorkerGroup(),
Fields.useEnvironmentName(model, !model.id),
...Fields.useTaskGroup(model, projectCode),
...Fields.useFailed(),
Fields.useDelayTime(model),
...Fields.useTimeoutAlarm(model),
...Fields.useHiveCli(model),
Fields.usePreTasks()
] as IJsonItem[],
model
}
}
...@@ -85,4 +85,3 @@ export function usePytorch({ ...@@ -85,4 +85,3 @@ export function usePytorch({
model model
} }
} }
...@@ -306,6 +306,9 @@ interface ITaskParams { ...@@ -306,6 +306,9 @@ interface ITaskParams {
restEndpoint?: string restEndpoint?: string
zeppelinProductionNoteDirectory?: string zeppelinProductionNoteDirectory?: string
productionNoteDirectory?: string productionNoteDirectory?: string
hiveCliOptions?: string
hiveSqlScript?: string
hiveCliTaskExecutionType?: string
noteId?: string noteId?: string
paragraphId?: string paragraphId?: string
condaEnvName?: string condaEnvName?: string
......
...@@ -44,6 +44,7 @@ export type TaskType = ...@@ -44,6 +44,7 @@ export type TaskType =
| 'CHUNJUN' | 'CHUNJUN'
| 'FLINK_STREAM' | 'FLINK_STREAM'
| 'PYTORCH' | 'PYTORCH'
| 'HIVECLI'
export type TaskExecuteType = 'STREAM' | 'BATCH' export type TaskExecuteType = 'STREAM' | 'BATCH'
...@@ -151,6 +152,10 @@ export const TASK_TYPES_MAP = { ...@@ -151,6 +152,10 @@ export const TASK_TYPES_MAP = {
PYTORCH: { PYTORCH: {
alias: 'Pytorch', alias: 'Pytorch',
helperLinkDisable: true helperLinkDisable: true
},
HIVECLI: {
alias: 'HIVECLI',
helperLinkDisable: true
} }
} as { } as {
[key in TaskType]: { [key in TaskType]: {
......
...@@ -160,9 +160,7 @@ export default defineComponent({ ...@@ -160,9 +160,7 @@ export default defineComponent({
> >
<NForm ref='startFormRef' model={this.startForm}> <NForm ref='startFormRef' model={this.startForm}>
<NFormItem label={t('project.task.task_name')} path='task_name'> <NFormItem label={t('project.task.task_name')} path='task_name'>
<div title={this.row.taskName}> <div title={this.row.taskName}>{this.row.taskName}</div>
{this.row.taskName}
</div>
</NFormItem> </NFormItem>
<NFormItem <NFormItem
label={t('project.task.notification_strategy')} label={t('project.task.notification_strategy')}
......
...@@ -133,8 +133,8 @@ export default defineComponent({ ...@@ -133,8 +133,8 @@ export default defineComponent({
onClick={this.startRunning} onClick={this.startRunning}
> >
{t('project.node.start')} {t('project.node.start')}
</NButton>) </NButton>
} )}
{this.menuDisplay && ( {this.menuDisplay && (
<> <>
<NButton <NButton
......
...@@ -159,6 +159,9 @@ $bgLight: #ffffff; ...@@ -159,6 +159,9 @@ $bgLight: #ffffff;
&.icon-zeppelin { &.icon-zeppelin {
background-image: url('/images/task-icons/zeppelin.png'); background-image: url('/images/task-icons/zeppelin.png');
} }
&.icon-hivecli {
background-image: url('/images/task-icons/hivecli.png');
}
&.icon-k8s { &.icon-k8s {
background-image: url('/images/task-icons/k8s.png'); background-image: url('/images/task-icons/k8s.png');
} }
...@@ -248,6 +251,9 @@ $bgLight: #ffffff; ...@@ -248,6 +251,9 @@ $bgLight: #ffffff;
&.icon-zeppelin { &.icon-zeppelin {
background-image: url('/images/task-icons/zeppelin_hover.png'); background-image: url('/images/task-icons/zeppelin_hover.png');
} }
&.icon-hivecli {
background-image: url('/images/task-icons/hivecli_hover.png');
}
&.icon-k8s { &.icon-k8s {
background-image: url('/images/task-icons/k8s_hover.png'); background-image: url('/images/task-icons/k8s_hover.png');
} }
......
...@@ -27,7 +27,7 @@ import { ...@@ -27,7 +27,7 @@ import {
computed computed
} from 'vue' } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { useRoute } from "vue-router" import { useRoute } from 'vue-router'
import Modal from '@/components/modal' import Modal from '@/components/modal'
import { useForm } from './use-form' import { useForm } from './use-form'
import { useModal } from './use-modal' import { useModal } from './use-modal'
...@@ -147,7 +147,9 @@ export default defineComponent({ ...@@ -147,7 +147,9 @@ export default defineComponent({
} }
] ]
const showTaskDependType = computed(() => route.name === 'workflow-definition-detail') const showTaskDependType = computed(
() => route.name === 'workflow-definition-detail'
)
const renderLabel = (option: any) => { const renderLabel = (option: any) => {
return [ return [
...@@ -267,13 +269,19 @@ export default defineComponent({ ...@@ -267,13 +269,19 @@ export default defineComponent({
> >
<NRadioGroup v-model:value={this.startForm.taskDependType}> <NRadioGroup v-model:value={this.startForm.taskDependType}>
<NSpace> <NSpace>
<NRadio value='TASK_POST'>{t('project.workflow.backward_execution')}</NRadio> <NRadio value='TASK_POST'>
<NRadio value='TASK_PRE'>{t('project.workflow.forward_execution')}</NRadio> {t('project.workflow.backward_execution')}
<NRadio value='TASK_ONLY'>{t('project.workflow.current_node_execution')}</NRadio> </NRadio>
<NRadio value='TASK_PRE'>
{t('project.workflow.forward_execution')}
</NRadio>
<NRadio value='TASK_ONLY'>
{t('project.workflow.current_node_execution')}
</NRadio>
</NSpace> </NSpace>
</NRadioGroup> </NRadioGroup>
</NFormItem>) </NFormItem>
} )}
<NFormItem <NFormItem
label={t('project.workflow.notification_strategy')} label={t('project.workflow.notification_strategy')}
path='warningType' path='warningType'
...@@ -345,7 +353,9 @@ export default defineComponent({ ...@@ -345,7 +353,9 @@ export default defineComponent({
label={t('project.workflow.mode_of_dependent')} label={t('project.workflow.mode_of_dependent')}
path='complementDependentMode' path='complementDependentMode'
> >
<NRadioGroup v-model:value={this.startForm.complementDependentMode}> <NRadioGroup
v-model:value={this.startForm.complementDependentMode}
>
<NSpace> <NSpace>
<NRadio value={'OFF_MODE'}> <NRadio value={'OFF_MODE'}>
{t('project.workflow.close')} {t('project.workflow.close')}
......
...@@ -26,7 +26,13 @@ import { ...@@ -26,7 +26,13 @@ import {
NTooltip, NTooltip,
NPopconfirm NPopconfirm
} from 'naive-ui' } from 'naive-ui'
import { defineComponent, getCurrentInstance, onMounted, toRefs, watch } from 'vue' import {
defineComponent,
getCurrentInstance,
onMounted,
toRefs,
watch
} from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { useTable } from './use-table' import { useTable } from './use-table'
import { useRouter, useRoute } from 'vue-router' import { useRouter, useRoute } from 'vue-router'
...@@ -128,7 +134,12 @@ export default defineComponent({ ...@@ -128,7 +134,12 @@ export default defineComponent({
> >
{t('project.workflow.create_workflow')} {t('project.workflow.create_workflow')}
</NButton> </NButton>
<NButton strong secondary size='small' onClick={() => (this.showRef = true)}> <NButton
strong
secondary
size='small'
onClick={() => (this.showRef = true)}
>
{t('project.workflow.import_workflow')} {t('project.workflow.import_workflow')}
</NButton> </NButton>
</NSpace> </NSpace>
......
...@@ -16,14 +16,7 @@ ...@@ -16,14 +16,7 @@
*/ */
import { SearchOutlined } from '@vicons/antd' import { SearchOutlined } from '@vicons/antd'
import { import { NInput, NButton, NDatePicker, NSelect, NIcon, NSpace } from 'naive-ui'
NInput,
NButton,
NDatePicker,
NSelect,
NIcon,
NSpace
} from 'naive-ui'
import { defineComponent, getCurrentInstance, ref } from 'vue' import { defineComponent, getCurrentInstance, ref } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { format } from 'date-fns' import { format } from 'date-fns'
...@@ -102,7 +95,7 @@ export default defineComponent({ ...@@ -102,7 +95,7 @@ export default defineComponent({
<NSelect <NSelect
options={options} options={options}
size='small' size='small'
style={{width: '210px'}} style={{ width: '210px' }}
defaultValue={''} defaultValue={''}
v-model:value={this.stateTypeRef} v-model:value={this.stateTypeRef}
/> />
......
...@@ -16,7 +16,14 @@ ...@@ -16,7 +16,14 @@
*/ */
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { defineComponent, onMounted, ref, reactive, Ref, getCurrentInstance } from 'vue' import {
defineComponent,
onMounted,
ref,
reactive,
Ref,
getCurrentInstance
} from 'vue'
import { import {
NIcon, NIcon,
NSpace, NSpace,
......
...@@ -14,7 +14,13 @@ ...@@ -14,7 +14,13 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { defineComponent, toRefs, PropType, watch, getCurrentInstance } from 'vue' import {
defineComponent,
toRefs,
PropType,
watch,
getCurrentInstance
} from 'vue'
import { NForm, NFormItem, NInput } from 'naive-ui' import { NForm, NFormItem, NInput } from 'naive-ui'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import Modal from '@/components/modal' import Modal from '@/components/modal'
......
...@@ -15,7 +15,14 @@ ...@@ -15,7 +15,14 @@
* limitations under the License. * limitations under the License.
*/ */
import { ref, defineComponent, toRefs, reactive, onMounted, getCurrentInstance } from 'vue' import {
ref,
defineComponent,
toRefs,
reactive,
onMounted,
getCurrentInstance
} from 'vue'
import { import {
NButton, NButton,
NIcon, NIcon,
......
...@@ -15,7 +15,13 @@ ...@@ -15,7 +15,13 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineComponent, PropType, toRefs, onMounted, getCurrentInstance } from 'vue' import {
defineComponent,
PropType,
toRefs,
onMounted,
getCurrentInstance
} from 'vue'
import { NForm, NFormItem, NInput } from 'naive-ui' import { NForm, NFormItem, NInput } from 'naive-ui'
import { useForm } from '../use-form' import { useForm } from '../use-form'
import Modal from '@/components/modal' import Modal from '@/components/modal'
...@@ -83,7 +89,9 @@ const FormModal = defineComponent({ ...@@ -83,7 +89,9 @@ const FormModal = defineComponent({
path='priority' path='priority'
> >
<NInput <NInput
allowInput={this.trim} v-model:value={this.formData.priority} /> allowInput={this.trim}
v-model:value={this.formData.priority}
/>
</NFormItem> </NFormItem>
</NForm> </NForm>
</Modal> </Modal>
......
...@@ -15,7 +15,14 @@ ...@@ -15,7 +15,14 @@
* limitations under the License. * limitations under the License.
*/ */
import { ref, defineComponent, toRefs, reactive, onMounted, getCurrentInstance } from 'vue' import {
ref,
defineComponent,
toRefs,
reactive,
onMounted,
getCurrentInstance
} from 'vue'
import { import {
NButton, NButton,
NIcon, NIcon,
......
...@@ -15,7 +15,15 @@ ...@@ -15,7 +15,15 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineComponent, toRefs, PropType, watch, onMounted, ref, getCurrentInstance } from 'vue' import {
defineComponent,
toRefs,
PropType,
watch,
onMounted,
ref,
getCurrentInstance
} from 'vue'
import { import {
NUpload, NUpload,
NIcon, NIcon,
......
...@@ -15,7 +15,15 @@ ...@@ -15,7 +15,15 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineComponent, Ref, toRefs, onMounted, toRef, watch, getCurrentInstance } from 'vue' import {
defineComponent,
Ref,
toRefs,
onMounted,
toRef,
watch,
getCurrentInstance
} from 'vue'
import { import {
NIcon, NIcon,
NSpace, NSpace,
...@@ -114,7 +122,7 @@ export default defineComponent({ ...@@ -114,7 +122,7 @@ export default defineComponent({
/> />
<NButton type='primary' size='small' onClick={this.handleSearch}> <NButton type='primary' size='small' onClick={this.handleSearch}>
<NIcon> <NIcon>
<SearchOutlined/> <SearchOutlined />
</NIcon> </NIcon>
</NButton> </NButton>
</NSpace> </NSpace>
......
...@@ -15,7 +15,15 @@ ...@@ -15,7 +15,15 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineComponent, Ref, toRefs, onMounted, toRef, watch, getCurrentInstance } from 'vue' import {
defineComponent,
Ref,
toRefs,
onMounted,
toRef,
watch,
getCurrentInstance
} from 'vue'
import { import {
NIcon, NIcon,
NSpace, NSpace,
......
...@@ -15,7 +15,13 @@ ...@@ -15,7 +15,13 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineComponent, getCurrentInstance, PropType, toRefs, watch } from 'vue' import {
defineComponent,
getCurrentInstance,
PropType,
toRefs,
watch
} from 'vue'
import Modal from '@/components/modal' import Modal from '@/components/modal'
import { NForm, NFormItem, NInput, NSelect } from 'naive-ui' import { NForm, NFormItem, NInput, NSelect } from 'naive-ui'
import { useModal } from './use-modal' import { useModal } from './use-modal'
......
...@@ -15,7 +15,13 @@ ...@@ -15,7 +15,13 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineComponent, getCurrentInstance, onMounted, toRefs, watch } from 'vue' import {
defineComponent,
getCurrentInstance,
onMounted,
toRefs,
watch
} from 'vue'
import { import {
NButton, NButton,
NDataTable, NDataTable,
......
...@@ -15,7 +15,14 @@ ...@@ -15,7 +15,14 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineComponent, toRefs, watch, onMounted, ref, getCurrentInstance } from 'vue' import {
defineComponent,
toRefs,
watch,
onMounted,
ref,
getCurrentInstance
} from 'vue'
import { NSelect, NInput } from 'naive-ui' import { NSelect, NInput } from 'naive-ui'
import { isFunction } from 'lodash' import { isFunction } from 'lodash'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
......
...@@ -15,7 +15,14 @@ ...@@ -15,7 +15,14 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineComponent, getCurrentInstance, onMounted, ref, toRefs, watch } from 'vue' import {
defineComponent,
getCurrentInstance,
onMounted,
ref,
toRefs,
watch
} from 'vue'
import { import {
NButton, NButton,
NInput, NInput,
...@@ -121,10 +128,7 @@ const AlarmInstanceManage = defineComponent({ ...@@ -121,10 +128,7 @@ const AlarmInstanceManage = defineComponent({
{t('security.alarm_instance.create_alarm_instance')} {t('security.alarm_instance.create_alarm_instance')}
</NButton> </NButton>
)} )}
<NSpace <NSpace justify='end' wrap={false}>
justify='end'
wrap={false}
>
<NInput <NInput
allowInput={this.trim} allowInput={this.trim}
v-model={[this.searchVal, 'value']} v-model={[this.searchVal, 'value']}
...@@ -145,7 +149,12 @@ const AlarmInstanceManage = defineComponent({ ...@@ -145,7 +149,12 @@ const AlarmInstanceManage = defineComponent({
</Card> </Card>
<Card title={t('menu.alarm_instance_manage')}> <Card title={t('menu.alarm_instance_manage')}>
<NSpace vertical> <NSpace vertical>
<NDataTable columns={columns} data={list} loading={loading} striped /> <NDataTable
columns={columns}
data={list}
loading={loading}
striped
/>
<NSpace justify='center'> <NSpace justify='center'>
<NPagination <NPagination
page={page} page={page}
......
...@@ -15,7 +15,13 @@ ...@@ -15,7 +15,13 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineComponent, getCurrentInstance, PropType, toRefs, watch } from 'vue' import {
defineComponent,
getCurrentInstance,
PropType,
toRefs,
watch
} from 'vue'
import Modal from '@/components/modal' import Modal from '@/components/modal'
import { NForm, NFormItem, NInput } from 'naive-ui' import { NForm, NFormItem, NInput } from 'naive-ui'
import { useModal } from './use-modal' import { useModal } from './use-modal'
......
...@@ -15,7 +15,13 @@ ...@@ -15,7 +15,13 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineComponent, getCurrentInstance, onMounted, toRefs, watch } from 'vue' import {
defineComponent,
getCurrentInstance,
onMounted,
toRefs,
watch
} from 'vue'
import { import {
NButton, NButton,
NDataTable, NDataTable,
......
...@@ -15,7 +15,13 @@ ...@@ -15,7 +15,13 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineComponent, getCurrentInstance, PropType, toRefs, watch } from 'vue' import {
defineComponent,
getCurrentInstance,
PropType,
toRefs,
watch
} from 'vue'
import Modal from '@/components/modal' import Modal from '@/components/modal'
import { NForm, NFormItem, NInput, NSelect } from 'naive-ui' import { NForm, NFormItem, NInput, NSelect } from 'naive-ui'
import { useModal } from './use-modal' import { useModal } from './use-modal'
......
...@@ -15,7 +15,13 @@ ...@@ -15,7 +15,13 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineComponent, getCurrentInstance, onMounted, toRefs, watch } from 'vue' import {
defineComponent,
getCurrentInstance,
onMounted,
toRefs,
watch
} from 'vue'
import { import {
NButton, NButton,
NDataTable, NDataTable,
......
...@@ -15,7 +15,13 @@ ...@@ -15,7 +15,13 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineComponent, getCurrentInstance, PropType, toRefs, watch } from 'vue' import {
defineComponent,
getCurrentInstance,
PropType,
toRefs,
watch
} from 'vue'
import Modal from '@/components/modal' import Modal from '@/components/modal'
import { import {
NForm, NForm,
...@@ -120,7 +126,11 @@ const K8sNamespaceModal = defineComponent({ ...@@ -120,7 +126,11 @@ const K8sNamespaceModal = defineComponent({
show={this.showModalRef} show={this.showModalRef}
onCancel={this.cancelModal} onCancel={this.cancelModal}
onConfirm={this.confirmModal} onConfirm={this.confirmModal}
confirmDisabled={!this.model.namespace || (this.model.clusterCode == null || this.model.clusterCode === '')} confirmDisabled={
!this.model.namespace ||
this.model.clusterCode == null ||
this.model.clusterCode === ''
}
confirmLoading={this.saving} confirmLoading={this.saving}
> >
{{ {{
......
...@@ -15,7 +15,13 @@ ...@@ -15,7 +15,13 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineComponent, getCurrentInstance, onMounted, toRefs, watch } from 'vue' import {
defineComponent,
getCurrentInstance,
onMounted,
toRefs,
watch
} from 'vue'
import { import {
NButton, NButton,
NDataTable, NDataTable,
......
...@@ -15,7 +15,13 @@ ...@@ -15,7 +15,13 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineComponent, getCurrentInstance, PropType, toRefs, watch } from 'vue' import {
defineComponent,
getCurrentInstance,
PropType,
toRefs,
watch
} from 'vue'
import Modal from '@/components/modal' import Modal from '@/components/modal'
import { NForm, NFormItem, NInput, NSelect } from 'naive-ui' import { NForm, NFormItem, NInput, NSelect } from 'naive-ui'
import { useModalData } from './use-modalData' import { useModalData } from './use-modalData'
......
...@@ -15,7 +15,13 @@ ...@@ -15,7 +15,13 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineComponent, toRefs, onMounted, watch, getCurrentInstance } from 'vue' import {
defineComponent,
toRefs,
onMounted,
watch,
getCurrentInstance
} from 'vue'
import { import {
NButton, NButton,
NInput, NInput,
......
...@@ -15,7 +15,13 @@ ...@@ -15,7 +15,13 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineComponent, getCurrentInstance, PropType, toRefs, watch } from 'vue' import {
defineComponent,
getCurrentInstance,
PropType,
toRefs,
watch
} from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { import {
NInput, NInput,
......
...@@ -80,7 +80,11 @@ const UsersManage = defineComponent({ ...@@ -80,7 +80,11 @@ const UsersManage = defineComponent({
</NButton> </NButton>
<NSpace> <NSpace>
<NInput <NInput
allowInput={this.trim} v-model:value={this.searchVal} size='small' clearable /> allowInput={this.trim}
v-model:value={this.searchVal}
size='small'
clearable
/>
<NButton type='primary' size='small' onClick={this.onUpdatedList}> <NButton type='primary' size='small' onClick={this.onUpdatedList}>
<NIcon> <NIcon>
<SearchOutlined /> <SearchOutlined />
......
...@@ -15,7 +15,13 @@ ...@@ -15,7 +15,13 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineComponent, getCurrentInstance, PropType, toRefs, watch } from 'vue' import {
defineComponent,
getCurrentInstance,
PropType,
toRefs,
watch
} from 'vue'
import Modal from '@/components/modal' import Modal from '@/components/modal'
import { NForm, NFormItem, NInput, NSelect } from 'naive-ui' import { NForm, NFormItem, NInput, NSelect } from 'naive-ui'
import { useModal } from './use-modal' import { useModal } from './use-modal'
......
...@@ -15,7 +15,13 @@ ...@@ -15,7 +15,13 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineComponent, getCurrentInstance, onMounted, toRefs, watch } from 'vue' import {
defineComponent,
getCurrentInstance,
onMounted,
toRefs,
watch
} from 'vue'
import { import {
NButton, NButton,
NDataTable, NDataTable,
......
...@@ -15,7 +15,13 @@ ...@@ -15,7 +15,13 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineComponent, getCurrentInstance, PropType, toRefs, watch } from 'vue' import {
defineComponent,
getCurrentInstance,
PropType,
toRefs,
watch
} from 'vue'
import Modal from '@/components/modal' import Modal from '@/components/modal'
import { NForm, NFormItem, NInput } from 'naive-ui' import { NForm, NFormItem, NInput } from 'naive-ui'
import { useModal } from './use-modal' import { useModal } from './use-modal'
......
...@@ -15,7 +15,13 @@ ...@@ -15,7 +15,13 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineComponent, getCurrentInstance, onMounted, toRefs, watch } from 'vue' import {
defineComponent,
getCurrentInstance,
onMounted,
toRefs,
watch
} from 'vue'
import { import {
NButton, NButton,
NDataTable, NDataTable,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册