mirror of
https://github.com/ansible/awx.git
synced 2026-01-17 04:31:21 -03:30
Removed admin support (no longer used or maintained).
This commit is contained in:
parent
7754f475ad
commit
352197c5d2
@ -1,391 +0,0 @@
|
||||
# Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
# All Rights Reserved.
|
||||
|
||||
# Django admin isn't officially supported!
|
||||
|
||||
# Python
|
||||
import json
|
||||
import urllib
|
||||
|
||||
# Django
|
||||
from django.conf.urls import *
|
||||
from django.contrib import admin
|
||||
from django.contrib.admin.util import unquote
|
||||
from django.contrib import messages
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.utils.timezone import now
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.auth.admin import UserAdmin
|
||||
|
||||
# AWX
|
||||
from awx.lib.compat import format_html
|
||||
from awx.main.models import *
|
||||
from awx.main.forms import *
|
||||
|
||||
|
||||
class UserAdmin(UserAdmin):
|
||||
fieldsets = (
|
||||
(None, {'fields': ('username', 'password')}),
|
||||
(_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),
|
||||
(_('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser')}),
|
||||
(_('Important dates'), {'fields': ('last_login', 'date_joined')}),
|
||||
)
|
||||
readonly_fields = ('last_login', 'date_joined')
|
||||
list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff')
|
||||
list_filter = ('is_staff', 'is_superuser', 'is_active', 'groups')
|
||||
search_fields = ('username', 'first_name', 'last_name', 'email')
|
||||
ordering = ('username',)
|
||||
|
||||
try:
|
||||
admin.site.unregister(User)
|
||||
except admin.site.NotRegistered:
|
||||
pass
|
||||
admin.site.register(User, UserAdmin)
|
||||
|
||||
# FIXME: Hide auth.Group admin
|
||||
|
||||
class BaseModelAdmin(admin.ModelAdmin):
|
||||
|
||||
def save_model(self, request, obj, form, change):
|
||||
# Automatically set created_by when saved from the admin.
|
||||
# FIXME: Doesn't handle inline model instances yet.
|
||||
if hasattr(obj, 'created_by') and obj.created_by is None:
|
||||
obj.created_by = request.user
|
||||
return super(BaseModelAdmin, self).save_model(request, obj, form, change)
|
||||
|
||||
class OrganizationAdmin(BaseModelAdmin):
|
||||
|
||||
list_display = ('name', 'description', 'active')
|
||||
list_filter = ('active', 'tags')
|
||||
fieldsets = (
|
||||
(None, {'fields': (('name', 'active'), 'description',)}),
|
||||
(_('Members'), {'fields': ('users', 'admins',)}),
|
||||
(_('Projects'), {'fields': ('projects',)}),
|
||||
(_('Tags'), {'fields': ('tags',)}),
|
||||
(_('Audit'), {'fields': ('created', 'created_by',)}),
|
||||
)
|
||||
readonly_fields = ('active', 'created', 'created_by')
|
||||
filter_horizontal = ('users', 'admins', 'projects')
|
||||
|
||||
class InventoryHostInline(admin.StackedInline):
|
||||
|
||||
model = Host
|
||||
extra = 0
|
||||
fields = ('name', 'description', 'active', 'tags')
|
||||
readonly_fields = ('active',)
|
||||
|
||||
class InventoryGroupInline(admin.StackedInline):
|
||||
|
||||
model = Group
|
||||
extra = 0
|
||||
fields = ('name', 'description', 'active', 'parents', 'hosts', 'tags')
|
||||
readonly_fields = ('active',)
|
||||
filter_horizontal = ('parents', 'hosts')
|
||||
|
||||
class InventoryAdmin(BaseModelAdmin):
|
||||
|
||||
list_display = ('name', 'organization', 'description', 'active')
|
||||
list_filter = ('organization', 'active')
|
||||
form = InventoryAdminForm
|
||||
fieldsets = (
|
||||
(None, {'fields': (('name', 'active'), 'organization', 'description',
|
||||
'variables')}),
|
||||
(_('Tags'), {'fields': ('tags',)}),
|
||||
(_('Audit'), {'fields': ('created', 'created_by',)}),
|
||||
)
|
||||
readonly_fields = ('active', 'created', 'created_by')
|
||||
inlines = [InventoryHostInline, InventoryGroupInline]
|
||||
|
||||
class JobHostSummaryInline(admin.TabularInline):
|
||||
|
||||
model = JobHostSummary
|
||||
extra = 0
|
||||
can_delete = False
|
||||
|
||||
def has_add_permission(self, request):
|
||||
return False
|
||||
|
||||
class JobEventInline(admin.StackedInline):
|
||||
|
||||
model = JobEvent
|
||||
extra = 0
|
||||
can_delete = False
|
||||
|
||||
def has_add_permission(self, request):
|
||||
return False
|
||||
|
||||
def get_event_data_display(self, obj):
|
||||
return format_html('<pre class="json-display">{0}</pre>',
|
||||
json.dumps(obj.event_data, indent=4))
|
||||
get_event_data_display.short_description = _('Event data')
|
||||
get_event_data_display.allow_tags = True
|
||||
|
||||
class JobHostSummaryInlineForHost(JobHostSummaryInline):
|
||||
|
||||
fields = ('job', 'changed', 'dark', 'failures', 'ok', 'processed',
|
||||
'skipped', 'failed')
|
||||
readonly_fields = ('job', 'changed', 'dark', 'failures', 'ok', 'processed',
|
||||
'skipped', 'failed')
|
||||
|
||||
class JobEventInlineForHost(JobEventInline):
|
||||
|
||||
fields = ('job', 'created', 'event', 'get_event_data_display')
|
||||
readonly_fields = ('job', 'created', 'event', 'get_event_data_display')
|
||||
|
||||
class HostAdmin(BaseModelAdmin):
|
||||
|
||||
list_display = ('name', 'inventory', 'description', 'active')
|
||||
list_filter = ('inventory', 'active')
|
||||
form = HostAdminForm
|
||||
fieldsets = (
|
||||
(None, {'fields': (('name', 'active'), 'inventory', 'description',
|
||||
'variables',
|
||||
)}),
|
||||
(_('Tags'), {'fields': ('tags',)}),
|
||||
(_('Audit'), {'fields': ('created', 'created_by',)}),
|
||||
)
|
||||
readonly_fields = ('active', 'created', 'created_by')
|
||||
# FIXME: Edit reverse of many to many for groups.
|
||||
inlines = [JobHostSummaryInlineForHost, JobEventInlineForHost]
|
||||
|
||||
class GroupAdmin(BaseModelAdmin):
|
||||
|
||||
list_display = ('name', 'description', 'active')
|
||||
form = GroupAdminForm
|
||||
fieldsets = (
|
||||
(None, {'fields': (('name', 'active'), 'inventory', 'description',
|
||||
'parents', 'variables')}),
|
||||
(_('Tags'), {'fields': ('tags',)}),
|
||||
(_('Audit'), {'fields': ('created', 'created_by',)}),
|
||||
)
|
||||
readonly_fields = ('active', 'created', 'created_by')
|
||||
filter_horizontal = ('parents', 'hosts')
|
||||
|
||||
class CredentialAdmin(BaseModelAdmin):
|
||||
|
||||
fieldsets = (
|
||||
(None, {'fields': (('name', 'active'), ('user', 'team'), 'description')}),
|
||||
(_('Auth Info'), {'fields': (('username', 'password'),
|
||||
'ssh_key_data', 'ssh_key_unlock',
|
||||
('sudo_username', 'sudo_password'))}),
|
||||
(_('Tags'), {'fields': ('tags',)}),
|
||||
(_('Audit'), {'fields': ('created', 'created_by',)}),
|
||||
)
|
||||
readonly_fields = ('active', 'created', 'created_by')
|
||||
|
||||
class TeamAdmin(BaseModelAdmin):
|
||||
|
||||
list_display = ('name', 'description', 'active')
|
||||
filter_horizontal = ('projects', 'users')
|
||||
|
||||
class ProjectUpdateInline(admin.StackedInline):
|
||||
|
||||
model = ProjectUpdate
|
||||
extra = 0
|
||||
can_delete = True
|
||||
fields = ('created', 'status', 'result_stdout')
|
||||
readonly_fields = ('created', 'status', 'result_stdout')
|
||||
|
||||
def has_add_permission(self, request):
|
||||
return False
|
||||
|
||||
class ProjectAdmin(BaseModelAdmin):
|
||||
|
||||
list_display = ('name', 'description', 'active')
|
||||
fieldsets = (
|
||||
(None, {'fields': (('name', 'active'), 'description', 'local_path',
|
||||
'get_playbooks_display')}),
|
||||
(_('SCM'), {'fields': ('scm_type', 'scm_url', 'scm_branch')}),
|
||||
(_('Tags'), {'fields': ('tags',)}),
|
||||
(_('Audit'), {'fields': ('created', 'created_by',)}),
|
||||
)
|
||||
readonly_fields = ('active', 'created', 'created_by',
|
||||
'get_playbooks_display')
|
||||
form = ProjectAdminForm
|
||||
inlines = [ProjectUpdateInline]
|
||||
|
||||
def get_playbooks_display(self, obj):
|
||||
return '<br/>'.join([format_html('{0}', x) for x in
|
||||
obj.playbooks])
|
||||
get_playbooks_display.short_description = _('Playbooks')
|
||||
get_playbooks_display.allow_tags = True
|
||||
|
||||
class PermissionAdmin(BaseModelAdmin):
|
||||
|
||||
list_display = ('name', 'description', 'active')
|
||||
|
||||
class JobTemplateAdmin(BaseModelAdmin):
|
||||
|
||||
list_display = ('name', 'description', 'active', 'get_create_link_display',
|
||||
'get_jobs_link_display')
|
||||
fieldsets = (
|
||||
(None, {'fields': ('name', 'active', 'description',
|
||||
'get_create_link_display', 'get_jobs_link_display')}),
|
||||
(_('Job Parameters'), {'fields': ('inventory', 'project', 'playbook',
|
||||
'credential', 'job_type')}),
|
||||
(_('More Options'), {'fields': ('forks', 'limit', 'verbosity',
|
||||
'extra_vars', 'job_tags', 'host_config_key'),
|
||||
'classes': ('collapse',)}),
|
||||
(_('Tags'), {'fields': ('tags',)}),
|
||||
(_('Audit'), {'fields': ('created', 'created_by',)}),
|
||||
)
|
||||
readonly_fields = ('active', 'created', 'created_by',
|
||||
'get_create_link_display', 'get_jobs_link_display')
|
||||
form = JobTemplateAdminForm
|
||||
|
||||
def get_create_link_display(self, obj):
|
||||
if not obj or not obj.pk:
|
||||
return ''
|
||||
info = Job._meta.app_label, Job._meta.module_name
|
||||
create_url = reverse('admin:%s_%s_add' % info,
|
||||
current_app=self.admin_site.name)
|
||||
create_opts = {
|
||||
'job_template': obj.pk,
|
||||
'job_type': obj.job_type,
|
||||
'description': obj.description,
|
||||
'name': '%s %s' % (obj.name, now().isoformat()),
|
||||
}
|
||||
if obj.inventory:
|
||||
create_opts['inventory'] = obj.inventory.pk
|
||||
if obj.project:
|
||||
create_opts['project'] = obj.project.pk
|
||||
if obj.playbook:
|
||||
create_opts['playbook'] = obj.playbook
|
||||
if obj.credential:
|
||||
create_opts['credential'] = obj.credential.pk
|
||||
if obj.forks:
|
||||
create_opts['forks'] = obj.forks
|
||||
if obj.limit:
|
||||
create_opts['limit'] = obj.limit
|
||||
if obj.verbosity:
|
||||
create_opts['verbosity'] = obj.verbosity
|
||||
if obj.extra_vars:
|
||||
create_opts['extra_vars'] = obj.extra_vars
|
||||
if obj.job_tags:
|
||||
create_opts['job_tags'] = obj.job_tags
|
||||
create_url += '?%s' % urllib.urlencode(create_opts)
|
||||
return format_html('<a href="{0}">{1}</a>', create_url, 'Create Job')
|
||||
get_create_link_display.short_description = _('Create Job')
|
||||
get_create_link_display.allow_tags = True
|
||||
|
||||
def get_jobs_link_display(self, obj):
|
||||
if not obj or not obj.pk:
|
||||
return ''
|
||||
info = Job._meta.app_label, Job._meta.module_name
|
||||
jobs_url = reverse('admin:%s_%s_changelist' % info,
|
||||
current_app=self.admin_site.name)
|
||||
jobs_url += '?job_template__id__exact=%d' % obj.pk
|
||||
return format_html('<a href="{0}">{1}</a>', jobs_url, 'View Jobs')
|
||||
get_jobs_link_display.short_description = _('View Jobs')
|
||||
get_jobs_link_display.allow_tags = True
|
||||
|
||||
class JobHostSummaryInlineForJob(JobHostSummaryInline):
|
||||
|
||||
fields = ('host', 'changed', 'dark', 'failures', 'ok', 'processed',
|
||||
'skipped', 'failed')
|
||||
readonly_fields = ('host', 'changed', 'dark', 'failures', 'ok',
|
||||
'processed', 'skipped', 'failed')
|
||||
|
||||
class JobEventInlineForJob(JobEventInline):
|
||||
|
||||
fields = ('created', 'event', 'get_event_data_display', 'failed', 'host')
|
||||
readonly_fields = ('created', 'event', 'get_event_data_display', 'failed',
|
||||
'host')
|
||||
|
||||
class JobAdmin(BaseModelAdmin):
|
||||
|
||||
list_display = ('__unicode__', 'job_template', 'project', 'playbook', 'status')
|
||||
list_filter = ('status',)
|
||||
fieldsets = (
|
||||
(None, {'fields': ('job_template', 'description')}),
|
||||
(_('Job Parameters'), {'fields': ('inventory', 'project', 'playbook',
|
||||
'credential', 'job_type')}),
|
||||
(_('More Options'), {'fields': ('forks', 'limit', 'verbosity',
|
||||
'extra_vars', 'job_tags'),
|
||||
'classes': ('collapse',)}),
|
||||
(_('Start Job'), {'fields': ('start_job', 'ssh_password',
|
||||
'sudo_password', 'ssh_key_unlock')}),
|
||||
(_('Tags'), {'fields': ('tags',)}),
|
||||
(_('Audit'), {'fields': ('created', 'created_by',)}),
|
||||
(_('Job Status'), {'fields': (('status', 'failed', 'cancel_job'),
|
||||
'get_result_stdout_display',
|
||||
'get_result_traceback_display',
|
||||
'celery_task_id')}),
|
||||
)
|
||||
readonly_fields = ('status', 'failed', 'get_job_template_display',
|
||||
'get_result_stdout_display',
|
||||
'get_result_traceback_display', 'celery_task_id',
|
||||
'created', 'created_by')
|
||||
form = JobAdminForm
|
||||
inlines = [JobHostSummaryInlineForJob, JobEventInlineForJob]
|
||||
|
||||
def get_readonly_fields(self, request, obj=None):
|
||||
ro_fields = list(super(JobAdmin, self).get_readonly_fields(request, obj))
|
||||
if obj and obj.pk and obj.status != 'new':
|
||||
ro_fields.extend(['description', 'job_template',
|
||||
'inventory', 'project', 'playbook', 'credential',
|
||||
'job_type', 'forks', 'limit',
|
||||
'verbosity', 'extra_vars', 'job_tags'])
|
||||
return ro_fields
|
||||
|
||||
def get_fieldsets(self, request, obj=None):
|
||||
fsets = list(super(JobAdmin, self).get_fieldsets(request, obj))
|
||||
if not obj or not obj.pk or obj.status == 'new':
|
||||
fsets = [fs for fs in fsets if
|
||||
'created' not in fs[1]['fields'] and
|
||||
'celery_task_id' not in fs[1]['fields']]
|
||||
if not obj or (obj and obj.pk and not obj.can_start):
|
||||
fsets = [fs for fs in fsets if 'start_job' not in fs[1]['fields']]
|
||||
if not obj or (obj and obj.pk and not obj.can_cancel):
|
||||
for fs in fsets:
|
||||
if 'celery_task_id' in fs[1]['fields']:
|
||||
fs[1]['fields'] = ('status', 'get_result_stdout_display',
|
||||
'get_result_traceback_display',
|
||||
'celery_task_id')
|
||||
return fsets
|
||||
|
||||
def get_inline_instances(self, request, obj=None):
|
||||
if obj and obj.pk and obj.status != 'new':
|
||||
return super(JobAdmin, self).get_inline_instances(request, obj)
|
||||
else:
|
||||
return []
|
||||
|
||||
def get_job_template_display(self, obj):
|
||||
if obj.job_template:
|
||||
info = JobTemplate._meta.app_label, JobTemplate._meta.module_name
|
||||
job_template_url = reverse('admin:%s_%s_change' % info,
|
||||
args=(obj.job_template.pk,),
|
||||
current_app=self.admin_site.name)
|
||||
return format_html('<a href="{0}">{1}</a>', job_template_url,
|
||||
obj.job_template)
|
||||
else:
|
||||
return _('(None)')
|
||||
get_job_template_display.short_description = _('Job template')
|
||||
get_job_template_display.allow_tags = True
|
||||
|
||||
def get_result_stdout_display(self, obj):
|
||||
return format_html('<pre class="result-display">{0}</pre>',
|
||||
obj.result_stdout or ' ')
|
||||
get_result_stdout_display.short_description = _('Stdout')
|
||||
get_result_stdout_display.allow_tags = True
|
||||
|
||||
def get_result_traceback_display(self, obj):
|
||||
return format_html('<pre class="result-display">{0}</pre>',
|
||||
obj.result_traceback or ' ')
|
||||
get_result_traceback_display.short_description = _('Traceback')
|
||||
get_result_traceback_display.allow_tags = True
|
||||
|
||||
admin.site.register(Organization, OrganizationAdmin)
|
||||
admin.site.register(Inventory, InventoryAdmin)
|
||||
#admin.site.register(Tag, TagAdmin)
|
||||
#admin.site.register(AuditTrail, AuditTrailAdmin)
|
||||
admin.site.register(Host, HostAdmin)
|
||||
admin.site.register(Group, GroupAdmin)
|
||||
#admin.site.register(VariableData, VariableDataAdmin)
|
||||
admin.site.register(Team, TeamAdmin)
|
||||
admin.site.register(Project, ProjectAdmin)
|
||||
admin.site.register(Credential, CredentialAdmin)
|
||||
admin.site.register(JobTemplate, JobTemplateAdmin)
|
||||
admin.site.register(Job, JobAdmin)
|
||||
@ -1,159 +0,0 @@
|
||||
# Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
# All Rights Reserved.
|
||||
|
||||
# Python
|
||||
import json
|
||||
|
||||
# PyYAML
|
||||
import yaml
|
||||
|
||||
# Django
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
# AWX
|
||||
from awx.main.models import *
|
||||
|
||||
EMPTY_CHOICE = ('', '---------')
|
||||
|
||||
class PlaybookOption(object):
|
||||
|
||||
def __init__(self, project, playbook):
|
||||
self.project, self.playbook = project, playbook
|
||||
|
||||
def __unicode__(self):
|
||||
return self.playbook
|
||||
|
||||
class PlaybookSelect(forms.Select):
|
||||
'''Custom select widget for playbooks related to a project.'''
|
||||
|
||||
def render_option(self, selected_choices, option_value, obj):
|
||||
opt = super(PlaybookSelect, self).render_option(selected_choices,
|
||||
option_value,
|
||||
unicode(obj))
|
||||
# Add a class with the project ID so JS can filter the options.
|
||||
if hasattr(obj, 'project'):
|
||||
opt = opt.replace('">', '" class="project-%s">' % obj.project.pk)
|
||||
return opt
|
||||
|
||||
class ModelFormWithVariables(forms.ModelForm):
|
||||
'''Custom model form to validate variable data.'''
|
||||
|
||||
def clean_variables(self):
|
||||
value = self.cleaned_data.get('variables', '')
|
||||
try:
|
||||
json.loads(value.strip() or '{}')
|
||||
except ValueError:
|
||||
try:
|
||||
yaml.safe_load(value)
|
||||
except yaml.YAMLError:
|
||||
raise forms.ValidationError('Must be valid JSON or YAML')
|
||||
return value
|
||||
|
||||
class InventoryAdminForm(ModelFormWithVariables):
|
||||
'''Custom model form for Inventory.'''
|
||||
|
||||
class Meta:
|
||||
model = Inventory
|
||||
|
||||
class HostAdminForm(ModelFormWithVariables):
|
||||
'''Custom model form for Hosts.'''
|
||||
|
||||
class Meta:
|
||||
model = Host
|
||||
|
||||
class GroupAdminForm(ModelFormWithVariables):
|
||||
'''Custom model form for Groups.'''
|
||||
|
||||
class Meta:
|
||||
model = Group
|
||||
|
||||
class ProjectAdminForm(forms.ModelForm):
|
||||
'''Custom admin form for Projects.'''
|
||||
|
||||
local_path = forms.ChoiceField(choices=[])
|
||||
|
||||
class Meta:
|
||||
model = Project
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ProjectAdminForm, self).__init__(*args, **kwargs)
|
||||
self.fields['local_path'].choices = [(x, x) for x in Project.get_local_path_choices()]
|
||||
|
||||
class JobTemplateAdminForm(forms.ModelForm):
|
||||
'''Custom admin form for creating/editing JobTemplates.'''
|
||||
|
||||
playbook = forms.ChoiceField(choices=[EMPTY_CHOICE], widget=PlaybookSelect)
|
||||
|
||||
class Meta:
|
||||
model = JobTemplate
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(JobTemplateAdminForm, self).__init__(*args, **kwargs)
|
||||
playbook_choices = []
|
||||
for project in Project.objects.all():
|
||||
for playbook in project.playbooks:
|
||||
playbook_choices.append((playbook,
|
||||
PlaybookOption(project, playbook)))
|
||||
self.fields['playbook'].choices = [EMPTY_CHOICE] + playbook_choices
|
||||
|
||||
class JobAdminForm(JobTemplateAdminForm):
|
||||
'''Custom admin form for creating Jobs.'''
|
||||
|
||||
start_job = forms.BooleanField(initial=False, required=False)
|
||||
ssh_password = forms.CharField(label=_('SSH password'), required=False)
|
||||
sudo_password = forms.CharField(required=False)
|
||||
ssh_key_unlock = forms.CharField(label=_('SSH key passphrase'),
|
||||
required=False)
|
||||
cancel_job = forms.BooleanField(initial=False, required=False)
|
||||
|
||||
class Meta:
|
||||
model = Job
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(JobAdminForm, self).__init__(*args, **kwargs)
|
||||
if self.instance.pk and self.instance.status != 'new':
|
||||
self.fields.pop('playbook', None)
|
||||
if (not self.data or self.data.get('start_job', '')) and \
|
||||
self.instance.credential and self.instance.can_start:
|
||||
for field in self.instance.get_passwords_needed_to_start():
|
||||
if field not in self.fields:
|
||||
continue
|
||||
self.fields[field].required = True
|
||||
|
||||
def clean_start_job(self):
|
||||
return self.cleaned_data.get('start_job', False)
|
||||
|
||||
def clean_cancel_job(self):
|
||||
return self.cleaned_data.get('cancel_job', False)
|
||||
|
||||
def clean(self):
|
||||
if self.instance.credential and self.instance.can_start:
|
||||
for field in self.instance.get_passwords_needed_to_start():
|
||||
if field in self.fields:
|
||||
self.fields[field].required = True
|
||||
return super(JobAdminForm, self).clean()
|
||||
|
||||
def save(self, commit=True):
|
||||
instance = super(JobAdminForm, self).save(commit)
|
||||
save_m2m = getattr(self, 'save_m2m', lambda: None)
|
||||
should_start = bool(self.cleaned_data.get('start_job', '') and
|
||||
instance.can_start)
|
||||
start_opts = {}
|
||||
for field in ('ssh_password', 'sudo_password', 'ssh_key_unlock'):
|
||||
value = self.cleaned_data.get(field, '')
|
||||
if value:
|
||||
start_opts[field] = value
|
||||
should_cancel = bool(self.cleaned_data.get('cancel_job', '') and
|
||||
instance.can_cancel)
|
||||
def new_save_m2m():
|
||||
save_m2m()
|
||||
if should_start:
|
||||
instance.start(**start_opts)
|
||||
if should_cancel:
|
||||
instance.cancel()
|
||||
if commit:
|
||||
new_save_m2m()
|
||||
else:
|
||||
self.save_m2m = new_save_m2m
|
||||
return instance
|
||||
@ -11,14 +11,11 @@ def handle_error(request, status=404, **kwargs):
|
||||
# FIXME: Should attempt to check HTTP Accept request header and return
|
||||
# plain JSON response instead of HTML (maybe only for /api/*).
|
||||
context = kwargs
|
||||
if 'django.contrib.admin' in settings.INSTALLED_APPS and request.path.startswith('/admin/'):
|
||||
template_name = 'admin/error.html'
|
||||
else:
|
||||
# Return enough context to popuplate the base API template.
|
||||
description = u'<pre class="err">%s</pre>' % context.get('content', '')
|
||||
context['description'] = mark_safe(description)
|
||||
context['content'] = ''
|
||||
template_name = 'error.html'
|
||||
# Return enough context to popuplate the base API template.
|
||||
description = u'<pre class="err">%s</pre>' % context.get('content', '')
|
||||
context['description'] = mark_safe(description)
|
||||
context['content'] = ''
|
||||
template_name = 'error.html'
|
||||
return render(request, template_name, context, status=status)
|
||||
|
||||
def handle_403(request):
|
||||
|
||||
@ -140,8 +140,6 @@ INSTALLED_APPS = (
|
||||
'awx.main',
|
||||
'awx.api',
|
||||
'awx.ui',
|
||||
# Django admin is disabled and not supported by default.
|
||||
#'django.contrib.admin',
|
||||
)
|
||||
|
||||
INTERNAL_IPS = ('127.0.0.1',)
|
||||
|
||||
@ -1,251 +0,0 @@
|
||||
{# Admin site customizations. #}
|
||||
{% extends "admin/base.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block title %}{{ title }} | {% trans 'AWX Admin' %}{% endblock %}
|
||||
|
||||
{% block extrastyle %}
|
||||
{{ block.super }}
|
||||
<link href="{{ STATIC_URL }}img/favicon.ico" rel="shortcut icon" />
|
||||
<style type="text/css">
|
||||
/* Heading and button background colors. */
|
||||
#header
|
||||
{
|
||||
background: #171717 !important;
|
||||
}
|
||||
.module h2,
|
||||
#content-related .module h2,
|
||||
.module caption,
|
||||
.inline-group h2,
|
||||
.button.default
|
||||
{
|
||||
background: #171717 !important;
|
||||
}
|
||||
input[type="submit"].default,
|
||||
.submit-row input.default
|
||||
{
|
||||
background: #51a351 !important;
|
||||
}
|
||||
body
|
||||
{
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
body h1, body h2, body h3 {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
/* Heading and button foreground colors. */
|
||||
#branding h1
|
||||
{
|
||||
color: white !important;
|
||||
margin: 0;
|
||||
padding-top: 4px;
|
||||
text-transform: uppercase;
|
||||
font-weight: normal;
|
||||
}
|
||||
#branding h1 img {
|
||||
height: 48px;
|
||||
width: auto;
|
||||
margin: -10px 8px -6px -2px;
|
||||
}
|
||||
#user-tools {
|
||||
padding-top: 1em;
|
||||
}
|
||||
.module h2,
|
||||
.module h2 a,
|
||||
#content-related .module h2,
|
||||
.module caption,
|
||||
.inline-group h2,
|
||||
a.section,
|
||||
a.section:link,
|
||||
a.section:visited,
|
||||
a.section:hover,
|
||||
.button.default,
|
||||
input[type="submit"].default,
|
||||
.submit-row input.default
|
||||
{
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
/* Link color. */
|
||||
a,
|
||||
a:link,
|
||||
a:visited,
|
||||
#changelist-filter a:hover,
|
||||
a:hover
|
||||
{
|
||||
color: #2773ae;
|
||||
}
|
||||
|
||||
/* Button border color. */
|
||||
.selector h2
|
||||
{
|
||||
border-color: #171717 !important;
|
||||
}
|
||||
body .button.default,
|
||||
body input[type="submit"].default,
|
||||
body .submit-row input.default
|
||||
{
|
||||
border: 1px solid #51a351;
|
||||
border-color: #7c7 #383 #383 #7c7;
|
||||
}
|
||||
#header {
|
||||
color: #ddd;
|
||||
border-bottom: none;
|
||||
}
|
||||
#header a:hover {
|
||||
color: #2078be;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Object Tools */
|
||||
body .object-tools li {
|
||||
background: #888;
|
||||
border-radius: 8px;
|
||||
}
|
||||
body .object-tools li:hover {
|
||||
background: #aaa;
|
||||
}
|
||||
body .object-tools a:link,
|
||||
body .object-tools a:visited,
|
||||
body .object-tools a:hover,
|
||||
body .object-tools li:hover a {
|
||||
background: transparent;
|
||||
text-decoration: none;
|
||||
}
|
||||
body .object-tools a.viewsitelink,
|
||||
body .object-tools a.golink,
|
||||
body .object-tools a.addlink {
|
||||
background: transparent;
|
||||
padding-right: 10px;
|
||||
}
|
||||
body .object-tools a.viewsitelink:hover,
|
||||
body .object-tools a.golink:hover,
|
||||
body .object-tools a.addlink:hover {
|
||||
background: transparent;
|
||||
}
|
||||
body .object-tools a.viewsitelink:after,
|
||||
body .object-tools a.golink:after {
|
||||
content: " \27a1";
|
||||
}
|
||||
body .object-tools a.addlink:after {
|
||||
content: " +";
|
||||
}
|
||||
|
||||
a:hover,
|
||||
a.section:hover
|
||||
{
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
tr.row1 {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
ul.messagelist li {
|
||||
background-color: #ccddee;
|
||||
}
|
||||
.errornote {
|
||||
border-color: #b22222 !important;
|
||||
color: #b22222 !important;
|
||||
background-color: #fdc !important;
|
||||
}
|
||||
.errorlist li {
|
||||
border-color: #b22222 !important;
|
||||
background-color: #d24242 !important;
|
||||
}
|
||||
.errors {
|
||||
background-color: #fdc !important;
|
||||
}
|
||||
.errors input,
|
||||
.errors select,
|
||||
.errors textarea {
|
||||
border: 1px solid #b22222 !important;
|
||||
}
|
||||
pre.json-display, pre.result-display {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
pre.result-display {
|
||||
width: 75%;
|
||||
border: 1px solid #ccc;
|
||||
background: #444;
|
||||
color: #eee;
|
||||
max-height: 300px;
|
||||
overflow: auto;
|
||||
}
|
||||
#job_host_summaries-group table td.original p {
|
||||
display: none
|
||||
}
|
||||
#job_host_summaries-group table tr.has_original td {
|
||||
padding-top: 5px;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block extrahead %}
|
||||
{{ block.super }}
|
||||
{% endblock %}
|
||||
|
||||
{% block blockbots %}
|
||||
{{ block.super }}
|
||||
<script type="text/javascript">
|
||||
var django = django || {};
|
||||
if (django.jQuery) {
|
||||
(function($) {
|
||||
window.refreshJobStatus = function() {
|
||||
var status = $('.field-status p').text();
|
||||
if (status == 'Running' || status == 'Pending') {
|
||||
var url = '{{ request.path }}';
|
||||
$.get(url, function(data) {
|
||||
var selectors = [
|
||||
'.form-row.field-status',
|
||||
'.field-get_result_stdout_display pre',
|
||||
'.field-get_result_stderr_display pre',
|
||||
'.field-get_result_traceback_display pre',
|
||||
'.field-get_result_stdout_display pre',
|
||||
'#job_host_summaries-group',
|
||||
'#job_events-group',
|
||||
]
|
||||
$.each(selectors, function(index, selector) {
|
||||
$(selector).html($(data).find(selector).html());
|
||||
});
|
||||
setTimeout('window.refreshJobStatus()', 5000);
|
||||
});
|
||||
}
|
||||
}
|
||||
// Update playbook list based on project selected.
|
||||
function onProjectChange() {
|
||||
var project_pk = $('select[name="project"]').val() || 0;
|
||||
$('select[name="playbook"] span option').unwrap();
|
||||
$('select[name="playbook"] option:not(.project-' + project_pk + '):not([value=""])').wrap('<span/>');
|
||||
}
|
||||
$(function() {
|
||||
$('select[name="project"]').each(onProjectChange).change(onProjectChange);
|
||||
})
|
||||
setTimeout('window.refreshJobStatus()', 2000);
|
||||
})(django.jQuery);
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block branding %}
|
||||
<h1 id="site-name"><img class="logo" src="{{ STATIC_URL }}img/logo.png">{% block branding_title %}{% trans 'AWX Admin' %}{% endblock %}</h1>
|
||||
{% endblock %}
|
||||
|
||||
{% block userlinks %}
|
||||
{{ block.super }}
|
||||
{% endblock %}
|
||||
|
||||
{% block nav-global %}
|
||||
{% if user.is_active and user.is_staff and not is_popup %}
|
||||
{# Placeholder for version/hostname info. #}
|
||||
{% endif %}
|
||||
{{ block.super }}
|
||||
{% endblock %}
|
||||
|
||||
{% block content_title %}
|
||||
{{ block.super }}
|
||||
{% endblock %}
|
||||
@ -1,20 +0,0 @@
|
||||
{% extends "admin/base_site.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block title %}{{ name }}{% endblock %}
|
||||
|
||||
{% block nav-global %}{% endblock %}
|
||||
|
||||
{% block content_title %}{% endblock %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
<div class="breadcrumbs">
|
||||
<a href="{% url "admin:index" %}">{% trans "Home" %}</a> ›
|
||||
{{ name }}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1 style="margin-bottom: 0.7em;">{{ name }}</h1>
|
||||
<p>{{ content }}</p>
|
||||
{% endblock %}
|
||||
12
awx/urls.py
12
awx/urls.py
@ -18,15 +18,3 @@ urlpatterns += patterns('awx.main.views',
|
||||
url(r'^404.html$', 'handle_404'),
|
||||
url(r'^500.html$', 'handle_500'),
|
||||
)
|
||||
|
||||
if 'django.contrib.admin' in settings.INSTALLED_APPS:
|
||||
from django.contrib import admin
|
||||
admin.autodiscover()
|
||||
urlpatterns += patterns('',
|
||||
url(r'^admin/', include(admin.site.urls)),
|
||||
)
|
||||
urlpatterns += patterns('awx.main.views',
|
||||
url(r'^admin/403.html$', 'handle_403'),
|
||||
url(r'^admin/404.html$', 'handle_404'),
|
||||
url(r'^admin/500.html$', 'handle_500'),
|
||||
)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user