mirror of https://github.com/jumpserver/jumpserver
[Feature] 修改ansible和ops
parent
e57121a780
commit
2b3551f1fc
|
@ -44,28 +44,18 @@ class Asset(models.Model):
|
|||
ip = models.GenericIPAddressField(max_length=32, verbose_name=_('IP'), db_index=True)
|
||||
hostname = models.CharField(max_length=128, unique=True, verbose_name=_('Hostname'))
|
||||
port = models.IntegerField(default=22, verbose_name=_('Port'))
|
||||
groups = models.ManyToManyField(AssetGroup, blank=True, related_name='assets',
|
||||
verbose_name=_('Asset groups'))
|
||||
admin_user = models.ForeignKey(AdminUser, null=True, blank=True, related_name='assets',
|
||||
on_delete=models.SET_NULL, verbose_name=_("Admin user"))
|
||||
system_users = models.ManyToManyField(SystemUser, blank=True,
|
||||
related_name='assets',
|
||||
verbose_name=_("System User"))
|
||||
idc = models.ForeignKey(IDC, blank=True, null=True, related_name='assets',
|
||||
on_delete=models.SET_NULL, verbose_name=_('IDC'),)
|
||||
groups = models.ManyToManyField(AssetGroup, blank=True, related_name='assets', verbose_name=_('Asset groups'))
|
||||
admin_user = models.ForeignKey(AdminUser, null=True, blank=True, related_name='assets', on_delete=models.SET_NULL, verbose_name=_("Admin user"))
|
||||
system_users = models.ManyToManyField(SystemUser, blank=True, related_name='assets', verbose_name=_("System User"))
|
||||
idc = models.ForeignKey(IDC, blank=True, null=True, related_name='assets', on_delete=models.SET_NULL, verbose_name=_('IDC'),)
|
||||
is_active = models.BooleanField(default=True, verbose_name=_('Is active'))
|
||||
type = models.CharField(choices=TYPE_CHOICES, max_length=16, blank=True, null=True,
|
||||
default='Server', verbose_name=_('Asset type'),)
|
||||
env = models.CharField(choices=ENV_CHOICES, max_length=8, blank=True, null=True,
|
||||
default='Prod', verbose_name=_('Asset environment'),)
|
||||
status = models.CharField(choices=STATUS_CHOICES, max_length=12, null=True, blank=True,
|
||||
default='In use', verbose_name=_('Asset status'))
|
||||
type = models.CharField(choices=TYPE_CHOICES, max_length=16, blank=True, null=True, default='Server', verbose_name=_('Asset type'),)
|
||||
env = models.CharField(choices=ENV_CHOICES, max_length=8, blank=True, null=True, default='Prod', verbose_name=_('Asset environment'),)
|
||||
status = models.CharField(choices=STATUS_CHOICES, max_length=12, null=True, blank=True, default='In use', verbose_name=_('Asset status'))
|
||||
|
||||
# Some information
|
||||
public_ip = models.GenericIPAddressField(max_length=32, blank=True,
|
||||
null=True, verbose_name=_('Public IP'))
|
||||
remote_card_ip = models.CharField(max_length=16, null=True, blank=True,
|
||||
verbose_name=_('Remote control card IP'))
|
||||
public_ip = models.GenericIPAddressField(max_length=32, blank=True, null=True, verbose_name=_('Public IP'))
|
||||
remote_card_ip = models.CharField(max_length=16, null=True, blank=True, verbose_name=_('Remote control card IP'))
|
||||
cabinet_no = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Cabinet number'))
|
||||
cabinet_pos = models.IntegerField(null=True, blank=True, verbose_name=_('Cabinet position'))
|
||||
number = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Asset number'))
|
||||
|
@ -114,22 +104,27 @@ class Asset(models.Model):
|
|||
|
||||
def _to_secret_json(self):
|
||||
"""Ansible use it create inventory"""
|
||||
return {
|
||||
data = {
|
||||
'id': self.id,
|
||||
'hostname': self.hostname,
|
||||
'ip': self.ip,
|
||||
'port': self.port,
|
||||
'groups': [group.name for group in self.groups.all()],
|
||||
'username': self.admin_user.username if self.admin_user else '',
|
||||
'password': self.admin_user.password if self.admin_user else '',
|
||||
'private_key': self.admin_user.private_key_file if self.admin_user else None,
|
||||
'become': {
|
||||
'method': self.admin_user.become_method,
|
||||
'user': self.admin_user.become_user,
|
||||
'pass': self.admin_user.become_pass,
|
||||
} if self.admin_user and self.admin_user.become else {},
|
||||
}
|
||||
|
||||
if self.admin_user:
|
||||
data.update({
|
||||
'username': self.admin_user.username,
|
||||
'password': self.admin_user.password,
|
||||
'private_key': self.admin_user.private_key_file,
|
||||
'become': {
|
||||
'method': self.admin_user.become_method,
|
||||
'user': self.admin_user.become_user,
|
||||
'pass': self.admin_user.become_pass,
|
||||
}
|
||||
})
|
||||
return data
|
||||
|
||||
class Meta:
|
||||
unique_together = ('ip', 'port')
|
||||
|
||||
|
|
|
@ -28,6 +28,9 @@ def private_key_validator(value):
|
|||
|
||||
|
||||
class AdminUser(models.Model):
|
||||
"""
|
||||
Ansible use admin user as devops user to run adHoc and Playbook
|
||||
"""
|
||||
BECOME_METHOD_CHOICES = (
|
||||
('sudo', 'sudo'),
|
||||
('su', 'su'),
|
||||
|
@ -35,24 +38,19 @@ class AdminUser(models.Model):
|
|||
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
||||
name = models.CharField(max_length=128, unique=True, verbose_name=_('Name'))
|
||||
username = models.CharField(max_length=16, verbose_name=_('Username'))
|
||||
_password = models.CharField(
|
||||
max_length=256, blank=True, null=True, verbose_name=_('Password'))
|
||||
_private_key = models.TextField(max_length=4096, blank=True, null=True, verbose_name=_('SSH private key'),
|
||||
validators=[private_key_validator,])
|
||||
_password = models.CharField(max_length=256, blank=True, null=True, verbose_name=_('Password'))
|
||||
_private_key = models.TextField(max_length=4096, blank=True, null=True, verbose_name=_('SSH private key'), validators=[private_key_validator,])
|
||||
become = models.BooleanField(default=True)
|
||||
become_method = models.CharField(choices=BECOME_METHOD_CHOICES, default='sudo', max_length=4)
|
||||
become_user = models.CharField(default='root', max_length=64)
|
||||
become_pass = models.CharField(default='', max_length=128)
|
||||
_public_key = models.TextField(
|
||||
max_length=4096, blank=True, verbose_name=_('SSH public key'))
|
||||
_public_key = models.TextField(max_length=4096, blank=True, verbose_name=_('SSH public key'))
|
||||
comment = models.TextField(blank=True, verbose_name=_('Comment'))
|
||||
date_created = models.DateTimeField(auto_now_add=True, null=True)
|
||||
created_by = models.CharField(
|
||||
max_length=32, null=True, verbose_name=_('Created by'))
|
||||
created_by = models.CharField(max_length=32, null=True, verbose_name=_('Created by'))
|
||||
|
||||
def __unicode__(self):
|
||||
def __str__(self):
|
||||
return self.name
|
||||
__str__ = __unicode__
|
||||
|
||||
@property
|
||||
def password(self):
|
||||
|
@ -134,33 +132,22 @@ class SystemUser(models.Model):
|
|||
('K', 'Public key'),
|
||||
)
|
||||
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
||||
name = models.CharField(max_length=128, unique=True,
|
||||
verbose_name=_('Name'))
|
||||
name = models.CharField(max_length=128, unique=True, verbose_name=_('Name'))
|
||||
username = models.CharField(max_length=16, verbose_name=_('Username'))
|
||||
_password = models.CharField(
|
||||
max_length=256, blank=True, verbose_name=_('Password'))
|
||||
protocol = models.CharField(
|
||||
max_length=16, choices=PROTOCOL_CHOICES, default='ssh', verbose_name=_('Protocol'))
|
||||
_private_key = models.TextField(
|
||||
max_length=8192, blank=True, verbose_name=_('SSH private key'))
|
||||
_public_key = models.TextField(
|
||||
max_length=8192, blank=True, verbose_name=_('SSH public key'))
|
||||
auth_method = models.CharField(choices=AUTH_METHOD_CHOICES, default='K',
|
||||
max_length=1, verbose_name=_('Auth method'))
|
||||
_password = models.CharField(max_length=256, blank=True, verbose_name=_('Password'))
|
||||
protocol = models.CharField(max_length=16, choices=PROTOCOL_CHOICES, default='ssh', verbose_name=_('Protocol'))
|
||||
_private_key = models.TextField(max_length=8192, blank=True, verbose_name=_('SSH private key'))
|
||||
_public_key = models.TextField(max_length=8192, blank=True, verbose_name=_('SSH public key'))
|
||||
auth_method = models.CharField(choices=AUTH_METHOD_CHOICES, default='K', max_length=1, verbose_name=_('Auth method'))
|
||||
auto_push = models.BooleanField(default=True, verbose_name=_('Auto push'))
|
||||
sudo = models.TextField(
|
||||
max_length=4096, default='/sbin/ifconfig', verbose_name=_('Sudo'))
|
||||
shell = models.CharField(
|
||||
max_length=64, default='/bin/bash', verbose_name=_('Shell'))
|
||||
sudo = models.TextField(default='/sbin/ifconfig', verbose_name=_('Sudo'))
|
||||
shell = models.CharField(max_length=64, default='/bin/bash', verbose_name=_('Shell'))
|
||||
date_created = models.DateTimeField(auto_now_add=True)
|
||||
created_by = models.CharField(
|
||||
max_length=32, blank=True, verbose_name=_('Created by'))
|
||||
comment = models.TextField(
|
||||
max_length=128, blank=True, verbose_name=_('Comment'))
|
||||
created_by = models.CharField(max_length=32, blank=True, verbose_name=_('Created by'))
|
||||
comment = models.TextField(max_length=128, blank=True, verbose_name=_('Comment'))
|
||||
|
||||
def __unicode__(self):
|
||||
def __str__(self):
|
||||
return self.name
|
||||
__str__ = __unicode__
|
||||
|
||||
@property
|
||||
def password(self):
|
||||
|
@ -182,9 +169,24 @@ class SystemUser(models.Model):
|
|||
def private_key(self, private_key_raw):
|
||||
self._private_key = signer.sign(private_key_raw)
|
||||
|
||||
@property
|
||||
def private_key_file(self):
|
||||
if not self.private_key:
|
||||
return None
|
||||
project_dir = settings.PROJECT_DIR
|
||||
tmp_dir = os.path.join(project_dir, 'tmp')
|
||||
key_name = md5(self._private_key.encode()).hexdigest()
|
||||
key_path = os.path.join(tmp_dir, key_name)
|
||||
if not os.path.exists(key_path):
|
||||
self.private_key.write_private_key_file(key_path)
|
||||
return key_path
|
||||
|
||||
@property
|
||||
def public_key(self):
|
||||
return signer.unsign(self._public_key)
|
||||
if self._public_key:
|
||||
return signer.unsign(self._public_key)
|
||||
else:
|
||||
return None
|
||||
|
||||
@public_key.setter
|
||||
def public_key(self, public_key_raw):
|
||||
|
@ -213,7 +215,8 @@ class SystemUser(models.Model):
|
|||
'shell': self.shell,
|
||||
'sudo': self.sudo,
|
||||
'password': self.password,
|
||||
'public_key': self.public_key
|
||||
'public_key': self.public_key,
|
||||
'private_key_file': self.private_key_file,
|
||||
}
|
||||
|
||||
@property
|
||||
|
|
|
@ -19,3 +19,32 @@ def test_admin_user_connective_manual(asset):
|
|||
|
||||
def get_assets_by_id_list(id_list):
|
||||
return Asset.objects.filter(id__in=id_list)
|
||||
|
||||
|
||||
def get_assets_by_hostname_list(hostname_list):
|
||||
return Asset.objects.filter(hostname__in=hostname_list)
|
||||
|
||||
|
||||
def get_asset_admin_user(user, asset):
|
||||
if user.is_superuser:
|
||||
return asset.admin_user
|
||||
else:
|
||||
msg = "{} have no permission for admin user".format(user.username)
|
||||
raise PermissionError(msg)
|
||||
|
||||
|
||||
def get_asset_system_user(user, asset, system_user_name):
|
||||
from perms.utils import get_user_granted_assets
|
||||
assets = get_user_granted_assets(user)
|
||||
system_users = {system_user.name: system_user for system_user in assets.get(asset)}
|
||||
|
||||
if system_user_name in system_users:
|
||||
return system_users[system_user_name]
|
||||
else:
|
||||
msg = "{} have no permission for {}".format(user.name, system_user_name)
|
||||
raise PermissionError(msg)
|
||||
|
||||
|
||||
def get_assets_with_admin_by_hostname_list(hostname_list):
|
||||
assets = Asset.objects.filter(hostname__in=hostname_list)
|
||||
return [(asset, asset.admin_user) for asset in assets]
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
|
@ -9,65 +9,85 @@ class AdHocResultCallback(CallbackBase):
|
|||
"""
|
||||
def __init__(self, display=None):
|
||||
# result_raw example: {
|
||||
# "ok": {"hostname": []},
|
||||
# "failed": {"hostname": []},
|
||||
# "unreachable: {"hostname": []},
|
||||
# "skipped": {"hostname": []},
|
||||
# "ok": {"hostname": [{"task_name": {},...],..},
|
||||
# "failed": {"hostname": ["task_name": {}..], ..},
|
||||
# "unreachable: {"hostname": ["task_name": {}, ..]},
|
||||
# "skipped": {"hostname": ["task_name": {}, ..], ..},
|
||||
# }
|
||||
# results_summary example: {
|
||||
# "contacted": {"hostname",...},
|
||||
# "dark": {"hostname": ["error",...],},
|
||||
# "dark": {"hostname": [{"task_name": "error"},...],},
|
||||
# }
|
||||
self.results_raw = dict(ok={}, failed={}, unreachable={}, skipped={})
|
||||
self.results_summary = dict(contacted=set(), dark={})
|
||||
super().__init__(display)
|
||||
|
||||
def gather_result(self, t, host, res):
|
||||
if self.results_raw[t].get(host):
|
||||
self.results_raw[t][host].append(res)
|
||||
else:
|
||||
self.results_raw[t][host] = [res]
|
||||
self.clean_result(t, host, res)
|
||||
def gather_result(self, t, res):
|
||||
host = res._host.get_name()
|
||||
task_name = res.task_name
|
||||
task_result = res._result
|
||||
|
||||
def clean_result(self, t, host, res):
|
||||
if self.results_raw[t].get(host):
|
||||
self.results_raw[t][host].append({task_name: task_result})
|
||||
else:
|
||||
self.results_raw[t][host] = [{task_name: task_result}]
|
||||
self.clean_result(t, host, task_name, task_result)
|
||||
|
||||
def clean_result(self, t, host, task_name, task_result):
|
||||
contacted = self.results_summary["contacted"]
|
||||
dark = self.results_summary["dark"]
|
||||
if t in ("ok", "skipped") and host not in dark:
|
||||
contacted.add(host)
|
||||
else:
|
||||
dark[host].append(res)
|
||||
if dark.get(host):
|
||||
dark[host].append({task_name: task_result})
|
||||
else:
|
||||
dark[host] = [{task_name: task_result}]
|
||||
if host in contacted:
|
||||
contacted.remove(dark)
|
||||
|
||||
def runner_on_ok(self, host, res):
|
||||
self.gather_result("ok", host, res)
|
||||
def v2_runner_on_failed(self, result, ignore_errors=False):
|
||||
self.gather_result("failed", result)
|
||||
|
||||
def runner_on_failed(self, host, res, ignore_errors=False):
|
||||
self.gather_result("failed", host, res)
|
||||
def v2_runner_on_ok(self, result):
|
||||
self.gather_result("ok", result)
|
||||
|
||||
def runner_on_unreachable(self, host, res):
|
||||
self.gather_result("unreachable", host, res)
|
||||
def v2_runner_on_skipped(self, result):
|
||||
self.gather_result("skipped", result)
|
||||
|
||||
def runner_on_skipped(self, host, item=None):
|
||||
self.gather_result("skipped", host, item)
|
||||
def v2_runner_on_unreachable(self, result):
|
||||
self.gather_result("unreachable", result)
|
||||
|
||||
|
||||
class CommandResultCallback(AdHocResultCallback):
|
||||
"""
|
||||
Command result callback
|
||||
"""
|
||||
def __init__(self, display=None):
|
||||
# results_command: {
|
||||
# "cmd": "",
|
||||
# "stderr": "",
|
||||
# "stdout": "",
|
||||
# "rc": 0,
|
||||
# "delta": 0:0:0.123
|
||||
# }
|
||||
#
|
||||
self.results_command = dict()
|
||||
super().__init__(display)
|
||||
|
||||
def gather_result(self, t, host, res):
|
||||
super().gather_result(t, host, res)
|
||||
self.gather_cmd(t, host, res)
|
||||
def gather_result(self, t, res):
|
||||
super().gather_result(t, res)
|
||||
self.gather_cmd(t, res)
|
||||
|
||||
def gather_cmd(self, t, host, res):
|
||||
def gather_cmd(self, t, res):
|
||||
host = res._host.get_name()
|
||||
cmd = {}
|
||||
if t == "ok":
|
||||
cmd['cmd'] = res.get('cmd')
|
||||
cmd['stderr'] = res.get('stderr')
|
||||
cmd['stdout'] = res.get('stdout')
|
||||
cmd['rc'] = res.get('rc')
|
||||
cmd['cmd'] = res._result.get('cmd')
|
||||
cmd['stderr'] = res._result.get('stderr')
|
||||
cmd['stdout'] = res._result.get('stdout')
|
||||
cmd['rc'] = res._result.get('rc')
|
||||
cmd['delta'] = res._result.get('delta')
|
||||
else:
|
||||
cmd['err'] = "Error: {}".format(res)
|
||||
self.results_command[host] = cmd
|
||||
|
|
|
@ -170,6 +170,10 @@ class AdHocRunner:
|
|||
"pattern: %s dose not match any hosts." % pattern
|
||||
)
|
||||
|
||||
def set_option(self, k, v):
|
||||
kwargs = {k: v}
|
||||
self.options = self.options._replace(**kwargs)
|
||||
|
||||
def run(self, tasks, pattern, play_name='Ansible Ad-hoc', gather_facts='no'):
|
||||
"""
|
||||
:param tasks: [{'action': {'module': 'shell', 'args': 'ls'}, ...}, ]
|
||||
|
|
|
@ -24,8 +24,8 @@ class TestAdHocRunner(unittest.TestCase):
|
|||
|
||||
def test_run(self):
|
||||
tasks = [
|
||||
{"action": {"module": "shell", "args": "ls"}},
|
||||
{"action": {"module": "shell", "args": "whoami"}},
|
||||
{"action": {"module": "shell", "args": "ls"}, "name": "run_cmd"},
|
||||
{"action": {"module": "shell", "args": "whoami"}, "name": "run_whoami"},
|
||||
]
|
||||
ret = self.runner.run(tasks, "all")
|
||||
print(ret.results_summary)
|
||||
|
@ -48,6 +48,7 @@ class TestCommandRunner(unittest.TestCase):
|
|||
def test_execute(self):
|
||||
res = self.runner.execute('ls', 'all')
|
||||
print(res.results_command)
|
||||
print(res.results_raw)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
from rest_framework import viewsets
|
||||
|
||||
from .hands import IsSuperUser
|
||||
from .models import Playbook
|
||||
from .models import AdHoc
|
||||
from .serializers import TaskSerializer
|
||||
|
||||
|
||||
class TaskViewSet(viewsets.ModelViewSet):
|
||||
queryset = Playbook.objects.all()
|
||||
queryset = AdHoc.objects.all()
|
||||
serializer_class = TaskSerializer
|
||||
permission_classes = (IsSuperUser,)
|
||||
|
||||
|
|
|
@ -1,56 +1,76 @@
|
|||
# ~*~ coding: utf-8 ~*~
|
||||
|
||||
import logging
|
||||
from collections import OrderedDict
|
||||
import json
|
||||
import uuid
|
||||
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
__all__ = ["Playbook"]
|
||||
__all__ = ["AdHoc", "History"]
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AdHoc(models.Model):
|
||||
uuid = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
||||
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
||||
name = models.CharField(max_length=128, blank=True, verbose_name=_('Name'))
|
||||
tasks = models.TextField(verbose_name=_('Tasks')) # [{'name': 'task_name', 'module': '', 'args': ''}, ]
|
||||
hosts = models.TextField(blank=True, null=True, verbose_name=_('Hosts')) # Asset inventory may be change
|
||||
pattern = models.CharField(max_length=64, default='all', verbose_name=_('Playbook run pattern'))
|
||||
|
||||
@property
|
||||
def short_id(self):
|
||||
return str(self.id).split('-')[-1]
|
||||
|
||||
def __str__(self):
|
||||
return "%s" % self.name
|
||||
return self.name
|
||||
|
||||
def get_hosts_mapped_assets(self):
|
||||
from assets.utils import get_assets_by_id_list
|
||||
assets_id = [i for i in self.hosts.split(',')]
|
||||
assets = get_assets_by_id_list(assets_id)
|
||||
return assets
|
||||
|
||||
class AdHocData(models.Model):
|
||||
BECOME_METHOD_CHOICES = (
|
||||
('sudo', 'sudo'),
|
||||
('su', 'su'),
|
||||
)
|
||||
version = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
||||
subject = models.ForeignKey(AdHoc, on_delete=models.CASCADE)
|
||||
_tasks = models.TextField(verbose_name=_('Tasks')) # [{'name': 'task_name', 'action': {'module': '', 'args': ''}, 'other..': ''}, ]
|
||||
_hosts = models.TextField(blank=True, verbose_name=_('Hosts')) # ['hostname1', 'hostname2']
|
||||
run_as_admin = models.BooleanField(default=False, verbose_name=_('Run as admin'))
|
||||
run_as = models.CharField(max_length=128, verbose_name=_("Run as"))
|
||||
become = models.BooleanField(default=False, verbose_name=_("Become"))
|
||||
become_method = models.CharField(choices=BECOME_METHOD_CHOICES, default='sudo', max_length=4)
|
||||
become_user = models.CharField(default='root', max_length=64)
|
||||
become_pass = models.CharField(default='', max_length=128)
|
||||
pattern = models.CharField(max_length=64, default='', verbose_name=_('Pattern'))
|
||||
created_by = models.CharField(max_length=64, verbose_name=_('Create by'))
|
||||
date_created = models.DateTimeField(auto_created=True)
|
||||
|
||||
@property
|
||||
def inventory(self):
|
||||
return [asset._to_secret_json() for asset in self.get_hosts_mapped_assets()]
|
||||
def tasks(self):
|
||||
return json.loads(self._tasks)
|
||||
|
||||
@tasks.setter
|
||||
def tasks(self, item):
|
||||
self._tasks = json.dumps(item)
|
||||
|
||||
@property
|
||||
def module_args(self):
|
||||
task_tuple = []
|
||||
for module, args in json.loads(self._modules_args, object_pairs_hook=OrderedDict).items():
|
||||
task_tuple.append((module, args))
|
||||
return task_tuple
|
||||
def hosts(self):
|
||||
return json.loads(self._hosts)
|
||||
|
||||
@module_args.setter
|
||||
def module_args(self, task_tuple):
|
||||
module_args_ = OrderedDict({})
|
||||
for module, args in task_tuple:
|
||||
module_args_[module] = args
|
||||
self._modules_args = json.dumps(module_args_)
|
||||
@hosts.setter
|
||||
def hosts(self, item):
|
||||
self._hosts = json.dumps(item)
|
||||
|
||||
@property
|
||||
def short_version(self):
|
||||
return str(self.version).split('-')[-1]
|
||||
|
||||
def __str__(self):
|
||||
return "{} of {}".format(self.subject.name, self.short_version)
|
||||
|
||||
|
||||
class History(models.Model):
|
||||
class AdHocHistory(models.Model):
|
||||
uuid = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
||||
adhoc = models.ForeignKey(AdHocData, on_delete=models.CASCADE)
|
||||
date_start = models.DateTimeField(auto_now_add=True, verbose_name=_('Start time'))
|
||||
date_finished = models.DateTimeField(blank=True, null=True, verbose_name=_('End time'))
|
||||
timedelta = models.FloatField(default=0.0, verbose_name=_('Time'), null=True)
|
||||
|
@ -58,3 +78,10 @@ class History(models.Model):
|
|||
is_success = models.BooleanField(default=False, verbose_name=_('Is success'))
|
||||
result = models.TextField(blank=True, null=True, verbose_name=_('Playbook raw result'))
|
||||
summary = models.TextField(blank=True, null=True, verbose_name=_('Playbook summary'))
|
||||
|
||||
@property
|
||||
def short_id(self):
|
||||
return str(self.id).split('-')[-1]
|
||||
|
||||
def __str__(self):
|
||||
return self.short_id
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
from __future__ import unicode_literals
|
||||
from rest_framework import serializers
|
||||
|
||||
from .models import Playbook
|
||||
from .models import AdHoc
|
||||
|
||||
|
||||
class TaskSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Playbook
|
||||
model = AdHoc
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
|
|
|
@ -88,3 +88,14 @@ def is_uuid(s):
|
|||
else:
|
||||
return False
|
||||
|
||||
|
||||
def asset_to_dict(asset):
|
||||
return asset.to_json()
|
||||
|
||||
|
||||
def asset_to_dict_with_credential(asset):
|
||||
return asset._to_secret_json()
|
||||
|
||||
|
||||
def system_user_to_dict_with_credential(system_user):
|
||||
return system_user._to_secret_json()
|
||||
|
|
|
@ -9,13 +9,13 @@ from django.views.generic import ListView, DetailView, View
|
|||
from django.utils import timezone
|
||||
from django.shortcuts import redirect, reverse
|
||||
|
||||
from .models import Playbook
|
||||
from .models import AdHoc, AdHocData, AdHocHistory
|
||||
from ops.tasks import rerun_task
|
||||
|
||||
|
||||
class TaskListView(ListView):
|
||||
paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
|
||||
model = Playbook
|
||||
model = AdHoc
|
||||
ordering = ('-date_start',)
|
||||
context_object_name = 'task_list'
|
||||
template_name = 'ops/task_list.html'
|
||||
|
@ -63,7 +63,7 @@ class TaskListView(ListView):
|
|||
|
||||
|
||||
class TaskDetailView(DetailView):
|
||||
model = Playbook
|
||||
model = AdHocHistory
|
||||
template_name = 'ops/task_detail.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
|
|
@ -53,79 +53,6 @@ def get_user_group_granted_assets(user_group):
|
|||
return assets
|
||||
|
||||
|
||||
# def get_user_granted_asset_groups_direct(user):
|
||||
# """Return asset groups granted of the user direct nor inherit from user group
|
||||
#
|
||||
# :param user: Instance of :class: ``User``
|
||||
# :return: {asset_group: {system_user1, },
|
||||
# asset_group2: {system_user1, system_user2]}
|
||||
# """
|
||||
# asset_groups = {}
|
||||
# asset_permissions_direct = user.asset_permissions.all()
|
||||
#
|
||||
# for asset_permission in asset_permissions_direct:
|
||||
# if not asset_permission.is_valid:
|
||||
# continue
|
||||
# for asset_group in asset_permission.asset_groups.all():
|
||||
# if asset_group in asset_groups:
|
||||
# asset_groups[asset_group] |= set(asset_permission.system_users.all())
|
||||
# else:
|
||||
# setattr(asset_group, 'inherited', False)
|
||||
# asset_groups[asset_group] = set(asset_permission.system_users.all())
|
||||
#
|
||||
# return asset_groups
|
||||
|
||||
|
||||
# def get_user_granted_asset_groups_inherit_from_user_groups(user):
|
||||
# """Return asset groups granted of the user and inherit from user group
|
||||
#
|
||||
# :param user: Instance of :class: ``User``
|
||||
# :return: {asset_group: {system_user1, },
|
||||
# asset_group2: {system_user1, system_user2]}
|
||||
# """
|
||||
# asset_groups = {}
|
||||
# user_groups = user.groups.all()
|
||||
# asset_permissions = set()
|
||||
#
|
||||
# # Get asset permission list of user groups for this user
|
||||
# for user_group in user_groups:
|
||||
# asset_permissions |= set(user_group.asset_permissions.all())
|
||||
#
|
||||
# # Get asset groups granted from user groups
|
||||
# for asset_permission in asset_permissions:
|
||||
# if not asset_permission.is_valid:
|
||||
# continue
|
||||
# for asset_group in asset_permission.asset_groups.all():
|
||||
# if asset_group in asset_groups:
|
||||
# asset_groups[asset_group] |= set(asset_permission.system_users.all())
|
||||
# else:
|
||||
# setattr(asset_group, 'inherited', True)
|
||||
# asset_groups[asset_group] = set(asset_permission.system_users.all())
|
||||
#
|
||||
# return asset_groups
|
||||
|
||||
|
||||
# def get_user_granted_asset_groups(user):
|
||||
# """Get user granted asset groups all, include direct and inherit from user group
|
||||
#
|
||||
# :param user: Instance of :class: ``User``
|
||||
# :return: {asset_group1: {system_user1, system_user2}, asset_group2: {...}}
|
||||
# """
|
||||
#
|
||||
# asset_groups_inherit_from_user_groups = \
|
||||
# get_user_granted_asset_groups_inherit_from_user_groups(user)
|
||||
# asset_groups_direct = get_user_granted_asset_groups_direct(user)
|
||||
# asset_groups = asset_groups_inherit_from_user_groups
|
||||
#
|
||||
# # Merge direct granted and inherit from user group
|
||||
# for asset_group, system_users in asset_groups_direct.items():
|
||||
# if asset_group in asset_groups:
|
||||
# asset_groups[asset_group] |= asset_groups_direct[asset_group]
|
||||
# else:
|
||||
# asset_groups[asset_group] = asset_groups_direct[asset_group]
|
||||
# return asset_groups
|
||||
|
||||
|
||||
def get_user_granted_assets_direct(user):
|
||||
"""Return assets granted of the user directly
|
||||
|
||||
|
@ -225,6 +152,22 @@ def get_user_asset_permissions(user):
|
|||
return direct_permissions | user_group_permissions
|
||||
|
||||
|
||||
def get_user_granted_system_users(user):
|
||||
"""
|
||||
:param user: the user
|
||||
:return: {"system_user": ["asset", "asset1"], "system_user": []}
|
||||
"""
|
||||
assets = get_user_granted_assets(user)
|
||||
system_users_dict = {}
|
||||
for asset, system_users in assets.items():
|
||||
for system_user in system_users:
|
||||
if system_user in system_users_dict:
|
||||
system_users_dict[system_user].append(asset)
|
||||
else:
|
||||
system_users_dict[system_user] = [asset]
|
||||
return system_users_dict
|
||||
|
||||
|
||||
def get_user_groups_granted_in_asset(asset):
|
||||
pass
|
||||
|
||||
|
|
Loading…
Reference in New Issue