mirror of
https://github.com/ansible/awx.git
synced 2026-02-17 19:20:05 -03:30
Make the bulk endpoint templates work in API browser
Various fixes - Don't skip checking resource RBAC permissions for admins Necessary to handle bad input, e.g. providing a unified_job_template id that doesn't exit - In awxkit, only "walk" if we get 'url' in the result - Bulk host create should return url pointing to inventory, not inventory/hosts dont do org check for superuser
This commit is contained in:
committed by
Elijah DeLee
parent
9358d59f20
commit
7cb16ef91d
@@ -2077,7 +2077,7 @@ class BulkHostCreateSerializer(serializers.Serializer):
|
|||||||
item['url'] = reverse('api:host_detail', kwargs={'pk': r.id})
|
item['url'] = reverse('api:host_detail', kwargs={'pk': r.id})
|
||||||
item['inventory'] = reverse('api:inventory_detail', kwargs={'pk': validated_data['inventory'].id})
|
item['inventory'] = reverse('api:inventory_detail', kwargs={'pk': validated_data['inventory'].id})
|
||||||
host_data.append(item)
|
host_data.append(item)
|
||||||
return_data['url'] = reverse('api:inventory_hosts_list', kwargs={'pk': validated_data['inventory'].id})
|
return_data['url'] = reverse('api:inventory_detail', kwargs={'pk': validated_data['inventory'].id})
|
||||||
return_data['hosts'] = host_data
|
return_data['hosts'] = host_data
|
||||||
return return_data
|
return return_data
|
||||||
|
|
||||||
@@ -4640,21 +4640,19 @@ class BulkJobLaunchSerializer(BaseSerializer):
|
|||||||
if 'instance_groups' in job:
|
if 'instance_groups' in job:
|
||||||
[requested_use_instance_groups.add(instance_group) for instance_group in job['instance_groups']]
|
[requested_use_instance_groups.add(instance_group) for instance_group in job['instance_groups']]
|
||||||
|
|
||||||
# If we are not a superuser, check we have permissions
|
self.check_organization_permission(attrs, request)
|
||||||
if request and not request.user.is_superuser:
|
self.check_unified_job_permission(request, requested_ujts)
|
||||||
self.check_organization_permission(attrs, request)
|
if requested_use_inventories or 'inventory' in attrs:
|
||||||
self.check_unified_job_permission(request, requested_ujts)
|
self.check_inventory_permission(attrs, request, requested_use_inventories)
|
||||||
if requested_use_inventories or 'inventory' in attrs:
|
|
||||||
self.check_inventory_permission(attrs, request, requested_use_inventories)
|
|
||||||
|
|
||||||
if requested_use_labels:
|
if requested_use_labels:
|
||||||
self.check_label_permission(requested_use_labels)
|
self.check_label_permission(requested_use_labels)
|
||||||
|
|
||||||
if requested_use_instance_groups:
|
if requested_use_instance_groups:
|
||||||
self.check_instance_group_permission(request, requested_use_instance_groups)
|
self.check_instance_group_permission(request, requested_use_instance_groups)
|
||||||
|
|
||||||
if requested_use_execution_environments:
|
if requested_use_execution_environments:
|
||||||
self.check_instance_group_permission(request, requested_use_instance_groups)
|
self.check_instance_group_permission(request, requested_use_instance_groups)
|
||||||
|
|
||||||
# all of the unified job templates and related items have now been checked, we can now grab the objects from the DB
|
# all of the unified job templates and related items have now been checked, we can now grab the objects from the DB
|
||||||
jobs_object = self.get_objectified_jobs(
|
jobs_object = self.get_objectified_jobs(
|
||||||
@@ -4688,7 +4686,6 @@ class BulkJobLaunchSerializer(BaseSerializer):
|
|||||||
nodes = []
|
nodes = []
|
||||||
node_m2m_objects = {}
|
node_m2m_objects = {}
|
||||||
node_m2m_object_types_to_through_model = {
|
node_m2m_object_types_to_through_model = {
|
||||||
|
|
||||||
'credentials': WorkflowJobNode.credentials.through,
|
'credentials': WorkflowJobNode.credentials.through,
|
||||||
'labels': WorkflowJobNode.labels.through,
|
'labels': WorkflowJobNode.labels.through,
|
||||||
'instance_groups': WorkflowJobNode.instance_groups.through,
|
'instance_groups': WorkflowJobNode.instance_groups.through,
|
||||||
@@ -4759,21 +4756,22 @@ class BulkJobLaunchSerializer(BaseSerializer):
|
|||||||
# validate Organization
|
# validate Organization
|
||||||
# - If the orgs is not set, set it to the org of the launching user
|
# - If the orgs is not set, set it to the org of the launching user
|
||||||
# - If the user is part of multiple orgs, throw a validation error saying user is part of multiple orgs, please provide one
|
# - If the user is part of multiple orgs, throw a validation error saying user is part of multiple orgs, please provide one
|
||||||
if 'organization' not in attrs or attrs['organization'] == None or attrs['organization'] == '':
|
if not request.user.is_superuser:
|
||||||
if Organization.accessible_pk_qs(request.user, 'read_role').count() == 1:
|
if 'organization' not in attrs or attrs['organization'] == None or attrs['organization'] == '':
|
||||||
for tup in Organization.accessible_pk_qs(request.user, 'read_role').all():
|
if Organization.accessible_pk_qs(request.user, 'read_role').count() == 1:
|
||||||
attrs['organization'] = Organization.objects.filter(id__in=str(tup[0])).first()
|
for tup in Organization.accessible_pk_qs(request.user, 'read_role').all():
|
||||||
elif Organization.accessible_pk_qs(request.user, 'read_role').count() > 1:
|
attrs['organization'] = Organization.objects.filter(id__in=str(tup[0])).first()
|
||||||
raise serializers.ValidationError("User has permission to multiple Organizations, please set one of them in the request")
|
elif Organization.accessible_pk_qs(request.user, 'read_role').count() > 1:
|
||||||
|
raise serializers.ValidationError("User has permission to multiple Organizations, please set one of them in the request")
|
||||||
|
else:
|
||||||
|
raise serializers.ValidationError("User not part of any organization, please assign an organization to assign to the bulk job")
|
||||||
else:
|
else:
|
||||||
raise serializers.ValidationError("User not part of any organization, please assign an organization to assign to the bulk job")
|
allowed_orgs = set()
|
||||||
else:
|
requested_org = attrs['organization']
|
||||||
allowed_orgs = set()
|
if request and not request.user.is_superuser:
|
||||||
requested_org = attrs['organization']
|
[allowed_orgs.add(tup[0]) for tup in Organization.accessible_pk_qs(request.user, 'read_role').all()]
|
||||||
if request and not request.user.is_superuser:
|
if requested_org.id not in allowed_orgs:
|
||||||
[allowed_orgs.add(tup[0]) for tup in Organization.accessible_pk_qs(request.user, 'read_role').all()]
|
raise ValidationError(_(f"Organization {requested_org.id} not found or you don't have permissions to access it"))
|
||||||
if requested_org.id not in allowed_orgs:
|
|
||||||
raise ValidationError(_(f"Organization {requested_org.id} not found or you don't have permissions to access it"))
|
|
||||||
|
|
||||||
def check_unified_job_permission(self, request, requested_ujts):
|
def check_unified_job_permission(self, request, requested_ujts):
|
||||||
allowed_ujts = set()
|
allowed_ujts = set()
|
||||||
@@ -4786,6 +4784,7 @@ class BulkJobLaunchSerializer(BaseSerializer):
|
|||||||
if requested_ujts - allowed_ujts:
|
if requested_ujts - allowed_ujts:
|
||||||
not_allowed = requested_ujts - allowed_ujts
|
not_allowed = requested_ujts - allowed_ujts
|
||||||
raise serializers.ValidationError(_(f"Unified Job Templates {not_allowed} not found or you don't have permissions to access it"))
|
raise serializers.ValidationError(_(f"Unified Job Templates {not_allowed} not found or you don't have permissions to access it"))
|
||||||
|
|
||||||
def check_inventory_permission(self, attrs, request, requested_use_inventories):
|
def check_inventory_permission(self, attrs, request, requested_use_inventories):
|
||||||
accessible_use_inventories = {tup[0] for tup in Inventory.accessible_pk_qs(request.user, 'use_role')}
|
accessible_use_inventories = {tup[0] for tup in Inventory.accessible_pk_qs(request.user, 'use_role')}
|
||||||
if requested_use_inventories - accessible_use_inventories:
|
if requested_use_inventories - accessible_use_inventories:
|
||||||
|
|||||||
@@ -4,43 +4,38 @@ This endpoint allows the client to create multiple hosts and associate them with
|
|||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```
|
{
|
||||||
{
|
"inventory": 1,
|
||||||
"inventory": 1,
|
"hosts": [
|
||||||
"hosts": [
|
{"name": "example1.com", "variables": "ansible_connection: local"},
|
||||||
{"name": "example1.com", "variables": "ansible_connection: local"},
|
{"name": "example2.com"}
|
||||||
{"name": "example2.com"}
|
]
|
||||||
]
|
}
|
||||||
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Return data:
|
Return data:
|
||||||
|
|
||||||
```commandline
|
{
|
||||||
{
|
"url": "/api/v2/inventories/3/hosts/",
|
||||||
"url": "/api/v2/inventories/3/hosts/",
|
"hosts": [
|
||||||
"hosts": [
|
{
|
||||||
{
|
"name": "example1.com",
|
||||||
"name": "example1.com",
|
"enabled": true,
|
||||||
"enabled": true,
|
"instance_id": "",
|
||||||
"instance_id": "",
|
"description": "",
|
||||||
"description": "",
|
"variables": "ansible_connection: local",
|
||||||
"variables": "ansible_connection: local",
|
"id": 1255,
|
||||||
"id": 1255,
|
"url": "/api/v2/hosts/1255/",
|
||||||
"url": "/api/v2/hosts/1255/",
|
"inventory": "/api/v2/inventories/3/"
|
||||||
"inventory": "/api/v2/inventories/3/"
|
},
|
||||||
},
|
{
|
||||||
{
|
"name": "example2.com",
|
||||||
"name": "example2.com",
|
"enabled": true,
|
||||||
"enabled": true,
|
"instance_id": "",
|
||||||
"instance_id": "",
|
"description": "",
|
||||||
"description": "",
|
"variables": "",
|
||||||
"variables": "",
|
"id": 1256,
|
||||||
"id": 1256,
|
"url": "/api/v2/hosts/1256/",
|
||||||
"url": "/api/v2/hosts/1256/",
|
"inventory": "/api/v2/inventories/3/"
|
||||||
"inventory": "/api/v2/inventories/3/"
|
}
|
||||||
}
|
]
|
||||||
]
|
}
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -4,13 +4,10 @@ This endpoint allows the client to launch multiple UnifiedJobTemplates at a time
|
|||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```
|
{
|
||||||
{
|
"name": "my bulk job",
|
||||||
"name": "my bulk job",
|
"jobs": [
|
||||||
"jobs": [
|
{"unified_job_template": 7, "inventory": 2},
|
||||||
{"unified_job_template": 7, "inventory": 2},
|
{"unified_job_template": 7, "credentials": [3]}
|
||||||
{"unified_job_template": 7, "credentials": [3]}
|
]
|
||||||
]
|
}
|
||||||
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ from rest_framework.reverse import reverse
|
|||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
|
||||||
|
from awx.main.models import UnifiedJob, Host
|
||||||
from awx.api.generics import (
|
from awx.api.generics import (
|
||||||
GenericAPIView,
|
GenericAPIView,
|
||||||
APIView,
|
APIView,
|
||||||
|
|||||||
@@ -15,7 +15,10 @@ page.register_page([resources.bulk, (resources.bulk, 'get')], Bulk)
|
|||||||
class BulkJobLaunch(base.Base):
|
class BulkJobLaunch(base.Base):
|
||||||
def post(self, payload={}):
|
def post(self, payload={}):
|
||||||
result = self.connection.post(self.endpoint, payload)
|
result = self.connection.post(self.endpoint, payload)
|
||||||
return self.walk(result.json()['url'])
|
if 'url' in result.json():
|
||||||
|
return self.walk(result.json()['url'])
|
||||||
|
else:
|
||||||
|
return self.page_identity(result, request_json={})
|
||||||
|
|
||||||
|
|
||||||
page.register_page(resources.bulk_job_launch, BulkJobLaunch)
|
page.register_page(resources.bulk_job_launch, BulkJobLaunch)
|
||||||
|
|||||||
Reference in New Issue
Block a user