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
from collections import namedtuple
from django.db import migrations, models
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):
dependencies = [

View File

@ -2,6 +2,12 @@
import time
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):
@ -59,5 +65,6 @@ class Migration(migrations.Migration):
]
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
# 这应该和账号有关
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_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"))
@ -61,6 +61,74 @@ class Platform(models.Model):
)
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):
return self.name

View File

@ -5,14 +5,23 @@ from functools import partial
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
def check_platform_method(manifest):
required_keys = ['category', 'method', 'name', 'id']
def check_platform_method(manifest, manifest_path):
required_keys = ['category', 'method', 'name', 'id', 'type']
less_key = set(required_keys) - set(manifest.keys())
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
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():
methods = []
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, '.')
if len(rel_path.split('/')) != 3:
continue
manifest_path = os.path.join(path, 'manifest.yml')
if not os.path.exists(manifest_path):
continue
with open(manifest_path, 'r') as f:
manifest = yaml.safe_load(f)
check_platform_method(manifest)
check_platform_method(manifest, manifest_path)
methods.append(manifest)
check_platform_methods(methods)
return methods
def filter_key(manifest, attr, value):
manifest_value = manifest.get(attr, '')
if manifest_value == 'all':
return True
if isinstance(manifest_value, str):
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):

View File

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

View File

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

View File

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

View File

@ -2,6 +2,7 @@ id: change_password_sqlserver
name: Change password for SQLServer
version: 1
category: database
type: sqlserver
type:
- sqlserver
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
name: Change password for AIX
category: host
type:
- aix
method: change_password

View File

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

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,
'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()
]
if field.__class__.__name__ == 'ChoiceDisplayField':
field_info['type'] = 'display_choice'
return field_info
def get_filters_fields(self, request, view):