mirror of https://github.com/openspug/spug
A 自定义发布新增用于文件分发的数据传输动作
parent
467f9e99e1
commit
d5a5ee2340
|
@ -125,6 +125,28 @@ def _ext2_deploy(req, helper, env):
|
||||||
helper.local(f'cd /tmp && {action["data"]}', env)
|
helper.local(f'cd /tmp && {action["data"]}', env)
|
||||||
step += 1
|
step += 1
|
||||||
helper.send_step('local', 100, '完成\r\n' if step == 2 else '\r\n')
|
helper.send_step('local', 100, '完成\r\n' if step == 2 else '\r\n')
|
||||||
|
|
||||||
|
for action in host_actions:
|
||||||
|
if action.get('type') == 'transfer':
|
||||||
|
helper.send_info('local', f'{human_time()} 检测到数据传输动作,执行打包... ')
|
||||||
|
action['src'] = action['src'].rstrip('/ ')
|
||||||
|
action['dst'] = action['dst'].rstrip('/ ')
|
||||||
|
if not action['src'] or not action['dst']:
|
||||||
|
helper.send_error('local', f'invalid path for transfer, src: {action["src"]} dst: {action["dst"]}')
|
||||||
|
is_dir, exclude = os.path.isdir(action['src']), ''
|
||||||
|
sp_dir, sd_dst = os.path.split(action['src'])
|
||||||
|
contain = sd_dst
|
||||||
|
if action['mode'] != '0' and is_dir:
|
||||||
|
files = helper.parse_filter_rule(action['rule'], ',')
|
||||||
|
if files:
|
||||||
|
if action['mode'] == '1':
|
||||||
|
contain = ' '.join(f'{sd_dst}/{x}' for x in files)
|
||||||
|
else:
|
||||||
|
exclude = ' '.join(f'--exclude={sd_dst}/{x}' for x in files)
|
||||||
|
tar_gz_file = f'{env.SPUG_VERSION}.tar.gz'
|
||||||
|
helper.local(f'cd {sp_dir} && rm -f {req.deploy_id}_*.tar.gz && tar zcf {tar_gz_file} {exclude} {contain}')
|
||||||
|
helper.send_info('local', '完成\r\n')
|
||||||
|
break
|
||||||
if host_actions:
|
if host_actions:
|
||||||
threads, latest_exception = [], None
|
threads, latest_exception = [], None
|
||||||
with futures.ThreadPoolExecutor(max_workers=min(10, os.cpu_count() + 5)) as executor:
|
with futures.ThreadPoolExecutor(max_workers=min(10, os.cpu_count() + 5)) as executor:
|
||||||
|
@ -202,7 +224,19 @@ def _deploy_ext2_host(helper, h_id, actions, env):
|
||||||
helper.send_step(h_id, 2, '完成\r\n')
|
helper.send_step(h_id, 2, '完成\r\n')
|
||||||
for index, action in enumerate(actions):
|
for index, action in enumerate(actions):
|
||||||
helper.send_step(h_id, 2 + index, f'{human_time()} {action["title"]}...\r\n')
|
helper.send_step(h_id, 2 + index, f'{human_time()} {action["title"]}...\r\n')
|
||||||
helper.remote(host.id, ssh, f'cd /tmp && {action["data"]}', env)
|
if action.get('type') == 'transfer':
|
||||||
|
sp_dir, sd_dst = os.path.split(action['src'])
|
||||||
|
tar_gz_file = f'{env.SPUG_VERSION}.tar.gz'
|
||||||
|
try:
|
||||||
|
ssh.put_file(os.path.join(sp_dir, tar_gz_file), f'/tmp/{tar_gz_file}')
|
||||||
|
except Exception as e:
|
||||||
|
helper.send_error(host.id, f'exception: {e}')
|
||||||
|
|
||||||
|
command = f'cd /tmp && tar xf {tar_gz_file} && rm -f {tar_gz_file} '
|
||||||
|
command += f'&& rm -rf {action["dst"]} && mv /tmp/{sd_dst} {action["dst"]} && echo "transfer completed"'
|
||||||
|
else:
|
||||||
|
command = f'cd /tmp && {action["data"]}'
|
||||||
|
helper.remote(host.id, ssh, command, env)
|
||||||
|
|
||||||
helper.send_step(h_id, 100, f'\r\n{human_time()} ** 发布成功 **')
|
helper.send_step(h_id, 100, f'\r\n{human_time()} ** 发布成功 **')
|
||||||
|
|
||||||
|
|
|
@ -5,13 +5,14 @@
|
||||||
*/
|
*/
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
import { Form, Input, Button, message, Divider, Alert, Icon } from 'antd';
|
import { Form, Input, Button, message, Divider, Alert, Icon, Select } from 'antd';
|
||||||
import Editor from 'react-ace';
|
import Editor from 'react-ace';
|
||||||
import 'ace-builds/src-noconflict/mode-sh';
|
import 'ace-builds/src-noconflict/mode-sh';
|
||||||
import 'ace-builds/src-noconflict/theme-tomorrow';
|
import 'ace-builds/src-noconflict/theme-tomorrow';
|
||||||
import styles from './index.module.css';
|
import styles from './index.module.css';
|
||||||
import { http, cleanCommand } from 'libs';
|
import { http, cleanCommand } from 'libs';
|
||||||
import store from './store';
|
import store from './store';
|
||||||
|
import lds from 'lodash';
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
class Ext2Setup3 extends React.Component {
|
class Ext2Setup3 extends React.Component {
|
||||||
|
@ -27,7 +28,7 @@ class Ext2Setup3 extends React.Component {
|
||||||
const info = store.deploy;
|
const info = store.deploy;
|
||||||
info['app_id'] = store.app_id;
|
info['app_id'] = store.app_id;
|
||||||
info['extend'] = '2';
|
info['extend'] = '2';
|
||||||
info['host_actions'] = info['host_actions'].filter(x => x.title && x.data);
|
info['host_actions'] = info['host_actions'].filter(x => (x.title && x.data) || (x.title && x.src && x.dst));
|
||||||
info['server_actions'] = info['server_actions'].filter(x => x.title && x.data);
|
info['server_actions'] = info['server_actions'].filter(x => x.title && x.data);
|
||||||
http.post('/api/app/deploy/', info)
|
http.post('/api/app/deploy/', info)
|
||||||
.then(res => {
|
.then(res => {
|
||||||
|
@ -87,17 +88,48 @@ class Ext2Setup3 extends React.Component {
|
||||||
<Form.Item required label={`目标主机动作${index + 1}`}>
|
<Form.Item required label={`目标主机动作${index + 1}`}>
|
||||||
<Input value={item['title']} onChange={e => item['title'] = e.target.value} placeholder="请输入"/>
|
<Input value={item['title']} onChange={e => item['title'] = e.target.value} placeholder="请输入"/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
{item['type'] === 'transfer' ? ([
|
||||||
<Form.Item required label="执行内容">
|
<Form.Item key={0} label="过滤规则">
|
||||||
<Editor
|
<Input
|
||||||
mode="sh"
|
spellCheck={false}
|
||||||
theme="tomorrow"
|
placeholder="请输入逗号分割的过滤规则"
|
||||||
width="100%"
|
value={item['rule']}
|
||||||
height="100px"
|
onChange={e => item['rule'] = e.target.value.replace(',', ',')}
|
||||||
value={item['data']}
|
disabled={item['mode'] === '0'}
|
||||||
onChange={v => item['data'] = cleanCommand(v)}
|
addonBefore={(
|
||||||
placeholder="请输入要执行的动作"/>
|
<Select style={{width: 100}} value={item['mode']} onChange={v => item['mode'] = v}>
|
||||||
</Form.Item>
|
<Select.Option value="0">关闭</Select.Option>
|
||||||
|
<Select.Option value="1">包含</Select.Option>
|
||||||
|
<Select.Option value="2">排除</Select.Option>
|
||||||
|
</Select>
|
||||||
|
)}/>
|
||||||
|
</Form.Item>,
|
||||||
|
<Form.Item key={1} required label="传输路径" extra={<a
|
||||||
|
target="_blank" rel="noopener noreferrer"
|
||||||
|
href="https://spug.dev/docs/deploy-config#%E6%95%B0%E6%8D%AE%E4%BC%A0%E8%BE%93">使用前请务必阅读官方文档。</a>}>
|
||||||
|
<Input
|
||||||
|
spellCheck={false}
|
||||||
|
value={item['src']}
|
||||||
|
placeholder="请输入本地路径(部署spug的容器或主机)"
|
||||||
|
onChange={e => item['src'] = e.target.value}/>
|
||||||
|
<Input
|
||||||
|
spellCheck={false}
|
||||||
|
value={item['dst']}
|
||||||
|
placeholder="请输入目标主机路径"
|
||||||
|
onChange={e => item['dst'] = e.target.value}/>
|
||||||
|
</Form.Item>
|
||||||
|
]) : (
|
||||||
|
<Form.Item required label="执行内容">
|
||||||
|
<Editor
|
||||||
|
mode="sh"
|
||||||
|
theme="tomorrow"
|
||||||
|
width="100%"
|
||||||
|
height="100px"
|
||||||
|
value={item['data']}
|
||||||
|
onChange={v => item['data'] = cleanCommand(v)}
|
||||||
|
placeholder="请输入要执行的动作"/>
|
||||||
|
</Form.Item>
|
||||||
|
)}
|
||||||
<div className={styles.delAction} onClick={() => host_actions.splice(index, 1)}>
|
<div className={styles.delAction} onClick={() => host_actions.splice(index, 1)}>
|
||||||
<Icon type="minus-circle"/>移除
|
<Icon type="minus-circle"/>移除
|
||||||
</div>
|
</div>
|
||||||
|
@ -107,6 +139,13 @@ class Ext2Setup3 extends React.Component {
|
||||||
<Button type="dashed" block onClick={() => host_actions.push({})}>
|
<Button type="dashed" block onClick={() => host_actions.push({})}>
|
||||||
<Icon type="plus"/>添加目标主机执行动作(在部署目标主机执行)
|
<Icon type="plus"/>添加目标主机执行动作(在部署目标主机执行)
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
block
|
||||||
|
type="dashed"
|
||||||
|
disabled={lds.findIndex(host_actions, x => x.type === 'transfer') !== -1}
|
||||||
|
onClick={() => host_actions.push({type: 'transfer', title: '数据传输', mode: '0'})}>
|
||||||
|
<Icon type="plus"/>添加数据传输动作(仅能添加一个)
|
||||||
|
</Button>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item wrapperCol={{span: 14, offset: 6}}>
|
<Form.Item wrapperCol={{span: 14, offset: 6}}>
|
||||||
<Button
|
<Button
|
||||||
|
|
Loading…
Reference in New Issue