Model changes based on jobs API discussion, code and test fixes to work with those changes.

This commit is contained in:
Chris Church
2013-05-08 17:41:10 -04:00
parent 6238f0ab9a
commit f7cd605415
11 changed files with 638 additions and 110 deletions

View File

@@ -72,10 +72,10 @@ class OrganizationAdmin(BaseModelAdmin):
(_('Members'), {'fields': ('users', 'admins',)}), (_('Members'), {'fields': ('users', 'admins',)}),
(_('Projects'), {'fields': ('projects',)}), (_('Projects'), {'fields': ('projects',)}),
(_('Tags'), {'fields': ('tags',)}), (_('Tags'), {'fields': ('tags',)}),
(_('Audit Trail'), {'fields': ('creation_date', 'created_by', (_('Audit Trail'), {'fields': ('created', 'created_by',
'audit_trail',)}), 'audit_trail',)}),
) )
readonly_fields = ('creation_date', 'created_by', 'audit_trail') readonly_fields = ('created', 'created_by', 'audit_trail')
filter_horizontal = ('users', 'admins', 'projects', 'tags') filter_horizontal = ('users', 'admins', 'projects', 'tags')
class InventoryHostInline(admin.StackedInline): class InventoryHostInline(admin.StackedInline):
@@ -99,9 +99,9 @@ class InventoryAdmin(BaseModelAdmin):
fieldsets = ( fieldsets = (
(None, {'fields': (('name', 'active'), 'organization', 'description',)}), (None, {'fields': (('name', 'active'), 'organization', 'description',)}),
(_('Tags'), {'fields': ('tags',)}), (_('Tags'), {'fields': ('tags',)}),
(_('Audit Trail'), {'fields': ('creation_date', 'created_by', 'audit_trail',)}), (_('Audit Trail'), {'fields': ('created', 'created_by', 'audit_trail',)}),
) )
readonly_fields = ('creation_date', 'created_by', 'audit_trail') readonly_fields = ('created', 'created_by', 'audit_trail')
filter_horizontal = ('tags',) filter_horizontal = ('tags',)
inlines = [InventoryHostInline, InventoryGroupInline] inlines = [InventoryHostInline, InventoryGroupInline]
@@ -168,9 +168,9 @@ class HostAdmin(BaseModelAdmin):
(None, {'fields': (('name', 'active'), 'inventory', 'description', 'variable_data', (None, {'fields': (('name', 'active'), 'inventory', 'description', 'variable_data',
)}), )}),
(_('Tags'), {'fields': ('tags',)}), (_('Tags'), {'fields': ('tags',)}),
(_('Audit Trail'), {'fields': ('creation_date', 'created_by', 'audit_trail',)}), (_('Audit Trail'), {'fields': ('created', 'created_by', 'audit_trail',)}),
) )
readonly_fields = ('creation_date', 'created_by', 'audit_trail') readonly_fields = ('created', 'created_by', 'audit_trail')
filter_horizontal = ('tags',) filter_horizontal = ('tags',)
# FIXME: Edit reverse of many to many for groups. # FIXME: Edit reverse of many to many for groups.
#inlines = [VariableDataInline] #inlines = [VariableDataInline]
@@ -183,9 +183,9 @@ class GroupAdmin(BaseModelAdmin):
(None, {'fields': (('name', 'active'), 'inventory', 'description', (None, {'fields': (('name', 'active'), 'inventory', 'description',
'parents')}), 'parents')}),
(_('Tags'), {'fields': ('tags',)}), (_('Tags'), {'fields': ('tags',)}),
(_('Audit Trail'), {'fields': ('creation_date', 'created_by', 'audit_trail',)}), (_('Audit Trail'), {'fields': ('created', 'created_by', 'audit_trail',)}),
) )
readonly_fields = ('creation_date', 'created_by', 'audit_trail') readonly_fields = ('created', 'created_by', 'audit_trail')
filter_horizontal = ('parents', 'hosts', 'tags') filter_horizontal = ('parents', 'hosts', 'tags')
#inlines = [VariableDataInline] #inlines = [VariableDataInline]
@@ -202,9 +202,9 @@ class CredentialAdmin(BaseModelAdmin):
'ssh_key_data', 'ssh_key_unlock', 'ssh_key_data', 'ssh_key_unlock',
('sudo_username', 'sudo_password'))}), ('sudo_username', 'sudo_password'))}),
#(_('Tags'), {'fields': ('tags',)}), #(_('Tags'), {'fields': ('tags',)}),
(_('Audit Trail'), {'fields': ('creation_date', 'created_by', 'audit_trail',)}), (_('Audit Trail'), {'fields': ('created', 'created_by', 'audit_trail',)}),
) )
readonly_fields = ('creation_date', 'created_by', 'audit_trail') readonly_fields = ('created', 'created_by', 'audit_trail')
filter_horizontal = ('tags',) filter_horizontal = ('tags',)
class TeamAdmin(BaseModelAdmin): class TeamAdmin(BaseModelAdmin):
@@ -219,9 +219,9 @@ class ProjectAdmin(BaseModelAdmin):
(None, {'fields': (('name', 'active'), 'description', 'local_path', (None, {'fields': (('name', 'active'), 'description', 'local_path',
'get_available_playbooks_display')}), 'get_available_playbooks_display')}),
(_('Tags'), {'fields': ('tags',)}), (_('Tags'), {'fields': ('tags',)}),
(_('Audit Trail'), {'fields': ('creation_date', 'created_by', 'audit_trail',)}), (_('Audit Trail'), {'fields': ('created', 'created_by', 'audit_trail',)}),
) )
readonly_fields = ('creation_date', 'created_by', 'audit_trail', readonly_fields = ('created', 'created_by', 'audit_trail',
'get_available_playbooks_display') 'get_available_playbooks_display')
filter_horizontal = ('tags',) filter_horizontal = ('tags',)
@@ -245,14 +245,14 @@ class JobTemplateAdmin(BaseModelAdmin):
'get_create_link_display', 'get_jobs_link_display')}), 'get_create_link_display', 'get_jobs_link_display')}),
(_('Job Parameters'), {'fields': ('inventory', 'project', 'playbook', (_('Job Parameters'), {'fields': ('inventory', 'project', 'playbook',
'credential', 'job_type')}), 'credential', 'job_type')}),
(_('More Options'), {'fields': ('use_sudo', 'forks', 'limit', (_('More Options'), {'fields': ('forks', 'limit',
'verbosity', 'extra_vars'), 'verbosity', 'extra_vars'),
'classes': ('collapse',)}), 'classes': ('collapse',)}),
#(_('Tags'), {'fields': ('tags',)}), #(_('Tags'), {'fields': ('tags',)}),
(_('Audit Trail'), {'fields': ('creation_date', 'created_by', (_('Audit Trail'), {'fields': ('created', 'created_by',
'audit_trail',)}), 'audit_trail',)}),
) )
readonly_fields = ('creation_date', 'created_by', 'audit_trail', readonly_fields = ('created', 'created_by', 'audit_trail',
'get_create_link_display', 'get_jobs_link_display') 'get_create_link_display', 'get_jobs_link_display')
form = JobTemplateAdminForm form = JobTemplateAdminForm
#filter_horizontal = ('tags',) #filter_horizontal = ('tags',)
@@ -277,9 +277,6 @@ class JobTemplateAdmin(BaseModelAdmin):
create_opts['playbook'] = obj.playbook create_opts['playbook'] = obj.playbook
if obj.credential: if obj.credential:
create_opts['credential'] = obj.credential.pk create_opts['credential'] = obj.credential.pk
if obj.use_sudo is not None:
# Assume these are the defaults for a null boolean field select.
create_opts['use_sudo'] = 2 if obj.use_sudo else 3
if obj.forks: if obj.forks:
create_opts['forks'] = obj.forks create_opts['forks'] = obj.forks
if obj.limit: if obj.limit:
@@ -287,7 +284,7 @@ class JobTemplateAdmin(BaseModelAdmin):
if obj.verbosity: if obj.verbosity:
create_opts['verbosity'] = obj.verbosity create_opts['verbosity'] = obj.verbosity
if obj.extra_vars: if obj.extra_vars:
create_opts['extra_vars'] = json.dumps(obj.extra_vars) create_opts['extra_vars'] = obj.extra_vars
create_url += '?%s' % urllib.urlencode(create_opts) create_url += '?%s' % urllib.urlencode(create_opts)
return format_html('<a href="{0}">{1}</a>', create_url, 'Create Job') return format_html('<a href="{0}">{1}</a>', create_url, 'Create Job')
get_create_link_display.short_description = _('Create Job') get_create_link_display.short_description = _('Create Job')
@@ -313,8 +310,9 @@ class JobHostSummaryInlineForJob(JobHostSummaryInline):
class JobEventInlineForJob(JobEventInline): class JobEventInlineForJob(JobEventInline):
fields = ('created', 'event', 'get_event_data_display', 'host') fields = ('created', 'event', 'get_event_data_display', 'failed', 'host')
readonly_fields = ('created', 'event', 'get_event_data_display', 'host') readonly_fields = ('created', 'event', 'get_event_data_display', 'failed',
'host')
class JobAdmin(BaseModelAdmin): class JobAdmin(BaseModelAdmin):
@@ -324,24 +322,23 @@ class JobAdmin(BaseModelAdmin):
(None, {'fields': ('name', 'job_template', 'description')}), (None, {'fields': ('name', 'job_template', 'description')}),
(_('Job Parameters'), {'fields': ('inventory', 'project', 'playbook', (_('Job Parameters'), {'fields': ('inventory', 'project', 'playbook',
'credential', 'job_type')}), 'credential', 'job_type')}),
(_('More Options'), {'fields': ('use_sudo', 'forks', 'limit', (_('More Options'), {'fields': ('forks', 'limit', 'verbosity',
'verbosity', 'extra_vars'), 'extra_vars'),
'classes': ('collapse',)}), 'classes': ('collapse',)}),
(_('Start Job'), {'fields': ('start_job', 'ssh_password', (_('Start Job'), {'fields': ('start_job', 'ssh_password',
'sudo_password', 'ssh_key_unlock')}), 'sudo_password', 'ssh_key_unlock')}),
#(_('Tags'), {'fields': ('tags',)}), #(_('Tags'), {'fields': ('tags',)}),
(_('Audit Trail'), {'fields': ('creation_date', 'created_by', (_('Audit Trail'), {'fields': ('created', 'created_by',
'audit_trail',)}), 'audit_trail',)}),
(_('Job Status'), {'fields': (('status', 'cancel_job'), (_('Job Status'), {'fields': (('status', 'failed', 'cancel_job'),
'get_result_stdout_display', 'get_result_stdout_display',
'get_result_stderr_display',
'get_result_traceback_display', 'get_result_traceback_display',
'celery_task_id')}), 'celery_task_id')}),
) )
readonly_fields = ('status', 'get_job_template_display', readonly_fields = ('status', 'failed', 'get_job_template_display',
'get_result_stdout_display', 'get_result_stderr_display', 'get_result_stdout_display',
'get_result_traceback_display', 'celery_task_id', 'get_result_traceback_display', 'celery_task_id',
'creation_date', 'created_by', 'audit_trail',) 'created', 'created_by', 'audit_trail',)
filter_horizontal = ('tags',) filter_horizontal = ('tags',)
form = JobAdminForm form = JobAdminForm
inlines = [JobHostSummaryInlineForJob, JobEventInlineForJob] inlines = [JobHostSummaryInlineForJob, JobEventInlineForJob]
@@ -351,7 +348,7 @@ class JobAdmin(BaseModelAdmin):
if obj and obj.pk and obj.status != 'new': if obj and obj.pk and obj.status != 'new':
ro_fields.extend(['name', 'description', 'job_template', ro_fields.extend(['name', 'description', 'job_template',
'inventory', 'project', 'playbook', 'credential', 'inventory', 'project', 'playbook', 'credential',
'job_type', 'use_sudo', 'forks', 'limit', 'job_type', 'forks', 'limit',
'verbosity', 'extra_vars']) 'verbosity', 'extra_vars'])
return ro_fields return ro_fields
@@ -359,7 +356,7 @@ class JobAdmin(BaseModelAdmin):
fsets = list(super(JobAdmin, self).get_fieldsets(request, obj)) fsets = list(super(JobAdmin, self).get_fieldsets(request, obj))
if not obj or not obj.pk or obj.status == 'new': if not obj or not obj.pk or obj.status == 'new':
fsets = [fs for fs in fsets if fsets = [fs for fs in fsets if
'creation_date' not in fs[1]['fields'] and 'created' not in fs[1]['fields'] and
'celery_task_id' not in fs[1]['fields']] 'celery_task_id' not in fs[1]['fields']]
if not obj or (obj and obj.pk and obj.status != 'new'): if not obj or (obj and obj.pk and obj.status != 'new'):
fsets = [fs for fs in fsets if 'start_job' not in fs[1]['fields']] fsets = [fs for fs in fsets if 'start_job' not in fs[1]['fields']]
@@ -367,7 +364,6 @@ class JobAdmin(BaseModelAdmin):
for fs in fsets: for fs in fsets:
if 'celery_task_id' in fs[1]['fields']: if 'celery_task_id' in fs[1]['fields']:
fs[1]['fields'] = ('status', 'get_result_stdout_display', fs[1]['fields'] = ('status', 'get_result_stdout_display',
'get_result_stderr_display',
'get_result_traceback_display', 'get_result_traceback_display',
'celery_task_id') 'celery_task_id')
return fsets return fsets
@@ -397,12 +393,6 @@ class JobAdmin(BaseModelAdmin):
get_result_stdout_display.short_description = _('Stdout') get_result_stdout_display.short_description = _('Stdout')
get_result_stdout_display.allow_tags = True get_result_stdout_display.allow_tags = True
def get_result_stderr_display(self, obj):
return format_html('<pre class="result-display">{0}</pre>',
obj.result_stderr or ' ')
get_result_stderr_display.short_description = _('Stderr')
get_result_stderr_display.allow_tags = True
def get_result_traceback_display(self, obj): def get_result_traceback_display(self, obj):
return format_html('<pre class="result-display">{0}</pre>', return format_html('<pre class="result-display">{0}</pre>',
obj.result_traceback or ' ') obj.result_traceback or ' ')

View File

@@ -293,20 +293,25 @@ class VariableBaseDetail(BaseDetail):
this_object = None this_object = None
if hasattr(request.DATA, 'dict'):
data = request.DATA.dict()
else:
data = request.DATA
try: try:
this_object = getattr(through_obj, self.__class__.reverse_relationship, None) this_object = getattr(through_obj, self.__class__.reverse_relationship, None)
except: except:
pass pass
if this_object is None: if this_object is None:
this_object = self.__class__.model.objects.create(data=python_json.dumps(request.DATA)) this_object = self.__class__.model.objects.create(data=data)
else: else:
this_object.data = python_json.dumps(request.DATA) this_object.data = data
this_object.save() this_object.save()
setattr(through_obj, self.__class__.reverse_relationship, this_object) setattr(through_obj, self.__class__.reverse_relationship, this_object)
through_obj.save() through_obj.save()
return Response(status=status.HTTP_200_OK, data=python_json.loads(this_object.data)) return Response(status=status.HTTP_200_OK, data=this_object.data)
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
@@ -322,7 +327,7 @@ class VariableBaseDetail(BaseDetail):
if this_object is None: if this_object is None:
new_args = {} new_args = {}
new_args['data'] = python_json.dumps(dict()) new_args['data'] = {}
this_object = self.__class__.model.objects.create(**new_args) this_object = self.__class__.model.objects.create(**new_args)
setattr(through_obj, self.__class__.reverse_relationship, this_object) setattr(through_obj, self.__class__.reverse_relationship, this_object)
through_obj.save() through_obj.save()
@@ -333,5 +338,5 @@ class VariableBaseDetail(BaseDetail):
if not check_user_access(request.user, Inventory, 'read', through_obj.inventory): if not check_user_access(request.user, Inventory, 'read', through_obj.inventory):
raise PermissionDenied raise PermissionDenied
return Response(status=status.HTTP_200_OK, data=python_json.loads(this_object.data)) return Response(status=status.HTTP_200_OK, data=this_object.data)

View File

@@ -47,7 +47,7 @@ class Command(NoArgsCommand):
'children': list(group.children.values_list('name', flat=True)), 'children': list(group.children.values_list('name', flat=True)),
} }
if group.variable_data is not None: if group.variable_data is not None:
group_info['vars'] = json.loads(group.variable_data.data) group_info['vars'] = group.variable_data.data
group_info = dict(filter(lambda x: bool(x[1]), group_info.items())) group_info = dict(filter(lambda x: bool(x[1]), group_info.items()))
if group_info.keys() in ([], ['hosts']): if group_info.keys() in ([], ['hosts']):
@@ -66,7 +66,7 @@ class Command(NoArgsCommand):
raise CommandError('Host %s not found in the given inventory' % hostname) raise CommandError('Host %s not found in the given inventory' % hostname)
hostvars = {} hostvars = {}
if host.variable_data is not None: if host.variable_data is not None:
hostvars = json.loads(host.variable_data.data) hostvars = host.variable_data.data
self.stdout.write(json.dumps(hostvars, indent=indent)) self.stdout.write(json.dumps(hostvars, indent=indent))
def handle_noargs(self, **options): def handle_noargs(self, **options):

View File

@@ -0,0 +1,517 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Deleting field 'Job.creation_date'
db.delete_column(u'main_job', 'creation_date')
# Deleting field 'Job.use_sudo'
db.delete_column(u'main_job', 'use_sudo')
# Deleting field 'Job.result_stderr'
db.delete_column(u'main_job', 'result_stderr')
# Adding field 'Job.created'
db.add_column(u'main_job', 'created',
self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, default=datetime.datetime(2013, 5, 8, 0, 0), blank=True),
keep_default=False)
# Adding field 'Job.failed'
db.add_column(u'main_job', 'failed',
self.gf('django.db.models.fields.BooleanField')(default=False),
keep_default=False)
# Changing field 'Job.extra_vars'
db.alter_column(u'main_job', 'extra_vars', self.gf('django.db.models.fields.TextField')())
# Deleting field 'Inventory.creation_date'
db.delete_column(u'main_inventory', 'creation_date')
# Adding field 'Inventory.created'
db.add_column(u'main_inventory', 'created',
self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, default=datetime.datetime(2013, 5, 8, 0, 0), blank=True),
keep_default=False)
# Deleting field 'Host.creation_date'
db.delete_column(u'main_host', 'creation_date')
# Adding field 'Host.created'
db.add_column(u'main_host', 'created',
self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, default=datetime.datetime(2013, 5, 8, 0, 0), blank=True),
keep_default=False)
# Adding field 'Host.last_job'
db.add_column(u'main_host', 'last_job',
self.gf('django.db.models.fields.related.ForeignKey')(related_name='hosts_as_last_job+', on_delete=models.SET_NULL, default=None, to=orm['main.Job'], blank=True, null=True),
keep_default=False)
# Adding field 'Host.last_job_host_summary'
db.add_column(u'main_host', 'last_job_host_summary',
self.gf('django.db.models.fields.related.ForeignKey')(related_name='hosts_as_last_job_summary+', on_delete=models.SET_NULL, default=None, to=orm['main.JobHostSummary'], blank=True, null=True),
keep_default=False)
# Deleting field 'Group.creation_date'
db.delete_column(u'main_group', 'creation_date')
# Adding field 'Group.created'
db.add_column(u'main_group', 'created',
self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, default=datetime.datetime(2013, 5, 8, 0, 0), blank=True),
keep_default=False)
# Deleting field 'Credential.creation_date'
db.delete_column(u'main_credential', 'creation_date')
# Adding field 'Credential.created'
db.add_column(u'main_credential', 'created',
self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, default=datetime.datetime(2013, 5, 8, 0, 0), blank=True),
keep_default=False)
# Deleting field 'JobTemplate.use_sudo'
db.delete_column(u'main_jobtemplate', 'use_sudo')
# Deleting field 'JobTemplate.creation_date'
db.delete_column(u'main_jobtemplate', 'creation_date')
# Adding field 'JobTemplate.created'
db.add_column(u'main_jobtemplate', 'created',
self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, default=datetime.datetime(2013, 5, 8, 0, 0), blank=True),
keep_default=False)
# Changing field 'JobTemplate.extra_vars'
db.alter_column(u'main_jobtemplate', 'extra_vars', self.gf('django.db.models.fields.TextField')())
# Deleting field 'Team.creation_date'
db.delete_column(u'main_team', 'creation_date')
# Adding field 'Team.created'
db.add_column(u'main_team', 'created',
self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, default=datetime.datetime(2013, 5, 8, 0, 0), blank=True),
keep_default=False)
# Deleting field 'Project.creation_date'
db.delete_column(u'main_project', 'creation_date')
# Adding field 'Project.created'
db.add_column(u'main_project', 'created',
self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, default=datetime.datetime(2013, 5, 8, 0, 0), blank=True),
keep_default=False)
# Adding field 'JobEvent.failed'
db.add_column(u'main_jobevent', 'failed',
self.gf('django.db.models.fields.BooleanField')(default=False),
keep_default=False)
# Deleting field 'Permission.creation_date'
db.delete_column(u'main_permission', 'creation_date')
# Adding field 'Permission.created'
db.add_column(u'main_permission', 'created',
self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, default=datetime.datetime(2013, 5, 8, 0, 0), blank=True),
keep_default=False)
# Deleting field 'VariableData.creation_date'
db.delete_column(u'main_variabledata', 'creation_date')
# Adding field 'VariableData.created'
db.add_column(u'main_variabledata', 'created',
self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, default=datetime.datetime(2013, 5, 8, 0, 0), blank=True),
keep_default=False)
# Changing field 'VariableData.data'
db.alter_column(u'main_variabledata', 'data', self.gf('jsonfield.fields.JSONField')())
# Deleting field 'Organization.creation_date'
db.delete_column(u'main_organization', 'creation_date')
# Adding field 'Organization.created'
db.add_column(u'main_organization', 'created',
self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, default=datetime.datetime(2013, 5, 8, 0, 0), blank=True),
keep_default=False)
def backwards(self, orm):
# Adding field 'Job.creation_date'
db.add_column(u'main_job', 'creation_date',
self.gf('django.db.models.fields.DateField')(auto_now_add=True, default=datetime.datetime(2013, 5, 8, 0, 0), blank=True),
keep_default=False)
# Adding field 'Job.use_sudo'
db.add_column(u'main_job', 'use_sudo',
self.gf('django.db.models.fields.NullBooleanField')(default=None, null=True, blank=True),
keep_default=False)
# Adding field 'Job.result_stderr'
db.add_column(u'main_job', 'result_stderr',
self.gf('django.db.models.fields.TextField')(default='', blank=True),
keep_default=False)
# Deleting field 'Job.created'
db.delete_column(u'main_job', 'created')
# Deleting field 'Job.failed'
db.delete_column(u'main_job', 'failed')
# Changing field 'Job.extra_vars'
db.alter_column(u'main_job', 'extra_vars', self.gf('jsonfield.fields.JSONField')())
# Adding field 'Inventory.creation_date'
db.add_column(u'main_inventory', 'creation_date',
self.gf('django.db.models.fields.DateField')(auto_now_add=True, default=datetime.datetime(2013, 5, 8, 0, 0), blank=True),
keep_default=False)
# Deleting field 'Inventory.created'
db.delete_column(u'main_inventory', 'created')
# Adding field 'Host.creation_date'
db.add_column(u'main_host', 'creation_date',
self.gf('django.db.models.fields.DateField')(auto_now_add=True, default=datetime.datetime(2013, 5, 8, 0, 0), blank=True),
keep_default=False)
# Deleting field 'Host.created'
db.delete_column(u'main_host', 'created')
# Deleting field 'Host.last_job'
db.delete_column(u'main_host', 'last_job_id')
# Deleting field 'Host.last_job_host_summary'
db.delete_column(u'main_host', 'last_job_host_summary_id')
# Adding field 'Group.creation_date'
db.add_column(u'main_group', 'creation_date',
self.gf('django.db.models.fields.DateField')(auto_now_add=True, default=datetime.datetime(2013, 5, 8, 0, 0), blank=True),
keep_default=False)
# Deleting field 'Group.created'
db.delete_column(u'main_group', 'created')
# Adding field 'Credential.creation_date'
db.add_column(u'main_credential', 'creation_date',
self.gf('django.db.models.fields.DateField')(auto_now_add=True, default=datetime.datetime(2013, 5, 8, 0, 0), blank=True),
keep_default=False)
# Deleting field 'Credential.created'
db.delete_column(u'main_credential', 'created')
# Adding field 'JobTemplate.use_sudo'
db.add_column(u'main_jobtemplate', 'use_sudo',
self.gf('django.db.models.fields.NullBooleanField')(default=None, null=True, blank=True),
keep_default=False)
# Adding field 'JobTemplate.creation_date'
db.add_column(u'main_jobtemplate', 'creation_date',
self.gf('django.db.models.fields.DateField')(auto_now_add=True, default=datetime.datetime(2013, 5, 8, 0, 0), blank=True),
keep_default=False)
# Deleting field 'JobTemplate.created'
db.delete_column(u'main_jobtemplate', 'created')
# Changing field 'JobTemplate.extra_vars'
db.alter_column(u'main_jobtemplate', 'extra_vars', self.gf('jsonfield.fields.JSONField')())
# Adding field 'Team.creation_date'
db.add_column(u'main_team', 'creation_date',
self.gf('django.db.models.fields.DateField')(auto_now_add=True, default=datetime.datetime(2013, 5, 8, 0, 0), blank=True),
keep_default=False)
# Deleting field 'Team.created'
db.delete_column(u'main_team', 'created')
# Adding field 'Project.creation_date'
db.add_column(u'main_project', 'creation_date',
self.gf('django.db.models.fields.DateField')(auto_now_add=True, default=datetime.datetime(2013, 5, 8, 0, 0), blank=True),
keep_default=False)
# Deleting field 'Project.created'
db.delete_column(u'main_project', 'created')
# Deleting field 'JobEvent.failed'
db.delete_column(u'main_jobevent', 'failed')
# Adding field 'Permission.creation_date'
db.add_column(u'main_permission', 'creation_date',
self.gf('django.db.models.fields.DateField')(auto_now_add=True, default=datetime.datetime(2013, 5, 8, 0, 0), blank=True),
keep_default=False)
# Deleting field 'Permission.created'
db.delete_column(u'main_permission', 'created')
# Adding field 'VariableData.creation_date'
db.add_column(u'main_variabledata', 'creation_date',
self.gf('django.db.models.fields.DateField')(auto_now_add=True, default=datetime.datetime(2013, 5, 8, 0, 0), blank=True),
keep_default=False)
# Deleting field 'VariableData.created'
db.delete_column(u'main_variabledata', 'created')
# Changing field 'VariableData.data'
db.alter_column(u'main_variabledata', 'data', self.gf('django.db.models.fields.TextField')())
# Adding field 'Organization.creation_date'
db.add_column(u'main_organization', 'creation_date',
self.gf('django.db.models.fields.DateField')(auto_now_add=True, default=datetime.datetime(2013, 5, 8, 0, 0), blank=True),
keep_default=False)
# Deleting field 'Organization.created'
db.delete_column(u'main_organization', 'created')
models = {
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'main.audittrail': {
'Meta': {'object_name': 'AuditTrail'},
'comment': ('django.db.models.fields.TextField', [], {}),
'delta': ('django.db.models.fields.TextField', [], {}),
'detail': ('django.db.models.fields.TextField', [], {}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
'resource_type': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
'tag': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['main.Tag']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'})
},
'main.credential': {
'Meta': {'object_name': 'Credential'},
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'audit_trail': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'credential_by_audit_trail'", 'blank': 'True', 'to': "orm['main.AuditTrail']"}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': '"{\'class\': \'credential\', \'app_label\': \'main\'}(class)s_created"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}),
'ssh_key_data': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
'ssh_key_unlock': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
'ssh_password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
'ssh_username': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
'sudo_password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
'sudo_username': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'credential_by_tag'", 'blank': 'True', 'to': "orm['main.Tag']"}),
'team': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'credentials'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Team']", 'blank': 'True', 'null': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'credentials'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': u"orm['auth.User']", 'blank': 'True', 'null': 'True'})
},
'main.group': {
'Meta': {'unique_together': "(('name', 'inventory'),)", 'object_name': 'Group'},
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'audit_trail': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'group_by_audit_trail'", 'blank': 'True', 'to': "orm['main.AuditTrail']"}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': '"{\'class\': \'group\', \'app_label\': \'main\'}(class)s_created"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'groups'", 'blank': 'True', 'to': "orm['main.Host']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'groups'", 'to': "orm['main.Inventory']"}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}),
'parents': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'children'", 'blank': 'True', 'to': "orm['main.Group']"}),
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'group_by_tag'", 'blank': 'True', 'to': "orm['main.Tag']"}),
'variable_data': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'group'", 'unique': 'True', 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.VariableData']", 'blank': 'True', 'null': 'True'})
},
'main.host': {
'Meta': {'unique_together': "(('name', 'inventory'),)", 'object_name': 'Host'},
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'audit_trail': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'host_by_audit_trail'", 'blank': 'True', 'to': "orm['main.AuditTrail']"}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': '"{\'class\': \'host\', \'app_label\': \'main\'}(class)s_created"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'hosts'", 'to': "orm['main.Inventory']"}),
'last_job': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'hosts_as_last_job+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Job']", 'blank': 'True', 'null': 'True'}),
'last_job_host_summary': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'hosts_as_last_job_summary+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': u"orm['main.JobHostSummary']", 'blank': 'True', 'null': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}),
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'host_by_tag'", 'blank': 'True', 'to': "orm['main.Tag']"}),
'variable_data': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'host'", 'unique': 'True', 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.VariableData']", 'blank': 'True', 'null': 'True'})
},
'main.inventory': {
'Meta': {'unique_together': "(('name', 'organization'),)", 'object_name': 'Inventory'},
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'audit_trail': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'inventory_by_audit_trail'", 'blank': 'True', 'to': "orm['main.AuditTrail']"}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': '"{\'class\': \'inventory\', \'app_label\': \'main\'}(class)s_created"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}),
'organization': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'inventories'", 'to': "orm['main.Organization']"}),
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'inventory_by_tag'", 'blank': 'True', 'to': "orm['main.Tag']"})
},
'main.job': {
'Meta': {'object_name': 'Job'},
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'audit_trail': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'job_by_audit_trail'", 'blank': 'True', 'to': "orm['main.AuditTrail']"}),
'cancel_flag': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'celery_task_id': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100', 'blank': 'True'}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': '"{\'class\': \'job\', \'app_label\': \'main\'}(class)s_created"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Credential']"}),
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
'extra_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
'failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'forks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}),
'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'jobs'", 'blank': 'True', 'through': u"orm['main.JobHostSummary']", 'to': "orm['main.Host']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Inventory']"}),
'job_template': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.JobTemplate']", 'blank': 'True', 'null': 'True'}),
'job_type': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
'limit': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}),
'playbook': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['main.Project']"}),
'result_stdout': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
'result_traceback': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
'status': ('django.db.models.fields.CharField', [], {'default': "'new'", 'max_length': '20'}),
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'job_by_tag'", 'blank': 'True', 'to': "orm['main.Tag']"}),
'verbosity': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'})
},
'main.jobevent': {
'Meta': {'ordering': "('pk',)", 'object_name': 'JobEvent'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'event': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'event_data': ('jsonfield.fields.JSONField', [], {'default': "''", 'blank': 'True'}),
'failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'host': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'job_events'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Host']", 'blank': 'True', 'null': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'job': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'job_events'", 'to': "orm['main.Job']"})
},
u'main.jobhostsummary': {
'Meta': {'ordering': "('-pk',)", 'unique_together': "[('job', 'host')]", 'object_name': 'JobHostSummary'},
'changed': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
'dark': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
'failures': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
'host': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'job_host_summaries'", 'to': "orm['main.Host']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'job': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'job_host_summaries'", 'to': "orm['main.Job']"}),
'ok': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
'processed': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
'skipped': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})
},
'main.jobtemplate': {
'Meta': {'object_name': 'JobTemplate'},
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'audit_trail': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'jobtemplate_by_audit_trail'", 'blank': 'True', 'to': "orm['main.AuditTrail']"}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': '"{\'class\': \'jobtemplate\', \'app_label\': \'main\'}(class)s_created"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'job_templates'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
'extra_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
'forks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'job_templates'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Inventory']"}),
'job_type': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
'limit': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}),
'playbook': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}),
'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'job_templates'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['main.Project']"}),
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'jobtemplate_by_tag'", 'blank': 'True', 'to': "orm['main.Tag']"}),
'verbosity': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'})
},
'main.organization': {
'Meta': {'object_name': 'Organization'},
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'admins': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'admin_of_organizations'", 'blank': 'True', 'to': u"orm['auth.User']"}),
'audit_trail': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'organization_by_audit_trail'", 'blank': 'True', 'to': "orm['main.AuditTrail']"}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': '"{\'class\': \'organization\', \'app_label\': \'main\'}(class)s_created"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}),
'projects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'organizations'", 'blank': 'True', 'to': u"orm['main.Project']"}),
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'organization_by_tag'", 'blank': 'True', 'to': "orm['main.Tag']"}),
'users': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'organizations'", 'blank': 'True', 'to': u"orm['auth.User']"})
},
'main.permission': {
'Meta': {'object_name': 'Permission'},
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'audit_trail': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'permission_by_audit_trail'", 'blank': 'True', 'to': "orm['main.AuditTrail']"}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': '"{\'class\': \'permission\', \'app_label\': \'main\'}(class)s_created"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'permissions'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Inventory']"}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}),
'permission_type': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
'project': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'permissions'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['main.Project']"}),
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'permission_by_tag'", 'blank': 'True', 'to': "orm['main.Tag']"}),
'team': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'permissions'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Team']"}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'permissions'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"})
},
u'main.project': {
'Meta': {'object_name': 'Project'},
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'audit_trail': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'project_by_audit_trail'", 'blank': 'True', 'to': "orm['main.AuditTrail']"}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': '"{\'class\': \'project\', \'app_label\': u\'main\'}(class)s_created"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'local_path': ('django.db.models.fields.FilePathField', [], {'path': "'/Users/chris/Sandbox/ansible-commander/lib/projects'", 'unique': 'True', 'max_length': '1024'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}),
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'project_by_tag'", 'blank': 'True', 'to': "orm['main.Tag']"})
},
'main.tag': {
'Meta': {'object_name': 'Tag'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '512'})
},
'main.team': {
'Meta': {'object_name': 'Team'},
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'audit_trail': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'team_by_audit_trail'", 'blank': 'True', 'to': "orm['main.AuditTrail']"}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': '"{\'class\': \'team\', \'app_label\': \'main\'}(class)s_created"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}),
'organization': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'teams'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Organization']"}),
'projects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'teams'", 'blank': 'True', 'to': u"orm['main.Project']"}),
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'team_by_tag'", 'blank': 'True', 'to': "orm['main.Tag']"}),
'users': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'teams'", 'blank': 'True', 'to': u"orm['auth.User']"})
},
'main.variabledata': {
'Meta': {'object_name': 'VariableData'},
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'audit_trail': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'variabledata_by_audit_trail'", 'blank': 'True', 'to': "orm['main.AuditTrail']"}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': '"{\'class\': \'variabledata\', \'app_label\': \'main\'}(class)s_created"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}),
'data': ('jsonfield.fields.JSONField', [], {'default': "''"}),
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}),
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'variabledata_by_tag'", 'blank': 'True', 'to': "orm['main.Tag']"})
}
}
complete_apps = ['main']

View File

@@ -30,6 +30,7 @@ from jsonfield import JSONField
from djcelery.models import TaskMeta from djcelery.models import TaskMeta
from rest_framework.authtoken.models import Token from rest_framework.authtoken.models import Token
import yaml import yaml
from lib.main.fields import *
# TODO: reporting model TBD # TODO: reporting model TBD
@@ -81,7 +82,7 @@ class EditHelper(object):
@classmethod @classmethod
def illegal_changes(cls, request, obj, model_class): def illegal_changes(cls, request, obj, model_class):
''' have any illegal changes been made (for a PUT request)? ''' ''' have any illegal changes been made (for a PUT request)? '''
from lib.main.access import * from lib.main.access import check_user_access
#can_admin = model_class.can_user_administrate(request.user, obj, request.DATA) #can_admin = model_class.can_user_administrate(request.user, obj, request.DATA)
can_admin = check_user_access(request.user, User, 'change', obj, request.DATA) can_admin = check_user_access(request.user, User, 'change', obj, request.DATA)
if (not can_admin) or (can_admin == 'partial'): if (not can_admin) or (can_admin == 'partial'):
@@ -121,9 +122,7 @@ class PrimordialModel(models.Model):
description = models.TextField(blank=True, default='') description = models.TextField(blank=True, default='')
created_by = models.ForeignKey('auth.User', on_delete=SET_NULL, null=True, related_name='%s(class)s_created', editable=False) # not blank=False on purpose for admin! created_by = models.ForeignKey('auth.User', on_delete=SET_NULL, null=True, related_name='%s(class)s_created', editable=False) # not blank=False on purpose for admin!
creation_date = models.DateField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
#created = models.DateTimeField(auto_now_add=True)
#modified = models.DateTimeField(auto_now=True)
tags = models.ManyToManyField('Tag', related_name='%(class)s_by_tag', blank=True) tags = models.ManyToManyField('Tag', related_name='%(class)s_by_tag', blank=True)
audit_trail = models.ManyToManyField('AuditTrail', related_name='%(class)s_by_audit_trail', blank=True) audit_trail = models.ManyToManyField('AuditTrail', related_name='%(class)s_by_audit_trail', blank=True)
active = models.BooleanField(default=True) active = models.BooleanField(default=True)
@@ -222,8 +221,10 @@ class Host(CommonModelNameNotUnique):
app_label = 'main' app_label = 'main'
unique_together = (("name", "inventory"),) unique_together = (("name", "inventory"),)
variable_data = models.OneToOneField('VariableData', null=True, default=None, blank=True, on_delete=SET_NULL, related_name='host') variable_data = models.OneToOneField('VariableData', null=True, default=None, blank=True, on_delete=SET_NULL, related_name='host')
inventory = models.ForeignKey('Inventory', null=False, related_name='hosts') inventory = models.ForeignKey('Inventory', null=False, related_name='hosts')
last_job = models.ForeignKey('Job', blank=True, null=True, default=None, on_delete=models.SET_NULL, related_name='hosts_as_last_job+')
last_job_host_summary = models.ForeignKey('JobHostSummary', blank=True, null=True, default=None, on_delete=models.SET_NULL, related_name='hosts_as_last_job_summary+')
def __unicode__(self): def __unicode__(self):
return self.name return self.name
@@ -269,7 +270,7 @@ class VariableData(CommonModelNameNotUnique):
#host = models.OneToOneField('Host', null=True, default=None, blank=True, on_delete=SET_NULL, related_name='variable_data') #host = models.OneToOneField('Host', null=True, default=None, blank=True, on_delete=SET_NULL, related_name='variable_data')
#group = models.OneToOneField('Group', null=True, default=None, blank=True, on_delete=SET_NULL, related_name='variable_data') #group = models.OneToOneField('Group', null=True, default=None, blank=True, on_delete=SET_NULL, related_name='variable_data')
data = models.TextField() # FIXME: JsonField (and validation) data = JSONField(default='')
def __unicode__(self): def __unicode__(self):
return '%s = %s' % (self.name, self.data) return '%s = %s' % (self.name, self.data)
@@ -499,10 +500,6 @@ class JobTemplate(CommonModel):
default=None, default=None,
on_delete=models.SET_NULL, on_delete=models.SET_NULL,
) )
use_sudo = models.NullBooleanField(
blank=True,
default=None,
)
forks = models.PositiveIntegerField( forks = models.PositiveIntegerField(
blank=True, blank=True,
default=0, default=0,
@@ -516,7 +513,7 @@ class JobTemplate(CommonModel):
blank=True, blank=True,
default=0, default=0,
) )
extra_vars = JSONField( extra_vars = models.TextField(
blank=True, blank=True,
default='', default='',
) )
@@ -534,7 +531,6 @@ class JobTemplate(CommonModel):
kwargs.setdefault('project', self.project) kwargs.setdefault('project', self.project)
kwargs.setdefault('playbook', self.playbook) kwargs.setdefault('playbook', self.playbook)
kwargs.setdefault('credential', self.credential) kwargs.setdefault('credential', self.credential)
kwargs.setdefault('use_sudo', self.use_sudo)
kwargs.setdefault('forks', self.forks) kwargs.setdefault('forks', self.forks)
kwargs.setdefault('limit', self.limit) kwargs.setdefault('limit', self.limit)
kwargs.setdefault('verbosity', self.verbosity) kwargs.setdefault('verbosity', self.verbosity)
@@ -600,10 +596,6 @@ class Job(CommonModel):
playbook = models.CharField( playbook = models.CharField(
max_length=1024, max_length=1024,
) )
use_sudo = models.NullBooleanField(
blank=True,
default=None,
)
forks = models.PositiveIntegerField( forks = models.PositiveIntegerField(
blank=True, blank=True,
default=0, default=0,
@@ -617,7 +609,7 @@ class Job(CommonModel):
blank=True, blank=True,
default=0, default=0,
) )
extra_vars = JSONField( extra_vars = models.TextField(
blank=True, blank=True,
default='', default='',
) )
@@ -631,12 +623,10 @@ class Job(CommonModel):
default='new', default='new',
editable=False, editable=False,
) )
result_stdout = models.TextField( failed = models.BooleanField(
blank=True, default=False,
default='',
editable=False,
) )
result_stderr = models.TextField( result_stdout = models.TextField(
blank=True, blank=True,
default='', default='',
editable=False, editable=False,
@@ -663,6 +653,14 @@ class Job(CommonModel):
def get_absolute_url(self): def get_absolute_url(self):
return reverse('main:job_detail', args=(self.pk,)) return reverse('main:job_detail', args=(self.pk,))
def save(self, *args, **kwargs):
self.failed = bool(self.status in ('failed', 'error', 'canceled'))
super(Job, self).save(*args, **kwargs)
@property
def extra_vars_dict(self):
'''Return extra_vars key=value pairs as a dictionary.'''
@property @property
def celery_task(self): def celery_task(self):
try: try:
@@ -795,8 +793,16 @@ class JobEvent(models.Model):
('playbook_on_stats', _('Playbook on Stats')), ('playbook_on_stats', _('Playbook on Stats')),
] ]
FAILED_EVENTS = [
'runner_on_failed',
'runner_on_error',
'runner_on_unreachable',
'runner_on_async_failed',
]
class Meta: class Meta:
app_label = 'main' app_label = 'main'
ordering = ('pk',)
job = models.ForeignKey( job = models.ForeignKey(
'Job', 'Job',
@@ -814,6 +820,9 @@ class JobEvent(models.Model):
blank=True, blank=True,
default='', default='',
) )
failed = models.BooleanField(
default=False,
)
host = models.ForeignKey( host = models.ForeignKey(
'Host', 'Host',
related_name='job_events', related_name='job_events',
@@ -835,6 +844,7 @@ class JobEvent(models.Model):
self.host = self.job.inventory.hosts.get(name=self.event_data['host']) self.host = self.job.inventory.hosts.get(name=self.event_data['host'])
except (Host.DoesNotExist, AttributeError): except (Host.DoesNotExist, AttributeError):
pass pass
self.failed = bool(self.event in self.FAILED_EVENTS)
super(JobEvent, self).save(*args, **kwargs) super(JobEvent, self).save(*args, **kwargs)
self.update_host_summary_from_stats() self.update_host_summary_from_stats()

View File

@@ -25,7 +25,8 @@ from rest_framework.templatetags.rest_framework import replace_query_param
# Ansible Commander # Ansible Commander
from lib.main.models import * from lib.main.models import *
BASE_FIELDS = ('id', 'url', 'related', 'summary_fields', 'creation_date', 'name', 'description') BASE_FIELDS = ('id', 'url', 'related', 'summary_fields', 'created',
'creation_date', 'name', 'description')
class NextPageField(pagination.NextPageField): class NextPageField(pagination.NextPageField):
''' makes the pagination relative URL not full URL ''' ''' makes the pagination relative URL not full URL '''
@@ -76,7 +77,8 @@ class BaseSerializer(serializers.ModelSerializer):
summary_fields = serializers.SerializerMethodField('get_summary_fields') summary_fields = serializers.SerializerMethodField('get_summary_fields')
# make certain fields read only # make certain fields read only
creation_date = serializers.SerializerMethodField('get_creation_date') # FIXME: is model Date or DateTime, fix model created = serializers.SerializerMethodField('get_created')
creation_date = serializers.SerializerMethodField('get_creation_date') # FIXME: temporarily left this field in case anything uses it.. should be removed.
active = serializers.SerializerMethodField('get_active') active = serializers.SerializerMethodField('get_active')
def get_absolute_url(self, obj): def get_absolute_url(self, obj):
@@ -109,7 +111,13 @@ class BaseSerializer(serializers.ModelSerializer):
if isinstance(obj, User): if isinstance(obj, User):
return obj.date_joined.date() return obj.date_joined.date()
else: else:
return obj.creation_date return obj.created.date()
def get_created(self, obj):
if isinstance(obj, User):
return obj.date_joined
else:
return obj.created
def get_active(self, obj): def get_active(self, obj):
if isinstance(obj, User): if isinstance(obj, User):
@@ -280,8 +288,8 @@ class UserSerializer(BaseSerializer):
class Meta: class Meta:
model = User model = User
fields = ('id', 'url', 'related', 'creation_date', 'username', fields = ('id', 'url', 'related', 'created', 'creation_date',
'first_name', 'last_name', 'email', 'is_active', 'username', 'first_name', 'last_name', 'email', 'is_active',
'is_superuser',) 'is_superuser',)
def get_related(self, obj): def get_related(self, obj):
@@ -330,8 +338,8 @@ class JobTemplateSerializer(BaseSerializer):
class Meta: class Meta:
model = JobTemplate model = JobTemplate
fields = BASE_FIELDS + ('job_type', 'inventory', 'project', 'playbook', fields = BASE_FIELDS + ('job_type', 'inventory', 'project', 'playbook',
'credential', 'use_sudo', 'forks', 'limit', 'credential', 'forks', 'limit', 'verbosity',
'verbosity', 'extra_vars') 'extra_vars')
def get_related(self, obj): def get_related(self, obj):
res = super(JobTemplateSerializer, self).get_related(obj) res = super(JobTemplateSerializer, self).get_related(obj)
@@ -352,9 +360,10 @@ class JobSerializer(BaseSerializer):
model = Job model = Job
fields = BASE_FIELDS + ('job_template', 'job_type', 'inventory', fields = BASE_FIELDS + ('job_template', 'job_type', 'inventory',
'project', 'playbook', 'credential', 'project', 'playbook', 'credential',
'use_sudo', 'forks', 'limit', 'verbosity', 'forks', 'limit', 'verbosity', 'extra_vars',
'extra_vars', 'status', 'result_stdout', 'status', 'failed', 'result_stdout',
'result_traceback', 'passwords_needed_to_start') 'result_traceback',
'passwords_needed_to_start')
def get_related(self, obj): def get_related(self, obj):
res = super(JobSerializer, self).get_related(obj) res = super(JobSerializer, self).get_related(obj)
@@ -387,7 +396,8 @@ class JobEventSerializer(BaseSerializer):
class Meta: class Meta:
model = JobEvent model = JobEvent
fields = ('id', 'url', 'job', 'event', 'event_data', 'host', 'related') fields = ('id', 'url', 'job', 'event', 'event_data', 'failed', 'host',
'related')
def get_related(self, obj): def get_related(self, obj):
res = super(JobEventSerializer, self).get_related(obj) res = super(JobEventSerializer, self).get_related(obj)

View File

@@ -45,9 +45,13 @@ class RunJob(Task):
''' '''
job = Job.objects.get(pk=job_pk) job = Job.objects.get(pk=job_pk)
if job_updates: if job_updates:
update_fields = []
for field, value in job_updates.items(): for field, value in job_updates.items():
setattr(job, field, value) setattr(job, field, value)
job.save(update_fields=job_updates.keys()) update_fields.append(field)
if field == 'status':
update_fields.append('failed')
job.save(update_fields=update_fields)
return job return job
def get_path_to(self, *args): def get_path_to(self, *args):
@@ -120,25 +124,20 @@ class RunJob(Task):
args = ['ansible-playbook', '-i', inventory_script] args = ['ansible-playbook', '-i', inventory_script]
if job.job_type == 'check': if job.job_type == 'check':
args.append('--check') args.append('--check')
args.append('--user=%s' % ssh_username) args.extend(['-u', ssh_username])
if 'ssh_password' in kwargs.get('passwords', {}): if 'ssh_password' in kwargs.get('passwords', {}):
args.append('--ask-pass') args.append('--ask-pass')
if job.use_sudo: args.extend(['-U', sudo_username])
args.append('--sudo')
args.append('--sudo-user=%s' % sudo_username)
if 'sudo_password' in kwargs.get('passwords', {}): if 'sudo_password' in kwargs.get('passwords', {}):
args.append('--ask-sudo-pass') args.append('--ask-sudo-pass')
if job.forks: # FIXME: Max limit? if job.forks: # FIXME: Max limit?
args.append('--forks=%d' % job.forks) args.append('--forks=%d' % job.forks)
if job.limit: if job.limit:
args.append('--limit=%s' % job.limit) args.extend(['-l', job.limit])
if job.verbosity: if job.verbosity:
args.append('-%s' % ('v' * min(3, job.verbosity))) args.append('-%s' % ('v' * min(3, job.verbosity)))
if job.extra_vars: if job.extra_vars:
# FIXME: escaping! args.extend(['-e', job.extra_vars])
extra_vars = ' '.join(['%s=%s' % (str(k), str(v)) for k,v in
job.extra_vars.items()])
args.append('--extra-vars=%s' % extra_vars)
args.append(job.playbook) # relative path to project.local_path args.append(job.playbook) # relative path to project.local_path
ssh_key_path = kwargs.get('ssh_key_path', '') ssh_key_path = kwargs.get('ssh_key_path', '')
if ssh_key_path: if ssh_key_path:
@@ -152,7 +151,7 @@ class RunJob(Task):
Run the job using pexpect to capture output and provide passwords when Run the job using pexpect to capture output and provide passwords when
requested. requested.
''' '''
status, stdout, stderr = 'error', '', '' status, stdout = 'error', ''
logfile = cStringIO.StringIO() logfile = cStringIO.StringIO()
logfile_pos = logfile.tell() logfile_pos = logfile.tell()
child = pexpect.spawn(args[0], args[1:], cwd=cwd, env=env) child = pexpect.spawn(args[0], args[1:], cwd=cwd, env=env)
@@ -190,22 +189,22 @@ class RunJob(Task):
else: else:
status = 'failed' status = 'failed'
stdout = logfile.getvalue() stdout = logfile.getvalue()
return status, stdout, stderr return status, stdout
def run(self, job_pk, **kwargs): def run(self, job_pk, **kwargs):
''' '''
Run the job using ansible-playbook and capture its output. Run the job using ansible-playbook and capture its output.
''' '''
job = self.update_job(job_pk, status='running') job = self.update_job(job_pk, status='running')
status, stdout, stderr, tb = 'error', '', '', '' status, stdout, tb = 'error', '', ''
try: try:
kwargs['ssh_key_path'] = self.build_ssh_key_path(job, **kwargs) kwargs['ssh_key_path'] = self.build_ssh_key_path(job, **kwargs)
kwargs['passwords'] = self.build_passwords(job, **kwargs) kwargs['passwords'] = self.build_passwords(job, **kwargs)
args = self.build_args(job, **kwargs) args = self.build_args(job, **kwargs)
cwd = job.project.local_path cwd = job.project.local_path
env = self.build_env(job, **kwargs) env = self.build_env(job, **kwargs)
status, stdout, stderr = self.run_pexpect(job_pk, args, cwd, env, status, stdout = self.run_pexpect(job_pk, args, cwd, env,
kwargs['passwords']) kwargs['passwords'])
except Exception: except Exception:
tb = traceback.format_exc() tb = traceback.format_exc()
finally: finally:
@@ -215,4 +214,4 @@ class RunJob(Task):
except IOError: except IOError:
pass pass
self.update_job(job_pk, status=status, result_stdout=stdout, self.update_job(job_pk, status=status, result_stdout=stdout,
result_stderr=stderr, result_traceback=tb) result_traceback=tb)

View File

@@ -124,7 +124,7 @@ class AcomInventoryTest(BaseCommandTest):
hosts = [] hosts = []
for x in xrange(10): for x in xrange(10):
if n > 0: if n > 0:
variable_data = VariableData.objects.create(data=json.dumps({'ho': 'hum-%d' % x})) variable_data = VariableData.objects.create(data={'ho': 'hum-%d' % x})
else: else:
variable_data = None variable_data = None
host = inventory.hosts.create(name='host-%02d-%02d.example.com' % (n, x), host = inventory.hosts.create(name='host-%02d-%02d.example.com' % (n, x),
@@ -135,7 +135,7 @@ class AcomInventoryTest(BaseCommandTest):
groups = [] groups = []
for x in xrange(5): for x in xrange(5):
if n > 0: if n > 0:
variable_data = VariableData.objects.create(data=json.dumps({'gee': 'whiz-%d' % x})) variable_data = VariableData.objects.create(data={'gee': 'whiz-%d' % x})
else: else:
variable_data = None variable_data = None
group = inventory.groups.create(name='group-%d' % x, group = inventory.groups.create(name='group-%d' % x,
@@ -199,7 +199,7 @@ class AcomInventoryTest(BaseCommandTest):
set(group.hosts.values_list('name', flat=True))) set(group.hosts.values_list('name', flat=True)))
if group.variable_data: if group.variable_data:
self.assertEqual(v.get('vars', {}), self.assertEqual(v.get('vars', {}),
json.loads(group.variable_data.data)) group.variable_data.data)
if k == 'group-3': if k == 'group-3':
self.assertEqual(set(v.get('children', [])), self.assertEqual(set(v.get('children', [])),
set(group.children.values_list('name', flat=True))) set(group.children.values_list('name', flat=True)))
@@ -224,7 +224,7 @@ class AcomInventoryTest(BaseCommandTest):
host=host.name) host=host.name)
self.assertEqual(result, None) self.assertEqual(result, None)
data = json.loads(stdout) data = json.loads(stdout)
self.assertEqual(data, json.loads(host.variable_data.data)) self.assertEqual(data, host.variable_data.data)
def test_invalid_host(self): def test_invalid_host(self):
# Valid host, but not part of the specified inventory. # Valid host, but not part of the specified inventory.

View File

@@ -86,7 +86,7 @@ class OrganizationsTest(BaseTest):
self.check_pagination_and_size(response, 10, previous=None, next=None) self.check_pagination_and_size(response, 10, previous=None, next=None)
self.assertEqual(len(response['results']), self.assertEqual(len(response['results']),
Organization.objects.count()) Organization.objects.count())
for field in ['id', 'url', 'name', 'description', 'creation_date']: for field in ['id', 'url', 'name', 'description', 'created']:
self.assertTrue(field in response['results'][0], self.assertTrue(field in response['results'][0],
'field %s not in result' % field) 'field %s not in result' % field)

View File

@@ -213,7 +213,6 @@ class RunJobTest(BaseCeleryTest):
self.assertEqual(job.status, 'pending') self.assertEqual(job.status, 'pending')
job = Job.objects.get(pk=job.pk) job = Job.objects.get(pk=job.pk)
#print 'stdout:', job.result_stdout #print 'stdout:', job.result_stdout
#print 'stderr:', job.result_stderr
#print job.status #print job.status
#print settings.DATABASES #print settings.DATABASES
#print self.run_job_args #print self.run_job_args
@@ -352,9 +351,8 @@ class RunJobTest(BaseCeleryTest):
def test_extra_job_options(self): def test_extra_job_options(self):
self.create_test_project(TEST_PLAYBOOK) self.create_test_project(TEST_PLAYBOOK)
job_template = self.create_test_job_template(use_sudo=True, forks=3, job_template = self.create_test_job_template(forks=3, verbosity=2,
verbosity=2, extra_vars='foo=1')
extra_vars={'foo': 1})
job = self.create_test_job(job_template=job_template) job = self.create_test_job(job_template=job_template)
self.assertEqual(job.status, 'new') self.assertEqual(job.status, 'new')
self.assertFalse(job.get_passwords_needed_to_start()) self.assertFalse(job.get_passwords_needed_to_start())
@@ -365,10 +363,9 @@ class RunJobTest(BaseCeleryTest):
# privileges, but we're mainly checking the command line arguments. # privileges, but we're mainly checking the command line arguments.
self.assertTrue(job.status in ('successful', 'failed')) self.assertTrue(job.status in ('successful', 'failed'))
self.assertTrue(job.result_stdout) self.assertTrue(job.result_stdout)
self.assertTrue('--sudo' in self.run_job_args)
self.assertTrue('--forks=3' in self.run_job_args) self.assertTrue('--forks=3' in self.run_job_args)
self.assertTrue('-vv' in self.run_job_args) self.assertTrue('-vv' in self.run_job_args)
self.assertTrue('--extra-vars=foo=1' in self.run_job_args) self.assertTrue('-e' in self.run_job_args)
def test_limit_option(self): def test_limit_option(self):
self.create_test_project(TEST_PLAYBOOK) self.create_test_project(TEST_PLAYBOOK)
@@ -380,7 +377,7 @@ class RunJobTest(BaseCeleryTest):
self.assertEqual(job.status, 'pending') self.assertEqual(job.status, 'pending')
job = Job.objects.get(pk=job.pk) job = Job.objects.get(pk=job.pk)
self.assertEqual(job.status, 'failed') self.assertEqual(job.status, 'failed')
self.assertTrue('--limit=bad.example.com' in self.run_job_args) self.assertTrue('-l' in self.run_job_args)
def test_ssh_username_and_password(self): def test_ssh_username_and_password(self):
self.create_test_credential(ssh_username='sshuser', self.create_test_credential(ssh_username='sshuser',
@@ -394,7 +391,7 @@ class RunJobTest(BaseCeleryTest):
self.assertEqual(job.status, 'pending') self.assertEqual(job.status, 'pending')
job = Job.objects.get(pk=job.pk) job = Job.objects.get(pk=job.pk)
self.assertEqual(job.status, 'successful') self.assertEqual(job.status, 'successful')
self.assertTrue('--user=sshuser' in self.run_job_args) self.assertTrue('-u' in self.run_job_args)
self.assertTrue('--ask-pass' in self.run_job_args) self.assertTrue('--ask-pass' in self.run_job_args)
def test_ssh_ask_password(self): def test_ssh_ask_password(self):
@@ -427,7 +424,7 @@ class RunJobTest(BaseCeleryTest):
# Job may fail if current user doesn't have password-less sudo # Job may fail if current user doesn't have password-less sudo
# privileges, but we're mainly checking the command line arguments. # privileges, but we're mainly checking the command line arguments.
self.assertTrue(job.status in ('successful', 'failed')) self.assertTrue(job.status in ('successful', 'failed'))
self.assertTrue('--sudo-user=sudouser' in self.run_job_args) self.assertTrue('-U' in self.run_job_args)
self.assertTrue('--ask-sudo-pass' in self.run_job_args) self.assertTrue('--ask-sudo-pass' in self.run_job_args)
def test_sudo_ask_password(self): def test_sudo_ask_password(self):

View File

@@ -221,7 +221,7 @@ LOGGING = {
'handlers': ['console'], 'handlers': ['console'],
}, },
'django.request': { 'django.request': {
'handlers': ['console','mail_admins'], 'handlers': ['mail_admins', 'console'],
'level': 'ERROR', 'level': 'ERROR',
'propagate': False, 'propagate': False,
}, },