perf: automations push ping verify

pull/9008/head
feng 2022-10-28 18:28:41 +08:00
parent 994a484adb
commit 121ba1df07
43 changed files with 339 additions and 157 deletions

View File

@ -1,19 +1,68 @@
import os import os
import shutil
import yaml import yaml
import shutil
from hashlib import md5
from copy import deepcopy
from socket import gethostname
from collections import defaultdict from collections import defaultdict
from django.conf import settings from django.conf import settings
from django.utils import timezone from django.utils import timezone
from django.db.models import Model
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from common.utils import get_logger from common.utils import get_logger
from common.utils import ssh_pubkey_gen, ssh_key_string_to_obj
from assets.const import SecretType
from assets.automations.methods import platform_automation_methods from assets.automations.methods import platform_automation_methods
from ops.ansible import JMSInventory, PlaybookRunner, DefaultCallback from ops.ansible import JMSInventory, PlaybookRunner, DefaultCallback
logger = get_logger(__name__) logger = get_logger(__name__)
class PushOrVerifyHostCallbackMixin:
execution: Model()
host_account_mapper: dict
ignore_account: bool
generate_public_key: callable
generate_private_key_path: callable
def host_callback(self, host, asset=None, account=None, automation=None, path_dir=None, **kwargs):
host = super().host_callback(host, asset=asset, account=account, automation=automation, **kwargs)
if host.get('error'):
return host
accounts = asset.accounts.all()
if self.ignore_account and account:
accounts = accounts.exclude(id=account.id)
if '*' not in self.execution.snapshot['accounts']:
accounts = accounts.filter(username__in=self.execution.snapshot['accounts'])
inventory_hosts = []
for account in accounts:
h = deepcopy(host)
h['name'] += '_' + account.username
self.host_account_mapper[h['name']] = account
secret = account.secret
private_key_path = None
if account.secret_type == SecretType.ssh_key:
private_key_path = self.generate_private_key_path(secret, path_dir)
secret = self.generate_public_key(secret)
h['secret_type'] = account.secret_type
h['account'] = {
'name': account.name,
'username': account.username,
'secret_type': account.secret_type,
'secret': secret,
'private_key_path': private_key_path
}
inventory_hosts.append(h)
return inventory_hosts
class PlaybookCallback(DefaultCallback): class PlaybookCallback(DefaultCallback):
def playbook_on_stats(self, event_data, **kwargs): def playbook_on_stats(self, event_data, **kwargs):
super().playbook_on_stats(event_data, **kwargs) super().playbook_on_stats(event_data, **kwargs)
@ -66,20 +115,33 @@ class BasePlaybookManager:
method_attr = '{}_method'.format(self.__class__.method_type()) method_attr = '{}_method'.format(self.__class__.method_type())
method_enabled = automation and \ method_enabled = automation and \
getattr(automation, enabled_attr) and \ getattr(automation, enabled_attr) and \
getattr(automation, method_attr) and \ getattr(automation, method_attr) and \
getattr(automation, method_attr) in self.method_id_meta_mapper getattr(automation, method_attr) in self.method_id_meta_mapper
if not method_enabled: if not method_enabled:
host['error'] = _('{} disabled'.format(self.__class__.method_type())) host['error'] = _('{} disabled'.format(self.__class__.method_type()))
return host return host
return host return host
@staticmethod
def generate_public_key(private_key):
return ssh_pubkey_gen(private_key=private_key, hostname=gethostname())
@staticmethod
def generate_private_key_path(secret, path_dir):
key_name = '.' + md5(secret.encode('utf-8')).hexdigest()
key_path = os.path.join(path_dir, key_name)
if not os.path.exists(key_path):
ssh_key_string_to_obj(secret, password=None).write_private_key_file(key_path)
os.chmod(key_path, 0o400)
return key_path
def generate_inventory(self, platformed_assets, inventory_path): def generate_inventory(self, platformed_assets, inventory_path):
inventory = JMSInventory( inventory = JMSInventory(
manager=self,
assets=platformed_assets, assets=platformed_assets,
account_policy=self.ansible_account_policy, account_policy=self.ansible_account_policy,
host_callback=self.host_callback,
) )
inventory.write_to_file(inventory_path) inventory.write_to_file(inventory_path)
@ -105,7 +167,7 @@ class BasePlaybookManager:
def get_runners(self): def get_runners(self):
runners = [] runners = []
for platform, assets in self.get_assets_group_by_platform().items(): for platform, assets in self.get_assets_group_by_platform().items():
assets_bulked = [assets[i:i+self.bulk_size] for i in range(0, len(assets), self.bulk_size)] assets_bulked = [assets[i:i + self.bulk_size] for i in range(0, len(assets), self.bulk_size)]
for i, _assets in enumerate(assets_bulked, start=1): for i, _assets in enumerate(assets_bulked, start=1):
sub_dir = '{}_{}'.format(platform.name, i) sub_dir = '{}_{}'.format(platform.name, i)
@ -148,7 +210,7 @@ class BasePlaybookManager:
print(" inventory: {}".format(runner.inventory)) print(" inventory: {}".format(runner.inventory))
print(" playbook: {}".format(runner.playbook)) print(" playbook: {}".format(runner.playbook))
def run(self, *args, **kwargs): def run(self, *args, **kwargs):
runners = self.get_runners() runners = self.get_runners()
if len(runners) > 1: if len(runners) > 1:
print("### 分批次执行开始任务, 总共 {}\n".format(len(runners))) print("### 分批次执行开始任务, 总共 {}\n".format(len(runners)))

View File

@ -10,7 +10,7 @@
login_password: "{{ jms_account.secret }}" login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}" login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}" login_port: "{{ jms_asset.port }}"
login_db: "{{ jms_asset.database }}" login_db: "{{ jms_asset.category_property.db_name }}"
register: db_info register: db_info
- name: Display PostgreSQL version - name: Display PostgreSQL version
@ -24,7 +24,7 @@
login_password: "{{ jms_account.secret }}" login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}" login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}" login_port: "{{ jms_asset.port }}"
db: "{{ jms_asset.database }}" db: "{{ jms_asset.category_property.db_name }}"
name: "{{ account.username }}" name: "{{ account.username }}"
password: "{{ account.secret }}" password: "{{ account.secret }}"
when: db_info is succeeded when: db_info is succeeded
@ -36,7 +36,7 @@
login_password: "{{ account.secret }}" login_password: "{{ account.secret }}"
login_host: "{{ jms_asset.address }}" login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}" login_port: "{{ jms_asset.port }}"
db: "{{ jms_asset.database }}" db: "{{ jms_asset.category_property.db_name }}"
when: when:
- db_info is succeeded - db_info is succeeded
- change_info is succeeded - change_info is succeeded

View File

@ -1,58 +0,0 @@
- hosts: demo
gather_facts: no
tasks:
- name: Test privileged account
ansible.builtin.ping:
#
# - name: print variables
# debug:
# msg: "Username: {{ account.username }}, Secret: {{ account.secret }}, Secret type: {{ secret_type }}"
- name: Change password
ansible.builtin.user:
name: "{{ account.username }}"
password: "{{ account.secret | password_hash('sha512') }}"
update_password: always
when: secret_type == "password"
- name: create user If it already exists, no operation will be performed
ansible.builtin.user:
name: "{{ account.username }}"
when: secret_type == "ssh_key"
- name: remove jumpserver ssh key
ansible.builtin.lineinfile:
dest: "{{ kwargs.dest }}"
regexp: "{{ kwargs.regexp }}"
state: absent
when:
- secret_type == "ssh_key"
- kwargs.strategy == "set_jms"
- name: Change SSH key
ansible.builtin.authorized_key:
user: "{{ account.username }}"
key: "{{ account.secret }}"
exclusive: "{{ kwargs.exclusive }}"
when: secret_type == "ssh_key"
- name: Refresh connection
ansible.builtin.meta: reset_connection
- name: Verify password
ansible.builtin.ping:
become: no
vars:
ansible_user: "{{ account.username }}"
ansible_password: "{{ account.secret }}"
ansible_become: no
when: secret_type == "password"
- name: Verify SSH key
ansible.builtin.ping:
become: no
vars:
ansible_user: "{{ account.username }}"
ansible_ssh_private_key_file: "{{ account.private_key_path }}"
ansible_become: no
when: secret_type == "ssh_key"

View File

@ -1,6 +0,0 @@
id: change_secret_aix
name: Change password for AIX
category: host
type:
- aix
method: change_secret

View File

@ -1,14 +1,11 @@
import os
import random import random
import string import string
from hashlib import md5
from copy import deepcopy from copy import deepcopy
from socket import gethostname
from collections import defaultdict from collections import defaultdict
from django.utils import timezone from django.utils import timezone
from common.utils import lazyproperty, gen_key_pair, ssh_pubkey_gen, ssh_key_string_to_obj from common.utils import lazyproperty, gen_key_pair
from assets.models import ChangeSecretRecord from assets.models import ChangeSecretRecord
from assets.const import ( from assets.const import (
AutomationTypes, SecretType, SecretStrategy, SSHKeyStrategy, DEFAULT_PASSWORD_RULES AutomationTypes, SecretType, SecretStrategy, SSHKeyStrategy, DEFAULT_PASSWORD_RULES
@ -39,19 +36,6 @@ class ChangeSecretManager(BasePlaybookManager):
private_key, public_key = gen_key_pair() private_key, public_key = gen_key_pair()
return private_key return private_key
@staticmethod
def generate_public_key(private_key):
return ssh_pubkey_gen(private_key=private_key, hostname=gethostname())
@staticmethod
def generate_private_key_path(secret, path_dir):
key_name = '.' + md5(secret.encode('utf-8')).hexdigest()
key_path = os.path.join(path_dir, key_name)
if not os.path.exists(key_path):
ssh_key_string_to_obj(secret, password=None).write_private_key_file(key_path)
os.chmod(key_path, 0o400)
return key_path
def generate_password(self): def generate_password(self):
kwargs = self.execution.snapshot['password_rules'] or {} kwargs = self.execution.snapshot['password_rules'] or {}
length = int(kwargs.get('length', DEFAULT_PASSWORD_RULES['length'])) length = int(kwargs.get('length', DEFAULT_PASSWORD_RULES['length']))

View File

@ -1,6 +1,8 @@
from .change_secret.manager import ChangeSecretManager from .change_secret.manager import ChangeSecretManager
from .gather_facts.manager import GatherFactsManager from .gather_facts.manager import GatherFactsManager
from .gather_accounts.manager import GatherAccountsManager from .gather_accounts.manager import GatherAccountsManager
from .verify_account.manager import VerifyAccountManager
from .push_account.manager import PushAccountManager
from ..const import AutomationTypes from ..const import AutomationTypes
@ -9,6 +11,8 @@ class ExecutionManager:
AutomationTypes.change_secret: ChangeSecretManager, AutomationTypes.change_secret: ChangeSecretManager,
AutomationTypes.gather_facts: GatherFactsManager, AutomationTypes.gather_facts: GatherFactsManager,
AutomationTypes.gather_accounts: GatherAccountsManager, AutomationTypes.gather_accounts: GatherAccountsManager,
AutomationTypes.verify_account: VerifyAccountManager,
AutomationTypes.push_account: PushAccountManager,
} }
def __init__(self, execution): def __init__(self, execution):

View File

@ -1,7 +1,7 @@
- hosts: mysql - hosts: mysql
gather_facts: no gather_facts: no
vars: vars:
ansible_python_interpreter: /usr/local/bin/python ansible_python_interpreter: /Users/xiaofeng/Desktop/jumpserver/venv/bin/python
tasks: tasks:
- name: Get info - name: Get info
@ -9,7 +9,7 @@
login_user: "{{ jms_account.username }}" login_user: "{{ jms_account.username }}"
login_password: "{{ jms_account.secret }}" login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}" login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}" login_port: 1234
filter: users filter: users
register: db_info register: db_info

View File

@ -10,7 +10,7 @@
login_password: "{{ jms_account.secret }}" login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}" login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}" login_port: "{{ jms_asset.port }}"
login_db: "{{ jms_asset.database }}" login_db: "{{ jms_asset.category_property.db_name }}"
filter: "roles" filter: "roles"
register: db_info register: db_info

View File

@ -2,8 +2,10 @@
gather_facts: no gather_facts: no
tasks: tasks:
- name: Gather posix account - name: Gather posix account
ansible.builtin.win_shell: ansible.builtin.shell:
cmd: net user cmd: >
users=$(getent passwd | grep -v nologin | grep -v shutdown | awk -F":" '{ print $1 }');for i in $users;
do last -w -F $i -1 | head -1 | grep -v ^$ | awk '{ print $1"@"$3"@"$5,$6,$7,$8 }';done
register: result register: result
- name: Define info by set_fact - name: Define info by set_fact

View File

@ -1,18 +1,14 @@
- hosts: windows - hosts: demo
gather_facts: yes gather_facts: no
tasks: tasks:
- name: Get info - name: Gather posix account
set_fact: ansible.builtin.win_shell:
info: cmd: net user
arch: "{{ ansible_architecture2 }}" register: result
distribution: "{{ ansible_distribution }}"
distribution_version: "{{ ansible_distribution_version }}" - name: Define info by set_fact
kernel: "{{ ansible_kernel }}" ansible.builtin.set_fact:
vendor: "{{ ansible_system_vendor }}" info: "{{ result.stdout_lines }}"
model: "{{ ansible_product_name }}"
sn: "{{ ansible_product_serial }}"
cpu_vcpus: "{{ ansible_processor_vcpus }}"
memory: "{{ ansible_memtotal_mb }}"
- debug: - debug:
var: info var: info

View File

@ -2,7 +2,7 @@ from common.utils import get_logger
from assets.const import AutomationTypes from assets.const import AutomationTypes
from orgs.utils import tmp_to_org from orgs.utils import tmp_to_org
from .filter import GatherAccountsFilter from .filter import GatherAccountsFilter
from ...models import Account, GatheredUser from ...models import GatheredUser
from ..base.manager import BasePlaybookManager from ..base.manager import BasePlaybookManager
logger = get_logger(__name__) logger = get_logger(__name__)
@ -42,4 +42,4 @@ class GatherAccountsManager(BasePlaybookManager):
defaults['ip_last_login'] = data['address'][:32] defaults['ip_last_login'] = data['address'][:32]
GatheredUser.objects.update_or_create(defaults=defaults, asset=asset, username=username) GatheredUser.objects.update_or_create(defaults=defaults, asset=asset, username=username)
else: else:
logger.error("Not found info, task name must be 'Get info': {}".format(host)) logger.error("Not found info".format(host))

View File

@ -10,7 +10,7 @@
login_password: "{{ jms_account.secret }}" login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}" login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}" login_port: "{{ jms_asset.port }}"
login_db: "{{ jms_asset.database }}" login_db: "{{ jms_asset.category_property.db_name }}"
register: db_info register: db_info
- name: Define info by set_fact - name: Define info by set_fact

View File

@ -26,4 +26,4 @@ class GatherFactsManager(BasePlaybookManager):
asset.info = info asset.info = info
asset.save() asset.save()
else: else:
logger.error("Not found info, task name must be 'Get info': {}".format(host)) logger.error("Not found info: {}".format(host))

View File

@ -2,12 +2,6 @@
gather_facts: no gather_facts: no
vars: vars:
ansible_python_interpreter: /usr/local/bin/python ansible_python_interpreter: /usr/local/bin/python
jms_account:
username: root
password: redhat
jms_asset:
address: 127.0.0.1
port: 3306
tasks: tasks:
- name: Test MySQL connection - name: Test MySQL connection
@ -17,4 +11,3 @@
login_host: "{{ jms_asset.address }}" login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}" login_port: "{{ jms_asset.port }}"
filter: version filter: version
register: db_info

View File

@ -2,16 +2,6 @@
gather_facts: no gather_facts: no
vars: vars:
ansible_python_interpreter: /usr/local/bin/python ansible_python_interpreter: /usr/local/bin/python
jms_account:
username: postgre
secret: postgre
jms_asset:
address: 127.0.0.1
port: 5432
database: testdb
account:
username: test
secret: jumpserver
tasks: tasks:
- name: Test PostgreSQL connection - name: Test PostgreSQL connection
@ -20,4 +10,4 @@
login_password: "{{ jms_account.secret }}" login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}" login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}" login_port: "{{ jms_asset.port }}"
login_db: "{{ jms_asset.database }}" login_db: "{{ jms_asset.category_property.db_name }}"

View File

@ -2,4 +2,4 @@
gather_facts: no gather_facts: no
tasks: tasks:
- name: Windows ping - name: Windows ping
win_ping: ansible.builtin.win_ping:

View File

@ -6,4 +6,15 @@ logger = get_logger(__name__)
class PingManager(BasePlaybookManager): class PingManager(BasePlaybookManager):
pass def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.host_asset_mapper = {}
@classmethod
def method_type(cls):
return AutomationTypes.ping
def host_callback(self, host, asset=None, **kwargs):
super().host_callback(host, asset=asset, **kwargs)
self.host_asset_mapper[host['name']] = asset
return host

View File

@ -0,0 +1,15 @@
- hosts: mysql
gather_facts: no
vars:
ansible_python_interpreter: /usr/local/bin/python
tasks:
- name: Add user account.username
community.mysql.mysql_user:
login_user: "{{ jms_account.username }}"
login_password: "{{ jms_account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
name: "{{ account.username }}"
password: "{{ account.secret }}"
host: "%"

View File

@ -0,0 +1,6 @@
id: push_account_mysql
name: Push account from MySQL
category: database
type:
- mysql
method: push_account

View File

@ -0,0 +1,16 @@
- hosts: postgresql
gather_facts: no
vars:
ansible_python_interpreter: /usr/local/bin/python
tasks:
- name: Add user account.username
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.category_property.db_name }}"
name: "{{ account.username }}"
password: "{{ account.secret }}"

View File

@ -0,0 +1,6 @@
id: push_account_postgresql
name: Push account for PostgreSQL
category: database
type:
- postgresql
method: push_account

View File

@ -0,0 +1,19 @@
- hosts: demo
gather_facts: no
tasks:
- name: Add user account.username
ansible.builtin.user:
name: "{{ account.username }}"
- name: Set account.username password
ansible.builtin.user:
name: "{{ account.username }}"
password: "{{ account.secret | password_hash('sha512') }}"
update_password: always
when: secret_type == "password"
- name: Set account.username SSH key
ansible.builtin.authorized_key:
user: "{{ account.username }}"
key: "{{ account.secret }}"
when: secret_type == "ssh_key"

View File

@ -0,0 +1,7 @@
id: push_account_posix
name: Push posix account
category: host
type:
- linux
- unix
method: push_account

View File

@ -0,0 +1,13 @@
- hosts: windows
gather_facts: yes
tasks:
- name: Add user account.username
ansible.windows.win_user:
vars:
fullname: "{{ account.username }}"
name: "{{ account.username }}"
password: "{{ account.secret }}"
state: present
password_expired: no
update_password: always
password_never_expires: yes

View File

@ -0,0 +1,7 @@
id: push_account_windows
name: Push account windows
version: 1
method: push_account
category: host
type:
- windows

View File

@ -0,0 +1,17 @@
from common.utils import get_logger
from assets.const import AutomationTypes
from ..base.manager import BasePlaybookManager, PushOrVerifyHostCallbackMixin
logger = get_logger(__name__)
class PushAccountManager(PushOrVerifyHostCallbackMixin, BasePlaybookManager):
ignore_account = True
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.host_account_mapper = {}
@classmethod
def method_type(cls):
return AutomationTypes.push_account

View File

@ -0,0 +1,13 @@
- hosts: mysql
gather_facts: no
vars:
ansible_python_interpreter: /usr/local/bin/python
tasks:
- name: Verify account
community.mysql.mysql_info:
login_user: "{{ account.username }}"
login_password: "{{ account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
filter: version

View File

@ -0,0 +1,6 @@
id: verify_account_mysql
name: Verify account from MySQL
category: database
type:
- mysql
method: verify_account

View File

@ -0,0 +1,13 @@
- hosts: postgresql
gather_facts: no
vars:
ansible_python_interpreter: /usr/local/bin/python
tasks:
- name: Verify account
community.postgresql.postgresql_ping:
login_user: "{{ account.username }}"
login_password: "{{ account.secret }}"
login_host: "{{ jms_asset.address }}"
login_port: "{{ jms_asset.port }}"
db: "{{ jms_asset.category_property.db_name }}"

View File

@ -0,0 +1,6 @@
id: verify_account_postgresql
name: Verify account for PostgreSQL
category: database
type:
- postgresql
method: verify_account

View File

@ -0,0 +1,11 @@
- hosts: demo
gather_facts: no
tasks:
- name: Verify account
ansible.builtin.ping:
become: no
vars:
ansible_user: "{{ account.username }}"
ansible_password: "{{ account.secret }}"
ansible_ssh_private_key_file: "{{ account.private_key_path }}"
ansible_become: no

View File

@ -0,0 +1,7 @@
id: verify_account_posix
name: Verify posix account
category: host
type:
- linux
- unix
method: verify_account

View File

@ -0,0 +1,8 @@
- hosts: windows
gather_facts: yes
tasks:
- name: Verify account
ansible.windows.win_ping:
vars:
ansible_user: "{{ account.username }}"
ansible_password: "{{ account.secret }}"

View File

@ -0,0 +1,7 @@
id: verify_account_windows
name: Verify account windows
version: 1
method: verify_account
category: host
type:
- windows

View File

@ -0,0 +1,25 @@
from common.utils import get_logger
from assets.const import AutomationTypes, Connectivity
from ..base.manager import BasePlaybookManager, PushOrVerifyHostCallbackMixin
logger = get_logger(__name__)
class VerifyAccountManager(PushOrVerifyHostCallbackMixin, BasePlaybookManager):
ignore_account = False
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.host_account_mapper = {}
@classmethod
def method_type(cls):
return AutomationTypes.verify_account
def on_host_success(self, host, result):
account = self.host_account_mapper.get(host)
account.set_connectivity(Connectivity.ok)
def on_host_error(self, host, error, result):
account = self.host_account_mapper.get(host)
account.set_connectivity(Connectivity.failed)

View File

@ -1,6 +1,6 @@
from .change_secret import * from .change_secret import *
from .discovery_account import * from .discovery_account import *
from .push_account import * from .push_account import *
from .verify_secret import *
from .gather_facts import * from .gather_facts import *
from .gather_accounts import * from .gather_accounts import *
from .verify_account import *

View File

@ -2,7 +2,6 @@ from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from common.db import fields from common.db import fields
from common.const.choices import Trigger
from common.db.models import JMSBaseModel from common.db.models import JMSBaseModel
from assets.const import AutomationTypes, SecretType, SecretStrategy, SSHKeyStrategy from assets.const import AutomationTypes, SecretType, SecretStrategy, SSHKeyStrategy
from .base import BaseAutomation from .base import BaseAutomation

View File

@ -1,15 +1,16 @@
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from assets.const import AutomationTypes
from .base import BaseAutomation from .base import BaseAutomation
__all__ = ['PushAccountAutomation']
class PushAccountAutomation(BaseAutomation): class PushAccountAutomation(BaseAutomation):
class Meta:
verbose_name = _("Push automation")
def to_attr_json(self): def save(self, *args, **kwargs):
attr_json = super().to_attr_json() self.type = AutomationTypes.verify_account
attr_json.update({ super().save(*args, **kwargs)
'type': 'push_account'
}) class Meta:
return attr_json verbose_name = _("Push asset account")

View File

@ -1,12 +1,15 @@
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from assets.const import AutomationTypes
from .base import BaseAutomation from .base import BaseAutomation
__all__ = ['VerifyAccountAutomation']
class VerifyAccountAutomation(BaseAutomation): class VerifyAccountAutomation(BaseAutomation):
class Meta:
verbose_name = _("Verify account automation")
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
self.type = 'verify_account' self.type = AutomationTypes.verify_account
super().save(*args, **kwargs) super().save(*args, **kwargs)
class Meta:
verbose_name = _("Verify asset account")

View File

@ -49,7 +49,7 @@ class DefaultCallback:
} }
self.result['ok'][host][task] = detail self.result['ok'][host][task] = detail
def runer_on_failed(self, event_data, host=None, task=None, res=None, **kwargs): def runner_on_failed(self, event_data, host=None, task=None, res=None, **kwargs):
detail = { detail = {
'action': event_data.get('task_action', ''), 'action': event_data.get('task_action', ''),
'res': res, 'res': res,

View File

@ -9,8 +9,10 @@ __all__ = ['JMSInventory']
class JMSInventory: class JMSInventory:
def __init__(self, manager, assets=None, account_policy='smart', def __init__(
account_prefer='root,administrator', host_callback=None): self, assets=None, account_policy='smart',
account_prefer='root,administrator', host_callback=None
):
""" """
:param assets: :param assets:
:param account_prefer: account username name if not set use account_policy :param account_prefer: account username name if not set use account_policy
@ -79,10 +81,7 @@ class JMSInventory:
ssh_protocol_matched = list(filter(lambda x: x.name == 'ssh', protocols)) ssh_protocol_matched = list(filter(lambda x: x.name == 'ssh', protocols))
ssh_protocol = ssh_protocol_matched[0] if ssh_protocol_matched else None ssh_protocol = ssh_protocol_matched[0] if ssh_protocol_matched else None
host['ansible_host'] = asset.address host['ansible_host'] = asset.address
if asset.port == 0: host['ansible_port'] = ssh_protocol.port if ssh_protocol else 22
host['ansible_port'] = ssh_protocol.port if ssh_protocol else 22
else:
host['ansible_port'] = asset.port
su_from = account.su_from su_from = account.su_from
if platform.su_enabled and su_from: if platform.su_enabled and su_from:
@ -166,9 +165,9 @@ class JMSInventory:
platform_assets = self.group_by_platform(self.assets) platform_assets = self.group_by_platform(self.assets)
for platform, assets in platform_assets.items(): for platform, assets in platform_assets.items():
automation = platform.automation automation = platform.automation
protocols = platform.protocols.all()
for asset in assets: for asset in assets:
protocols = asset.protocols.all()
account = self.select_account(asset) account = self.select_account(asset)
host = self.asset_to_host(asset, account, automation, protocols, platform) host = self.asset_to_host(asset, account, automation, protocols, platform)