mirror of
https://github.com/ansible/awx.git
synced 2026-05-24 00:57:48 -02:30
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:
@@ -25,9 +25,8 @@ import hashlib
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
import django
|
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.base import schema
|
||||||
|
from django.db.backends.utils import names_digest
|
||||||
HAS_DJANGO = True
|
HAS_DJANGO = True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
HAS_DJANGO = False
|
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
|
# 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,
|
# upgrade Django; if you're upgrading Django and see this error,
|
||||||
# update the version check below, and confirm that FIPS still works.
|
# update the version check below, and confirm that FIPS still works.
|
||||||
if django.__version__ != '1.11.20':
|
# If operating in a FIPS environment, `hashlib.md5()` will raise a `ValueError`,
|
||||||
raise RuntimeError("Django version other than 1.11.20 detected {}. \
|
# but will support the `usedforsecurity` keyword on RHEL and Centos systems.
|
||||||
Subclassing BaseDatabaseSchemaEditor is known to work for Django 1.11.20 \
|
|
||||||
and may not work in newer Django versions.".format(django.__version__))
|
|
||||||
|
|
||||||
|
# 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):
|
|
||||||
"""
|
|
||||||
Generates a 32-bit digest of a set of arguments that can be used to
|
|
||||||
shorten identifying names.
|
|
||||||
"""
|
|
||||||
try:
|
try:
|
||||||
h = hashlib.md5()
|
names_digest('foo', 'bar', 'baz', length=8)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
def names_digest(*args, length):
|
||||||
|
"""
|
||||||
|
Generate a 32-bit digest of a set of arguments that can be used to shorten
|
||||||
|
identifying names. Support for use in FIPS environments.
|
||||||
|
"""
|
||||||
h = hashlib.md5(usedforsecurity=False)
|
h = hashlib.md5(usedforsecurity=False)
|
||||||
for arg in args:
|
for arg in args:
|
||||||
h.update(force_bytes(arg))
|
h.update(arg.encode())
|
||||||
return h.hexdigest()[:8]
|
return h.hexdigest()[:length]
|
||||||
|
|
||||||
|
schema.names_digest = names_digest
|
||||||
schema.BaseDatabaseSchemaEditor = FipsBaseDatabaseSchemaEditor
|
|
||||||
|
|
||||||
|
|
||||||
def find_commands(management_dir):
|
def find_commands(management_dir):
|
||||||
|
|||||||
@@ -401,21 +401,21 @@ class ListAPIView(generics.ListAPIView, GenericAPIView):
|
|||||||
continue
|
continue
|
||||||
if getattr(field, 'related_model', None):
|
if getattr(field, 'related_model', None):
|
||||||
fields.add('{}__search'.format(field.name))
|
fields.add('{}__search'.format(field.name))
|
||||||
for rel in self.model._meta.related_objects:
|
for related in self.model._meta.related_objects:
|
||||||
name = rel.related_name
|
name = related.related_name
|
||||||
if isinstance(rel, OneToOneRel) and self.model._meta.verbose_name.startswith('unified'):
|
if isinstance(related, OneToOneRel) and self.model._meta.verbose_name.startswith('unified'):
|
||||||
# Add underscores for polymorphic subclasses for user utility
|
# 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('+'):
|
if skip_related_name(name) or name.endswith('+'):
|
||||||
continue
|
continue
|
||||||
fields.add('{}__search'.format(name))
|
fields.add('{}__search'.format(name))
|
||||||
m2m_rel = []
|
m2m_related = []
|
||||||
m2m_rel += self.model._meta.local_many_to_many
|
m2m_related += self.model._meta.local_many_to_many
|
||||||
if issubclass(self.model, UnifiedJobTemplate) and self.model != UnifiedJobTemplate:
|
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:
|
if issubclass(self.model, UnifiedJob) and self.model != UnifiedJob:
|
||||||
m2m_rel += UnifiedJob._meta.local_many_to_many
|
m2m_related += UnifiedJob._meta.local_many_to_many
|
||||||
for relationship in m2m_rel:
|
for relationship in m2m_related:
|
||||||
if skip_related_name(relationship.name):
|
if skip_related_name(relationship.name):
|
||||||
continue
|
continue
|
||||||
if relationship.related_model._meta.app_label != 'main':
|
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.
|
# 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
|
return False
|
||||||
|
|
||||||
# Always allow superusers
|
# Always allow superusers
|
||||||
|
|||||||
@@ -2560,7 +2560,7 @@ class CredentialSerializer(BaseSerializer):
|
|||||||
|
|
||||||
def validate_credential_type(self, credential_type):
|
def validate_credential_type(self, credential_type):
|
||||||
if self.instance and credential_type.pk != self.instance.credential_type.pk:
|
if self.instance and credential_type.pk != self.instance.credential_type.pk:
|
||||||
for rel in (
|
for related_objects in (
|
||||||
'ad_hoc_commands',
|
'ad_hoc_commands',
|
||||||
'insights_inventories',
|
'insights_inventories',
|
||||||
'unifiedjobs',
|
'unifiedjobs',
|
||||||
@@ -2569,7 +2569,7 @@ class CredentialSerializer(BaseSerializer):
|
|||||||
'projectupdates',
|
'projectupdates',
|
||||||
'workflowjobnodes'
|
'workflowjobnodes'
|
||||||
):
|
):
|
||||||
if getattr(self.instance, rel).count() > 0:
|
if getattr(self.instance, related_objects).count() > 0:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
_('You cannot change the credential type of the credential, as it may break the functionality'
|
_('You cannot change the credential type of the credential, as it may break the functionality'
|
||||||
' of the resources using it.'),
|
' of the resources using it.'),
|
||||||
@@ -4640,37 +4640,37 @@ class ActivityStreamSerializer(BaseSerializer):
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
def get_related(self, obj):
|
def get_related(self, obj):
|
||||||
rel = {}
|
data = {}
|
||||||
if obj.actor is not None:
|
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:
|
for fk, __ in self._local_summarizable_fk_fields:
|
||||||
if not hasattr(obj, fk):
|
if not hasattr(obj, fk):
|
||||||
continue
|
continue
|
||||||
m2m_list = self._get_rel(obj, fk)
|
m2m_list = self._get_related_objects(obj, fk)
|
||||||
if m2m_list:
|
if m2m_list:
|
||||||
rel[fk] = []
|
data[fk] = []
|
||||||
id_list = []
|
id_list = []
|
||||||
for thisItem in m2m_list:
|
for item in m2m_list:
|
||||||
if getattr(thisItem, 'id', None) in id_list:
|
if getattr(item, 'id', None) in id_list:
|
||||||
continue
|
continue
|
||||||
id_list.append(getattr(thisItem, 'id', None))
|
id_list.append(getattr(item, 'id', None))
|
||||||
if hasattr(thisItem, 'get_absolute_url'):
|
if hasattr(item, 'get_absolute_url'):
|
||||||
rel_url = thisItem.get_absolute_url(self.context.get('request'))
|
url = item.get_absolute_url(self.context.get('request'))
|
||||||
else:
|
else:
|
||||||
view_name = fk + '_detail'
|
view_name = fk + '_detail'
|
||||||
rel_url = self.reverse('api:' + view_name, kwargs={'pk': thisItem.id})
|
url = self.reverse('api:' + view_name, kwargs={'pk': item.id})
|
||||||
rel[fk].append(rel_url)
|
data[fk].append(url)
|
||||||
|
|
||||||
if fk == 'schedule':
|
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):
|
if obj.setting and obj.setting.get('category', None):
|
||||||
rel['setting'] = self.reverse(
|
data['setting'] = self.reverse(
|
||||||
'api:setting_singleton_detail',
|
'api:setting_singleton_detail',
|
||||||
kwargs={'category_slug': obj.setting['category']}
|
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_model = ActivityStream._meta.get_field(fk).related_model
|
||||||
related_manager = getattr(obj, fk)
|
related_manager = getattr(obj, fk)
|
||||||
if issubclass(related_model, PolymorphicModel) and hasattr(obj, '_prefetched_objects_cache'):
|
if issubclass(related_model, PolymorphicModel) and hasattr(obj, '_prefetched_objects_cache'):
|
||||||
@@ -4703,7 +4703,7 @@ class ActivityStreamSerializer(BaseSerializer):
|
|||||||
try:
|
try:
|
||||||
if not hasattr(obj, fk):
|
if not hasattr(obj, fk):
|
||||||
continue
|
continue
|
||||||
m2m_list = self._get_rel(obj, fk)
|
m2m_list = self._get_related_objects(obj, fk)
|
||||||
if m2m_list:
|
if m2m_list:
|
||||||
summary_fields[fk] = []
|
summary_fields[fk] = []
|
||||||
for thisItem in m2m_list:
|
for thisItem in m2m_list:
|
||||||
|
|||||||
@@ -2997,7 +2997,7 @@ class WorkflowJobTemplateNodeChildrenBaseList(EnforceParentRelationshipMixin, Su
|
|||||||
relationships = ['success_nodes', 'failure_nodes', 'always_nodes']
|
relationships = ['success_nodes', 'failure_nodes', 'always_nodes']
|
||||||
relationships.remove(self.relationship)
|
relationships.remove(self.relationship)
|
||||||
qs = functools.reduce(lambda x, y: (x | y),
|
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():
|
if models.WorkflowJobTemplateNode.objects.filter(Q(pk=parent.id) & qs).exists():
|
||||||
return {"Error": _("Relationship not allowed.")}
|
return {"Error": _("Relationship not allowed.")}
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ class Migration(migrations.Migration):
|
|||||||
('modified', models.DateTimeField(default=None, editable=False)),
|
('modified', models.DateTimeField(default=None, editable=False)),
|
||||||
('key', models.CharField(max_length=255)),
|
('key', models.CharField(max_length=255)),
|
||||||
('value', jsonfield.fields.JSONField(null=True)),
|
('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={
|
options={
|
||||||
'abstract': False,
|
'abstract': False,
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ def ws_connect(message):
|
|||||||
headers = dict(message.content.get('headers', ''))
|
headers = dict(message.content.get('headers', ''))
|
||||||
message.reply_channel.send({"accept": True})
|
message.reply_channel.send({"accept": True})
|
||||||
message.content['method'] = 'FAKE'
|
message.content['method'] = 'FAKE'
|
||||||
if message.user.is_authenticated():
|
if message.user.is_authenticated:
|
||||||
message.reply_channel.send(
|
message.reply_channel.send(
|
||||||
{"text": json.dumps({"accept": True, "user": message.user.id})}
|
{"text": json.dumps({"accept": True, "user": message.user.id})}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -11,8 +11,9 @@ from jinja2 import Environment, StrictUndefined
|
|||||||
from jinja2.exceptions import UndefinedError, TemplateSyntaxError
|
from jinja2.exceptions import UndefinedError, TemplateSyntaxError
|
||||||
|
|
||||||
# Django
|
# Django
|
||||||
import django
|
from django.contrib.postgres.fields import JSONField as upstream_JSONBField
|
||||||
from django.core import exceptions as django_exceptions
|
from django.core import exceptions as django_exceptions
|
||||||
|
from django.core.serializers.json import DjangoJSONEncoder
|
||||||
from django.db.models.signals import (
|
from django.db.models.signals import (
|
||||||
post_save,
|
post_save,
|
||||||
post_delete,
|
post_delete,
|
||||||
@@ -37,7 +38,6 @@ import jsonschema.exceptions
|
|||||||
|
|
||||||
# Django-JSONField
|
# Django-JSONField
|
||||||
from jsonfield import JSONField as upstream_JSONField
|
from jsonfield import JSONField as upstream_JSONField
|
||||||
from jsonbfield.fields import JSONField as upstream_JSONBField
|
|
||||||
|
|
||||||
# DRF
|
# DRF
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
@@ -76,10 +76,10 @@ class JSONField(upstream_JSONField):
|
|||||||
def db_type(self, connection):
|
def db_type(self, connection):
|
||||||
return 'text'
|
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:
|
if value in {'', None} and not self.null:
|
||||||
return {}
|
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):
|
class JSONBField(upstream_JSONBField):
|
||||||
@@ -91,12 +91,12 @@ class JSONBField(upstream_JSONBField):
|
|||||||
def get_db_prep_value(self, value, connection, prepared=False):
|
def get_db_prep_value(self, value, connection, prepared=False):
|
||||||
if connection.vendor == 'sqlite':
|
if connection.vendor == 'sqlite':
|
||||||
# sqlite (which we use for tests) does not support jsonb;
|
# 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(
|
return super(JSONBField, self).get_db_prep_value(
|
||||||
value, connection, prepared
|
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
|
# Work around a bug in django-jsonfield
|
||||||
# https://bitbucket.org/schinckel/django-jsonfield/issues/57/cannot-use-in-the-same-project-as-djangos
|
# https://bitbucket.org/schinckel/django-jsonfield/issues/57/cannot-use-in-the-same-project-as-djangos
|
||||||
if isinstance(value, str):
|
if isinstance(value, str):
|
||||||
@@ -112,14 +112,9 @@ class AutoSingleRelatedObjectDescriptor(ReverseOneToOneDescriptor):
|
|||||||
|
|
||||||
def __get__(self, instance, instance_type=None):
|
def __get__(self, instance, instance_type=None):
|
||||||
try:
|
try:
|
||||||
return super(AutoSingleRelatedObjectDescriptor,
|
return super(AutoSingleRelatedObjectDescriptor, self).__get__(instance, instance_type)
|
||||||
self).__get__(instance, instance_type)
|
|
||||||
except self.related.related_model.DoesNotExist:
|
except self.related.related_model.DoesNotExist:
|
||||||
obj = self.related.related_model(**{self.related.field.name: instance})
|
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()
|
obj.save()
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
@@ -453,21 +448,6 @@ class JSONSchemaField(JSONBField):
|
|||||||
params={'value': value},
|
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')
|
@JSONSchemaField.format_checker.checks('vault_id')
|
||||||
def format_vault_id(value):
|
def format_vault_id(value):
|
||||||
@@ -986,7 +966,7 @@ class OAuth2ClientSecretField(models.CharField):
|
|||||||
encrypt_value(value), connection, prepared
|
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$'):
|
if value and value.startswith('$encrypted$'):
|
||||||
return decrypt_value(get_encryption_key('value', pk=None), value)
|
return decrypt_value(get_encryption_key('value', pk=None), value)
|
||||||
return value
|
return value
|
||||||
@@ -1022,38 +1002,6 @@ class OrderedManyToManyDescriptor(ManyToManyDescriptor):
|
|||||||
'%s__position' % self.through._meta.model_name
|
'%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 OrderedManyRelatedManager
|
||||||
|
|
||||||
return add_custom_queryset_to_many_related_manager(
|
return add_custom_queryset_to_many_related_manager(
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ class ActivityStreamMiddleware(threading.local, MiddlewareMixin):
|
|||||||
super().__init__(get_response)
|
super().__init__(get_response)
|
||||||
|
|
||||||
def process_request(self, request):
|
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
|
user = request.user
|
||||||
else:
|
else:
|
||||||
user = None
|
user = None
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ class Migration(migrations.Migration):
|
|||||||
('modified', models.DateTimeField(default=None, editable=False)),
|
('modified', models.DateTimeField(default=None, editable=False)),
|
||||||
('host_name', models.CharField(default='', max_length=1024, 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', 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)),
|
('failed', models.BooleanField(default=False, editable=False)),
|
||||||
('changed', models.BooleanField(default=False, editable=False)),
|
('changed', models.BooleanField(default=False, editable=False)),
|
||||||
('counter', models.PositiveIntegerField(default=0)),
|
('counter', models.PositiveIntegerField(default=0)),
|
||||||
@@ -62,7 +62,7 @@ class Migration(migrations.Migration):
|
|||||||
('expires', models.DateTimeField(default=django.utils.timezone.now)),
|
('expires', models.DateTimeField(default=django.utils.timezone.now)),
|
||||||
('request_hash', models.CharField(default='', max_length=40, blank=True)),
|
('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)),
|
('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(
|
migrations.CreateModel(
|
||||||
@@ -198,7 +198,7 @@ class Migration(migrations.Migration):
|
|||||||
('created', models.DateTimeField(default=None, editable=False)),
|
('created', models.DateTimeField(default=None, editable=False)),
|
||||||
('modified', 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', 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)),
|
('failed', models.BooleanField(default=False, editable=False)),
|
||||||
('changed', models.BooleanField(default=False, editable=False)),
|
('changed', models.BooleanField(default=False, editable=False)),
|
||||||
('host_name', models.CharField(default='', max_length=1024, 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)),
|
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||||
('created', models.DateTimeField(auto_now_add=True)),
|
('created', models.DateTimeField(auto_now_add=True)),
|
||||||
('modified', models.DateTimeField(auto_now=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(
|
migrations.CreateModel(
|
||||||
@@ -287,7 +287,7 @@ class Migration(migrations.Migration):
|
|||||||
('created', models.DateTimeField(default=None, editable=False)),
|
('created', models.DateTimeField(default=None, editable=False)),
|
||||||
('modified', models.DateTimeField(default=None, editable=False)),
|
('modified', models.DateTimeField(default=None, editable=False)),
|
||||||
('ldap_dn', models.CharField(default='', max_length=1024)),
|
('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(
|
migrations.CreateModel(
|
||||||
@@ -304,7 +304,7 @@ class Migration(migrations.Migration):
|
|||||||
('dtend', models.DateTimeField(default=None, null=True, editable=False)),
|
('dtend', models.DateTimeField(default=None, null=True, editable=False)),
|
||||||
('rrule', models.CharField(max_length=255)),
|
('rrule', models.CharField(max_length=255)),
|
||||||
('next_run', models.DateTimeField(default=None, null=True, editable=False)),
|
('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)),
|
('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)),
|
('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')),
|
('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)),
|
('name', models.CharField(max_length=512)),
|
||||||
('old_pk', models.PositiveIntegerField(default=None, null=True, editable=False)),
|
('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')])),
|
('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')])),
|
('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)),
|
('failed', models.BooleanField(default=False, editable=False)),
|
||||||
('started', models.DateTimeField(default=None, null=True, 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)),
|
('elapsed', models.DecimalField(editable=False, max_digits=12, decimal_places=3)),
|
||||||
('job_args', models.TextField(default='', editable=False, blank=True)),
|
('job_args', models.TextField(default='', editable=False, blank=True)),
|
||||||
('job_cwd', models.CharField(default='', max_length=1024, 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)),
|
('job_explanation', models.TextField(default='', editable=False, blank=True)),
|
||||||
('start_args', 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)),
|
('result_stdout_text', models.TextField(default='', editable=False, blank=True)),
|
||||||
@@ -380,7 +380,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='AdHocCommand',
|
name='AdHocCommand',
|
||||||
fields=[
|
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')])),
|
('job_type', models.CharField(default='run', max_length=64, choices=[('run', 'Run'), ('check', 'Check')])),
|
||||||
('limit', models.CharField(default='', max_length=1024, blank=True)),
|
('limit', models.CharField(default='', max_length=1024, blank=True)),
|
||||||
('module_name', 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(
|
migrations.CreateModel(
|
||||||
name='InventorySource',
|
name='InventorySource',
|
||||||
fields=[
|
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', 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_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)),
|
('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(
|
migrations.CreateModel(
|
||||||
name='InventoryUpdate',
|
name='InventoryUpdate',
|
||||||
fields=[
|
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', 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_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)),
|
('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(
|
migrations.CreateModel(
|
||||||
name='Job',
|
name='Job',
|
||||||
fields=[
|
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')])),
|
('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)),
|
('playbook', models.CharField(default='', max_length=1024, blank=True)),
|
||||||
('forks', models.PositiveIntegerField(default=0, 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)')])),
|
('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)),
|
('extra_vars', models.TextField(default='', blank=True)),
|
||||||
('job_tags', models.CharField(default='', max_length=1024, 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)),
|
('skip_tags', models.CharField(default='', max_length=1024, blank=True)),
|
||||||
('start_at_task', 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)),
|
('become_enabled', models.BooleanField(default=False)),
|
||||||
@@ -448,7 +448,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='JobTemplate',
|
name='JobTemplate',
|
||||||
fields=[
|
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')])),
|
('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)),
|
('playbook', models.CharField(default='', max_length=1024, blank=True)),
|
||||||
('forks', models.PositiveIntegerField(default=0, 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)')])),
|
('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)),
|
('extra_vars', models.TextField(default='', blank=True)),
|
||||||
('job_tags', models.CharField(default='', max_length=1024, 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)),
|
('skip_tags', models.CharField(default='', max_length=1024, blank=True)),
|
||||||
('start_at_task', 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)),
|
('become_enabled', models.BooleanField(default=False)),
|
||||||
('host_config_key', models.CharField(default='', max_length=1024, blank=True)),
|
('host_config_key', models.CharField(default='', max_length=1024, blank=True)),
|
||||||
('ask_variables_on_launch', models.BooleanField(default=False)),
|
('ask_variables_on_launch', models.BooleanField(default=False)),
|
||||||
('survey_enabled', 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={
|
options={
|
||||||
'ordering': ('name',),
|
'ordering': ('name',),
|
||||||
@@ -473,7 +473,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='Project',
|
name='Project',
|
||||||
fields=[
|
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)),
|
('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_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)),
|
('scm_url', models.CharField(default='', max_length=1024, verbose_name='SCM URL', blank=True)),
|
||||||
@@ -492,7 +492,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='ProjectUpdate',
|
name='ProjectUpdate',
|
||||||
fields=[
|
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)),
|
('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_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)),
|
('scm_url', models.CharField(default='', max_length=1024, verbose_name='SCM URL', blank=True)),
|
||||||
@@ -505,7 +505,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='SystemJob',
|
name='SystemJob',
|
||||||
fields=[
|
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')])),
|
('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)),
|
('extra_vars', models.TextField(default='', blank=True)),
|
||||||
],
|
],
|
||||||
@@ -517,7 +517,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='SystemJobTemplate',
|
name='SystemJobTemplate',
|
||||||
fields=[
|
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')])),
|
('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),
|
bases=('main.unifiedjobtemplate', models.Model),
|
||||||
@@ -550,7 +550,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='unifiedjobtemplate',
|
model_name='unifiedjobtemplate',
|
||||||
name='polymorphic_ctype',
|
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(
|
migrations.AddField(
|
||||||
model_name='unifiedjobtemplate',
|
model_name='unifiedjobtemplate',
|
||||||
@@ -575,7 +575,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='unifiedjob',
|
model_name='unifiedjob',
|
||||||
name='polymorphic_ctype',
|
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(
|
migrations.AddField(
|
||||||
model_name='unifiedjob',
|
model_name='unifiedjob',
|
||||||
@@ -595,7 +595,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='schedule',
|
model_name='schedule',
|
||||||
name='unified_job_template',
|
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(
|
migrations.AddField(
|
||||||
model_name='permission',
|
model_name='permission',
|
||||||
@@ -610,12 +610,12 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='joborigin',
|
model_name='joborigin',
|
||||||
name='unified_job',
|
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(
|
migrations.AddField(
|
||||||
model_name='inventory',
|
model_name='inventory',
|
||||||
name='organization',
|
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(
|
migrations.AddField(
|
||||||
model_name='inventory',
|
model_name='inventory',
|
||||||
@@ -625,7 +625,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='host',
|
model_name='host',
|
||||||
name='inventory',
|
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(
|
migrations.AddField(
|
||||||
model_name='host',
|
model_name='host',
|
||||||
@@ -650,7 +650,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='group',
|
model_name='group',
|
||||||
name='inventory',
|
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(
|
migrations.AddField(
|
||||||
model_name='group',
|
model_name='group',
|
||||||
@@ -680,12 +680,12 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='credential',
|
model_name='credential',
|
||||||
name='team',
|
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(
|
migrations.AddField(
|
||||||
model_name='credential',
|
model_name='credential',
|
||||||
name='user',
|
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(
|
migrations.AddField(
|
||||||
model_name='adhoccommandevent',
|
model_name='adhoccommandevent',
|
||||||
@@ -774,7 +774,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='projectupdate',
|
model_name='projectupdate',
|
||||||
name='project',
|
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(
|
migrations.AddField(
|
||||||
model_name='project',
|
model_name='project',
|
||||||
@@ -814,12 +814,12 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='jobhostsummary',
|
model_name='jobhostsummary',
|
||||||
name='job',
|
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(
|
migrations.AddField(
|
||||||
model_name='jobevent',
|
model_name='jobevent',
|
||||||
name='job',
|
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(
|
migrations.AddField(
|
||||||
model_name='job',
|
model_name='job',
|
||||||
@@ -859,7 +859,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='inventoryupdate',
|
model_name='inventoryupdate',
|
||||||
name='inventory_source',
|
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(
|
migrations.AddField(
|
||||||
model_name='inventoryupdate',
|
model_name='inventoryupdate',
|
||||||
@@ -874,12 +874,12 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='inventorysource',
|
model_name='inventorysource',
|
||||||
name='group',
|
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(
|
migrations.AddField(
|
||||||
model_name='inventorysource',
|
model_name='inventorysource',
|
||||||
name='inventory',
|
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(
|
migrations.AddField(
|
||||||
model_name='inventorysource',
|
model_name='inventorysource',
|
||||||
@@ -916,7 +916,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='adhoccommandevent',
|
model_name='adhoccommandevent',
|
||||||
name='ad_hoc_command',
|
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(
|
migrations.AddField(
|
||||||
model_name='adhoccommand',
|
model_name='adhoccommand',
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ from django.conf import settings
|
|||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
|
|
||||||
import jsonfield.fields
|
import jsonfield.fields
|
||||||
import jsonbfield.fields
|
|
||||||
import taggit.managers
|
import taggit.managers
|
||||||
|
|
||||||
|
|
||||||
@@ -144,7 +143,7 @@ class Migration(migrations.Migration):
|
|||||||
('category', models.CharField(max_length=128)),
|
('category', models.CharField(max_length=128)),
|
||||||
('value', models.TextField(blank=True)),
|
('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')])),
|
('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
|
# Notification changes
|
||||||
@@ -185,7 +184,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='notification',
|
model_name='notification',
|
||||||
name='notification_template',
|
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(
|
migrations.AddField(
|
||||||
model_name='activitystream',
|
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)),
|
('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)),
|
('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)),
|
('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)),
|
('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', help_text='Host for the facts that the fact scan captured.')),
|
('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(
|
migrations.AlterIndexTogether(
|
||||||
@@ -318,7 +317,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='project',
|
model_name='project',
|
||||||
name='organization',
|
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(
|
migrations.AlterField(
|
||||||
model_name='team',
|
model_name='team',
|
||||||
@@ -367,7 +366,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='credential',
|
model_name='credential',
|
||||||
name='organization',
|
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)),
|
('members', models.ManyToManyField(related_name='roles', to=settings.AUTH_USER_MODEL)),
|
||||||
('parents', models.ManyToManyField(related_name='children', to='main.Role')),
|
('parents', models.ManyToManyField(related_name='children', to='main.Role')),
|
||||||
('implicit_parents', models.TextField(default='[]')),
|
('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)),
|
('object_id', models.PositiveIntegerField(default=None, null=True)),
|
||||||
|
|
||||||
],
|
],
|
||||||
@@ -398,8 +397,8 @@ class Migration(migrations.Migration):
|
|||||||
('role_field', models.TextField()),
|
('role_field', models.TextField()),
|
||||||
('content_type_id', models.PositiveIntegerField()),
|
('content_type_id', models.PositiveIntegerField()),
|
||||||
('object_id', models.PositiveIntegerField()),
|
('object_id', models.PositiveIntegerField()),
|
||||||
('ancestor', models.ForeignKey(related_name='+', to='main.Role')),
|
('ancestor', models.ForeignKey(on_delete=models.CASCADE, related_name='+', to='main.Role')),
|
||||||
('descendent', models.ForeignKey(related_name='+', to='main.Role')),
|
('descendent', models.ForeignKey(on_delete=models.CASCADE, related_name='+', to='main.Role')),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'db_table': 'main_rbac_role_ancestors',
|
'db_table': 'main_rbac_role_ancestors',
|
||||||
@@ -569,7 +568,7 @@ class Migration(migrations.Migration):
|
|||||||
('name', models.CharField(max_length=512)),
|
('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)),
|
('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)),
|
('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')),
|
('tags', taggit.managers.TaggableManager(to='taggit.Tag', through='taggit.TaggedItem', blank=True, help_text='A comma-separated list of tags.', verbose_name='Tags')),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
@@ -599,12 +598,12 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='label',
|
model_name='label',
|
||||||
name='organization',
|
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(
|
migrations.AlterField(
|
||||||
model_name='label',
|
model_name='label',
|
||||||
name='organization',
|
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
|
# InventorySource Credential
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
@@ -630,12 +629,12 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='credential',
|
model_name='credential',
|
||||||
name='deprecated_team',
|
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(
|
migrations.AlterField(
|
||||||
model_name='credential',
|
model_name='credential',
|
||||||
name='deprecated_user',
|
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(
|
migrations.AlterField(
|
||||||
model_name='credential',
|
model_name='credential',
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='team',
|
model_name='team',
|
||||||
name='organization',
|
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,
|
preserve_default=False,
|
||||||
),
|
),
|
||||||
] + _squashed.operations(SQUASHED_30, applied=True)
|
] + _squashed.operations(SQUASHED_30, applied=True)
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='WorkflowJob',
|
name='WorkflowJob',
|
||||||
fields=[
|
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)),
|
('extra_vars', models.TextField(default='', blank=True)),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
@@ -100,7 +100,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='WorkflowJobTemplate',
|
name='WorkflowJobTemplate',
|
||||||
fields=[
|
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)),
|
('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')),
|
('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)),
|
('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)),
|
('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)),
|
('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={
|
options={
|
||||||
'abstract': False,
|
'abstract': False,
|
||||||
@@ -161,7 +161,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='workflowjobnode',
|
model_name='workflowjobnode',
|
||||||
name='char_prompts',
|
name='char_prompts',
|
||||||
field=jsonfield.fields.JSONField(default={}, blank=True),
|
field=jsonfield.fields.JSONField(default=dict, blank=True),
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='workflowjobnode',
|
model_name='workflowjobnode',
|
||||||
@@ -191,7 +191,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='workflowjobtemplatenode',
|
model_name='workflowjobtemplatenode',
|
||||||
name='char_prompts',
|
name='char_prompts',
|
||||||
field=jsonfield.fields.JSONField(default={}, blank=True),
|
field=jsonfield.fields.JSONField(default=dict, blank=True),
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='workflowjobtemplatenode',
|
model_name='workflowjobtemplatenode',
|
||||||
@@ -211,7 +211,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='workflowjobnode',
|
model_name='workflowjobnode',
|
||||||
name='workflow_job',
|
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(
|
migrations.AlterField(
|
||||||
model_name='workflowjobtemplate',
|
model_name='workflowjobtemplate',
|
||||||
@@ -227,12 +227,12 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='job',
|
model_name='job',
|
||||||
name='artifacts',
|
name='artifacts',
|
||||||
field=jsonfield.fields.JSONField(default={}, editable=False, blank=True),
|
field=jsonfield.fields.JSONField(default=dict, editable=False, blank=True),
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='workflowjobnode',
|
model_name='workflowjobnode',
|
||||||
name='ancestor_artifacts',
|
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
|
# Job timeout settings
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
@@ -397,7 +397,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='workflowjob',
|
model_name='workflowjob',
|
||||||
name='survey_passwords',
|
name='survey_passwords',
|
||||||
field=jsonfield.fields.JSONField(default={}, editable=False, blank=True),
|
field=jsonfield.fields.JSONField(default=dict, editable=False, blank=True),
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='workflowjobtemplate',
|
model_name='workflowjobtemplate',
|
||||||
@@ -407,33 +407,33 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='workflowjobtemplate',
|
model_name='workflowjobtemplate',
|
||||||
name='survey_spec',
|
name='survey_spec',
|
||||||
field=jsonfield.fields.JSONField(default={}, blank=True),
|
field=jsonfield.fields.JSONField(default=dict, blank=True),
|
||||||
),
|
),
|
||||||
# JSON field changes
|
# JSON field changes
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='adhoccommandevent',
|
model_name='adhoccommandevent',
|
||||||
name='event_data',
|
name='event_data',
|
||||||
field=awx.main.fields.JSONField(default={}, blank=True),
|
field=awx.main.fields.JSONField(default=dict, blank=True),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='job',
|
model_name='job',
|
||||||
name='artifacts',
|
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(
|
migrations.AlterField(
|
||||||
model_name='job',
|
model_name='job',
|
||||||
name='survey_passwords',
|
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(
|
migrations.AlterField(
|
||||||
model_name='jobevent',
|
model_name='jobevent',
|
||||||
name='event_data',
|
name='event_data',
|
||||||
field=awx.main.fields.JSONField(default={}, blank=True),
|
field=awx.main.fields.JSONField(default=dict, blank=True),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='jobtemplate',
|
model_name='jobtemplate',
|
||||||
name='survey_spec',
|
name='survey_spec',
|
||||||
field=awx.main.fields.JSONField(default={}, blank=True),
|
field=awx.main.fields.JSONField(default=dict, blank=True),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='notification',
|
model_name='notification',
|
||||||
@@ -453,37 +453,37 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='schedule',
|
model_name='schedule',
|
||||||
name='extra_data',
|
name='extra_data',
|
||||||
field=awx.main.fields.JSONField(default={}, blank=True),
|
field=awx.main.fields.JSONField(default=dict, blank=True),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='unifiedjob',
|
model_name='unifiedjob',
|
||||||
name='job_env',
|
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(
|
migrations.AlterField(
|
||||||
model_name='workflowjob',
|
model_name='workflowjob',
|
||||||
name='survey_passwords',
|
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(
|
migrations.AlterField(
|
||||||
model_name='workflowjobnode',
|
model_name='workflowjobnode',
|
||||||
name='ancestor_artifacts',
|
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(
|
migrations.AlterField(
|
||||||
model_name='workflowjobnode',
|
model_name='workflowjobnode',
|
||||||
name='char_prompts',
|
name='char_prompts',
|
||||||
field=awx.main.fields.JSONField(default={}, blank=True),
|
field=awx.main.fields.JSONField(default=dict, blank=True),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='workflowjobtemplate',
|
model_name='workflowjobtemplate',
|
||||||
name='survey_spec',
|
name='survey_spec',
|
||||||
field=awx.main.fields.JSONField(default={}, blank=True),
|
field=awx.main.fields.JSONField(default=dict, blank=True),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='workflowjobtemplatenode',
|
model_name='workflowjobtemplatenode',
|
||||||
name='char_prompts',
|
name='char_prompts',
|
||||||
field=awx.main.fields.JSONField(default={}, blank=True),
|
field=awx.main.fields.JSONField(default=dict, blank=True),
|
||||||
),
|
),
|
||||||
# Job Project Update
|
# Job Project Update
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
|
|||||||
@@ -55,12 +55,12 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='inventorysource',
|
model_name='inventorysource',
|
||||||
name='deprecated_group',
|
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(
|
migrations.AlterField(
|
||||||
model_name='inventorysource',
|
model_name='inventorysource',
|
||||||
name='inventory',
|
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
|
# Smart Inventory
|
||||||
@@ -78,13 +78,13 @@ class Migration(migrations.Migration):
|
|||||||
name='SmartInventoryMembership',
|
name='SmartInventoryMembership',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
('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(
|
migrations.AddField(
|
||||||
model_name='smartinventorymembership',
|
model_name='smartinventorymembership',
|
||||||
name='inventory',
|
name='inventory',
|
||||||
field=models.ForeignKey(related_name='+', to='main.Inventory'),
|
field=models.ForeignKey(on_delete=models.CASCADE, related_name='+', to='main.Inventory'),
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='host',
|
model_name='host',
|
||||||
@@ -105,19 +105,19 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='inventory',
|
model_name='inventory',
|
||||||
name='organization',
|
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
|
# Facts
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='fact',
|
model_name='fact',
|
||||||
name='facts',
|
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(
|
migrations.AddField(
|
||||||
model_name='host',
|
model_name='host',
|
||||||
name='ansible_facts',
|
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(
|
migrations.AddField(
|
||||||
model_name='host',
|
model_name='host',
|
||||||
@@ -148,12 +148,12 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='inventorysource',
|
model_name='inventorysource',
|
||||||
name='source_project',
|
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(
|
migrations.AddField(
|
||||||
model_name='inventoryupdate',
|
model_name='inventoryupdate',
|
||||||
name='source_project_update',
|
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(
|
migrations.AddField(
|
||||||
model_name='project',
|
model_name='project',
|
||||||
@@ -200,7 +200,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='notificationtemplate',
|
model_name='notificationtemplate',
|
||||||
name='organization',
|
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(
|
migrations.AlterUniqueTogether(
|
||||||
name='notificationtemplate',
|
name='notificationtemplate',
|
||||||
@@ -312,7 +312,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='inventory',
|
model_name='inventory',
|
||||||
name='insights_credential',
|
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(
|
migrations.AlterField(
|
||||||
model_name='inventory',
|
model_name='inventory',
|
||||||
@@ -382,10 +382,10 @@ class Migration(migrations.Migration):
|
|||||||
('name', models.CharField(max_length=512)),
|
('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')])),
|
('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)),
|
('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.')),
|
('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={}, 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.')),
|
('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.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True)),
|
('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.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.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')),
|
('tags', taggit.managers.TaggableManager(to='taggit.Tag', through='taggit.TaggedItem', blank=True, help_text='A comma-separated list of tags.', verbose_name='Tags')),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
@@ -399,23 +399,23 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='credential',
|
model_name='credential',
|
||||||
name='inputs',
|
name='inputs',
|
||||||
field=awx.main.fields.CredentialInputField(default={}, blank=True),
|
field=awx.main.fields.CredentialInputField(default=dict, blank=True),
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='credential',
|
model_name='credential',
|
||||||
name='credential_type',
|
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,
|
preserve_default=False,
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='job',
|
model_name='job',
|
||||||
name='vault_credential',
|
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(
|
migrations.AddField(
|
||||||
model_name='jobtemplate',
|
model_name='jobtemplate',
|
||||||
name='vault_credential',
|
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(
|
migrations.AddField(
|
||||||
model_name='job',
|
model_name='job',
|
||||||
@@ -452,7 +452,7 @@ class Migration(migrations.Migration):
|
|||||||
('name', models.CharField(unique=True, max_length=250)),
|
('name', models.CharField(unique=True, max_length=250)),
|
||||||
('created', models.DateTimeField(auto_now_add=True)),
|
('created', models.DateTimeField(auto_now_add=True)),
|
||||||
('modified', models.DateTimeField(auto_now=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')),
|
('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(
|
migrations.AddField(
|
||||||
model_name='unifiedjob',
|
model_name='unifiedjob',
|
||||||
name='instance_group',
|
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(
|
migrations.AddField(
|
||||||
model_name='unifiedjobtemplate',
|
model_name='unifiedjobtemplate',
|
||||||
|
|||||||
@@ -103,12 +103,12 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='credential',
|
model_name='credential',
|
||||||
name='credential_type',
|
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(
|
migrations.AlterField(
|
||||||
model_name='credential',
|
model_name='credential',
|
||||||
name='inputs',
|
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(
|
migrations.RemoveField(
|
||||||
model_name='job',
|
model_name='job',
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='schedule',
|
model_name='schedule',
|
||||||
name='char_prompts',
|
name='char_prompts',
|
||||||
field=awx.main.fields.JSONField(default={}, blank=True),
|
field=awx.main.fields.JSONField(default=dict, blank=True),
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='schedule',
|
model_name='schedule',
|
||||||
@@ -35,7 +35,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='schedule',
|
model_name='schedule',
|
||||||
name='survey_passwords',
|
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(
|
migrations.AddField(
|
||||||
model_name='workflowjobnode',
|
model_name='workflowjobnode',
|
||||||
@@ -45,12 +45,12 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='workflowjobnode',
|
model_name='workflowjobnode',
|
||||||
name='extra_data',
|
name='extra_data',
|
||||||
field=awx.main.fields.JSONField(default={}, blank=True),
|
field=awx.main.fields.JSONField(default=dict, blank=True),
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='workflowjobnode',
|
model_name='workflowjobnode',
|
||||||
name='survey_passwords',
|
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(
|
migrations.AddField(
|
||||||
model_name='workflowjobtemplatenode',
|
model_name='workflowjobtemplatenode',
|
||||||
@@ -60,12 +60,12 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='workflowjobtemplatenode',
|
model_name='workflowjobtemplatenode',
|
||||||
name='extra_data',
|
name='extra_data',
|
||||||
field=awx.main.fields.JSONField(default={}, blank=True),
|
field=awx.main.fields.JSONField(default=dict, blank=True),
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='workflowjobtemplatenode',
|
model_name='workflowjobtemplatenode',
|
||||||
name='survey_passwords',
|
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
|
# Run data migration before removing the old credential field
|
||||||
migrations.RunPython(migration_utils.set_current_apps_for_migrations, migrations.RunPython.noop),
|
migrations.RunPython(migration_utils.set_current_apps_for_migrations, migrations.RunPython.noop),
|
||||||
@@ -83,9 +83,9 @@ class Migration(migrations.Migration):
|
|||||||
name='JobLaunchConfig',
|
name='JobLaunchConfig',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
('extra_data', 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={}, editable=False)),
|
('survey_passwords', awx.main.fields.JSONField(blank=True, default=dict, editable=False)),
|
||||||
('char_prompts', awx.main.fields.JSONField(blank=True, default={})),
|
('char_prompts', awx.main.fields.JSONField(blank=True, default=dict)),
|
||||||
('credentials', models.ManyToManyField(related_name='joblaunchconfigs', to='main.Credential')),
|
('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')),
|
('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')),
|
('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(
|
migrations.AddField(
|
||||||
model_name='workflowjobtemplate',
|
model_name='workflowjobtemplate',
|
||||||
name='ask_variables_on_launch',
|
name='ask_variables_on_launch',
|
||||||
field=awx.main.fields.AskForField(default=False),
|
field=awx.main.fields.AskForField(blank=True, default=False),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='jobtemplate',
|
model_name='jobtemplate',
|
||||||
name='ask_credential_on_launch',
|
name='ask_credential_on_launch',
|
||||||
field=awx.main.fields.AskForField(default=False),
|
field=awx.main.fields.AskForField(blank=True, default=False),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='jobtemplate',
|
model_name='jobtemplate',
|
||||||
name='ask_diff_mode_on_launch',
|
name='ask_diff_mode_on_launch',
|
||||||
field=awx.main.fields.AskForField(default=False),
|
field=awx.main.fields.AskForField(blank=True, default=False),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='jobtemplate',
|
model_name='jobtemplate',
|
||||||
name='ask_inventory_on_launch',
|
name='ask_inventory_on_launch',
|
||||||
field=awx.main.fields.AskForField(default=False),
|
field=awx.main.fields.AskForField(blank=True, default=False),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='jobtemplate',
|
model_name='jobtemplate',
|
||||||
name='ask_job_type_on_launch',
|
name='ask_job_type_on_launch',
|
||||||
field=awx.main.fields.AskForField(default=False),
|
field=awx.main.fields.AskForField(blank=True, default=False),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='jobtemplate',
|
model_name='jobtemplate',
|
||||||
name='ask_limit_on_launch',
|
name='ask_limit_on_launch',
|
||||||
field=awx.main.fields.AskForField(default=False),
|
field=awx.main.fields.AskForField(blank=True, default=False),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='jobtemplate',
|
model_name='jobtemplate',
|
||||||
name='ask_skip_tags_on_launch',
|
name='ask_skip_tags_on_launch',
|
||||||
field=awx.main.fields.AskForField(default=False),
|
field=awx.main.fields.AskForField(blank=True, default=False),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='jobtemplate',
|
model_name='jobtemplate',
|
||||||
name='ask_tags_on_launch',
|
name='ask_tags_on_launch',
|
||||||
field=awx.main.fields.AskForField(default=False),
|
field=awx.main.fields.AskForField(blank=True, default=False),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='jobtemplate',
|
model_name='jobtemplate',
|
||||||
name='ask_variables_on_launch',
|
name='ask_variables_on_launch',
|
||||||
field=awx.main.fields.AskForField(default=False),
|
field=awx.main.fields.AskForField(blank=True, default=False),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='jobtemplate',
|
model_name='jobtemplate',
|
||||||
name='ask_verbosity_on_launch',
|
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')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
('created', models.DateTimeField(default=None, editable=False)),
|
('created', models.DateTimeField(default=None, editable=False)),
|
||||||
('modified', 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)),
|
('uuid', models.CharField(default='', editable=False, max_length=1024)),
|
||||||
('counter', models.PositiveIntegerField(default=0, editable=False)),
|
('counter', models.PositiveIntegerField(default=0, editable=False)),
|
||||||
('stdout', models.TextField(default='', editable=False)),
|
('stdout', models.TextField(default='', editable=False)),
|
||||||
@@ -40,7 +40,7 @@ class Migration(migrations.Migration):
|
|||||||
('created', models.DateTimeField(default=None, editable=False)),
|
('created', models.DateTimeField(default=None, editable=False)),
|
||||||
('modified', 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', 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)),
|
('failed', models.BooleanField(default=False, editable=False)),
|
||||||
('changed', models.BooleanField(default=False, editable=False)),
|
('changed', models.BooleanField(default=False, editable=False)),
|
||||||
('uuid', models.CharField(default='', editable=False, max_length=1024)),
|
('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')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
('created', models.DateTimeField(default=None, editable=False)),
|
('created', models.DateTimeField(default=None, editable=False)),
|
||||||
('modified', 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)),
|
('uuid', models.CharField(default='', editable=False, max_length=1024)),
|
||||||
('counter', models.PositiveIntegerField(default=0, editable=False)),
|
('counter', models.PositiveIntegerField(default=0, editable=False)),
|
||||||
('stdout', models.TextField(default='', editable=False)),
|
('stdout', models.TextField(default='', editable=False)),
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='workflowjob',
|
model_name='workflowjob',
|
||||||
name='char_prompts',
|
name='char_prompts',
|
||||||
field=awx.main.fields.JSONField(blank=True, default={}),
|
field=awx.main.fields.JSONField(blank=True, default=dict),
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='workflowjob',
|
model_name='workflowjob',
|
||||||
@@ -27,7 +27,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='workflowjobtemplate',
|
model_name='workflowjobtemplate',
|
||||||
name='ask_inventory_on_launch',
|
name='ask_inventory_on_launch',
|
||||||
field=awx.main.fields.AskForField(default=False),
|
field=awx.main.fields.AskForField(blank=True, default=False),
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='workflowjobtemplate',
|
model_name='workflowjobtemplate',
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ class Migration(migrations.Migration):
|
|||||||
('modified', models.DateTimeField(default=None, editable=False)),
|
('modified', models.DateTimeField(default=None, editable=False)),
|
||||||
('description', models.TextField(blank=True, default='')),
|
('description', models.TextField(blank=True, default='')),
|
||||||
('input_field_name', models.CharField(max_length=1024)),
|
('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)),
|
('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)),
|
('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')),
|
('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(
|
migrations.AddField(
|
||||||
model_name='job',
|
model_name='job',
|
||||||
name='survey_passwords',
|
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': [
|
'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
|
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.
|
# Add custom methods to User model for permissions checks.
|
||||||
from django.contrib.auth.models import User # noqa
|
from django.contrib.auth.models import User # noqa
|
||||||
from awx.main.access import ( # 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):
|
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
|
# NOTE: this if-else block ensures existing enterprise users are still able to
|
||||||
# log in. Remove it in a future release
|
# log in. Remove it in a future release
|
||||||
if category == 'radius':
|
if category == 'radius':
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ class Credential(PasswordFieldsModel, CommonModelNameNotUnique, ResourceMixin):
|
|||||||
)
|
)
|
||||||
inputs = CredentialInputField(
|
inputs = CredentialInputField(
|
||||||
blank=True,
|
blank=True,
|
||||||
default={},
|
default=dict,
|
||||||
help_text=_('Enter inputs using either JSON or YAML syntax. Use the '
|
help_text=_('Enter inputs using either JSON or YAML syntax. Use the '
|
||||||
'radio button to toggle between the two. Refer to the '
|
'radio button to toggle between the two. Refer to the '
|
||||||
'Ansible Tower documentation for example syntax.')
|
'Ansible Tower documentation for example syntax.')
|
||||||
@@ -343,14 +343,14 @@ class CredentialType(CommonModelNameNotUnique):
|
|||||||
)
|
)
|
||||||
inputs = CredentialTypeInputField(
|
inputs = CredentialTypeInputField(
|
||||||
blank=True,
|
blank=True,
|
||||||
default={},
|
default=dict,
|
||||||
help_text=_('Enter inputs using either JSON or YAML syntax. Use the '
|
help_text=_('Enter inputs using either JSON or YAML syntax. Use the '
|
||||||
'radio button to toggle between the two. Refer to the '
|
'radio button to toggle between the two. Refer to the '
|
||||||
'Ansible Tower documentation for example syntax.')
|
'Ansible Tower documentation for example syntax.')
|
||||||
)
|
)
|
||||||
injectors = CredentialTypeInjectorField(
|
injectors = CredentialTypeInjectorField(
|
||||||
blank=True,
|
blank=True,
|
||||||
default={},
|
default=dict,
|
||||||
help_text=_('Enter injectors using either JSON or YAML syntax. Use the '
|
help_text=_('Enter injectors using either JSON or YAML syntax. Use the '
|
||||||
'radio button to toggle between the two. Refer to the '
|
'radio button to toggle between the two. Refer to the '
|
||||||
'Ansible Tower documentation for example syntax.')
|
'Ansible Tower documentation for example syntax.')
|
||||||
@@ -1117,7 +1117,7 @@ class CredentialInputSource(PrimordialModel):
|
|||||||
)
|
)
|
||||||
metadata = DynamicCredentialInputField(
|
metadata = DynamicCredentialInputField(
|
||||||
blank=True,
|
blank=True,
|
||||||
default={}
|
default=dict
|
||||||
)
|
)
|
||||||
|
|
||||||
def clean_target_credential(self):
|
def clean_target_credential(self):
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ class BasePlaybookEvent(CreatedModifiedModel):
|
|||||||
)
|
)
|
||||||
event_data = JSONField(
|
event_data = JSONField(
|
||||||
blank=True,
|
blank=True,
|
||||||
default={},
|
default=dict,
|
||||||
)
|
)
|
||||||
failed = models.BooleanField(
|
failed = models.BooleanField(
|
||||||
default=False,
|
default=False,
|
||||||
@@ -567,7 +567,7 @@ class BaseCommandEvent(CreatedModifiedModel):
|
|||||||
|
|
||||||
event_data = JSONField(
|
event_data = JSONField(
|
||||||
blank=True,
|
blank=True,
|
||||||
default={},
|
default=dict,
|
||||||
)
|
)
|
||||||
uuid = models.CharField(
|
uuid = models.CharField(
|
||||||
max_length=1024,
|
max_length=1024,
|
||||||
|
|||||||
@@ -650,7 +650,7 @@ class Host(CommonModelNameNotUnique, RelatedJobsMixin):
|
|||||||
)
|
)
|
||||||
ansible_facts = JSONBField(
|
ansible_facts = JSONBField(
|
||||||
blank=True,
|
blank=True,
|
||||||
default={},
|
default=dict,
|
||||||
help_text=_('Arbitrary JSON structure of most recent ansible_facts, per-host.'),
|
help_text=_('Arbitrary JSON structure of most recent ansible_facts, per-host.'),
|
||||||
)
|
)
|
||||||
ansible_facts_modified = models.DateTimeField(
|
ansible_facts_modified = models.DateTimeField(
|
||||||
|
|||||||
@@ -485,7 +485,7 @@ class Job(UnifiedJob, JobOptions, SurveyJobMixin, JobNotificationMixin, TaskMana
|
|||||||
)
|
)
|
||||||
artifacts = JSONField(
|
artifacts = JSONField(
|
||||||
blank=True,
|
blank=True,
|
||||||
default={},
|
default=dict,
|
||||||
editable=False,
|
editable=False,
|
||||||
)
|
)
|
||||||
scm_revision = models.CharField(
|
scm_revision = models.CharField(
|
||||||
@@ -847,7 +847,7 @@ class LaunchTimeConfigBase(BaseModel):
|
|||||||
# This is a solution to the nullable CharField problem, specific to prompting
|
# This is a solution to the nullable CharField problem, specific to prompting
|
||||||
char_prompts = JSONField(
|
char_prompts = JSONField(
|
||||||
blank=True,
|
blank=True,
|
||||||
default={}
|
default=dict
|
||||||
)
|
)
|
||||||
|
|
||||||
def prompts_dict(self, display=False):
|
def prompts_dict(self, display=False):
|
||||||
@@ -927,11 +927,11 @@ class LaunchTimeConfig(LaunchTimeConfigBase):
|
|||||||
# Special case prompting fields, even more special than the other ones
|
# Special case prompting fields, even more special than the other ones
|
||||||
extra_data = JSONField(
|
extra_data = JSONField(
|
||||||
blank=True,
|
blank=True,
|
||||||
default={}
|
default=dict
|
||||||
)
|
)
|
||||||
survey_passwords = prevent_search(JSONField(
|
survey_passwords = prevent_search(JSONField(
|
||||||
blank=True,
|
blank=True,
|
||||||
default={},
|
default=dict,
|
||||||
editable=False,
|
editable=False,
|
||||||
))
|
))
|
||||||
# Credentials needed for non-unified job / unified JT models
|
# Credentials needed for non-unified job / unified JT models
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ class SurveyJobTemplateMixin(models.Model):
|
|||||||
)
|
)
|
||||||
survey_spec = prevent_search(JSONField(
|
survey_spec = prevent_search(JSONField(
|
||||||
blank=True,
|
blank=True,
|
||||||
default={},
|
default=dict,
|
||||||
))
|
))
|
||||||
ask_variables_on_launch = AskForField(
|
ask_variables_on_launch = AskForField(
|
||||||
blank=True,
|
blank=True,
|
||||||
@@ -360,7 +360,7 @@ class SurveyJobMixin(models.Model):
|
|||||||
|
|
||||||
survey_passwords = prevent_search(JSONField(
|
survey_passwords = prevent_search(JSONField(
|
||||||
blank=True,
|
blank=True,
|
||||||
default={},
|
default=dict,
|
||||||
editable=False,
|
editable=False,
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|||||||
@@ -641,7 +641,7 @@ class UnifiedJob(PolymorphicModel, PasswordFieldsModel, CommonModelNameNotUnique
|
|||||||
)
|
)
|
||||||
job_env = prevent_search(JSONField(
|
job_env = prevent_search(JSONField(
|
||||||
blank=True,
|
blank=True,
|
||||||
default={},
|
default=dict,
|
||||||
editable=False,
|
editable=False,
|
||||||
))
|
))
|
||||||
job_explanation = models.TextField(
|
job_explanation = models.TextField(
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ class WorkflowJobNode(WorkflowNodeBase):
|
|||||||
)
|
)
|
||||||
ancestor_artifacts = JSONField(
|
ancestor_artifacts = JSONField(
|
||||||
blank=True,
|
blank=True,
|
||||||
default={},
|
default=dict,
|
||||||
editable=False,
|
editable=False,
|
||||||
)
|
)
|
||||||
do_not_run = models.BooleanField(
|
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 not instance_group.is_isolated
|
||||||
assert isolated_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
|
assert isolated_instance_group.is_isolated
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ def run_command(name, *args, **options):
|
|||||||
command_runner = options.pop('command_runner', call_command)
|
command_runner = options.pop('command_runner', call_command)
|
||||||
stdin_fileobj = options.pop('stdin_fileobj', None)
|
stdin_fileobj = options.pop('stdin_fileobj', None)
|
||||||
options.setdefault('verbosity', 1)
|
options.setdefault('verbosity', 1)
|
||||||
options.setdefault('interactive', False)
|
|
||||||
original_stdin = sys.stdin
|
original_stdin = sys.stdin
|
||||||
original_stdout = sys.stdout
|
original_stdout = sys.stdout
|
||||||
original_stderr = sys.stderr
|
original_stderr = sys.stderr
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ from django.urls import resolve
|
|||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.core.serializers.json import DjangoJSONEncoder
|
from django.core.serializers.json import DjangoJSONEncoder
|
||||||
from django.db.backends.sqlite3.base import SQLiteCursorWrapper
|
from django.db.backends.sqlite3.base import SQLiteCursorWrapper
|
||||||
from jsonbfield.fields import JSONField
|
|
||||||
|
|
||||||
# AWX
|
# AWX
|
||||||
|
from awx.main.fields import JSONBField
|
||||||
from awx.main.models.projects import Project
|
from awx.main.models.projects import Project
|
||||||
from awx.main.models.ha import Instance
|
from awx.main.models.ha import Instance
|
||||||
|
|
||||||
@@ -737,7 +737,7 @@ def get_db_prep_save(self, value, connection, **kwargs):
|
|||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def monkeypatch_jsonbfield_get_db_prep_save(mocker):
|
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
|
@pytest.fixture
|
||||||
|
|||||||
@@ -457,4 +457,4 @@ def test_duplicate_name_within_template(job_template):
|
|||||||
with pytest.raises(IntegrityError) as ierror:
|
with pytest.raises(IntegrityError) as ierror:
|
||||||
s2.save()
|
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
|
from django.core.exceptions import ValidationError
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
|
||||||
class TestWorkflowDAGFunctional(TransactionTestCase):
|
class TestWorkflowDAGFunctional(TransactionTestCase):
|
||||||
def workflow_job(self, states=['new', 'new', 'new', 'new', 'new']):
|
def workflow_job(self, states=['new', 'new', 'new', 'new', 'new']):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
import pytest
|
|
||||||
|
|
||||||
from django.test import TransactionTestCase
|
from django.test import TransactionTestCase
|
||||||
|
|
||||||
from awx.main.models import (
|
from awx.main.models import (
|
||||||
@@ -8,7 +6,6 @@ from awx.main.models import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
|
||||||
class TestCapacityMapping(TransactionTestCase):
|
class TestCapacityMapping(TransactionTestCase):
|
||||||
|
|
||||||
def sample_cluster(self):
|
def sample_cluster(self):
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ def test_job_notification_data(inventory, machine_credential, project):
|
|||||||
survey_passwords={"SSN": encrypted_str},
|
survey_passwords={"SSN": encrypted_str},
|
||||||
project=project,
|
project=project,
|
||||||
)
|
)
|
||||||
job.credentials = [machine_credential]
|
job.credentials.set([machine_credential])
|
||||||
notification_data = job.notification_data(block=0)
|
notification_data = job.notification_data(block=0)
|
||||||
assert json.loads(notification_data['extra_vars'])['SSN'] == encrypted_str
|
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
|
from awx.main.models import User, Organization, Inventory
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
|
||||||
class TestSysAuditorTransactional(TransactionTestCase):
|
class TestSysAuditorTransactional(TransactionTestCase):
|
||||||
def rando(self):
|
def rando(self):
|
||||||
return User.objects.create(username='rando', password='rando', email='rando@com.com')
|
return User.objects.create(username='rando', password='rando', email='rando@com.com')
|
||||||
|
|||||||
@@ -186,11 +186,8 @@ class TestResourceAccessList:
|
|||||||
|
|
||||||
def mock_request(self):
|
def mock_request(self):
|
||||||
return mock.MagicMock(
|
return mock.MagicMock(
|
||||||
user=mock.MagicMock(
|
user=mock.MagicMock(is_anonymous=False, is_superuser=False),
|
||||||
is_anonymous=mock.MagicMock(return_value=False),
|
method='GET')
|
||||||
is_superuser=False
|
|
||||||
), method='GET')
|
|
||||||
|
|
||||||
|
|
||||||
def mock_view(self, parent=None):
|
def mock_view(self, parent=None):
|
||||||
view = ResourceAccessList()
|
view = ResourceAccessList()
|
||||||
@@ -200,7 +197,6 @@ class TestResourceAccessList:
|
|||||||
view.get_parent_object = lambda: parent
|
view.get_parent_object = lambda: parent
|
||||||
return view
|
return view
|
||||||
|
|
||||||
|
|
||||||
def test_parent_access_check_failed(self, mocker, mock_organization):
|
def test_parent_access_check_failed(self, mocker, mock_organization):
|
||||||
mock_access = mocker.MagicMock(__name__='for logger', return_value=False)
|
mock_access = mocker.MagicMock(__name__='for logger', return_value=False)
|
||||||
with mocker.patch('awx.main.access.BaseAccess.can_read', mock_access):
|
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())
|
self.mock_view(parent=mock_organization).check_permissions(self.mock_request())
|
||||||
mock_access.assert_called_once_with(mock_organization)
|
mock_access.assert_called_once_with(mock_organization)
|
||||||
|
|
||||||
|
|
||||||
def test_parent_access_check_worked(self, mocker, mock_organization):
|
def test_parent_access_check_worked(self, mocker, mock_organization):
|
||||||
mock_access = mocker.MagicMock(__name__='for logger', return_value=True)
|
mock_access = mocker.MagicMock(__name__='for logger', return_value=True)
|
||||||
with mocker.patch('awx.main.access.BaseAccess.can_read', mock_access):
|
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
|
from awx.api.urls import urlpatterns as api_patterns
|
||||||
|
|
||||||
# Django
|
# Django
|
||||||
from django.urls import RegexURLResolver, RegexURLPattern
|
from django.urls import URLResolver, URLPattern
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
@@ -20,24 +20,24 @@ def all_views():
|
|||||||
'''
|
'''
|
||||||
returns a set of all views in the app
|
returns a set of all views in the app
|
||||||
'''
|
'''
|
||||||
patterns = set([])
|
patterns = set()
|
||||||
url_views = set([])
|
url_views = set()
|
||||||
# Add recursive URL patterns
|
# Add recursive URL patterns
|
||||||
unprocessed = set(api_patterns)
|
unprocessed = set(api_patterns)
|
||||||
while unprocessed:
|
while unprocessed:
|
||||||
to_process = unprocessed.copy()
|
to_process = unprocessed.copy()
|
||||||
unprocessed = set([])
|
unprocessed = set()
|
||||||
for pattern in to_process:
|
for pattern in to_process:
|
||||||
if hasattr(pattern, 'lookup_str') and not pattern.lookup_str.startswith('awx.api'):
|
if hasattr(pattern, 'lookup_str') and not pattern.lookup_str.startswith('awx.api'):
|
||||||
continue
|
continue
|
||||||
patterns.add(pattern)
|
patterns.add(pattern)
|
||||||
if isinstance(pattern, RegexURLResolver):
|
if isinstance(pattern, URLResolver):
|
||||||
for sub_pattern in pattern.url_patterns:
|
for sub_pattern in pattern.url_patterns:
|
||||||
if sub_pattern not in patterns:
|
if sub_pattern not in patterns:
|
||||||
unprocessed.add(sub_pattern)
|
unprocessed.add(sub_pattern)
|
||||||
# Get view classes
|
# Get view classes
|
||||||
for pattern in patterns:
|
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)
|
url_views.add(pattern.callback.view_class)
|
||||||
return url_views
|
return url_views
|
||||||
|
|
||||||
|
|||||||
@@ -57,5 +57,5 @@ def test_really_long_event_fields(field):
|
|||||||
})
|
})
|
||||||
manager.create.assert_called_with(**{
|
manager.create.assert_called_with(**{
|
||||||
'job_id': 123,
|
'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)
|
field = model._meta.get_field(field_name)
|
||||||
if field_name == 'name':
|
if field_name == 'name':
|
||||||
has_name = True
|
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)
|
fk_names.append(field_name)
|
||||||
elif issubclass(type(field), models.CharField) and field.choices:
|
elif issubclass(type(field), models.CharField) and field.choices:
|
||||||
fields.append(field_name)
|
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][:]
|
fields, fk_names = configuration[model][0][:], configuration[model][1][:]
|
||||||
adj_list = []
|
adj_list = []
|
||||||
for fk_name in fk_names:
|
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):
|
if issubclass(next_model, ContentType):
|
||||||
continue
|
continue
|
||||||
if next_model not in configuration or\
|
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)
|
return render(request, 'error.html', kwargs, status=status)
|
||||||
|
|
||||||
|
|
||||||
def handle_400(request):
|
def handle_400(request, exception):
|
||||||
kwargs = {
|
kwargs = {
|
||||||
'name': _('Bad Request'),
|
'name': _('Bad Request'),
|
||||||
'content': _('The request could not be understood by the server.'),
|
'content': _('The request could not be understood by the server.'),
|
||||||
@@ -68,7 +68,7 @@ def handle_400(request):
|
|||||||
return handle_error(request, 400, **kwargs)
|
return handle_error(request, 400, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def handle_403(request):
|
def handle_403(request, exception):
|
||||||
kwargs = {
|
kwargs = {
|
||||||
'name': _('Forbidden'),
|
'name': _('Forbidden'),
|
||||||
'content': _('You don\'t have permission to access the requested resource.'),
|
'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)
|
return handle_error(request, 403, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def handle_404(request):
|
def handle_404(request, exception):
|
||||||
kwargs = {
|
kwargs = {
|
||||||
'name': _('Not Found'),
|
'name': _('Not Found'),
|
||||||
'content': _('The requested resource could not be 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.contrib.auth.models import User
|
||||||
from django.conf import settings as django_settings
|
from django.conf import settings as django_settings
|
||||||
from django.core.signals import setting_changed
|
from django.core.signals import setting_changed
|
||||||
|
from django.utils.encoding import force_text
|
||||||
|
|
||||||
# django-auth-ldap
|
# django-auth-ldap
|
||||||
from django_auth_ldap.backend import LDAPSettings as BaseLDAPSettings
|
from django_auth_ldap.backend import LDAPSettings as BaseLDAPSettings
|
||||||
@@ -98,7 +99,7 @@ class LDAPBackend(BaseLDAPBackend):
|
|||||||
|
|
||||||
settings = property(_get_settings, _set_settings)
|
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:
|
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
|
# with python-ldap, if you want to set connection-specific TLS
|
||||||
# parameters, you must also specify OPT_X_TLS_NEWCTX = 0
|
# parameters, you must also specify OPT_X_TLS_NEWCTX = 0
|
||||||
@@ -124,7 +125,7 @@ class LDAPBackend(BaseLDAPBackend):
|
|||||||
raise ImproperlyConfigured(
|
raise ImproperlyConfigured(
|
||||||
"{} must be an {} instance.".format(setting_name, type_)
|
"{} 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:
|
except Exception:
|
||||||
logger.exception("Encountered an error authenticating to LDAP")
|
logger.exception("Encountered an error authenticating to LDAP")
|
||||||
return None
|
return None
|
||||||
@@ -179,7 +180,7 @@ def _decorate_enterprise_user(user, provider):
|
|||||||
def _get_or_set_enterprise_user(username, password, provider):
|
def _get_or_set_enterprise_user(username, password, provider):
|
||||||
created = False
|
created = False
|
||||||
try:
|
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:
|
except User.DoesNotExist:
|
||||||
user = User(username=username)
|
user = User(username=username)
|
||||||
enterprise_auth = _decorate_enterprise_user(user, provider)
|
enterprise_auth = _decorate_enterprise_user(user, provider)
|
||||||
@@ -196,10 +197,10 @@ class RADIUSBackend(BaseRADIUSBackend):
|
|||||||
Custom Radius backend to verify license status
|
Custom Radius backend to verify license status
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def authenticate(self, username, password):
|
def authenticate(self, request, username, password):
|
||||||
if not django_settings.RADIUS_SERVER:
|
if not django_settings.RADIUS_SERVER:
|
||||||
return None
|
return None
|
||||||
return super(RADIUSBackend, self).authenticate(None, username, password)
|
return super(RADIUSBackend, self).authenticate(request, username, password)
|
||||||
|
|
||||||
def get_user(self, user_id):
|
def get_user(self, user_id):
|
||||||
if not django_settings.RADIUS_SERVER:
|
if not django_settings.RADIUS_SERVER:
|
||||||
@@ -209,7 +210,7 @@ class RADIUSBackend(BaseRADIUSBackend):
|
|||||||
return user
|
return user
|
||||||
|
|
||||||
def get_django_user(self, username, password=None):
|
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):
|
class TACACSPlusBackend(object):
|
||||||
@@ -217,7 +218,7 @@ class TACACSPlusBackend(object):
|
|||||||
Custom TACACS+ auth backend for AWX
|
Custom TACACS+ auth backend for AWX
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def authenticate(self, username, password):
|
def authenticate(self, request, username, password):
|
||||||
if not django_settings.TACACSPLUS_HOST:
|
if not django_settings.TACACSPLUS_HOST:
|
||||||
return None
|
return None
|
||||||
try:
|
try:
|
||||||
@@ -284,13 +285,13 @@ class SAMLAuth(BaseSAMLAuth):
|
|||||||
idp_config = self.setting('ENABLED_IDPS')[idp_name]
|
idp_config = self.setting('ENABLED_IDPS')[idp_name]
|
||||||
return TowerSAMLIdentityProvider(idp_name, **idp_config)
|
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,
|
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_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_TECHNICAL_CONTACT, django_settings.SOCIAL_AUTH_SAML_SUPPORT_CONTACT,
|
||||||
django_settings.SOCIAL_AUTH_SAML_ENABLED_IDPS]):
|
django_settings.SOCIAL_AUTH_SAML_ENABLED_IDPS]):
|
||||||
return None
|
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
|
# Comes from https://github.com/omab/python-social-auth/blob/v0.2.21/social/backends/base.py#L91
|
||||||
if getattr(user, 'is_new', False):
|
if getattr(user, 'is_new', False):
|
||||||
_decorate_enterprise_user(user, 'saml')
|
_decorate_enterprise_user(user, 'saml')
|
||||||
@@ -307,7 +308,7 @@ class SAMLAuth(BaseSAMLAuth):
|
|||||||
return super(SAMLAuth, self).get_user(user_id)
|
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.
|
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
|
should_add = True
|
||||||
if should_add:
|
if should_add:
|
||||||
user.save()
|
user.save()
|
||||||
rel.add(user)
|
related.add(user)
|
||||||
elif remove and user in rel.all():
|
elif remove and user in related.all():
|
||||||
user.save()
|
user.save()
|
||||||
rel.remove(user)
|
related.remove(user)
|
||||||
|
|
||||||
|
|
||||||
@receiver(populate_user, dispatch_uid='populate-ldap-user')
|
@receiver(populate_user, dispatch_uid='populate-ldap-user')
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ class SocialAuthMiddleware(SocialAuthExceptionMiddleware):
|
|||||||
request.successful_authenticator = None
|
request.successful_authenticator = None
|
||||||
|
|
||||||
if not request.path.startswith('/sso/') and 'migrations_notran' not in request.path:
|
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,
|
# The rest of the code base rely hevily on type/inheritance checks,
|
||||||
# LazyObject sent from Django auth middleware can be buggy if not
|
# LazyObject sent from Django auth middleware can be buggy if not
|
||||||
# converted back to its original object.
|
# converted back to its original object.
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ class Migration(migrations.Migration):
|
|||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
('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+')])),
|
('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(
|
migrations.AlterUniqueTogether(
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ def prevent_inactive_login(backend, details, user=None, *args, **kwargs):
|
|||||||
raise AuthInactive(backend)
|
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
|
Helper function to update m2m relationship based on user matching one or
|
||||||
more expressions.
|
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):
|
if ex.match(user.username) or ex.match(user.email):
|
||||||
should_add = True
|
should_add = True
|
||||||
if should_add:
|
if should_add:
|
||||||
rel.add(user)
|
related.add(user)
|
||||||
elif remove:
|
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
|
from awx.main.models import Organization
|
||||||
|
|
||||||
org_ids = []
|
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 = Organization.objects.get_or_create(name=org_name)[0]
|
||||||
|
|
||||||
org_ids.append(org.id)
|
org_ids.append(org.id)
|
||||||
getattr(org, rel).members.add(user)
|
getattr(org, related).members.add(user)
|
||||||
|
|
||||||
if remove:
|
if remove:
|
||||||
[o.member_role.members.remove(user) for o in
|
[o.member_role.members.remove(user) for o in
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ def existing_tacacsplus_user():
|
|||||||
user = User.objects.get(username="foo")
|
user = User.objects.get(username="foo")
|
||||||
except User.DoesNotExist:
|
except User.DoesNotExist:
|
||||||
user = User(username="foo")
|
user = User(username="foo")
|
||||||
|
user.set_unusable_password()
|
||||||
user.save()
|
user.save()
|
||||||
enterprise_auth = UserEnterpriseAuth(user=user, provider='tacacs+')
|
enterprise_auth = UserEnterpriseAuth(user=user, provider='tacacs+')
|
||||||
enterprise_auth.save()
|
enterprise_auth.save()
|
||||||
|
|||||||
@@ -8,7 +8,10 @@ from awx.sso.backends import _get_or_set_enterprise_user
|
|||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_fetch_user_if_exist(existing_tacacsplus_user):
|
def test_fetch_user_if_exist(existing_tacacsplus_user):
|
||||||
|
with mock.patch('awx.sso.backends.logger') as mocked_logger:
|
||||||
new_user = _get_or_set_enterprise_user("foo", "password", "tacacs+")
|
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
|
assert new_user == existing_tacacsplus_user
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from unittest import mock
|
|||||||
def test_empty_host_fails_auth(tacacsplus_backend):
|
def test_empty_host_fails_auth(tacacsplus_backend):
|
||||||
with mock.patch('awx.sso.backends.django_settings') as settings:
|
with mock.patch('awx.sso.backends.django_settings') as settings:
|
||||||
settings.TACACSPLUS_HOST = ''
|
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
|
assert ret_user is None
|
||||||
|
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ def test_client_raises_exception(tacacsplus_backend):
|
|||||||
mock.patch('tacacs_plus.TACACSClient', return_value=client):
|
mock.patch('tacacs_plus.TACACSClient', return_value=client):
|
||||||
settings.TACACSPLUS_HOST = 'localhost'
|
settings.TACACSPLUS_HOST = 'localhost'
|
||||||
settings.TACACSPLUS_AUTH_PROTOCOL = 'ascii'
|
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
|
assert ret_user is None
|
||||||
logger.exception.assert_called_once_with(
|
logger.exception.assert_called_once_with(
|
||||||
"TACACS+ Authentication Error: foo"
|
"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):
|
mock.patch('tacacs_plus.TACACSClient', return_value=client):
|
||||||
settings.TACACSPLUS_HOST = 'localhost'
|
settings.TACACSPLUS_HOST = 'localhost'
|
||||||
settings.TACACSPLUS_AUTH_PROTOCOL = 'ascii'
|
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
|
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):
|
mock.patch('awx.sso.backends._get_or_set_enterprise_user', return_value=user):
|
||||||
settings.TACACSPLUS_HOST = 'localhost'
|
settings.TACACSPLUS_HOST = 'localhost'
|
||||||
settings.TACACSPLUS_AUTH_PROTOCOL = 'ascii'
|
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
|
assert ret_user == user
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ class CompleteView(BaseRedirectView):
|
|||||||
|
|
||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
response = super(CompleteView, self).dispatch(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)))
|
logger.info(smart_text(u"User {} logged in".format(self.request.user.username)))
|
||||||
response.set_cookie('userLoggedIn', 'true')
|
response.set_cookie('userLoggedIn', 'true')
|
||||||
current_user = UserSerializer(self.request.user)
|
current_user = UserSerializer(self.request.user)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{% extends "rest_framework/api.html" %}
|
{% extends "rest_framework/api.html" %}
|
||||||
{% load i18n staticfiles %}
|
{% load i18n static %}
|
||||||
|
|
||||||
{% block title %}{{ name }} · {% trans 'AWX' %}{% endblock %}
|
{% block title %}{{ name }} · {% trans 'AWX' %}{% endblock %}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{# Partial copy of login_base.html from rest_framework with AWX change. #}
|
{# Partial copy of login_base.html from rest_framework with AWX change. #}
|
||||||
{% extends 'rest_framework/api.html' %}
|
{% extends 'rest_framework/api.html' %}
|
||||||
{% load i18n staticfiles %}
|
{% load i18n static %}
|
||||||
|
|
||||||
{% block breadcrumbs %}
|
{% block breadcrumbs %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -40,12 +40,5 @@ if social_django.__version__ != '2.1.0':
|
|||||||
still works".format(social_django.__version__))
|
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.
|
# Return the default Django WSGI application.
|
||||||
application = get_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
|
celery==4.3.0
|
||||||
daphne==1.3.0 # Last before backwards-incompatible channels 2 upgrade
|
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
|
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-auth-ldap==1.7.0
|
||||||
django-cors-headers==2.4.0
|
django-cors-headers==2.4.0
|
||||||
django-crum==0.7.2
|
django-crum==0.7.2
|
||||||
django-extensions==2.0.0
|
django-extensions==2.0.0
|
||||||
django-jsonfield==1.0.1
|
django-jsonfield==1.2.0
|
||||||
django-oauth-toolkit==1.1.3
|
django-oauth-toolkit==1.1.3
|
||||||
django-polymorphic==2.0.2
|
django-polymorphic==2.0.2
|
||||||
django-pglocks==1.0.2
|
django-pglocks==1.0.2
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ django-auth-ldap==1.7.0
|
|||||||
django-cors-headers==2.4.0
|
django-cors-headers==2.4.0
|
||||||
django-crum==0.7.2
|
django-crum==0.7.2
|
||||||
django-extensions==2.0.0
|
django-extensions==2.0.0
|
||||||
django-jsonfield==1.0.1
|
django-jsonfield==1.2.0
|
||||||
django-oauth-toolkit==1.1.3
|
django-oauth-toolkit==1.1.3
|
||||||
django-pglocks==1.0.2
|
django-pglocks==1.0.2
|
||||||
django-polymorphic==2.0.2
|
django-polymorphic==2.0.2
|
||||||
@@ -35,7 +35,7 @@ django-radius==1.3.3
|
|||||||
django-solo==1.1.3
|
django-solo==1.1.3
|
||||||
django-split-settings==0.3.0
|
django-split-settings==0.3.0
|
||||||
django-taggit==0.22.2
|
django-taggit==0.22.2
|
||||||
django==1.11.20
|
django==2.2.2
|
||||||
djangorestframework-yaml==1.0.3
|
djangorestframework-yaml==1.0.3
|
||||||
djangorestframework==3.9.4
|
djangorestframework==3.9.4
|
||||||
|
|
||||||
@@ -102,6 +102,7 @@ six==1.12.0 # via ansible-runner, asgi-amqp, asgiref, autobahn, au
|
|||||||
slackclient==1.1.2
|
slackclient==1.1.2
|
||||||
social-auth-app-django==2.1.0
|
social-auth-app-django==2.1.0
|
||||||
social-auth-core==3.0.0
|
social-auth-core==3.0.0
|
||||||
|
sqlparse==0.3.0 # via django
|
||||||
tacacs_plus==1.0
|
tacacs_plus==1.0
|
||||||
tempora==1.14.1 # via irc, jaraco.logging
|
tempora==1.14.1 # via irc, jaraco.logging
|
||||||
twilio==6.10.4
|
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/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-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
|
ARG UID=0
|
||||||
|
|
||||||
RUN yum -y update && yum -y install epel-release
|
|
||||||
|
|
||||||
# sync with installer/roles/image_build/templates/Dockerfile.j2
|
# sync with installer/roles/image_build/templates/Dockerfile.j2
|
||||||
RUN yum -y install acl \
|
RUN dnf -y install acl \
|
||||||
alsa-lib \
|
alsa-lib \
|
||||||
ansible \
|
ansible \
|
||||||
atk \
|
atk \
|
||||||
@@ -14,12 +12,15 @@ RUN yum -y install acl \
|
|||||||
curl \
|
curl \
|
||||||
cyrus-sasl \
|
cyrus-sasl \
|
||||||
cyrus-sasl-devel \
|
cyrus-sasl-devel \
|
||||||
|
findutils \
|
||||||
gcc \
|
gcc \
|
||||||
gcc-c++ \
|
gcc-c++ \
|
||||||
GConf2 \
|
GConf2 \
|
||||||
git \
|
git \
|
||||||
|
glibc-locale-source \
|
||||||
gtk3 \
|
gtk3 \
|
||||||
ipa-gothic-fonts \
|
ipa-gothic-fonts \
|
||||||
|
iproute \
|
||||||
krb5-devel \
|
krb5-devel \
|
||||||
krb5-libs \
|
krb5-libs \
|
||||||
krb5-workstation \
|
krb5-workstation \
|
||||||
@@ -45,16 +46,16 @@ RUN yum -y install acl \
|
|||||||
nodejs \
|
nodejs \
|
||||||
openldap-devel \
|
openldap-devel \
|
||||||
openssh-server \
|
openssh-server \
|
||||||
|
postgresql-contrib \
|
||||||
postgresql-devel \
|
postgresql-devel \
|
||||||
python-devel \
|
python-devel \
|
||||||
python-pip \
|
python-pip \
|
||||||
python-psutil \
|
python-psutil \
|
||||||
python-psycopg2 \
|
python-psycopg2 \
|
||||||
python-setuptools \
|
python-setuptools \
|
||||||
python36-devel \
|
python3-devel \
|
||||||
python36-setuptools \
|
python3-setuptools \
|
||||||
rsync \
|
rsync \
|
||||||
setools-libs \
|
|
||||||
subversion \
|
subversion \
|
||||||
sudo \
|
sudo \
|
||||||
swig \
|
swig \
|
||||||
|
|||||||
Reference in New Issue
Block a user