mirror of
https://github.com/ansible/awx.git
synced 2026-01-15 03:40:42 -03:30
Add WorkflowJob.instance_groups and distinguish from char_prompts
This removes a loop that ran on import the loop was giving the wrong behavior and it initialized too many fields as char_prompts fields With this, we will now enumerate the char_prompts type fields manually
This commit is contained in:
parent
697193d3d6
commit
68e11d2b81
@ -214,4 +214,24 @@ class Migration(migrations.Migration):
|
||||
to='main.InstanceGroup',
|
||||
),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='WorkflowJobInstanceGroupMembership',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('position', models.PositiveIntegerField(db_index=True, default=None, null=True)),
|
||||
('instancegroup', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='main.instancegroup')),
|
||||
('workflowjobnode', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='main.workflowjob')),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='workflowjob',
|
||||
name='instance_groups',
|
||||
field=awx.main.fields.OrderedManyToManyField(
|
||||
blank=True,
|
||||
editable=False,
|
||||
related_name='workflow_job_instance_groups',
|
||||
through='main.WorkflowJobInstanceGroupMembership',
|
||||
to='main.InstanceGroup',
|
||||
),
|
||||
),
|
||||
]
|
||||
|
||||
@ -489,3 +489,14 @@ class WorkflowJobNodeBaseInstanceGroupMembership(models.Model):
|
||||
default=None,
|
||||
db_index=True,
|
||||
)
|
||||
|
||||
|
||||
class WorkflowJobInstanceGroupMembership(models.Model):
|
||||
|
||||
workflowjobnode = models.ForeignKey('WorkflowJob', on_delete=models.CASCADE)
|
||||
instancegroup = models.ForeignKey('InstanceGroup', on_delete=models.CASCADE)
|
||||
position = models.PositiveIntegerField(
|
||||
null=True,
|
||||
default=None,
|
||||
db_index=True,
|
||||
)
|
||||
|
||||
@ -943,6 +943,28 @@ class LaunchTimeConfigBase(BaseModel):
|
||||
# This is a solution to the nullable CharField problem, specific to prompting
|
||||
char_prompts = JSONBlob(default=dict, blank=True)
|
||||
|
||||
# Define fields that are not really fields, but alias to char_prompts lookups
|
||||
limit = NullablePromptPseudoField('limit')
|
||||
scm_branch = NullablePromptPseudoField('scm_branch')
|
||||
job_tags = NullablePromptPseudoField('job_tags')
|
||||
skip_tags = NullablePromptPseudoField('skip_tags')
|
||||
diff_mode = NullablePromptPseudoField('diff_mode')
|
||||
job_type = NullablePromptPseudoField('job_type')
|
||||
verbosity = NullablePromptPseudoField('verbosity')
|
||||
forks = NullablePromptPseudoField('forks')
|
||||
job_slice_count = NullablePromptPseudoField('job_slice_count')
|
||||
timeout = NullablePromptPseudoField('timeout')
|
||||
|
||||
# NOTE: additional fields are assumed to exist but must be defined in subclasses
|
||||
# due to technical limitations
|
||||
SUBCLASS_FIELDS = (
|
||||
'instance_groups', # needs a through model defined
|
||||
'extra_vars', # alternates between extra_vars and extra_data
|
||||
'credentials', # already a unified job and unified JT field
|
||||
'labels', # already a unified job and unified JT field
|
||||
'execution_environment', # already a unified job and unified JT field
|
||||
)
|
||||
|
||||
def prompts_dict(self, display=False):
|
||||
data = {}
|
||||
# Some types may have different prompts, but always subset of JT prompts
|
||||
@ -977,15 +999,6 @@ class LaunchTimeConfigBase(BaseModel):
|
||||
return data
|
||||
|
||||
|
||||
for field_name in JobTemplate.get_ask_mapping().keys():
|
||||
if field_name == 'extra_vars':
|
||||
continue
|
||||
try:
|
||||
LaunchTimeConfigBase._meta.get_field(field_name)
|
||||
except FieldDoesNotExist:
|
||||
setattr(LaunchTimeConfigBase, field_name, NullablePromptPseudoField(field_name))
|
||||
|
||||
|
||||
class LaunchTimeConfig(LaunchTimeConfigBase):
|
||||
"""
|
||||
Common model for all objects that save details of a saved launch config
|
||||
@ -1004,12 +1017,9 @@ class LaunchTimeConfig(LaunchTimeConfigBase):
|
||||
blank=True,
|
||||
)
|
||||
)
|
||||
# Credentials needed for non-unified job / unified JT models
|
||||
# Fields needed for non-unified job / unified JT models, because they are defined on unified models
|
||||
credentials = models.ManyToManyField('Credential', related_name='%(class)ss')
|
||||
|
||||
# Labels needed for non-unified job / unified JT models
|
||||
labels = models.ManyToManyField('Label', related_name='%(class)s_labels')
|
||||
|
||||
execution_environment = models.ForeignKey(
|
||||
'ExecutionEnvironment', null=True, blank=True, default=None, on_delete=polymorphic.SET_NULL, related_name='%(class)s_as_prompt'
|
||||
)
|
||||
|
||||
@ -384,6 +384,10 @@ class WorkflowJobOptions(LaunchTimeConfigBase):
|
||||
)
|
||||
)
|
||||
)
|
||||
# Workflow jobs are used for sliced jobs, and thus, must be a conduit for any JT prompts
|
||||
instance_groups = OrderedManyToManyField(
|
||||
'InstanceGroup', related_name='workflow_job_instance_groups', blank=True, editable=False, through='WorkflowJobInstanceGroupMembership'
|
||||
)
|
||||
allow_simultaneous = models.BooleanField(default=False)
|
||||
|
||||
extra_vars_dict = VarsDictProperty('extra_vars', True)
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import pytest
|
||||
|
||||
# AWX
|
||||
from awx.main.models import JobTemplate, JobLaunchConfig, ExecutionEnvironment
|
||||
from awx.main.models.jobs import JobTemplate, JobLaunchConfig, LaunchTimeConfigBase
|
||||
from awx.main.models.execution_environments import ExecutionEnvironment
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@ -75,3 +76,28 @@ class TestConfigReversibility:
|
||||
print(prompts)
|
||||
print(config.prompts_dict())
|
||||
assert config.prompts_dict() == prompts
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestLaunchConfigModels:
|
||||
def get_concrete_subclasses(self, cls):
|
||||
r = []
|
||||
for c in cls.__subclasses__():
|
||||
if c._meta.abstract:
|
||||
r.extend(self.get_concrete_subclasses(c))
|
||||
else:
|
||||
r.append(c)
|
||||
return r
|
||||
|
||||
def test_non_job_config_complete(self):
|
||||
"""This performs model validation which replaces code that used run on import."""
|
||||
for field_name in JobTemplate.get_ask_mapping().keys():
|
||||
if field_name in LaunchTimeConfigBase.SUBCLASS_FIELDS:
|
||||
assert not hasattr(LaunchTimeConfigBase, field_name)
|
||||
else:
|
||||
assert hasattr(LaunchTimeConfigBase, field_name)
|
||||
|
||||
def test_subclass_fields_complete(self):
|
||||
for cls in self.get_concrete_subclasses(LaunchTimeConfigBase):
|
||||
for field_name in LaunchTimeConfigBase.SUBCLASS_FIELDS:
|
||||
assert hasattr(cls, field_name)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user