diff --git a/spug_api/apps/deploy/helper.py b/spug_api/apps/deploy/helper.py index ff35543..5945ed1 100644 --- a/spug_api/apps/deploy/helper.py +++ b/spug_api/apps/deploy/helper.py @@ -1,9 +1,7 @@ # Copyright: (c) OpenSpug Organization. https://github.com/openspug/spug # Copyright: (c) # Released under the AGPL-3.0 License. -from django_redis import get_redis_connection -from django.conf import settings -from libs.utils import human_datetime +from libs.utils import human_datetime, render_str from libs.spug import Notification from apps.host.models import Host import subprocess @@ -208,13 +206,13 @@ class Helper: def add_callback(self, func): self.callback.append(func) - def parse_filter_rule(self, data: str, sep='\n'): + def parse_filter_rule(self, data: str, sep='\n', env=None): data, files = data.strip(), [] if data: for line in data.split(sep): line = line.strip() if line and not line.startswith('#'): - files.append(line) + files.append(render_str(line, env)) return files def _send(self, message): diff --git a/spug_api/apps/deploy/utils.py b/spug_api/apps/deploy/utils.py index e3afca6..7409fb8 100644 --- a/spug_api/apps/deploy/utils.py +++ b/spug_api/apps/deploy/utils.py @@ -4,7 +4,7 @@ from django_redis import get_redis_connection from django.conf import settings from django.db import close_old_connections -from libs.utils import AttrDict, human_time +from libs.utils import AttrDict, human_time, render_str from apps.host.models import Host from apps.config.utils import compose_configs from apps.repository.models import Repository @@ -74,8 +74,6 @@ def _ext1_deploy(req, helper, env): ) build_repository(rep, helper) req.repository = rep - extend = req.deploy.extend_obj - env.update(SPUG_DST_DIR=extend.dst_dir) extras = json.loads(req.extra) if extras[0] == 'repository': extras = extras[1:] @@ -127,22 +125,25 @@ def _ext2_deploy(req, helper, env): helper.send_step('local', step, f'{human_time()} {action["title"]}...\r\n') helper.local(f'cd /tmp && {action["data"]}', env) step += 1 - helper.send_step('local', 100, '') for action in host_actions: if action.get('type') == 'transfer': + action['src'] = render_str(action['src'].strip().rstrip('/'), env) + action['dst'] = render_str(action['dst'].strip().rstrip('/'), env) if action.get('src_mode') == '1': break - helper.send_info('local', f'{human_time()} 检测到来源为本地路径的数据传输动作,执行打包... \r\n') + helper.send_step('local', step, f'{human_time()} 检测到来源为本地路径的数据传输动作,执行打包... \r\n') 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"]}') + helper.send_error('local', f'Invalid path for transfer, src: {action["src"]} dst: {action["dst"]}') + if not os.path.exists(action['src']): + helper.send_error('local', f'No such file or directory: {action["src"]}') 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'], ',') + files = helper.parse_filter_rule(action['rule'], ',', env) if files: if action['mode'] == '1': contain = ' '.join(f'{sd_dst}/{x}' for x in files) @@ -159,6 +160,8 @@ def _ext2_deploy(req, helper, env): helper.send_info('local', f'{human_time()} \033[32m完成√\033[0m\r\n') helper.add_callback(partial(os.remove, os.path.join(sp_dir, tar_gz_file))) break + helper.send_step('local', 100, '') + if host_actions: if req.deploy.is_parallel: threads, latest_exception = [], None @@ -194,12 +197,15 @@ def _ext2_deploy(req, helper, env): def _deploy_ext1_host(req, helper, h_id, env): - extend = req.deploy.extend_obj helper.send_step(h_id, 1, f'\033[32m就绪√\033[0m\r\n{human_time()} 数据准备... ') host = Host.objects.filter(pk=h_id).first() if not host: helper.send_error(h_id, 'no such host') env.update({'SPUG_HOST_ID': h_id, 'SPUG_HOST_NAME': host.hostname}) + extend = req.deploy.extend_obj + extend.dst_dir = render_str(extend.dst_dir, env) + extend.dst_repo = render_str(extend.dst_repo, env) + env.update(SPUG_DST_DIR=extend.dst_dir) with host.get_ssh(default_env=env) as ssh: base_dst_dir = os.path.dirname(extend.dst_dir) code, _ = ssh.exec_command_raw( diff --git a/spug_api/apps/deploy/views.py b/spug_api/apps/deploy/views.py index 4c6ac4f..96ebb08 100644 --- a/spug_api/apps/deploy/views.py +++ b/spug_api/apps/deploy/views.py @@ -159,12 +159,14 @@ class RequestDetailView(View): outputs['local'] = {'id': 'local', 'step': 0, 'data': f'{human_time()} 建立连接... '} if req.deploy.extend == '2': outputs['local'] = {'id': 'local', 'step': 0, 'data': f'{human_time()} 建立连接... '} - if req.deploy.extend == '2': - s_actions = json.loads(req.deploy.extend_obj.server_actions) - h_actions = json.loads(req.deploy.extend_obj.host_actions) - if not h_actions: - outputs = {'local': outputs['local']} - return json_response({'s_actions': s_actions, 'h_actions': h_actions, 'outputs': outputs}) + s_actions = json.loads(req.deploy.extend_obj.server_actions) + h_actions = json.loads(req.deploy.extend_obj.host_actions) + for item in h_actions: + if item.get('type') == 'transfer' and item.get('src_mode') == '0': + s_actions.append({'title': '执行打包'}) + if not h_actions: + outputs = {'local': outputs['local']} + return json_response({'s_actions': s_actions, 'h_actions': h_actions, 'outputs': outputs}) return json_response({'outputs': outputs}) @auth('deploy.request.approve') diff --git a/spug_api/apps/repository/utils.py b/spug_api/apps/repository/utils.py index 3d7817e..ecdfa87 100644 --- a/spug_api/apps/repository/utils.py +++ b/spug_api/apps/repository/utils.py @@ -4,7 +4,7 @@ from django_redis import get_redis_connection from django.conf import settings from django.db import close_old_connections -from libs.utils import AttrDict, human_time +from libs.utils import AttrDict, human_time, render_str from apps.repository.models import Repository from apps.app.utils import fetch_repo from apps.config.utils import compose_configs @@ -68,13 +68,13 @@ def _build(rep: Repository, helper, env): git_dir = os.path.join(REPOS_DIR, str(rep.deploy_id)) build_dir = os.path.join(REPOS_DIR, rep.spug_version) tar_file = os.path.join(BUILD_DIR, f'{rep.spug_version}.tar.gz') - env.update(SPUG_DST_DIR=extend.dst_dir) if extras[0] == 'branch': tree_ish = extras[2] env.update(SPUG_GIT_BRANCH=extras[1], SPUG_GIT_COMMIT_ID=extras[2]) else: tree_ish = extras[1] env.update(SPUG_GIT_TAG=extras[1]) + env.update(SPUG_DST_DIR=render_str(extend.dst_dir, env)) fetch_repo(rep.deploy_id, extend.git_repo) helper.send_info('local', '\033[32m完成√\033[0m\r\n') @@ -93,7 +93,7 @@ def _build(rep: Repository, helper, env): helper.send_step('local', 4, f'\r\n{human_time()} 执行打包... ') filter_rule, exclude, contain = json.loads(extend.filter_rule), '', rep.spug_version - files = helper.parse_filter_rule(filter_rule['data']) + files = helper.parse_filter_rule(filter_rule['data'], env=env) if files: if filter_rule['type'] == 'exclude': excludes = [] diff --git a/spug_api/libs/utils.py b/spug_api/libs/utils.py index f1f2046..05aff4f 100644 --- a/spug_api/libs/utils.py +++ b/spug_api/libs/utils.py @@ -5,6 +5,7 @@ from django.http.response import HttpResponse from django.db.models import QuerySet from datetime import datetime, date as datetime_date from decimal import Decimal +from string import Template import string import random import json @@ -62,6 +63,11 @@ def human_diff_time(time1, time2): return '%d天%s' % (delta.days, text) if delta.days else text +# 字符串模版渲染 +def render_str(template, datasheet): + return Template(template).safe_substitute(datasheet) + + def json_response(data='', error=''): content = AttrDict(data=data, error=error) if error: diff --git a/spug_web/src/pages/deploy/request/index.module.less b/spug_web/src/pages/deploy/request/index.module.less index e3d13df..d493a24 100644 --- a/spug_web/src/pages/deploy/request/index.module.less +++ b/spug_web/src/pages/deploy/request/index.module.less @@ -69,6 +69,7 @@ } .header { + flex: 1; display: flex; justify-content: space-between; align-items: center; @@ -90,12 +91,6 @@ font-size: 22px; color: #1890ff; } - - .icon { - font-size: 22px; - font-weight: 300; - color: #1890ff; - } } }