Replace all previously text-based json fields with JSONBlob

This JSONBlob field type is a wrapper around Django's new generic
JSONField, but with the database column type forced to be text.  This
should behave close enough to our old wrapper around
django-jsonfield's JSONField and will avoid needing to do the
out-of-band database migration.
This commit is contained in:
Jeff Bradberry 2022-03-23 17:27:28 -04:00
parent 7b2b979c1b
commit e3f3ab224a
24 changed files with 101 additions and 77 deletions

View File

@ -4,6 +4,8 @@ from __future__ import unicode_literals
from django.db import migrations, models
from django.conf import settings
import awx.main.fields
class Migration(migrations.Migration):
@ -17,7 +19,7 @@ class Migration(migrations.Migration):
('created', models.DateTimeField(default=None, editable=False)),
('modified', models.DateTimeField(default=None, editable=False)),
('key', models.CharField(max_length=255)),
('value', models.JSONField(null=True)),
('value', awx.main.fields.JSONBlob(null=True)),
(
'user',
models.ForeignKey(related_name='settings', default=None, editable=False, to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True),

View File

@ -1,11 +1,13 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
from django.db import migrations
import awx.main.fields
class Migration(migrations.Migration):
dependencies = [('conf', '0002_v310_copy_tower_settings')]
operations = [migrations.AlterField(model_name='setting', name='value', field=models.JSONField(null=True))]
operations = [migrations.AlterField(model_name='setting', name='value', field=awx.main.fields.JSONBlob(null=True))]

View File

@ -8,6 +8,7 @@ import json
from django.db import models
# AWX
from awx.main.fields import JSONBlob
from awx.main.models.base import CreatedModifiedModel, prevent_search
from awx.main.utils import encrypt_field
from awx.conf import settings_registry
@ -18,7 +19,7 @@ __all__ = ['Setting']
class Setting(CreatedModifiedModel):
key = models.CharField(max_length=255)
value = models.JSONField(null=True)
value = JSONBlob(null=True)
user = prevent_search(models.ForeignKey('auth.User', related_name='settings', default=None, null=True, editable=False, on_delete=models.CASCADE))
def __str__(self):

View File

@ -43,7 +43,6 @@ from rest_framework import serializers
from awx.main.utils.filters import SmartFilter
from awx.main.utils.encryption import encrypt_value, decrypt_value, get_encryption_key
from awx.main.validators import validate_ssh_private_key
from awx.main.models.rbac import batch_role_ancestor_rebuilding, Role, ROLE_SINGLETON_SYSTEM_ADMINISTRATOR, ROLE_SINGLETON_SYSTEM_AUDITOR
from awx.main.constants import ENV_BLOCKLIST
from awx.main import utils
@ -130,6 +129,9 @@ def is_implicit_parent(parent_role, child_role):
the model definition. This does not include any role parents that
might have been set by the user.
"""
# Avoid circular import
from awx.main.models.rbac import ROLE_SINGLETON_SYSTEM_ADMINISTRATOR, ROLE_SINGLETON_SYSTEM_AUDITOR
if child_role.content_object is None:
# The only singleton implicit parent is the system admin being
# a parent of the system auditor role
@ -286,6 +288,9 @@ class ImplicitRoleField(models.ForeignKey):
Model = utils.get_current_apps().get_model('main', instance.__class__.__name__)
latest_instance = Model.objects.get(pk=instance.pk)
# Avoid circular import
from awx.main.models.rbac import batch_role_ancestor_rebuilding, Role
with batch_role_ancestor_rebuilding():
# Create any missing role objects
missing_roles = []
@ -340,6 +345,10 @@ class ImplicitRoleField(models.ForeignKey):
Role_ = utils.get_current_apps().get_model('main', 'Role')
child_ids = [x for x in Role_.parents.through.objects.filter(to_role_id__in=role_ids).distinct().values_list('from_role_id', flat=True)]
Role_.objects.filter(id__in=role_ids).delete()
# Avoid circular import
from awx.main.models.rbac import Role
Role.rebuild_role_ancestor_list([], child_ids)

View File

@ -622,7 +622,7 @@ class Migration(migrations.Migration):
('dtend', models.DateTimeField(default=None, null=True, editable=False)),
('rrule', models.CharField(max_length=255)),
('next_run', models.DateTimeField(default=None, null=True, editable=False)),
('extra_data', models.JSONField(default=dict, null=True, blank=True)),
('extra_data', awx.main.fields.JSONBlob(default=dict, blank=True)),
(
'created_by',
models.ForeignKey(
@ -750,7 +750,7 @@ class Migration(migrations.Migration):
('elapsed', models.DecimalField(editable=False, max_digits=12, decimal_places=3)),
('job_args', models.TextField(default='', editable=False, blank=True)),
('job_cwd', models.CharField(default='', max_length=1024, editable=False, blank=True)),
('job_env', models.JSONField(default=dict, editable=False, null=True, blank=True)),
('job_env', awx.main.fields.JSONBlob(default=dict, editable=False, blank=True)),
('job_explanation', models.TextField(default='', editable=False, blank=True)),
('start_args', models.TextField(default='', editable=False, blank=True)),
('result_stdout_text', models.TextField(default='', editable=False, blank=True)),
@ -1034,7 +1034,7 @@ class Migration(migrations.Migration):
('host_config_key', models.CharField(default='', max_length=1024, blank=True)),
('ask_variables_on_launch', models.BooleanField(default=False)),
('survey_enabled', models.BooleanField(default=False)),
('survey_spec', models.JSONField(default=dict, blank=True)),
('survey_spec', awx.main.fields.JSONBlob(default=dict, blank=True)),
],
options={
'ordering': ('name',),

View File

@ -198,7 +198,7 @@ class Migration(migrations.Migration):
),
('recipients', models.TextField(default='', editable=False, blank=True)),
('subject', models.TextField(default='', editable=False, blank=True)),
('body', models.JSONField(default=dict, null=True, blank=True)),
('body', awx.main.fields.JSONBlob(default=dict, blank=True)),
],
options={
'ordering': ('pk',),
@ -229,7 +229,7 @@ class Migration(migrations.Migration):
],
),
),
('notification_configuration', models.JSONField(default=dict)),
('notification_configuration', awx.main.fields.JSONBlob(default=dict)),
(
'created_by',
models.ForeignKey(

View File

@ -220,7 +220,7 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='workflowjobnode',
name='char_prompts',
field=models.JSONField(default=dict, null=True, blank=True),
field=awx.main.fields.JSONBlob(default=dict, blank=True),
),
migrations.AddField(
model_name='workflowjobnode',
@ -259,7 +259,7 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='workflowjobtemplatenode',
name='char_prompts',
field=models.JSONField(default=dict, null=True, blank=True),
field=awx.main.fields.JSONBlob(default=dict, blank=True),
),
migrations.AddField(
model_name='workflowjobtemplatenode',
@ -307,12 +307,12 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='job',
name='artifacts',
field=models.JSONField(default=dict, editable=False, null=True, blank=True),
field=awx.main.fields.JSONBlob(default=dict, editable=False, blank=True),
),
migrations.AddField(
model_name='workflowjobnode',
name='ancestor_artifacts',
field=models.JSONField(default=dict, editable=False, null=True, blank=True),
field=awx.main.fields.JSONBlob(default=dict, editable=False, blank=True),
),
# Job timeout settings
migrations.AddField(
@ -380,7 +380,9 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='project',
name='playbook_files',
field=models.JSONField(default=list, help_text='List of playbooks found in the project', verbose_name='Playbook Files', editable=False, blank=True),
field=awx.main.fields.JSONBlob(
default=list, help_text='List of playbooks found in the project', verbose_name='Playbook Files', editable=False, blank=True
),
),
# Job events to stdout
migrations.AddField(
@ -536,7 +538,7 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='workflowjob',
name='survey_passwords',
field=models.JSONField(default=dict, editable=False, null=True, blank=True),
field=awx.main.fields.JSONBlob(default=dict, editable=False, blank=True),
),
migrations.AddField(
model_name='workflowjobtemplate',
@ -546,7 +548,7 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='workflowjobtemplate',
name='survey_spec',
field=models.JSONField(default=dict, blank=True),
field=awx.main.fields.JSONBlob(default=dict, blank=True),
),
# JSON field changes
migrations.AlterField(
@ -557,12 +559,12 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name='job',
name='artifacts',
field=models.JSONField(default=dict, editable=False, null=True, blank=True),
field=awx.main.fields.JSONBlob(default=dict, editable=False, blank=True),
),
migrations.AlterField(
model_name='job',
name='survey_passwords',
field=models.JSONField(default=dict, editable=False, null=True, blank=True),
field=awx.main.fields.JSONBlob(default=dict, editable=False, blank=True),
),
migrations.AlterField(
model_name='jobevent',
@ -572,57 +574,59 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name='jobtemplate',
name='survey_spec',
field=models.JSONField(default=dict, blank=True),
field=awx.main.fields.JSONBlob(default=dict, blank=True),
),
migrations.AlterField(
model_name='notification',
name='body',
field=models.JSONField(default=dict, null=True, blank=True),
field=awx.main.fields.JSONBlob(default=dict, blank=True),
),
migrations.AlterField(
model_name='notificationtemplate',
name='notification_configuration',
field=models.JSONField(default=dict),
field=awx.main.fields.JSONBlob(default=dict),
),
migrations.AlterField(
model_name='project',
name='playbook_files',
field=models.JSONField(default=list, help_text='List of playbooks found in the project', verbose_name='Playbook Files', editable=False, blank=True),
field=awx.main.fields.JSONBlob(
default=list, help_text='List of playbooks found in the project', verbose_name='Playbook Files', editable=False, blank=True
),
),
migrations.AlterField(
model_name='schedule',
name='extra_data',
field=models.JSONField(default=dict, null=True, blank=True),
field=awx.main.fields.JSONBlob(default=dict, blank=True),
),
migrations.AlterField(
model_name='unifiedjob',
name='job_env',
field=models.JSONField(default=dict, editable=False, null=True, blank=True),
field=awx.main.fields.JSONBlob(default=dict, editable=False, blank=True),
),
migrations.AlterField(
model_name='workflowjob',
name='survey_passwords',
field=models.JSONField(default=dict, editable=False, null=True, blank=True),
field=awx.main.fields.JSONBlob(default=dict, editable=False, blank=True),
),
migrations.AlterField(
model_name='workflowjobnode',
name='ancestor_artifacts',
field=models.JSONField(default=dict, editable=False, null=True, blank=True),
field=awx.main.fields.JSONBlob(default=dict, editable=False, blank=True),
),
migrations.AlterField(
model_name='workflowjobnode',
name='char_prompts',
field=models.JSONField(default=dict, null=True, blank=True),
field=awx.main.fields.JSONBlob(default=dict, blank=True),
),
migrations.AlterField(
model_name='workflowjobtemplate',
name='survey_spec',
field=models.JSONField(default=dict, blank=True),
field=awx.main.fields.JSONBlob(default=dict, blank=True),
),
migrations.AlterField(
model_name='workflowjobtemplatenode',
name='char_prompts',
field=models.JSONField(default=dict, null=True, blank=True),
field=awx.main.fields.JSONBlob(default=dict, blank=True),
),
# Job Project Update
migrations.AddField(

View File

@ -175,7 +175,7 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='project',
name='inventory_files',
field=models.JSONField(
field=awx.main.fields.JSONBlob(
default=list,
help_text='Suggested list of content that could be Ansible inventory in the project',
verbose_name='Inventory Files',

View File

@ -1,7 +1,9 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
from django.db import migrations
import awx.main.fields
class Migration(migrations.Migration):
@ -14,6 +16,6 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='activitystream',
name='setting',
field=models.JSONField(default=dict, null=True, blank=True),
field=awx.main.fields.JSONBlob(default=dict, blank=True),
),
]

View File

@ -20,7 +20,7 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='schedule',
name='char_prompts',
field=models.JSONField(default=dict, null=True, blank=True),
field=awx.main.fields.JSONBlob(default=dict, blank=True),
),
migrations.AddField(
model_name='schedule',
@ -37,7 +37,7 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='schedule',
name='survey_passwords',
field=models.JSONField(default=dict, editable=False, null=True, blank=True),
field=awx.main.fields.JSONBlob(default=dict, editable=False, blank=True),
),
migrations.AddField(
model_name='workflowjobnode',
@ -47,12 +47,12 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='workflowjobnode',
name='extra_data',
field=models.JSONField(default=dict, null=True, blank=True),
field=awx.main.fields.JSONBlob(default=dict, blank=True),
),
migrations.AddField(
model_name='workflowjobnode',
name='survey_passwords',
field=models.JSONField(default=dict, editable=False, null=True, blank=True),
field=awx.main.fields.JSONBlob(default=dict, editable=False, blank=True),
),
migrations.AddField(
model_name='workflowjobtemplatenode',
@ -62,12 +62,12 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='workflowjobtemplatenode',
name='extra_data',
field=models.JSONField(default=dict, null=True, blank=True),
field=awx.main.fields.JSONBlob(default=dict, blank=True),
),
migrations.AddField(
model_name='workflowjobtemplatenode',
name='survey_passwords',
field=models.JSONField(default=dict, editable=False, null=True, blank=True),
field=awx.main.fields.JSONBlob(default=dict, editable=False, blank=True),
),
# Run data migration before removing the old credential field
migrations.RunPython(migration_utils.set_current_apps_for_migrations, migrations.RunPython.noop),
@ -85,9 +85,9 @@ class Migration(migrations.Migration):
name='JobLaunchConfig',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('extra_data', models.JSONField(blank=True, null=True, default=dict)),
('survey_passwords', models.JSONField(blank=True, null=True, default=dict, editable=False)),
('char_prompts', models.JSONField(blank=True, null=True, default=dict)),
('extra_data', awx.main.fields.JSONBlob(blank=True, default=dict)),
('survey_passwords', awx.main.fields.JSONBlob(blank=True, default=dict, editable=False)),
('char_prompts', awx.main.fields.JSONBlob(blank=True, default=dict)),
('credentials', models.ManyToManyField(related_name='joblaunchconfigs', to='main.Credential')),
(
'inventory',

View File

@ -1,8 +1,10 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from decimal import Decimal
from django.db import migrations, models
from decimal import Decimal
import awx.main.fields
class Migration(migrations.Migration):
@ -15,7 +17,7 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='instancegroup',
name='policy_instance_list',
field=models.JSONField(
field=awx.main.fields.JSONBlob(
default=list, help_text='List of exact-match Instances that will always be automatically assigned to this group', blank=True
),
),

View File

@ -2,7 +2,9 @@
# Generated by Django 1.11.11 on 2018-05-21 19:51
from __future__ import unicode_literals
from django.db import models, migrations
from django.db import migrations
import awx.main.fields
class Migration(migrations.Migration):
@ -15,6 +17,6 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='activitystream',
name='deleted_actor',
field=models.JSONField(null=True),
field=awx.main.fields.JSONBlob(null=True),
),
]

View File

@ -2,10 +2,11 @@
# Generated by Django 1.11.11 on 2018-09-27 19:50
from __future__ import unicode_literals
import awx.main.fields
from django.db import migrations, models
import django.db.models.deletion
import awx.main.fields
class Migration(migrations.Migration):
@ -17,7 +18,7 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='workflowjob',
name='char_prompts',
field=models.JSONField(blank=True, null=True, default=dict),
field=awx.main.fields.JSONBlob(blank=True, default=dict),
),
migrations.AddField(
model_name='workflowjob',

View File

@ -4,6 +4,7 @@ from __future__ import unicode_literals
from django.db import migrations, models
import awx.main.fields
import awx.main.models.notifications
@ -17,7 +18,7 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='notificationtemplate',
name='messages',
field=models.JSONField(
field=awx.main.fields.JSONBlob(
default=awx.main.models.notifications.NotificationTemplate.default_messages,
help_text='Optional custom messages for notification template.',
null=True,

View File

@ -24,7 +24,7 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='workflowjobtemplate',
name='char_prompts',
field=models.JSONField(blank=True, null=True, default=dict),
field=awx.main.fields.JSONBlob(blank=True, default=dict),
),
migrations.AlterField(
model_name='joblaunchconfig',

View File

@ -29,7 +29,7 @@ SQUASHED_30 = {
migrations.AddField(
model_name='job',
name='survey_passwords',
field=models.JSONField(default=dict, editable=False, null=True, blank=True),
field=awx.main.fields.JSONBlob(default=dict, editable=False, blank=True),
),
],
'0031_v302_migrate_survey_passwords': [

View File

@ -3,6 +3,7 @@
# AWX
from awx.api.versioning import reverse
from awx.main.fields import JSONBlob
from awx.main.models.base import accepts_json
# Django
@ -35,7 +36,7 @@ class ActivityStream(models.Model):
operation = models.CharField(max_length=13, choices=OPERATION_CHOICES)
timestamp = models.DateTimeField(auto_now_add=True)
changes = accepts_json(models.TextField(blank=True))
deleted_actor = models.JSONField(null=True)
deleted_actor = JSONBlob(null=True)
action_node = models.CharField(
blank=True,
default='',
@ -83,7 +84,7 @@ class ActivityStream(models.Model):
o_auth2_application = models.ManyToManyField("OAuth2Application", blank=True)
o_auth2_access_token = models.ManyToManyField("OAuth2AccessToken", blank=True)
setting = models.JSONField(default=dict, null=True, blank=True)
setting = JSONBlob(default=dict, blank=True)
def __str__(self):
operation = self.operation if 'operation' in self.__dict__ else '_delayed_'

View File

@ -18,6 +18,7 @@ from solo.models import SingletonModel
from awx import __version__ as awx_application_version
from awx.api.versioning import reverse
from awx.main.fields import JSONBlob
from awx.main.managers import InstanceManager, InstanceGroupManager, UUID_DEFAULT
from awx.main.constants import JOB_FOLDER_PREFIX
from awx.main.models.base import BaseModel, HasEditsMixin, prevent_search
@ -327,7 +328,7 @@ class InstanceGroup(HasPolicyEditsMixin, BaseModel, RelatedJobsMixin):
)
policy_instance_percentage = models.IntegerField(default=0, help_text=_("Percentage of Instances to automatically assign to this group"))
policy_instance_minimum = models.IntegerField(default=0, help_text=_("Static minimum number of Instances to automatically assign to this group"))
policy_instance_list = models.JSONField(
policy_instance_list = JSONBlob(
default=list, blank=True, help_text=_("List of exact-match Instances that will always be automatically assigned to this group")
)

View File

@ -44,7 +44,7 @@ from awx.main.models.notifications import (
JobNotificationMixin,
)
from awx.main.utils import parse_yaml_or_json, getattr_dne, NullablePromptPseudoField
from awx.main.fields import ImplicitRoleField, AskForField
from awx.main.fields import ImplicitRoleField, AskForField, JSONBlob
from awx.main.models.mixins import (
ResourceMixin,
SurveyJobTemplateMixin,
@ -546,9 +546,8 @@ class Job(UnifiedJob, JobOptions, SurveyJobMixin, JobNotificationMixin, TaskMana
editable=False,
through='JobHostSummary',
)
artifacts = models.JSONField(
artifacts = JSONBlob(
default=dict,
null=True,
blank=True,
editable=False,
)
@ -886,7 +885,7 @@ class LaunchTimeConfigBase(BaseModel):
)
# All standard fields are stored in this dictionary field
# This is a solution to the nullable CharField problem, specific to prompting
char_prompts = models.JSONField(default=dict, null=True, blank=True)
char_prompts = JSONBlob(default=dict, blank=True)
def prompts_dict(self, display=False):
data = {}
@ -939,12 +938,11 @@ class LaunchTimeConfig(LaunchTimeConfigBase):
abstract = True
# Special case prompting fields, even more special than the other ones
extra_data = models.JSONField(default=dict, null=True, blank=True)
extra_data = JSONBlob(default=dict, blank=True)
survey_passwords = prevent_search(
models.JSONField(
JSONBlob(
default=dict,
editable=False,
null=True,
blank=True,
)
)

View File

@ -24,7 +24,7 @@ from awx.main.utils import parse_yaml_or_json, get_custom_venv_choices, get_lice
from awx.main.utils.execution_environments import get_default_execution_environment
from awx.main.utils.encryption import decrypt_value, get_encryption_key, is_encrypted
from awx.main.utils.polymorphic import build_polymorphic_ctypes_map
from awx.main.fields import AskForField
from awx.main.fields import AskForField, JSONBlob
from awx.main.constants import ACTIVE_STATES
@ -103,7 +103,7 @@ class SurveyJobTemplateMixin(models.Model):
survey_enabled = models.BooleanField(
default=False,
)
survey_spec = prevent_search(models.JSONField(default=dict, blank=True))
survey_spec = prevent_search(JSONBlob(default=dict, blank=True))
ask_variables_on_launch = AskForField(blank=True, default=False, allows_field='extra_vars')
def survey_password_variables(self):
@ -365,10 +365,9 @@ class SurveyJobMixin(models.Model):
abstract = True
survey_passwords = prevent_search(
models.JSONField(
JSONBlob(
default=dict,
editable=False,
null=True,
blank=True,
)
)

View File

@ -17,6 +17,7 @@ from jinja2.exceptions import TemplateSyntaxError, UndefinedError, SecurityError
# AWX
from awx.api.versioning import reverse
from awx.main.fields import JSONBlob
from awx.main.models.base import CommonModelNameNotUnique, CreatedModifiedModel, prevent_search
from awx.main.utils import encrypt_field, decrypt_field, set_environ
from awx.main.notifications.email_backend import CustomEmailBackend
@ -69,12 +70,12 @@ class NotificationTemplate(CommonModelNameNotUnique):
choices=NOTIFICATION_TYPE_CHOICES,
)
notification_configuration = prevent_search(models.JSONField(default=dict))
notification_configuration = prevent_search(JSONBlob(default=dict))
def default_messages():
return {'started': None, 'success': None, 'error': None, 'workflow_approval': None}
messages = models.JSONField(null=True, blank=True, default=default_messages, help_text=_('Optional custom messages for notification template.'))
messages = JSONBlob(null=True, blank=True, default=default_messages, help_text=_('Optional custom messages for notification template.'))
def has_message(self, condition):
potential_template = self.messages.get(condition, {})
@ -236,7 +237,7 @@ class Notification(CreatedModifiedModel):
default='',
editable=False,
)
body = models.JSONField(default=dict, null=True, blank=True)
body = JSONBlob(default=dict, blank=True)
def get_absolute_url(self, request=None):
return reverse('api:notification_detail', kwargs={'pk': self.pk}, request=request)

View File

@ -33,7 +33,7 @@ from awx.main.models.mixins import ResourceMixin, TaskManagerProjectUpdateMixin,
from awx.main.utils import update_scm_url, polymorphic
from awx.main.utils.ansible import skip_directory, could_be_inventory, could_be_playbook
from awx.main.utils.execution_environments import get_control_plane_execution_environment
from awx.main.fields import ImplicitRoleField
from awx.main.fields import ImplicitRoleField, JSONBlob
from awx.main.models.rbac import (
ROLE_SINGLETON_SYSTEM_ADMINISTRATOR,
ROLE_SINGLETON_SYSTEM_AUDITOR,
@ -293,7 +293,7 @@ class Project(UnifiedJobTemplate, ProjectOptions, ResourceMixin, CustomVirtualEn
help_text=_('The last revision fetched by a project update'),
)
playbook_files = models.JSONField(
playbook_files = JSONBlob(
default=list,
blank=True,
editable=False,
@ -301,7 +301,7 @@ class Project(UnifiedJobTemplate, ProjectOptions, ResourceMixin, CustomVirtualEn
help_text=_('List of playbooks found in the project'),
)
inventory_files = models.JSONField(
inventory_files = JSONBlob(
default=list,
blank=True,
editable=False,

View File

@ -54,7 +54,7 @@ from awx.main.utils import polymorphic
from awx.main.constants import ACTIVE_STATES, CAN_CANCEL
from awx.main.redact import UriCleaner, REPLACE_STR
from awx.main.consumers import emit_channel_notification
from awx.main.fields import AskForField, OrderedManyToManyField
from awx.main.fields import AskForField, OrderedManyToManyField, JSONBlob
__all__ = ['UnifiedJobTemplate', 'UnifiedJob', 'StdoutMaxBytesExceeded']
@ -653,9 +653,8 @@ class UnifiedJob(
editable=False,
)
job_env = prevent_search(
models.JSONField(
JSONBlob(
default=dict,
null=True,
blank=True,
editable=False,
)

View File

@ -28,7 +28,7 @@ from awx.main.models import prevent_search, accepts_json, UnifiedJobTemplate, Un
from awx.main.models.notifications import NotificationTemplate, JobNotificationMixin
from awx.main.models.base import CreatedModifiedModel, VarsDictProperty
from awx.main.models.rbac import ROLE_SINGLETON_SYSTEM_ADMINISTRATOR, ROLE_SINGLETON_SYSTEM_AUDITOR
from awx.main.fields import ImplicitRoleField, AskForField
from awx.main.fields import ImplicitRoleField, AskForField, JSONBlob
from awx.main.models.mixins import (
ResourceMixin,
SurveyJobTemplateMixin,
@ -231,9 +231,8 @@ class WorkflowJobNode(WorkflowNodeBase):
default=None,
on_delete=models.CASCADE,
)
ancestor_artifacts = models.JSONField(
ancestor_artifacts = JSONBlob(
default=dict,
null=True,
blank=True,
editable=False,
)