perf: 修改 fields 支持 display choices

pull/8873/head
ibuler 2022-08-31 10:06:16 +08:00
parent ffd08eef74
commit 728dc43b6c
17 changed files with 142 additions and 54 deletions

View File

@ -1,35 +1,8 @@
# Generated by Django 3.1.14 on 2022-04-30 14:41 # Generated by Django 3.1.14 on 2022-04-30 14:41
from collections import namedtuple
from django.db import migrations, models from django.db import migrations, models
import django.db.models.deletion import django.db.models.deletion
def migrate_platform_set_ops(apps, *args):
platform_model = apps.get_model('assets', 'Platform')
default_ok = {
'su_enabled': True,
'su_method': 'sudo',
'domain_enabled': True,
'change_password_enabled': True,
'change_password_method': 'change_password_linux',
'verify_account_enabled': True,
'verify_account_method': 'verify_account_ansible',
}
platform_ops_map = {
'Linux': {**default_ok, 'change_password_method': 'change_password_linux'},
'Windows': {**default_ok, 'change_password_method': 'change_password_windows'},
'AIX': {**default_ok, 'change_password_method': 'change_password_aix'},
}
platforms = platform_model.objects.all()
for p in platforms:
p.set_ops = True
p.save()
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [

View File

@ -2,6 +2,12 @@
import time import time
from django.db import migrations from django.db import migrations
from assets.models import Platform
def migrate_platform_set_ops(apps, *args):
platform_model = apps.get_model('assets', 'Platform')
Platform.set_default_platforms_ops(platform_model)
def migrate_accounts(apps, schema_editor): def migrate_accounts(apps, schema_editor):
@ -59,5 +65,6 @@ class Migration(migrations.Migration):
] ]
operations = [ operations = [
migrations.RunPython(migrate_accounts) migrations.RunPython(migrate_accounts),
migrations.RunPython(migrate_platform_set_ops)
] ]

View File

@ -40,7 +40,7 @@ class Platform(models.Model):
# Accounts # Accounts
# 这应该和账号有关 # 这应该和账号有关
su_enabled = models.BooleanField(default=False, verbose_name=_("Su enabled")) su_enabled = models.BooleanField(default=False, verbose_name=_("Su enabled"))
su_method = models.TextField(max_length=32, blank=True, null=True, verbose_name=_("SU method")) su_method = models.CharField(max_length=32, blank=True, null=True, verbose_name=_("SU method"))
ping_enabled = models.BooleanField(default=False) ping_enabled = models.BooleanField(default=False)
ping_method = models.TextField(max_length=32, blank=True, null=True, verbose_name=_("Ping method")) ping_method = models.TextField(max_length=32, blank=True, null=True, verbose_name=_("Ping method"))
verify_account_enabled = models.BooleanField(default=False, verbose_name=_("Verify account enabled")) verify_account_enabled = models.BooleanField(default=False, verbose_name=_("Verify account enabled"))
@ -61,6 +61,74 @@ class Platform(models.Model):
) )
return linux.id return linux.id
@staticmethod
def set_default_platforms_ops(platform_model):
default_ok = {
'su_enabled': True,
'su_method': 'sudo',
'domain_enabled': True,
'change_password_enabled': True,
'change_password_method': 'change_password_linux',
'verify_account_enabled': True,
'verify_account_method': 'ansible_posix_ping',
}
db_default = {
'su_enabled': False,
'domain_enabled': True,
'change_password_enabled': True,
'verify_account_enabled': True,
}
platform_ops_map = {
('host', 'linux'): {
**default_ok,
'change_password_method': 'change_password_linux',
'verify_account_method': 'ansible_posix_ping'
},
('host', 'windows'): {
**default_ok,
'su_enabled': False,
'change_password_method': 'change_password_windows',
'verify_account_method': 'ansible_win_ping'
},
('host', 'unix'): {
**default_ok,
'verify_account_method': 'ansible_posix_ping',
'change_password_method': 'change_password_aix'
},
('database', 'mysql'): {
**db_default,
'verify_account_method': 'mysql_ping',
'change_password_method': 'change_password_mysql'
},
('database', 'postgresql'): {
**db_default,
'verify_account_method': 'postgresql_ping',
'change_password_method': 'change_password_postgresql'
},
('database', 'oracle'): {
**db_default,
'verify_account_method': 'oracle_ping',
'change_password_method': 'change_password_oracle'
},
('database', 'sqlserver'): {
**db_default,
'verify_account_method': 'mysql_ping',
'change_password_method': 'change_password_sqlserver'
},
}
platforms = platform_model.objects.all()
updated = []
for p in platforms:
attrs = platform_ops_map.get((p.category, p.type), {})
if not attrs:
continue
for k, v in attrs.items():
setattr(p, k, v)
updated.append(p)
platform_model.objects.bulk_update(updated, list(default_ok.keys()))
def __str__(self): def __str__(self):
return self.name return self.name

View File

@ -5,14 +5,23 @@ from functools import partial
BASE_DIR = os.path.dirname(os.path.abspath(__file__)) BASE_DIR = os.path.dirname(os.path.abspath(__file__))
def check_platform_method(manifest): def check_platform_method(manifest, manifest_path):
required_keys = ['category', 'method', 'name', 'id'] required_keys = ['category', 'method', 'name', 'id', 'type']
less_key = set(required_keys) - set(manifest.keys()) less_key = set(required_keys) - set(manifest.keys())
if less_key: if less_key:
raise ValueError("Manifest missing keys: {}".format(less_key)) raise ValueError("Manifest missing keys: {}, {}".format(less_key, manifest_path))
if not isinstance(manifest['type'], list):
raise ValueError("Manifest type must be a list: {}".format(manifest_path))
return True return True
def check_platform_methods(methods):
ids = [m['id'] for m in methods]
for i, _id in enumerate(ids):
if _id in ids[i+1:]:
raise ValueError("Duplicate id: {}".format(_id))
def get_platform_methods(): def get_platform_methods():
methods = [] methods = []
for root, dirs, files in os.walk(BASE_DIR, topdown=False): for root, dirs, files in os.walk(BASE_DIR, topdown=False):
@ -21,25 +30,25 @@ def get_platform_methods():
rel_path = path.replace(BASE_DIR, '.') rel_path = path.replace(BASE_DIR, '.')
if len(rel_path.split('/')) != 3: if len(rel_path.split('/')) != 3:
continue continue
manifest_path = os.path.join(path, 'manifest.yml') manifest_path = os.path.join(path, 'manifest.yml')
if not os.path.exists(manifest_path): if not os.path.exists(manifest_path):
continue continue
with open(manifest_path, 'r') as f: with open(manifest_path, 'r') as f:
manifest = yaml.safe_load(f) manifest = yaml.safe_load(f)
check_platform_method(manifest) check_platform_method(manifest, manifest_path)
methods.append(manifest) methods.append(manifest)
check_platform_methods(methods)
return methods return methods
def filter_key(manifest, attr, value): def filter_key(manifest, attr, value):
manifest_value = manifest.get(attr, '') manifest_value = manifest.get(attr, '')
if manifest_value == 'all':
return True
if isinstance(manifest_value, str): if isinstance(manifest_value, str):
manifest_value = [manifest_value] manifest_value = [manifest_value]
return value in manifest_value return value in manifest_value or 'all' in manifest_value
def filter_platform_methods(category, tp, method): def filter_platform_methods(category, tp, method):

View File

@ -1,6 +1,6 @@
id: change_password_mysql id: change_password_mysql
name: Change password for MySQL name: Change password for MySQL
category: database category: database
type: mysql type:
- mysql
method: change_password method: change_password

View File

@ -2,4 +2,5 @@ id: change_password_oracle
name: Change password for Oracle name: Change password for Oracle
method: change_password method: change_password
category: database category: database
type: oracle type:
- oracle

View File

@ -1,5 +1,6 @@
id: change_password_postgresql id: change_password_postgresql
name: Change password for PostgreSQL name: Change password for PostgreSQL
category: database category: database
type: postgresql type:
- postgresql
method: change_password method: change_password

View File

@ -2,6 +2,7 @@ id: change_password_sqlserver
name: Change password for SQLServer name: Change password for SQLServer
version: 1 version: 1
category: database category: database
type: sqlserver type:
- sqlserver
method: change_password method: change_password

View File

@ -0,0 +1,10 @@
id: ansible_posix_ping
name: Ansible posix ping
description: Ansible ping
category: host
type:
- linux
- unix
- macos
- bsd
method: verify_account

View File

@ -0,0 +1,13 @@
- hosts: centos
gather_facts: no
vars:
account:
username: web
password: test123
tasks:
- name: Verify password
win_ping:
vars:
ansible_user: "{{ account.username }}"
ansible_pass: "{{ account.password }}"

View File

@ -0,0 +1,6 @@
id: ansible_win_ping
name: Ansible win ping
category: host
type:
- windows
method: verify_account

View File

@ -1,4 +1,6 @@
id: change_password_aix id: change_password_aix
name: Change password for AIX name: Change password for AIX
category: host category: host
type:
- aix
method: change_password method: change_password

View File

@ -3,9 +3,5 @@ name: Change password local account for Windows
version: 1 version: 1
method: change_password method: change_password
category: host category: host
type: windows type:
vars: - windows
account:
username: test
password: teset123
public_key: test

View File

@ -1,6 +0,0 @@
id: verify_account_ansible
name: Ansible ping
description: Ansible ping
category: host
type: all
method: verify_account

View File

@ -54,3 +54,8 @@ class ChoiceDisplayField(ChoiceField):
'value': value, 'value': value,
'label': self.choice_mapper.get(six.text_type(value), value), 'label': self.choice_mapper.get(six.text_type(value), value),
} }
def to_internal_value(self, data):
if isinstance(data, dict):
return data.get('value')
return super(ChoiceDisplayField, self).to_internal_value(data)

View File

@ -90,6 +90,8 @@ class SimpleMetadataWithFilters(SimpleMetadata):
for choice_value, choice_name in dict(field.choices).items() for choice_value, choice_name in dict(field.choices).items()
] ]
if field.__class__.__name__ == 'ChoiceDisplayField':
field_info['type'] = 'display_choice'
return field_info return field_info
def get_filters_fields(self, request, view): def get_filters_fields(self, request, view):