mirror of
https://github.com/ansible/awx.git
synced 2026-01-09 23:12:08 -03:30
awxkit cli support
fixes for awx cli
This commit is contained in:
parent
861ba8a727
commit
34834252ff
@ -1971,7 +1971,8 @@ class BulkHostCreateSerializer(serializers.Serializer):
|
||||
inventory = serializers.PrimaryKeyRelatedField(
|
||||
queryset=Inventory.objects.all(), required=True, write_only=True, help_text=_('Primary Key ID of inventory to add hosts to.')
|
||||
)
|
||||
hosts = serializers.ListField(child=BulkHostSerializer(), allow_empty=False, max_length=1000, write_only=True, help_text=_('Hosts to be created.'))
|
||||
hosts_help_text = _('List of hosts to be created, JSON. e.g. [{"name": "example.com"}, {"name": "127.0.0.1"}]')
|
||||
hosts = serializers.ListField(child=BulkHostSerializer(), allow_empty=False, max_length=1000, write_only=True, help_text=hosts_help_text)
|
||||
|
||||
class Meta:
|
||||
fields = ('inventory', 'hosts')
|
||||
@ -4582,8 +4583,9 @@ class BulkJobNodeSerializer(serializers.Serializer):
|
||||
|
||||
|
||||
class BulkJobLaunchSerializer(BaseSerializer):
|
||||
name = serializers.CharField(max_length=512, write_only=True, required=False) # limited by max name of jobs
|
||||
jobs = BulkJobNodeSerializer(many=True, allow_empty=False, write_only=True, max_length=1000)
|
||||
name = serializers.CharField(default='Bulk Job Launch', max_length=512, write_only=True, required=False, allow_blank=True) # limited by max name of jobs
|
||||
job_node_help_text = _('List of jobs to be launched, JSON. e.g. [{"unified_job_template": 7}, {"unified_job_template": 10}]')
|
||||
jobs = BulkJobNodeSerializer(many=True, allow_empty=False, write_only=True, max_length=1000, help_text=job_node_help_text)
|
||||
description = serializers.CharField(write_only=True, required=False, allow_blank=False)
|
||||
extra_vars = serializers.CharField(write_only=True, required=False, allow_blank=False)
|
||||
organization = serializers.PrimaryKeyRelatedField(
|
||||
@ -4673,11 +4675,11 @@ class BulkJobLaunchSerializer(BaseSerializer):
|
||||
job_node_data = validated_data.pop('jobs')
|
||||
# FIXME: Need to set organization on the WorkflowJob in order for users to be able to see it --
|
||||
# normally their permission is sourced from the underlying WorkflowJobTemplate
|
||||
# maybe we need to add Organization to WorkflowJob
|
||||
if 'name' not in validated_data:
|
||||
validated_data['name'] = 'Bulk Job Launch'
|
||||
|
||||
# maybe we need to add Organization to WorkflowJobd
|
||||
wfj_limit = validated_data.pop('limit', None)
|
||||
wfj = WorkflowJob.objects.create(**validated_data, is_bulk_job=True)
|
||||
if wfj_limit:
|
||||
wfj.limit = wfj_limit
|
||||
nodes = []
|
||||
node_m2m_objects = {}
|
||||
node_m2m_object_types_to_through_model = {
|
||||
|
||||
@ -16,9 +16,25 @@ from awx.api import (
|
||||
)
|
||||
|
||||
|
||||
class BulkJobLaunchView(GenericAPIView):
|
||||
_ignore_model_permissions = True
|
||||
class BulkView(APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
renderer_classes = [
|
||||
renderers.BrowsableAPIRenderer,
|
||||
JSONRenderer,
|
||||
]
|
||||
allowed_methods = ['GET', 'OPTIONS']
|
||||
|
||||
def get(self, request, format=None):
|
||||
'''List top level resources'''
|
||||
data = OrderedDict()
|
||||
data['host_create'] = reverse('api:bulk_host_create', request=request)
|
||||
data['job_launch'] = reverse('api:bulk_job_launch', request=request)
|
||||
return Response(data)
|
||||
|
||||
|
||||
class BulkJobLaunchView(GenericAPIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
model = UnifiedJob
|
||||
serializer_class = serializers.BulkJobLaunchSerializer
|
||||
allowed_methods = ['GET', 'POST', 'OPTIONS']
|
||||
|
||||
@ -35,26 +51,9 @@ class BulkJobLaunchView(GenericAPIView):
|
||||
return Response(bulkjob_serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
|
||||
class BulkView(APIView):
|
||||
_ignore_model_permissions = True
|
||||
permission_classes = [IsAuthenticated]
|
||||
renderer_classes = [
|
||||
renderers.BrowsableAPIRenderer,
|
||||
JSONRenderer,
|
||||
]
|
||||
allowed_methods = ['GET', 'OPTIONS']
|
||||
|
||||
def get(self, request, format=None):
|
||||
'''List top level resources'''
|
||||
data = OrderedDict()
|
||||
data['bulk_host_create'] = reverse('api:bulk_host_create', request=request)
|
||||
data['bulk_job_launch'] = reverse('api:bulk_job_launch', request=request)
|
||||
return Response(data)
|
||||
|
||||
|
||||
class BulkHostCreateView(GenericAPIView):
|
||||
_ignore_model_permissions = True
|
||||
permission_classes = [IsAuthenticated]
|
||||
model = Host
|
||||
serializer_class = serializers.BulkHostCreateSerializer
|
||||
allowed_methods = ['GET', 'POST', 'OPTIONS']
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
# Order matters
|
||||
from .page import * # NOQA
|
||||
from .base import * # NOQA
|
||||
from .bulk import * # NOQA
|
||||
from .access_list import * # NOQA
|
||||
from .api import * # NOQA
|
||||
from .authtoken import * # NOQA
|
||||
|
||||
12
awxkit/awxkit/api/pages/bulk.py
Normal file
12
awxkit/awxkit/api/pages/bulk.py
Normal file
@ -0,0 +1,12 @@
|
||||
from awxkit.api.resources import resources
|
||||
from . import base
|
||||
from . import page
|
||||
|
||||
|
||||
class Bulk(base.Base):
|
||||
def get(self, **query_parameters):
|
||||
request = self.connection.get(self.endpoint, query_parameters, headers={'Accept': 'application/json'})
|
||||
return self.page_identity(request)
|
||||
|
||||
|
||||
page.register_page([resources.bulk, (resources.bulk, 'get')], Bulk)
|
||||
@ -13,6 +13,7 @@ class Resources(object):
|
||||
_applications = 'applications/'
|
||||
_auth = 'auth/'
|
||||
_authtoken = 'authtoken/'
|
||||
_bulk = 'bulk/'
|
||||
_config = 'config/'
|
||||
_config_attach = 'config/attach/'
|
||||
_credential = r'credentials/\d+/'
|
||||
|
||||
@ -44,6 +44,10 @@ class CustomAction(metaclass=CustomActionRegistryMeta):
|
||||
|
||||
|
||||
class Launchable(object):
|
||||
@property
|
||||
def options_endpoint(self):
|
||||
return self.page.endpoint + '1/{}/'.format(self.action)
|
||||
|
||||
def add_arguments(self, parser, resource_options_parser, with_pk=True):
|
||||
from .options import pk_or_name
|
||||
|
||||
@ -53,7 +57,7 @@ class Launchable(object):
|
||||
parser.choices[self.action].add_argument('--action-timeout', type=int, help='If set with --monitor or --wait, time out waiting on job completion.')
|
||||
parser.choices[self.action].add_argument('--wait', action='store_true', help='If set, waits until the launched job finishes.')
|
||||
|
||||
launch_time_options = self.page.connection.options(self.page.endpoint + '1/{}/'.format(self.action))
|
||||
launch_time_options = self.page.connection.options(self.options_endpoint)
|
||||
if launch_time_options.ok:
|
||||
launch_time_options = launch_time_options.json()['actions']['POST']
|
||||
resource_options_parser.options['LAUNCH'] = launch_time_options
|
||||
@ -90,6 +94,48 @@ class JobTemplateLaunch(Launchable, CustomAction):
|
||||
resource = 'job_templates'
|
||||
|
||||
|
||||
class BulkJobLaunch(Launchable, CustomAction):
|
||||
action = 'job_launch'
|
||||
resource = 'bulk'
|
||||
|
||||
@property
|
||||
def options_endpoint(self):
|
||||
return self.page.endpoint + '{}/'.format(self.action)
|
||||
|
||||
def add_arguments(self, parser, resource_options_parser):
|
||||
Launchable.add_arguments(self, parser, resource_options_parser, with_pk=False)
|
||||
|
||||
def perform(self, **kwargs):
|
||||
monitor_kwargs = {
|
||||
'monitor': kwargs.pop('monitor', False),
|
||||
'wait': kwargs.pop('wait', False),
|
||||
'action_timeout': kwargs.pop('action_timeout', False),
|
||||
}
|
||||
response = self.page.get().job_launch.post(kwargs)
|
||||
self.monitor(response, **monitor_kwargs)
|
||||
return response
|
||||
|
||||
|
||||
class BulkHostCreate(CustomAction):
|
||||
action = 'host_create'
|
||||
resource = 'bulk'
|
||||
|
||||
@property
|
||||
def options_endpoint(self):
|
||||
return self.page.endpoint + '{}/'.format(self.action)
|
||||
|
||||
def add_arguments(self, parser, resource_options_parser):
|
||||
options = self.page.connection.options(self.options_endpoint)
|
||||
if options.ok:
|
||||
options = options.json()['actions']['POST']
|
||||
resource_options_parser.options['HOSTCREATEPOST'] = options
|
||||
resource_options_parser.build_query_arguments(self.action, 'HOSTCREATEPOST')
|
||||
|
||||
def perform(self, **kwargs):
|
||||
response = self.page.get().host_create.post(kwargs)
|
||||
return response
|
||||
|
||||
|
||||
class ProjectUpdate(Launchable, CustomAction):
|
||||
action = 'update'
|
||||
resource = 'projects'
|
||||
|
||||
@ -163,7 +163,10 @@ class ResourceOptionsParser(object):
|
||||
if method == 'list' and param.get('filterable') is False:
|
||||
continue
|
||||
|
||||
def json_or_yaml(v):
|
||||
def list_of_json_or_yaml(v):
|
||||
return json_or_yaml(v, expected_type=list)
|
||||
|
||||
def json_or_yaml(v, expected_type=dict):
|
||||
if v.startswith('@'):
|
||||
v = open(os.path.expanduser(v[1:])).read()
|
||||
try:
|
||||
@ -174,15 +177,16 @@ class ResourceOptionsParser(object):
|
||||
except Exception:
|
||||
raise argparse.ArgumentTypeError("{} is not valid JSON or YAML".format(v))
|
||||
|
||||
if not isinstance(parsed, dict):
|
||||
if not isinstance(parsed, expected_type):
|
||||
raise argparse.ArgumentTypeError("{} is not valid JSON or YAML".format(v))
|
||||
|
||||
for k, v in parsed.items():
|
||||
# add support for file reading at top-level JSON keys
|
||||
# (to make things like SSH key data easier to work with)
|
||||
if isinstance(v, str) and v.startswith('@'):
|
||||
path = os.path.expanduser(v[1:])
|
||||
parsed[k] = open(path).read()
|
||||
if expected_type is dict:
|
||||
for k, v in parsed.items():
|
||||
# add support for file reading at top-level JSON keys
|
||||
# (to make things like SSH key data easier to work with)
|
||||
if isinstance(v, str) and v.startswith('@'):
|
||||
path = os.path.expanduser(v[1:])
|
||||
parsed[k] = open(path).read()
|
||||
|
||||
return parsed
|
||||
|
||||
@ -258,6 +262,19 @@ class ResourceOptionsParser(object):
|
||||
if k == 'extra_vars':
|
||||
args.append('-e')
|
||||
|
||||
# special handling for bulk endpoints
|
||||
if self.resource == 'bulk':
|
||||
if method == "host_create":
|
||||
if k == "inventory":
|
||||
kwargs['required'] = required = True
|
||||
if k == 'hosts':
|
||||
kwargs['type'] = list_of_json_or_yaml
|
||||
kwargs['required'] = required = True
|
||||
if method == "job_launch":
|
||||
if k == 'jobs':
|
||||
kwargs['type'] = list_of_json_or_yaml
|
||||
kwargs['required'] = required = True
|
||||
|
||||
if required:
|
||||
if required_group is None:
|
||||
required_group = self.parser.choices[method].add_argument_group('required arguments')
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user