Merge pull request #6232 from ryanpetrello/jt_promptable_extra_creds

add prompting for JT.extra_credentials
This commit is contained in:
Ryan Petrello
2017-05-11 07:51:36 -04:00
committed by GitHub
12 changed files with 304 additions and 38 deletions

View File

@@ -2184,7 +2184,7 @@ class JobOptionsSerializer(LabelsListMixin, BaseSerializer):
res['cloud_credential'] = self.reverse('api:credential_detail', kwargs={'pk': cloud_cred})
net_cred = obj.network_credential
if net_cred:
res['cloud_credential'] = self.reverse('api:credential_detail', kwargs={'pk': net_cred})
res['network_credential'] = self.reverse('api:credential_detail', kwargs={'pk': net_cred})
return res
@@ -2302,7 +2302,15 @@ class JobTemplateSerializer(JobTemplateMixin, UnifiedJobTemplateSerializer, JobO
model = JobTemplate
fields = ('*', 'host_config_key', 'ask_variables_on_launch', 'ask_limit_on_launch', 'ask_tags_on_launch',
'ask_skip_tags_on_launch', 'ask_job_type_on_launch', 'ask_verbosity_on_launch', 'ask_inventory_on_launch',
'ask_credential_on_launch', 'survey_enabled', 'become_enabled', 'allow_simultaneous')
'ask_credential_on_launch', 'ask_extra_credentials_on_launch', 'survey_enabled', 'become_enabled',
'allow_simultaneous')
# TODO: remove in 3.3
def get_fields(self):
ret = super(JobTemplateSerializer, self).get_fields()
if self.version == 1:
ret.pop('ask_extra_credentials_on_launch')
return ret
def get_related(self, obj):
res = super(JobTemplateSerializer, self).get_related(obj)
@@ -2972,18 +2980,19 @@ class JobLaunchSerializer(BaseSerializer):
model = JobTemplate
fields = ('can_start_without_user_input', 'passwords_needed_to_start',
'extra_vars', 'limit', 'job_tags', 'skip_tags', 'job_type', 'inventory',
'credential', 'ask_variables_on_launch', 'ask_tags_on_launch',
'credential', 'extra_credentials', 'ask_variables_on_launch', 'ask_tags_on_launch',
'ask_skip_tags_on_launch', 'ask_job_type_on_launch', 'ask_limit_on_launch',
'ask_verbosity_on_launch', 'ask_inventory_on_launch', 'ask_credential_on_launch',
'survey_enabled', 'variables_needed_to_start',
'ask_extra_credentials_on_launch', 'survey_enabled', 'variables_needed_to_start',
'credential_needed_to_start', 'inventory_needed_to_start',
'job_template_data', 'defaults')
read_only_fields = (
'ask_variables_on_launch', 'ask_limit_on_launch', 'ask_tags_on_launch',
'ask_skip_tags_on_launch', 'ask_job_type_on_launch', 'ask_verbosity_on_launch',
'ask_inventory_on_launch', 'ask_credential_on_launch')
'ask_inventory_on_launch', 'ask_credential_on_launch', 'ask_extra_credentials_on_launch')
extra_kwargs = {
'credential': {'write_only': True,},
'extra_credentials': {'write_only': True, 'default': [], 'allow_empty': True},
'limit': {'write_only': True,},
'job_tags': {'write_only': True,},
'skip_tags': {'write_only': True,},
@@ -2991,6 +3000,14 @@ class JobLaunchSerializer(BaseSerializer):
'inventory': {'write_only': True,}
}
# TODO: remove in 3.3
def get_fields(self):
ret = super(JobLaunchSerializer, self).get_fields()
if self.version == 1:
ret.pop('extra_credentials')
ret.pop('ask_extra_credentials_on_launch')
return ret
def get_credential_needed_to_start(self, obj):
return not (obj and obj.credential)
@@ -3010,6 +3027,9 @@ class JobLaunchSerializer(BaseSerializer):
defaults_dict[field] = dict(
name=getattrd(obj, '%s.name' % field, None),
id=getattrd(obj, '%s.pk' % field, None))
elif field == 'extra_credentials':
if self.version > 1:
defaults_dict[field] = [cred.id for cred in obj.extra_credentials.all()]
else:
defaults_dict[field] = getattr(obj, field)
return defaults_dict
@@ -3060,6 +3080,15 @@ class JobLaunchSerializer(BaseSerializer):
if validation_errors:
errors['variables_needed_to_start'] = validation_errors
extra_cred_kinds = []
for cred in data.get('extra_credentials', []):
cred = Credential.objects.get(id=cred)
if cred.credential_type.pk in extra_cred_kinds:
errors['extra_credentials'] = _('Cannot assign multiple %s credentials.' % cred.credential_type.name)
if cred.credential_type.kind not in ('net', 'cloud'):
errors['extra_credentials'] = _('Extra credentials must be network or cloud.')
extra_cred_kinds.append(cred.credential_type.pk)
# Special prohibited cases for scan jobs
errors.update(obj._extra_job_type_errors(data))
@@ -3073,6 +3102,7 @@ class JobLaunchSerializer(BaseSerializer):
JT_skip_tags = obj.skip_tags
JT_inventory = obj.inventory
JT_credential = obj.credential
extra_credentials = attrs.pop('extra_credentials', None)
attrs = super(JobLaunchSerializer, self).validate(attrs)
obj.extra_vars = JT_extra_vars
obj.limit = JT_limit
@@ -3081,6 +3111,8 @@ class JobLaunchSerializer(BaseSerializer):
obj.job_tags = JT_job_tags
obj.inventory = JT_inventory
obj.credential = JT_credential
if extra_credentials is not None:
attrs['extra_credentials'] = extra_credentials
return attrs

View File

@@ -2526,29 +2526,41 @@ class JobTemplateLaunch(RetrieveAPIView, GenericAPIView):
data['extra_vars'] = extra_vars
ask_for_vars_dict = obj._ask_for_vars_dict()
ask_for_vars_dict.pop('extra_vars')
if get_request_version(self.request) == 1: # TODO: remove in 3.3
ask_for_vars_dict.pop('extra_credentials')
for field in ask_for_vars_dict:
if not ask_for_vars_dict[field]:
data.pop(field, None)
elif field == 'inventory' or field == 'credential':
data[field] = getattrd(obj, "%s.%s" % (field, 'id'), None)
elif field == 'extra_credentials':
data[field] = [cred.id for cred in obj.extra_credentials.all()]
else:
data[field] = getattr(obj, field)
return data
def post(self, request, *args, **kwargs):
obj = self.get_object()
ignored_fields = {}
if 'credential' not in request.data and 'credential_id' in request.data:
request.data['credential'] = request.data['credential_id']
if 'inventory' not in request.data and 'inventory_id' in request.data:
request.data['inventory'] = request.data['inventory_id']
if get_request_version(self.request) == 1: # TODO: remove in 3.3
extra_creds = request.data.pop('extra_credentials', None)
if extra_creds is not None:
ignored_fields['extra_credentials'] = extra_creds
passwords = {}
serializer = self.serializer_class(instance=obj, data=request.data, context={'obj': obj, 'data': request.data, 'passwords': passwords})
if not serializer.is_valid():
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
prompted_fields, ignored_fields = obj._accept_or_ignore_job_kwargs(**request.data)
_accepted_or_ignored = obj._accept_or_ignore_job_kwargs(**request.data)
prompted_fields = _accepted_or_ignored[0]
ignored_fields.update(_accepted_or_ignored[1])
if 'credential' in prompted_fields and prompted_fields['credential'] != getattrd(obj, 'credential.pk', None):
new_credential = get_object_or_400(Credential, pk=get_pk_from_dict(prompted_fields, 'credential'))
@@ -2560,6 +2572,11 @@ class JobTemplateLaunch(RetrieveAPIView, GenericAPIView):
if request.user not in new_inventory.use_role:
raise PermissionDenied()
for cred in prompted_fields.get('extra_credentials', []):
new_credential = get_object_or_400(Credential, pk=cred)
if request.user not in new_credential.use_role:
raise PermissionDenied()
new_job = obj.create_unified_job(**prompted_fields)
result = new_job.signal_start(**passwords)