mirror of https://github.com/jumpserver/jumpserver
feat: 同步删除远程机器账号
parent
8f82ca9856
commit
eca50874f0
|
@ -1,9 +1,12 @@
|
|||
from rest_framework.generics import CreateAPIView
|
||||
from rest_framework.response import Response
|
||||
|
||||
from accounts import serializers
|
||||
from accounts.tasks import verify_accounts_connectivity_task, push_accounts_to_assets_task
|
||||
from accounts.permissions import AccountTaskActionPermission
|
||||
from accounts.tasks import (
|
||||
remove_accounts_task, verify_accounts_connectivity_task, push_accounts_to_assets_task
|
||||
)
|
||||
from assets.exceptions import NotSupportedTemporarilyError
|
||||
from authentication.permissions import UserConfirmation, ConfirmType
|
||||
|
||||
__all__ = [
|
||||
'AccountsTaskCreateAPI',
|
||||
|
@ -12,16 +15,16 @@ __all__ = [
|
|||
|
||||
class AccountsTaskCreateAPI(CreateAPIView):
|
||||
serializer_class = serializers.AccountTaskSerializer
|
||||
permission_classes = (AccountTaskActionPermission,)
|
||||
|
||||
def check_permissions(self, request):
|
||||
act = request.data.get('action')
|
||||
if act == 'push':
|
||||
code = 'accounts.push_account'
|
||||
else:
|
||||
code = 'accounts.verify_account'
|
||||
has = request.user.has_perm(code)
|
||||
if not has:
|
||||
self.permission_denied(request)
|
||||
def get_permissions(self):
|
||||
act = self.request.data.get('action')
|
||||
if act == 'remove':
|
||||
self.permission_classes = [
|
||||
AccountTaskActionPermission,
|
||||
UserConfirmation.require(ConfirmType.PASSWORD)
|
||||
]
|
||||
return super().get_permissions()
|
||||
|
||||
def perform_create(self, serializer):
|
||||
data = serializer.validated_data
|
||||
|
@ -31,6 +34,10 @@ class AccountsTaskCreateAPI(CreateAPIView):
|
|||
|
||||
if data['action'] == 'push':
|
||||
task = push_accounts_to_assets_task.delay(account_ids, params)
|
||||
elif data['action'] == 'remove':
|
||||
gather_accounts = data.get('gather_accounts', [])
|
||||
gather_account_ids = [str(a.id) for a in gather_accounts]
|
||||
task = remove_accounts_task.delay(gather_account_ids)
|
||||
else:
|
||||
account = accounts[0]
|
||||
asset = account.asset
|
||||
|
@ -43,9 +50,3 @@ class AccountsTaskCreateAPI(CreateAPIView):
|
|||
data["task"] = task.id
|
||||
setattr(serializer, '_data', data)
|
||||
return task
|
||||
|
||||
def get_exception_handler(self):
|
||||
def handler(e, context):
|
||||
return Response({"error": str(e)}, status=401)
|
||||
|
||||
return handler
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
from .push_account.manager import PushAccountManager
|
||||
from .change_secret.manager import ChangeSecretManager
|
||||
from .verify_account.manager import VerifyAccountManager
|
||||
from .backup_account.manager import AccountBackupManager
|
||||
from .change_secret.manager import ChangeSecretManager
|
||||
from .gather_accounts.manager import GatherAccountsManager
|
||||
from .push_account.manager import PushAccountManager
|
||||
from .remove_account.manager import RemoveAccountManager
|
||||
from .verify_account.manager import VerifyAccountManager
|
||||
from .verify_gateway_account.manager import VerifyGatewayAccountManager
|
||||
from ..const import AutomationTypes
|
||||
|
||||
|
@ -12,6 +13,7 @@ class ExecutionManager:
|
|||
AutomationTypes.push_account: PushAccountManager,
|
||||
AutomationTypes.change_secret: ChangeSecretManager,
|
||||
AutomationTypes.verify_account: VerifyAccountManager,
|
||||
AutomationTypes.remove_account: RemoveAccountManager,
|
||||
AutomationTypes.gather_accounts: GatherAccountsManager,
|
||||
AutomationTypes.verify_gateway_account: VerifyGatewayAccountManager,
|
||||
# TODO 后期迁移到自动化策略中
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
- hosts: mongodb
|
||||
gather_facts: no
|
||||
vars:
|
||||
ansible_python_interpreter: /opt/py3/bin/python
|
||||
|
||||
tasks:
|
||||
- name: "Remove account"
|
||||
mongodb_user:
|
||||
login_user: "{{ jms_account.username }}"
|
||||
login_password: "{{ jms_account.secret }}"
|
||||
login_host: "{{ jms_asset.address }}"
|
||||
login_port: "{{ jms_asset.port }}"
|
||||
login_database: "{{ jms_asset.spec_info.db_name }}"
|
||||
ssl: "{{ jms_asset.spec_info.use_ssl }}"
|
||||
ssl_ca_certs: "{{ jms_asset.secret_info.ca_cert | default('') }}"
|
||||
ssl_certfile: "{{ jms_asset.secret_info.client_key | default('') }}"
|
||||
connection_options:
|
||||
- tlsAllowInvalidHostnames: "{{ jms_asset.spec_info.allow_invalid_cert}}"
|
||||
db: "{{ jms_asset.spec_info.db_name }}"
|
||||
name: "{{ account.username }}"
|
||||
state: absent
|
|
@ -0,0 +1,12 @@
|
|||
id: remove_account_mongodb
|
||||
name: "{{ 'MongoDB account remove' | trans }}"
|
||||
category: database
|
||||
type:
|
||||
- mongodb
|
||||
method: remove_account
|
||||
|
||||
i18n:
|
||||
MongoDB account remove:
|
||||
zh: 使用 Ansible 模块 mongodb 删除账号
|
||||
ja: Ansible モジュール mongodb を使用してアカウントを削除する
|
||||
en: Delete account using Ansible module mongodb
|
|
@ -0,0 +1,18 @@
|
|||
- hosts: mysql
|
||||
gather_facts: no
|
||||
vars:
|
||||
ansible_python_interpreter: /opt/py3/bin/python
|
||||
|
||||
tasks:
|
||||
- name: "Remove account"
|
||||
community.mysql.mysql_user:
|
||||
login_user: "{{ jms_account.username }}"
|
||||
login_password: "{{ jms_account.secret }}"
|
||||
login_host: "{{ jms_asset.address }}"
|
||||
login_port: "{{ jms_asset.port }}"
|
||||
check_hostname: "{{ check_ssl if check_ssl else omit }}"
|
||||
ca_cert: "{{ jms_asset.secret_info.ca_cert | default(omit) if check_ssl else omit }}"
|
||||
client_cert: "{{ jms_asset.secret_info.client_cert | default(omit) if check_ssl else omit }}"
|
||||
client_key: "{{ jms_asset.secret_info.client_key | default(omit) if check_ssl else omit }}"
|
||||
name: "{{ account.username }}"
|
||||
state: absent
|
|
@ -0,0 +1,14 @@
|
|||
id: remove_account_mysql
|
||||
name: "{{ 'MySQL account remove' | trans }}"
|
||||
category: database
|
||||
type:
|
||||
- mysql
|
||||
- mariadb
|
||||
method: remove_account
|
||||
|
||||
i18n:
|
||||
MySQL account remove:
|
||||
zh: 使用 Ansible 模块 mysql_user 删除账号
|
||||
ja: Ansible モジュール mysql_user を使用してアカウントを削除します
|
||||
en: Use the Ansible module mysql_user to delete the account
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
- hosts: oracle
|
||||
gather_facts: no
|
||||
vars:
|
||||
ansible_python_interpreter: /opt/py3/bin/python
|
||||
|
||||
tasks:
|
||||
- name: "Remove account"
|
||||
oracle_user:
|
||||
login_user: "{{ jms_account.username }}"
|
||||
login_password: "{{ jms_account.secret }}"
|
||||
login_host: "{{ jms_asset.address }}"
|
||||
login_port: "{{ jms_asset.port }}"
|
||||
login_database: "{{ jms_asset.spec_info.db_name }}"
|
||||
mode: "{{ jms_account.mode }}"
|
||||
name: "{{ account.username }}"
|
||||
state: absent
|
|
@ -0,0 +1,12 @@
|
|||
id: remove_account_oracle
|
||||
name: "{{ 'Oracle account remove' | trans }}"
|
||||
category: database
|
||||
type:
|
||||
- oracle
|
||||
method: remove_account
|
||||
|
||||
i18n:
|
||||
Oracle account remove:
|
||||
zh: 使用 Python 模块 oracledb 删除账号
|
||||
ja: Python モジュール oracledb を使用してアカウントを検証する
|
||||
en: Using Python module oracledb to verify account
|
|
@ -0,0 +1,15 @@
|
|||
- hosts: postgresql
|
||||
gather_facts: no
|
||||
vars:
|
||||
ansible_python_interpreter: /opt/py3/bin/python
|
||||
|
||||
tasks:
|
||||
- name: "Remove account"
|
||||
community.postgresql.postgresql_user:
|
||||
login_user: "{{ jms_account.username }}"
|
||||
login_password: "{{ jms_account.secret }}"
|
||||
login_host: "{{ jms_asset.address }}"
|
||||
login_port: "{{ jms_asset.port }}"
|
||||
db: "{{ jms_asset.spec_info.db_name }}"
|
||||
name: "{{ account.username }}"
|
||||
state: absent
|
|
@ -0,0 +1,12 @@
|
|||
id: remove_account_postgresql
|
||||
name: "{{ 'PostgreSQL account remove' | trans }}"
|
||||
category: database
|
||||
type:
|
||||
- postgresql
|
||||
method: remove_account
|
||||
|
||||
i18n:
|
||||
PostgreSQL account remove:
|
||||
zh: 使用 Ansible 模块 postgresql_user 删除账号
|
||||
ja: Ansible モジュール postgresql_user を使用してアカウントを削除します
|
||||
en: Use the Ansible module postgresql_user to delete the account
|
|
@ -0,0 +1,14 @@
|
|||
- hosts: sqlserver
|
||||
gather_facts: no
|
||||
vars:
|
||||
ansible_python_interpreter: /opt/py3/bin/python
|
||||
|
||||
tasks:
|
||||
- name: "Remove account"
|
||||
community.general.mssql_script:
|
||||
login_user: "{{ jms_account.username }}"
|
||||
login_password: "{{ jms_account.secret }}"
|
||||
login_host: "{{ jms_asset.address }}"
|
||||
login_port: "{{ jms_asset.port }}"
|
||||
name: "{{ jms_asset.spec_info.db_name }}"
|
||||
script: "DROP USER {{ account.username }}"
|
|
@ -0,0 +1,12 @@
|
|||
id: remove_account_sqlserver
|
||||
name: "{{ 'SQLServer account remove' | trans }}"
|
||||
category: database
|
||||
type:
|
||||
- sqlserver
|
||||
method: remove_account
|
||||
|
||||
i18n:
|
||||
SQLServer account remove:
|
||||
zh: 使用 Ansible 模块 mssql 删除账号
|
||||
ja: Ansible モジュール mssql を使用してアカウントを削除する
|
||||
en: Use Ansible module mssql to delete account
|
|
@ -0,0 +1,25 @@
|
|||
- hosts: demo
|
||||
gather_facts: no
|
||||
tasks:
|
||||
- name: "Get user home directory path"
|
||||
ansible.builtin.shell:
|
||||
cmd: "getent passwd {{ account.username }} | cut -d: -f6"
|
||||
register: user_home_dir
|
||||
ignore_errors: yes
|
||||
|
||||
- name: "Check if user home directory exists"
|
||||
ansible.builtin.stat:
|
||||
path: "{{ user_home_dir.stdout }}"
|
||||
register: home_dir
|
||||
when: user_home_dir.stdout != ""
|
||||
|
||||
- name: "Rename user home directory if it exists"
|
||||
ansible.builtin.command:
|
||||
cmd: "mv {{ user_home_dir.stdout }} {{ user_home_dir.stdout }}.bak"
|
||||
when: home_dir.stat.exists and user_home_dir.stdout != ""
|
||||
|
||||
- name: "Remove account"
|
||||
ansible.builtin.user:
|
||||
name: "{{ account.username }}"
|
||||
state: absent
|
||||
remove: "{{ home_dir.stat.exists }}"
|
|
@ -0,0 +1,13 @@
|
|||
id: remove_account_posix
|
||||
name: "{{ 'Posix account remove' | trans }}"
|
||||
category: host
|
||||
type:
|
||||
- linux
|
||||
- unix
|
||||
method: remove_account
|
||||
|
||||
i18n:
|
||||
Posix account remove:
|
||||
zh: 使用 Ansible 模块 user 删除账号
|
||||
ja: Ansible モジュール ユーザーを使用してアカウントを削除します
|
||||
en: Use the Ansible module user to delete the account
|
|
@ -0,0 +1,9 @@
|
|||
- hosts: windows
|
||||
gather_facts: no
|
||||
tasks:
|
||||
- name: "Remove account"
|
||||
ansible.windows.win_user:
|
||||
name: "{{ account.username }}"
|
||||
state: absent
|
||||
purge: yes
|
||||
force: yes
|
|
@ -0,0 +1,13 @@
|
|||
id: remove_account_windows
|
||||
name: "{{ 'Windows account remove' | trans }}"
|
||||
version: 1
|
||||
method: remove_account
|
||||
category: host
|
||||
type:
|
||||
- windows
|
||||
|
||||
i18n:
|
||||
Windows account remove:
|
||||
zh: 使用 Ansible 模块 win_user 删除账号
|
||||
ja: Ansible モジュール win_user を使用してアカウントを削除する
|
||||
en: Use the Ansible module win_user to delete an account
|
|
@ -0,0 +1,67 @@
|
|||
import os
|
||||
from copy import deepcopy
|
||||
|
||||
from django.db.models import QuerySet
|
||||
|
||||
from accounts.const import AutomationTypes
|
||||
from accounts.models import Account
|
||||
from common.utils import get_logger
|
||||
from ..base.manager import AccountBasePlaybookManager
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
class RemoveAccountManager(AccountBasePlaybookManager):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.host_account_mapper = {}
|
||||
|
||||
def prepare_runtime_dir(self):
|
||||
path = super().prepare_runtime_dir()
|
||||
ansible_config_path = os.path.join(path, 'ansible.cfg')
|
||||
|
||||
with open(ansible_config_path, 'w') as f:
|
||||
f.write('[ssh_connection]\n')
|
||||
f.write('ssh_args = -o ControlMaster=no -o ControlPersist=no\n')
|
||||
return path
|
||||
|
||||
@classmethod
|
||||
def method_type(cls):
|
||||
return AutomationTypes.remove_account
|
||||
|
||||
def get_gather_accounts(self, privilege_account, gather_accounts: QuerySet):
|
||||
gather_account_ids = self.execution.snapshot['gather_accounts']
|
||||
gather_accounts = gather_accounts.filter(id__in=gather_account_ids)
|
||||
gather_accounts = gather_accounts.exclude(
|
||||
username__in=[privilege_account.username, 'root', 'Administrator']
|
||||
)
|
||||
return gather_accounts
|
||||
|
||||
def host_callback(self, host, asset=None, account=None, automation=None, path_dir=None, **kwargs):
|
||||
if host.get('error'):
|
||||
return host
|
||||
|
||||
gather_accounts = asset.gatheredaccount_set.all()
|
||||
gather_accounts = self.get_gather_accounts(account, gather_accounts)
|
||||
|
||||
inventory_hosts = []
|
||||
|
||||
for gather_account in gather_accounts:
|
||||
h = deepcopy(host)
|
||||
h['name'] += '(' + gather_account.username + ')'
|
||||
self.host_account_mapper[h['name']] = (asset, gather_account)
|
||||
h['account'] = {'username': gather_account.username}
|
||||
inventory_hosts.append(h)
|
||||
return inventory_hosts
|
||||
|
||||
def on_host_success(self, host, result):
|
||||
tuple_asset_gather_account = self.host_account_mapper.get(host)
|
||||
if not tuple_asset_gather_account:
|
||||
return
|
||||
asset, gather_account = tuple_asset_gather_account
|
||||
Account.objects.filter(
|
||||
asset_id=asset.id,
|
||||
username=gather_account.username
|
||||
).delete()
|
||||
gather_account.delete()
|
|
@ -1,4 +1,4 @@
|
|||
- hosts: mongdb
|
||||
- hosts: mongodb
|
||||
gather_facts: no
|
||||
vars:
|
||||
ansible_python_interpreter: /opt/py3/bin/python
|
||||
|
|
|
@ -24,6 +24,7 @@ class AutomationTypes(models.TextChoices):
|
|||
push_account = 'push_account', _('Push account')
|
||||
change_secret = 'change_secret', _('Change secret')
|
||||
verify_account = 'verify_account', _('Verify account')
|
||||
remove_account = 'remove_account', _('Remove account')
|
||||
gather_accounts = 'gather_accounts', _('Gather accounts')
|
||||
verify_gateway_account = 'verify_gateway_account', _('Verify gateway account')
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ from django.db import migrations
|
|||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('accounts', '0006_gatheredaccount'),
|
||||
]
|
||||
|
@ -12,6 +11,13 @@ class Migration(migrations.Migration):
|
|||
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'},
|
||||
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'),
|
||||
('remove_account', 'Can remove account'),
|
||||
], 'verbose_name': 'Account'},
|
||||
),
|
||||
]
|
||||
|
|
|
@ -69,6 +69,7 @@ class Account(AbsConnectivity, LabeledMixin, BaseAccount):
|
|||
('view_historyaccountsecret', _('Can view asset history account secret')),
|
||||
('verify_account', _('Can verify account')),
|
||||
('push_account', _('Can push account')),
|
||||
('remove_account', _('Can remove account')),
|
||||
]
|
||||
|
||||
def __str__(self):
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
from rest_framework import permissions
|
||||
|
||||
|
||||
def check_permissions(request):
|
||||
act = request.data.get('action')
|
||||
if act == 'push':
|
||||
code = 'accounts.push_account'
|
||||
elif act == 'remove':
|
||||
code = 'accounts.remove_account'
|
||||
else:
|
||||
code = 'accounts.verify_account'
|
||||
return request.user.has_perm(code)
|
||||
|
||||
|
||||
class AccountTaskActionPermission(permissions.IsAuthenticated):
|
||||
|
||||
def has_permission(self, request, view):
|
||||
return super().has_permission(request, view) \
|
||||
and check_permissions(request)
|
|
@ -10,7 +10,7 @@ from rest_framework.generics import get_object_or_404
|
|||
from rest_framework.validators import UniqueTogetherValidator
|
||||
|
||||
from accounts.const import SecretType, Source, AccountInvalidPolicy
|
||||
from accounts.models import Account, AccountTemplate
|
||||
from accounts.models import Account, AccountTemplate, GatheredAccount
|
||||
from accounts.tasks import push_accounts_to_assets_task
|
||||
from assets.const import Category, AllTypes
|
||||
from assets.models import Asset
|
||||
|
@ -458,11 +458,15 @@ class AccountTaskSerializer(serializers.Serializer):
|
|||
('test', 'test'),
|
||||
('verify', 'verify'),
|
||||
('push', 'push'),
|
||||
('remove', 'remove'),
|
||||
)
|
||||
action = serializers.ChoiceField(choices=ACTION_CHOICES, write_only=True)
|
||||
accounts = serializers.PrimaryKeyRelatedField(
|
||||
queryset=Account.objects, required=False, allow_empty=True, many=True
|
||||
)
|
||||
gather_accounts = serializers.PrimaryKeyRelatedField(
|
||||
queryset=GatheredAccount.objects, required=False, allow_empty=True, many=True
|
||||
)
|
||||
task = serializers.CharField(read_only=True)
|
||||
params = serializers.JSONField(
|
||||
decoder=None, encoder=None, required=False,
|
||||
|
|
|
@ -2,5 +2,6 @@ from .automation import *
|
|||
from .backup_account import *
|
||||
from .gather_accounts import *
|
||||
from .push_account import *
|
||||
from .remove_account import *
|
||||
from .template import *
|
||||
from .verify_account import *
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
from celery import shared_task
|
||||
from django.utils.translation import gettext_noop, gettext_lazy as _
|
||||
|
||||
from accounts.const import AutomationTypes
|
||||
from accounts.tasks.common import quickstart_automation_by_snapshot
|
||||
from common.utils import get_logger
|
||||
|
||||
logger = get_logger(__file__)
|
||||
|
||||
__all__ = ['remove_accounts_task']
|
||||
|
||||
|
||||
@shared_task(
|
||||
queue="ansible", verbose_name=_('Remove accounts'),
|
||||
activity_callback=lambda self, gather_account_ids, *args, **kwargs: (gather_account_ids, None)
|
||||
)
|
||||
def remove_accounts_task(gather_account_ids):
|
||||
from accounts.models import GatheredAccount
|
||||
|
||||
gather_accounts = GatheredAccount.objects.filter(
|
||||
id__in=gather_account_ids
|
||||
)
|
||||
task_name = gettext_noop("Remove accounts")
|
||||
|
||||
task_snapshot = {
|
||||
'assets': [str(i.asset_id) for i in gather_accounts],
|
||||
'gather_accounts': [str(i.id) for i in gather_accounts],
|
||||
}
|
||||
|
||||
tp = AutomationTypes.remove_account
|
||||
quickstart_automation_by_snapshot(task_name, tp, task_snapshot)
|
|
@ -0,0 +1,55 @@
|
|||
# Generated by Django 4.1.10 on 2023-12-05 10:03
|
||||
from functools import reduce
|
||||
|
||||
from django.db import migrations, models
|
||||
from django.db.models import F
|
||||
|
||||
|
||||
def migrate_automation_ansible_remove_account(apps, *args):
|
||||
automation_model = apps.get_model('assets', 'PlatformAutomation')
|
||||
automation_map = {
|
||||
('oracle',): 'remove_account_oracle',
|
||||
('windows',): 'remove_account_windows',
|
||||
('mongodb',): 'remove_account_mongodb',
|
||||
('linux', 'unix'): 'remove_account_posix',
|
||||
('sqlserver',): 'remove_account_sqlserver',
|
||||
('mysql', 'mariadb'): 'remove_account_mysql',
|
||||
('postgresql',): 'remove_account_postgresql',
|
||||
}
|
||||
|
||||
update_objs = []
|
||||
types = list(reduce(lambda x, y: x + y, automation_map.keys()))
|
||||
qs = automation_model.objects.filter(platform__type__in=types).annotate(tp=F('platform__type'))
|
||||
for automation in qs:
|
||||
for types, method in automation_map.items():
|
||||
if automation.tp in types:
|
||||
automation.remove_account_enabled = True
|
||||
automation.remove_account_method = method
|
||||
break
|
||||
update_objs.append(automation)
|
||||
automation_model.objects.bulk_update(update_objs, ['remove_account_enabled', 'remove_account_method'])
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('assets', '0125_auto_20231011_1053'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='platformautomation',
|
||||
name='remove_account_enabled',
|
||||
field=models.BooleanField(default=False, verbose_name='Remove account enabled'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='platformautomation',
|
||||
name='remove_account_method',
|
||||
field=models.TextField(blank=True, max_length=32, null=True, verbose_name='Remove account method'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='platformautomation',
|
||||
name='remove_account_params',
|
||||
field=models.JSONField(default=dict, verbose_name='Remove account params'),
|
||||
),
|
||||
migrations.RunPython(migrate_automation_ansible_remove_account)
|
||||
]
|
|
@ -72,6 +72,12 @@ class PlatformAutomation(models.Model):
|
|||
max_length=32, blank=True, null=True, verbose_name=_("Gather facts method")
|
||||
)
|
||||
gather_accounts_params = models.JSONField(default=dict, verbose_name=_("Gather facts params"))
|
||||
|
||||
remove_account_enabled = models.BooleanField(default=False, verbose_name=_("Remove account enabled"))
|
||||
remove_account_method = models.TextField(
|
||||
max_length=32, blank=True, null=True, verbose_name=_("Remove account method")
|
||||
)
|
||||
remove_account_params = models.JSONField(default=dict, verbose_name=_("Remove account params"))
|
||||
platform = models.OneToOneField('Platform', on_delete=models.CASCADE, related_name='automation', null=True)
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue