mirror of
https://github.com/ansible/awx.git
synced 2026-03-22 11:25:08 -02:30
adding prompt-to-launch field on Labels field in Workflow Templates; with necessary UI and testing changes
Co-authored-by: Keith Grant <keithjgrant@gmail.com>
This commit is contained in:
committed by
Alan Rominger
parent
4e665ca77f
commit
663ef2cc64
@@ -3199,7 +3199,7 @@ class JobRelaunchSerializer(BaseSerializer):
|
|||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
|
|
||||||
class JobCreateScheduleSerializer(BaseSerializer):
|
class JobCreateScheduleSerializer(LabelsListMixin, BaseSerializer):
|
||||||
|
|
||||||
can_schedule = serializers.SerializerMethodField()
|
can_schedule = serializers.SerializerMethodField()
|
||||||
prompts = serializers.SerializerMethodField()
|
prompts = serializers.SerializerMethodField()
|
||||||
@@ -3230,6 +3230,8 @@ class JobCreateScheduleSerializer(BaseSerializer):
|
|||||||
if 'credentials' in ret:
|
if 'credentials' in ret:
|
||||||
all_creds = [self._summarize('credential', cred) for cred in ret['credentials']]
|
all_creds = [self._summarize('credential', cred) for cred in ret['credentials']]
|
||||||
ret['credentials'] = all_creds
|
ret['credentials'] = all_creds
|
||||||
|
if 'labels' in ret:
|
||||||
|
ret['labels'] = self._summary_field_labels(obj)
|
||||||
return ret
|
return ret
|
||||||
except JobLaunchConfig.DoesNotExist:
|
except JobLaunchConfig.DoesNotExist:
|
||||||
return {'all': _('Unknown, job may have been ran before launch configurations were saved.')}
|
return {'all': _('Unknown, job may have been ran before launch configurations were saved.')}
|
||||||
@@ -3402,6 +3404,9 @@ class WorkflowJobTemplateSerializer(JobTemplateMixin, LabelsListMixin, UnifiedJo
|
|||||||
limit = serializers.CharField(allow_blank=True, allow_null=True, required=False, default=None)
|
limit = serializers.CharField(allow_blank=True, allow_null=True, required=False, default=None)
|
||||||
scm_branch = serializers.CharField(allow_blank=True, allow_null=True, required=False, default=None)
|
scm_branch = serializers.CharField(allow_blank=True, allow_null=True, required=False, default=None)
|
||||||
|
|
||||||
|
skip_tags = serializers.CharField(allow_blank=True, allow_null=True, required=False, default=None)
|
||||||
|
job_tags = serializers.CharField(allow_blank=True, allow_null=True, required=False, default=None)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = WorkflowJobTemplate
|
model = WorkflowJobTemplate
|
||||||
fields = (
|
fields = (
|
||||||
@@ -3420,6 +3425,11 @@ class WorkflowJobTemplateSerializer(JobTemplateMixin, LabelsListMixin, UnifiedJo
|
|||||||
'webhook_service',
|
'webhook_service',
|
||||||
'webhook_credential',
|
'webhook_credential',
|
||||||
'-execution_environment',
|
'-execution_environment',
|
||||||
|
'ask_labels_on_launch',
|
||||||
|
'ask_skip_tags_on_launch',
|
||||||
|
'ask_tags_on_launch',
|
||||||
|
'skip_tags',
|
||||||
|
'job_tags',
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_related(self, obj):
|
def get_related(self, obj):
|
||||||
@@ -3458,12 +3468,13 @@ class WorkflowJobTemplateSerializer(JobTemplateMixin, LabelsListMixin, UnifiedJo
|
|||||||
def validate_extra_vars(self, value):
|
def validate_extra_vars(self, value):
|
||||||
return vars_validate_or_raise(value)
|
return vars_validate_or_raise(value)
|
||||||
|
|
||||||
|
# posting
|
||||||
def validate(self, attrs):
|
def validate(self, attrs):
|
||||||
attrs = super(WorkflowJobTemplateSerializer, self).validate(attrs)
|
attrs = super(WorkflowJobTemplateSerializer, self).validate(attrs)
|
||||||
|
|
||||||
# process char_prompts, these are not direct fields on the model
|
# process char_prompts, these are not direct fields on the model
|
||||||
mock_obj = self.Meta.model()
|
mock_obj = self.Meta.model()
|
||||||
for field_name in ('scm_branch', 'limit'):
|
for field_name in ('scm_branch', 'limit', 'skip_tags', 'job_tags'):
|
||||||
if field_name in attrs:
|
if field_name in attrs:
|
||||||
setattr(mock_obj, field_name, attrs[field_name])
|
setattr(mock_obj, field_name, attrs[field_name])
|
||||||
attrs.pop(field_name)
|
attrs.pop(field_name)
|
||||||
@@ -3489,6 +3500,9 @@ class WorkflowJobSerializer(LabelsListMixin, UnifiedJobSerializer):
|
|||||||
limit = serializers.CharField(allow_blank=True, allow_null=True, required=False, default=None)
|
limit = serializers.CharField(allow_blank=True, allow_null=True, required=False, default=None)
|
||||||
scm_branch = serializers.CharField(allow_blank=True, allow_null=True, required=False, default=None)
|
scm_branch = serializers.CharField(allow_blank=True, allow_null=True, required=False, default=None)
|
||||||
|
|
||||||
|
skip_tags = serializers.CharField(allow_blank=True, allow_null=True, required=False, default=None)
|
||||||
|
job_tags = serializers.CharField(allow_blank=True, allow_null=True, required=False, default=None)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = WorkflowJob
|
model = WorkflowJob
|
||||||
fields = (
|
fields = (
|
||||||
@@ -3508,6 +3522,8 @@ class WorkflowJobSerializer(LabelsListMixin, UnifiedJobSerializer):
|
|||||||
'webhook_service',
|
'webhook_service',
|
||||||
'webhook_credential',
|
'webhook_credential',
|
||||||
'webhook_guid',
|
'webhook_guid',
|
||||||
|
'skip_tags',
|
||||||
|
'job_tags',
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_related(self, obj):
|
def get_related(self, obj):
|
||||||
@@ -4333,6 +4349,10 @@ class WorkflowJobLaunchSerializer(BaseSerializer):
|
|||||||
scm_branch = serializers.CharField(required=False, write_only=True, allow_blank=True)
|
scm_branch = serializers.CharField(required=False, write_only=True, allow_blank=True)
|
||||||
workflow_job_template_data = serializers.SerializerMethodField()
|
workflow_job_template_data = serializers.SerializerMethodField()
|
||||||
|
|
||||||
|
labels = serializers.PrimaryKeyRelatedField(many=True, queryset=Label.objects.all(), required=False, write_only=True)
|
||||||
|
skip_tags = serializers.CharField(required=False, write_only=True, allow_blank=True)
|
||||||
|
job_tags = serializers.CharField(required=False, write_only=True, allow_blank=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = WorkflowJobTemplate
|
model = WorkflowJobTemplate
|
||||||
fields = (
|
fields = (
|
||||||
@@ -4352,8 +4372,22 @@ class WorkflowJobLaunchSerializer(BaseSerializer):
|
|||||||
'workflow_job_template_data',
|
'workflow_job_template_data',
|
||||||
'survey_enabled',
|
'survey_enabled',
|
||||||
'ask_variables_on_launch',
|
'ask_variables_on_launch',
|
||||||
|
'ask_labels_on_launch',
|
||||||
|
'labels',
|
||||||
|
'ask_skip_tags_on_launch',
|
||||||
|
'ask_tags_on_launch',
|
||||||
|
'skip_tags',
|
||||||
|
'job_tags',
|
||||||
|
)
|
||||||
|
read_only_fields = (
|
||||||
|
'ask_inventory_on_launch',
|
||||||
|
'ask_variables_on_launch',
|
||||||
|
'ask_skip_tags_on_launch',
|
||||||
|
'ask_labels_on_launch',
|
||||||
|
'ask_limit_on_launch',
|
||||||
|
'ask_scm_branch_on_launch',
|
||||||
|
'ask_tags_on_launch',
|
||||||
)
|
)
|
||||||
read_only_fields = ('ask_inventory_on_launch', 'ask_variables_on_launch')
|
|
||||||
|
|
||||||
def get_survey_enabled(self, obj):
|
def get_survey_enabled(self, obj):
|
||||||
if obj:
|
if obj:
|
||||||
@@ -4361,10 +4395,15 @@ class WorkflowJobLaunchSerializer(BaseSerializer):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def get_defaults(self, obj):
|
def get_defaults(self, obj):
|
||||||
|
|
||||||
defaults_dict = {}
|
defaults_dict = {}
|
||||||
for field_name in WorkflowJobTemplate.get_ask_mapping().keys():
|
for field_name in WorkflowJobTemplate.get_ask_mapping().keys():
|
||||||
if field_name == 'inventory':
|
if field_name == 'inventory':
|
||||||
defaults_dict[field_name] = dict(name=getattrd(obj, '%s.name' % field_name, None), id=getattrd(obj, '%s.pk' % field_name, None))
|
defaults_dict[field_name] = dict(name=getattrd(obj, '%s.name' % field_name, None), id=getattrd(obj, '%s.pk' % field_name, None))
|
||||||
|
elif field_name == 'labels':
|
||||||
|
for label in obj.labels.all():
|
||||||
|
label_dict = {"id": label.id, "name": label.name}
|
||||||
|
defaults_dict.setdefault(field_name, []).append(label_dict)
|
||||||
else:
|
else:
|
||||||
defaults_dict[field_name] = getattr(obj, field_name)
|
defaults_dict[field_name] = getattr(obj, field_name)
|
||||||
return defaults_dict
|
return defaults_dict
|
||||||
@@ -4373,6 +4412,7 @@ class WorkflowJobLaunchSerializer(BaseSerializer):
|
|||||||
return dict(name=obj.name, id=obj.id, description=obj.description)
|
return dict(name=obj.name, id=obj.id, description=obj.description)
|
||||||
|
|
||||||
def validate(self, attrs):
|
def validate(self, attrs):
|
||||||
|
|
||||||
template = self.instance
|
template = self.instance
|
||||||
|
|
||||||
accepted, rejected, errors = template._accept_or_ignore_job_kwargs(**attrs)
|
accepted, rejected, errors = template._accept_or_ignore_job_kwargs(**attrs)
|
||||||
@@ -4390,6 +4430,7 @@ class WorkflowJobLaunchSerializer(BaseSerializer):
|
|||||||
WFJT_inventory = template.inventory
|
WFJT_inventory = template.inventory
|
||||||
WFJT_limit = template.limit
|
WFJT_limit = template.limit
|
||||||
WFJT_scm_branch = template.scm_branch
|
WFJT_scm_branch = template.scm_branch
|
||||||
|
|
||||||
super(WorkflowJobLaunchSerializer, self).validate(attrs)
|
super(WorkflowJobLaunchSerializer, self).validate(attrs)
|
||||||
template.extra_vars = WFJT_extra_vars
|
template.extra_vars = WFJT_extra_vars
|
||||||
template.inventory = WFJT_inventory
|
template.inventory = WFJT_inventory
|
||||||
|
|||||||
@@ -3197,13 +3197,17 @@ class WorkflowJobTemplateLaunch(RetrieveAPIView):
|
|||||||
data['extra_vars'] = extra_vars
|
data['extra_vars'] = extra_vars
|
||||||
modified_ask_mapping = models.WorkflowJobTemplate.get_ask_mapping()
|
modified_ask_mapping = models.WorkflowJobTemplate.get_ask_mapping()
|
||||||
modified_ask_mapping.pop('extra_vars')
|
modified_ask_mapping.pop('extra_vars')
|
||||||
for field_name, ask_field_name in obj.get_ask_mapping().items():
|
|
||||||
|
for field, ask_field_name in modified_ask_mapping.items():
|
||||||
if not getattr(obj, ask_field_name):
|
if not getattr(obj, ask_field_name):
|
||||||
data.pop(field_name, None)
|
data.pop(field, None)
|
||||||
elif field_name == 'inventory':
|
elif isinstance(getattr(obj.__class__, field).field, ForeignKey):
|
||||||
data[field_name] = getattrd(obj, "%s.%s" % (field_name, 'id'), None)
|
data[field] = getattrd(obj, "%s.%s" % (field, 'id'), None)
|
||||||
|
elif isinstance(getattr(obj.__class__, field).field, ManyToManyField):
|
||||||
|
data[field] = [item.id for item in getattr(obj, field).all()]
|
||||||
else:
|
else:
|
||||||
data[field_name] = getattr(obj, field_name)
|
data[field] = getattr(obj, field)
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
|
|||||||
@@ -107,4 +107,20 @@ class Migration(migrations.Migration):
|
|||||||
blank=True, editable=False, related_name='joblaunchconfigs', through='main.JobLaunchConfigInstanceGroupMembership', to='main.InstanceGroup'
|
blank=True, editable=False, related_name='joblaunchconfigs', through='main.JobLaunchConfigInstanceGroupMembership', to='main.InstanceGroup'
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
# added WFJT prompts
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='workflowjobtemplate',
|
||||||
|
name='ask_labels_on_launch',
|
||||||
|
field=awx.main.fields.AskForField(blank=True, default=False),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='workflowjobtemplate',
|
||||||
|
name='ask_skip_tags_on_launch',
|
||||||
|
field=awx.main.fields.AskForField(blank=True, default=False),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='workflowjobtemplate',
|
||||||
|
name='ask_tags_on_launch',
|
||||||
|
field=awx.main.fields.AskForField(blank=True, default=False),
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -227,15 +227,6 @@ class JobTemplate(UnifiedJobTemplate, JobOptions, SurveyJobTemplateMixin, Resour
|
|||||||
blank=True,
|
blank=True,
|
||||||
default=False,
|
default=False,
|
||||||
)
|
)
|
||||||
ask_limit_on_launch = AskForField(
|
|
||||||
blank=True,
|
|
||||||
default=False,
|
|
||||||
)
|
|
||||||
ask_tags_on_launch = AskForField(blank=True, default=False, allows_field='job_tags')
|
|
||||||
ask_skip_tags_on_launch = AskForField(
|
|
||||||
blank=True,
|
|
||||||
default=False,
|
|
||||||
)
|
|
||||||
ask_job_type_on_launch = AskForField(
|
ask_job_type_on_launch = AskForField(
|
||||||
blank=True,
|
blank=True,
|
||||||
default=False,
|
default=False,
|
||||||
@@ -244,20 +235,11 @@ class JobTemplate(UnifiedJobTemplate, JobOptions, SurveyJobTemplateMixin, Resour
|
|||||||
blank=True,
|
blank=True,
|
||||||
default=False,
|
default=False,
|
||||||
)
|
)
|
||||||
ask_inventory_on_launch = AskForField(
|
|
||||||
blank=True,
|
|
||||||
default=False,
|
|
||||||
)
|
|
||||||
ask_credential_on_launch = AskForField(blank=True, default=False, allows_field='credentials')
|
ask_credential_on_launch = AskForField(blank=True, default=False, allows_field='credentials')
|
||||||
ask_scm_branch_on_launch = AskForField(blank=True, default=False, allows_field='scm_branch')
|
|
||||||
ask_execution_environment_on_launch = AskForField(
|
ask_execution_environment_on_launch = AskForField(
|
||||||
blank=True,
|
blank=True,
|
||||||
default=False,
|
default=False,
|
||||||
)
|
)
|
||||||
ask_labels_on_launch = AskForField(
|
|
||||||
blank=True,
|
|
||||||
default=False,
|
|
||||||
)
|
|
||||||
ask_forks_on_launch = AskForField(
|
ask_forks_on_launch = AskForField(
|
||||||
blank=True,
|
blank=True,
|
||||||
default=False,
|
default=False,
|
||||||
|
|||||||
@@ -104,6 +104,33 @@ class SurveyJobTemplateMixin(models.Model):
|
|||||||
default=False,
|
default=False,
|
||||||
)
|
)
|
||||||
survey_spec = prevent_search(JSONBlob(default=dict, blank=True))
|
survey_spec = prevent_search(JSONBlob(default=dict, blank=True))
|
||||||
|
|
||||||
|
ask_inventory_on_launch = AskForField(
|
||||||
|
blank=True,
|
||||||
|
default=False,
|
||||||
|
)
|
||||||
|
ask_limit_on_launch = AskForField(
|
||||||
|
blank=True,
|
||||||
|
default=False,
|
||||||
|
)
|
||||||
|
ask_scm_branch_on_launch = AskForField(
|
||||||
|
blank=True,
|
||||||
|
default=False,
|
||||||
|
allows_field='scm_branch',
|
||||||
|
)
|
||||||
|
ask_labels_on_launch = AskForField(
|
||||||
|
blank=True,
|
||||||
|
default=False,
|
||||||
|
)
|
||||||
|
ask_tags_on_launch = AskForField(
|
||||||
|
blank=True,
|
||||||
|
default=False,
|
||||||
|
allows_field='job_tags',
|
||||||
|
)
|
||||||
|
ask_skip_tags_on_launch = AskForField(
|
||||||
|
blank=True,
|
||||||
|
default=False,
|
||||||
|
)
|
||||||
ask_variables_on_launch = AskForField(blank=True, default=False, allows_field='extra_vars')
|
ask_variables_on_launch = AskForField(blank=True, default=False, allows_field='extra_vars')
|
||||||
|
|
||||||
def survey_password_variables(self):
|
def survey_password_variables(self):
|
||||||
|
|||||||
@@ -422,6 +422,7 @@ class UnifiedJobTemplate(PolymorphicModel, CommonModelNameNotUnique, ExecutionEn
|
|||||||
if unified_job.__class__ in activity_stream_registrar.models:
|
if unified_job.__class__ in activity_stream_registrar.models:
|
||||||
activity_stream_create(None, unified_job, True)
|
activity_stream_create(None, unified_job, True)
|
||||||
unified_job.log_lifecycle("created")
|
unified_job.log_lifecycle("created")
|
||||||
|
|
||||||
return unified_job
|
return unified_job
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ from awx.main.models import prevent_search, accepts_json, UnifiedJobTemplate, Un
|
|||||||
from awx.main.models.notifications import NotificationTemplate, JobNotificationMixin
|
from awx.main.models.notifications import NotificationTemplate, JobNotificationMixin
|
||||||
from awx.main.models.base import CreatedModifiedModel, VarsDictProperty
|
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.models.rbac import ROLE_SINGLETON_SYSTEM_ADMINISTRATOR, ROLE_SINGLETON_SYSTEM_AUDITOR
|
||||||
from awx.main.fields import ImplicitRoleField, AskForField, JSONBlob
|
from awx.main.fields import ImplicitRoleField, JSONBlob
|
||||||
from awx.main.models.mixins import (
|
from awx.main.models.mixins import (
|
||||||
ResourceMixin,
|
ResourceMixin,
|
||||||
SurveyJobTemplateMixin,
|
SurveyJobTemplateMixin,
|
||||||
@@ -385,7 +385,7 @@ class WorkflowJobOptions(LaunchTimeConfigBase):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def _get_unified_job_field_names(cls):
|
def _get_unified_job_field_names(cls):
|
||||||
r = set(f.name for f in WorkflowJobOptions._meta.fields) | set(
|
r = set(f.name for f in WorkflowJobOptions._meta.fields) | set(
|
||||||
['name', 'description', 'organization', 'survey_passwords', 'labels', 'limit', 'scm_branch']
|
['name', 'description', 'organization', 'survey_passwords', 'labels', 'limit', 'scm_branch', 'job_tags', 'skip_tags']
|
||||||
)
|
)
|
||||||
r.remove('char_prompts') # needed due to copying launch config to launch config
|
r.remove('char_prompts') # needed due to copying launch config to launch config
|
||||||
return r
|
return r
|
||||||
@@ -425,26 +425,28 @@ class WorkflowJobOptions(LaunchTimeConfigBase):
|
|||||||
class WorkflowJobTemplate(UnifiedJobTemplate, WorkflowJobOptions, SurveyJobTemplateMixin, ResourceMixin, RelatedJobsMixin, WebhookTemplateMixin):
|
class WorkflowJobTemplate(UnifiedJobTemplate, WorkflowJobOptions, SurveyJobTemplateMixin, ResourceMixin, RelatedJobsMixin, WebhookTemplateMixin):
|
||||||
|
|
||||||
SOFT_UNIQUE_TOGETHER = [('polymorphic_ctype', 'name', 'organization')]
|
SOFT_UNIQUE_TOGETHER = [('polymorphic_ctype', 'name', 'organization')]
|
||||||
FIELDS_TO_PRESERVE_AT_COPY = ['labels', 'organization', 'instance_groups', 'workflow_job_template_nodes', 'credentials', 'survey_spec']
|
FIELDS_TO_PRESERVE_AT_COPY = [
|
||||||
|
'labels',
|
||||||
|
'organization',
|
||||||
|
'instance_groups',
|
||||||
|
'workflow_job_template_nodes',
|
||||||
|
'credentials',
|
||||||
|
'survey_spec',
|
||||||
|
'skip_tags',
|
||||||
|
'job_tags',
|
||||||
|
]
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
app_label = 'main'
|
app_label = 'main'
|
||||||
|
|
||||||
ask_inventory_on_launch = AskForField(
|
notification_templates_approvals = models.ManyToManyField(
|
||||||
|
"NotificationTemplate",
|
||||||
blank=True,
|
blank=True,
|
||||||
default=False,
|
related_name='%(class)s_notification_templates_for_approvals',
|
||||||
)
|
)
|
||||||
ask_limit_on_launch = AskForField(
|
admin_role = ImplicitRoleField(
|
||||||
blank=True,
|
parent_role=['singleton:' + ROLE_SINGLETON_SYSTEM_ADMINISTRATOR, 'organization.workflow_admin_role'],
|
||||||
default=False,
|
|
||||||
)
|
)
|
||||||
ask_scm_branch_on_launch = AskForField(
|
|
||||||
blank=True,
|
|
||||||
default=False,
|
|
||||||
)
|
|
||||||
notification_templates_approvals = models.ManyToManyField("NotificationTemplate", blank=True, related_name='%(class)s_notification_templates_for_approvals')
|
|
||||||
|
|
||||||
admin_role = ImplicitRoleField(parent_role=['singleton:' + ROLE_SINGLETON_SYSTEM_ADMINISTRATOR, 'organization.workflow_admin_role'])
|
|
||||||
execute_role = ImplicitRoleField(
|
execute_role = ImplicitRoleField(
|
||||||
parent_role=[
|
parent_role=[
|
||||||
'admin_role',
|
'admin_role',
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ def mk_workflow_job_template(name, extra_vars='', spec=None, organization=None,
|
|||||||
if extra_vars:
|
if extra_vars:
|
||||||
extra_vars = json.dumps(extra_vars)
|
extra_vars = json.dumps(extra_vars)
|
||||||
|
|
||||||
wfjt = WorkflowJobTemplate(name=name, extra_vars=extra_vars, organization=organization, webhook_service=webhook_service)
|
wfjt = WorkflowJobTemplate.objects.create(name=name, extra_vars=extra_vars, organization=organization, webhook_service=webhook_service)
|
||||||
|
|
||||||
if spec:
|
if spec:
|
||||||
wfjt.survey_spec = spec
|
wfjt.survey_spec = spec
|
||||||
|
|||||||
@@ -706,7 +706,7 @@ def jt_linked(organization, project, inventory, machine_credential, credential,
|
|||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def workflow_job_template(organization):
|
def workflow_job_template(organization):
|
||||||
wjt = WorkflowJobTemplate(name='test-workflow_job_template', organization=organization)
|
wjt = WorkflowJobTemplate.objects.create(name='test-workflow_job_template', organization=organization)
|
||||||
wjt.save()
|
wjt.save()
|
||||||
|
|
||||||
return wjt
|
return wjt
|
||||||
|
|||||||
@@ -287,12 +287,25 @@ class TestWorkflowJobTemplatePrompts:
|
|||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def wfjt_prompts(self):
|
def wfjt_prompts(self):
|
||||||
return WorkflowJobTemplate.objects.create(
|
return WorkflowJobTemplate.objects.create(
|
||||||
ask_inventory_on_launch=True, ask_variables_on_launch=True, ask_limit_on_launch=True, ask_scm_branch_on_launch=True
|
ask_variables_on_launch=True,
|
||||||
|
ask_inventory_on_launch=True,
|
||||||
|
ask_tags_on_launch=True,
|
||||||
|
ask_labels_on_launch=True,
|
||||||
|
ask_limit_on_launch=True,
|
||||||
|
ask_scm_branch_on_launch=True,
|
||||||
|
ask_skip_tags_on_launch=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def prompts_data(self, inventory):
|
def prompts_data(self, inventory):
|
||||||
return dict(inventory=inventory, extra_vars={'foo': 'bar'}, limit='webservers', scm_branch='release-3.3')
|
return dict(
|
||||||
|
inventory=inventory,
|
||||||
|
extra_vars={'foo': 'bar'},
|
||||||
|
limit='webservers',
|
||||||
|
scm_branch='release-3.3',
|
||||||
|
job_tags='foo',
|
||||||
|
skip_tags='bar',
|
||||||
|
)
|
||||||
|
|
||||||
def test_apply_workflow_job_prompts(self, workflow_job_template, wfjt_prompts, prompts_data, inventory):
|
def test_apply_workflow_job_prompts(self, workflow_job_template, wfjt_prompts, prompts_data, inventory):
|
||||||
# null or empty fields used
|
# null or empty fields used
|
||||||
@@ -300,6 +313,9 @@ class TestWorkflowJobTemplatePrompts:
|
|||||||
assert workflow_job.limit is None
|
assert workflow_job.limit is None
|
||||||
assert workflow_job.inventory is None
|
assert workflow_job.inventory is None
|
||||||
assert workflow_job.scm_branch is None
|
assert workflow_job.scm_branch is None
|
||||||
|
assert workflow_job.job_tags is None
|
||||||
|
assert workflow_job.skip_tags is None
|
||||||
|
assert len(workflow_job.labels.all()) is 0
|
||||||
|
|
||||||
# fields from prompts used
|
# fields from prompts used
|
||||||
workflow_job = workflow_job_template.create_unified_job(**prompts_data)
|
workflow_job = workflow_job_template.create_unified_job(**prompts_data)
|
||||||
@@ -307,15 +323,21 @@ class TestWorkflowJobTemplatePrompts:
|
|||||||
assert workflow_job.limit == 'webservers'
|
assert workflow_job.limit == 'webservers'
|
||||||
assert workflow_job.inventory == inventory
|
assert workflow_job.inventory == inventory
|
||||||
assert workflow_job.scm_branch == 'release-3.3'
|
assert workflow_job.scm_branch == 'release-3.3'
|
||||||
|
assert workflow_job.job_tags == 'foo'
|
||||||
|
assert workflow_job.skip_tags == 'bar'
|
||||||
|
|
||||||
# non-null fields from WFJT used
|
# non-null fields from WFJT used
|
||||||
workflow_job_template.inventory = inventory
|
workflow_job_template.inventory = inventory
|
||||||
workflow_job_template.limit = 'fooo'
|
workflow_job_template.limit = 'fooo'
|
||||||
workflow_job_template.scm_branch = 'bar'
|
workflow_job_template.scm_branch = 'bar'
|
||||||
|
workflow_job_template.job_tags = 'baz'
|
||||||
|
workflow_job_template.skip_tags = 'dinosaur'
|
||||||
workflow_job = workflow_job_template.create_unified_job()
|
workflow_job = workflow_job_template.create_unified_job()
|
||||||
assert workflow_job.limit == 'fooo'
|
assert workflow_job.limit == 'fooo'
|
||||||
assert workflow_job.inventory == inventory
|
assert workflow_job.inventory == inventory
|
||||||
assert workflow_job.scm_branch == 'bar'
|
assert workflow_job.scm_branch == 'bar'
|
||||||
|
assert workflow_job.job_tags == 'baz'
|
||||||
|
assert workflow_job.skip_tags == 'dinosaur'
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_process_workflow_job_prompts(self, inventory, workflow_job_template, wfjt_prompts, prompts_data):
|
def test_process_workflow_job_prompts(self, inventory, workflow_job_template, wfjt_prompts, prompts_data):
|
||||||
@@ -340,12 +362,19 @@ class TestWorkflowJobTemplatePrompts:
|
|||||||
ask_limit_on_launch=True,
|
ask_limit_on_launch=True,
|
||||||
scm_branch='bar',
|
scm_branch='bar',
|
||||||
ask_scm_branch_on_launch=True,
|
ask_scm_branch_on_launch=True,
|
||||||
|
job_tags='foo',
|
||||||
|
skip_tags='bar',
|
||||||
),
|
),
|
||||||
user=org_admin,
|
user=org_admin,
|
||||||
expect=201,
|
expect=201,
|
||||||
)
|
)
|
||||||
wfjt = WorkflowJobTemplate.objects.get(id=r.data['id'])
|
wfjt = WorkflowJobTemplate.objects.get(id=r.data['id'])
|
||||||
assert wfjt.char_prompts == {'limit': 'foooo', 'scm_branch': 'bar'}
|
assert wfjt.char_prompts == {
|
||||||
|
'limit': 'foooo',
|
||||||
|
'scm_branch': 'bar',
|
||||||
|
'job_tags': 'foo',
|
||||||
|
'skip_tags': 'bar',
|
||||||
|
}
|
||||||
assert wfjt.ask_scm_branch_on_launch is True
|
assert wfjt.ask_scm_branch_on_launch is True
|
||||||
assert wfjt.ask_limit_on_launch is True
|
assert wfjt.ask_limit_on_launch is True
|
||||||
|
|
||||||
@@ -355,6 +384,67 @@ class TestWorkflowJobTemplatePrompts:
|
|||||||
assert r.data['limit'] == 'prompt_limit'
|
assert r.data['limit'] == 'prompt_limit'
|
||||||
assert r.data['scm_branch'] == 'prompt_branch'
|
assert r.data['scm_branch'] == 'prompt_branch'
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_set_all_ask_for_prompts_false_from_post(self, post, organization, inventory, org_admin):
|
||||||
|
'''
|
||||||
|
Tests default behaviour and values of ask_for_* fields on WFJT via POST
|
||||||
|
'''
|
||||||
|
r = post(
|
||||||
|
url=reverse('api:workflow_job_template_list'),
|
||||||
|
data=dict(
|
||||||
|
name='workflow that tests ask_for prompts',
|
||||||
|
organization=organization.id,
|
||||||
|
inventory=inventory.id,
|
||||||
|
job_tags='',
|
||||||
|
skip_tags='',
|
||||||
|
),
|
||||||
|
user=org_admin,
|
||||||
|
expect=201,
|
||||||
|
)
|
||||||
|
wfjt = WorkflowJobTemplate.objects.get(id=r.data['id'])
|
||||||
|
|
||||||
|
assert wfjt.ask_inventory_on_launch is False
|
||||||
|
assert wfjt.ask_labels_on_launch is False
|
||||||
|
assert wfjt.ask_limit_on_launch is False
|
||||||
|
assert wfjt.ask_scm_branch_on_launch is False
|
||||||
|
assert wfjt.ask_skip_tags_on_launch is False
|
||||||
|
assert wfjt.ask_tags_on_launch is False
|
||||||
|
assert wfjt.ask_variables_on_launch is False
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_set_all_ask_for_prompts_true_from_post(self, post, organization, inventory, org_admin):
|
||||||
|
'''
|
||||||
|
Tests behaviour and values of ask_for_* fields on WFJT via POST
|
||||||
|
'''
|
||||||
|
r = post(
|
||||||
|
url=reverse('api:workflow_job_template_list'),
|
||||||
|
data=dict(
|
||||||
|
name='workflow that tests ask_for prompts',
|
||||||
|
organization=organization.id,
|
||||||
|
inventory=inventory.id,
|
||||||
|
job_tags='',
|
||||||
|
skip_tags='',
|
||||||
|
ask_inventory_on_launch=True,
|
||||||
|
ask_labels_on_launch=True,
|
||||||
|
ask_limit_on_launch=True,
|
||||||
|
ask_scm_branch_on_launch=True,
|
||||||
|
ask_skip_tags_on_launch=True,
|
||||||
|
ask_tags_on_launch=True,
|
||||||
|
ask_variables_on_launch=True,
|
||||||
|
),
|
||||||
|
user=org_admin,
|
||||||
|
expect=201,
|
||||||
|
)
|
||||||
|
wfjt = WorkflowJobTemplate.objects.get(id=r.data['id'])
|
||||||
|
|
||||||
|
assert wfjt.ask_inventory_on_launch is True
|
||||||
|
assert wfjt.ask_labels_on_launch is True
|
||||||
|
assert wfjt.ask_limit_on_launch is True
|
||||||
|
assert wfjt.ask_scm_branch_on_launch is True
|
||||||
|
assert wfjt.ask_skip_tags_on_launch is True
|
||||||
|
assert wfjt.ask_tags_on_launch is True
|
||||||
|
assert wfjt.ask_variables_on_launch is True
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_workflow_ancestors(organization):
|
def test_workflow_ancestors(organization):
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ from awx.api.serializers import (
|
|||||||
from awx.main.models import Job, WorkflowJobTemplateNode, WorkflowJob, WorkflowJobNode, WorkflowJobTemplate, Project, Inventory, JobTemplate
|
from awx.main.models import Job, WorkflowJobTemplateNode, WorkflowJob, WorkflowJobNode, WorkflowJobTemplate, Project, Inventory, JobTemplate
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
@mock.patch('awx.api.serializers.UnifiedJobTemplateSerializer.get_related', lambda x, y: {})
|
@mock.patch('awx.api.serializers.UnifiedJobTemplateSerializer.get_related', lambda x, y: {})
|
||||||
class TestWorkflowJobTemplateSerializerGetRelated:
|
class TestWorkflowJobTemplateSerializerGetRelated:
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
@@ -58,6 +59,7 @@ class TestWorkflowNodeBaseSerializerGetRelated:
|
|||||||
assert 'unified_job_template' not in related
|
assert 'unified_job_template' not in related
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
@mock.patch('awx.api.serializers.BaseSerializer.get_related', lambda x, y: {})
|
@mock.patch('awx.api.serializers.BaseSerializer.get_related', lambda x, y: {})
|
||||||
class TestWorkflowJobTemplateNodeSerializerGetRelated:
|
class TestWorkflowJobTemplateNodeSerializerGetRelated:
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
@@ -146,6 +148,7 @@ class TestWorkflowJobTemplateNodeSerializerCharPrompts:
|
|||||||
assert WFJT_serializer.instance.limit == 'webservers'
|
assert WFJT_serializer.instance.limit == 'webservers'
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
@mock.patch('awx.api.serializers.BaseSerializer.validate', lambda self, attrs: attrs)
|
@mock.patch('awx.api.serializers.BaseSerializer.validate', lambda self, attrs: attrs)
|
||||||
class TestWorkflowJobTemplateNodeSerializerSurveyPasswords:
|
class TestWorkflowJobTemplateNodeSerializerSurveyPasswords:
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
@@ -162,7 +165,7 @@ class TestWorkflowJobTemplateNodeSerializerSurveyPasswords:
|
|||||||
|
|
||||||
def test_set_survey_passwords_create(self, jt):
|
def test_set_survey_passwords_create(self, jt):
|
||||||
serializer = WorkflowJobTemplateNodeSerializer()
|
serializer = WorkflowJobTemplateNodeSerializer()
|
||||||
wfjt = WorkflowJobTemplate(name='fake-wfjt')
|
wfjt = WorkflowJobTemplate.objects.create(name='fake-wfjt')
|
||||||
attrs = serializer.validate({'unified_job_template': jt, 'workflow_job_template': wfjt, 'extra_data': {'var1': 'secret_answer'}})
|
attrs = serializer.validate({'unified_job_template': jt, 'workflow_job_template': wfjt, 'extra_data': {'var1': 'secret_answer'}})
|
||||||
assert 'survey_passwords' in attrs
|
assert 'survey_passwords' in attrs
|
||||||
assert 'var1' in attrs['survey_passwords']
|
assert 'var1' in attrs['survey_passwords']
|
||||||
@@ -171,7 +174,7 @@ class TestWorkflowJobTemplateNodeSerializerSurveyPasswords:
|
|||||||
|
|
||||||
def test_set_survey_passwords_modify(self, jt):
|
def test_set_survey_passwords_modify(self, jt):
|
||||||
serializer = WorkflowJobTemplateNodeSerializer()
|
serializer = WorkflowJobTemplateNodeSerializer()
|
||||||
wfjt = WorkflowJobTemplate(name='fake-wfjt')
|
wfjt = WorkflowJobTemplate.objects.create(name='fake-wfjt')
|
||||||
serializer.instance = WorkflowJobTemplateNode(workflow_job_template=wfjt, unified_job_template=jt)
|
serializer.instance = WorkflowJobTemplateNode(workflow_job_template=wfjt, unified_job_template=jt)
|
||||||
attrs = serializer.validate({'unified_job_template': jt, 'workflow_job_template': wfjt, 'extra_data': {'var1': 'secret_answer'}})
|
attrs = serializer.validate({'unified_job_template': jt, 'workflow_job_template': wfjt, 'extra_data': {'var1': 'secret_answer'}})
|
||||||
assert 'survey_passwords' in attrs
|
assert 'survey_passwords' in attrs
|
||||||
@@ -181,7 +184,7 @@ class TestWorkflowJobTemplateNodeSerializerSurveyPasswords:
|
|||||||
|
|
||||||
def test_use_db_answer(self, jt, mocker):
|
def test_use_db_answer(self, jt, mocker):
|
||||||
serializer = WorkflowJobTemplateNodeSerializer()
|
serializer = WorkflowJobTemplateNodeSerializer()
|
||||||
wfjt = WorkflowJobTemplate(name='fake-wfjt')
|
wfjt = WorkflowJobTemplate.objects.create(name='fake-wfjt')
|
||||||
serializer.instance = WorkflowJobTemplateNode(workflow_job_template=wfjt, unified_job_template=jt, extra_data={'var1': '$encrypted$foooooo'})
|
serializer.instance = WorkflowJobTemplateNode(workflow_job_template=wfjt, unified_job_template=jt, extra_data={'var1': '$encrypted$foooooo'})
|
||||||
with mocker.patch('awx.main.models.mixins.decrypt_value', return_value='foo'):
|
with mocker.patch('awx.main.models.mixins.decrypt_value', return_value='foo'):
|
||||||
attrs = serializer.validate({'unified_job_template': jt, 'workflow_job_template': wfjt, 'extra_data': {'var1': '$encrypted$'}})
|
attrs = serializer.validate({'unified_job_template': jt, 'workflow_job_template': wfjt, 'extra_data': {'var1': '$encrypted$'}})
|
||||||
@@ -196,7 +199,7 @@ class TestWorkflowJobTemplateNodeSerializerSurveyPasswords:
|
|||||||
with that particular var omitted so on launch time the default takes effect
|
with that particular var omitted so on launch time the default takes effect
|
||||||
"""
|
"""
|
||||||
serializer = WorkflowJobTemplateNodeSerializer()
|
serializer = WorkflowJobTemplateNodeSerializer()
|
||||||
wfjt = WorkflowJobTemplate(name='fake-wfjt')
|
wfjt = WorkflowJobTemplate.objects.create(name='fake-wfjt')
|
||||||
jt.survey_spec['spec'][0]['default'] = '$encrypted$bar'
|
jt.survey_spec['spec'][0]['default'] = '$encrypted$bar'
|
||||||
attrs = serializer.validate({'unified_job_template': jt, 'workflow_job_template': wfjt, 'extra_data': {'var1': '$encrypted$'}})
|
attrs = serializer.validate({'unified_job_template': jt, 'workflow_job_template': wfjt, 'extra_data': {'var1': '$encrypted$'}})
|
||||||
assert 'survey_passwords' in attrs
|
assert 'survey_passwords' in attrs
|
||||||
|
|||||||
@@ -259,13 +259,14 @@ def test_survey_encryption_defaults(survey_spec_factory, question_type, default,
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.survey
|
@pytest.mark.survey
|
||||||
|
@pytest.mark.django_db
|
||||||
class TestWorkflowSurveys:
|
class TestWorkflowSurveys:
|
||||||
def test_update_kwargs_survey_defaults(self, survey_spec_factory):
|
def test_update_kwargs_survey_defaults(self, survey_spec_factory):
|
||||||
"Assure that the survey default over-rides a JT variable"
|
"Assure that the survey default over-rides a JT variable"
|
||||||
spec = survey_spec_factory('var1')
|
spec = survey_spec_factory('var1')
|
||||||
spec['spec'][0]['default'] = 3
|
spec['spec'][0]['default'] = 3
|
||||||
spec['spec'][0]['required'] = False
|
spec['spec'][0]['required'] = False
|
||||||
wfjt = WorkflowJobTemplate(name="test-wfjt", survey_spec=spec, survey_enabled=True, extra_vars="var1: 5")
|
wfjt = WorkflowJobTemplate.objects.create(name="test-wfjt", survey_spec=spec, survey_enabled=True, extra_vars="var1: 5")
|
||||||
updated_extra_vars = wfjt._update_unified_job_kwargs({}, {})
|
updated_extra_vars = wfjt._update_unified_job_kwargs({}, {})
|
||||||
assert 'extra_vars' in updated_extra_vars
|
assert 'extra_vars' in updated_extra_vars
|
||||||
assert json.loads(updated_extra_vars['extra_vars'])['var1'] == 3
|
assert json.loads(updated_extra_vars['extra_vars'])['var1'] == 3
|
||||||
@@ -277,7 +278,7 @@ class TestWorkflowSurveys:
|
|||||||
spec['spec'][0]['required'] = False
|
spec['spec'][0]['required'] = False
|
||||||
spec['spec'][1]['required'] = True
|
spec['spec'][1]['required'] = True
|
||||||
spec['spec'][2]['required'] = False
|
spec['spec'][2]['required'] = False
|
||||||
wfjt = WorkflowJobTemplate(name="test-wfjt", survey_spec=spec, survey_enabled=True, extra_vars="question2: hiworld")
|
wfjt = WorkflowJobTemplate.objects.create(name="test-wfjt", survey_spec=spec, survey_enabled=True, extra_vars="question2: hiworld")
|
||||||
assert wfjt.variables_needed_to_start == ['question2']
|
assert wfjt.variables_needed_to_start == ['question2']
|
||||||
assert not wfjt.can_start_without_user_input()
|
assert not wfjt.can_start_without_user_input()
|
||||||
|
|
||||||
@@ -311,6 +312,6 @@ class TestExtraVarsNoPrompt:
|
|||||||
self.process_vars_and_assert(jt, provided_vars, valid)
|
self.process_vars_and_assert(jt, provided_vars, valid)
|
||||||
|
|
||||||
def test_wfjt_extra_vars_counting(self, provided_vars, valid):
|
def test_wfjt_extra_vars_counting(self, provided_vars, valid):
|
||||||
wfjt = WorkflowJobTemplate(name='foo', extra_vars={'tmpl_var': 'bar'})
|
wfjt = WorkflowJobTemplate.objects.create(name='foo', extra_vars={'tmpl_var': 'bar'})
|
||||||
prompted_fields, ignored_fields, errors = wfjt._accept_or_ignore_job_kwargs(extra_vars=provided_vars)
|
prompted_fields, ignored_fields, errors = wfjt._accept_or_ignore_job_kwargs(extra_vars=provided_vars)
|
||||||
self.process_vars_and_assert(wfjt, provided_vars, valid)
|
self.process_vars_and_assert(wfjt, provided_vars, valid)
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ def workflow_job_unit():
|
|||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def workflow_job_template_unit():
|
def workflow_job_template_unit():
|
||||||
return WorkflowJobTemplate(name='workflow')
|
return WorkflowJobTemplate.objects.create(name='workflow')
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
@@ -151,6 +151,7 @@ def test_node_getter_and_setters():
|
|||||||
assert node.job_type == 'check'
|
assert node.job_type == 'check'
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
class TestWorkflowJobCreate:
|
class TestWorkflowJobCreate:
|
||||||
def test_create_no_prompts(self, wfjt_node_no_prompts, workflow_job_unit, mocker):
|
def test_create_no_prompts(self, wfjt_node_no_prompts, workflow_job_unit, mocker):
|
||||||
mock_create = mocker.MagicMock()
|
mock_create = mocker.MagicMock()
|
||||||
@@ -183,6 +184,7 @@ class TestWorkflowJobCreate:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
@mock.patch('awx.main.models.workflow.WorkflowNodeBase.get_parent_nodes', lambda self: [])
|
@mock.patch('awx.main.models.workflow.WorkflowNodeBase.get_parent_nodes', lambda self: [])
|
||||||
class TestWorkflowJobNodeJobKWARGS:
|
class TestWorkflowJobNodeJobKWARGS:
|
||||||
"""
|
"""
|
||||||
@@ -231,4 +233,12 @@ class TestWorkflowJobNodeJobKWARGS:
|
|||||||
|
|
||||||
|
|
||||||
def test_get_ask_mapping_integrity():
|
def test_get_ask_mapping_integrity():
|
||||||
assert list(WorkflowJobTemplate.get_ask_mapping().keys()) == ['extra_vars', 'inventory', 'limit', 'scm_branch']
|
assert list(WorkflowJobTemplate.get_ask_mapping().keys()) == [
|
||||||
|
'inventory',
|
||||||
|
'limit',
|
||||||
|
'scm_branch',
|
||||||
|
'labels',
|
||||||
|
'job_tags',
|
||||||
|
'skip_tags',
|
||||||
|
'extra_vars',
|
||||||
|
]
|
||||||
|
|||||||
@@ -196,6 +196,7 @@ def test_jt_can_add_bad_data(user_unit):
|
|||||||
assert not access.can_add({'asdf': 'asdf'})
|
assert not access.can_add({'asdf': 'asdf'})
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
class TestWorkflowAccessMethods:
|
class TestWorkflowAccessMethods:
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def workflow(self, workflow_job_template_factory):
|
def workflow(self, workflow_job_template_factory):
|
||||||
|
|||||||
@@ -16,8 +16,12 @@ import CredentialsStep from './steps/CredentialsStep';
|
|||||||
import CredentialPasswordsStep from './steps/CredentialPasswordsStep';
|
import CredentialPasswordsStep from './steps/CredentialPasswordsStep';
|
||||||
import OtherPromptsStep from './steps/OtherPromptsStep';
|
import OtherPromptsStep from './steps/OtherPromptsStep';
|
||||||
import PreviewStep from './steps/PreviewStep';
|
import PreviewStep from './steps/PreviewStep';
|
||||||
|
import executionEnvironmentHelpTextStrings from 'screens/ExecutionEnvironment/shared/ExecutionEnvironment.helptext';
|
||||||
|
import { ExecutionEnvironment } from 'types';
|
||||||
|
import ExecutionEnvironmentStep from './steps/ExecutionEnvironmentStep';
|
||||||
|
|
||||||
jest.mock('../../api/models/Inventories');
|
jest.mock('../../api/models/Inventories');
|
||||||
|
jest.mock('../../api/models/ExecutionEnvironments');
|
||||||
jest.mock('../../api/models/CredentialTypes');
|
jest.mock('../../api/models/CredentialTypes');
|
||||||
jest.mock('../../api/models/Credentials');
|
jest.mock('../../api/models/Credentials');
|
||||||
jest.mock('../../api/models/JobTemplates');
|
jest.mock('../../api/models/JobTemplates');
|
||||||
@@ -150,13 +154,14 @@ describe('LaunchPrompt', () => {
|
|||||||
const wizard = await waitForElement(wrapper, 'Wizard');
|
const wizard = await waitForElement(wrapper, 'Wizard');
|
||||||
const steps = wizard.prop('steps');
|
const steps = wizard.prop('steps');
|
||||||
|
|
||||||
expect(steps).toHaveLength(6);
|
expect(steps).toHaveLength(7);
|
||||||
expect(steps[0].name.props.children).toEqual('Inventory');
|
expect(steps[0].name.props.children).toEqual('Inventory');
|
||||||
expect(steps[1].name.props.children).toEqual('Credentials');
|
expect(steps[1].name.props.children).toEqual('Credentials');
|
||||||
expect(steps[2].name.props.children).toEqual('Credential passwords');
|
expect(steps[2].name.props.children).toEqual('Credential passwords');
|
||||||
expect(steps[3].name.props.children).toEqual('Other prompts');
|
expect(steps[3].name.props.children).toEqual('Execution Environment');
|
||||||
expect(steps[4].name.props.children).toEqual('Survey');
|
expect(steps[4].name.props.children).toEqual('Other prompts');
|
||||||
expect(steps[5].name.props.children).toEqual('Preview');
|
expect(steps[5].name.props.children).toEqual('Survey');
|
||||||
|
expect(steps[6].name.props.children).toEqual('Preview');
|
||||||
expect(wizard.find('WizardHeader').prop('title')).toBe('Launch | Foobar');
|
expect(wizard.find('WizardHeader').prop('title')).toBe('Launch | Foobar');
|
||||||
expect(wizard.find('WizardHeader').prop('description')).toBe(
|
expect(wizard.find('WizardHeader').prop('description')).toBe(
|
||||||
'Foo Description'
|
'Foo Description'
|
||||||
|
|||||||
@@ -22,12 +22,18 @@ const jobTemplateData = {
|
|||||||
allow_simultaneous: false,
|
allow_simultaneous: false,
|
||||||
ask_credential_on_launch: false,
|
ask_credential_on_launch: false,
|
||||||
ask_diff_mode_on_launch: false,
|
ask_diff_mode_on_launch: false,
|
||||||
|
ask_execution_environment_on_launch: false,
|
||||||
|
ask_forks_on_launch: false,
|
||||||
|
ask_instance_groups_on_launch: false,
|
||||||
ask_inventory_on_launch: false,
|
ask_inventory_on_launch: false,
|
||||||
|
ask_job_slice_count_on_launch: false,
|
||||||
ask_job_type_on_launch: false,
|
ask_job_type_on_launch: false,
|
||||||
|
ask_labels_on_launch: false,
|
||||||
ask_limit_on_launch: false,
|
ask_limit_on_launch: false,
|
||||||
ask_scm_branch_on_launch: false,
|
ask_scm_branch_on_launch: false,
|
||||||
ask_skip_tags_on_launch: false,
|
ask_skip_tags_on_launch: false,
|
||||||
ask_tags_on_launch: false,
|
ask_tags_on_launch: false,
|
||||||
|
ask_timeout_on_launch: false,
|
||||||
ask_variables_on_launch: false,
|
ask_variables_on_launch: false,
|
||||||
ask_verbosity_on_launch: false,
|
ask_verbosity_on_launch: false,
|
||||||
ask_execution_environment_on_launch: false,
|
ask_execution_environment_on_launch: false,
|
||||||
|
|||||||
@@ -35,13 +35,18 @@ const mockJobTemplate = {
|
|||||||
allow_simultaneous: false,
|
allow_simultaneous: false,
|
||||||
ask_scm_branch_on_launch: false,
|
ask_scm_branch_on_launch: false,
|
||||||
ask_diff_mode_on_launch: false,
|
ask_diff_mode_on_launch: false,
|
||||||
|
ask_execution_environment_on_launch: false,
|
||||||
|
ask_forks_on_launch: false,
|
||||||
|
ask_instance_groups_on_launch: false,
|
||||||
ask_variables_on_launch: false,
|
ask_variables_on_launch: false,
|
||||||
ask_limit_on_launch: false,
|
ask_limit_on_launch: false,
|
||||||
ask_tags_on_launch: false,
|
ask_tags_on_launch: false,
|
||||||
ask_skip_tags_on_launch: false,
|
ask_skip_tags_on_launch: false,
|
||||||
ask_job_type_on_launch: false,
|
ask_job_type_on_launch: false,
|
||||||
|
ask_labels_on_launch: false,
|
||||||
ask_verbosity_on_launch: false,
|
ask_verbosity_on_launch: false,
|
||||||
ask_inventory_on_launch: false,
|
ask_inventory_on_launch: false,
|
||||||
|
ask_job_slice_count_on_launch: false,
|
||||||
ask_credential_on_launch: false,
|
ask_credential_on_launch: false,
|
||||||
ask_execution_environment_on_launch: false,
|
ask_execution_environment_on_launch: false,
|
||||||
ask_forks_on_launch: false,
|
ask_forks_on_launch: false,
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ describe('<WorkflowJobTemplateAdd/>', () => {
|
|||||||
test('calls workflowJobTemplatesAPI with correct information on submit', async () => {
|
test('calls workflowJobTemplatesAPI with correct information on submit', async () => {
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper.find('input#wfjt-name').simulate('change', {
|
wrapper.find('input#wfjt-name').simulate('change', {
|
||||||
target: { value: 'Alex', name: 'name' },
|
target: { value: 'Alex Singh', name: 'name' },
|
||||||
});
|
});
|
||||||
|
|
||||||
wrapper.find('LabelSelect').find('SelectToggle').simulate('click');
|
wrapper.find('LabelSelect').find('SelectToggle').simulate('click');
|
||||||
@@ -104,18 +104,23 @@ describe('<WorkflowJobTemplateAdd/>', () => {
|
|||||||
wrapper.find('form').simulate('submit');
|
wrapper.find('form').simulate('submit');
|
||||||
});
|
});
|
||||||
await expect(WorkflowJobTemplatesAPI.create).toHaveBeenCalledWith({
|
await expect(WorkflowJobTemplatesAPI.create).toHaveBeenCalledWith({
|
||||||
name: 'Alex',
|
name: 'Alex Singh',
|
||||||
allow_simultaneous: false,
|
allow_simultaneous: false,
|
||||||
ask_inventory_on_launch: false,
|
ask_inventory_on_launch: false,
|
||||||
|
ask_labels_on_launch: false,
|
||||||
ask_limit_on_launch: false,
|
ask_limit_on_launch: false,
|
||||||
ask_scm_branch_on_launch: false,
|
ask_scm_branch_on_launch: false,
|
||||||
|
ask_skip_tags_on_launch: false,
|
||||||
|
ask_tags_on_launch: false,
|
||||||
ask_variables_on_launch: false,
|
ask_variables_on_launch: false,
|
||||||
description: '',
|
description: '',
|
||||||
extra_vars: '---',
|
extra_vars: '---',
|
||||||
inventory: undefined,
|
inventory: undefined,
|
||||||
|
job_tags: '',
|
||||||
limit: null,
|
limit: null,
|
||||||
organization: undefined,
|
organization: undefined,
|
||||||
scm_branch: '',
|
scm_branch: '',
|
||||||
|
skip_tags: '',
|
||||||
webhook_credential: undefined,
|
webhook_credential: undefined,
|
||||||
webhook_service: '',
|
webhook_service: '',
|
||||||
webhook_url: '',
|
webhook_url: '',
|
||||||
|
|||||||
@@ -161,6 +161,7 @@ describe('<WorkflowJobTemplateEdit/>', () => {
|
|||||||
expect(WorkflowJobTemplatesAPI.update).toHaveBeenCalledWith(6, {
|
expect(WorkflowJobTemplatesAPI.update).toHaveBeenCalledWith(6, {
|
||||||
name: 'Alex',
|
name: 'Alex',
|
||||||
description: 'Apollo and Athena',
|
description: 'Apollo and Athena',
|
||||||
|
skip_tags: '',
|
||||||
inventory: 1,
|
inventory: 1,
|
||||||
organization: 1,
|
organization: 1,
|
||||||
scm_branch: 'main',
|
scm_branch: 'main',
|
||||||
@@ -174,6 +175,11 @@ describe('<WorkflowJobTemplateEdit/>', () => {
|
|||||||
ask_limit_on_launch: false,
|
ask_limit_on_launch: false,
|
||||||
ask_scm_branch_on_launch: false,
|
ask_scm_branch_on_launch: false,
|
||||||
ask_variables_on_launch: false,
|
ask_variables_on_launch: false,
|
||||||
|
ask_labels_on_launch: false,
|
||||||
|
ask_skip_tags_on_launch: false,
|
||||||
|
ask_tags_on_launch: false,
|
||||||
|
job_tags: '',
|
||||||
|
skip_tags: '',
|
||||||
});
|
});
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
await expect(WorkflowJobTemplatesAPI.disassociateLabel).toBeCalledWith(6, {
|
await expect(WorkflowJobTemplatesAPI.disassociateLabel).toBeCalledWith(6, {
|
||||||
@@ -273,16 +279,21 @@ describe('<WorkflowJobTemplateEdit/>', () => {
|
|||||||
expect(WorkflowJobTemplatesAPI.update).toBeCalledWith(6, {
|
expect(WorkflowJobTemplatesAPI.update).toBeCalledWith(6, {
|
||||||
allow_simultaneous: false,
|
allow_simultaneous: false,
|
||||||
ask_inventory_on_launch: false,
|
ask_inventory_on_launch: false,
|
||||||
|
ask_labels_on_launch: false,
|
||||||
ask_limit_on_launch: false,
|
ask_limit_on_launch: false,
|
||||||
ask_scm_branch_on_launch: false,
|
ask_scm_branch_on_launch: false,
|
||||||
|
ask_skip_tags_on_launch: false,
|
||||||
|
ask_tags_on_launch: false,
|
||||||
ask_variables_on_launch: false,
|
ask_variables_on_launch: false,
|
||||||
description: 'bar',
|
description: 'bar',
|
||||||
extra_vars: '---',
|
extra_vars: '---',
|
||||||
inventory: 1,
|
inventory: 1,
|
||||||
|
job_tags: '',
|
||||||
limit: '5000',
|
limit: '5000',
|
||||||
name: 'Foo',
|
name: 'Foo',
|
||||||
organization: 1,
|
organization: 1,
|
||||||
scm_branch: 'devel',
|
scm_branch: 'devel',
|
||||||
|
skip_tags: '',
|
||||||
webhook_credential: null,
|
webhook_credential: null,
|
||||||
webhook_service: '',
|
webhook_service: '',
|
||||||
webhook_url: '',
|
webhook_url: '',
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ const wfHelpTextStrings = () => ({
|
|||||||
webhookKey: t`Webhook services can use this as a shared secret.`,
|
webhookKey: t`Webhook services can use this as a shared secret.`,
|
||||||
webhookCredential: t`Optionally select the credential to use to send status updates back to the webhook service.`,
|
webhookCredential: t`Optionally select the credential to use to send status updates back to the webhook service.`,
|
||||||
webhookService: t`Select a webhook service.`,
|
webhookService: t`Select a webhook service.`,
|
||||||
|
skipTags: t`Skip tags are useful when you have a large playbook, and you want to skip specific parts of a play or task. Use commas to separate multiple tags. Refer to the documentation for details on the usage of tags.`,
|
||||||
enabledOptions: (
|
enabledOptions: (
|
||||||
<>
|
<>
|
||||||
<p>{t`Concurrent jobs: If enabled, simultaneous runs of this workflow job template will be allowed.`}</p>
|
<p>{t`Concurrent jobs: If enabled, simultaneous runs of this workflow job template will be allowed.`}</p>
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import CheckboxField from 'components/FormField/CheckboxField';
|
|||||||
import Popover from 'components/Popover';
|
import Popover from 'components/Popover';
|
||||||
import { WorkFlowJobTemplate } from 'types';
|
import { WorkFlowJobTemplate } from 'types';
|
||||||
import LabelSelect from 'components/LabelSelect';
|
import LabelSelect from 'components/LabelSelect';
|
||||||
|
import { TagMultiSelect } from 'components/MultiSelect';
|
||||||
import WebhookSubForm from './WebhookSubForm';
|
import WebhookSubForm from './WebhookSubForm';
|
||||||
import getHelpText from './WorkflowJobTemplate.helptext';
|
import getHelpText from './WorkflowJobTemplate.helptext';
|
||||||
|
|
||||||
@@ -59,6 +60,8 @@ function WorkflowJobTemplateForm({
|
|||||||
const [, webhookKeyMeta, webhookKeyHelpers] = useField('webhook_key');
|
const [, webhookKeyMeta, webhookKeyHelpers] = useField('webhook_key');
|
||||||
const [, webhookCredentialMeta, webhookCredentialHelpers] =
|
const [, webhookCredentialMeta, webhookCredentialHelpers] =
|
||||||
useField('webhook_credential');
|
useField('webhook_credential');
|
||||||
|
const [skipTagsField, , skipTagsHelpers] = useField('skip_tags');
|
||||||
|
const [jobTagsField, , jobTagsHelpers] = useField('job_tags');
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (enableWebhooks) {
|
if (enableWebhooks) {
|
||||||
@@ -167,7 +170,6 @@ function WorkflowJobTemplateForm({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</FieldWithPrompt>
|
</FieldWithPrompt>
|
||||||
|
|
||||||
<FieldWithPrompt
|
<FieldWithPrompt
|
||||||
fieldId="wfjt-scm-branch"
|
fieldId="wfjt-scm-branch"
|
||||||
label={t`Source control branch`}
|
label={t`Source control branch`}
|
||||||
@@ -184,14 +186,11 @@ function WorkflowJobTemplateForm({
|
|||||||
aria-label={t`source control branch`}
|
aria-label={t`source control branch`}
|
||||||
/>
|
/>
|
||||||
</FieldWithPrompt>
|
</FieldWithPrompt>
|
||||||
</FormColumnLayout>
|
|
||||||
<FormFullWidthLayout>
|
|
||||||
<FieldWithPrompt
|
<FieldWithPrompt
|
||||||
fieldId="template-labels"
|
|
||||||
label={t`Labels`}
|
label={t`Labels`}
|
||||||
|
fieldId="template-labels"
|
||||||
promptId="template-ask-labels-on-launch"
|
promptId="template-ask-labels-on-launch"
|
||||||
promptName="ask_labels_on_launch"
|
promptName="ask_labels_on_launch"
|
||||||
tooltip={helpText.labels}
|
|
||||||
>
|
>
|
||||||
<LabelSelect
|
<LabelSelect
|
||||||
value={labelsField.value}
|
value={labelsField.value}
|
||||||
@@ -200,16 +199,42 @@ function WorkflowJobTemplateForm({
|
|||||||
createText={t`Create`}
|
createText={t`Create`}
|
||||||
/>
|
/>
|
||||||
</FieldWithPrompt>
|
</FieldWithPrompt>
|
||||||
</FormFullWidthLayout>
|
<FormFullWidthLayout>
|
||||||
<FormFullWidthLayout>
|
<VariablesField
|
||||||
<VariablesField
|
id="wfjt-variables"
|
||||||
id="wfjt-variables"
|
name="extra_vars"
|
||||||
name="extra_vars"
|
label={t`Variables`}
|
||||||
label={t`Variables`}
|
promptId="template-ask-variables-on-launch"
|
||||||
promptId="template-ask-variables-on-launch"
|
tooltip={helpText.variables}
|
||||||
tooltip={helpText.variables}
|
/>
|
||||||
/>
|
</FormFullWidthLayout>
|
||||||
</FormFullWidthLayout>
|
<FormColumnLayout>
|
||||||
|
<FieldWithPrompt
|
||||||
|
fieldId="template-tags"
|
||||||
|
label={t`Job Tags`}
|
||||||
|
promptId="template-ask-tags-on-launch"
|
||||||
|
promptName="ask_tags_on_launch"
|
||||||
|
tooltip={helpText.jobTags}
|
||||||
|
>
|
||||||
|
<TagMultiSelect
|
||||||
|
value={jobTagsField.value}
|
||||||
|
onChange={(value) => jobTagsHelpers.setValue(value)}
|
||||||
|
/>
|
||||||
|
</FieldWithPrompt>
|
||||||
|
</FormColumnLayout>
|
||||||
|
<FieldWithPrompt
|
||||||
|
fieldId="template-skip-tags"
|
||||||
|
label={t`Skip Tags`}
|
||||||
|
promptId="template-ask-skip-tags-on-launch"
|
||||||
|
promptName="ask_skip_tags_on_launch"
|
||||||
|
tooltip={helpText.skipTags}
|
||||||
|
>
|
||||||
|
<TagMultiSelect
|
||||||
|
value={skipTagsField.value}
|
||||||
|
onChange={(value) => skipTagsHelpers.setValue(value)}
|
||||||
|
/>
|
||||||
|
</FieldWithPrompt>
|
||||||
|
</FormColumnLayout>
|
||||||
<FormGroup fieldId="options" label={t`Options`}>
|
<FormGroup fieldId="options" label={t`Options`}>
|
||||||
<FormCheckboxLayout isInline>
|
<FormCheckboxLayout isInline>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
@@ -282,6 +307,8 @@ const FormikApp = withFormik({
|
|||||||
extra_vars: template.extra_vars || '---',
|
extra_vars: template.extra_vars || '---',
|
||||||
limit: template.limit || '',
|
limit: template.limit || '',
|
||||||
scm_branch: template.scm_branch || '',
|
scm_branch: template.scm_branch || '',
|
||||||
|
skip_tags: template.skip_tags || '',
|
||||||
|
job_tags: template.job_tags || '',
|
||||||
allow_simultaneous: template.allow_simultaneous || false,
|
allow_simultaneous: template.allow_simultaneous || false,
|
||||||
webhook_credential: template?.summary_fields?.webhook_credential || null,
|
webhook_credential: template?.summary_fields?.webhook_credential || null,
|
||||||
webhook_service: template.webhook_service || '',
|
webhook_service: template.webhook_service || '',
|
||||||
@@ -290,6 +317,8 @@ const FormikApp = withFormik({
|
|||||||
ask_inventory_on_launch: template.ask_inventory_on_launch || false,
|
ask_inventory_on_launch: template.ask_inventory_on_launch || false,
|
||||||
ask_variables_on_launch: template.ask_variables_on_launch || false,
|
ask_variables_on_launch: template.ask_variables_on_launch || false,
|
||||||
ask_scm_branch_on_launch: template.ask_scm_branch_on_launch || false,
|
ask_scm_branch_on_launch: template.ask_scm_branch_on_launch || false,
|
||||||
|
ask_skip_tags_on_launch: template.ask_skip_tags_on_launch || false,
|
||||||
|
ask_tags_on_launch: template.ask_tags_on_launch || false,
|
||||||
webhook_url: template?.related?.webhook_receiver
|
webhook_url: template?.related?.webhook_receiver
|
||||||
? `${urlOrigin}${template.related.webhook_receiver}`
|
? `${urlOrigin}${template.related.webhook_receiver}`
|
||||||
: '',
|
: '',
|
||||||
|
|||||||
@@ -189,7 +189,9 @@ describe('<WorkflowJobTemplateForm/>', () => {
|
|||||||
'FieldWithPrompt[label="Inventory"]',
|
'FieldWithPrompt[label="Inventory"]',
|
||||||
'FieldWithPrompt[label="Limit"]',
|
'FieldWithPrompt[label="Limit"]',
|
||||||
'FieldWithPrompt[label="Source control branch"]',
|
'FieldWithPrompt[label="Source control branch"]',
|
||||||
'FormGroup[label="Labels"]',
|
'FieldWithPrompt[label="Labels"]',
|
||||||
|
'FieldWithPrompt[label="Skip Tags"]',
|
||||||
|
'FieldWithPrompt[label="Job Tags"]',
|
||||||
'VariablesField',
|
'VariablesField',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,16 @@ options:
|
|||||||
description:
|
description:
|
||||||
- Variables which will be made available to jobs ran inside the workflow.
|
- Variables which will be made available to jobs ran inside the workflow.
|
||||||
type: dict
|
type: dict
|
||||||
|
job_tags:
|
||||||
|
description:
|
||||||
|
- Comma separated list of the tags to use for the job template.
|
||||||
|
type: str
|
||||||
|
ask_tags_on_launch:
|
||||||
|
description:
|
||||||
|
- Prompt user for job tags on launch.
|
||||||
|
type: bool
|
||||||
|
aliases:
|
||||||
|
- ask_tags
|
||||||
organization:
|
organization:
|
||||||
description:
|
description:
|
||||||
- Organization the workflow job template exists in.
|
- Organization the workflow job template exists in.
|
||||||
@@ -85,6 +95,22 @@ options:
|
|||||||
description:
|
description:
|
||||||
- Prompt user for limit on launch of this workflow job template
|
- Prompt user for limit on launch of this workflow job template
|
||||||
type: bool
|
type: bool
|
||||||
|
ask_labels_on_launch:
|
||||||
|
description:
|
||||||
|
- Prompt user for labels on launch.
|
||||||
|
type: bool
|
||||||
|
aliases:
|
||||||
|
- ask_labels
|
||||||
|
ask_skip_tags_on_launch:
|
||||||
|
description:
|
||||||
|
- Prompt user for job tags to skip on launch.
|
||||||
|
type: bool
|
||||||
|
aliases:
|
||||||
|
- ask_skip_tags
|
||||||
|
skip_tags:
|
||||||
|
description:
|
||||||
|
- Comma separated list of the tags to skip for the job template.
|
||||||
|
type: str
|
||||||
webhook_service:
|
webhook_service:
|
||||||
description:
|
description:
|
||||||
- Service that webhook requests will be accepted from
|
- Service that webhook requests will be accepted from
|
||||||
@@ -665,11 +691,15 @@ def main():
|
|||||||
copy_from=dict(),
|
copy_from=dict(),
|
||||||
description=dict(),
|
description=dict(),
|
||||||
extra_vars=dict(type='dict'),
|
extra_vars=dict(type='dict'),
|
||||||
|
job_tags=dict(),
|
||||||
|
skip_tags=dict(),
|
||||||
organization=dict(),
|
organization=dict(),
|
||||||
survey_spec=dict(type='dict', aliases=['survey']),
|
survey_spec=dict(type='dict', aliases=['survey']),
|
||||||
survey_enabled=dict(type='bool'),
|
survey_enabled=dict(type='bool'),
|
||||||
allow_simultaneous=dict(type='bool'),
|
allow_simultaneous=dict(type='bool'),
|
||||||
ask_variables_on_launch=dict(type='bool'),
|
ask_variables_on_launch=dict(type='bool'),
|
||||||
|
ask_labels_on_launch=dict(type='bool', aliases=['ask_labels']),
|
||||||
|
ask_skip_tags_on_launch=dict(type='bool', aliases=['ask_skip_tags']),
|
||||||
inventory=dict(),
|
inventory=dict(),
|
||||||
limit=dict(),
|
limit=dict(),
|
||||||
scm_branch=dict(),
|
scm_branch=dict(),
|
||||||
@@ -752,7 +782,11 @@ def main():
|
|||||||
'ask_scm_branch_on_launch',
|
'ask_scm_branch_on_launch',
|
||||||
'ask_limit_on_launch',
|
'ask_limit_on_launch',
|
||||||
'ask_variables_on_launch',
|
'ask_variables_on_launch',
|
||||||
|
'ask_labels_on_launch',
|
||||||
|
'ask_skip_tags_on_launch',
|
||||||
'webhook_service',
|
'webhook_service',
|
||||||
|
'job_tags',
|
||||||
|
'skip_tags',
|
||||||
):
|
):
|
||||||
field_val = module.params.get(field_name)
|
field_val = module.params.get(field_name)
|
||||||
if field_val is not None:
|
if field_val is not None:
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ def test_create_workflow_job_template(run_module, admin_user, organization, surv
|
|||||||
'survey_spec': survey_spec,
|
'survey_spec': survey_spec,
|
||||||
'survey_enabled': True,
|
'survey_enabled': True,
|
||||||
'state': 'present',
|
'state': 'present',
|
||||||
|
'job_tags': '',
|
||||||
|
'skip_tags': '',
|
||||||
},
|
},
|
||||||
admin_user,
|
admin_user,
|
||||||
)
|
)
|
||||||
@@ -35,7 +37,16 @@ def test_create_workflow_job_template(run_module, admin_user, organization, surv
|
|||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_create_modify_no_survey(run_module, admin_user, organization, survey_spec):
|
def test_create_modify_no_survey(run_module, admin_user, organization, survey_spec):
|
||||||
result = run_module('workflow_job_template', {'name': 'foo-workflow', 'organization': organization.name}, admin_user)
|
result = run_module(
|
||||||
|
'workflow_job_template',
|
||||||
|
{
|
||||||
|
'name': 'foo-workflow',
|
||||||
|
'organization': organization.name,
|
||||||
|
'job_tags': '',
|
||||||
|
'skip_tags': '',
|
||||||
|
},
|
||||||
|
admin_user,
|
||||||
|
)
|
||||||
assert not result.get('failed', False), result.get('msg', result)
|
assert not result.get('failed', False), result.get('msg', result)
|
||||||
assert result.get('changed', False), result
|
assert result.get('changed', False), result
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user