mirror of
https://github.com/ansible/awx.git
synced 2024-10-31 15:21:13 +03:00
Merge pull request #4070 from jbradberry/upgrade-django-2.2
Upgrade Django to 2.2 Reviewed-by: https://github.com/softwarefactory-project-zuul[bot]
This commit is contained in:
commit
b8b98b136b
@ -25,9 +25,8 @@ import hashlib
|
||||
|
||||
try:
|
||||
import django
|
||||
from django.utils.encoding import force_bytes
|
||||
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
|
||||
from django.db.backends.base import schema
|
||||
from django.db.backends.utils import names_digest
|
||||
HAS_DJANGO = True
|
||||
except ImportError:
|
||||
HAS_DJANGO = False
|
||||
@ -37,30 +36,33 @@ if HAS_DJANGO is True:
|
||||
# This line exists to make sure we don't regress on FIPS support if we
|
||||
# upgrade Django; if you're upgrading Django and see this error,
|
||||
# update the version check below, and confirm that FIPS still works.
|
||||
if django.__version__ != '1.11.20':
|
||||
raise RuntimeError("Django version other than 1.11.20 detected {}. \
|
||||
Subclassing BaseDatabaseSchemaEditor is known to work for Django 1.11.20 \
|
||||
and may not work in newer Django versions.".format(django.__version__))
|
||||
# If operating in a FIPS environment, `hashlib.md5()` will raise a `ValueError`,
|
||||
# but will support the `usedforsecurity` keyword on RHEL and Centos systems.
|
||||
|
||||
# Keep an eye on https://code.djangoproject.com/ticket/28401
|
||||
target_version = '2.2.2'
|
||||
if django.__version__ != target_version:
|
||||
raise RuntimeError(
|
||||
"Django version other than {target} detected: {current}. "
|
||||
"Overriding `names_digest` is known to work for Django {target} "
|
||||
"and may not work in other Django versions.".format(target=target_version,
|
||||
current=django.__version__)
|
||||
)
|
||||
|
||||
class FipsBaseDatabaseSchemaEditor(BaseDatabaseSchemaEditor):
|
||||
|
||||
@classmethod
|
||||
def _digest(cls, *args):
|
||||
try:
|
||||
names_digest('foo', 'bar', 'baz', length=8)
|
||||
except ValueError:
|
||||
def names_digest(*args, length):
|
||||
"""
|
||||
Generates a 32-bit digest of a set of arguments that can be used to
|
||||
shorten identifying names.
|
||||
Generate a 32-bit digest of a set of arguments that can be used to shorten
|
||||
identifying names. Support for use in FIPS environments.
|
||||
"""
|
||||
try:
|
||||
h = hashlib.md5()
|
||||
except ValueError:
|
||||
h = hashlib.md5(usedforsecurity=False)
|
||||
h = hashlib.md5(usedforsecurity=False)
|
||||
for arg in args:
|
||||
h.update(force_bytes(arg))
|
||||
return h.hexdigest()[:8]
|
||||
h.update(arg.encode())
|
||||
return h.hexdigest()[:length]
|
||||
|
||||
|
||||
schema.BaseDatabaseSchemaEditor = FipsBaseDatabaseSchemaEditor
|
||||
schema.names_digest = names_digest
|
||||
|
||||
|
||||
def find_commands(management_dir):
|
||||
|
@ -401,21 +401,21 @@ class ListAPIView(generics.ListAPIView, GenericAPIView):
|
||||
continue
|
||||
if getattr(field, 'related_model', None):
|
||||
fields.add('{}__search'.format(field.name))
|
||||
for rel in self.model._meta.related_objects:
|
||||
name = rel.related_name
|
||||
if isinstance(rel, OneToOneRel) and self.model._meta.verbose_name.startswith('unified'):
|
||||
for related in self.model._meta.related_objects:
|
||||
name = related.related_name
|
||||
if isinstance(related, OneToOneRel) and self.model._meta.verbose_name.startswith('unified'):
|
||||
# Add underscores for polymorphic subclasses for user utility
|
||||
name = rel.related_model._meta.verbose_name.replace(" ", "_")
|
||||
name = related.related_model._meta.verbose_name.replace(" ", "_")
|
||||
if skip_related_name(name) or name.endswith('+'):
|
||||
continue
|
||||
fields.add('{}__search'.format(name))
|
||||
m2m_rel = []
|
||||
m2m_rel += self.model._meta.local_many_to_many
|
||||
m2m_related = []
|
||||
m2m_related += self.model._meta.local_many_to_many
|
||||
if issubclass(self.model, UnifiedJobTemplate) and self.model != UnifiedJobTemplate:
|
||||
m2m_rel += UnifiedJobTemplate._meta.local_many_to_many
|
||||
m2m_related += UnifiedJobTemplate._meta.local_many_to_many
|
||||
if issubclass(self.model, UnifiedJob) and self.model != UnifiedJob:
|
||||
m2m_rel += UnifiedJob._meta.local_many_to_many
|
||||
for relationship in m2m_rel:
|
||||
m2m_related += UnifiedJob._meta.local_many_to_many
|
||||
for relationship in m2m_related:
|
||||
if skip_related_name(relationship.name):
|
||||
continue
|
||||
if relationship.related_model._meta.app_label != 'main':
|
||||
|
@ -95,7 +95,7 @@ class ModelAccessPermission(permissions.BasePermission):
|
||||
'''
|
||||
|
||||
# Don't allow anonymous users. 401, not 403, hence no raised exception.
|
||||
if not request.user or request.user.is_anonymous():
|
||||
if not request.user or request.user.is_anonymous:
|
||||
return False
|
||||
|
||||
# Always allow superusers
|
||||
|
@ -2560,7 +2560,7 @@ class CredentialSerializer(BaseSerializer):
|
||||
|
||||
def validate_credential_type(self, credential_type):
|
||||
if self.instance and credential_type.pk != self.instance.credential_type.pk:
|
||||
for rel in (
|
||||
for related_objects in (
|
||||
'ad_hoc_commands',
|
||||
'insights_inventories',
|
||||
'unifiedjobs',
|
||||
@ -2569,7 +2569,7 @@ class CredentialSerializer(BaseSerializer):
|
||||
'projectupdates',
|
||||
'workflowjobnodes'
|
||||
):
|
||||
if getattr(self.instance, rel).count() > 0:
|
||||
if getattr(self.instance, related_objects).count() > 0:
|
||||
raise ValidationError(
|
||||
_('You cannot change the credential type of the credential, as it may break the functionality'
|
||||
' of the resources using it.'),
|
||||
@ -4640,37 +4640,37 @@ class ActivityStreamSerializer(BaseSerializer):
|
||||
return ""
|
||||
|
||||
def get_related(self, obj):
|
||||
rel = {}
|
||||
data = {}
|
||||
if obj.actor is not None:
|
||||
rel['actor'] = self.reverse('api:user_detail', kwargs={'pk': obj.actor.pk})
|
||||
data['actor'] = self.reverse('api:user_detail', kwargs={'pk': obj.actor.pk})
|
||||
for fk, __ in self._local_summarizable_fk_fields:
|
||||
if not hasattr(obj, fk):
|
||||
continue
|
||||
m2m_list = self._get_rel(obj, fk)
|
||||
m2m_list = self._get_related_objects(obj, fk)
|
||||
if m2m_list:
|
||||
rel[fk] = []
|
||||
data[fk] = []
|
||||
id_list = []
|
||||
for thisItem in m2m_list:
|
||||
if getattr(thisItem, 'id', None) in id_list:
|
||||
for item in m2m_list:
|
||||
if getattr(item, 'id', None) in id_list:
|
||||
continue
|
||||
id_list.append(getattr(thisItem, 'id', None))
|
||||
if hasattr(thisItem, 'get_absolute_url'):
|
||||
rel_url = thisItem.get_absolute_url(self.context.get('request'))
|
||||
id_list.append(getattr(item, 'id', None))
|
||||
if hasattr(item, 'get_absolute_url'):
|
||||
url = item.get_absolute_url(self.context.get('request'))
|
||||
else:
|
||||
view_name = fk + '_detail'
|
||||
rel_url = self.reverse('api:' + view_name, kwargs={'pk': thisItem.id})
|
||||
rel[fk].append(rel_url)
|
||||
url = self.reverse('api:' + view_name, kwargs={'pk': item.id})
|
||||
data[fk].append(url)
|
||||
|
||||
if fk == 'schedule':
|
||||
rel['unified_job_template'] = thisItem.unified_job_template.get_absolute_url(self.context.get('request'))
|
||||
data['unified_job_template'] = item.unified_job_template.get_absolute_url(self.context.get('request'))
|
||||
if obj.setting and obj.setting.get('category', None):
|
||||
rel['setting'] = self.reverse(
|
||||
data['setting'] = self.reverse(
|
||||
'api:setting_singleton_detail',
|
||||
kwargs={'category_slug': obj.setting['category']}
|
||||
)
|
||||
return rel
|
||||
return data
|
||||
|
||||
def _get_rel(self, obj, fk):
|
||||
def _get_related_objects(self, obj, fk):
|
||||
related_model = ActivityStream._meta.get_field(fk).related_model
|
||||
related_manager = getattr(obj, fk)
|
||||
if issubclass(related_model, PolymorphicModel) and hasattr(obj, '_prefetched_objects_cache'):
|
||||
@ -4703,7 +4703,7 @@ class ActivityStreamSerializer(BaseSerializer):
|
||||
try:
|
||||
if not hasattr(obj, fk):
|
||||
continue
|
||||
m2m_list = self._get_rel(obj, fk)
|
||||
m2m_list = self._get_related_objects(obj, fk)
|
||||
if m2m_list:
|
||||
summary_fields[fk] = []
|
||||
for thisItem in m2m_list:
|
||||
|
@ -2997,7 +2997,7 @@ class WorkflowJobTemplateNodeChildrenBaseList(EnforceParentRelationshipMixin, Su
|
||||
relationships = ['success_nodes', 'failure_nodes', 'always_nodes']
|
||||
relationships.remove(self.relationship)
|
||||
qs = functools.reduce(lambda x, y: (x | y),
|
||||
(Q(**{'{}__in'.format(rel): [sub.id]}) for rel in relationships))
|
||||
(Q(**{'{}__in'.format(r): [sub.id]}) for r in relationships))
|
||||
|
||||
if models.WorkflowJobTemplateNode.objects.filter(Q(pk=parent.id) & qs).exists():
|
||||
return {"Error": _("Relationship not allowed.")}
|
||||
|
@ -21,7 +21,8 @@ class Migration(migrations.Migration):
|
||||
('modified', models.DateTimeField(default=None, editable=False)),
|
||||
('key', models.CharField(max_length=255)),
|
||||
('value', jsonfield.fields.JSONField(null=True)),
|
||||
('user', models.ForeignKey(related_name='settings', default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True)),
|
||||
('user', models.ForeignKey(related_name='settings', default=None, editable=False,
|
||||
to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
|
@ -24,7 +24,7 @@ def ws_connect(message):
|
||||
headers = dict(message.content.get('headers', ''))
|
||||
message.reply_channel.send({"accept": True})
|
||||
message.content['method'] = 'FAKE'
|
||||
if message.user.is_authenticated():
|
||||
if message.user.is_authenticated:
|
||||
message.reply_channel.send(
|
||||
{"text": json.dumps({"accept": True, "user": message.user.id})}
|
||||
)
|
||||
|
@ -11,8 +11,9 @@ from jinja2 import Environment, StrictUndefined
|
||||
from jinja2.exceptions import UndefinedError, TemplateSyntaxError
|
||||
|
||||
# Django
|
||||
import django
|
||||
from django.contrib.postgres.fields import JSONField as upstream_JSONBField
|
||||
from django.core import exceptions as django_exceptions
|
||||
from django.core.serializers.json import DjangoJSONEncoder
|
||||
from django.db.models.signals import (
|
||||
post_save,
|
||||
post_delete,
|
||||
@ -37,7 +38,6 @@ import jsonschema.exceptions
|
||||
|
||||
# Django-JSONField
|
||||
from jsonfield import JSONField as upstream_JSONField
|
||||
from jsonbfield.fields import JSONField as upstream_JSONBField
|
||||
|
||||
# DRF
|
||||
from rest_framework import serializers
|
||||
@ -76,10 +76,10 @@ class JSONField(upstream_JSONField):
|
||||
def db_type(self, connection):
|
||||
return 'text'
|
||||
|
||||
def from_db_value(self, value, expression, connection, context):
|
||||
def from_db_value(self, value, expression, connection):
|
||||
if value in {'', None} and not self.null:
|
||||
return {}
|
||||
return super(JSONField, self).from_db_value(value, expression, connection, context)
|
||||
return super(JSONField, self).from_db_value(value, expression, connection)
|
||||
|
||||
|
||||
class JSONBField(upstream_JSONBField):
|
||||
@ -91,12 +91,12 @@ class JSONBField(upstream_JSONBField):
|
||||
def get_db_prep_value(self, value, connection, prepared=False):
|
||||
if connection.vendor == 'sqlite':
|
||||
# sqlite (which we use for tests) does not support jsonb;
|
||||
return json.dumps(value)
|
||||
return json.dumps(value, cls=DjangoJSONEncoder)
|
||||
return super(JSONBField, self).get_db_prep_value(
|
||||
value, connection, prepared
|
||||
)
|
||||
|
||||
def from_db_value(self, value, expression, connection, context):
|
||||
def from_db_value(self, value, expression, connection):
|
||||
# Work around a bug in django-jsonfield
|
||||
# https://bitbucket.org/schinckel/django-jsonfield/issues/57/cannot-use-in-the-same-project-as-djangos
|
||||
if isinstance(value, str):
|
||||
@ -112,14 +112,9 @@ class AutoSingleRelatedObjectDescriptor(ReverseOneToOneDescriptor):
|
||||
|
||||
def __get__(self, instance, instance_type=None):
|
||||
try:
|
||||
return super(AutoSingleRelatedObjectDescriptor,
|
||||
self).__get__(instance, instance_type)
|
||||
return super(AutoSingleRelatedObjectDescriptor, self).__get__(instance, instance_type)
|
||||
except self.related.related_model.DoesNotExist:
|
||||
obj = self.related.related_model(**{self.related.field.name: instance})
|
||||
if self.related.field.rel.parent_link:
|
||||
raise NotImplementedError('not supported with polymorphic!')
|
||||
for f in instance._meta.local_fields:
|
||||
setattr(obj, f.name, getattr(instance, f.name))
|
||||
obj.save()
|
||||
return obj
|
||||
|
||||
@ -453,21 +448,6 @@ class JSONSchemaField(JSONBField):
|
||||
params={'value': value},
|
||||
)
|
||||
|
||||
def get_db_prep_value(self, value, connection, prepared=False):
|
||||
if connection.vendor == 'sqlite':
|
||||
# sqlite (which we use for tests) does not support jsonb;
|
||||
return json.dumps(value)
|
||||
return super(JSONSchemaField, self).get_db_prep_value(
|
||||
value, connection, prepared
|
||||
)
|
||||
|
||||
def from_db_value(self, value, expression, connection, context):
|
||||
# Work around a bug in django-jsonfield
|
||||
# https://bitbucket.org/schinckel/django-jsonfield/issues/57/cannot-use-in-the-same-project-as-djangos
|
||||
if isinstance(value, str):
|
||||
return json.loads(value)
|
||||
return value
|
||||
|
||||
|
||||
@JSONSchemaField.format_checker.checks('vault_id')
|
||||
def format_vault_id(value):
|
||||
@ -986,7 +966,7 @@ class OAuth2ClientSecretField(models.CharField):
|
||||
encrypt_value(value), connection, prepared
|
||||
)
|
||||
|
||||
def from_db_value(self, value, expression, connection, context):
|
||||
def from_db_value(self, value, expression, connection):
|
||||
if value and value.startswith('$encrypted$'):
|
||||
return decrypt_value(get_encryption_key('value', pk=None), value)
|
||||
return value
|
||||
@ -1022,38 +1002,6 @@ class OrderedManyToManyDescriptor(ManyToManyDescriptor):
|
||||
'%s__position' % self.through._meta.model_name
|
||||
)
|
||||
|
||||
def add(self, *objs):
|
||||
# Django < 2 doesn't support this method on
|
||||
# ManyToManyFields w/ an intermediary model
|
||||
# We should be able to remove this code snippet when we
|
||||
# upgrade Django.
|
||||
# see: https://github.com/django/django/blob/stable/1.11.x/django/db/models/fields/related_descriptors.py#L926
|
||||
if not django.__version__.startswith('1.'):
|
||||
raise RuntimeError(
|
||||
'This method is no longer necessary in Django>=2'
|
||||
)
|
||||
try:
|
||||
self.through._meta.auto_created = True
|
||||
super(OrderedManyRelatedManager, self).add(*objs)
|
||||
finally:
|
||||
self.through._meta.auto_created = False
|
||||
|
||||
def remove(self, *objs):
|
||||
# Django < 2 doesn't support this method on
|
||||
# ManyToManyFields w/ an intermediary model
|
||||
# We should be able to remove this code snippet when we
|
||||
# upgrade Django.
|
||||
# see: https://github.com/django/django/blob/stable/1.11.x/django/db/models/fields/related_descriptors.py#L944
|
||||
if not django.__version__.startswith('1.'):
|
||||
raise RuntimeError(
|
||||
'This method is no longer necessary in Django>=2'
|
||||
)
|
||||
try:
|
||||
self.through._meta.auto_created = True
|
||||
super(OrderedManyRelatedManager, self).remove(*objs)
|
||||
finally:
|
||||
self.through._meta.auto_created = False
|
||||
|
||||
return OrderedManyRelatedManager
|
||||
|
||||
return add_custom_queryset_to_many_related_manager(
|
||||
|
@ -73,7 +73,7 @@ class ActivityStreamMiddleware(threading.local, MiddlewareMixin):
|
||||
super().__init__(get_response)
|
||||
|
||||
def process_request(self, request):
|
||||
if hasattr(request, 'user') and hasattr(request.user, 'is_authenticated') and request.user.is_authenticated():
|
||||
if hasattr(request, 'user') and request.user.is_authenticated:
|
||||
user = request.user
|
||||
else:
|
||||
user = None
|
||||
|
@ -44,7 +44,7 @@ class Migration(migrations.Migration):
|
||||
('modified', models.DateTimeField(default=None, editable=False)),
|
||||
('host_name', models.CharField(default='', max_length=1024, editable=False)),
|
||||
('event', models.CharField(max_length=100, choices=[('runner_on_failed', 'Host Failed'), ('runner_on_ok', 'Host OK'), ('runner_on_unreachable', 'Host Unreachable'), ('runner_on_skipped', 'Host Skipped')])),
|
||||
('event_data', jsonfield.fields.JSONField(default={}, blank=True)),
|
||||
('event_data', jsonfield.fields.JSONField(default=dict, blank=True)),
|
||||
('failed', models.BooleanField(default=False, editable=False)),
|
||||
('changed', models.BooleanField(default=False, editable=False)),
|
||||
('counter', models.PositiveIntegerField(default=0)),
|
||||
@ -62,7 +62,7 @@ class Migration(migrations.Migration):
|
||||
('expires', models.DateTimeField(default=django.utils.timezone.now)),
|
||||
('request_hash', models.CharField(default='', max_length=40, blank=True)),
|
||||
('reason', models.CharField(default='', help_text='Reason the auth token was invalidated.', max_length=1024, blank=True)),
|
||||
('user', models.ForeignKey(related_name='auth_tokens', to=settings.AUTH_USER_MODEL)),
|
||||
('user', models.ForeignKey(related_name='auth_tokens', on_delete=models.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
@ -198,7 +198,7 @@ class Migration(migrations.Migration):
|
||||
('created', models.DateTimeField(default=None, editable=False)),
|
||||
('modified', models.DateTimeField(default=None, editable=False)),
|
||||
('event', models.CharField(max_length=100, choices=[('runner_on_failed', 'Host Failed'), ('runner_on_ok', 'Host OK'), ('runner_on_error', 'Host Failure'), ('runner_on_skipped', 'Host Skipped'), ('runner_on_unreachable', 'Host Unreachable'), ('runner_on_no_hosts', 'No Hosts Remaining'), ('runner_on_async_poll', 'Host Polling'), ('runner_on_async_ok', 'Host Async OK'), ('runner_on_async_failed', 'Host Async Failure'), ('runner_on_file_diff', 'File Difference'), ('playbook_on_start', 'Playbook Started'), ('playbook_on_notify', 'Running Handlers'), ('playbook_on_no_hosts_matched', 'No Hosts Matched'), ('playbook_on_no_hosts_remaining', 'No Hosts Remaining'), ('playbook_on_task_start', 'Task Started'), ('playbook_on_vars_prompt', 'Variables Prompted'), ('playbook_on_setup', 'Gathering Facts'), ('playbook_on_import_for_host', 'internal: on Import for Host'), ('playbook_on_not_import_for_host', 'internal: on Not Import for Host'), ('playbook_on_play_start', 'Play Started'), ('playbook_on_stats', 'Playbook Complete')])),
|
||||
('event_data', jsonfield.fields.JSONField(default={}, blank=True)),
|
||||
('event_data', jsonfield.fields.JSONField(default=dict, blank=True)),
|
||||
('failed', models.BooleanField(default=False, editable=False)),
|
||||
('changed', models.BooleanField(default=False, editable=False)),
|
||||
('host_name', models.CharField(default='', max_length=1024, editable=False)),
|
||||
@ -241,7 +241,7 @@ class Migration(migrations.Migration):
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('created', models.DateTimeField(auto_now_add=True)),
|
||||
('modified', models.DateTimeField(auto_now=True)),
|
||||
('instance', models.ForeignKey(to='main.Instance')),
|
||||
('instance', models.ForeignKey(on_delete=models.CASCADE, to='main.Instance')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
@ -287,7 +287,7 @@ class Migration(migrations.Migration):
|
||||
('created', models.DateTimeField(default=None, editable=False)),
|
||||
('modified', models.DateTimeField(default=None, editable=False)),
|
||||
('ldap_dn', models.CharField(default='', max_length=1024)),
|
||||
('user', awx.main.fields.AutoOneToOneField(related_name='profile', editable=False, to=settings.AUTH_USER_MODEL)),
|
||||
('user', awx.main.fields.AutoOneToOneField(related_name='profile', editable=False, on_delete=models.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
@ -304,7 +304,7 @@ class Migration(migrations.Migration):
|
||||
('dtend', models.DateTimeField(default=None, null=True, editable=False)),
|
||||
('rrule', models.CharField(max_length=255)),
|
||||
('next_run', models.DateTimeField(default=None, null=True, editable=False)),
|
||||
('extra_data', jsonfield.fields.JSONField(default={}, blank=True)),
|
||||
('extra_data', jsonfield.fields.JSONField(default=dict, blank=True)),
|
||||
('created_by', models.ForeignKey(related_name="{u'class': 'schedule', u'app_label': 'main'}(class)s_created+", on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True)),
|
||||
('modified_by', models.ForeignKey(related_name="{u'class': 'schedule', u'app_label': 'main'}(class)s_modified+", on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True)),
|
||||
('tags', taggit.managers.TaggableManager(to='taggit.Tag', through='taggit.TaggedItem', blank=True, help_text='A comma-separated list of tags.', verbose_name='Tags')),
|
||||
@ -343,7 +343,7 @@ class Migration(migrations.Migration):
|
||||
('name', models.CharField(max_length=512)),
|
||||
('old_pk', models.PositiveIntegerField(default=None, null=True, editable=False)),
|
||||
('launch_type', models.CharField(default='manual', max_length=20, editable=False, choices=[('manual', 'Manual'), ('relaunch', 'Relaunch'), ('callback', 'Callback'), ('scheduled', 'Scheduled'), ('dependency', 'Dependency')])),
|
||||
('cancel_flag', models.BooleanField(default=False, editable=False)),
|
||||
('cancel_flag', models.BooleanField(blank=True, default=False, editable=False)),
|
||||
('status', models.CharField(default='new', max_length=20, editable=False, choices=[('new', 'New'), ('pending', 'Pending'), ('waiting', 'Waiting'), ('running', 'Running'), ('successful', 'Successful'), ('failed', 'Failed'), ('error', 'Error'), ('canceled', 'Canceled')])),
|
||||
('failed', models.BooleanField(default=False, editable=False)),
|
||||
('started', models.DateTimeField(default=None, null=True, editable=False)),
|
||||
@ -351,7 +351,7 @@ class Migration(migrations.Migration):
|
||||
('elapsed', models.DecimalField(editable=False, max_digits=12, decimal_places=3)),
|
||||
('job_args', models.TextField(default='', editable=False, blank=True)),
|
||||
('job_cwd', models.CharField(default='', max_length=1024, editable=False, blank=True)),
|
||||
('job_env', jsonfield.fields.JSONField(default={}, editable=False, blank=True)),
|
||||
('job_env', jsonfield.fields.JSONField(default=dict, editable=False, blank=True)),
|
||||
('job_explanation', models.TextField(default='', editable=False, blank=True)),
|
||||
('start_args', models.TextField(default='', editable=False, blank=True)),
|
||||
('result_stdout_text', models.TextField(default='', editable=False, blank=True)),
|
||||
@ -380,7 +380,7 @@ class Migration(migrations.Migration):
|
||||
migrations.CreateModel(
|
||||
name='AdHocCommand',
|
||||
fields=[
|
||||
('unifiedjob_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='main.UnifiedJob')),
|
||||
('unifiedjob_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, on_delete=django.db.models.deletion.CASCADE, serialize=False, to='main.UnifiedJob')),
|
||||
('job_type', models.CharField(default='run', max_length=64, choices=[('run', 'Run'), ('check', 'Check')])),
|
||||
('limit', models.CharField(default='', max_length=1024, blank=True)),
|
||||
('module_name', models.CharField(default='', max_length=1024, blank=True)),
|
||||
@ -394,7 +394,7 @@ class Migration(migrations.Migration):
|
||||
migrations.CreateModel(
|
||||
name='InventorySource',
|
||||
fields=[
|
||||
('unifiedjobtemplate_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='main.UnifiedJobTemplate')),
|
||||
('unifiedjobtemplate_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, on_delete=django.db.models.deletion.CASCADE, serialize=False, to='main.UnifiedJobTemplate')),
|
||||
('source', models.CharField(default='', max_length=32, blank=True, choices=[('', 'Manual'), ('file', 'Local File, Directory or Script'), ('rax', 'Rackspace Cloud Servers'), ('ec2', 'Amazon EC2'), ('gce', 'Google Compute Engine'), ('azure', 'Microsoft Azure'), ('vmware', 'VMware vCenter'), ('openstack', 'OpenStack'), ('custom', 'Custom Script')])),
|
||||
('source_path', models.CharField(default='', max_length=1024, editable=False, blank=True)),
|
||||
('source_vars', models.TextField(default='', help_text='Inventory source variables in YAML or JSON format.', blank=True)),
|
||||
@ -411,7 +411,7 @@ class Migration(migrations.Migration):
|
||||
migrations.CreateModel(
|
||||
name='InventoryUpdate',
|
||||
fields=[
|
||||
('unifiedjob_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='main.UnifiedJob')),
|
||||
('unifiedjob_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, on_delete=django.db.models.deletion.CASCADE, serialize=False, to='main.UnifiedJob')),
|
||||
('source', models.CharField(default='', max_length=32, blank=True, choices=[('', 'Manual'), ('file', 'Local File, Directory or Script'), ('rax', 'Rackspace Cloud Servers'), ('ec2', 'Amazon EC2'), ('gce', 'Google Compute Engine'), ('azure', 'Microsoft Azure'), ('vmware', 'VMware vCenter'), ('openstack', 'OpenStack'), ('custom', 'Custom Script')])),
|
||||
('source_path', models.CharField(default='', max_length=1024, editable=False, blank=True)),
|
||||
('source_vars', models.TextField(default='', help_text='Inventory source variables in YAML or JSON format.', blank=True)),
|
||||
@ -427,7 +427,7 @@ class Migration(migrations.Migration):
|
||||
migrations.CreateModel(
|
||||
name='Job',
|
||||
fields=[
|
||||
('unifiedjob_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='main.UnifiedJob')),
|
||||
('unifiedjob_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, on_delete=django.db.models.deletion.CASCADE, serialize=False, to='main.UnifiedJob')),
|
||||
('job_type', models.CharField(default='run', max_length=64, choices=[('run', 'Run'), ('check', 'Check'), ('scan', 'Scan')])),
|
||||
('playbook', models.CharField(default='', max_length=1024, blank=True)),
|
||||
('forks', models.PositiveIntegerField(default=0, blank=True)),
|
||||
@ -435,7 +435,7 @@ class Migration(migrations.Migration):
|
||||
('verbosity', models.PositiveIntegerField(default=0, blank=True, choices=[(0, '0 (Normal)'), (1, '1 (Verbose)'), (2, '2 (More Verbose)'), (3, '3 (Debug)'), (4, '4 (Connection Debug)'), (5, '5 (WinRM Debug)')])),
|
||||
('extra_vars', models.TextField(default='', blank=True)),
|
||||
('job_tags', models.CharField(default='', max_length=1024, blank=True)),
|
||||
('force_handlers', models.BooleanField(default=False)),
|
||||
('force_handlers', models.BooleanField(blank=True, default=False)),
|
||||
('skip_tags', models.CharField(default='', max_length=1024, blank=True)),
|
||||
('start_at_task', models.CharField(default='', max_length=1024, blank=True)),
|
||||
('become_enabled', models.BooleanField(default=False)),
|
||||
@ -448,7 +448,7 @@ class Migration(migrations.Migration):
|
||||
migrations.CreateModel(
|
||||
name='JobTemplate',
|
||||
fields=[
|
||||
('unifiedjobtemplate_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='main.UnifiedJobTemplate')),
|
||||
('unifiedjobtemplate_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, on_delete=django.db.models.deletion.CASCADE, serialize=False, to='main.UnifiedJobTemplate')),
|
||||
('job_type', models.CharField(default='run', max_length=64, choices=[('run', 'Run'), ('check', 'Check'), ('scan', 'Scan')])),
|
||||
('playbook', models.CharField(default='', max_length=1024, blank=True)),
|
||||
('forks', models.PositiveIntegerField(default=0, blank=True)),
|
||||
@ -456,14 +456,14 @@ class Migration(migrations.Migration):
|
||||
('verbosity', models.PositiveIntegerField(default=0, blank=True, choices=[(0, '0 (Normal)'), (1, '1 (Verbose)'), (2, '2 (More Verbose)'), (3, '3 (Debug)'), (4, '4 (Connection Debug)'), (5, '5 (WinRM Debug)')])),
|
||||
('extra_vars', models.TextField(default='', blank=True)),
|
||||
('job_tags', models.CharField(default='', max_length=1024, blank=True)),
|
||||
('force_handlers', models.BooleanField(default=False)),
|
||||
('force_handlers', models.BooleanField(blank=True, default=False)),
|
||||
('skip_tags', models.CharField(default='', max_length=1024, blank=True)),
|
||||
('start_at_task', models.CharField(default='', max_length=1024, blank=True)),
|
||||
('become_enabled', models.BooleanField(default=False)),
|
||||
('host_config_key', models.CharField(default='', max_length=1024, blank=True)),
|
||||
('ask_variables_on_launch', models.BooleanField(default=False)),
|
||||
('survey_enabled', models.BooleanField(default=False)),
|
||||
('survey_spec', jsonfield.fields.JSONField(default={}, blank=True)),
|
||||
('survey_spec', jsonfield.fields.JSONField(default=dict, blank=True)),
|
||||
],
|
||||
options={
|
||||
'ordering': ('name',),
|
||||
@ -473,7 +473,7 @@ class Migration(migrations.Migration):
|
||||
migrations.CreateModel(
|
||||
name='Project',
|
||||
fields=[
|
||||
('unifiedjobtemplate_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='main.UnifiedJobTemplate')),
|
||||
('unifiedjobtemplate_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, on_delete=django.db.models.deletion.CASCADE, serialize=False, to='main.UnifiedJobTemplate')),
|
||||
('local_path', models.CharField(help_text='Local path (relative to PROJECTS_ROOT) containing playbooks and related files for this project.', max_length=1024, blank=True)),
|
||||
('scm_type', models.CharField(default='', max_length=8, verbose_name='SCM Type', blank=True, choices=[('', 'Manual'), ('git', 'Git'), ('hg', 'Mercurial'), ('svn', 'Subversion')])),
|
||||
('scm_url', models.CharField(default='', max_length=1024, verbose_name='SCM URL', blank=True)),
|
||||
@ -492,7 +492,7 @@ class Migration(migrations.Migration):
|
||||
migrations.CreateModel(
|
||||
name='ProjectUpdate',
|
||||
fields=[
|
||||
('unifiedjob_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='main.UnifiedJob')),
|
||||
('unifiedjob_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, on_delete=django.db.models.deletion.CASCADE, serialize=False, to='main.UnifiedJob')),
|
||||
('local_path', models.CharField(help_text='Local path (relative to PROJECTS_ROOT) containing playbooks and related files for this project.', max_length=1024, blank=True)),
|
||||
('scm_type', models.CharField(default='', max_length=8, verbose_name='SCM Type', blank=True, choices=[('', 'Manual'), ('git', 'Git'), ('hg', 'Mercurial'), ('svn', 'Subversion')])),
|
||||
('scm_url', models.CharField(default='', max_length=1024, verbose_name='SCM URL', blank=True)),
|
||||
@ -505,7 +505,7 @@ class Migration(migrations.Migration):
|
||||
migrations.CreateModel(
|
||||
name='SystemJob',
|
||||
fields=[
|
||||
('unifiedjob_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='main.UnifiedJob')),
|
||||
('unifiedjob_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, on_delete=django.db.models.deletion.CASCADE, serialize=False, to='main.UnifiedJob')),
|
||||
('job_type', models.CharField(default='', max_length=32, blank=True, choices=[('cleanup_jobs', 'Remove jobs older than a certain number of days'), ('cleanup_activitystream', 'Remove activity stream entries older than a certain number of days'), ('cleanup_deleted', 'Purge previously deleted items from the database'), ('cleanup_facts', 'Purge and/or reduce the granularity of system tracking data')])),
|
||||
('extra_vars', models.TextField(default='', blank=True)),
|
||||
],
|
||||
@ -517,7 +517,7 @@ class Migration(migrations.Migration):
|
||||
migrations.CreateModel(
|
||||
name='SystemJobTemplate',
|
||||
fields=[
|
||||
('unifiedjobtemplate_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='main.UnifiedJobTemplate')),
|
||||
('unifiedjobtemplate_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, on_delete=django.db.models.deletion.CASCADE, serialize=False, to='main.UnifiedJobTemplate')),
|
||||
('job_type', models.CharField(default='', max_length=32, blank=True, choices=[('cleanup_jobs', 'Remove jobs older than a certain number of days'), ('cleanup_activitystream', 'Remove activity stream entries older than a certain number of days'), ('cleanup_deleted', 'Purge previously deleted items from the database'), ('cleanup_facts', 'Purge and/or reduce the granularity of system tracking data')])),
|
||||
],
|
||||
bases=('main.unifiedjobtemplate', models.Model),
|
||||
@ -550,7 +550,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='unifiedjobtemplate',
|
||||
name='polymorphic_ctype',
|
||||
field=models.ForeignKey(related_name='polymorphic_main.unifiedjobtemplate_set+', editable=False, to='contenttypes.ContentType', null=True),
|
||||
field=models.ForeignKey(related_name='polymorphic_main.unifiedjobtemplate_set+', editable=False, on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType', null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='unifiedjobtemplate',
|
||||
@ -575,7 +575,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='unifiedjob',
|
||||
name='polymorphic_ctype',
|
||||
field=models.ForeignKey(related_name='polymorphic_main.unifiedjob_set+', editable=False, to='contenttypes.ContentType', null=True),
|
||||
field=models.ForeignKey(related_name='polymorphic_main.unifiedjob_set+', editable=False, on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType', null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='unifiedjob',
|
||||
@ -595,7 +595,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='schedule',
|
||||
name='unified_job_template',
|
||||
field=models.ForeignKey(related_name='schedules', to='main.UnifiedJobTemplate'),
|
||||
field=models.ForeignKey(related_name='schedules', on_delete=django.db.models.deletion.CASCADE, to='main.UnifiedJobTemplate'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='permission',
|
||||
@ -610,12 +610,12 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='joborigin',
|
||||
name='unified_job',
|
||||
field=models.OneToOneField(related_name='job_origin', to='main.UnifiedJob'),
|
||||
field=models.OneToOneField(related_name='job_origin', on_delete=django.db.models.deletion.CASCADE, to='main.UnifiedJob'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='inventory',
|
||||
name='organization',
|
||||
field=models.ForeignKey(related_name='inventories', to='main.Organization', help_text='Organization containing this inventory.'),
|
||||
field=models.ForeignKey(related_name='inventories', on_delete=django.db.models.deletion.CASCADE, to='main.Organization', help_text='Organization containing this inventory.'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='inventory',
|
||||
@ -625,7 +625,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='host',
|
||||
name='inventory',
|
||||
field=models.ForeignKey(related_name='hosts', to='main.Inventory'),
|
||||
field=models.ForeignKey(related_name='hosts', on_delete=django.db.models.deletion.CASCADE, to='main.Inventory'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='host',
|
||||
@ -650,7 +650,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='group',
|
||||
name='inventory',
|
||||
field=models.ForeignKey(related_name='groups', to='main.Inventory'),
|
||||
field=models.ForeignKey(related_name='groups', on_delete=django.db.models.deletion.CASCADE, to='main.Inventory'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='group',
|
||||
@ -680,12 +680,12 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='credential',
|
||||
name='team',
|
||||
field=models.ForeignKey(related_name='credentials', default=None, blank=True, to='main.Team', null=True),
|
||||
field=models.ForeignKey(related_name='credentials', on_delete=django.db.models.deletion.SET_NULL, default=None, blank=True, to='main.Team', null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='credential',
|
||||
name='user',
|
||||
field=models.ForeignKey(related_name='credentials', default=None, blank=True, to=settings.AUTH_USER_MODEL, null=True),
|
||||
field=models.ForeignKey(related_name='credentials', on_delete=django.db.models.deletion.SET_NULL, default=None, blank=True, to=settings.AUTH_USER_MODEL, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='adhoccommandevent',
|
||||
@ -774,7 +774,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='projectupdate',
|
||||
name='project',
|
||||
field=models.ForeignKey(related_name='project_updates', editable=False, to='main.Project'),
|
||||
field=models.ForeignKey(related_name='project_updates', on_delete=django.db.models.deletion.CASCADE, editable=False, to='main.Project'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='project',
|
||||
@ -814,12 +814,12 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='jobhostsummary',
|
||||
name='job',
|
||||
field=models.ForeignKey(related_name='job_host_summaries', editable=False, to='main.Job'),
|
||||
field=models.ForeignKey(related_name='job_host_summaries', on_delete=django.db.models.deletion.CASCADE, editable=False, to='main.Job'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='jobevent',
|
||||
name='job',
|
||||
field=models.ForeignKey(related_name='job_events', editable=False, to='main.Job'),
|
||||
field=models.ForeignKey(related_name='job_events', on_delete=django.db.models.deletion.CASCADE, editable=False, to='main.Job'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='job',
|
||||
@ -859,7 +859,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='inventoryupdate',
|
||||
name='inventory_source',
|
||||
field=models.ForeignKey(related_name='inventory_updates', editable=False, to='main.InventorySource'),
|
||||
field=models.ForeignKey(related_name='inventory_updates', on_delete=django.db.models.deletion.CASCADE, editable=False, to='main.InventorySource'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='inventoryupdate',
|
||||
@ -874,12 +874,12 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='inventorysource',
|
||||
name='group',
|
||||
field=awx.main.fields.AutoOneToOneField(related_name='inventory_source', null=True, default=None, editable=False, to='main.Group'),
|
||||
field=awx.main.fields.AutoOneToOneField(related_name='inventory_source', on_delete=django.db.models.deletion.SET_NULL, null=True, default=None, editable=False, to='main.Group'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='inventorysource',
|
||||
name='inventory',
|
||||
field=models.ForeignKey(related_name='inventory_sources', default=None, editable=False, to='main.Inventory', null=True),
|
||||
field=models.ForeignKey(related_name='inventory_sources', on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to='main.Inventory', null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='inventorysource',
|
||||
@ -916,7 +916,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='adhoccommandevent',
|
||||
name='ad_hoc_command',
|
||||
field=models.ForeignKey(related_name='ad_hoc_command_events', editable=False, to='main.AdHocCommand'),
|
||||
field=models.ForeignKey(related_name='ad_hoc_command_events', on_delete=django.db.models.deletion.CASCADE, editable=False, to='main.AdHocCommand'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='adhoccommand',
|
||||
|
@ -13,7 +13,6 @@ from django.conf import settings
|
||||
from django.utils.timezone import now
|
||||
|
||||
import jsonfield.fields
|
||||
import jsonbfield.fields
|
||||
import taggit.managers
|
||||
|
||||
|
||||
@ -144,7 +143,7 @@ class Migration(migrations.Migration):
|
||||
('category', models.CharField(max_length=128)),
|
||||
('value', models.TextField(blank=True)),
|
||||
('value_type', models.CharField(max_length=12, choices=[('string', 'String'), ('int', 'Integer'), ('float', 'Decimal'), ('json', 'JSON'), ('bool', 'Boolean'), ('password', 'Password'), ('list', 'List')])),
|
||||
('user', models.ForeignKey(related_name='settings', default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True)),
|
||||
('user', models.ForeignKey(related_name='settings', default=None, editable=False, to=settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True)),
|
||||
],
|
||||
),
|
||||
# Notification changes
|
||||
@ -185,7 +184,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='notification',
|
||||
name='notification_template',
|
||||
field=models.ForeignKey(related_name='notifications', editable=False, to='main.NotificationTemplate'),
|
||||
field=models.ForeignKey(related_name='notifications', editable=False, on_delete=models.CASCADE, to='main.NotificationTemplate'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='activitystream',
|
||||
@ -239,8 +238,8 @@ class Migration(migrations.Migration):
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('timestamp', models.DateTimeField(default=None, help_text='Date and time of the corresponding fact scan gathering time.', editable=False)),
|
||||
('module', models.CharField(max_length=128)),
|
||||
('facts', jsonbfield.fields.JSONField(default={}, help_text='Arbitrary JSON structure of module facts captured at timestamp for a single host.', blank=True)),
|
||||
('host', models.ForeignKey(related_name='facts', to='main.Host', help_text='Host for the facts that the fact scan captured.')),
|
||||
('facts', awx.main.fields.JSONBField(default=dict, help_text='Arbitrary JSON structure of module facts captured at timestamp for a single host.', blank=True)),
|
||||
('host', models.ForeignKey(related_name='facts', to='main.Host', on_delete=models.CASCADE, help_text='Host for the facts that the fact scan captured.')),
|
||||
],
|
||||
),
|
||||
migrations.AlterIndexTogether(
|
||||
@ -318,7 +317,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='project',
|
||||
name='organization',
|
||||
field=models.ForeignKey(related_name='projects', to='main.Organization', blank=True, null=True),
|
||||
field=models.ForeignKey(related_name='projects', to='main.Organization', on_delete=models.CASCADE, blank=True, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='team',
|
||||
@ -367,7 +366,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='credential',
|
||||
name='organization',
|
||||
field=models.ForeignKey(related_name='credentials', default=None, blank=True, to='main.Organization', null=True),
|
||||
field=models.ForeignKey(related_name='credentials', on_delete=models.CASCADE, default=None, blank=True, to='main.Organization', null=True),
|
||||
),
|
||||
|
||||
#
|
||||
@ -382,7 +381,7 @@ class Migration(migrations.Migration):
|
||||
('members', models.ManyToManyField(related_name='roles', to=settings.AUTH_USER_MODEL)),
|
||||
('parents', models.ManyToManyField(related_name='children', to='main.Role')),
|
||||
('implicit_parents', models.TextField(default='[]')),
|
||||
('content_type', models.ForeignKey(default=None, to='contenttypes.ContentType', null=True)),
|
||||
('content_type', models.ForeignKey(default=None, to='contenttypes.ContentType', on_delete=models.CASCADE, null=True)),
|
||||
('object_id', models.PositiveIntegerField(default=None, null=True)),
|
||||
|
||||
],
|
||||
@ -398,8 +397,8 @@ class Migration(migrations.Migration):
|
||||
('role_field', models.TextField()),
|
||||
('content_type_id', models.PositiveIntegerField()),
|
||||
('object_id', models.PositiveIntegerField()),
|
||||
('ancestor', models.ForeignKey(related_name='+', to='main.Role')),
|
||||
('descendent', models.ForeignKey(related_name='+', to='main.Role')),
|
||||
('ancestor', models.ForeignKey(on_delete=models.CASCADE, related_name='+', to='main.Role')),
|
||||
('descendent', models.ForeignKey(on_delete=models.CASCADE, related_name='+', to='main.Role')),
|
||||
],
|
||||
options={
|
||||
'db_table': 'main_rbac_role_ancestors',
|
||||
@ -569,7 +568,7 @@ class Migration(migrations.Migration):
|
||||
('name', models.CharField(max_length=512)),
|
||||
('created_by', models.ForeignKey(related_name="{u'class': 'label', u'app_label': 'main'}(class)s_created+", on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True)),
|
||||
('modified_by', models.ForeignKey(related_name="{u'class': 'label', u'app_label': 'main'}(class)s_modified+", on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True)),
|
||||
('organization', models.ForeignKey(related_name='labels', to='main.Organization', help_text='Organization this label belongs to.')),
|
||||
('organization', models.ForeignKey(related_name='labels', on_delete=django.db.models.deletion.CASCADE, to='main.Organization', help_text='Organization this label belongs to.')),
|
||||
('tags', taggit.managers.TaggableManager(to='taggit.Tag', through='taggit.TaggedItem', blank=True, help_text='A comma-separated list of tags.', verbose_name='Tags')),
|
||||
],
|
||||
options={
|
||||
@ -599,12 +598,12 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='label',
|
||||
name='organization',
|
||||
field=models.ForeignKey(related_name='labels', on_delete=django.db.models.deletion.SET_NULL, default=None, blank=True, to='main.Organization', help_text='Organization this label belongs to.', null=True),
|
||||
field=models.ForeignKey(related_name='labels', on_delete=django.db.models.deletion.CASCADE, default=None, blank=True, to='main.Organization', help_text='Organization this label belongs to.', null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='label',
|
||||
name='organization',
|
||||
field=models.ForeignKey(related_name='labels', to='main.Organization', help_text='Organization this label belongs to.'),
|
||||
field=models.ForeignKey(related_name='labels', on_delete=django.db.models.deletion.CASCADE, to='main.Organization', help_text='Organization this label belongs to.'),
|
||||
),
|
||||
# InventorySource Credential
|
||||
migrations.AddField(
|
||||
@ -630,12 +629,12 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='credential',
|
||||
name='deprecated_team',
|
||||
field=models.ForeignKey(related_name='deprecated_credentials', default=None, blank=True, to='main.Team', null=True),
|
||||
field=models.ForeignKey(related_name='deprecated_credentials', on_delete=django.db.models.deletion.SET_NULL, default=None, blank=True, to='main.Team', null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='credential',
|
||||
name='deprecated_user',
|
||||
field=models.ForeignKey(related_name='deprecated_credentials', default=None, blank=True, to=settings.AUTH_USER_MODEL, null=True),
|
||||
field=models.ForeignKey(related_name='deprecated_credentials', on_delete=django.db.models.deletion.SET_NULL, default=None, blank=True, to=settings.AUTH_USER_MODEL, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='credential',
|
||||
|
@ -116,7 +116,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='team',
|
||||
name='organization',
|
||||
field=models.ForeignKey(related_name='teams', to='main.Organization'),
|
||||
field=models.ForeignKey(related_name='teams', on_delete=models.CASCADE, to='main.Organization'),
|
||||
preserve_default=False,
|
||||
),
|
||||
] + _squashed.operations(SQUASHED_30, applied=True)
|
||||
|
@ -74,7 +74,7 @@ class Migration(migrations.Migration):
|
||||
migrations.CreateModel(
|
||||
name='WorkflowJob',
|
||||
fields=[
|
||||
('unifiedjob_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='main.UnifiedJob')),
|
||||
('unifiedjob_ptr', models.OneToOneField(parent_link=True, auto_created=True, on_delete=models.CASCADE, primary_key=True, serialize=False, to='main.UnifiedJob')),
|
||||
('extra_vars', models.TextField(default='', blank=True)),
|
||||
],
|
||||
options={
|
||||
@ -100,7 +100,7 @@ class Migration(migrations.Migration):
|
||||
migrations.CreateModel(
|
||||
name='WorkflowJobTemplate',
|
||||
fields=[
|
||||
('unifiedjobtemplate_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='main.UnifiedJobTemplate')),
|
||||
('unifiedjobtemplate_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, on_delete=models.CASCADE, serialize=False, to='main.UnifiedJobTemplate')),
|
||||
('extra_vars', models.TextField(default='', blank=True)),
|
||||
('admin_role', awx.main.fields.ImplicitRoleField(related_name='+', parent_role='singleton:system_administrator', to='main.Role', null='True')),
|
||||
],
|
||||
@ -116,7 +116,7 @@ class Migration(migrations.Migration):
|
||||
('failure_nodes', models.ManyToManyField(related_name='workflowjobtemplatenodes_failure', to='main.WorkflowJobTemplateNode', blank=True)),
|
||||
('success_nodes', models.ManyToManyField(related_name='workflowjobtemplatenodes_success', to='main.WorkflowJobTemplateNode', blank=True)),
|
||||
('unified_job_template', models.ForeignKey(related_name='workflowjobtemplatenodes', on_delete=django.db.models.deletion.SET_NULL, default=None, blank=True, to='main.UnifiedJobTemplate', null=True)),
|
||||
('workflow_job_template', models.ForeignKey(related_name='workflow_job_template_nodes', default=None, blank=True, to='main.WorkflowJobTemplate', null=True)),
|
||||
('workflow_job_template', models.ForeignKey(related_name='workflow_job_template_nodes', on_delete=models.SET_NULL, default=None, blank=True, to='main.WorkflowJobTemplate', null=True)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
@ -161,7 +161,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='workflowjobnode',
|
||||
name='char_prompts',
|
||||
field=jsonfield.fields.JSONField(default={}, blank=True),
|
||||
field=jsonfield.fields.JSONField(default=dict, blank=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='workflowjobnode',
|
||||
@ -191,7 +191,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='workflowjobtemplatenode',
|
||||
name='char_prompts',
|
||||
field=jsonfield.fields.JSONField(default={}, blank=True),
|
||||
field=jsonfield.fields.JSONField(default=dict, blank=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='workflowjobtemplatenode',
|
||||
@ -211,7 +211,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='workflowjobnode',
|
||||
name='workflow_job',
|
||||
field=models.ForeignKey(related_name='workflow_job_nodes', default=None, blank=True, to='main.WorkflowJob', null=True),
|
||||
field=models.ForeignKey(related_name='workflow_job_nodes', on_delete=django.db.models.deletion.CASCADE, default=None, blank=True, to='main.WorkflowJob', null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='workflowjobtemplate',
|
||||
@ -227,12 +227,12 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='job',
|
||||
name='artifacts',
|
||||
field=jsonfield.fields.JSONField(default={}, editable=False, blank=True),
|
||||
field=jsonfield.fields.JSONField(default=dict, editable=False, blank=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='workflowjobnode',
|
||||
name='ancestor_artifacts',
|
||||
field=jsonfield.fields.JSONField(default={}, editable=False, blank=True),
|
||||
field=jsonfield.fields.JSONField(default=dict, editable=False, blank=True),
|
||||
),
|
||||
# Job timeout settings
|
||||
migrations.AddField(
|
||||
@ -397,7 +397,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='workflowjob',
|
||||
name='survey_passwords',
|
||||
field=jsonfield.fields.JSONField(default={}, editable=False, blank=True),
|
||||
field=jsonfield.fields.JSONField(default=dict, editable=False, blank=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='workflowjobtemplate',
|
||||
@ -407,33 +407,33 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='workflowjobtemplate',
|
||||
name='survey_spec',
|
||||
field=jsonfield.fields.JSONField(default={}, blank=True),
|
||||
field=jsonfield.fields.JSONField(default=dict, blank=True),
|
||||
),
|
||||
# JSON field changes
|
||||
migrations.AlterField(
|
||||
model_name='adhoccommandevent',
|
||||
name='event_data',
|
||||
field=awx.main.fields.JSONField(default={}, blank=True),
|
||||
field=awx.main.fields.JSONField(default=dict, blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='job',
|
||||
name='artifacts',
|
||||
field=awx.main.fields.JSONField(default={}, editable=False, blank=True),
|
||||
field=awx.main.fields.JSONField(default=dict, editable=False, blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='job',
|
||||
name='survey_passwords',
|
||||
field=awx.main.fields.JSONField(default={}, editable=False, blank=True),
|
||||
field=awx.main.fields.JSONField(default=dict, editable=False, blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='jobevent',
|
||||
name='event_data',
|
||||
field=awx.main.fields.JSONField(default={}, blank=True),
|
||||
field=awx.main.fields.JSONField(default=dict, blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='jobtemplate',
|
||||
name='survey_spec',
|
||||
field=awx.main.fields.JSONField(default={}, blank=True),
|
||||
field=awx.main.fields.JSONField(default=dict, blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='notification',
|
||||
@ -453,37 +453,37 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='schedule',
|
||||
name='extra_data',
|
||||
field=awx.main.fields.JSONField(default={}, blank=True),
|
||||
field=awx.main.fields.JSONField(default=dict, blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='unifiedjob',
|
||||
name='job_env',
|
||||
field=awx.main.fields.JSONField(default={}, editable=False, blank=True),
|
||||
field=awx.main.fields.JSONField(default=dict, editable=False, blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='workflowjob',
|
||||
name='survey_passwords',
|
||||
field=awx.main.fields.JSONField(default={}, editable=False, blank=True),
|
||||
field=awx.main.fields.JSONField(default=dict, editable=False, blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='workflowjobnode',
|
||||
name='ancestor_artifacts',
|
||||
field=awx.main.fields.JSONField(default={}, editable=False, blank=True),
|
||||
field=awx.main.fields.JSONField(default=dict, editable=False, blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='workflowjobnode',
|
||||
name='char_prompts',
|
||||
field=awx.main.fields.JSONField(default={}, blank=True),
|
||||
field=awx.main.fields.JSONField(default=dict, blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='workflowjobtemplate',
|
||||
name='survey_spec',
|
||||
field=awx.main.fields.JSONField(default={}, blank=True),
|
||||
field=awx.main.fields.JSONField(default=dict, blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='workflowjobtemplatenode',
|
||||
name='char_prompts',
|
||||
field=awx.main.fields.JSONField(default={}, blank=True),
|
||||
field=awx.main.fields.JSONField(default=dict, blank=True),
|
||||
),
|
||||
# Job Project Update
|
||||
migrations.AddField(
|
||||
|
@ -55,12 +55,12 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='inventorysource',
|
||||
name='deprecated_group',
|
||||
field=models.OneToOneField(related_name='deprecated_inventory_source', null=True, default=None, to='main.Group'),
|
||||
field=models.OneToOneField(related_name='deprecated_inventory_source', on_delete=models.CASCADE, null=True, default=None, to='main.Group'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='inventorysource',
|
||||
name='inventory',
|
||||
field=models.ForeignKey(related_name='inventory_sources', default=None, to='main.Inventory', null=True),
|
||||
field=models.ForeignKey(related_name='inventory_sources', default=None, to='main.Inventory', on_delete=models.CASCADE, null=True),
|
||||
),
|
||||
|
||||
# Smart Inventory
|
||||
@ -78,13 +78,13 @@ class Migration(migrations.Migration):
|
||||
name='SmartInventoryMembership',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('host', models.ForeignKey(related_name='+', to='main.Host')),
|
||||
('host', models.ForeignKey(related_name='+', on_delete=models.CASCADE, to='main.Host')),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='smartinventorymembership',
|
||||
name='inventory',
|
||||
field=models.ForeignKey(related_name='+', to='main.Inventory'),
|
||||
field=models.ForeignKey(on_delete=models.CASCADE, related_name='+', to='main.Inventory'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='host',
|
||||
@ -105,19 +105,19 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='inventory',
|
||||
name='organization',
|
||||
field=models.ForeignKey(related_name='inventories', on_delete=models.deletion.SET_NULL, to='main.Organization', help_text='Organization containing this inventory.', null=True),
|
||||
field=models.ForeignKey(related_name='inventories', on_delete=models.SET_NULL, to='main.Organization', help_text='Organization containing this inventory.', null=True),
|
||||
),
|
||||
|
||||
# Facts
|
||||
migrations.AlterField(
|
||||
model_name='fact',
|
||||
name='facts',
|
||||
field=awx.main.fields.JSONBField(default={}, help_text='Arbitrary JSON structure of module facts captured at timestamp for a single host.', blank=True),
|
||||
field=awx.main.fields.JSONBField(default=dict, help_text='Arbitrary JSON structure of module facts captured at timestamp for a single host.', blank=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='host',
|
||||
name='ansible_facts',
|
||||
field=awx.main.fields.JSONBField(default={}, help_text='Arbitrary JSON structure of most recent ansible_facts, per-host.', blank=True),
|
||||
field=awx.main.fields.JSONBField(default=dict, help_text='Arbitrary JSON structure of most recent ansible_facts, per-host.', blank=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='host',
|
||||
@ -148,12 +148,12 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='inventorysource',
|
||||
name='source_project',
|
||||
field=models.ForeignKey(related_name='scm_inventory_sources', default=None, blank=True, to='main.Project', help_text='Project containing inventory file used as source.', null=True),
|
||||
field=models.ForeignKey(related_name='scm_inventory_sources', on_delete=models.CASCADE, default=None, blank=True, to='main.Project', help_text='Project containing inventory file used as source.', null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='inventoryupdate',
|
||||
name='source_project_update',
|
||||
field=models.ForeignKey(related_name='scm_inventory_updates', default=None, blank=True, to='main.ProjectUpdate', help_text='Inventory files from this Project Update were used for the inventory update.', null=True),
|
||||
field=models.ForeignKey(related_name='scm_inventory_updates', on_delete=models.CASCADE, default=None, blank=True, to='main.ProjectUpdate', help_text='Inventory files from this Project Update were used for the inventory update.', null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='project',
|
||||
@ -200,7 +200,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='notificationtemplate',
|
||||
name='organization',
|
||||
field=models.ForeignKey(related_name='notification_templates', to='main.Organization', null=True),
|
||||
field=models.ForeignKey(related_name='notification_templates', on_delete=models.CASCADE, to='main.Organization', null=True),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='notificationtemplate',
|
||||
@ -312,7 +312,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='inventory',
|
||||
name='insights_credential',
|
||||
field=models.ForeignKey(related_name='insights_inventories', on_delete=models.deletion.SET_NULL, default=None, blank=True, to='main.Credential', help_text='Credentials to be used by hosts belonging to this inventory when accessing Red Hat Insights API.', null=True),
|
||||
field=models.ForeignKey(related_name='insights_inventories', on_delete=models.SET_NULL, default=None, blank=True, to='main.Credential', help_text='Credentials to be used by hosts belonging to this inventory when accessing Red Hat Insights API.', null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='inventory',
|
||||
@ -382,10 +382,10 @@ class Migration(migrations.Migration):
|
||||
('name', models.CharField(max_length=512)),
|
||||
('kind', models.CharField(max_length=32, choices=[('ssh', 'Machine'), ('vault', 'Vault'), ('net', 'Network'), ('scm', 'Source Control'), ('cloud', 'Cloud'), ('insights', 'Insights')])),
|
||||
('managed_by_tower', models.BooleanField(default=False, editable=False)),
|
||||
('inputs', awx.main.fields.CredentialTypeInputField(default={}, blank=True, help_text='Enter inputs using either JSON or YAML syntax. Use the radio button to toggle between the two. Refer to the Ansible Tower documentation for example syntax.')),
|
||||
('injectors', awx.main.fields.CredentialTypeInjectorField(default={}, blank=True, help_text='Enter injectors using either JSON or YAML syntax. Use the radio button to toggle between the two. Refer to the Ansible Tower documentation for example syntax.')),
|
||||
('created_by', models.ForeignKey(related_name="{u'class': 'credentialtype', u'app_label': 'main'}(class)s_created+", on_delete=models.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True)),
|
||||
('modified_by', models.ForeignKey(related_name="{u'class': 'credentialtype', u'app_label': 'main'}(class)s_modified+", on_delete=models.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True)),
|
||||
('inputs', awx.main.fields.CredentialTypeInputField(default=dict, blank=True, help_text='Enter inputs using either JSON or YAML syntax. Use the radio button to toggle between the two. Refer to the Ansible Tower documentation for example syntax.')),
|
||||
('injectors', awx.main.fields.CredentialTypeInjectorField(default=dict, blank=True, help_text='Enter injectors using either JSON or YAML syntax. Use the radio button to toggle between the two. Refer to the Ansible Tower documentation for example syntax.')),
|
||||
('created_by', models.ForeignKey(related_name="{u'class': 'credentialtype', u'app_label': 'main'}(class)s_created+", on_delete=models.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True)),
|
||||
('modified_by', models.ForeignKey(related_name="{u'class': 'credentialtype', u'app_label': 'main'}(class)s_modified+", on_delete=models.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True)),
|
||||
('tags', taggit.managers.TaggableManager(to='taggit.Tag', through='taggit.TaggedItem', blank=True, help_text='A comma-separated list of tags.', verbose_name='Tags')),
|
||||
],
|
||||
options={
|
||||
@ -399,23 +399,23 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='credential',
|
||||
name='inputs',
|
||||
field=awx.main.fields.CredentialInputField(default={}, blank=True),
|
||||
field=awx.main.fields.CredentialInputField(default=dict, blank=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='credential',
|
||||
name='credential_type',
|
||||
field=models.ForeignKey(related_name='credentials', to='main.CredentialType', null=True),
|
||||
field=models.ForeignKey(related_name='credentials', on_delete=models.CASCADE, to='main.CredentialType', null=True),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='job',
|
||||
name='vault_credential',
|
||||
field=models.ForeignKey(related_name='jobs_as_vault_credential+', on_delete=models.deletion.SET_NULL, default=None, blank=True, to='main.Credential', null=True),
|
||||
field=models.ForeignKey(related_name='jobs_as_vault_credential+', on_delete=models.SET_NULL, default=None, blank=True, to='main.Credential', null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='jobtemplate',
|
||||
name='vault_credential',
|
||||
field=models.ForeignKey(related_name='jobtemplates_as_vault_credential+', on_delete=models.deletion.SET_NULL, default=None, blank=True, to='main.Credential', null=True),
|
||||
field=models.ForeignKey(related_name='jobtemplates_as_vault_credential+', on_delete=models.SET_NULL, default=None, blank=True, to='main.Credential', null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='job',
|
||||
@ -452,7 +452,7 @@ class Migration(migrations.Migration):
|
||||
('name', models.CharField(unique=True, max_length=250)),
|
||||
('created', models.DateTimeField(auto_now_add=True)),
|
||||
('modified', models.DateTimeField(auto_now=True)),
|
||||
('controller', models.ForeignKey(related_name='controlled_groups', default=None, editable=False, to='main.InstanceGroup', help_text='Instance Group to remotely control this group.', null=True)),
|
||||
('controller', models.ForeignKey(related_name='controlled_groups', on_delete=models.CASCADE, default=None, editable=False, to='main.InstanceGroup', help_text='Instance Group to remotely control this group.', null=True)),
|
||||
('instances', models.ManyToManyField(help_text='Instances that are members of this InstanceGroup', related_name='rampart_groups', editable=False, to='main.Instance')),
|
||||
],
|
||||
),
|
||||
@ -464,7 +464,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='unifiedjob',
|
||||
name='instance_group',
|
||||
field=models.ForeignKey(on_delete=models.deletion.SET_NULL, default=None, blank=True, to='main.InstanceGroup', help_text='The Rampart/Instance group the job was run under', null=True),
|
||||
field=models.ForeignKey(on_delete=models.SET_NULL, default=None, blank=True, to='main.InstanceGroup', help_text='The Rampart/Instance group the job was run under', null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='unifiedjobtemplate',
|
||||
|
@ -103,12 +103,12 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='credential',
|
||||
name='credential_type',
|
||||
field=models.ForeignKey(related_name='credentials', to='main.CredentialType', null=False, help_text='Specify the type of credential you want to create. Refer to the Ansible Tower documentation for details on each type.')
|
||||
field=models.ForeignKey(related_name='credentials', to='main.CredentialType', on_delete=models.CASCADE, null=False, help_text='Specify the type of credential you want to create. Refer to the Ansible Tower documentation for details on each type.')
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='credential',
|
||||
name='inputs',
|
||||
field=awx.main.fields.CredentialInputField(default={}, help_text='Enter inputs using either JSON or YAML syntax. Use the radio button to toggle between the two. Refer to the Ansible Tower documentation for example syntax.', blank=True),
|
||||
field=awx.main.fields.CredentialInputField(default=dict, help_text='Enter inputs using either JSON or YAML syntax. Use the radio button to toggle between the two. Refer to the Ansible Tower documentation for example syntax.', blank=True),
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='job',
|
||||
|
@ -20,7 +20,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='schedule',
|
||||
name='char_prompts',
|
||||
field=awx.main.fields.JSONField(default={}, blank=True),
|
||||
field=awx.main.fields.JSONField(default=dict, blank=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='schedule',
|
||||
@ -35,7 +35,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='schedule',
|
||||
name='survey_passwords',
|
||||
field=awx.main.fields.JSONField(default={}, editable=False, blank=True),
|
||||
field=awx.main.fields.JSONField(default=dict, editable=False, blank=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='workflowjobnode',
|
||||
@ -45,12 +45,12 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='workflowjobnode',
|
||||
name='extra_data',
|
||||
field=awx.main.fields.JSONField(default={}, blank=True),
|
||||
field=awx.main.fields.JSONField(default=dict, blank=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='workflowjobnode',
|
||||
name='survey_passwords',
|
||||
field=awx.main.fields.JSONField(default={}, editable=False, blank=True),
|
||||
field=awx.main.fields.JSONField(default=dict, editable=False, blank=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='workflowjobtemplatenode',
|
||||
@ -60,12 +60,12 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='workflowjobtemplatenode',
|
||||
name='extra_data',
|
||||
field=awx.main.fields.JSONField(default={}, blank=True),
|
||||
field=awx.main.fields.JSONField(default=dict, blank=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='workflowjobtemplatenode',
|
||||
name='survey_passwords',
|
||||
field=awx.main.fields.JSONField(default={}, editable=False, blank=True),
|
||||
field=awx.main.fields.JSONField(default=dict, editable=False, blank=True),
|
||||
),
|
||||
# Run data migration before removing the old credential field
|
||||
migrations.RunPython(migration_utils.set_current_apps_for_migrations, migrations.RunPython.noop),
|
||||
@ -83,9 +83,9 @@ class Migration(migrations.Migration):
|
||||
name='JobLaunchConfig',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('extra_data', awx.main.fields.JSONField(blank=True, default={})),
|
||||
('survey_passwords', awx.main.fields.JSONField(blank=True, default={}, editable=False)),
|
||||
('char_prompts', awx.main.fields.JSONField(blank=True, default={})),
|
||||
('extra_data', awx.main.fields.JSONField(blank=True, default=dict)),
|
||||
('survey_passwords', awx.main.fields.JSONField(blank=True, default=dict, editable=False)),
|
||||
('char_prompts', awx.main.fields.JSONField(blank=True, default=dict)),
|
||||
('credentials', models.ManyToManyField(related_name='joblaunchconfigs', to='main.Credential')),
|
||||
('inventory', models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='joblaunchconfigs', to='main.Inventory')),
|
||||
('job', models.OneToOneField(editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='launch_config', to='main.UnifiedJob')),
|
||||
@ -94,51 +94,51 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='workflowjobtemplate',
|
||||
name='ask_variables_on_launch',
|
||||
field=awx.main.fields.AskForField(default=False),
|
||||
field=awx.main.fields.AskForField(blank=True, default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='jobtemplate',
|
||||
name='ask_credential_on_launch',
|
||||
field=awx.main.fields.AskForField(default=False),
|
||||
field=awx.main.fields.AskForField(blank=True, default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='jobtemplate',
|
||||
name='ask_diff_mode_on_launch',
|
||||
field=awx.main.fields.AskForField(default=False),
|
||||
field=awx.main.fields.AskForField(blank=True, default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='jobtemplate',
|
||||
name='ask_inventory_on_launch',
|
||||
field=awx.main.fields.AskForField(default=False),
|
||||
field=awx.main.fields.AskForField(blank=True, default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='jobtemplate',
|
||||
name='ask_job_type_on_launch',
|
||||
field=awx.main.fields.AskForField(default=False),
|
||||
field=awx.main.fields.AskForField(blank=True, default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='jobtemplate',
|
||||
name='ask_limit_on_launch',
|
||||
field=awx.main.fields.AskForField(default=False),
|
||||
field=awx.main.fields.AskForField(blank=True, default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='jobtemplate',
|
||||
name='ask_skip_tags_on_launch',
|
||||
field=awx.main.fields.AskForField(default=False),
|
||||
field=awx.main.fields.AskForField(blank=True, default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='jobtemplate',
|
||||
name='ask_tags_on_launch',
|
||||
field=awx.main.fields.AskForField(default=False),
|
||||
field=awx.main.fields.AskForField(blank=True, default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='jobtemplate',
|
||||
name='ask_variables_on_launch',
|
||||
field=awx.main.fields.AskForField(default=False),
|
||||
field=awx.main.fields.AskForField(blank=True, default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='jobtemplate',
|
||||
name='ask_verbosity_on_launch',
|
||||
field=awx.main.fields.AskForField(default=False),
|
||||
field=awx.main.fields.AskForField(blank=True, default=False),
|
||||
),
|
||||
]
|
||||
|
@ -20,7 +20,7 @@ class Migration(migrations.Migration):
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('created', models.DateTimeField(default=None, editable=False)),
|
||||
('modified', models.DateTimeField(default=None, editable=False)),
|
||||
('event_data', awx.main.fields.JSONField(blank=True, default={})),
|
||||
('event_data', awx.main.fields.JSONField(blank=True, default=dict)),
|
||||
('uuid', models.CharField(default='', editable=False, max_length=1024)),
|
||||
('counter', models.PositiveIntegerField(default=0, editable=False)),
|
||||
('stdout', models.TextField(default='', editable=False)),
|
||||
@ -40,7 +40,7 @@ class Migration(migrations.Migration):
|
||||
('created', models.DateTimeField(default=None, editable=False)),
|
||||
('modified', models.DateTimeField(default=None, editable=False)),
|
||||
('event', models.CharField(choices=[('runner_on_failed', 'Host Failed'), ('runner_on_ok', 'Host OK'), ('runner_on_error', 'Host Failure'), ('runner_on_skipped', 'Host Skipped'), ('runner_on_unreachable', 'Host Unreachable'), ('runner_on_no_hosts', 'No Hosts Remaining'), ('runner_on_async_poll', 'Host Polling'), ('runner_on_async_ok', 'Host Async OK'), ('runner_on_async_failed', 'Host Async Failure'), ('runner_item_on_ok', 'Item OK'), ('runner_item_on_failed', 'Item Failed'), ('runner_item_on_skipped', 'Item Skipped'), ('runner_retry', 'Host Retry'), ('runner_on_file_diff', 'File Difference'), ('playbook_on_start', 'Playbook Started'), ('playbook_on_notify', 'Running Handlers'), ('playbook_on_include', 'Including File'), ('playbook_on_no_hosts_matched', 'No Hosts Matched'), ('playbook_on_no_hosts_remaining', 'No Hosts Remaining'), ('playbook_on_task_start', 'Task Started'), ('playbook_on_vars_prompt', 'Variables Prompted'), ('playbook_on_setup', 'Gathering Facts'), ('playbook_on_import_for_host', 'internal: on Import for Host'), ('playbook_on_not_import_for_host', 'internal: on Not Import for Host'), ('playbook_on_play_start', 'Play Started'), ('playbook_on_stats', 'Playbook Complete'), ('debug', 'Debug'), ('verbose', 'Verbose'), ('deprecated', 'Deprecated'), ('warning', 'Warning'), ('system_warning', 'System Warning'), ('error', 'Error')], max_length=100)),
|
||||
('event_data', awx.main.fields.JSONField(blank=True, default={})),
|
||||
('event_data', awx.main.fields.JSONField(blank=True, default=dict)),
|
||||
('failed', models.BooleanField(default=False, editable=False)),
|
||||
('changed', models.BooleanField(default=False, editable=False)),
|
||||
('uuid', models.CharField(default='', editable=False, max_length=1024)),
|
||||
@ -65,7 +65,7 @@ class Migration(migrations.Migration):
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('created', models.DateTimeField(default=None, editable=False)),
|
||||
('modified', models.DateTimeField(default=None, editable=False)),
|
||||
('event_data', awx.main.fields.JSONField(blank=True, default={})),
|
||||
('event_data', awx.main.fields.JSONField(blank=True, default=dict)),
|
||||
('uuid', models.CharField(default='', editable=False, max_length=1024)),
|
||||
('counter', models.PositiveIntegerField(default=0, editable=False)),
|
||||
('stdout', models.TextField(default='', editable=False)),
|
||||
|
@ -17,7 +17,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='workflowjob',
|
||||
name='char_prompts',
|
||||
field=awx.main.fields.JSONField(blank=True, default={}),
|
||||
field=awx.main.fields.JSONField(blank=True, default=dict),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='workflowjob',
|
||||
@ -27,7 +27,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='workflowjobtemplate',
|
||||
name='ask_inventory_on_launch',
|
||||
field=awx.main.fields.AskForField(default=False),
|
||||
field=awx.main.fields.AskForField(blank=True, default=False),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='workflowjobtemplate',
|
||||
|
@ -34,7 +34,7 @@ class Migration(migrations.Migration):
|
||||
('modified', models.DateTimeField(default=None, editable=False)),
|
||||
('description', models.TextField(blank=True, default='')),
|
||||
('input_field_name', models.CharField(max_length=1024)),
|
||||
('metadata', awx.main.fields.DynamicCredentialInputField(blank=True, default={})),
|
||||
('metadata', awx.main.fields.DynamicCredentialInputField(blank=True, default=dict)),
|
||||
('created_by', models.ForeignKey(default=None, editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name="{'class': 'credentialinputsource', 'model_name': 'credentialinputsource', 'app_label': 'main'}(class)s_created+", to=settings.AUTH_USER_MODEL)),
|
||||
('modified_by', models.ForeignKey(default=None, editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name="{'class': 'credentialinputsource', 'model_name': 'credentialinputsource', 'app_label': 'main'}(class)s_modified+", to=settings.AUTH_USER_MODEL)),
|
||||
('source_credential', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='target_input_sources', to='main.Credential')),
|
||||
|
@ -30,7 +30,7 @@ SQUASHED_30 = {
|
||||
migrations.AddField(
|
||||
model_name='job',
|
||||
name='survey_passwords',
|
||||
field=jsonfield.fields.JSONField(default={}, editable=False, blank=True),
|
||||
field=jsonfield.fields.JSONField(default=dict, editable=False, blank=True),
|
||||
),
|
||||
],
|
||||
'0031_v302_migrate_survey_passwords': [
|
||||
|
@ -62,24 +62,6 @@ from awx.main.models.oauth import ( # noqa
|
||||
from oauth2_provider.models import Grant, RefreshToken # noqa -- needed django-oauth-toolkit model migrations
|
||||
|
||||
|
||||
|
||||
# Monkeypatch Django serializer to ignore django-taggit fields (which break
|
||||
# the dumpdata command; see https://github.com/alex/django-taggit/issues/155).
|
||||
from django.core.serializers.python import Serializer as _PythonSerializer
|
||||
_original_handle_m2m_field = _PythonSerializer.handle_m2m_field
|
||||
|
||||
|
||||
def _new_handle_m2m_field(self, obj, field):
|
||||
try:
|
||||
field.rel.through._meta
|
||||
except AttributeError:
|
||||
return
|
||||
return _original_handle_m2m_field(self, obj, field)
|
||||
|
||||
|
||||
_PythonSerializer.handle_m2m_field = _new_handle_m2m_field
|
||||
|
||||
|
||||
# Add custom methods to User model for permissions checks.
|
||||
from django.contrib.auth.models import User # noqa
|
||||
from awx.main.access import ( # noqa
|
||||
@ -158,7 +140,7 @@ User.add_to_class('is_system_auditor', user_is_system_auditor)
|
||||
|
||||
|
||||
def user_is_in_enterprise_category(user, category):
|
||||
ret = (category,) in user.enterprise_auth.all().values_list('provider') and not user.has_usable_password()
|
||||
ret = (category,) in user.enterprise_auth.values_list('provider') and not user.has_usable_password()
|
||||
# NOTE: this if-else block ensures existing enterprise users are still able to
|
||||
# log in. Remove it in a future release
|
||||
if category == 'radius':
|
||||
|
@ -105,7 +105,7 @@ class Credential(PasswordFieldsModel, CommonModelNameNotUnique, ResourceMixin):
|
||||
)
|
||||
inputs = CredentialInputField(
|
||||
blank=True,
|
||||
default={},
|
||||
default=dict,
|
||||
help_text=_('Enter inputs using either JSON or YAML syntax. Use the '
|
||||
'radio button to toggle between the two. Refer to the '
|
||||
'Ansible Tower documentation for example syntax.')
|
||||
@ -343,14 +343,14 @@ class CredentialType(CommonModelNameNotUnique):
|
||||
)
|
||||
inputs = CredentialTypeInputField(
|
||||
blank=True,
|
||||
default={},
|
||||
default=dict,
|
||||
help_text=_('Enter inputs using either JSON or YAML syntax. Use the '
|
||||
'radio button to toggle between the two. Refer to the '
|
||||
'Ansible Tower documentation for example syntax.')
|
||||
)
|
||||
injectors = CredentialTypeInjectorField(
|
||||
blank=True,
|
||||
default={},
|
||||
default=dict,
|
||||
help_text=_('Enter injectors using either JSON or YAML syntax. Use the '
|
||||
'radio button to toggle between the two. Refer to the '
|
||||
'Ansible Tower documentation for example syntax.')
|
||||
@ -1117,7 +1117,7 @@ class CredentialInputSource(PrimordialModel):
|
||||
)
|
||||
metadata = DynamicCredentialInputField(
|
||||
blank=True,
|
||||
default={}
|
||||
default=dict
|
||||
)
|
||||
|
||||
def clean_target_credential(self):
|
||||
|
@ -149,7 +149,7 @@ class BasePlaybookEvent(CreatedModifiedModel):
|
||||
)
|
||||
event_data = JSONField(
|
||||
blank=True,
|
||||
default={},
|
||||
default=dict,
|
||||
)
|
||||
failed = models.BooleanField(
|
||||
default=False,
|
||||
@ -567,7 +567,7 @@ class BaseCommandEvent(CreatedModifiedModel):
|
||||
|
||||
event_data = JSONField(
|
||||
blank=True,
|
||||
default={},
|
||||
default=dict,
|
||||
)
|
||||
uuid = models.CharField(
|
||||
max_length=1024,
|
||||
|
@ -650,7 +650,7 @@ class Host(CommonModelNameNotUnique, RelatedJobsMixin):
|
||||
)
|
||||
ansible_facts = JSONBField(
|
||||
blank=True,
|
||||
default={},
|
||||
default=dict,
|
||||
help_text=_('Arbitrary JSON structure of most recent ansible_facts, per-host.'),
|
||||
)
|
||||
ansible_facts_modified = models.DateTimeField(
|
||||
|
@ -485,7 +485,7 @@ class Job(UnifiedJob, JobOptions, SurveyJobMixin, JobNotificationMixin, TaskMana
|
||||
)
|
||||
artifacts = JSONField(
|
||||
blank=True,
|
||||
default={},
|
||||
default=dict,
|
||||
editable=False,
|
||||
)
|
||||
scm_revision = models.CharField(
|
||||
@ -847,7 +847,7 @@ class LaunchTimeConfigBase(BaseModel):
|
||||
# This is a solution to the nullable CharField problem, specific to prompting
|
||||
char_prompts = JSONField(
|
||||
blank=True,
|
||||
default={}
|
||||
default=dict
|
||||
)
|
||||
|
||||
def prompts_dict(self, display=False):
|
||||
@ -927,11 +927,11 @@ class LaunchTimeConfig(LaunchTimeConfigBase):
|
||||
# Special case prompting fields, even more special than the other ones
|
||||
extra_data = JSONField(
|
||||
blank=True,
|
||||
default={}
|
||||
default=dict
|
||||
)
|
||||
survey_passwords = prevent_search(JSONField(
|
||||
blank=True,
|
||||
default={},
|
||||
default=dict,
|
||||
editable=False,
|
||||
))
|
||||
# Credentials needed for non-unified job / unified JT models
|
||||
|
@ -100,7 +100,7 @@ class SurveyJobTemplateMixin(models.Model):
|
||||
)
|
||||
survey_spec = prevent_search(JSONField(
|
||||
blank=True,
|
||||
default={},
|
||||
default=dict,
|
||||
))
|
||||
ask_variables_on_launch = AskForField(
|
||||
blank=True,
|
||||
@ -360,7 +360,7 @@ class SurveyJobMixin(models.Model):
|
||||
|
||||
survey_passwords = prevent_search(JSONField(
|
||||
blank=True,
|
||||
default={},
|
||||
default=dict,
|
||||
editable=False,
|
||||
))
|
||||
|
||||
|
@ -641,7 +641,7 @@ class UnifiedJob(PolymorphicModel, PasswordFieldsModel, CommonModelNameNotUnique
|
||||
)
|
||||
job_env = prevent_search(JSONField(
|
||||
blank=True,
|
||||
default={},
|
||||
default=dict,
|
||||
editable=False,
|
||||
))
|
||||
job_explanation = models.TextField(
|
||||
|
@ -180,7 +180,7 @@ class WorkflowJobNode(WorkflowNodeBase):
|
||||
)
|
||||
ancestor_artifacts = JSONField(
|
||||
blank=True,
|
||||
default={},
|
||||
default=dict,
|
||||
editable=False,
|
||||
)
|
||||
do_not_run = models.BooleanField(
|
||||
|
@ -101,7 +101,7 @@ def test_instance_group_is_isolated(instance_group, isolated_instance_group):
|
||||
assert not instance_group.is_isolated
|
||||
assert isolated_instance_group.is_isolated
|
||||
|
||||
isolated_instance_group.instances = []
|
||||
isolated_instance_group.instances.set([])
|
||||
|
||||
assert isolated_instance_group.is_isolated
|
||||
|
||||
|
@ -12,7 +12,6 @@ def run_command(name, *args, **options):
|
||||
command_runner = options.pop('command_runner', call_command)
|
||||
stdin_fileobj = options.pop('stdin_fileobj', None)
|
||||
options.setdefault('verbosity', 1)
|
||||
options.setdefault('interactive', False)
|
||||
original_stdin = sys.stdin
|
||||
original_stdout = sys.stdout
|
||||
original_stderr = sys.stderr
|
||||
|
@ -11,9 +11,9 @@ from django.urls import resolve
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.serializers.json import DjangoJSONEncoder
|
||||
from django.db.backends.sqlite3.base import SQLiteCursorWrapper
|
||||
from jsonbfield.fields import JSONField
|
||||
|
||||
# AWX
|
||||
from awx.main.fields import JSONBField
|
||||
from awx.main.models.projects import Project
|
||||
from awx.main.models.ha import Instance
|
||||
|
||||
@ -737,7 +737,7 @@ def get_db_prep_save(self, value, connection, **kwargs):
|
||||
|
||||
@pytest.fixture
|
||||
def monkeypatch_jsonbfield_get_db_prep_save(mocker):
|
||||
JSONField.get_db_prep_save = get_db_prep_save
|
||||
JSONBField.get_db_prep_save = get_db_prep_save
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
@ -457,4 +457,4 @@ def test_duplicate_name_within_template(job_template):
|
||||
with pytest.raises(IntegrityError) as ierror:
|
||||
s2.save()
|
||||
|
||||
assert str(ierror.value) == "columns unified_job_template_id, name are not unique"
|
||||
assert str(ierror.value) == "UNIQUE constraint failed: main_schedule.unified_job_template_id, main_schedule.name"
|
||||
|
@ -20,7 +20,6 @@ from django.test import TransactionTestCase
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestWorkflowDAGFunctional(TransactionTestCase):
|
||||
def workflow_job(self, states=['new', 'new', 'new', 'new', 'new']):
|
||||
"""
|
||||
|
@ -1,5 +1,3 @@
|
||||
import pytest
|
||||
|
||||
from django.test import TransactionTestCase
|
||||
|
||||
from awx.main.models import (
|
||||
@ -8,7 +6,6 @@ from awx.main.models import (
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestCapacityMapping(TransactionTestCase):
|
||||
|
||||
def sample_cluster(self):
|
||||
|
@ -42,7 +42,7 @@ def test_job_notification_data(inventory, machine_credential, project):
|
||||
survey_passwords={"SSN": encrypted_str},
|
||||
project=project,
|
||||
)
|
||||
job.credentials = [machine_credential]
|
||||
job.credentials.set([machine_credential])
|
||||
notification_data = job.notification_data(block=0)
|
||||
assert json.loads(notification_data['extra_vars'])['SSN'] == encrypted_str
|
||||
|
||||
|
@ -7,7 +7,6 @@ from awx.main.access import UserAccess, RoleAccess, TeamAccess
|
||||
from awx.main.models import User, Organization, Inventory
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestSysAuditorTransactional(TransactionTestCase):
|
||||
def rando(self):
|
||||
return User.objects.create(username='rando', password='rando', email='rando@com.com')
|
||||
|
@ -186,11 +186,8 @@ class TestResourceAccessList:
|
||||
|
||||
def mock_request(self):
|
||||
return mock.MagicMock(
|
||||
user=mock.MagicMock(
|
||||
is_anonymous=mock.MagicMock(return_value=False),
|
||||
is_superuser=False
|
||||
), method='GET')
|
||||
|
||||
user=mock.MagicMock(is_anonymous=False, is_superuser=False),
|
||||
method='GET')
|
||||
|
||||
def mock_view(self, parent=None):
|
||||
view = ResourceAccessList()
|
||||
@ -200,7 +197,6 @@ class TestResourceAccessList:
|
||||
view.get_parent_object = lambda: parent
|
||||
return view
|
||||
|
||||
|
||||
def test_parent_access_check_failed(self, mocker, mock_organization):
|
||||
mock_access = mocker.MagicMock(__name__='for logger', return_value=False)
|
||||
with mocker.patch('awx.main.access.BaseAccess.can_read', mock_access):
|
||||
@ -208,7 +204,6 @@ class TestResourceAccessList:
|
||||
self.mock_view(parent=mock_organization).check_permissions(self.mock_request())
|
||||
mock_access.assert_called_once_with(mock_organization)
|
||||
|
||||
|
||||
def test_parent_access_check_worked(self, mocker, mock_organization):
|
||||
mock_access = mocker.MagicMock(__name__='for logger', return_value=True)
|
||||
with mocker.patch('awx.main.access.BaseAccess.can_read', mock_access):
|
||||
|
@ -6,7 +6,7 @@ from unittest.mock import PropertyMock
|
||||
from awx.api.urls import urlpatterns as api_patterns
|
||||
|
||||
# Django
|
||||
from django.urls import RegexURLResolver, RegexURLPattern
|
||||
from django.urls import URLResolver, URLPattern
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
@ -20,24 +20,24 @@ def all_views():
|
||||
'''
|
||||
returns a set of all views in the app
|
||||
'''
|
||||
patterns = set([])
|
||||
url_views = set([])
|
||||
patterns = set()
|
||||
url_views = set()
|
||||
# Add recursive URL patterns
|
||||
unprocessed = set(api_patterns)
|
||||
while unprocessed:
|
||||
to_process = unprocessed.copy()
|
||||
unprocessed = set([])
|
||||
unprocessed = set()
|
||||
for pattern in to_process:
|
||||
if hasattr(pattern, 'lookup_str') and not pattern.lookup_str.startswith('awx.api'):
|
||||
continue
|
||||
patterns.add(pattern)
|
||||
if isinstance(pattern, RegexURLResolver):
|
||||
if isinstance(pattern, URLResolver):
|
||||
for sub_pattern in pattern.url_patterns:
|
||||
if sub_pattern not in patterns:
|
||||
unprocessed.add(sub_pattern)
|
||||
# Get view classes
|
||||
for pattern in patterns:
|
||||
if isinstance(pattern, RegexURLPattern) and hasattr(pattern.callback, 'view_class'):
|
||||
if isinstance(pattern, URLPattern) and hasattr(pattern.callback, 'view_class'):
|
||||
url_views.add(pattern.callback.view_class)
|
||||
return url_views
|
||||
|
||||
|
@ -57,5 +57,5 @@ def test_really_long_event_fields(field):
|
||||
})
|
||||
manager.create.assert_called_with(**{
|
||||
'job_id': 123,
|
||||
'event_data': {field: 'X' * 1021 + '...'}
|
||||
'event_data': {field: 'X' * 1023 + '…'}
|
||||
})
|
||||
|
@ -208,7 +208,7 @@ def _check_unique_together_fields(model, ut):
|
||||
field = model._meta.get_field(field_name)
|
||||
if field_name == 'name':
|
||||
has_name = True
|
||||
elif type(field) == models.ForeignKey and field.rel.to != model:
|
||||
elif type(field) == models.ForeignKey and field.related_model != model:
|
||||
fk_names.append(field_name)
|
||||
elif issubclass(type(field), models.CharField) and field.choices:
|
||||
fields.append(field_name)
|
||||
@ -256,7 +256,7 @@ def _dfs(configuration, model, graph, dead_ends, new_deadends, parents):
|
||||
fields, fk_names = configuration[model][0][:], configuration[model][1][:]
|
||||
adj_list = []
|
||||
for fk_name in fk_names:
|
||||
next_model = model._meta.get_field(fk_name).rel.to
|
||||
next_model = model._meta.get_field(fk_name).related_model
|
||||
if issubclass(next_model, ContentType):
|
||||
continue
|
||||
if next_model not in configuration or\
|
||||
|
@ -60,7 +60,7 @@ def handle_error(request, status=404, **kwargs):
|
||||
return render(request, 'error.html', kwargs, status=status)
|
||||
|
||||
|
||||
def handle_400(request):
|
||||
def handle_400(request, exception):
|
||||
kwargs = {
|
||||
'name': _('Bad Request'),
|
||||
'content': _('The request could not be understood by the server.'),
|
||||
@ -68,7 +68,7 @@ def handle_400(request):
|
||||
return handle_error(request, 400, **kwargs)
|
||||
|
||||
|
||||
def handle_403(request):
|
||||
def handle_403(request, exception):
|
||||
kwargs = {
|
||||
'name': _('Forbidden'),
|
||||
'content': _('You don\'t have permission to access the requested resource.'),
|
||||
@ -76,7 +76,7 @@ def handle_403(request):
|
||||
return handle_error(request, 403, **kwargs)
|
||||
|
||||
|
||||
def handle_404(request):
|
||||
def handle_404(request, exception):
|
||||
kwargs = {
|
||||
'name': _('Not Found'),
|
||||
'content': _('The requested resource could not be found.'),
|
||||
|
@ -13,6 +13,7 @@ from django.dispatch import receiver
|
||||
from django.contrib.auth.models import User
|
||||
from django.conf import settings as django_settings
|
||||
from django.core.signals import setting_changed
|
||||
from django.utils.encoding import force_text
|
||||
|
||||
# django-auth-ldap
|
||||
from django_auth_ldap.backend import LDAPSettings as BaseLDAPSettings
|
||||
@ -98,7 +99,7 @@ class LDAPBackend(BaseLDAPBackend):
|
||||
|
||||
settings = property(_get_settings, _set_settings)
|
||||
|
||||
def authenticate(self, username, password):
|
||||
def authenticate(self, request, username, password):
|
||||
if self.settings.START_TLS and ldap.OPT_X_TLS_REQUIRE_CERT in self.settings.CONNECTION_OPTIONS:
|
||||
# with python-ldap, if you want to set connection-specific TLS
|
||||
# parameters, you must also specify OPT_X_TLS_NEWCTX = 0
|
||||
@ -124,7 +125,7 @@ class LDAPBackend(BaseLDAPBackend):
|
||||
raise ImproperlyConfigured(
|
||||
"{} must be an {} instance.".format(setting_name, type_)
|
||||
)
|
||||
return super(LDAPBackend, self).authenticate(None, username, password)
|
||||
return super(LDAPBackend, self).authenticate(request, username, password)
|
||||
except Exception:
|
||||
logger.exception("Encountered an error authenticating to LDAP")
|
||||
return None
|
||||
@ -179,7 +180,7 @@ def _decorate_enterprise_user(user, provider):
|
||||
def _get_or_set_enterprise_user(username, password, provider):
|
||||
created = False
|
||||
try:
|
||||
user = User.objects.all().prefetch_related('enterprise_auth').get(username=username)
|
||||
user = User.objects.prefetch_related('enterprise_auth').get(username=username)
|
||||
except User.DoesNotExist:
|
||||
user = User(username=username)
|
||||
enterprise_auth = _decorate_enterprise_user(user, provider)
|
||||
@ -196,10 +197,10 @@ class RADIUSBackend(BaseRADIUSBackend):
|
||||
Custom Radius backend to verify license status
|
||||
'''
|
||||
|
||||
def authenticate(self, username, password):
|
||||
def authenticate(self, request, username, password):
|
||||
if not django_settings.RADIUS_SERVER:
|
||||
return None
|
||||
return super(RADIUSBackend, self).authenticate(None, username, password)
|
||||
return super(RADIUSBackend, self).authenticate(request, username, password)
|
||||
|
||||
def get_user(self, user_id):
|
||||
if not django_settings.RADIUS_SERVER:
|
||||
@ -209,7 +210,7 @@ class RADIUSBackend(BaseRADIUSBackend):
|
||||
return user
|
||||
|
||||
def get_django_user(self, username, password=None):
|
||||
return _get_or_set_enterprise_user(username, password, 'radius')
|
||||
return _get_or_set_enterprise_user(force_text(username), force_text(password), 'radius')
|
||||
|
||||
|
||||
class TACACSPlusBackend(object):
|
||||
@ -217,7 +218,7 @@ class TACACSPlusBackend(object):
|
||||
Custom TACACS+ auth backend for AWX
|
||||
'''
|
||||
|
||||
def authenticate(self, username, password):
|
||||
def authenticate(self, request, username, password):
|
||||
if not django_settings.TACACSPLUS_HOST:
|
||||
return None
|
||||
try:
|
||||
@ -284,13 +285,13 @@ class SAMLAuth(BaseSAMLAuth):
|
||||
idp_config = self.setting('ENABLED_IDPS')[idp_name]
|
||||
return TowerSAMLIdentityProvider(idp_name, **idp_config)
|
||||
|
||||
def authenticate(self, *args, **kwargs):
|
||||
def authenticate(self, request, *args, **kwargs):
|
||||
if not all([django_settings.SOCIAL_AUTH_SAML_SP_ENTITY_ID, django_settings.SOCIAL_AUTH_SAML_SP_PUBLIC_CERT,
|
||||
django_settings.SOCIAL_AUTH_SAML_SP_PRIVATE_KEY, django_settings.SOCIAL_AUTH_SAML_ORG_INFO,
|
||||
django_settings.SOCIAL_AUTH_SAML_TECHNICAL_CONTACT, django_settings.SOCIAL_AUTH_SAML_SUPPORT_CONTACT,
|
||||
django_settings.SOCIAL_AUTH_SAML_ENABLED_IDPS]):
|
||||
return None
|
||||
user = super(SAMLAuth, self).authenticate(*args, **kwargs)
|
||||
user = super(SAMLAuth, self).authenticate(request, *args, **kwargs)
|
||||
# Comes from https://github.com/omab/python-social-auth/blob/v0.2.21/social/backends/base.py#L91
|
||||
if getattr(user, 'is_new', False):
|
||||
_decorate_enterprise_user(user, 'saml')
|
||||
@ -307,7 +308,7 @@ class SAMLAuth(BaseSAMLAuth):
|
||||
return super(SAMLAuth, self).get_user(user_id)
|
||||
|
||||
|
||||
def _update_m2m_from_groups(user, ldap_user, rel, opts, remove=True):
|
||||
def _update_m2m_from_groups(user, ldap_user, related, opts, remove=True):
|
||||
'''
|
||||
Hepler function to update m2m relationship based on LDAP group membership.
|
||||
'''
|
||||
@ -328,10 +329,10 @@ def _update_m2m_from_groups(user, ldap_user, rel, opts, remove=True):
|
||||
should_add = True
|
||||
if should_add:
|
||||
user.save()
|
||||
rel.add(user)
|
||||
elif remove and user in rel.all():
|
||||
related.add(user)
|
||||
elif remove and user in related.all():
|
||||
user.save()
|
||||
rel.remove(user)
|
||||
related.remove(user)
|
||||
|
||||
|
||||
@receiver(populate_user, dispatch_uid='populate-ldap-user')
|
||||
|
@ -39,7 +39,7 @@ class SocialAuthMiddleware(SocialAuthExceptionMiddleware):
|
||||
request.successful_authenticator = None
|
||||
|
||||
if not request.path.startswith('/sso/') and 'migrations_notran' not in request.path:
|
||||
if request.user and request.user.is_authenticated():
|
||||
if request.user and request.user.is_authenticated:
|
||||
# The rest of the code base rely hevily on type/inheritance checks,
|
||||
# LazyObject sent from Django auth middleware can be buggy if not
|
||||
# converted back to its original object.
|
||||
|
@ -17,7 +17,7 @@ class Migration(migrations.Migration):
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('provider', models.CharField(max_length=32, choices=[(b'radius', 'RADIUS'), (b'tacacs+', 'TACACS+')])),
|
||||
('user', models.ForeignKey(related_name='enterprise_auth', to=settings.AUTH_USER_MODEL)),
|
||||
('user', models.ForeignKey(related_name='enterprise_auth', on_delete=models.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
|
@ -50,7 +50,7 @@ def prevent_inactive_login(backend, details, user=None, *args, **kwargs):
|
||||
raise AuthInactive(backend)
|
||||
|
||||
|
||||
def _update_m2m_from_expression(user, rel, expr, remove=True):
|
||||
def _update_m2m_from_expression(user, related, expr, remove=True):
|
||||
'''
|
||||
Helper function to update m2m relationship based on user matching one or
|
||||
more expressions.
|
||||
@ -73,12 +73,12 @@ def _update_m2m_from_expression(user, rel, expr, remove=True):
|
||||
if ex.match(user.username) or ex.match(user.email):
|
||||
should_add = True
|
||||
if should_add:
|
||||
rel.add(user)
|
||||
related.add(user)
|
||||
elif remove:
|
||||
rel.remove(user)
|
||||
related.remove(user)
|
||||
|
||||
|
||||
def _update_org_from_attr(user, rel, attr, remove, remove_admins):
|
||||
def _update_org_from_attr(user, related, attr, remove, remove_admins):
|
||||
from awx.main.models import Organization
|
||||
|
||||
org_ids = []
|
||||
@ -87,7 +87,7 @@ def _update_org_from_attr(user, rel, attr, remove, remove_admins):
|
||||
org = Organization.objects.get_or_create(name=org_name)[0]
|
||||
|
||||
org_ids.append(org.id)
|
||||
getattr(org, rel).members.add(user)
|
||||
getattr(org, related).members.add(user)
|
||||
|
||||
if remove:
|
||||
[o.member_role.members.remove(user) for o in
|
||||
|
@ -27,6 +27,7 @@ def existing_tacacsplus_user():
|
||||
user = User.objects.get(username="foo")
|
||||
except User.DoesNotExist:
|
||||
user = User(username="foo")
|
||||
user.set_unusable_password()
|
||||
user.save()
|
||||
enterprise_auth = UserEnterpriseAuth(user=user, provider='tacacs+')
|
||||
enterprise_auth.save()
|
||||
|
@ -8,8 +8,11 @@ from awx.sso.backends import _get_or_set_enterprise_user
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_fetch_user_if_exist(existing_tacacsplus_user):
|
||||
new_user = _get_or_set_enterprise_user("foo", "password", "tacacs+")
|
||||
assert new_user == existing_tacacsplus_user
|
||||
with mock.patch('awx.sso.backends.logger') as mocked_logger:
|
||||
new_user = _get_or_set_enterprise_user("foo", "password", "tacacs+")
|
||||
mocked_logger.debug.assert_not_called()
|
||||
mocked_logger.warn.assert_not_called()
|
||||
assert new_user == existing_tacacsplus_user
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
|
@ -4,7 +4,7 @@ from unittest import mock
|
||||
def test_empty_host_fails_auth(tacacsplus_backend):
|
||||
with mock.patch('awx.sso.backends.django_settings') as settings:
|
||||
settings.TACACSPLUS_HOST = ''
|
||||
ret_user = tacacsplus_backend.authenticate(u"user", u"pass")
|
||||
ret_user = tacacsplus_backend.authenticate(None, u"user", u"pass")
|
||||
assert ret_user is None
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ def test_client_raises_exception(tacacsplus_backend):
|
||||
mock.patch('tacacs_plus.TACACSClient', return_value=client):
|
||||
settings.TACACSPLUS_HOST = 'localhost'
|
||||
settings.TACACSPLUS_AUTH_PROTOCOL = 'ascii'
|
||||
ret_user = tacacsplus_backend.authenticate(u"user", u"pass")
|
||||
ret_user = tacacsplus_backend.authenticate(None, u"user", u"pass")
|
||||
assert ret_user is None
|
||||
logger.exception.assert_called_once_with(
|
||||
"TACACS+ Authentication Error: foo"
|
||||
@ -32,7 +32,7 @@ def test_client_return_invalid_fails_auth(tacacsplus_backend):
|
||||
mock.patch('tacacs_plus.TACACSClient', return_value=client):
|
||||
settings.TACACSPLUS_HOST = 'localhost'
|
||||
settings.TACACSPLUS_AUTH_PROTOCOL = 'ascii'
|
||||
ret_user = tacacsplus_backend.authenticate(u"user", u"pass")
|
||||
ret_user = tacacsplus_backend.authenticate(None, u"user", u"pass")
|
||||
assert ret_user is None
|
||||
|
||||
|
||||
@ -48,5 +48,5 @@ def test_client_return_valid_passes_auth(tacacsplus_backend):
|
||||
mock.patch('awx.sso.backends._get_or_set_enterprise_user', return_value=user):
|
||||
settings.TACACSPLUS_HOST = 'localhost'
|
||||
settings.TACACSPLUS_AUTH_PROTOCOL = 'ascii'
|
||||
ret_user = tacacsplus_backend.authenticate(u"user", u"pass")
|
||||
ret_user = tacacsplus_backend.authenticate(None, u"user", u"pass")
|
||||
assert ret_user == user
|
||||
|
@ -40,7 +40,7 @@ class CompleteView(BaseRedirectView):
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
response = super(CompleteView, self).dispatch(request, *args, **kwargs)
|
||||
if self.request.user and self.request.user.is_authenticated():
|
||||
if self.request.user and self.request.user.is_authenticated:
|
||||
logger.info(smart_text(u"User {} logged in".format(self.request.user.username)))
|
||||
response.set_cookie('userLoggedIn', 'true')
|
||||
current_user = UserSerializer(self.request.user)
|
||||
|
@ -1,5 +1,5 @@
|
||||
{% extends "rest_framework/api.html" %}
|
||||
{% load i18n staticfiles %}
|
||||
{% load i18n static %}
|
||||
|
||||
{% block title %}{{ name }} · {% trans 'AWX' %}{% endblock %}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{# Partial copy of login_base.html from rest_framework with AWX change. #}
|
||||
{% extends 'rest_framework/api.html' %}
|
||||
{% load i18n staticfiles %}
|
||||
{% load i18n static %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
{% endblock %}
|
||||
|
@ -40,12 +40,5 @@ if social_django.__version__ != '2.1.0':
|
||||
still works".format(social_django.__version__))
|
||||
|
||||
|
||||
if not django.__version__.startswith('1.'):
|
||||
raise RuntimeError("Django version other than 1.XX detected {}. \
|
||||
Inherit from WSGIHandler to support short-circuit Django Middleware. \
|
||||
This is known to work for Django 1.XX and may not work with other, \
|
||||
even minor, versions.".format(django.__version__))
|
||||
|
||||
|
||||
# Return the default Django WSGI application.
|
||||
application = get_wsgi_application()
|
||||
|
@ -1,28 +0,0 @@
|
||||
|
||||
Copyright (c) Django Software Foundation and individual contributors.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of Django nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
25
docs/licenses/sqlparse.txt
Normal file
25
docs/licenses/sqlparse.txt
Normal file
@ -0,0 +1,25 @@
|
||||
Copyright (c) 2016, Andi Albrecht <albrecht.andi@gmail.com>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of the authors nor the names of its contributors may be
|
||||
used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
@ -7,12 +7,12 @@ channels==1.1.8
|
||||
celery==4.3.0
|
||||
daphne==1.3.0 # Last before backwards-incompatible channels 2 upgrade
|
||||
twisted[tls]>=17.1 # from daphne, see https://github.com/django/daphne/pull/257
|
||||
Django==1.11.20
|
||||
Django==2.2.2
|
||||
django-auth-ldap==1.7.0
|
||||
django-cors-headers==2.4.0
|
||||
django-crum==0.7.2
|
||||
django-extensions==2.0.0
|
||||
django-jsonfield==1.0.1
|
||||
django-jsonfield==1.2.0
|
||||
django-oauth-toolkit==1.1.3
|
||||
django-polymorphic==2.0.2
|
||||
django-pglocks==1.0.2
|
||||
|
@ -27,7 +27,7 @@ django-auth-ldap==1.7.0
|
||||
django-cors-headers==2.4.0
|
||||
django-crum==0.7.2
|
||||
django-extensions==2.0.0
|
||||
django-jsonfield==1.0.1
|
||||
django-jsonfield==1.2.0
|
||||
django-oauth-toolkit==1.1.3
|
||||
django-pglocks==1.0.2
|
||||
django-polymorphic==2.0.2
|
||||
@ -35,7 +35,7 @@ django-radius==1.3.3
|
||||
django-solo==1.1.3
|
||||
django-split-settings==0.3.0
|
||||
django-taggit==0.22.2
|
||||
django==1.11.20
|
||||
django==2.2.2
|
||||
djangorestframework-yaml==1.0.3
|
||||
djangorestframework==3.9.4
|
||||
|
||||
@ -102,6 +102,7 @@ six==1.12.0 # via ansible-runner, asgi-amqp, asgiref, autobahn, au
|
||||
slackclient==1.1.2
|
||||
social-auth-app-django==2.1.0
|
||||
social-auth-core==3.0.0
|
||||
sqlparse==0.3.0 # via django
|
||||
tacacs_plus==1.0
|
||||
tempora==1.14.1 # via irc, jaraco.logging
|
||||
twilio==6.10.4
|
||||
|
@ -1,3 +1,2 @@
|
||||
git+https://github.com/ansible/ansiconv.git@tower_1.0.0#egg=ansiconv
|
||||
git+https://github.com/ansible/django-qsstats-magic.git@py3#egg=django-qsstats-magic
|
||||
git+https://github.com/ansible/django-jsonbfield@fix-sqlite_serialization#egg=jsonbfield
|
||||
|
@ -1,11 +1,9 @@
|
||||
FROM centos:7
|
||||
FROM fedora:27
|
||||
|
||||
ARG UID=0
|
||||
|
||||
RUN yum -y update && yum -y install epel-release
|
||||
|
||||
# sync with installer/roles/image_build/templates/Dockerfile.j2
|
||||
RUN yum -y install acl \
|
||||
RUN dnf -y install acl \
|
||||
alsa-lib \
|
||||
ansible \
|
||||
atk \
|
||||
@ -14,12 +12,15 @@ RUN yum -y install acl \
|
||||
curl \
|
||||
cyrus-sasl \
|
||||
cyrus-sasl-devel \
|
||||
findutils \
|
||||
gcc \
|
||||
gcc-c++ \
|
||||
GConf2 \
|
||||
git \
|
||||
glibc-locale-source \
|
||||
gtk3 \
|
||||
ipa-gothic-fonts \
|
||||
iproute \
|
||||
krb5-devel \
|
||||
krb5-libs \
|
||||
krb5-workstation \
|
||||
@ -45,16 +46,16 @@ RUN yum -y install acl \
|
||||
nodejs \
|
||||
openldap-devel \
|
||||
openssh-server \
|
||||
postgresql-contrib \
|
||||
postgresql-devel \
|
||||
python-devel \
|
||||
python-pip \
|
||||
python-psutil \
|
||||
python-psycopg2 \
|
||||
python-setuptools \
|
||||
python36-devel \
|
||||
python36-setuptools \
|
||||
python3-devel \
|
||||
python3-setuptools \
|
||||
rsync \
|
||||
setools-libs \
|
||||
subversion \
|
||||
sudo \
|
||||
swig \
|
||||
|
Loading…
Reference in New Issue
Block a user