Merge pull request #534 from cchurch/django18

Django 1.8 and DRF 3.3 Support
This commit is contained in:
Wayne Witzel III
2016-02-04 14:28:44 -05:00
139 changed files with 2756 additions and 1425 deletions

View File

@@ -684,7 +684,7 @@ class ProjectAccess(BaseAccess):
def get_queryset(self):
qs = Project.objects.filter(active=True).distinct()
qs = qs.select_related('modified_by', 'credential', 'current_update', 'last_update')
qs = qs.select_related('modified_by', 'credential', 'current_job', 'last_job')
if self.user.is_superuser:
return qs
team_ids = set(Team.objects.filter(users__in=[self.user]).values_list('id', flat=True))
@@ -1280,7 +1280,7 @@ class AdHocCommandEventAccess(BaseAccess):
def get_queryset(self):
qs = self.model.objects.distinct()
qs = qs.select_related('created_by', 'modified_by', 'ad_hoc_command', 'host')
qs = qs.select_related('ad_hoc_command', 'host')
if self.user.is_superuser:
return qs
@@ -1308,8 +1308,7 @@ class JobHostSummaryAccess(BaseAccess):
def get_queryset(self):
qs = self.model.objects.distinct()
qs = qs.select_related('created_by', 'modified_by', 'job', 'job__job_template',
'host')
qs = qs.select_related('job', 'job__job_template', 'host')
if self.user.is_superuser:
return qs
job_qs = self.user.get_queryset(Job)
@@ -1334,8 +1333,7 @@ class JobEventAccess(BaseAccess):
def get_queryset(self):
qs = self.model.objects.distinct()
qs = qs.select_related('created_by', 'modified_by', 'job', 'job__job_template',
'host', 'parent')
qs = qs.select_related('job', 'job__job_template', 'host', 'parent')
qs = qs.prefetch_related('hosts', 'children')
# Filter certain "internal" events generated by async polling.
@@ -1495,7 +1493,6 @@ class ActivityStreamAccess(BaseAccess):
def get_queryset(self):
qs = self.model.objects.distinct()
#qs = qs.select_related('created_by')
qs = qs.select_related('actor')
qs = qs.prefetch_related('organization', 'user', 'inventory', 'host', 'group', 'inventory_source',
'inventory_update', 'credential', 'team', 'project', 'project_update',

View File

@@ -37,16 +37,14 @@ class TowerConfiguration(object):
if key not in settings_manifest:
raise AttributeError("Tower Setting with key '{0}' does not exist".format(key))
settings_entry = settings_manifest[key]
settings_actual = TowerSettings.objects.filter(key=key)
if not settings_actual.exists():
try:
settings_actual = TowerSettings.objects.get(key=key)
except TowerSettings.DoesNotExist:
settings_actual = TowerSettings(key=key,
description=settings_entry['description'],
category=settings_entry['category'],
value=value,
value_type=settings_entry['type'])
else:
settings_actual = settings_actual[0]
settings_actual.value = value
settings_actual.value_converted = value
settings_actual.save()
tower_settings = TowerConfiguration()

View File

@@ -5,9 +5,6 @@
from django.db import models
from django.db.models.fields.related import SingleRelatedObjectDescriptor
# South
from south.modelsinspector import add_introspection_rules
__all__ = ['AutoOneToOneField']
# Based on AutoOneToOneField from django-annoying:
@@ -20,8 +17,8 @@ class AutoSingleRelatedObjectDescriptor(SingleRelatedObjectDescriptor):
try:
return super(AutoSingleRelatedObjectDescriptor,
self).__get__(instance, instance_type)
except self.related.model.DoesNotExist:
obj = self.related.model(**{self.related.field.name: instance})
except self.related.related_model.DoesNotExist:
obj = self.related.related_model(**{self.related.field.name: instance})
if self.related.field.rel.parent_link:
raise NotImplementedError('not supported with polymorphic!')
for f in instance._meta.local_fields:
@@ -35,6 +32,3 @@ class AutoOneToOneField(models.OneToOneField):
def contribute_to_related_class(self, cls, related):
setattr(cls, related.get_accessor_name(),
AutoSingleRelatedObjectDescriptor(related))
add_introspection_rules([([AutoOneToOneField], [], {})],
[r'^awx\.main\.fields\.AutoOneToOneField'])

View File

@@ -1110,13 +1110,14 @@ class Command(NoArgsCommand):
for db_group in self.inventory.groups.filter(name__in=group_names):
mem_group = self.all_group.all_groups[db_group.name]
group_group_count += len(mem_group.children)
child_names = set([g.name for g in mem_group.children])
db_children_qs = self.inventory.groups.filter(name__in=child_names)
# FIXME: May fail unit tests when len(child_names) > 1000.
for db_child in db_children_qs.filter(children__id=db_group.id):
self.logger.info('Group "%s" already child of group "%s"', db_child.name, db_group.name)
for db_child in db_children_qs.exclude(children__id=db_group.id):
self._batch_add_m2m(db_group.children, db_child)
all_child_names = sorted([g.name for g in mem_group.children])
for offset2 in xrange(0, len(all_child_names), self._batch_size):
child_names = all_child_names[offset2:(offset2 + self._batch_size)]
db_children_qs = self.inventory.groups.filter(name__in=child_names)
for db_child in db_children_qs.filter(children__id=db_group.id):
self.logger.info('Group "%s" already child of group "%s"', db_child.name, db_group.name)
for db_child in db_children_qs.exclude(children__id=db_group.id):
self._batch_add_m2m(db_group.children, db_child)
self.logger.info('Group "%s" added as child of "%s"', db_child.name, db_group.name)
self._batch_add_m2m(db_group.children, flush=True)
if settings.SQL_DEBUG:

View File

@@ -16,7 +16,7 @@ from django.conf import settings
from django.core.management.base import NoArgsCommand
from django.db import transaction, DatabaseError
from django.utils.dateparse import parse_datetime
from django.utils.tzinfo import FixedOffset
from django.utils.timezone import FixedOffset
from django.db import connection
# AWX

View File

@@ -13,7 +13,7 @@ class HostManager(models.Manager):
def active_count(self):
"""Return count of active, unique hosts for licensing."""
try:
return self.filter(active=True, inventory__active=True).distinct('name').count()
return self.filter(active=True, inventory__active=True).order_by('name').distinct('name').count()
except NotImplementedError: # For unit tests only, SQLite doesn't support distinct('name')
return len(set(self.filter(active=True, inventory__active=True).values_list('name', flat=True)))

View File

@@ -0,0 +1,991 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2016 Ansible, Inc.
# All Rights Reserved.
from __future__ import unicode_literals
from django.db import migrations, models
import django.utils.timezone
import jsonfield.fields
import django.db.models.deletion
from django.conf import settings
import taggit.managers
import awx.main.fields
class Migration(migrations.Migration):
dependencies = [
('taggit', '0002_auto_20150616_2121'),
('contenttypes', '0002_remove_content_type_name'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='ActivityStream',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('operation', models.CharField(max_length=13, choices=[(b'create', 'Entity Created'), (b'update', 'Entity Updated'), (b'delete', 'Entity Deleted'), (b'associate', 'Entity Associated with another Entity'), (b'disassociate', 'Entity was Disassociated with another Entity')])),
('timestamp', models.DateTimeField(auto_now_add=True)),
('changes', models.TextField(blank=True)),
('object_relationship_type', models.TextField(blank=True)),
('object1', models.TextField()),
('object2', models.TextField()),
('actor', models.ForeignKey(related_name='activity_stream', on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, null=True)),
],
),
migrations.CreateModel(
name='AdHocCommandEvent',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('created', models.DateTimeField(default=None, editable=False)),
('modified', models.DateTimeField(default=None, editable=False)),
('host_name', models.CharField(default=b'', max_length=1024, editable=False)),
('event', models.CharField(max_length=100, choices=[(b'runner_on_failed', 'Host Failed'), (b'runner_on_ok', 'Host OK'), (b'runner_on_unreachable', 'Host Unreachable')])),
('event_data', jsonfield.fields.JSONField(default={}, blank=True)),
('failed', models.BooleanField(default=False, editable=False)),
('changed', models.BooleanField(default=False, editable=False)),
('counter', models.PositiveIntegerField(default=0)),
],
options={
'ordering': ('-pk',),
},
),
migrations.CreateModel(
name='AuthToken',
fields=[
('key', models.CharField(max_length=40, serialize=False, primary_key=True)),
('created', models.DateTimeField(auto_now_add=True)),
('modified', models.DateTimeField(auto_now=True)),
('expires', models.DateTimeField(default=django.utils.timezone.now)),
('request_hash', models.CharField(default=b'', max_length=40, blank=True)),
('reason', models.CharField(default=b'', help_text='Reason the auth token was invalidated.', max_length=1024, blank=True)),
('user', models.ForeignKey(related_name='auth_tokens', to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='Credential',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('created', models.DateTimeField(default=None, editable=False)),
('modified', models.DateTimeField(default=None, editable=False)),
('description', models.TextField(default=b'', blank=True)),
('active', models.BooleanField(default=True, editable=False)),
('name', models.CharField(max_length=512)),
('kind', models.CharField(default=b'ssh', max_length=32, choices=[(b'ssh', 'Machine'), (b'scm', 'Source Control'), (b'aws', 'Amazon Web Services'), (b'rax', 'Rackspace'), (b'vmware', 'VMware vCenter'), (b'gce', 'Google Compute Engine'), (b'azure', 'Microsoft Azure'), (b'openstack', 'OpenStack')])),
('cloud', models.BooleanField(default=False, editable=False)),
('host', models.CharField(default=b'', help_text='The hostname or IP address to use.', max_length=1024, verbose_name='Host', blank=True)),
('username', models.CharField(default=b'', help_text='Username for this credential.', max_length=1024, verbose_name='Username', blank=True)),
('password', models.CharField(default=b'', help_text='Password for this credential (or "ASK" to prompt the user for machine credentials).', max_length=1024, verbose_name='Password', blank=True)),
('security_token', models.CharField(default=b'', help_text='Security Token for this credential', max_length=1024, verbose_name='Security Token', blank=True)),
('project', models.CharField(default=b'', help_text='The identifier for the project.', max_length=100, verbose_name='Project', blank=True)),
('ssh_key_data', models.TextField(default=b'', help_text='RSA or DSA private key to be used instead of password.', verbose_name='SSH private key', blank=True)),
('ssh_key_unlock', models.CharField(default=b'', help_text='Passphrase to unlock SSH private key if encrypted (or "ASK" to prompt the user for machine credentials).', max_length=1024, verbose_name='SSH key unlock', blank=True)),
('become_method', models.CharField(default=b'', help_text='Privilege escalation method.', max_length=32, blank=True, choices=[(b'', 'None'), (b'sudo', 'Sudo'), (b'su', 'Su'), (b'pbrun', 'Pbrun'), (b'pfexec', 'Pfexec')])),
('become_username', models.CharField(default=b'', help_text='Privilege escalation username.', max_length=1024, blank=True)),
('become_password', models.CharField(default=b'', help_text='Password for privilege escalation method.', max_length=1024, blank=True)),
('vault_password', models.CharField(default=b'', help_text='Vault password (or "ASK" to prompt the user).', max_length=1024, blank=True)),
('created_by', models.ForeignKey(related_name="{u'class': 'credential', u'app_label': 'main'}(class)s_created+", on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True)),
('modified_by', models.ForeignKey(related_name="{u'class': 'credential', u'app_label': 'main'}(class)s_modified+", on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True)),
('tags', taggit.managers.TaggableManager(to='taggit.Tag', through='taggit.TaggedItem', blank=True, help_text='A comma-separated list of tags.', verbose_name='Tags')),
],
options={
'ordering': ('kind', 'name'),
},
),
migrations.CreateModel(
name='CustomInventoryScript',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('created', models.DateTimeField(default=None, editable=False)),
('modified', models.DateTimeField(default=None, editable=False)),
('description', models.TextField(default=b'', blank=True)),
('active', models.BooleanField(default=True, editable=False)),
('name', models.CharField(max_length=512)),
('script', models.TextField(default=b'', help_text='Inventory script contents', blank=True)),
('created_by', models.ForeignKey(related_name="{u'class': 'custominventoryscript', u'app_label': 'main'}(class)s_created+", on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True)),
('modified_by', models.ForeignKey(related_name="{u'class': 'custominventoryscript', u'app_label': 'main'}(class)s_modified+", on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True)),
],
options={
'ordering': ('name',),
},
),
migrations.CreateModel(
name='Group',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('created', models.DateTimeField(default=None, editable=False)),
('modified', models.DateTimeField(default=None, editable=False)),
('description', models.TextField(default=b'', blank=True)),
('active', models.BooleanField(default=True, editable=False)),
('name', models.CharField(max_length=512)),
('variables', models.TextField(default=b'', help_text='Group variables in JSON or YAML format.', blank=True)),
('total_hosts', models.PositiveIntegerField(default=0, help_text='Total number of hosts directly or indirectly in this group.', editable=False)),
('has_active_failures', models.BooleanField(default=False, help_text='Flag indicating whether this group has any hosts with active failures.', editable=False)),
('hosts_with_active_failures', models.PositiveIntegerField(default=0, help_text='Number of hosts in this group with active failures.', editable=False)),
('total_groups', models.PositiveIntegerField(default=0, help_text='Total number of child groups contained within this group.', editable=False)),
('groups_with_active_failures', models.PositiveIntegerField(default=0, help_text='Number of child groups within this group that have active failures.', editable=False)),
('has_inventory_sources', models.BooleanField(default=False, help_text='Flag indicating whether this group was created/updated from any external inventory sources.', editable=False)),
('created_by', models.ForeignKey(related_name="{u'class': 'group', u'app_label': 'main'}(class)s_created+", on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True)),
],
options={
'ordering': ('name',),
},
),
migrations.CreateModel(
name='Host',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('created', models.DateTimeField(default=None, editable=False)),
('modified', models.DateTimeField(default=None, editable=False)),
('description', models.TextField(default=b'', blank=True)),
('active', models.BooleanField(default=True, editable=False)),
('name', models.CharField(max_length=512)),
('enabled', models.BooleanField(default=True, help_text='Is this host online and available for running jobs?')),
('instance_id', models.CharField(default=b'', max_length=100, blank=True)),
('variables', models.TextField(default=b'', help_text='Host variables in JSON or YAML format.', blank=True)),
('has_active_failures', models.BooleanField(default=False, help_text='Flag indicating whether the last job failed for this host.', editable=False)),
('has_inventory_sources', models.BooleanField(default=False, help_text='Flag indicating whether this host was created/updated from any external inventory sources.', editable=False)),
('created_by', models.ForeignKey(related_name="{u'class': 'host', u'app_label': 'main'}(class)s_created+", on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True)),
],
options={
'ordering': ('inventory', 'name'),
},
),
migrations.CreateModel(
name='Instance',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('uuid', models.CharField(unique=True, max_length=40)),
('hostname', models.CharField(unique=True, max_length=250)),
('primary', models.BooleanField(default=False)),
('created', models.DateTimeField(auto_now_add=True)),
('modified', models.DateTimeField(auto_now=True)),
],
),
migrations.CreateModel(
name='Inventory',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('created', models.DateTimeField(default=None, editable=False)),
('modified', models.DateTimeField(default=None, editable=False)),
('description', models.TextField(default=b'', blank=True)),
('active', models.BooleanField(default=True, editable=False)),
('name', models.CharField(unique=True, max_length=512)),
('variables', models.TextField(default=b'', help_text='Inventory variables in JSON or YAML format.', blank=True)),
('has_active_failures', models.BooleanField(default=False, help_text='Flag indicating whether any hosts in this inventory have failed.', editable=False)),
('total_hosts', models.PositiveIntegerField(default=0, help_text='Total number of hosts in this inventory.', editable=False)),
('hosts_with_active_failures', models.PositiveIntegerField(default=0, help_text='Number of hosts in this inventory with active failures.', editable=False)),
('total_groups', models.PositiveIntegerField(default=0, help_text='Total number of groups in this inventory.', editable=False)),
('groups_with_active_failures', models.PositiveIntegerField(default=0, help_text='Number of groups in this inventory with active failures.', editable=False)),
('has_inventory_sources', models.BooleanField(default=False, help_text='Flag indicating whether this inventory has any external inventory sources.', editable=False)),
('total_inventory_sources', models.PositiveIntegerField(default=0, help_text='Total number of external inventory sources configured within this inventory.', editable=False)),
('inventory_sources_with_failures', models.PositiveIntegerField(default=0, help_text='Number of external inventory sources in this inventory with failures.', editable=False)),
('created_by', models.ForeignKey(related_name="{u'class': 'inventory', u'app_label': 'main'}(class)s_created+", on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True)),
('modified_by', models.ForeignKey(related_name="{u'class': 'inventory', u'app_label': 'main'}(class)s_modified+", on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True)),
],
options={
'ordering': ('name',),
'verbose_name_plural': 'inventories',
},
),
migrations.CreateModel(
name='JobEvent',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('created', models.DateTimeField(default=None, editable=False)),
('modified', models.DateTimeField(default=None, editable=False)),
('event', models.CharField(max_length=100, choices=[(b'runner_on_failed', 'Host Failed'), (b'runner_on_ok', 'Host OK'), (b'runner_on_error', 'Host Failure'), (b'runner_on_skipped', 'Host Skipped'), (b'runner_on_unreachable', 'Host Unreachable'), (b'runner_on_no_hosts', 'No Hosts Remaining'), (b'runner_on_async_poll', 'Host Polling'), (b'runner_on_async_ok', 'Host Async OK'), (b'runner_on_async_failed', 'Host Async Failure'), (b'runner_on_file_diff', 'File Difference'), (b'playbook_on_start', 'Playbook Started'), (b'playbook_on_notify', 'Running Handlers'), (b'playbook_on_no_hosts_matched', 'No Hosts Matched'), (b'playbook_on_no_hosts_remaining', 'No Hosts Remaining'), (b'playbook_on_task_start', 'Task Started'), (b'playbook_on_vars_prompt', 'Variables Prompted'), (b'playbook_on_setup', 'Gathering Facts'), (b'playbook_on_import_for_host', 'internal: on Import for Host'), (b'playbook_on_not_import_for_host', 'internal: on Not Import for Host'), (b'playbook_on_play_start', 'Play Started'), (b'playbook_on_stats', 'Playbook Complete')])),
('event_data', jsonfield.fields.JSONField(default={}, blank=True)),
('failed', models.BooleanField(default=False, editable=False)),
('changed', models.BooleanField(default=False, editable=False)),
('host_name', models.CharField(default=b'', max_length=1024, editable=False)),
('play', models.CharField(default=b'', max_length=1024, editable=False)),
('role', models.CharField(default=b'', max_length=1024, editable=False)),
('task', models.CharField(default=b'', max_length=1024, editable=False)),
('counter', models.PositiveIntegerField(default=0)),
('host', models.ForeignKey(related_name='job_events_as_primary_host', on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to='main.Host', null=True)),
('hosts', models.ManyToManyField(related_name='job_events', editable=False, to='main.Host')),
('parent', models.ForeignKey(related_name='children', on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to='main.JobEvent', null=True)),
],
options={
'ordering': ('pk',),
},
),
migrations.CreateModel(
name='JobHostSummary',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('created', models.DateTimeField(default=None, editable=False)),
('modified', models.DateTimeField(default=None, editable=False)),
('host_name', models.CharField(default=b'', max_length=1024, editable=False)),
('changed', models.PositiveIntegerField(default=0, editable=False)),
('dark', models.PositiveIntegerField(default=0, editable=False)),
('failures', models.PositiveIntegerField(default=0, editable=False)),
('ok', models.PositiveIntegerField(default=0, editable=False)),
('processed', models.PositiveIntegerField(default=0, editable=False)),
('skipped', models.PositiveIntegerField(default=0, editable=False)),
('failed', models.BooleanField(default=False, editable=False)),
('host', models.ForeignKey(related_name='job_host_summaries', on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to='main.Host', null=True)),
],
options={
'ordering': ('-pk',),
'verbose_name_plural': 'job host summaries',
},
),
migrations.CreateModel(
name='JobOrigin',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('created', models.DateTimeField(auto_now_add=True)),
('modified', models.DateTimeField(auto_now=True)),
('instance', models.ForeignKey(to='main.Instance')),
],
),
migrations.CreateModel(
name='Organization',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('created', models.DateTimeField(default=None, editable=False)),
('modified', models.DateTimeField(default=None, editable=False)),
('description', models.TextField(default=b'', blank=True)),
('active', models.BooleanField(default=True, editable=False)),
('name', models.CharField(unique=True, max_length=512)),
('admins', models.ManyToManyField(related_name='admin_of_organizations', to=settings.AUTH_USER_MODEL, blank=True)),
('created_by', models.ForeignKey(related_name="{u'class': 'organization', u'app_label': 'main'}(class)s_created+", on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True)),
('modified_by', models.ForeignKey(related_name="{u'class': 'organization', u'app_label': 'main'}(class)s_modified+", on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True)),
('tags', taggit.managers.TaggableManager(to='taggit.Tag', through='taggit.TaggedItem', blank=True, help_text='A comma-separated list of tags.', verbose_name='Tags')),
('users', models.ManyToManyField(related_name='organizations', to=settings.AUTH_USER_MODEL, blank=True)),
],
options={
'ordering': ('name',),
},
),
migrations.CreateModel(
name='Permission',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('created', models.DateTimeField(default=None, editable=False)),
('modified', models.DateTimeField(default=None, editable=False)),
('description', models.TextField(default=b'', blank=True)),
('active', models.BooleanField(default=True, editable=False)),
('name', models.CharField(max_length=512)),
('permission_type', models.CharField(max_length=64, choices=[(b'read', 'Read Inventory'), (b'write', 'Edit Inventory'), (b'admin', 'Administrate Inventory'), (b'run', 'Deploy To Inventory'), (b'check', 'Deploy To Inventory (Dry Run)'), (b'scan', 'Scan an Inventory'), (b'create', 'Create a Job Template')])),
('run_ad_hoc_commands', models.BooleanField(default=False, help_text='Execute Commands on the Inventory')),
('created_by', models.ForeignKey(related_name="{u'class': 'permission', u'app_label': 'main'}(class)s_created+", on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True)),
('inventory', models.ForeignKey(related_name='permissions', on_delete=django.db.models.deletion.SET_NULL, to='main.Inventory', null=True)),
('modified_by', models.ForeignKey(related_name="{u'class': 'permission', u'app_label': 'main'}(class)s_modified+", on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True)),
('tags', taggit.managers.TaggableManager(to='taggit.Tag', through='taggit.TaggedItem', blank=True, help_text='A comma-separated list of tags.', verbose_name='Tags')),
],
),
migrations.CreateModel(
name='Profile',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('created', models.DateTimeField(default=None, editable=False)),
('modified', models.DateTimeField(default=None, editable=False)),
('ldap_dn', models.CharField(default=b'', max_length=1024)),
('user', awx.main.fields.AutoOneToOneField(related_name='profile', editable=False, to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='Schedule',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('created', models.DateTimeField(default=None, editable=False)),
('modified', models.DateTimeField(default=None, editable=False)),
('description', models.TextField(default=b'', blank=True)),
('active', models.BooleanField(default=True, editable=False)),
('name', models.CharField(unique=True, max_length=512)),
('enabled', models.BooleanField(default=True)),
('dtstart', models.DateTimeField(default=None, null=True, editable=False)),
('dtend', models.DateTimeField(default=None, null=True, editable=False)),
('rrule', models.CharField(max_length=255)),
('next_run', models.DateTimeField(default=None, null=True, editable=False)),
('extra_data', jsonfield.fields.JSONField(default={}, blank=True)),
('created_by', models.ForeignKey(related_name="{u'class': 'schedule', u'app_label': 'main'}(class)s_created+", on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True)),
('modified_by', models.ForeignKey(related_name="{u'class': 'schedule', u'app_label': 'main'}(class)s_modified+", on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True)),
('tags', taggit.managers.TaggableManager(to='taggit.Tag', through='taggit.TaggedItem', blank=True, help_text='A comma-separated list of tags.', verbose_name='Tags')),
],
options={
'ordering': ['-next_run'],
},
),
migrations.CreateModel(
name='Team',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('created', models.DateTimeField(default=None, editable=False)),
('modified', models.DateTimeField(default=None, editable=False)),
('description', models.TextField(default=b'', blank=True)),
('active', models.BooleanField(default=True, editable=False)),
('name', models.CharField(max_length=512)),
('created_by', models.ForeignKey(related_name="{u'class': 'team', u'app_label': 'main'}(class)s_created+", on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True)),
('modified_by', models.ForeignKey(related_name="{u'class': 'team', u'app_label': 'main'}(class)s_modified+", on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True)),
('organization', models.ForeignKey(related_name='teams', on_delete=django.db.models.deletion.SET_NULL, to='main.Organization', null=True)),
('tags', taggit.managers.TaggableManager(to='taggit.Tag', through='taggit.TaggedItem', blank=True, help_text='A comma-separated list of tags.', verbose_name='Tags')),
('users', models.ManyToManyField(related_name='teams', to=settings.AUTH_USER_MODEL, blank=True)),
],
options={
'ordering': ('organization__name', 'name'),
},
),
migrations.CreateModel(
name='UnifiedJob',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('created', models.DateTimeField(default=None, editable=False)),
('modified', models.DateTimeField(default=None, editable=False)),
('description', models.TextField(default=b'', blank=True)),
('active', models.BooleanField(default=True, editable=False)),
('name', models.CharField(max_length=512)),
('old_pk', models.PositiveIntegerField(default=None, null=True, editable=False)),
('launch_type', models.CharField(default=b'manual', max_length=20, editable=False, choices=[(b'manual', 'Manual'), (b'relaunch', 'Relaunch'), (b'callback', 'Callback'), (b'scheduled', 'Scheduled'), (b'dependency', 'Dependency')])),
('cancel_flag', models.BooleanField(default=False, editable=False)),
('status', models.CharField(default=b'new', max_length=20, editable=False, choices=[(b'new', 'New'), (b'pending', 'Pending'), (b'waiting', 'Waiting'), (b'running', 'Running'), (b'successful', 'Successful'), (b'failed', 'Failed'), (b'error', 'Error'), (b'canceled', 'Canceled')])),
('failed', models.BooleanField(default=False, editable=False)),
('started', models.DateTimeField(default=None, null=True, editable=False)),
('finished', models.DateTimeField(default=None, null=True, editable=False)),
('elapsed', models.DecimalField(editable=False, max_digits=12, decimal_places=3)),
('job_args', models.TextField(default=b'', editable=False, blank=True)),
('job_cwd', models.CharField(default=b'', max_length=1024, editable=False, blank=True)),
('job_env', jsonfield.fields.JSONField(default={}, editable=False, blank=True)),
('job_explanation', models.TextField(default=b'', editable=False, blank=True)),
('start_args', models.TextField(default=b'', editable=False, blank=True)),
('result_stdout_text', models.TextField(default=b'', editable=False, blank=True)),
('result_stdout_file', models.TextField(default=b'', editable=False, blank=True)),
('result_traceback', models.TextField(default=b'', editable=False, blank=True)),
('celery_task_id', models.CharField(default=b'', max_length=100, editable=False, blank=True)),
],
),
migrations.CreateModel(
name='UnifiedJobTemplate',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('created', models.DateTimeField(default=None, editable=False)),
('modified', models.DateTimeField(default=None, editable=False)),
('description', models.TextField(default=b'', blank=True)),
('active', models.BooleanField(default=True, editable=False)),
('name', models.CharField(max_length=512)),
('old_pk', models.PositiveIntegerField(default=None, null=True, editable=False)),
('last_job_failed', models.BooleanField(default=False, editable=False)),
('last_job_run', models.DateTimeField(default=None, null=True, editable=False)),
('has_schedules', models.BooleanField(default=False, editable=False)),
('next_job_run', models.DateTimeField(default=None, null=True, editable=False)),
('status', models.CharField(default=b'ok', max_length=32, editable=False, choices=[(b'new', 'New'), (b'pending', 'Pending'), (b'waiting', 'Waiting'), (b'running', 'Running'), (b'successful', 'Successful'), (b'failed', 'Failed'), (b'error', 'Error'), (b'canceled', 'Canceled'), (b'never updated', b'Never Updated'), (b'ok', b'OK'), (b'missing', b'Missing'), (b'none', 'No External Source'), (b'updating', 'Updating')])),
],
),
migrations.CreateModel(
name='AdHocCommand',
fields=[
('unifiedjob_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='main.UnifiedJob')),
('job_type', models.CharField(default=b'run', max_length=64, choices=[(b'run', 'Run'), (b'check', 'Check'), (b'scan', 'Scan')])),
('limit', models.CharField(default=b'', max_length=1024, blank=True)),
('module_name', models.CharField(default=b'', max_length=1024, blank=True)),
('module_args', models.TextField(default=b'', blank=True)),
('forks', models.PositiveIntegerField(default=0, blank=True)),
('verbosity', models.PositiveIntegerField(default=0, blank=True, choices=[(0, b'0 (Normal)'), (1, b'1 (Verbose)'), (2, b'2 (More Verbose)'), (3, b'3 (Debug)'), (4, b'4 (Connection Debug)'), (5, b'5 (WinRM Debug)')])),
('become_enabled', models.BooleanField(default=False)),
],
bases=('main.unifiedjob',),
),
migrations.CreateModel(
name='InventorySource',
fields=[
('unifiedjobtemplate_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='main.UnifiedJobTemplate')),
('source', models.CharField(default=b'', max_length=32, blank=True, choices=[(b'', 'Manual'), (b'file', 'Local File, Directory or Script'), (b'rax', 'Rackspace Cloud Servers'), (b'ec2', 'Amazon EC2'), (b'gce', 'Google Compute Engine'), (b'azure', 'Microsoft Azure'), (b'vmware', 'VMware vCenter'), (b'openstack', 'OpenStack'), (b'custom', 'Custom Script')])),
('source_path', models.CharField(default=b'', max_length=1024, editable=False, blank=True)),
('source_vars', models.TextField(default=b'', help_text='Inventory source variables in YAML or JSON format.', blank=True)),
('source_regions', models.CharField(default=b'', max_length=1024, blank=True)),
('instance_filters', models.CharField(default=b'', help_text='Comma-separated list of filter expressions (EC2 only). Hosts are imported when ANY of the filters match.', max_length=1024, blank=True)),
('group_by', models.CharField(default=b'', help_text='Limit groups automatically created from inventory source (EC2 only).', max_length=1024, blank=True)),
('overwrite', models.BooleanField(default=False, help_text='Overwrite local groups and hosts from remote inventory source.')),
('overwrite_vars', models.BooleanField(default=False, help_text='Overwrite local variables from remote inventory source.')),
('update_on_launch', models.BooleanField(default=False)),
('update_cache_timeout', models.PositiveIntegerField(default=0)),
],
bases=('main.unifiedjobtemplate', models.Model),
),
migrations.CreateModel(
name='InventoryUpdate',
fields=[
('unifiedjob_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='main.UnifiedJob')),
('source', models.CharField(default=b'', max_length=32, blank=True, choices=[(b'', 'Manual'), (b'file', 'Local File, Directory or Script'), (b'rax', 'Rackspace Cloud Servers'), (b'ec2', 'Amazon EC2'), (b'gce', 'Google Compute Engine'), (b'azure', 'Microsoft Azure'), (b'vmware', 'VMware vCenter'), (b'openstack', 'OpenStack'), (b'custom', 'Custom Script')])),
('source_path', models.CharField(default=b'', max_length=1024, editable=False, blank=True)),
('source_vars', models.TextField(default=b'', help_text='Inventory source variables in YAML or JSON format.', blank=True)),
('source_regions', models.CharField(default=b'', max_length=1024, blank=True)),
('instance_filters', models.CharField(default=b'', help_text='Comma-separated list of filter expressions (EC2 only). Hosts are imported when ANY of the filters match.', max_length=1024, blank=True)),
('group_by', models.CharField(default=b'', help_text='Limit groups automatically created from inventory source (EC2 only).', max_length=1024, blank=True)),
('overwrite', models.BooleanField(default=False, help_text='Overwrite local groups and hosts from remote inventory source.')),
('overwrite_vars', models.BooleanField(default=False, help_text='Overwrite local variables from remote inventory source.')),
('license_error', models.BooleanField(default=False, editable=False)),
],
bases=('main.unifiedjob', models.Model),
),
migrations.CreateModel(
name='Job',
fields=[
('unifiedjob_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='main.UnifiedJob')),
('job_type', models.CharField(default=b'run', max_length=64, choices=[(b'run', 'Run'), (b'check', 'Check'), (b'scan', 'Scan')])),
('playbook', models.CharField(default=b'', max_length=1024, blank=True)),
('forks', models.PositiveIntegerField(default=0, blank=True)),
('limit', models.CharField(default=b'', max_length=1024, blank=True)),
('verbosity', models.PositiveIntegerField(default=0, blank=True, choices=[(0, b'0 (Normal)'), (1, b'1 (Verbose)'), (2, b'2 (More Verbose)'), (3, b'3 (Debug)'), (4, b'4 (Connection Debug)'), (5, b'5 (WinRM Debug)')])),
('extra_vars', models.TextField(default=b'', blank=True)),
('job_tags', models.CharField(default=b'', max_length=1024, blank=True)),
('force_handlers', models.BooleanField(default=False)),
('skip_tags', models.CharField(default=b'', max_length=1024, blank=True)),
('start_at_task', models.CharField(default=b'', max_length=1024, blank=True)),
('become_enabled', models.BooleanField(default=False)),
],
options={
'ordering': ('id',),
},
bases=('main.unifiedjob', models.Model),
),
migrations.CreateModel(
name='JobTemplate',
fields=[
('unifiedjobtemplate_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='main.UnifiedJobTemplate')),
('job_type', models.CharField(default=b'run', max_length=64, choices=[(b'run', 'Run'), (b'check', 'Check'), (b'scan', 'Scan')])),
('playbook', models.CharField(default=b'', max_length=1024, blank=True)),
('forks', models.PositiveIntegerField(default=0, blank=True)),
('limit', models.CharField(default=b'', max_length=1024, blank=True)),
('verbosity', models.PositiveIntegerField(default=0, blank=True, choices=[(0, b'0 (Normal)'), (1, b'1 (Verbose)'), (2, b'2 (More Verbose)'), (3, b'3 (Debug)'), (4, b'4 (Connection Debug)'), (5, b'5 (WinRM Debug)')])),
('extra_vars', models.TextField(default=b'', blank=True)),
('job_tags', models.CharField(default=b'', max_length=1024, blank=True)),
('force_handlers', models.BooleanField(default=False)),
('skip_tags', models.CharField(default=b'', max_length=1024, blank=True)),
('start_at_task', models.CharField(default=b'', max_length=1024, blank=True)),
('become_enabled', models.BooleanField(default=False)),
('host_config_key', models.CharField(default=b'', max_length=1024, blank=True)),
('ask_variables_on_launch', models.BooleanField(default=False)),
('survey_enabled', models.BooleanField(default=False)),
('survey_spec', jsonfield.fields.JSONField(default={}, blank=True)),
],
options={
'ordering': ('name',),
},
bases=('main.unifiedjobtemplate', models.Model),
),
migrations.CreateModel(
name='Project',
fields=[
('unifiedjobtemplate_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='main.UnifiedJobTemplate')),
('local_path', models.CharField(help_text='Local path (relative to PROJECTS_ROOT) containing playbooks and related files for this project.', max_length=1024, blank=True)),
('scm_type', models.CharField(default=b'', max_length=8, verbose_name='SCM Type', blank=True, choices=[(b'', 'Manual'), (b'git', 'Git'), (b'hg', 'Mercurial'), (b'svn', 'Subversion')])),
('scm_url', models.CharField(default=b'', max_length=1024, verbose_name='SCM URL', blank=True)),
('scm_branch', models.CharField(default=b'', help_text='Specific branch, tag or commit to checkout.', max_length=256, verbose_name='SCM Branch', blank=True)),
('scm_clean', models.BooleanField(default=False)),
('scm_delete_on_update', models.BooleanField(default=False)),
('scm_delete_on_next_update', models.BooleanField(default=False, editable=False)),
('scm_update_on_launch', models.BooleanField(default=False)),
('scm_update_cache_timeout', models.PositiveIntegerField(default=0, blank=True)),
],
options={
'ordering': ('id',),
},
bases=('main.unifiedjobtemplate', models.Model),
),
migrations.CreateModel(
name='ProjectUpdate',
fields=[
('unifiedjob_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='main.UnifiedJob')),
('local_path', models.CharField(help_text='Local path (relative to PROJECTS_ROOT) containing playbooks and related files for this project.', max_length=1024, blank=True)),
('scm_type', models.CharField(default=b'', max_length=8, verbose_name='SCM Type', blank=True, choices=[(b'', 'Manual'), (b'git', 'Git'), (b'hg', 'Mercurial'), (b'svn', 'Subversion')])),
('scm_url', models.CharField(default=b'', max_length=1024, verbose_name='SCM URL', blank=True)),
('scm_branch', models.CharField(default=b'', help_text='Specific branch, tag or commit to checkout.', max_length=256, verbose_name='SCM Branch', blank=True)),
('scm_clean', models.BooleanField(default=False)),
('scm_delete_on_update', models.BooleanField(default=False)),
],
bases=('main.unifiedjob', models.Model),
),
migrations.CreateModel(
name='SystemJob',
fields=[
('unifiedjob_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='main.UnifiedJob')),
('job_type', models.CharField(default=b'', max_length=32, blank=True, choices=[(b'cleanup_jobs', 'Remove jobs older than a certain number of days'), (b'cleanup_activitystream', 'Remove activity stream entries older than a certain number of days'), (b'cleanup_deleted', 'Purge previously deleted items from the database'), (b'cleanup_facts', 'Purge and/or reduce the granularity of system tracking data')])),
('extra_vars', models.TextField(default=b'', blank=True)),
],
options={
'ordering': ('id',),
},
bases=('main.unifiedjob', models.Model),
),
migrations.CreateModel(
name='SystemJobTemplate',
fields=[
('unifiedjobtemplate_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='main.UnifiedJobTemplate')),
('job_type', models.CharField(default=b'', max_length=32, blank=True, choices=[(b'cleanup_jobs', 'Remove jobs older than a certain number of days'), (b'cleanup_activitystream', 'Remove activity stream entries older than a certain number of days'), (b'cleanup_deleted', 'Purge previously deleted items from the database'), (b'cleanup_facts', 'Purge and/or reduce the granularity of system tracking data')])),
],
bases=('main.unifiedjobtemplate', models.Model),
),
migrations.AddField(
model_name='unifiedjobtemplate',
name='created_by',
field=models.ForeignKey(related_name="{u'class': 'unifiedjobtemplate', u'app_label': 'main'}(class)s_created+", on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True),
),
migrations.AddField(
model_name='unifiedjobtemplate',
name='current_job',
field=models.ForeignKey(related_name='unifiedjobtemplate_as_current_job+', on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to='main.UnifiedJob', null=True),
),
migrations.AddField(
model_name='unifiedjobtemplate',
name='last_job',
field=models.ForeignKey(related_name='unifiedjobtemplate_as_last_job+', on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to='main.UnifiedJob', null=True),
),
migrations.AddField(
model_name='unifiedjobtemplate',
name='modified_by',
field=models.ForeignKey(related_name="{u'class': 'unifiedjobtemplate', u'app_label': 'main'}(class)s_modified+", on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True),
),
migrations.AddField(
model_name='unifiedjobtemplate',
name='next_schedule',
field=models.ForeignKey(related_name='unifiedjobtemplate_as_next_schedule+', on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to='main.Schedule', null=True),
),
migrations.AddField(
model_name='unifiedjobtemplate',
name='polymorphic_ctype',
field=models.ForeignKey(related_name='polymorphic_main.unifiedjobtemplate_set+', editable=False, to='contenttypes.ContentType', null=True),
),
migrations.AddField(
model_name='unifiedjobtemplate',
name='tags',
field=taggit.managers.TaggableManager(to='taggit.Tag', through='taggit.TaggedItem', blank=True, help_text='A comma-separated list of tags.', verbose_name='Tags'),
),
migrations.AddField(
model_name='unifiedjob',
name='created_by',
field=models.ForeignKey(related_name="{u'class': 'unifiedjob', u'app_label': 'main'}(class)s_created+", on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True),
),
migrations.AddField(
model_name='unifiedjob',
name='dependent_jobs',
field=models.ManyToManyField(related_name='_unifiedjob_dependent_jobs_+', editable=False, to='main.UnifiedJob'),
),
migrations.AddField(
model_name='unifiedjob',
name='modified_by',
field=models.ForeignKey(related_name="{u'class': 'unifiedjob', u'app_label': 'main'}(class)s_modified+", on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True),
),
migrations.AddField(
model_name='unifiedjob',
name='polymorphic_ctype',
field=models.ForeignKey(related_name='polymorphic_main.unifiedjob_set+', editable=False, to='contenttypes.ContentType', null=True),
),
migrations.AddField(
model_name='unifiedjob',
name='schedule',
field=models.ForeignKey(on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to='main.Schedule', null=True),
),
migrations.AddField(
model_name='unifiedjob',
name='tags',
field=taggit.managers.TaggableManager(to='taggit.Tag', through='taggit.TaggedItem', blank=True, help_text='A comma-separated list of tags.', verbose_name='Tags'),
),
migrations.AddField(
model_name='unifiedjob',
name='unified_job_template',
field=models.ForeignKey(related_name='unifiedjob_unified_jobs', on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to='main.UnifiedJobTemplate', null=True),
),
migrations.AddField(
model_name='schedule',
name='unified_job_template',
field=models.ForeignKey(related_name='schedules', to='main.UnifiedJobTemplate'),
),
migrations.AddField(
model_name='permission',
name='team',
field=models.ForeignKey(related_name='permissions', on_delete=django.db.models.deletion.SET_NULL, blank=True, to='main.Team', null=True),
),
migrations.AddField(
model_name='permission',
name='user',
field=models.ForeignKey(related_name='permissions', on_delete=django.db.models.deletion.SET_NULL, blank=True, to=settings.AUTH_USER_MODEL, null=True),
),
migrations.AddField(
model_name='joborigin',
name='unified_job',
field=models.OneToOneField(related_name='job_origin', to='main.UnifiedJob'),
),
migrations.AddField(
model_name='inventory',
name='organization',
field=models.ForeignKey(related_name='inventories', to='main.Organization', help_text='Organization containing this inventory.'),
),
migrations.AddField(
model_name='inventory',
name='tags',
field=taggit.managers.TaggableManager(to='taggit.Tag', through='taggit.TaggedItem', blank=True, help_text='A comma-separated list of tags.', verbose_name='Tags'),
),
migrations.AddField(
model_name='host',
name='inventory',
field=models.ForeignKey(related_name='hosts', to='main.Inventory'),
),
migrations.AddField(
model_name='host',
name='last_job_host_summary',
field=models.ForeignKey(related_name='hosts_as_last_job_summary+', on_delete=django.db.models.deletion.SET_NULL, default=None, blank=True, editable=False, to='main.JobHostSummary', null=True),
),
migrations.AddField(
model_name='host',
name='modified_by',
field=models.ForeignKey(related_name="{u'class': 'host', u'app_label': 'main'}(class)s_modified+", on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True),
),
migrations.AddField(
model_name='host',
name='tags',
field=taggit.managers.TaggableManager(to='taggit.Tag', through='taggit.TaggedItem', blank=True, help_text='A comma-separated list of tags.', verbose_name='Tags'),
),
migrations.AddField(
model_name='group',
name='hosts',
field=models.ManyToManyField(help_text='Hosts associated directly with this group.', related_name='groups', to='main.Host', blank=True),
),
migrations.AddField(
model_name='group',
name='inventory',
field=models.ForeignKey(related_name='groups', to='main.Inventory'),
),
migrations.AddField(
model_name='group',
name='modified_by',
field=models.ForeignKey(related_name="{u'class': 'group', u'app_label': 'main'}(class)s_modified+", on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True),
),
migrations.AddField(
model_name='group',
name='parents',
field=models.ManyToManyField(related_name='children', to='main.Group', blank=True),
),
migrations.AddField(
model_name='group',
name='tags',
field=taggit.managers.TaggableManager(to='taggit.Tag', through='taggit.TaggedItem', blank=True, help_text='A comma-separated list of tags.', verbose_name='Tags'),
),
migrations.AddField(
model_name='custominventoryscript',
name='organization',
field=models.ForeignKey(related_name='custom_inventory_scripts', on_delete=django.db.models.deletion.SET_NULL, to='main.Organization', help_text='Organization owning this inventory script', null=True),
),
migrations.AddField(
model_name='custominventoryscript',
name='tags',
field=taggit.managers.TaggableManager(to='taggit.Tag', through='taggit.TaggedItem', blank=True, help_text='A comma-separated list of tags.', verbose_name='Tags'),
),
migrations.AddField(
model_name='credential',
name='team',
field=models.ForeignKey(related_name='credentials', default=None, blank=True, to='main.Team', null=True),
),
migrations.AddField(
model_name='credential',
name='user',
field=models.ForeignKey(related_name='credentials', default=None, blank=True, to=settings.AUTH_USER_MODEL, null=True),
),
migrations.AddField(
model_name='adhoccommandevent',
name='host',
field=models.ForeignKey(related_name='ad_hoc_command_events', on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to='main.Host', null=True),
),
migrations.AddField(
model_name='activitystream',
name='credential',
field=models.ManyToManyField(to='main.Credential', blank=True),
),
migrations.AddField(
model_name='activitystream',
name='custom_inventory_script',
field=models.ManyToManyField(to='main.CustomInventoryScript', blank=True),
),
migrations.AddField(
model_name='activitystream',
name='group',
field=models.ManyToManyField(to='main.Group', blank=True),
),
migrations.AddField(
model_name='activitystream',
name='host',
field=models.ManyToManyField(to='main.Host', blank=True),
),
migrations.AddField(
model_name='activitystream',
name='inventory',
field=models.ManyToManyField(to='main.Inventory', blank=True),
),
migrations.AddField(
model_name='activitystream',
name='organization',
field=models.ManyToManyField(to='main.Organization', blank=True),
),
migrations.AddField(
model_name='activitystream',
name='permission',
field=models.ManyToManyField(to='main.Permission', blank=True),
),
migrations.AddField(
model_name='activitystream',
name='schedule',
field=models.ManyToManyField(to='main.Schedule', blank=True),
),
migrations.AddField(
model_name='activitystream',
name='team',
field=models.ManyToManyField(to='main.Team', blank=True),
),
migrations.AddField(
model_name='activitystream',
name='unified_job',
field=models.ManyToManyField(related_name='_activitystream_unified_job_+', to='main.UnifiedJob', blank=True),
),
migrations.AddField(
model_name='activitystream',
name='unified_job_template',
field=models.ManyToManyField(related_name='_activitystream_unified_job_template_+', to='main.UnifiedJobTemplate', blank=True),
),
migrations.AddField(
model_name='activitystream',
name='user',
field=models.ManyToManyField(to=settings.AUTH_USER_MODEL, blank=True),
),
migrations.AlterUniqueTogether(
name='unifiedjobtemplate',
unique_together=set([('polymorphic_ctype', 'name')]),
),
migrations.AddField(
model_name='team',
name='projects',
field=models.ManyToManyField(related_name='teams', to='main.Project', blank=True),
),
migrations.AddField(
model_name='systemjob',
name='system_job_template',
field=models.ForeignKey(related_name='jobs', on_delete=django.db.models.deletion.SET_NULL, default=None, blank=True, to='main.SystemJobTemplate', null=True),
),
migrations.AddField(
model_name='projectupdate',
name='credential',
field=models.ForeignKey(related_name='projectupdates', on_delete=django.db.models.deletion.SET_NULL, default=None, blank=True, to='main.Credential', null=True),
),
migrations.AddField(
model_name='projectupdate',
name='project',
field=models.ForeignKey(related_name='project_updates', editable=False, to='main.Project'),
),
migrations.AddField(
model_name='project',
name='credential',
field=models.ForeignKey(related_name='projects', on_delete=django.db.models.deletion.SET_NULL, default=None, blank=True, to='main.Credential', null=True),
),
migrations.AddField(
model_name='permission',
name='project',
field=models.ForeignKey(related_name='permissions', on_delete=django.db.models.deletion.SET_NULL, blank=True, to='main.Project', null=True),
),
migrations.AddField(
model_name='organization',
name='projects',
field=models.ManyToManyField(related_name='organizations', to='main.Project', blank=True),
),
migrations.AddField(
model_name='jobtemplate',
name='cloud_credential',
field=models.ForeignKey(related_name='jobtemplates_as_cloud_credential+', on_delete=django.db.models.deletion.SET_NULL, default=None, blank=True, to='main.Credential', null=True),
),
migrations.AddField(
model_name='jobtemplate',
name='credential',
field=models.ForeignKey(related_name='jobtemplates', on_delete=django.db.models.deletion.SET_NULL, default=None, blank=True, to='main.Credential', null=True),
),
migrations.AddField(
model_name='jobtemplate',
name='inventory',
field=models.ForeignKey(related_name='jobtemplates', on_delete=django.db.models.deletion.SET_NULL, to='main.Inventory', null=True),
),
migrations.AddField(
model_name='jobtemplate',
name='project',
field=models.ForeignKey(related_name='jobtemplates', on_delete=django.db.models.deletion.SET_NULL, default=None, blank=True, to='main.Project', null=True),
),
migrations.AddField(
model_name='jobhostsummary',
name='job',
field=models.ForeignKey(related_name='job_host_summaries', editable=False, to='main.Job'),
),
migrations.AddField(
model_name='jobevent',
name='job',
field=models.ForeignKey(related_name='job_events', editable=False, to='main.Job'),
),
migrations.AddField(
model_name='job',
name='cloud_credential',
field=models.ForeignKey(related_name='jobs_as_cloud_credential+', on_delete=django.db.models.deletion.SET_NULL, default=None, blank=True, to='main.Credential', null=True),
),
migrations.AddField(
model_name='job',
name='credential',
field=models.ForeignKey(related_name='jobs', on_delete=django.db.models.deletion.SET_NULL, default=None, blank=True, to='main.Credential', null=True),
),
migrations.AddField(
model_name='job',
name='hosts',
field=models.ManyToManyField(related_name='jobs', editable=False, through='main.JobHostSummary', to='main.Host'),
),
migrations.AddField(
model_name='job',
name='inventory',
field=models.ForeignKey(related_name='jobs', on_delete=django.db.models.deletion.SET_NULL, to='main.Inventory', null=True),
),
migrations.AddField(
model_name='job',
name='job_template',
field=models.ForeignKey(related_name='jobs', on_delete=django.db.models.deletion.SET_NULL, default=None, blank=True, to='main.JobTemplate', null=True),
),
migrations.AddField(
model_name='job',
name='project',
field=models.ForeignKey(related_name='jobs', on_delete=django.db.models.deletion.SET_NULL, default=None, blank=True, to='main.Project', null=True),
),
migrations.AddField(
model_name='inventoryupdate',
name='credential',
field=models.ForeignKey(related_name='inventoryupdates', on_delete=django.db.models.deletion.SET_NULL, default=None, blank=True, to='main.Credential', null=True),
),
migrations.AddField(
model_name='inventoryupdate',
name='inventory_source',
field=models.ForeignKey(related_name='inventory_updates', editable=False, to='main.InventorySource'),
),
migrations.AddField(
model_name='inventoryupdate',
name='source_script',
field=models.ForeignKey(on_delete=django.db.models.deletion.SET_NULL, default=None, blank=True, to='main.CustomInventoryScript', null=True),
),
migrations.AddField(
model_name='inventorysource',
name='credential',
field=models.ForeignKey(related_name='inventorysources', on_delete=django.db.models.deletion.SET_NULL, default=None, blank=True, to='main.Credential', null=True),
),
migrations.AddField(
model_name='inventorysource',
name='group',
field=awx.main.fields.AutoOneToOneField(related_name='inventory_source', null=True, default=None, editable=False, to='main.Group'),
),
migrations.AddField(
model_name='inventorysource',
name='inventory',
field=models.ForeignKey(related_name='inventory_sources', default=None, editable=False, to='main.Inventory', null=True),
),
migrations.AddField(
model_name='inventorysource',
name='source_script',
field=models.ForeignKey(on_delete=django.db.models.deletion.SET_NULL, default=None, blank=True, to='main.CustomInventoryScript', null=True),
),
migrations.AlterUniqueTogether(
name='inventory',
unique_together=set([('name', 'organization')]),
),
migrations.AddField(
model_name='host',
name='inventory_sources',
field=models.ManyToManyField(help_text='Inventory source(s) that created or modified this host.', related_name='hosts', editable=False, to='main.InventorySource'),
),
migrations.AddField(
model_name='host',
name='last_job',
field=models.ForeignKey(related_name='hosts_as_last_job+', on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to='main.Job', null=True),
),
migrations.AddField(
model_name='group',
name='inventory_sources',
field=models.ManyToManyField(help_text='Inventory source(s) that created or modified this group.', related_name='groups', editable=False, to='main.InventorySource'),
),
migrations.AlterUniqueTogether(
name='custominventoryscript',
unique_together=set([('name', 'organization')]),
),
migrations.AlterUniqueTogether(
name='credential',
unique_together=set([('user', 'team', 'kind', 'name')]),
),
migrations.AddField(
model_name='adhoccommandevent',
name='ad_hoc_command',
field=models.ForeignKey(related_name='ad_hoc_command_events', editable=False, to='main.AdHocCommand'),
),
migrations.AddField(
model_name='adhoccommand',
name='credential',
field=models.ForeignKey(related_name='ad_hoc_commands', on_delete=django.db.models.deletion.SET_NULL, default=None, to='main.Credential', null=True),
),
migrations.AddField(
model_name='adhoccommand',
name='hosts',
field=models.ManyToManyField(related_name='ad_hoc_commands', editable=False, through='main.AdHocCommandEvent', to='main.Host'),
),
migrations.AddField(
model_name='adhoccommand',
name='inventory',
field=models.ForeignKey(related_name='ad_hoc_commands', on_delete=django.db.models.deletion.SET_NULL, to='main.Inventory', null=True),
),
migrations.AddField(
model_name='activitystream',
name='ad_hoc_command',
field=models.ManyToManyField(to='main.AdHocCommand', blank=True),
),
migrations.AddField(
model_name='activitystream',
name='inventory_source',
field=models.ManyToManyField(to='main.InventorySource', blank=True),
),
migrations.AddField(
model_name='activitystream',
name='inventory_update',
field=models.ManyToManyField(to='main.InventoryUpdate', blank=True),
),
migrations.AddField(
model_name='activitystream',
name='job',
field=models.ManyToManyField(to='main.Job', blank=True),
),
migrations.AddField(
model_name='activitystream',
name='job_template',
field=models.ManyToManyField(to='main.JobTemplate', blank=True),
),
migrations.AddField(
model_name='activitystream',
name='project',
field=models.ManyToManyField(to='main.Project', blank=True),
),
migrations.AddField(
model_name='activitystream',
name='project_update',
field=models.ManyToManyField(to='main.ProjectUpdate', blank=True),
),
migrations.AlterUniqueTogether(
name='team',
unique_together=set([('organization', 'name')]),
),
migrations.AlterUniqueTogether(
name='jobhostsummary',
unique_together=set([('job', 'host_name')]),
),
migrations.AlterUniqueTogether(
name='host',
unique_together=set([('name', 'inventory')]),
),
migrations.AlterUniqueTogether(
name='group',
unique_together=set([('name', 'inventory')]),
),
migrations.AlterUniqueTogether(
name='adhoccommandevent',
unique_together=set([('ad_hoc_command', 'host_name')]),
),
]

View File

@@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2016 Ansible, Inc.
# All Rights Reserved.
from __future__ import unicode_literals
from django.db import migrations, models
from django.conf import settings
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('main', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='TowerSettings',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('created', models.DateTimeField(default=None, editable=False)),
('modified', models.DateTimeField(default=None, editable=False)),
('key', models.CharField(unique=True, max_length=255)),
('description', models.TextField()),
('category', models.CharField(max_length=128)),
('value', models.TextField()),
('value_type', models.CharField(max_length=12, choices=[(b'string', 'String'), (b'int', 'Integer'), (b'float', 'Decimal'), (b'json', 'JSON'), (b'bool', 'Boolean'), (b'password', 'Password'), (b'list', 'List')])),
('user', models.ForeignKey(related_name='settings', default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True)),
],
),
]

View File

@@ -1,2 +1,2 @@
# Copyright (c) 2015 Ansible, Inc.
# Copyright (c) 2016 Ansible, Inc.
# All Rights Reserved.

View File

@@ -30,9 +30,6 @@ __all__ = ['AdHocCommand', 'AdHocCommandEvent']
class AdHocCommand(UnifiedJob):
MODULE_NAME_CHOICES = [(x,x) for x in tower_settings.AD_HOC_COMMANDS]
MODULE_NAME_DEFAULT = 'command' if 'command' in tower_settings.AD_HOC_COMMANDS else None
class Meta(object):
app_label = 'main'
@@ -61,9 +58,8 @@ class AdHocCommand(UnifiedJob):
)
module_name = models.CharField(
max_length=1024,
default=MODULE_NAME_DEFAULT,
choices=MODULE_NAME_CHOICES,
blank=bool(MODULE_NAME_DEFAULT),
default='',
blank=True,
)
module_args = models.TextField(
blank=True,
@@ -88,6 +84,12 @@ class AdHocCommand(UnifiedJob):
through='AdHocCommandEvent',
)
def clean_inventory(self):
inv = self.inventory
if not inv or not inv.active:
raise ValidationError('Inventory is no longer available.')
return inv
def clean_credential(self):
cred = self.credential
if cred and cred.kind != 'ssh':

View File

@@ -9,7 +9,6 @@ import shlex
import yaml
# Django
from django.conf import settings
from django.db import models
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext_lazy as _
@@ -59,14 +58,14 @@ PERMISSION_TYPE_CHOICES = [
CLOUD_INVENTORY_SOURCES = ['ec2', 'rax', 'vmware', 'gce', 'azure', 'openstack', 'custom']
VERBOSITY_CHOICES = getattr(settings, 'VERBOSITY_CHOICES', [
VERBOSITY_CHOICES = [
(0, '0 (Normal)'),
(1, '1 (Verbose)'),
(2, '2 (More Verbose)'),
(3, '3 (Debug)'),
(4, '4 (Connection Debug)'),
(5, '5 (WinRM Debug)'),
])
]
class VarsDictProperty(object):
@@ -157,16 +156,6 @@ class BaseModel(models.Model):
self.save(update_fields=update_fields)
return update_fields
def save(self, *args, **kwargs):
# For compatibility with Django 1.4.x, attempt to handle any calls to
# save that pass update_fields.
try:
super(BaseModel, self).save(*args, **kwargs)
except TypeError:
if 'update_fields' not in kwargs:
raise
kwargs.pop('update_fields')
super(BaseModel, self).save(*args, **kwargs)
class CreatedModifiedModel(BaseModel):
'''

View File

@@ -6,10 +6,13 @@ import json
# Django
from django.db import models
from django.utils.encoding import smart_text
from django.utils.translation import ugettext_lazy as _
# Tower
from awx.main.models.base import CreatedModifiedModel
class TowerSettings(CreatedModifiedModel):
class Meta:
@@ -53,10 +56,21 @@ class TowerSettings(CreatedModifiedModel):
elif self.value_type == 'list':
converted_type = [x.strip() for x in self.value.split(',')]
elif self.value_type == 'bool':
converted_type = self.value in [True, "true", "True", 1, "1", "yes"]
converted_type = smart_text(self.value).lower() in ('true', 'yes', '1')
elif self.value_type == 'string':
converted_type = self.value
else:
t = __builtins__[self.value_type]
converted_type = t(self.value)
return converted_type
@value_converted.setter
def value_converted(self, value):
if self.value_type == 'json':
self.value = json.dumps(value)
elif self.value_type == 'list':
self.value = ','.join(value)
elif self.value_type == 'bool':
self.value = smart_text(bool(value))
else:
self.value = smart_text(value)

View File

@@ -539,7 +539,7 @@ class Group(CommonModelNameNotUnique):
def mark_actual():
all_group_hosts = Group.hosts.through.objects.select_related("host", "group").filter(group__inventory=self.inventory)
group_hosts = {'groups': {}, 'hosts': {}}
all_group_parents = Group.parents.through.objects.select_related("parent", "group").filter(from_group__inventory=self.inventory)
all_group_parents = Group.parents.through.objects.select_related("from_group", "to_group").filter(from_group__inventory=self.inventory)
group_children = {}
group_parents = {}
marked_hosts = []

View File

@@ -317,3 +317,10 @@ def user_mark_inactive(user, save=True):
user.save()
User.add_to_class('mark_inactive', user_mark_inactive)
# Add get_absolute_url method to User model if not present.
if not hasattr(User, 'get_absolute_url'):
def user_get_absolute_url(user):
return reverse('api:user_detail', args=(user.pk,))
User.add_to_class('get_absolute_url', user_get_absolute_url)

View File

@@ -11,7 +11,7 @@ import urlparse
from django.conf import settings
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import smart_str
from django.utils.encoding import smart_str, smart_text
from django.core.exceptions import ValidationError
from django.core.urlresolvers import reverse
from django.utils.timezone import now, make_aware, get_default_timezone
@@ -181,7 +181,7 @@ class ProjectOptions(models.Model):
# Filter files in a tasks subdirectory.
if 'tasks' in playbook.split(os.sep):
continue
results.append(playbook)
results.append(smart_text(playbook))
return sorted(results, key=lambda x: smart_str(x).lower())

View File

@@ -47,7 +47,7 @@ class ScheduleManager(ScheduleFilterMethods, models.Manager):
use_for_related_objects = True
def get_query_set(self):
def get_queryset(self):
return ScheduleQuerySet(self.model, using=self._db)

View File

@@ -8,13 +8,13 @@ import logging
import re
import os
import os.path
from collections import OrderedDict
from StringIO import StringIO
# Django
from django.conf import settings
from django.db import models
from django.core.exceptions import NON_FIELD_ERRORS
from django.utils.datastructures import SortedDict
from django.utils.translation import ugettext_lazy as _
from django.utils.timezone import now
@@ -77,7 +77,7 @@ class UnifiedJobTemplate(PolymorphicModel, CommonModelNameNotUnique):
('updating', _('Updating')), # Same as running.
]
ALL_STATUS_CHOICES = SortedDict(PROJECT_STATUS_CHOICES + INVENTORY_SOURCE_STATUS_CHOICES + JOB_TEMPLATE_STATUS_CHOICES + DEPRECATED_STATUS_CHOICES).items()
ALL_STATUS_CHOICES = OrderedDict(PROJECT_STATUS_CHOICES + INVENTORY_SOURCE_STATUS_CHOICES + JOB_TEMPLATE_STATUS_CHOICES + DEPRECATED_STATUS_CHOICES).items()
class Meta:
app_label = 'main'

View File

@@ -0,0 +1,2 @@
# Copyright (c) 2015 Ansible, Inc.
# All Rights Reserved.

View File

@@ -3,6 +3,7 @@
# Python
import codecs
from collections import OrderedDict
import ConfigParser
import cStringIO
import json
@@ -37,7 +38,6 @@ from celery import Task, task
# Django
from django.conf import settings
from django.db import transaction, DatabaseError
from django.utils.datastructures import SortedDict
from django.utils.timezone import now
# AWX
@@ -423,7 +423,7 @@ class BaseTask(Task):
prompts, and values are password lookup keys (keys that are returned
from build_passwords).
'''
return SortedDict()
return OrderedDict()
@task_timer
def run_pexpect(self, instance, args, cwd, env, passwords, stdout_handle,

View File

@@ -0,0 +1,2 @@
# Copyright (c) 2015 Ansible, Inc.
# All Rights Reserved.

View File

@@ -25,6 +25,7 @@ from django.conf import settings, UserSettingsHolder
from django.contrib.auth.models import User
from django.test.client import Client
from django.test.utils import override_settings
from django.utils.encoding import force_text
# AWX
from awx.main.models import * # noqa
@@ -132,6 +133,7 @@ class BaseTestMixin(QueueTestMixin, MockCommonlySlowTestMixin):
if settings.CALLBACK_CONSUMER_PORT:
callback_port = random.randint(55700, 55799)
settings.CALLBACK_CONSUMER_PORT = 'tcp://127.0.0.1:%d' % callback_port
os.environ['CALLBACK_CONSUMER_PORT'] = settings.CALLBACK_CONSUMER_PORT
callback_queue_path = '/tmp/callback_receiver_test_%d.ipc' % callback_port
self._temp_paths.append(callback_queue_path)
settings.CALLBACK_QUEUE_PORT = 'ipc://%s' % callback_queue_path
@@ -425,8 +427,6 @@ class BaseTestMixin(QueueTestMixin, MockCommonlySlowTestMixin):
return_response_object=False, client_kwargs=None):
assert method is not None
method_name = method.lower()
#if method_name not in ('options', 'head', 'get', 'delete'):
# assert data is not None
client_kwargs = client_kwargs or {}
if accept:
client_kwargs['HTTP_ACCEPT'] = accept
@@ -457,7 +457,7 @@ class BaseTestMixin(QueueTestMixin, MockCommonlySlowTestMixin):
client = Client(**client_kwargs)
method = getattr(client, method_name)
response = None
if data is not None:
if method_name not in ('options', 'head', 'get', 'delete'):
data_type = data_type or 'json'
if data_type == 'json':
response = method(url, json.dumps(data), 'application/json')
@@ -469,9 +469,9 @@ class BaseTestMixin(QueueTestMixin, MockCommonlySlowTestMixin):
response = method(url)
self.assertFalse(response.status_code == 500 and expect != 500,
'Failed (500): %s' % response.content)
'Failed (500): %s' % force_text(response.content))
if expect is not None:
assert response.status_code == expect, "expected status %s, got %s for url=%s as auth=%s: %s" % (expect, response.status_code, url, auth, response.content)
assert response.status_code == expect, u"expected status %s, got %s for url=%s as auth=%s: %s" % (expect, response.status_code, url, auth, force_text(response.content))
if method_name == 'head':
self.assertFalse(response.content)
if return_response_object:
@@ -479,16 +479,16 @@ class BaseTestMixin(QueueTestMixin, MockCommonlySlowTestMixin):
if response.status_code not in [204, 405] and method_name != 'head' and response.content:
# no JSON responses in these at least for now, 409 should probably return some (FIXME)
if response['Content-Type'].startswith('application/json'):
obj = json.loads(response.content)
obj = json.loads(force_text(response.content))
elif response['Content-Type'].startswith('application/yaml'):
obj = yaml.safe_load(response.content)
obj = yaml.safe_load(force_text(response.content))
elif response['Content-Type'].startswith('text/plain'):
obj = {
'content': response.content
'content': force_text(response.content)
}
elif response['Content-Type'].startswith('text/html'):
obj = {
'content': response.content
'content': force_text(response.content)
}
else:
self.fail('Unsupport response content type %s' % response['Content-Type'])

View File

@@ -18,6 +18,7 @@ from crum import impersonate
# AWX
from awx.main.utils import * # noqa
from awx.main.models import * # noqa
from awx.main.conf import tower_settings
from awx.main.tests.base import BaseJobExecutionTest
from awx.main.tests.data.ssh import (
TEST_SSH_KEY_DATA,
@@ -746,11 +747,15 @@ class AdHocCommandApiTest(BaseAdHocCommandTest):
# Try to relaunch ad hoc command when module has been removed from
# allowed list of modules.
with self.settings(AD_HOC_COMMANDS=[]):
try:
ad_hoc_commands = tower_settings.AD_HOC_COMMANDS
tower_settings.AD_HOC_COMMANDS = []
with self.current_user('admin'):
response = self.get(url, expect=200)
self.assertEqual(response['passwords_needed_to_start'], [])
response = self.post(url, {}, expect=400)
finally:
tower_settings.AD_HOC_COMMANDS = ad_hoc_commands
# Try to relaunch after the inventory has been marked inactive.
self.inventory.mark_inactive()

View File

@@ -14,7 +14,6 @@ import urlparse
import unittest2 as unittest
# Django
import django
from django.conf import settings
from django.contrib.auth.models import User
from django.core.management import call_command
@@ -1066,8 +1065,6 @@ class InventoryImportTest(BaseCommandMixin, BaseLiveServerTest):
self.assertNotEqual(new_inv.total_groups, 0)
self.assertElapsedLessThan(30)
@unittest.skipIf(hasattr(django.db.backend, 'sqlite3'),
'Skip this test if we are on sqlite')
def test_splunk_inventory(self):
new_inv = self.organizations[0].inventories.create(name='splunk')
self.assertEqual(new_inv.hosts.count(), 0)

View File

@@ -535,7 +535,7 @@ class InventoryTest(BaseTest):
vars_a = dict(asdf=7777, dog='droopy', cat='battlecat', unstructured=dict(a=[1,1,1],b=dict(x=1,y=2)))
vars_b = dict(asdf=8888, dog='snoopy', cat='cheshire', unstructured=dict(a=[2,2,2],b=dict(x=3,y=4)))
vars_c = dict(asdf=9999, dog='pluto', cat='five', unstructured=dict(a=[3,3,3],b=dict(z=5)))
group = Group.objects.get(id=1)
group = Group.objects.order_by('pk')[0]
vdata1_url = reverse('api:group_variable_data', args=(group.pk,))
@@ -1330,6 +1330,18 @@ class InventoryUpdatesTest(BaseTransactionTest):
self.delete(inv_up_url, expect=204)
self.get(inv_up_url, expect=404)
def print_group_tree(self, group, depth=0):
print (' ' * depth) + '+ ' + group.name
for host in group.hosts.order_by('name'):
print (' ' * depth) + ' - ' + host.name
for child in group.children.order_by('name'):
self.print_group_tree(child, depth + 1)
def print_inventory_tree(self, inventory):
# Print out group/host tree for debugging.
for group in inventory.root_groups.order_by('name'):
self.print_group_tree(group)
def test_put_inventory_source_detail_with_regions(self):
creds_url = reverse('api:credential_list')
inv_src_url1 = reverse('api:inventory_source_detail',
@@ -1749,6 +1761,7 @@ class InventoryUpdatesTest(BaseTransactionTest):
# its own child).
self.assertTrue(self.group in self.inventory.root_groups)
# Verify that returned groups are nested:
#self.print_inventory_tree(self.inventory)
child_names = self.group.children.values_list('name', flat=True)
for name in child_names:
self.assertFalse(name.startswith('us-'))
@@ -1766,7 +1779,10 @@ class InventoryUpdatesTest(BaseTransactionTest):
self.assertTrue('tags' in child_names)
self.assertTrue('images' in child_names)
self.assertFalse('tag_none' in child_names)
self.assertTrue('tag_none' in self.group.children.get(name='tags').children.values_list('name', flat=True))
# Only check for tag_none as a child of tags if there is a tag_none group;
# the test inventory *may* have tags set for all hosts.
if self.inventory.groups.filter(name='tag_none').exists():
self.assertTrue('tag_none' in self.group.children.get(name='tags').children.values_list('name', flat=True))
self.assertFalse('instances' in child_names)
# Make sure we clean up the cache path when finished (when one is not
# provided explicitly via source_vars).
@@ -1816,7 +1832,10 @@ class InventoryUpdatesTest(BaseTransactionTest):
self.assertTrue(self.group.children.get(name='security_groups').children.filter(active=True).count())
self.assertTrue('tags' in child_names)
self.assertTrue(self.group.children.get(name='tags').children.filter(active=True).count())
self.assertTrue('tag_none' in self.group.children.get(name='tags').children.values_list('name', flat=True))
# Only check for tag_none as a child of tags if there is a tag_none group;
# the test inventory *may* have tags set for all hosts.
if self.inventory.groups.filter(name='tag_none').exists():
self.assertTrue('tag_none' in self.group.children.get(name='tags').children.values_list('name', flat=True))
self.assertTrue('images' in child_names)
self.assertTrue(self.group.children.get(name='images').children.filter(active=True).count())
self.assertTrue('instances' in child_names)
@@ -1840,21 +1859,9 @@ class InventoryUpdatesTest(BaseTransactionTest):
# Replacement text should not be left in inventory source name.
self.assertFalse(InventorySource.objects.filter(name__icontains='__replace_').exists())
# Inventory update name should be based on inventory/group names and need not have the inventory source pk.
print InventoryUpdate.objects.values_list('name', 'inventory_source__name')
#print InventoryUpdate.objects.values_list('name', 'inventory_source__name')
for inventory_update in InventoryUpdate.objects.all():
self.assertFalse(inventory_update.name.endswith(inventory_update.inventory_source.name), inventory_update.name)
return
# Print out group/host tree for debugging.
print
def draw_tree(g, d=0):
print (' ' * d) + '+ ' + g.name
for h in g.hosts.order_by('name'):
print (' ' * d) + ' - ' + h.name
for c in g.children.order_by('name'):
draw_tree(c, d + 1)
for g in self.inventory.root_groups.order_by('name'):
draw_tree(g)
def test_update_from_rax(self):
source_username = getattr(settings, 'TEST_RACKSPACE_USERNAME', '')

View File

@@ -15,7 +15,7 @@ import django.test
from django.conf import settings
from django.core.urlresolvers import reverse
from django.test.utils import override_settings
from django.utils.encoding import smart_str
from django.utils.encoding import smart_text
# Requests
import requests
@@ -216,26 +216,26 @@ class JobTemplateTest(BaseJobTestMixin, django.test.TestCase):
# due to being an org admin for that project and no credential assigned to that template
with self.current_user(self.user_bob):
resp = self.get(url, expect=200)
print [x['name'] for x in resp['results']]
#print [x['name'] for x in resp['results']]
self.assertEquals(resp['count'], 3)
# Chuck has permission to see all Eng Job Templates as Lead Engineer
# Note: Since chuck is an org admin he can also see the support scan template
with self.current_user(self.user_chuck):
resp = self.get(url, expect=200)
print [x['name'] for x in resp['results']]
#print [x['name'] for x in resp['results']]
self.assertEquals(resp['count'], 3)
# Doug is in engineering but can only run scan jobs so he can only see the one Job Template
with self.current_user(self.user_doug):
resp = self.get(url, expect=200)
print [x['name'] for x in resp['results']]
#print [x['name'] for x in resp['results']]
self.assertEquals(resp['count'], 1)
# Juan can't see any job templates in Engineering because he lacks the inventory read permission
with self.current_user(self.user_juan):
resp = self.get(url, expect=200)
print [x['name'] for x in resp['results']]
#print [x['name'] for x in resp['results']]
self.assertEquals(resp['count'], 0)
# We give Juan inventory permission and he can see both Job Templates because he already has deploy permission
@@ -248,19 +248,19 @@ class JobTemplateTest(BaseJobTestMixin, django.test.TestCase):
)
with self.current_user(self.user_juan):
resp = self.get(url, expect=200)
print [x['name'] for x in resp['results']]
#print [x['name'] for x in resp['results']]
self.assertEquals(resp['count'], 2)
# Randall is on the ops testers team that has permission to run a single check playbook on ops west
with self.current_user(self.user_randall):
resp = self.get(url, expect=200)
print [x['name'] for x in resp['results']]
#print [x['name'] for x in resp['results']]
self.assertEquals(resp['count'], 1)
# Holly is on the ops east team and can see all of that team's job templates
with self.current_user(self.user_holly):
resp = self.get(url, expect=200)
print [x['name'] for x in resp['results']]
#print [x['name'] for x in resp['results']]
self.assertEquals(resp['count'], 3)
# Chuck is temporarily assigned to ops east team to help them running some playbooks
@@ -268,7 +268,7 @@ class JobTemplateTest(BaseJobTestMixin, django.test.TestCase):
self.team_ops_east.users.add(self.user_chuck)
with self.current_user(self.user_chuck):
resp = self.get(url, expect=200)
print [x['name'] for x in resp['results']]
#print [x['name'] for x in resp['results']]
self.assertEquals(resp['count'], 6)
@@ -313,7 +313,7 @@ class JobTemplateTest(BaseJobTestMixin, django.test.TestCase):
self.assertEqual(jt.inventory.pk, data['inventory'])
self.assertEqual(jt.credential, None)
self.assertEqual(jt.project.pk, data['project'])
self.assertEqual(smart_str(jt.playbook), data['playbook'])
self.assertEqual(smart_text(jt.playbook), data['playbook'])
# Test that all required fields are really required.
data['name'] = 'another new job template'
@@ -903,8 +903,10 @@ class JobTemplateCallbackTest(BaseJobTestMixin, django.test.LiveServerTestCase):
# Set a limit on the job template to verify the callback job limit is
# set to the intersection of this limit and the host name.
job_template.limit = 'bakers:slicers:packagers'
job_template.save(update_fields=['limit'])
# job_template.limit = 'bakers:slicers:packagers'
# job_template.save(update_fields=['limit'])
JobTemplate.objects.filter(pk=job_template.pk).update(limit='bakers:slicers:packagers')
job_template = JobTemplate.objects.get(pk=job_template.pk)
# Try when hostname is also an IP address, even if a different one is
# specified via ansible_ssh_host.

Some files were not shown because too many files have changed in this diff Show More