mirror of https://github.com/jumpserver/jumpserver
perf: 解决冲突
commit
cde59f7ae8
|
@ -45,6 +45,7 @@ class AccountViewSet(OrgBulkModelViewSet):
|
|||
accounts = asset.accounts.all()
|
||||
else:
|
||||
accounts = []
|
||||
accounts = self.filter_queryset(accounts)
|
||||
serializer = serializers.AccountSerializer(accounts, many=True)
|
||||
return Response(data=serializer.data)
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ from rest_framework.response import Response
|
|||
|
||||
from accounts import serializers
|
||||
from accounts.tasks import verify_accounts_connectivity_task, push_accounts_to_assets_task
|
||||
from assets.exceptions import NotSupportedTemporarilyError
|
||||
|
||||
__all__ = [
|
||||
'AccountsTaskCreateAPI',
|
||||
|
@ -28,6 +29,11 @@ class AccountsTaskCreateAPI(CreateAPIView):
|
|||
if data['action'] == 'push':
|
||||
task = push_accounts_to_assets_task.delay(account_ids)
|
||||
else:
|
||||
account = accounts[0]
|
||||
asset = account.asset
|
||||
if not asset.auto_info['ansible_enabled'] or \
|
||||
not asset.auto_info['ping_enabled']:
|
||||
raise NotSupportedTemporarilyError()
|
||||
task = verify_accounts_connectivity_task.delay(account_ids)
|
||||
|
||||
data = getattr(serializer, '_data', {})
|
||||
|
|
|
@ -86,6 +86,10 @@ class ChangeSecretManager(AccountBasePlaybookManager):
|
|||
accounts = accounts.filter(username__in=self.snapshot_account_usernames)
|
||||
|
||||
accounts = accounts.filter(secret_type=self.secret_type)
|
||||
if not accounts:
|
||||
print('没有发现待改密账号: %s 用户名: %s 类型: %s' % (asset.name, account.username, self.secret_type))
|
||||
return []
|
||||
|
||||
method_attr = getattr(automation, self.method_type() + '_method')
|
||||
method_hosts = self.method_hosts_mapper[method_attr]
|
||||
method_hosts = [h for h in method_hosts if h != host['name']]
|
||||
|
@ -137,8 +141,10 @@ class ChangeSecretManager(AccountBasePlaybookManager):
|
|||
recorder.status = 'success'
|
||||
recorder.date_finished = timezone.now()
|
||||
recorder.save()
|
||||
print('recorder.new_secret', recorder.new_secret)
|
||||
account = recorder.account
|
||||
if not account:
|
||||
print("Account not found, deleted ?", recorder)
|
||||
return
|
||||
account.secret = recorder.new_secret
|
||||
account.save(update_fields=['secret'])
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ class PushAccountManager(ChangeSecretManager, AccountBasePlaybookManager):
|
|||
|
||||
def get_accounts(self, privilege_account, accounts: QuerySet):
|
||||
if not privilege_account:
|
||||
logger.debug(f'not privilege account')
|
||||
print(f'not privilege account')
|
||||
return []
|
||||
snapshot_account_usernames = self.execution.snapshot['accounts']
|
||||
if '*' in snapshot_account_usernames:
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
tasks:
|
||||
- name: Verify account
|
||||
mongodb_ping:
|
||||
login_user: "{{ jms_account.username }}"
|
||||
login_password: "{{ jms_account.secret }}"
|
||||
login_user: "{{ account.username }}"
|
||||
login_password: "{{ account.secret }}"
|
||||
login_host: "{{ jms_asset.address }}"
|
||||
login_port: "{{ jms_asset.port }}"
|
||||
login_database: "{{ jms_asset.spec_info.db_name }}"
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
tasks:
|
||||
- name: Verify account
|
||||
oracle_ping:
|
||||
login_user: "{{ jms_account.username }}"
|
||||
login_password: "{{ jms_account.secret }}"
|
||||
login_user: "{{ account.username }}"
|
||||
login_password: "{{ account.secret }}"
|
||||
login_host: "{{ jms_asset.address }}"
|
||||
login_port: "{{ jms_asset.port }}"
|
||||
login_database: "{{ jms_asset.spec_info.db_name }}"
|
||||
mode: "{{ jms_account.mode }}"
|
||||
mode: "{{ account.mode }}"
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
tasks:
|
||||
- name: Verify account
|
||||
community.general.mssql_script:
|
||||
login_user: "{{ jms_account.username }}"
|
||||
login_password: "{{ jms_account.secret }}"
|
||||
login_user: "{{ account.username }}"
|
||||
login_password: "{{ account.secret }}"
|
||||
login_host: "{{ jms_asset.address }}"
|
||||
login_port: "{{ jms_asset.port }}"
|
||||
name: '{{ jms_asset.spec_info.db_name }}'
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
# Generated by Django 3.2.14 on 2023-02-21 05:13
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('accounts', '0007_alter_account_options'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='account',
|
||||
options={'permissions': [('view_accountsecret', 'Can view asset account secret'), ('view_historyaccount', 'Can view asset history account'), ('view_historyaccountsecret', 'Can view asset history account secret'), ('verify_account', 'Can verify account'), ('push_account', 'Can push account')], 'verbose_name': 'Account'},
|
||||
),
|
||||
]
|
|
@ -68,6 +68,9 @@ class Account(AbsConnectivity, BaseAccount):
|
|||
('push_account', _('Can push account')),
|
||||
]
|
||||
|
||||
def __str__(self):
|
||||
return '{}'.format(self.username)
|
||||
|
||||
@lazyproperty
|
||||
def platform(self):
|
||||
return self.asset.platform
|
||||
|
@ -78,9 +81,6 @@ class Account(AbsConnectivity, BaseAccount):
|
|||
return self.username
|
||||
return self.name
|
||||
|
||||
def __str__(self):
|
||||
return '{}'.format(self.username)
|
||||
|
||||
@lazyproperty
|
||||
def has_secret(self):
|
||||
return bool(self.secret)
|
||||
|
@ -99,14 +99,6 @@ class Account(AbsConnectivity, BaseAccount):
|
|||
""" 排除自己和以自己为 su-from 的账号 """
|
||||
return self.asset.accounts.exclude(id=self.id).exclude(su_from=self)
|
||||
|
||||
def secret_changed(self):
|
||||
history = self.history.first()
|
||||
if not history:
|
||||
return True
|
||||
if history.secret != self.secret or history.secret_type != self.secret_type:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class AccountTemplate(BaseAccount):
|
||||
class Meta:
|
||||
|
|
|
@ -109,7 +109,7 @@ class BaseAccount(JMSOrgBaseModel):
|
|||
|
||||
@property
|
||||
def private_key_path(self):
|
||||
if not self.secret_type != SecretType.SSH_KEY \
|
||||
if self.secret_type != SecretType.SSH_KEY \
|
||||
or not self.secret \
|
||||
or not self.private_key:
|
||||
return None
|
||||
|
|
|
@ -43,7 +43,7 @@ class AccountSerializerCreateValidateMixin:
|
|||
def push_account(instance, push_now):
|
||||
if not push_now:
|
||||
return
|
||||
push_accounts_to_assets_task.delay([instance.id], [instance.asset_id])
|
||||
push_accounts_to_assets_task.delay([instance.id])
|
||||
|
||||
def create(self, validated_data):
|
||||
push_now = validated_data.pop('push_now', None)
|
||||
|
@ -102,7 +102,7 @@ class AccountSerializer(AccountSerializerCreateMixin, BaseAccountSerializer):
|
|||
class Meta(BaseAccountSerializer.Meta):
|
||||
model = Account
|
||||
fields = BaseAccountSerializer.Meta.fields \
|
||||
+ ['su_from', 'version', 'asset'] \
|
||||
+ ['su_from', 'asset'] \
|
||||
+ ['template', 'push_now', 'source']
|
||||
extra_kwargs = {
|
||||
**BaseAccountSerializer.Meta.extra_kwargs,
|
||||
|
|
|
@ -38,6 +38,8 @@ class BaseAutomationSerializer(PeriodTaskSerializerMixin, BulkOrgResourceModelSe
|
|||
}
|
||||
|
||||
def validate_name(self, name):
|
||||
if self.instance:
|
||||
return name
|
||||
if BaseAutomation.objects.filter(name=name, type=self.model_type).exists():
|
||||
raise serializers.ValidationError(_('Name already exists'))
|
||||
return name
|
||||
|
|
|
@ -1,17 +1,3 @@
|
|||
from django.db.models.signals import pre_save
|
||||
from django.dispatch import receiver
|
||||
|
||||
from common.utils import get_logger
|
||||
from .models import Account
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
@receiver(pre_save, sender=Account)
|
||||
def on_account_pre_create(sender, instance, update_fields=(), **kwargs):
|
||||
# 这是创建时
|
||||
if instance.version == 0 or instance.secret_changed():
|
||||
instance.version += 1
|
||||
|
||||
# 即使在 root 组织也不怕
|
||||
instance.org_id = instance.asset.org_id
|
||||
|
|
|
@ -8,12 +8,10 @@ from rest_framework.response import Response
|
|||
|
||||
from accounts.tasks import push_accounts_to_assets_task, verify_accounts_connectivity_task
|
||||
from assets import serializers
|
||||
from assets.exceptions import NotSupportedTemporarilyError
|
||||
from assets.filters import IpInFilterBackend, LabelFilterBackend, NodeFilterBackend
|
||||
from assets.models import Asset, Gateway
|
||||
from assets.tasks import (
|
||||
test_assets_connectivity_manual,
|
||||
update_assets_hardware_info_manual
|
||||
)
|
||||
from assets.tasks import test_assets_connectivity_manual, update_assets_hardware_info_manual
|
||||
from common.api import SuggestionMixin
|
||||
from common.drf.filters import BaseFilterSet
|
||||
from common.utils import get_logger, is_uuid
|
||||
|
@ -154,6 +152,10 @@ class AssetsTaskMixin:
|
|||
if data["action"] == "refresh":
|
||||
task = update_assets_hardware_info_manual(assets)
|
||||
else:
|
||||
asset = assets[0]
|
||||
if not asset.auto_info['ansible_enabled'] or \
|
||||
not asset.auto_info['ping_enabled']:
|
||||
raise NotSupportedTemporarilyError()
|
||||
task = test_assets_connectivity_manual(assets)
|
||||
return task
|
||||
|
||||
|
@ -205,9 +207,9 @@ class AssetTaskCreateApi(AssetsTaskMixin, generics.CreateAPIView):
|
|||
asset_ids = [asset.id]
|
||||
account_ids = accounts.values_list("id", flat=True)
|
||||
if action == "push_account":
|
||||
task = push_accounts_to_assets_task.delay(account_ids, asset_ids)
|
||||
task = push_accounts_to_assets_task.delay(account_ids)
|
||||
elif action == "test_account":
|
||||
task = verify_accounts_connectivity_task.delay(account_ids, asset_ids)
|
||||
task = verify_accounts_connectivity_task.delay(account_ids)
|
||||
else:
|
||||
task = None
|
||||
return task
|
||||
|
|
|
@ -67,7 +67,7 @@ class BasePlaybookManager:
|
|||
if not os.path.exists(path):
|
||||
os.makedirs(path, exist_ok=True, mode=0o755)
|
||||
if settings.DEBUG_DEV:
|
||||
logger.debug('Ansible runtime dir: {}'.format(path))
|
||||
print(f'Ansible runtime dir: {path}')
|
||||
return path
|
||||
|
||||
@staticmethod
|
||||
|
@ -156,10 +156,9 @@ class BasePlaybookManager:
|
|||
return sub_playbook_path
|
||||
|
||||
def get_runners(self):
|
||||
# TODO 临时打印一下 找一下打印不出日志的原因
|
||||
print('ansible runner: 任务开始执行')
|
||||
assets_group_by_platform = self.get_assets_group_by_platform()
|
||||
print('ansible runner: 获取资产分组', assets_group_by_platform)
|
||||
if settings.DEBUG_DEV:
|
||||
print("assets_group_by_platform: {}".format(assets_group_by_platform))
|
||||
runners = []
|
||||
for platform, assets in assets_group_by_platform.items():
|
||||
assets_bulked = [assets[i:i + self.bulk_size] for i in range(0, len(assets), self.bulk_size)]
|
||||
|
@ -213,6 +212,7 @@ class BasePlaybookManager:
|
|||
def file_to_json(path):
|
||||
with open(path, 'r') as f:
|
||||
d = json.load(f)
|
||||
|
||||
return d
|
||||
|
||||
@staticmethod
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import status
|
||||
|
||||
from common.exceptions import JMSException
|
||||
|
||||
|
||||
class NodeIsBeingUpdatedByOthers(JMSException):
|
||||
status_code = status.HTTP_409_CONFLICT
|
||||
|
||||
|
||||
class NotSupportedTemporarilyError(JMSException):
|
||||
default_detail = _("This function is not supported temporarily")
|
||||
|
|
|
@ -12,6 +12,6 @@ class Migration(migrations.Migration):
|
|||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='asset',
|
||||
options={'ordering': ['name'], 'permissions': [('refresh_assethardwareinfo', 'Can refresh asset hardware info'), ('test_assetconnectivity', 'Can test asset connectivity'), ('push_assetaccount', 'Can push account to asset'), ('test_account', 'Can verify account'), ('match_asset', 'Can match asset'), ('change_assettonode', 'Can change asset nodes')], 'verbose_name': 'Asset'},
|
||||
options={'ordering': ['name'], 'permissions': [('refresh_assethardwareinfo', 'Can refresh asset hardware info'), ('test_assetconnectivity', 'Can test asset connectivity'), ('match_asset', 'Can match asset'), ('change_assetnodes', 'Can change asset nodes')], 'verbose_name': 'Asset'},
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
# Generated by Django 3.2.14 on 2023-02-21 05:11
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('assets', '0109_alter_asset_options'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='asset',
|
||||
options={'ordering': ['name'], 'permissions': [('refresh_assethardwareinfo', 'Can refresh asset hardware info'), ('test_assetconnectivity', 'Can test asset connectivity'), ('match_asset', 'Can match asset'), ('change_assetnodes', 'Can change asset nodes')], 'verbose_name': 'Asset'},
|
||||
),
|
||||
]
|
|
@ -277,6 +277,8 @@ class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSeriali
|
|||
|
||||
@atomic
|
||||
def update(self, instance, validated_data):
|
||||
if not validated_data.get('accounts'):
|
||||
validated_data.pop('accounts', None)
|
||||
nodes_display = validated_data.pop('nodes_display', '')
|
||||
instance = super().update(instance, validated_data)
|
||||
self.perform_nodes_display_create(instance, nodes_display)
|
||||
|
|
|
@ -530,7 +530,7 @@ class Config(dict):
|
|||
'PERIOD_TASK_ENABLED': True,
|
||||
|
||||
# 导航栏 帮助
|
||||
'HELP_DOCUMENT_URL': 'http://docs.jumpserver.org',
|
||||
'HELP_DOCUMENT_URL': 'https://docs.jumpserver.org/zh/v3/',
|
||||
'HELP_SUPPORT_URL': 'http://www.jumpserver.org/support/',
|
||||
|
||||
'FORGOT_PASSWORD_URL': '',
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:331188bb5169bb463da018a635589e12a2136d476db264ac7e5d6e5d63ca474a
|
||||
size 135916
|
||||
oid sha256:af57d16430705feb02ebbb99fc3a2f5fc3bab69209f558aa4d69b1e8055a6f5f
|
||||
size 136036
|
||||
|
|
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-02-21 18:29+0800\n"
|
||||
"POT-Creation-Date: 2023-02-21 22:44+0800\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
@ -908,7 +908,7 @@ msgstr "アプリケーション"
|
|||
msgid "Can match application"
|
||||
msgstr "アプリケーションを一致させることができます"
|
||||
|
||||
#: assets/api/asset/asset.py:144
|
||||
#: assets/api/asset/asset.py:142
|
||||
msgid "Cannot create asset directly, you should create a host or other"
|
||||
msgstr ""
|
||||
"資産を直接作成することはできません。ホストまたはその他を作成する必要がありま"
|
||||
|
@ -1051,6 +1051,10 @@ msgstr "基本"
|
|||
msgid "Script"
|
||||
msgstr "脚本"
|
||||
|
||||
#: assets/exceptions.py:12
|
||||
msgid "This function is not supported temporarily"
|
||||
msgstr "この機能は一時的にサポートされていません"
|
||||
|
||||
#: assets/models/_user.py:25
|
||||
msgid "SSH private key"
|
||||
msgstr "SSH秘密鍵"
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2cdc2b875c98f41bd698833a989195d8cc4245f39f52b7eab41ad4d95075cb17
|
||||
size 111666
|
||||
oid sha256:3b6ee4a378810f2515be5020e3fa0b1297e1c207260ca60bb14dc5407ca19c43
|
||||
size 111750
|
||||
|
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: JumpServer 0.3.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-02-21 18:29+0800\n"
|
||||
"POT-Creation-Date: 2023-02-21 22:44+0800\n"
|
||||
"PO-Revision-Date: 2021-05-20 10:54+0800\n"
|
||||
"Last-Translator: ibuler <ibuler@qq.com>\n"
|
||||
"Language-Team: JumpServer team<ibuler@qq.com>\n"
|
||||
|
@ -902,7 +902,7 @@ msgstr "应用程序"
|
|||
msgid "Can match application"
|
||||
msgstr "匹配应用"
|
||||
|
||||
#: assets/api/asset/asset.py:144
|
||||
#: assets/api/asset/asset.py:142
|
||||
msgid "Cannot create asset directly, you should create a host or other"
|
||||
msgstr "不能直接创建资产, 你应该创建主机或其他资产"
|
||||
|
||||
|
@ -1043,6 +1043,10 @@ msgstr "基本"
|
|||
msgid "Script"
|
||||
msgstr "脚本"
|
||||
|
||||
#: assets/exceptions.py:12
|
||||
msgid "This function is not supported temporarily"
|
||||
msgstr "暂时不支持此功能"
|
||||
|
||||
#: assets/models/_user.py:25
|
||||
msgid "SSH private key"
|
||||
msgstr "SSH密钥"
|
||||
|
|
|
@ -6,6 +6,7 @@ from django.conf import settings
|
|||
from django.shortcuts import get_object_or_404
|
||||
from rest_framework import status
|
||||
|
||||
from common.exceptions import JMSException
|
||||
from orgs.mixins.api import OrgBulkModelViewSet
|
||||
from ..exception import PlaybookNoValidEntry
|
||||
from ..models import Playbook
|
||||
|
@ -39,7 +40,11 @@ class PlaybookViewSet(OrgBulkModelViewSet):
|
|||
if 'multipart/form-data' in self.request.headers['Content-Type']:
|
||||
src_path = os.path.join(settings.MEDIA_ROOT, instance.path.name)
|
||||
dest_path = os.path.join(settings.DATA_DIR, "ops", "playbook", instance.id.__str__())
|
||||
unzip_playbook(src_path, dest_path)
|
||||
try:
|
||||
unzip_playbook(src_path, dest_path)
|
||||
except RuntimeError as e:
|
||||
raise JMSException(code='invalid_playbook_file', detail={"msg": "Unzip failed"})
|
||||
|
||||
if 'main.yml' not in os.listdir(dest_path):
|
||||
raise PlaybookNoValidEntry
|
||||
|
||||
|
|
|
@ -111,7 +111,8 @@ class Applet(JMSBaseModel):
|
|||
return instance
|
||||
|
||||
def select_host_account(self):
|
||||
hosts = list(self.hosts.all())
|
||||
# 选择激活的发布机
|
||||
hosts = list(self.hosts.filter(is_active=True).all())
|
||||
if not hosts:
|
||||
return None
|
||||
|
||||
|
|
Loading…
Reference in New Issue