Moved API code into separate Django app.

This commit is contained in:
Chris Church 2013-11-04 15:44:43 -05:00
parent 2a58d50cfa
commit 98883e771f
61 changed files with 1553 additions and 1546 deletions

View File

@ -98,7 +98,7 @@ class APIView(views.APIView):
template_list = []
for klass in inspect.getmro(type(self)):
template_basename = camelcase_to_underscore(klass.__name__)
template_list.append('main/%s.md' % template_basename)
template_list.append('api/%s.md' % template_basename)
context = self.get_description_context()
return render_to_string(template_list, context)

4
awx/api/models.py Normal file
View File

@ -0,0 +1,4 @@
# Copyright (c) 2013 AnsibleWorks, Inc.
# All Rights Reserved.
# Empty models file.

View File

@ -16,7 +16,7 @@ from awx.main.access import *
from awx.main.models import *
from awx.main.utils import get_object_or_400
logger = logging.getLogger('awx.main.permissions')
logger = logging.getLogger('awx.api.permissions')
__all__ = ['ModelAccessPermission', 'JobTemplateCallbackPermission',
'JobTaskPermission']

View File

@ -132,14 +132,14 @@ class BaseSerializer(serializers.ModelSerializer):
if obj is None:
return ''
elif isinstance(obj, User):
return reverse('main:user_detail', args=(obj.pk,))
return reverse('api:user_detail', args=(obj.pk,))
else:
return obj.get_absolute_url()
def get_related(self, obj):
res = SortedDict()
if getattr(obj, 'created_by', None):
res['created_by'] = reverse('main:user_detail', args=(obj.created_by.pk,))
res['created_by'] = reverse('api:user_detail', args=(obj.created_by.pk,))
return res
def get_summary_fields(self, obj):
@ -237,12 +237,12 @@ class UserSerializer(BaseSerializer):
return {}
res = super(UserSerializer, self).get_related(obj)
res.update(dict(
teams = reverse('main:user_teams_list', args=(obj.pk,)),
organizations = reverse('main:user_organizations_list', args=(obj.pk,)),
admin_of_organizations = reverse('main:user_admin_of_organizations_list', args=(obj.pk,)),
projects = reverse('main:user_projects_list', args=(obj.pk,)),
credentials = reverse('main:user_credentials_list', args=(obj.pk,)),
permissions = reverse('main:user_permissions_list', args=(obj.pk,)),
teams = reverse('api:user_teams_list', args=(obj.pk,)),
organizations = reverse('api:user_organizations_list', args=(obj.pk,)),
admin_of_organizations = reverse('api:user_admin_of_organizations_list', args=(obj.pk,)),
projects = reverse('api:user_projects_list', args=(obj.pk,)),
credentials = reverse('api:user_credentials_list', args=(obj.pk,)),
permissions = reverse('api:user_permissions_list', args=(obj.pk,)),
))
return res
@ -286,13 +286,13 @@ class OrganizationSerializer(BaseSerializer):
return {}
res = super(OrganizationSerializer, self).get_related(obj)
res.update(dict(
#audit_trail = reverse('main:organization_audit_trail_list', args=(obj.pk,)),
projects = reverse('main:organization_projects_list', args=(obj.pk,)),
inventories = reverse('main:organization_inventories_list', args=(obj.pk,)),
users = reverse('main:organization_users_list', args=(obj.pk,)),
admins = reverse('main:organization_admins_list', args=(obj.pk,)),
#tags = reverse('main:organization_tags_list', args=(obj.pk,)),
teams = reverse('main:organization_teams_list', args=(obj.pk,)),
#audit_trail = reverse('api:organization_audit_trail_list', args=(obj.pk,)),
projects = reverse('api:organization_projects_list', args=(obj.pk,)),
inventories = reverse('api:organization_inventories_list', args=(obj.pk,)),
users = reverse('api:organization_users_list', args=(obj.pk,)),
admins = reverse('api:organization_admins_list', args=(obj.pk,)),
#tags = reverse('api:organization_tags_list', args=(obj.pk,)),
teams = reverse('api:organization_teams_list', args=(obj.pk,)),
))
return res
@ -314,20 +314,20 @@ class ProjectSerializer(BaseSerializer):
return {}
res = super(ProjectSerializer, self).get_related(obj)
res.update(dict(
organizations = reverse('main:project_organizations_list', args=(obj.pk,)),
teams = reverse('main:project_teams_list', args=(obj.pk,)),
playbooks = reverse('main:project_playbooks', args=(obj.pk,)),
update = reverse('main:project_update_view', args=(obj.pk,)),
project_updates = reverse('main:project_updates_list', args=(obj.pk,)),
organizations = reverse('api:project_organizations_list', args=(obj.pk,)),
teams = reverse('api:project_teams_list', args=(obj.pk,)),
playbooks = reverse('api:project_playbooks', args=(obj.pk,)),
update = reverse('api:project_update_view', args=(obj.pk,)),
project_updates = reverse('api:project_updates_list', args=(obj.pk,)),
))
if obj.credential:
res['credential'] = reverse('main:credential_detail',
res['credential'] = reverse('api:credential_detail',
args=(obj.credential.pk,))
if obj.current_update:
res['current_update'] = reverse('main:project_update_detail',
res['current_update'] = reverse('api:project_update_detail',
args=(obj.current_update.pk,))
if obj.last_update:
res['last_update'] = reverse('main:project_update_detail',
res['last_update'] = reverse('api:project_update_detail',
args=(obj.last_update.pk,))
return res
@ -433,8 +433,8 @@ class ProjectUpdateSerializer(BaseSerializer):
return {}
res = super(ProjectUpdateSerializer, self).get_related(obj)
res.update(dict(
project = reverse('main:project_detail', args=(obj.project.pk,)),
cancel = reverse('main:project_update_cancel', args=(obj.pk,)),
project = reverse('api:project_detail', args=(obj.project.pk,)),
cancel = reverse('api:project_update_cancel', args=(obj.pk,)),
))
return res
@ -467,14 +467,14 @@ class InventorySerializer(BaseSerializerWithVariables):
return {}
res = super(InventorySerializer, self).get_related(obj)
res.update(dict(
hosts = reverse('main:inventory_hosts_list', args=(obj.pk,)),
groups = reverse('main:inventory_groups_list', args=(obj.pk,)),
root_groups = reverse('main:inventory_root_groups_list', args=(obj.pk,)),
variable_data = reverse('main:inventory_variable_data', args=(obj.pk,)),
script = reverse('main:inventory_script_view', args=(obj.pk,)),
tree = reverse('main:inventory_tree_view', args=(obj.pk,)),
organization = reverse('main:organization_detail', args=(obj.organization.pk,)),
inventory_sources = reverse('main:inventory_inventory_sources_list', args=(obj.pk,)),
hosts = reverse('api:inventory_hosts_list', args=(obj.pk,)),
groups = reverse('api:inventory_groups_list', args=(obj.pk,)),
root_groups = reverse('api:inventory_root_groups_list', args=(obj.pk,)),
variable_data = reverse('api:inventory_variable_data', args=(obj.pk,)),
script = reverse('api:inventory_script_view', args=(obj.pk,)),
tree = reverse('api:inventory_tree_view', args=(obj.pk,)),
organization = reverse('api:organization_detail', args=(obj.organization.pk,)),
inventory_sources = reverse('api:inventory_inventory_sources_list', args=(obj.pk,)),
))
return res
@ -491,18 +491,18 @@ class HostSerializer(BaseSerializerWithVariables):
return {}
res = super(HostSerializer, self).get_related(obj)
res.update(dict(
variable_data = reverse('main:host_variable_data', args=(obj.pk,)),
inventory = reverse('main:inventory_detail', args=(obj.inventory.pk,)),
groups = reverse('main:host_groups_list', args=(obj.pk,)),
all_groups = reverse('main:host_all_groups_list', args=(obj.pk,)),
job_events = reverse('main:host_job_events_list', args=(obj.pk,)),
job_host_summaries = reverse('main:host_job_host_summaries_list', args=(obj.pk,)),
#inventory_sources = reverse('main:host_inventory_sources_list', args=(obj.pk,)),
variable_data = reverse('api:host_variable_data', args=(obj.pk,)),
inventory = reverse('api:inventory_detail', args=(obj.inventory.pk,)),
groups = reverse('api:host_groups_list', args=(obj.pk,)),
all_groups = reverse('api:host_all_groups_list', args=(obj.pk,)),
job_events = reverse('api:host_job_events_list', args=(obj.pk,)),
job_host_summaries = reverse('api:host_job_host_summaries_list', args=(obj.pk,)),
#inventory_sources = reverse('api:host_inventory_sources_list', args=(obj.pk,)),
))
if obj.last_job:
res['last_job'] = reverse('main:job_detail', args=(obj.last_job.pk,))
res['last_job'] = reverse('api:job_detail', args=(obj.last_job.pk,))
if obj.last_job_host_summary:
res['last_job_host_summary'] = reverse('main:job_host_summary_detail', args=(obj.last_job_host_summary.pk,))
res['last_job_host_summary'] = reverse('api:job_host_summary_detail', args=(obj.last_job_host_summary.pk,))
return res
def get_summary_fields(self, obj):
@ -589,16 +589,16 @@ class GroupSerializer(BaseSerializerWithVariables):
return {}
res = super(GroupSerializer, self).get_related(obj)
res.update(dict(
variable_data = reverse('main:group_variable_data', args=(obj.pk,)),
hosts = reverse('main:group_hosts_list', args=(obj.pk,)),
potential_children = reverse('main:group_potential_children_list', args=(obj.pk,)),
children = reverse('main:group_children_list', args=(obj.pk,)),
all_hosts = reverse('main:group_all_hosts_list', args=(obj.pk,)),
inventory = reverse('main:inventory_detail', args=(obj.inventory.pk,)),
job_events = reverse('main:group_job_events_list', args=(obj.pk,)),
job_host_summaries = reverse('main:group_job_host_summaries_list', args=(obj.pk,)),
inventory_source = reverse('main:inventory_source_detail', args=(obj.inventory_source.pk,)),
#inventory_sources = reverse('main:group_inventory_sources_list', args=(obj.pk,)),
variable_data = reverse('api:group_variable_data', args=(obj.pk,)),
hosts = reverse('api:group_hosts_list', args=(obj.pk,)),
potential_children = reverse('api:group_potential_children_list', args=(obj.pk,)),
children = reverse('api:group_children_list', args=(obj.pk,)),
all_hosts = reverse('api:group_all_hosts_list', args=(obj.pk,)),
inventory = reverse('api:inventory_detail', args=(obj.inventory.pk,)),
job_events = reverse('api:group_job_events_list', args=(obj.pk,)),
job_host_summaries = reverse('api:group_job_host_summaries_list', args=(obj.pk,)),
inventory_source = reverse('api:inventory_source_detail', args=(obj.inventory_source.pk,)),
#inventory_sources = reverse('api:group_inventory_sources_list', args=(obj.pk,)),
))
return res
@ -676,23 +676,23 @@ class InventorySourceSerializer(BaseSerializer):
return {}
res = super(InventorySourceSerializer, self).get_related(obj)
res.update(dict(
update = reverse('main:inventory_source_update_view', args=(obj.pk,)),
inventory_updates = reverse('main:inventory_source_updates_list', args=(obj.pk,)),
#hosts = reverse('main:inventory_source_hosts_list', args=(obj.pk,)),
#groups = reverse('main:inventory_source_groups_list', args=(obj.pk,)),
update = reverse('api:inventory_source_update_view', args=(obj.pk,)),
inventory_updates = reverse('api:inventory_source_updates_list', args=(obj.pk,)),
#hosts = reverse('api:inventory_source_hosts_list', args=(obj.pk,)),
#groups = reverse('api:inventory_source_groups_list', args=(obj.pk,)),
))
if obj.inventory:
res['inventory'] = reverse('main:inventory_detail', args=(obj.inventory.pk,))
res['inventory'] = reverse('api:inventory_detail', args=(obj.inventory.pk,))
if obj.group:
res['group'] = reverse('main:group_detail', args=(obj.group.pk,))
res['group'] = reverse('api:group_detail', args=(obj.group.pk,))
if obj.credential:
res['credential'] = reverse('main:credential_detail',
res['credential'] = reverse('api:credential_detail',
args=(obj.credential.pk,))
if obj.current_update:
res['current_update'] = reverse('main:inventory_update_detail',
res['current_update'] = reverse('api:inventory_update_detail',
args=(obj.current_update.pk,))
if obj.last_update:
res['last_update'] = reverse('main:inventory_update_detail',
res['last_update'] = reverse('api:inventory_update_detail',
args=(obj.last_update.pk,))
return res
@ -741,8 +741,8 @@ class InventoryUpdateSerializer(BaseSerializer):
return {}
res = super(InventoryUpdateSerializer, self).get_related(obj)
res.update(dict(
inventory_source = reverse('main:inventory_source_detail', args=(obj.inventory_source.pk,)),
cancel = reverse('main:inventory_update_cancel', args=(obj.pk,)),
inventory_source = reverse('api:inventory_source_detail', args=(obj.inventory_source.pk,)),
cancel = reverse('api:inventory_update_cancel', args=(obj.pk,)),
))
return res
@ -757,11 +757,11 @@ class TeamSerializer(BaseSerializer):
return {}
res = super(TeamSerializer, self).get_related(obj)
res.update(dict(
projects = reverse('main:team_projects_list', args=(obj.pk,)),
users = reverse('main:team_users_list', args=(obj.pk,)),
credentials = reverse('main:team_credentials_list', args=(obj.pk,)),
organization = reverse('main:organization_detail', args=(obj.organization.pk,)),
permissions = reverse('main:team_permissions_list', args=(obj.pk,)),
projects = reverse('api:team_projects_list', args=(obj.pk,)),
users = reverse('api:team_users_list', args=(obj.pk,)),
credentials = reverse('api:team_credentials_list', args=(obj.pk,)),
organization = reverse('api:organization_detail', args=(obj.organization.pk,)),
permissions = reverse('api:team_permissions_list', args=(obj.pk,)),
))
return res
@ -777,13 +777,13 @@ class PermissionSerializer(BaseSerializer):
return {}
res = super(PermissionSerializer, self).get_related(obj)
if obj.user:
res['user'] = reverse('main:user_detail', args=(obj.user.pk,))
res['user'] = reverse('api:user_detail', args=(obj.user.pk,))
if obj.team:
res['team'] = reverse('main:team_detail', args=(obj.team.pk,))
res['team'] = reverse('api:team_detail', args=(obj.team.pk,))
if obj.project:
res['project'] = reverse('main:project_detail', args=(obj.project.pk,))
res['project'] = reverse('api:project_detail', args=(obj.project.pk,))
if obj.inventory:
res['inventory'] = reverse('main:inventory_detail', args=(obj.inventory.pk,))
res['inventory'] = reverse('api:inventory_detail', args=(obj.inventory.pk,))
return res
def validate(self, attrs):
@ -837,9 +837,9 @@ class CredentialSerializer(BaseSerializer):
return {}
res = super(CredentialSerializer, self).get_related(obj)
if obj.user:
res['user'] = reverse('main:user_detail', args=(obj.user.pk,))
res['user'] = reverse('api:user_detail', args=(obj.user.pk,))
if obj.team:
res['team'] = reverse('main:team_detail', args=(obj.team.pk,))
res['team'] = reverse('api:team_detail', args=(obj.team.pk,))
return res
class JobTemplateSerializer(BaseSerializer):
@ -855,14 +855,14 @@ class JobTemplateSerializer(BaseSerializer):
return {}
res = super(JobTemplateSerializer, self).get_related(obj)
res.update(dict(
inventory = reverse('main:inventory_detail', args=(obj.inventory.pk,)),
project = reverse('main:project_detail', args=(obj.project.pk,)),
jobs = reverse('main:job_template_jobs_list', args=(obj.pk,)),
inventory = reverse('api:inventory_detail', args=(obj.inventory.pk,)),
project = reverse('api:project_detail', args=(obj.project.pk,)),
jobs = reverse('api:job_template_jobs_list', args=(obj.pk,)),
))
if obj.credential:
res['credential'] = reverse('main:credential_detail', args=(obj.credential.pk,))
res['credential'] = reverse('api:credential_detail', args=(obj.credential.pk,))
if obj.host_config_key:
res['callback'] = reverse('main:job_template_callback', args=(obj.pk,))
res['callback'] = reverse('api:job_template_callback', args=(obj.pk,))
return res
def validate_playbook(self, attrs, source):
@ -892,18 +892,18 @@ class JobSerializer(BaseSerializer):
return {}
res = super(JobSerializer, self).get_related(obj)
res.update(dict(
inventory = reverse('main:inventory_detail', args=(obj.inventory.pk,)),
project = reverse('main:project_detail', args=(obj.project.pk,)),
credential = reverse('main:credential_detail', args=(obj.credential.pk,)),
job_events = reverse('main:job_job_events_list', args=(obj.pk,)),
job_host_summaries = reverse('main:job_job_host_summaries_list', args=(obj.pk,)),
inventory = reverse('api:inventory_detail', args=(obj.inventory.pk,)),
project = reverse('api:project_detail', args=(obj.project.pk,)),
credential = reverse('api:credential_detail', args=(obj.credential.pk,)),
job_events = reverse('api:job_job_events_list', args=(obj.pk,)),
job_host_summaries = reverse('api:job_job_host_summaries_list', args=(obj.pk,)),
))
if obj.job_template:
res['job_template'] = reverse('main:job_template_detail', args=(obj.job_template.pk,))
res['job_template'] = reverse('api:job_template_detail', args=(obj.job_template.pk,))
if obj.can_start or True:
res['start'] = reverse('main:job_start', args=(obj.pk,))
res['start'] = reverse('api:job_start', args=(obj.pk,))
if obj.can_cancel or True:
res['cancel'] = reverse('main:job_cancel', args=(obj.pk,))
res['cancel'] = reverse('api:job_cancel', args=(obj.pk,))
return res
def from_native(self, data, files):
@ -942,8 +942,8 @@ class JobHostSummarySerializer(BaseSerializer):
return {}
res = super(JobHostSummarySerializer, self).get_related(obj)
res.update(dict(
job=reverse('main:job_detail', args=(obj.job.pk,)),
host=reverse('main:host_detail', args=(obj.host.pk,))
job=reverse('api:job_detail', args=(obj.job.pk,)),
host=reverse('api:host_detail', args=(obj.host.pk,))
))
return res
@ -975,17 +975,17 @@ class JobEventSerializer(BaseSerializer):
return {}
res = super(JobEventSerializer, self).get_related(obj)
res.update(dict(
job = reverse('main:job_detail', args=(obj.job.pk,)),
#children = reverse('main:job_event_children_list', args=(obj.pk,)),
job = reverse('api:job_detail', args=(obj.job.pk,)),
#children = reverse('api:job_event_children_list', args=(obj.pk,)),
))
if obj.parent:
res['parent'] = reverse('main:job_event_detail', args=(obj.parent.pk,))
res['parent'] = reverse('api:job_event_detail', args=(obj.parent.pk,))
if obj.children.count():
res['children'] = reverse('main:job_event_children_list', args=(obj.pk,))
res['children'] = reverse('api:job_event_children_list', args=(obj.pk,))
if obj.host:
res['host'] = reverse('main:host_detail', args=(obj.host.pk,))
res['host'] = reverse('api:host_detail', args=(obj.host.pk,))
if obj.hosts.count():
res['hosts'] = reverse('main:job_event_hosts_list', args=(obj.pk,))
res['hosts'] = reverse('api:job_event_hosts_list', args=(obj.pk,))
return res
def get_summary_fields(self, obj):

View File

@ -18,7 +18,7 @@ additional results if there are more than will fit on a single page. The
Each {{ model_verbose_name }} data structure includes the following fields:
{% include "main/_result_fields_common.md" %}
{% include "api/_result_fields_common.md" %}
## Sorting

View File

@ -0,0 +1,3 @@
{{ docstring }}
{% include "api/_new_in_awx.md" %}

View File

@ -4,4 +4,4 @@ Make a GET request to this resource to retrieve a list of all
{{ model_verbose_name_plural }} directly or indirectly belonging to this
{{ parent_model_verbose_name }}.
{% include "main/_list_common.md" %}
{% include "api/_list_common.md" %}

View File

@ -4,6 +4,6 @@ Make a GET request to this resource to retrieve a list of
{{ model_verbose_name_plural }} available to be added as children of the
current {{ parent_model_verbose_name }}.
{% include "main/_list_common.md" %}
{% include "api/_list_common.md" %}
{% include "main/_new_in_awx.md" %}
{% include "api/_new_in_awx.md" %}

View File

@ -4,4 +4,4 @@ Make a GET request to this resource to retrieve a list of all
{{ model_verbose_name_plural }} of which the selected
{{ parent_model_verbose_name }} is directly or indirectly a member.
{% include "main/_list_common.md" %}
{% include "api/_list_common.md" %}

View File

@ -4,4 +4,4 @@ Make a GET request to this resource to retrieve a list of root (top-level)
{{ model_verbose_name_plural }} associated with this
{{ parent_model_verbose_name }}.
{% include "main/_list_common.md" %}
{% include "api/_list_common.md" %}

View File

@ -10,4 +10,4 @@ Make a POST request to this resource to cancel a pending or running inventory
update. The response status code will be 202 if successful, or 405 if the
update cannot be canceled.
{% include "main/_new_in_awx.md" %}
{% include "api/_new_in_awx.md" %}

View File

@ -15,4 +15,4 @@ If successful, the response status code will be 202. If any required passwords
are not provided, a 400 status code will be returned. If the inventory source
is not defined or cannot be updated, a 405 status code will be returned.
{% include "main/_new_in_awx.md" %}
{% include "api/_new_in_awx.md" %}

View File

@ -10,6 +10,6 @@ also containing a list of its children.
Each group data structure includes the following fields:
{% include "main/_result_fields_common.md" %}
{% include "api/_result_fields_common.md" %}
{% include "main/_new_in_awx.md" %}
{% include "api/_new_in_awx.md" %}

View File

@ -1,4 +1,4 @@
{% include "main/list_create_api_view.md" %}
{% include "api/list_create_api_view.md" %}
If the `job_template` field is specified, any fields not explicitly provided
for the new job (except `name` and `description`) will use the default values

View File

@ -1,4 +1,4 @@
{% extends "main/sub_list_create_api_view.md" %}
{% extends "api/sub_list_create_api_view.md" %}
{% block post_create %}
Any fields not explicitly provided for the new job (except `name` and

View File

@ -3,6 +3,6 @@
Make a GET request to this resource to retrieve the list of
{{ model_verbose_name_plural }}.
{% include "main/_list_common.md" %}
{% include "api/_list_common.md" %}
{% include "main/_new_in_awx.md" %}
{% include "api/_new_in_awx.md" %}

View File

@ -1,4 +1,4 @@
{% include "main/list_api_view.md" %}
{% include "api/list_api_view.md" %}
# Create {{ model_verbose_name_plural|title }}:
@ -6,7 +6,7 @@ Make a POST request to this resource with the following {{ model_verbose_name }}
fields to create a new {{ model_verbose_name }}:
{% with write_only=1 %}
{% include "main/_result_fields_common.md" %}
{% include "api/_result_fields_common.md" %}
{% endwith %}
{% include "main/_new_in_awx.md" %}
{% include "api/_new_in_awx.md" %}

View File

@ -1,3 +1,3 @@
{% with model_verbose_name="admin user" model_verbose_name_plural="admin users" %}
{% include "main/sub_list_create_api_view.md" %}
{% include "api/sub_list_create_api_view.md" %}
{% endwith %}

View File

@ -10,4 +10,4 @@ Make a POST request to this resource to cancel a pending or running project
update. The response status code will be 202 if successful, or 405 if the
update cannot be canceled.
{% include "main/_new_in_awx.md" %}
{% include "api/_new_in_awx.md" %}

View File

@ -15,4 +15,4 @@ If successful, the response status code will be 202. If any required passwords
are not provided, a 400 status code will be returned. If the project cannot be
updated, a 405 status code will be returned.
{% include "main/_new_in_awx.md" %}
{% include "api/_new_in_awx.md" %}

View File

@ -3,7 +3,7 @@
Make GET request to this resource to retrieve a single {{ model_verbose_name }}
record containing the following fields:
{% include "main/_result_fields_common.md" %}
{% include "api/_result_fields_common.md" %}
{% include "main/_new_in_awx.md" %}
{% include "api/_new_in_awx.md" %}

View File

@ -1,4 +1,4 @@
{% include "main/retrieve_api_view.md" %}
{% include "api/retrieve_api_view.md" %}
# Update {{ model_verbose_name|title }}:
@ -6,11 +6,11 @@ Make a PUT or PATCH request to this resource to update this
{{ model_verbose_name }}. The following fields may be modified:
{% with write_only=1 %}
{% include "main/_result_fields_common.md" %}
{% include "api/_result_fields_common.md" %}
{% endwith %}
For a PUT request, include **all** fields in the request.
For a PATCH request, include only the fields that are being modified.
{% include "main/_new_in_awx.md" %}
{% include "api/_new_in_awx.md" %}

View File

@ -1,4 +1,4 @@
{% include "main/retrieve_api_view.md" %}
{% include "api/retrieve_api_view.md" %}
# Update {{ model_verbose_name|title }}:
@ -6,7 +6,7 @@ Make a PUT or PATCH request to this resource to update this
{{ model_verbose_name }}. The following fields may be modified:
{% with write_only=1 %}
{% include "main/_result_fields_common.md" %}
{% include "api/_result_fields_common.md" %}
{% endwith %}
For a PUT request, include **all** fields in the request.
@ -17,4 +17,4 @@ For a PATCH request, include only the fields that are being modified.
Make a DELETE request to this resource to delete this {{ model_verbose_name }}.
{% include "main/_new_in_awx.md" %}
{% include "api/_new_in_awx.md" %}

View File

@ -4,6 +4,6 @@ Make a GET request to this resource to retrieve a list of
{{ model_verbose_name_plural }} associated with the selected
{{ parent_model_verbose_name }}.
{% include "main/_list_common.md" %}
{% include "api/_list_common.md" %}
{% include "main/_new_in_awx.md" %}
{% include "api/_new_in_awx.md" %}

View File

@ -1,4 +1,4 @@
{% include "main/sub_list_api_view.md" %}
{% include "api/sub_list_api_view.md" %}
# Create {{ model_verbose_name_plural|title }} for this {{ parent_model_verbose_name|title }}:
@ -7,7 +7,7 @@ fields to create a new {{ model_verbose_name }} associated with this
{{ parent_model_verbose_name }}.
{% with write_only=1 %}
{% include "main/_result_fields_common.md" %}
{% include "api/_result_fields_common.md" %}
{% endwith %}
{% block post_create %}{% endblock %}
@ -36,4 +36,4 @@ remove the {{ model_verbose_name }} from this {{ parent_model_verbose_name }}
without deleting the {{ model_verbose_name }}.
{% endif %}
{% include "main/_new_in_awx.md" %}
{% include "api/_new_in_awx.md" %}

View File

@ -4,4 +4,4 @@ Make a GET request to this resource to retrieve a list of
{{ model_verbose_name_plural }} of which the selected
{{ parent_model_verbose_name }} is an admin.
{% include "main/_list_common.md" %}
{% include "api/_list_common.md" %}

View File

@ -2,6 +2,6 @@ Make a GET request to retrieve user information about the current user.
One result should be returned containing the following fields:
{% include "main/_result_fields_common.md" %}
{% include "api/_result_fields_common.md" %}
Use the primary URL for the user (/api/v1/users/N/) to modify the user.

170
awx/api/urls.py Normal file
View File

@ -0,0 +1,170 @@
# Copyright (c) 2013 AnsibleWorks, Inc.
# All Rights Reserved.
from django.conf.urls import include, patterns, url as original_url
def url(regex, view, kwargs=None, name=None, prefix=''):
# Set default name from view name (if a string).
if isinstance(view, basestring) and name is None:
name = view
return original_url(regex, view, kwargs, name, prefix)
organization_urls = patterns('awx.api.views',
url(r'^$', 'organization_list'),
url(r'^(?P<pk>[0-9]+)/$', 'organization_detail'),
url(r'^(?P<pk>[0-9]+)/users/$', 'organization_users_list'),
url(r'^(?P<pk>[0-9]+)/admins/$', 'organization_admins_list'),
url(r'^(?P<pk>[0-9]+)/inventories/$', 'organization_inventories_list'),
url(r'^(?P<pk>[0-9]+)/projects/$', 'organization_projects_list'),
url(r'^(?P<pk>[0-9]+)/teams/$', 'organization_teams_list'),
)
user_urls = patterns('awx.api.views',
url(r'^$', 'user_list'),
url(r'^(?P<pk>[0-9]+)/$', 'user_detail'),
url(r'^(?P<pk>[0-9]+)/teams/$', 'user_teams_list'),
url(r'^(?P<pk>[0-9]+)/organizations/$', 'user_organizations_list'),
url(r'^(?P<pk>[0-9]+)/admin_of_organizations/$', 'user_admin_of_organizations_list'),
url(r'^(?P<pk>[0-9]+)/projects/$', 'user_projects_list'),
url(r'^(?P<pk>[0-9]+)/credentials/$', 'user_credentials_list'),
url(r'^(?P<pk>[0-9]+)/permissions/$', 'user_permissions_list'),
)
project_urls = patterns('awx.api.views',
url(r'^$', 'project_list'),
url(r'^(?P<pk>[0-9]+)/$', 'project_detail'),
url(r'^(?P<pk>[0-9]+)/playbooks/$', 'project_playbooks'),
url(r'^(?P<pk>[0-9]+)/organizations/$', 'project_organizations_list'),
url(r'^(?P<pk>[0-9]+)/teams/$', 'project_teams_list'),
url(r'^(?P<pk>[0-9]+)/update/$', 'project_update_view'),
url(r'^(?P<pk>[0-9]+)/project_updates/$', 'project_updates_list'),
)
project_update_urls = patterns('awx.api.views',
url(r'^(?P<pk>[0-9]+)/$', 'project_update_detail'),
url(r'^(?P<pk>[0-9]+)/cancel/$', 'project_update_cancel'),
)
team_urls = patterns('awx.api.views',
url(r'^$', 'team_list'),
url(r'^(?P<pk>[0-9]+)/$', 'team_detail'),
url(r'^(?P<pk>[0-9]+)/projects/$', 'team_projects_list'),
url(r'^(?P<pk>[0-9]+)/users/$', 'team_users_list'),
url(r'^(?P<pk>[0-9]+)/credentials/$', 'team_credentials_list'),
url(r'^(?P<pk>[0-9]+)/permissions/$', 'team_permissions_list'),
)
inventory_urls = patterns('awx.api.views',
url(r'^$', 'inventory_list'),
url(r'^(?P<pk>[0-9]+)/$', 'inventory_detail'),
url(r'^(?P<pk>[0-9]+)/hosts/$', 'inventory_hosts_list'),
url(r'^(?P<pk>[0-9]+)/groups/$', 'inventory_groups_list'),
url(r'^(?P<pk>[0-9]+)/root_groups/$', 'inventory_root_groups_list'),
url(r'^(?P<pk>[0-9]+)/variable_data/$', 'inventory_variable_data'),
url(r'^(?P<pk>[0-9]+)/script/$', 'inventory_script_view'),
url(r'^(?P<pk>[0-9]+)/tree/$', 'inventory_tree_view'),
url(r'^(?P<pk>[0-9]+)/inventory_sources/$', 'inventory_inventory_sources_list'),
)
host_urls = patterns('awx.api.views',
url(r'^$', 'host_list'),
url(r'^(?P<pk>[0-9]+)/$', 'host_detail'),
url(r'^(?P<pk>[0-9]+)/variable_data/$', 'host_variable_data'),
url(r'^(?P<pk>[0-9]+)/groups/$', 'host_groups_list'),
url(r'^(?P<pk>[0-9]+)/all_groups/$', 'host_all_groups_list'),
url(r'^(?P<pk>[0-9]+)/job_events/', 'host_job_events_list'),
url(r'^(?P<pk>[0-9]+)/job_host_summaries/$', 'host_job_host_summaries_list'),
#url(r'^(?P<pk>[0-9]+)/inventory_sources/$', 'host_inventory_sources_list'),
)
group_urls = patterns('awx.api.views',
url(r'^$', 'group_list'),
url(r'^(?P<pk>[0-9]+)/$', 'group_detail'),
url(r'^(?P<pk>[0-9]+)/children/$', 'group_children_list'),
url(r'^(?P<pk>[0-9]+)/hosts/$', 'group_hosts_list'),
url(r'^(?P<pk>[0-9]+)/all_hosts/$', 'group_all_hosts_list'),
url(r'^(?P<pk>[0-9]+)/variable_data/$', 'group_variable_data'),
url(r'^(?P<pk>[0-9]+)/job_events/$', 'group_job_events_list'),
url(r'^(?P<pk>[0-9]+)/job_host_summaries/$', 'group_job_host_summaries_list'),
url(r'^(?P<pk>[0-9]+)/potential_children/$', 'group_potential_children_list'),
#url(r'^(?P<pk>[0-9]+)/inventory_sources/$', 'group_inventory_sources_list'),
)
inventory_source_urls = patterns('awx.api.views',
url(r'^$', 'inventory_source_list'),
url(r'^(?P<pk>[0-9]+)/$', 'inventory_source_detail'),
url(r'^(?P<pk>[0-9]+)/update/$', 'inventory_source_update_view'),
url(r'^(?P<pk>[0-9]+)/inventory_updates/$', 'inventory_source_updates_list'),
#url(r'^(?P<pk>[0-9]+)/groups/$', 'inventory_source_groups_list'),
#url(r'^(?P<pk>[0-9]+)/hosts/$', 'inventory_source_hosts_list'),
)
inventory_update_urls = patterns('awx.api.views',
url(r'^(?P<pk>[0-9]+)/$', 'inventory_update_detail'),
url(r'^(?P<pk>[0-9]+)/cancel/$', 'inventory_update_cancel'),
)
credential_urls = patterns('awx.api.views',
url(r'^$', 'credential_list'),
url(r'^(?P<pk>[0-9]+)/$', 'credential_detail'),
# See also credentials resources on users/teams.
)
permission_urls = patterns('awx.api.views',
url(r'^(?P<pk>[0-9]+)/$', 'permission_detail'),
)
job_template_urls = patterns('awx.api.views',
url(r'^$', 'job_template_list'),
url(r'^(?P<pk>[0-9]+)/$', 'job_template_detail'),
url(r'^(?P<pk>[0-9]+)/jobs/$', 'job_template_jobs_list'),
url(r'^(?P<pk>[0-9]+)/callback/$', 'job_template_callback'),
)
job_urls = patterns('awx.api.views',
url(r'^$', 'job_list'),
url(r'^(?P<pk>[0-9]+)/$', 'job_detail'),
url(r'^(?P<pk>[0-9]+)/start/$', 'job_start'),
url(r'^(?P<pk>[0-9]+)/cancel/$', 'job_cancel'),
url(r'^(?P<pk>[0-9]+)/job_host_summaries/$', 'job_job_host_summaries_list'),
url(r'^(?P<pk>[0-9]+)/job_events/$', 'job_job_events_list'),
)
job_host_summary_urls = patterns('awx.api.views',
url(r'^(?P<pk>[0-9]+)/$', 'job_host_summary_detail'),
)
job_event_urls = patterns('awx.api.views',
url(r'^$', 'job_event_list'),
url(r'^(?P<pk>[0-9]+)/$', 'job_event_detail'),
url(r'^(?P<pk>[0-9]+)/children/$', 'job_event_children_list'),
url(r'^(?P<pk>[0-9]+)/hosts/$', 'job_event_hosts_list'),
)
v1_urls = patterns('awx.api.views',
url(r'^$', 'api_v1_root_view'),
url(r'^config/$', 'api_v1_config_view'),
url(r'^authtoken/$', 'auth_token_view'),
url(r'^me/$', 'user_me_list'),
url(r'^organizations/', include(organization_urls)),
url(r'^users/', include(user_urls)),
url(r'^projects/', include(project_urls)),
url(r'^project_updates/', include(project_update_urls)),
url(r'^teams/', include(team_urls)),
url(r'^inventories/', include(inventory_urls)),
url(r'^hosts/', include(host_urls)),
url(r'^groups/', include(group_urls)),
url(r'^inventory_sources/', include(inventory_source_urls)),
url(r'^inventory_updates/', include(inventory_update_urls)),
url(r'^credentials/', include(credential_urls)),
url(r'^permissions/', include(permission_urls)),
url(r'^job_templates/', include(job_template_urls)),
url(r'^jobs/', include(job_urls)),
url(r'^job_host_summaries/', include(job_host_summary_urls)),
url(r'^job_events/', include(job_event_urls)),
)
urlpatterns = patterns('awx.api.views',
url(r'^$', 'api_root_view'),
url(r'^v1/', include(v1_urls)),
)

1059
awx/api/views.py Normal file

File diff suppressed because it is too large Load Diff

2
awx/lib/__init__.py Normal file
View File

@ -0,0 +1,2 @@
# Copyright (c) 2013 AnsibleWorks, Inc.
# All Rights Reserved.

View File

@ -15,7 +15,7 @@ from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin
from awx.main.compat import format_html
from awx.lib.compat import format_html
from awx.main.models import *
from awx.main.forms import *

View File

@ -35,7 +35,7 @@ from taggit.managers import TaggableManager
from djcelery.models import TaskMeta
# AWX
from awx.main.compat import slugify
from awx.lib.compat import slugify
from awx.main.fields import AutoOneToOneField
from awx.main.utils import encrypt_field, decrypt_field
@ -343,7 +343,7 @@ class Organization(CommonModel):
projects = models.ManyToManyField('Project', blank=True, related_name='organizations')
def get_absolute_url(self):
return reverse('main:organization_detail', args=(self.pk,))
return reverse('api:organization_detail', args=(self.pk,))
def __unicode__(self):
return self.name
@ -412,7 +412,7 @@ class Inventory(CommonModel):
)
def get_absolute_url(self):
return reverse('main:inventory_detail', args=(self.pk,))
return reverse('api:inventory_detail', args=(self.pk,))
def mark_inactive(self, save=True):
'''
@ -537,7 +537,7 @@ class Host(CommonModelNameNotUnique):
return self.name
def get_absolute_url(self):
return reverse('main:host_detail', args=(self.pk,))
return reverse('api:host_detail', args=(self.pk,))
def mark_inactive(self, save=True):
'''
@ -667,7 +667,7 @@ class Group(CommonModelNameNotUnique):
return self.name
def get_absolute_url(self):
return reverse('main:group_detail', args=(self.pk,))
return reverse('api:group_detail', args=(self.pk,))
def mark_inactive(self, save=True):
'''
@ -938,7 +938,7 @@ class InventorySource(PrimordialModel):
return inventory_update
def get_absolute_url(self):
return reverse('main:inventory_source_detail', args=(self.pk,))
return reverse('api:inventory_source_detail', args=(self.pk,))
class InventoryUpdate(CommonTask):
'''
@ -972,7 +972,7 @@ class InventoryUpdate(CommonTask):
return self.inventory_source
def get_absolute_url(self):
return reverse('main:inventory_update_detail', args=(self.pk,))
return reverse('api:inventory_update_detail', args=(self.pk,))
def _get_task_class(self):
from awx.main.tasks import RunInventoryUpdate
@ -1087,7 +1087,7 @@ class Credential(CommonModelNameNotUnique):
return needed
def get_absolute_url(self):
return reverse('main:credential_detail', args=(self.pk,))
return reverse('api:credential_detail', args=(self.pk,))
def clean(self):
if self.user and self.team:
@ -1142,7 +1142,7 @@ class Team(CommonModelNameNotUnique):
organization = models.ForeignKey('Organization', blank=False, null=True, on_delete=SET_NULL, related_name='teams')
def get_absolute_url(self):
return reverse('main:team_detail', args=(self.pk,))
return reverse('api:team_detail', args=(self.pk,))
class Project(CommonModel):
'''
@ -1377,7 +1377,7 @@ class Project(CommonModel):
return project_update
def get_absolute_url(self):
return reverse('main:project_detail', args=(self.pk,))
return reverse('api:project_detail', args=(self.pk,))
def get_project_path(self, check_if_exists=True):
local_path = os.path.basename(self.local_path)
@ -1435,7 +1435,7 @@ class ProjectUpdate(CommonTask):
)
def get_absolute_url(self):
return reverse('main:project_update_detail', args=(self.pk,))
return reverse('api:project_update_detail', args=(self.pk,))
def _get_parent_instance(self):
return self.project
@ -1507,7 +1507,7 @@ class Permission(CommonModelNameNotUnique):
))
def get_absolute_url(self):
return reverse('main:permission_detail', args=(self.pk,))
return reverse('api:permission_detail', args=(self.pk,))
# TODO: other job types (later)
@ -1607,7 +1607,7 @@ class JobTemplate(CommonModel):
return job
def get_absolute_url(self):
return reverse('main:job_template_detail', args=(self.pk,))
return reverse('api:job_template_detail', args=(self.pk,))
def can_start_without_user_input(self):
'''
@ -1719,7 +1719,7 @@ class Job(CommonTask):
)
def get_absolute_url(self):
return reverse('main:job_detail', args=(self.pk,))
return reverse('api:job_detail', args=(self.pk,))
extra_vars_dict = VarsDictProperty('extra_vars', True)
@ -1829,7 +1829,7 @@ class JobHostSummary(models.Model):
self.processed, self.skipped)
def get_absolute_url(self):
return reverse('main:job_host_summary_detail', args=(self.pk,))
return reverse('api:job_host_summary_detail', args=(self.pk,))
def save(self, *args, **kwargs):
self.failed = bool(self.dark or self.failures)
@ -1982,7 +1982,7 @@ class JobEvent(models.Model):
)
def get_absolute_url(self):
return reverse('main:job_event_detail', args=(self.pk,))
return reverse('api:job_event_detail', args=(self.pk,))
def __unicode__(self):
return u'%s @ %s' % (self.get_event_display(), self.created.isoformat())

View File

@ -1,3 +0,0 @@
{{ docstring }}
{% include "main/_new_in_awx.md" %}

View File

@ -44,7 +44,7 @@ class InventoryTest(BaseTest):
)
def test_get_inventory_list(self):
url = reverse('main:inventory_list')
url = reverse('api:inventory_list')
qs = Inventory.objects.filter(active=True).distinct()
# Check list view with invalid authentication.
@ -66,7 +66,7 @@ class InventoryTest(BaseTest):
self.check_get_list(url, self.nobody_django_user, nobody_qs)
def test_post_inventory_list(self):
url = reverse('main:inventory_list')
url = reverse('api:inventory_list')
# Check post to list view with invalid authentication.
new_inv_0 = dict(name='inventory-c', description='baz', organization=self.organizations[0].pk)
@ -95,8 +95,8 @@ class InventoryTest(BaseTest):
data = self.post(url, data=new_inv_denied, expect=403)
def test_get_inventory_detail(self):
url_a = reverse('main:inventory_detail', args=(self.inventory_a.pk,))
url_b = reverse('main:inventory_detail', args=(self.inventory_b.pk,))
url_a = reverse('api:inventory_detail', args=(self.inventory_a.pk,))
url_b = reverse('api:inventory_detail', args=(self.inventory_b.pk,))
# Check detail view with invalid authentication.
self.check_invalid_auth(url_a)
@ -125,8 +125,8 @@ class InventoryTest(BaseTest):
data = self.get(url_b, expect=403)
def test_put_inventory_detail(self):
url_a = reverse('main:inventory_detail', args=(self.inventory_a.pk,))
url_b = reverse('main:inventory_detail', args=(self.inventory_b.pk,))
url_a = reverse('api:inventory_detail', args=(self.inventory_a.pk,))
url_b = reverse('api:inventory_detail', args=(self.inventory_b.pk,))
# Check put to detail view with invalid authentication.
self.check_invalid_auth(url_a, methods=('put',))
@ -178,7 +178,7 @@ class InventoryTest(BaseTest):
# Via AC-376:
# Create an inventory. Leave the description empty.
# Edit the new inventory, change the Name, click Save.
list_url = reverse('main:inventory_list')
list_url = reverse('api:inventory_list')
new_data = dict(name='inventory-c', description='',
organization=self.organizations[0].pk)
new_id = max(Inventory.objects.values_list('pk', flat=True)) + 1
@ -186,7 +186,7 @@ class InventoryTest(BaseTest):
data = self.post(list_url, data=new_data, expect=201)
self.assertEqual(data['id'], new_id)
self.assertEqual(data['description'], '')
url_c = reverse('main:inventory_detail', args=(new_id,))
url_c = reverse('api:inventory_detail', args=(new_id,))
data = self.get(url_c, expect=200)
self.assertEqual(data['description'], '')
data['description'] = None
@ -194,8 +194,8 @@ class InventoryTest(BaseTest):
self.put(url_c, data, expect=200)
def test_delete_inventory_detail(self):
url_a = reverse('main:inventory_detail', args=(self.inventory_a.pk,))
url_b = reverse('main:inventory_detail', args=(self.inventory_b.pk,))
url_a = reverse('api:inventory_detail', args=(self.inventory_a.pk,))
url_b = reverse('api:inventory_detail', args=(self.inventory_b.pk,))
# Create test hosts and groups within each inventory.
self.inventory_a.hosts.create(name='host-a')
@ -246,11 +246,11 @@ class InventoryTest(BaseTest):
def test_main_line(self):
# some basic URLs...
inventories = reverse('main:inventory_list')
inventories_1 = reverse('main:inventory_detail', args=(self.inventory_a.pk,))
inventories_2 = reverse('main:inventory_detail', args=(self.inventory_b.pk,))
hosts = reverse('main:host_list')
groups = reverse('main:group_list')
inventories = reverse('api:inventory_list')
inventories_1 = reverse('api:inventory_detail', args=(self.inventory_a.pk,))
inventories_2 = reverse('api:inventory_detail', args=(self.inventory_b.pk,))
hosts = reverse('api:host_list')
groups = reverse('api:group_list')
# a super user can add hosts (but inventory ID is required)
@ -326,7 +326,7 @@ class InventoryTest(BaseTest):
new_group_c = dict(name='web4', inventory=inv.pk)
new_group_d = dict(name='web5', inventory=inv.pk)
new_group_e = dict(name='web6', inventory=inv.pk)
groups = reverse('main:group_list')
groups = reverse('api:group_list')
data0 = self.post(groups, data=invalid, expect=400, auth=self.get_super_credentials())
data0 = self.post(groups, data=new_group_a, expect=201, auth=self.get_super_credentials())
@ -360,7 +360,7 @@ class InventoryTest(BaseTest):
#################################################
# HOSTS->inventories POST via subcollection
url = reverse('main:inventory_hosts_list', args=(self.inventory_a.pk,))
url = reverse('api:inventory_hosts_list', args=(self.inventory_a.pk,))
new_host_a = dict(name='web100.example.com')
new_host_b = dict(name='web101.example.com')
new_host_c = dict(name='web102.example.com')
@ -377,7 +377,7 @@ class InventoryTest(BaseTest):
added_by_collection_c = self.post(url, data=new_host_c, expect=403, auth=self.get_nobody_credentials())
# a normal user with edit permission on the inventory can associate hosts with inventories
url5 = reverse('main:inventory_hosts_list', args=(inv.pk,))
url5 = reverse('api:inventory_hosts_list', args=(inv.pk,))
added_by_collection_d = self.post(url5, data=new_host_d, expect=201, auth=self.get_other_credentials())
got = self.get(url5, expect=200, auth=self.get_other_credentials())
self.assertEquals(got['count'], 4)
@ -392,9 +392,9 @@ class InventoryTest(BaseTest):
##################################################
# GROUPS->inventories POST via subcollection
root_groups = reverse('main:inventory_root_groups_list', args=(self.inventory_a.pk,))
root_groups = reverse('api:inventory_root_groups_list', args=(self.inventory_a.pk,))
url = reverse('main:inventory_groups_list', args=(self.inventory_a.pk,))
url = reverse('api:inventory_groups_list', args=(self.inventory_a.pk,))
new_group_a = dict(name='web100')
new_group_b = dict(name='web101')
new_group_c = dict(name='web102')
@ -411,7 +411,7 @@ class InventoryTest(BaseTest):
added_by_collection = self.post(url, data=new_group_c, expect=403, auth=self.get_nobody_credentials())
# a normal user with edit permissions on the inventory can associate groups with inventories
url5 = reverse('main:inventory_groups_list', args=(inv.pk,))
url5 = reverse('api:inventory_groups_list', args=(inv.pk,))
added_by_collection = self.post(url5, data=new_group_d, expect=201, auth=self.get_other_credentials())
# make sure duplicates give 400s
self.post(url5, data=new_group_d, expect=400, auth=self.get_other_credentials())
@ -436,7 +436,7 @@ class InventoryTest(BaseTest):
vars_c = dict(asdf=5555, dog='mouse', cat='mogwai', unstructured=dict(a=[3,0,3],b=dict(z=2600)))
# attempting to get a variable object creates it, even though it does not already exist
vdata_url = reverse('main:host_variable_data', args=(added_by_collection_a['id'],))
vdata_url = reverse('api:host_variable_data', args=(added_by_collection_a['id'],))
got = self.get(vdata_url, expect=200, auth=self.get_super_credentials())
self.assertEquals(got, {})
@ -467,8 +467,8 @@ class InventoryTest(BaseTest):
vars_c = dict(asdf=9999, dog='pluto', cat='five', unstructured=dict(a=[3,3,3],b=dict(z=5)))
groups = Group.objects.all()
vdata1_url = reverse('main:group_variable_data', args=(groups[0].pk,))
vdata2_url = reverse('main:group_variable_data', args=(groups[1].pk,))
vdata1_url = reverse('api:group_variable_data', args=(groups[0].pk,))
vdata2_url = reverse('api:group_variable_data', args=(groups[1].pk,))
# a super user can associate variable objects with groups
got = self.get(vdata1_url, expect=200, auth=self.get_super_credentials())
@ -493,7 +493,7 @@ class InventoryTest(BaseTest):
vars_b = dict(asdf=2736, dog='benji', cat='garfield', unstructured=dict(a=[2,2,2],b=dict(x=3,y=4)))
vars_c = dict(asdf=7692, dog='buck', cat='sylvester', unstructured=dict(a=[3,3,3],b=dict(z=5)))
vdata_url = reverse('main:inventory_variable_data', args=(self.inventory_a.pk,))
vdata_url = reverse('api:inventory_variable_data', args=(self.inventory_a.pk,))
# a super user can associate variable objects with inventory
got = self.get(vdata_url, expect=200, auth=self.get_super_credentials())
@ -536,14 +536,14 @@ class InventoryTest(BaseTest):
groups[0].save()
# access
url1 = reverse('main:group_hosts_list', args=(groups[0].pk,))
url1 = reverse('api:group_hosts_list', args=(groups[0].pk,))
data = self.get(url1, expect=200, auth=self.get_normal_credentials())
self.assertEquals(data['count'], 2)
self.assertTrue(host1.pk in [x['id'] for x in data['results']])
self.assertTrue(host3.pk in [x['id'] for x in data['results']])
# addition
url = reverse('main:host_detail', args=(host2.pk,))
url = reverse('api:host_detail', args=(host2.pk,))
got = self.get(url, expect=200, auth=self.get_normal_credentials())
self.assertEquals(got['id'], host2.pk)
posted = self.post(url1, data=got, expect=204, auth=self.get_normal_credentials())
@ -596,15 +596,15 @@ class InventoryTest(BaseTest):
g2.save()
# a super user can set subgroups
subgroups_url = reverse('main:group_children_list',
subgroups_url = reverse('api:group_children_list',
args=(Group.objects.get(name='web2').pk,))
child_url = reverse('main:group_detail',
child_url = reverse('api:group_detail',
args=(Group.objects.get(name='web4').pk,))
subgroups_url2 = reverse('main:group_children_list',
subgroups_url2 = reverse('api:group_children_list',
args=(Group.objects.get(name='web6').pk,))
subgroups_url3 = reverse('main:group_children_list',
subgroups_url3 = reverse('api:group_children_list',
args=(Group.objects.get(name='web100').pk,))
subgroups_url4 = reverse('main:group_children_list',
subgroups_url4 = reverse('api:group_children_list',
args=(Group.objects.get(name='web101').pk,))
got = self.get(child_url, expect=200, auth=self.get_super_credentials())
self.post(subgroups_url, data=got, expect=204, auth=self.get_super_credentials())
@ -625,7 +625,7 @@ class InventoryTest(BaseTest):
# a group can't be it's own grandparent
subsub = posted2['related']['children']
# this is the grandparent
original_url = reverse('main:group_detail', args=(Group.objects.get(name='web6').pk,))
original_url = reverse('api:group_detail', args=(Group.objects.get(name='web6').pk,))
parent_data = self.get(original_url, expect=200, auth=self.get_super_credentials())
# now posting to kid's children collection...
self.post(subsub, data=parent_data, expect=403, auth=self.get_super_credentials())
@ -648,7 +648,7 @@ class InventoryTest(BaseTest):
# slight detour
# can see all hosts under a group, even if it has subgroups
# this URL is NOT postable
all_hosts = reverse('main:group_all_hosts_list',
all_hosts = reverse('api:group_all_hosts_list',
args=(Group.objects.get(name='web2').pk,))
self.assertEqual(Group.objects.get(name='web2').hosts.count(), 3)
data = self.get(all_hosts, expect=200, auth=self.get_normal_credentials())
@ -669,7 +669,7 @@ class InventoryTest(BaseTest):
self.assertTrue(removed_group.parents.count())
self.assertTrue(removed_group.active)
for parent in removed_group.parents.all():
parent_children_url = reverse('main:group_children_list', args=(parent.pk,))
parent_children_url = reverse('api:group_children_list', args=(parent.pk,))
data = {'id': removed_group.pk, 'disassociate': 1}
self.post(parent_children_url, data, expect=204, auth=self.get_super_credentials())
removed_group = Group.objects.get(pk=result['id'])
@ -678,7 +678,7 @@ class InventoryTest(BaseTest):
# Removing a group from a hierarchy should migrate its children to the
# parent. The group itself will be deleted (marked inactive), and all
# relationships removed.
url = reverse('main:group_children_list', args=(gx2.pk,))
url = reverse('api:group_children_list', args=(gx2.pk,))
data = {
'id': gx3.pk,
'disassociate': 1,
@ -691,7 +691,7 @@ class InventoryTest(BaseTest):
#self.assertTrue(gx4 in gx2.children.all())
# Try with invalid hostnames and invalid IPs.
hosts = reverse('main:host_list')
hosts = reverse('api:host_list')
invalid_expect = 400 # hostname validation is disabled for now.
data = dict(name='', inventory=inv.pk)
with self.current_user(self.super_django_user):
@ -752,7 +752,7 @@ class InventoryTest(BaseTest):
h_d.groups.add(g_d)
# Old, slow 1.2 way.
url = reverse('main:inventory_script_view', args=(i_a.pk,))
url = reverse('api:inventory_script_view', args=(i_a.pk,))
with self.current_user(self.super_django_user):
response = self.get(url, expect=200)
self.assertTrue('all' in response)
@ -772,7 +772,7 @@ class InventoryTest(BaseTest):
self.assertEqual(response, h.variables_dict)
# New 1.3 way.
url = reverse('main:inventory_script_view', args=(i_a.pk,))
url = reverse('api:inventory_script_view', args=(i_a.pk,))
url = '%s?hostvars=1' % url
with self.current_user(self.super_django_user):
response = self.get(url, expect=200)
@ -792,7 +792,7 @@ class InventoryTest(BaseTest):
g_d = self.inventory_a.groups.create(name='D')
g_d.parents.add(g_c)
url = reverse('main:inventory_tree_view', args=(self.inventory_a.pk,))
url = reverse('api:inventory_tree_view', args=(self.inventory_a.pk,))
with self.current_user(self.super_django_user):
response = self.get(url, expect=200)

View File

@ -436,7 +436,7 @@ class JobTemplateTest(BaseJobTestMixin, django.test.TestCase):
'job_tags', 'host_config_key',)
def test_get_job_template_list(self):
url = reverse('main:job_template_list')
url = reverse('api:job_template_list')
qs = JobTemplate.objects.distinct()
fields = self.JOB_TEMPLATE_FIELDS
@ -474,7 +474,7 @@ class JobTemplateTest(BaseJobTestMixin, django.test.TestCase):
# FIXME: Check with other credentials.
def test_post_job_template_list(self):
url = reverse('main:job_template_list')
url = reverse('api:job_template_list')
data = dict(
name = 'new job template',
job_type = PERM_INVENTORY_DEPLOY,
@ -489,7 +489,7 @@ class JobTemplateTest(BaseJobTestMixin, django.test.TestCase):
# sue can always add job templates.
with self.current_user(self.user_sue):
response = self.post(url, data, expect=201)
detail_url = reverse('main:job_template_detail',
detail_url = reverse('api:job_template_detail',
args=(response['id'],))
self.assertEquals(response['url'], detail_url)
@ -530,7 +530,7 @@ class JobTemplateTest(BaseJobTestMixin, django.test.TestCase):
def test_get_job_template_detail(self):
jt = self.jt_eng_run
url = reverse('main:job_template_detail', args=(jt.pk,))
url = reverse('api:job_template_detail', args=(jt.pk,))
# Test with no auth and with invalid login.
self.check_invalid_auth(url)
@ -551,7 +551,7 @@ class JobTemplateTest(BaseJobTestMixin, django.test.TestCase):
def test_put_job_template_detail(self):
jt = self.jt_eng_run
url = reverse('main:job_template_detail', args=(jt.pk,))
url = reverse('api:job_template_detail', args=(jt.pk,))
# Test with no auth and with invalid login.
self.check_invalid_auth(url, methods=('put',))# 'patch'))
@ -568,7 +568,7 @@ class JobTemplateTest(BaseJobTestMixin, django.test.TestCase):
def test_get_job_template_job_list(self):
jt = self.jt_eng_run
url = reverse('main:job_template_jobs_list', args=(jt.pk,))
url = reverse('api:job_template_jobs_list', args=(jt.pk,))
# Test with no auth and with invalid login.
self.check_invalid_auth(url)
@ -586,7 +586,7 @@ class JobTemplateTest(BaseJobTestMixin, django.test.TestCase):
def test_post_job_template_job_list(self):
jt = self.jt_eng_run
url = reverse('main:job_template_jobs_list', args=(jt.pk,))
url = reverse('api:job_template_jobs_list', args=(jt.pk,))
data = dict(
name='new job from template',
credential=self.cred_bob.pk,
@ -604,7 +604,7 @@ class JobTemplateTest(BaseJobTestMixin, django.test.TestCase):
class JobTest(BaseJobTestMixin, django.test.TestCase):
def test_get_job_list(self):
url = reverse('main:job_list')
url = reverse('api:job_list')
# Test with no auth and with invalid login.
self.check_invalid_auth(url)
@ -622,7 +622,7 @@ class JobTest(BaseJobTestMixin, django.test.TestCase):
# FIXME: Check with other credentials.
def test_post_job_list(self):
url = reverse('main:job_list')
url = reverse('api:job_list')
data = dict(
name='new job without template',
job_type=PERM_INVENTORY_DEPLOY,
@ -652,7 +652,7 @@ class JobTest(BaseJobTestMixin, django.test.TestCase):
def test_get_job_detail(self):
job = self.job_ops_east_run
url = reverse('main:job_detail', args=(job.pk,))
url = reverse('api:job_detail', args=(job.pk,))
# Test with no auth and with invalid login.
self.check_invalid_auth(url)
@ -668,7 +668,7 @@ class JobTest(BaseJobTestMixin, django.test.TestCase):
def test_put_job_detail(self):
job = self.job_ops_west_run
url = reverse('main:job_detail', args=(job.pk,))
url = reverse('api:job_detail', args=(job.pk,))
# Test with no auth and with invalid login.
self.check_invalid_auth(url, methods=('put',))# 'patch'))
@ -697,7 +697,7 @@ class JobTest(BaseJobTestMixin, django.test.TestCase):
# FIXME: Check with other credentials and readonly fields.
def _test_mainline(self):
url = reverse('main:job_list')
url = reverse('api:job_list')
# job templates
data = self.get('/api/v1/job_templates/', expect=401)
@ -769,7 +769,7 @@ class JobStartCancelTest(BaseJobTestMixin, django.test.LiveServerTestCase):
def test_job_start(self):
job = self.job_ops_east_run
url = reverse('main:job_start', args=(job.pk,))
url = reverse('api:job_start', args=(job.pk,))
# Test with no auth and with invalid login.
self.check_invalid_auth(url)
@ -797,7 +797,7 @@ class JobStartCancelTest(BaseJobTestMixin, django.test.LiveServerTestCase):
# Test with a job that prompts for SSH and sudo passwords.
job = self.job_sup_run
url = reverse('main:job_start', args=(job.pk,))
url = reverse('api:job_start', args=(job.pk,))
with self.current_user(self.user_sue):
response = self.get(url)
self.assertTrue(response['can_start'])
@ -821,7 +821,7 @@ class JobStartCancelTest(BaseJobTestMixin, django.test.LiveServerTestCase):
credential=self.cred_greg,
created_by=self.user_sue,
)
url = reverse('main:job_start', args=(job.pk,))
url = reverse('api:job_start', args=(job.pk,))
with self.current_user(self.user_sue):
response = self.get(url)
self.assertTrue(response['can_start'])
@ -841,7 +841,7 @@ class JobStartCancelTest(BaseJobTestMixin, django.test.LiveServerTestCase):
credential=self.cred_greg,
created_by=self.user_sue,
)
url = reverse('main:job_start', args=(job.pk,))
url = reverse('api:job_start', args=(job.pk,))
with self.current_user(self.user_sue):
response = self.get(url)
self.assertTrue(response['can_start'])
@ -858,7 +858,7 @@ class JobStartCancelTest(BaseJobTestMixin, django.test.LiveServerTestCase):
def test_job_cancel(self):
job = self.job_ops_east_run
url = reverse('main:job_cancel', args=(job.pk,))
url = reverse('api:job_cancel', args=(job.pk,))
# Test with no auth and with invalid login.
self.check_invalid_auth(url)
@ -887,7 +887,7 @@ class JobStartCancelTest(BaseJobTestMixin, django.test.LiveServerTestCase):
job.start()
# Check that the job detail has been updated.
url = reverse('main:job_detail', args=(job.pk,))
url = reverse('api:job_detail', args=(job.pk,))
with self.current_user(self.user_sue):
response = self.get(url)
self.assertEqual(response['status'], 'successful',
@ -895,7 +895,7 @@ class JobStartCancelTest(BaseJobTestMixin, django.test.LiveServerTestCase):
self.assertTrue(response['result_stdout'])
# Test job events for completed job.
url = reverse('main:job_job_events_list', args=(job.pk,))
url = reverse('api:job_job_events_list', args=(job.pk,))
with self.current_user(self.user_sue):
response = self.get(url)
qs = job.job_events.all()
@ -908,13 +908,13 @@ class JobStartCancelTest(BaseJobTestMixin, django.test.LiveServerTestCase):
for job_event in job.job_events.all():
if job_event.host:
host_ids.add(job_event.host.pk)
url = reverse('main:job_event_detail', args=(job_event.pk,))
url = reverse('api:job_event_detail', args=(job_event.pk,))
with self.current_user(self.user_sue):
response = self.get(url)
# Also test job event list for each host.
for host in Host.objects.filter(pk__in=host_ids):
url = reverse('main:host_job_events_list', args=(host.pk,))
url = reverse('api:host_job_events_list', args=(host.pk,))
with self.current_user(self.user_sue):
response = self.get(url)
qs = host.job_events.all()
@ -924,7 +924,7 @@ class JobStartCancelTest(BaseJobTestMixin, django.test.LiveServerTestCase):
# Test job event list for groups.
for group in self.inv_ops_east.groups.all():
url = reverse('main:group_job_events_list', args=(group.pk,))
url = reverse('api:group_job_events_list', args=(group.pk,))
with self.current_user(self.user_sue):
response = self.get(url)
qs = group.job_events.all()
@ -933,7 +933,7 @@ class JobStartCancelTest(BaseJobTestMixin, django.test.LiveServerTestCase):
self.check_list_ids(response, qs)
# Test global job event list.
url = reverse('main:job_event_list')
url = reverse('api:job_event_list')
with self.current_user(self.user_sue):
response = self.get(url)
qs = JobEvent.objects.all()
@ -942,7 +942,7 @@ class JobStartCancelTest(BaseJobTestMixin, django.test.LiveServerTestCase):
self.check_list_ids(response, qs)
# Test job host summaries for completed job.
url = reverse('main:job_job_host_summaries_list', args=(job.pk,))
url = reverse('api:job_job_host_summaries_list', args=(job.pk,))
with self.current_user(self.user_sue):
response = self.get(url)
qs = job.job_host_summaries.all()
@ -956,14 +956,14 @@ class JobStartCancelTest(BaseJobTestMixin, django.test.LiveServerTestCase):
# Test individual job host summary records.
for job_host_summary in job.job_host_summaries.all():
url = reverse('main:job_host_summary_detail',
url = reverse('api:job_host_summary_detail',
args=(job_host_summary.pk,))
with self.current_user(self.user_sue):
response = self.get(url)
# Test job host summaries for each host.
for host in Host.objects.filter(pk__in=host_ids):
url = reverse('main:host_job_host_summaries_list', args=(host.pk,))
url = reverse('api:host_job_host_summaries_list', args=(host.pk,))
with self.current_user(self.user_sue):
response = self.get(url)
qs = host.job_host_summaries.all()
@ -973,7 +973,7 @@ class JobStartCancelTest(BaseJobTestMixin, django.test.LiveServerTestCase):
# Test job host summaries for groups.
for group in self.inv_ops_east.groups.all():
url = reverse('main:group_job_host_summaries_list', args=(group.pk,))
url = reverse('api:group_job_host_summaries_list', args=(group.pk,))
with self.current_user(self.user_sue):
response = self.get(url)
qs = group.job_host_summaries.all()
@ -1115,7 +1115,7 @@ class JobTemplateCallbackTest(BaseJobTestMixin, django.test.LiveServerTestCase):
job_template = jt
break
self.assertTrue(job_template)
url = reverse('main:job_template_callback', args=(job_template.pk,))
url = reverse('api:job_template_callback', args=(job_template.pk,))
data = dict(host_config_key=job_template.host_config_key)
# Test a POST to start a new job.
@ -1254,7 +1254,7 @@ class JobTemplateCallbackTest(BaseJobTestMixin, django.test.LiveServerTestCase):
job_template = jt
break
self.assertTrue(job_template)
url = reverse('main:job_template_callback', args=(job_template.pk,))
url = reverse('api:job_template_callback', args=(job_template.pk,))
data = dict(host_config_key=job_template.host_config_key)
# Should get an error when multiple hosts match to the same IP.
@ -1278,7 +1278,7 @@ class JobTemplateCallbackTest(BaseJobTestMixin, django.test.LiveServerTestCase):
job_template = jt
break
self.assertTrue(job_template)
url = reverse('main:job_template_callback', args=(job_template.pk,))
url = reverse('api:job_template_callback', args=(job_template.pk,))
data = dict(host_config_key=job_template.host_config_key)
# Test POST to start a new job when the template has no credential.
@ -1300,7 +1300,7 @@ class JobTemplateCallbackTest(BaseJobTestMixin, django.test.LiveServerTestCase):
job_template = jt
break
self.assertTrue(job_template)
url = reverse('main:job_template_callback', args=(job_template.pk,))
url = reverse('api:job_template_callback', args=(job_template.pk,))
data = dict(host_config_key=job_template.host_config_key)
# Test POST to start a new job when the credential would require user

View File

@ -14,7 +14,7 @@ from awx.main.tests.base import BaseTest
class OrganizationsTest(BaseTest):
def collection(self):
return reverse('main:organization_list')
return reverse('api:organization_list')
def setUp(self):
super(OrganizationsTest, self).setUp()
@ -53,7 +53,7 @@ class OrganizationsTest(BaseTest):
self.organizations[1].admins.add(self.normal_django_user)
def test_get_organization_list(self):
url = reverse('main:organization_list')
url = reverse('api:organization_list')
# no credentials == 401
self.options(url, expect=401)
@ -280,7 +280,7 @@ class OrganizationsTest(BaseTest):
def test_post_item_subobjects_users(self):
url = reverse('main:organization_users_list', args=(self.organizations[1].pk,))
url = reverse('api:organization_users_list', args=(self.organizations[1].pk,))
users = self.get(url, expect=200, auth=self.get_normal_credentials())
self.assertEqual(users['count'], 2)
self.post(url, dict(id=self.normal_django_user.pk), expect=204, auth=self.get_normal_credentials())
@ -293,7 +293,7 @@ class OrganizationsTest(BaseTest):
# post a completely new user to verify we can add users to the subcollection directly
new_user = dict(username='NewUser9000')
which_org = self.normal_django_user.admin_of_organizations.all()[0]
url = reverse('main:organization_users_list', args=(which_org.pk,))
url = reverse('api:organization_users_list', args=(which_org.pk,))
posted = self.post(url, new_user, expect=201, auth=self.get_normal_credentials())
all_users = self.get(url, expect=200, auth=self.get_normal_credentials())
@ -301,7 +301,7 @@ class OrganizationsTest(BaseTest):
def test_post_item_subobjects_admins(self):
url = reverse('main:organization_admins_list', args=(self.organizations[1].pk,))
url = reverse('api:organization_admins_list', args=(self.organizations[1].pk,))
admins = self.get(url, expect=200, auth=self.get_normal_credentials())
self.assertEqual(admins['count'], 2)
self.post(url, dict(id=self.other_django_user.pk), expect=204, auth=self.get_normal_credentials())
@ -395,7 +395,7 @@ class OrganizationsTest(BaseTest):
self.delete(self.collection(), expect=405, auth=self.get_super_credentials())
def test_invalid_post_data(self):
url = reverse('main:organization_list')
url = reverse('api:organization_list')
# API should gracefully handle data of an invalid type.
self.post(url, expect=400, data=None, auth=self.get_super_credentials())
self.post(url, expect=400, data=99, auth=self.get_super_credentials())
@ -403,7 +403,7 @@ class OrganizationsTest(BaseTest):
self.post(url, expect=400, data=3.14, auth=self.get_super_credentials())
self.post(url, expect=400, data=True, auth=self.get_super_credentials())
self.post(url, expect=400, data=[1,2,3], auth=self.get_super_credentials())
url = reverse('main:organization_users_list', args=(self.organizations[0].pk,))
url = reverse('api:organization_users_list', args=(self.organizations[0].pk,))
self.post(url, expect=400, data=None, auth=self.get_super_credentials())
self.post(url, expect=400, data=99, auth=self.get_super_credentials())
self.post(url, expect=400, data='abcd', auth=self.get_super_credentials())

View File

@ -38,7 +38,7 @@ class ProjectsTest(BaseTest):
# tests for users, projects, and teams
def collection(self):
return reverse('main:project_list')
return reverse('api:project_list')
def setUp(self):
super(ProjectsTest, self).setUp()
@ -148,7 +148,7 @@ class ProjectsTest(BaseTest):
def test_api_config(self):
# superuser can read all config data.
url = reverse('main:api_v1_config_view')
url = reverse('api:api_v1_config_view')
response = self.get(url, expect=200, auth=self.get_super_credentials())
self.assertTrue('project_base_dir' in response)
self.assertEqual(response['project_base_dir'], settings.PROJECTS_ROOT)
@ -188,7 +188,7 @@ class ProjectsTest(BaseTest):
# PROJECTS - LISTING
# can get projects list
projects = reverse('main:project_list')
projects = reverse('api:project_list')
# invalid auth
self.get(projects, expect=401)
self.get(projects, expect=401, auth=self.get_invalid_credentials())
@ -217,7 +217,7 @@ class ProjectsTest(BaseTest):
auth=self.get_super_credentials())
# can edit project using same local path.
project_detail = reverse('main:project_detail', args=(response['id'],))
project_detail = reverse('api:project_detail', args=(response['id'],))
project_data = self.get(project_detail, expect=200,
auth=self.get_super_credentials())
response = self.put(project_detail, project_data, expect=200,
@ -235,7 +235,7 @@ class ProjectsTest(BaseTest):
# =====================================================================
# PROJECTS - ACCESS
project = reverse('main:project_detail', args=(self.projects[3].pk,))
project = reverse('api:project_detail', args=(self.projects[3].pk,))
self.get(project, expect=200, auth=self.get_super_credentials())
self.get(project, expect=200, auth=self.get_normal_credentials())
self.get(project, expect=200, auth=self.get_other_credentials())
@ -246,18 +246,18 @@ class ProjectsTest(BaseTest):
self.get(project, expect=404, auth=self.get_normal_credentials())
# can list playbooks for projects
proj_playbooks = reverse('main:project_playbooks', args=(self.projects[2].pk,))
proj_playbooks = reverse('api:project_playbooks', args=(self.projects[2].pk,))
got = self.get(proj_playbooks, expect=200, auth=self.get_super_credentials())
self.assertEqual(got, self.projects[2].playbooks)
# can list member organizations for projects
proj_orgs = reverse('main:project_organizations_list', args=(self.projects[0].pk,))
proj_orgs = reverse('api:project_organizations_list', args=(self.projects[0].pk,))
# only usable as superuser
got = self.get(proj_orgs, expect=200, auth=self.get_normal_credentials())
got = self.get(proj_orgs, expect=200, auth=self.get_super_credentials())
self.get(proj_orgs, expect=403, auth=self.get_other_credentials())
self.assertEquals(got['count'], 1)
self.assertEquals(got['results'][0]['url'], reverse('main:organization_detail', args=(self.organizations[0].pk,)))
self.assertEquals(got['results'][0]['url'], reverse('api:organization_detail', args=(self.organizations[0].pk,)))
# post to create new org associated with this project.
self.post(proj_orgs, data={'name': 'New Org'}, expect=201, auth=self.get_super_credentials())
@ -267,8 +267,8 @@ class ProjectsTest(BaseTest):
# =====================================================================
# TEAMS
all_teams = reverse('main:team_list')
team1 = reverse('main:team_detail', args=(self.team1.pk,))
all_teams = reverse('api:team_list')
team1 = reverse('api:team_detail', args=(self.team1.pk,))
# can list teams
got = self.get(all_teams, expect=200, auth=self.get_super_credentials())
@ -277,7 +277,7 @@ class ProjectsTest(BaseTest):
# can get teams
got = self.get(team1, expect=200, auth=self.get_super_credentials())
self.assertEquals(got['url'], reverse('main:team_detail', args=(self.team1.pk,)))
self.assertEquals(got['url'], reverse('api:team_detail', args=(self.team1.pk,)))
got = self.get(team1, expect=200, auth=self.get_normal_credentials())
got = self.get(team1, expect=403, auth=self.get_other_credentials())
self.team1.users.add(User.objects.get(username='other'))
@ -303,7 +303,7 @@ class ProjectsTest(BaseTest):
url5 = posted1['url']
new_team = Team.objects.create(name='newTeam4', organization=self.organizations[1])
url = reverse('main:team_detail', args=(new_team.pk,))
url = reverse('api:team_detail', args=(new_team.pk,))
# can delete teams
self.delete(url, expect=401)
@ -316,7 +316,7 @@ class ProjectsTest(BaseTest):
# ORGANIZATION TEAMS
# can list organization teams (filtered by user) -- this is an org admin function
org_teams = reverse('main:organization_teams_list', args=(self.organizations[1].pk,))
org_teams = reverse('api:organization_teams_list', args=(self.organizations[1].pk,))
data1 = self.get(org_teams, expect=401)
data2 = self.get(org_teams, expect=403, auth=self.get_nobody_credentials())
data3 = self.get(org_teams, expect=403, auth=self.get_other_credentials())
@ -346,7 +346,7 @@ class ProjectsTest(BaseTest):
# TEAM PROJECTS
team = Team.objects.filter(active=True, organization__pk=self.organizations[1].pk)[0]
team_projects = reverse('main:team_projects_list', args=(team.pk,))
team_projects = reverse('api:team_projects_list', args=(team.pk,))
p1 = self.projects[0]
team.projects.add(p1)
@ -363,7 +363,7 @@ class ProjectsTest(BaseTest):
# TEAMS USER MEMBERSHIP
team = Team.objects.filter(active=True, organization__pk=self.organizations[1].pk)[0]
team_users = reverse('main:team_users_list', args=(team.pk,))
team_users = reverse('api:team_users_list', args=(team.pk,))
for x in team.users.all():
team.users.remove(x)
team.save()
@ -377,7 +377,7 @@ class ProjectsTest(BaseTest):
self.get(team_users, expect=200, auth=self.get_super_credentials())
# can add users to teams (but only users I can see)
all_users = self.get(reverse('main:user_list'), expect=200, auth=self.get_normal_credentials())
all_users = self.get(reverse('api:user_list'), expect=200, auth=self.get_normal_credentials())
for x in all_users['results']:
self.post(team_users, data=x, expect=403, auth=self.get_nobody_credentials())
self.post(team_users, data=x, expect=204, auth=self.get_normal_credentials())
@ -397,7 +397,7 @@ class ProjectsTest(BaseTest):
# from a user, can see what teams they are on (related resource)
other = User.objects.get(username = 'other')
url = reverse('main:user_teams_list', args=(other.pk,))
url = reverse('api:user_teams_list', args=(other.pk,))
self.get(url, expect=401)
self.get(url, expect=401, auth=self.get_invalid_credentials())
self.get(url, expect=403, auth=self.get_nobody_credentials())
@ -413,7 +413,7 @@ class ProjectsTest(BaseTest):
# =====================================================================
# USER PROJECTS
url = reverse('main:user_projects_list', args=(other.pk,))
url = reverse('api:user_projects_list', args=(other.pk,))
# from a user, can see what projects they can see based on team association
# though this resource doesn't do anything else
@ -427,8 +427,8 @@ class ProjectsTest(BaseTest):
# =====================================================================
# CREDENTIALS
other_creds = reverse('main:user_credentials_list', args=(other.pk,))
team_creds = reverse('main:team_credentials_list', args=(team.pk,))
other_creds = reverse('api:user_credentials_list', args=(other.pk,))
team_creds = reverse('api:team_credentials_list', args=(team.pk,))
new_credentials = dict(
name = 'credential',
@ -476,7 +476,7 @@ class ProjectsTest(BaseTest):
self.get(team_creds, expect=403, auth=self.get_nobody_credentials())
# Check /api/v1/credentials (GET)
url = reverse('main:credential_list')
url = reverse('api:credential_list')
with self.current_user(self.super_django_user):
self.options(url)
self.head(url)
@ -498,8 +498,8 @@ class ProjectsTest(BaseTest):
d_cred_user = dict(id=cred_user.pk, name='x', sudo_password='blippy', user=cred_user.user.pk)
d_cred_user2 = dict(id=cred_user.pk, name='x', sudo_password='blippy', user=self.super_django_user.pk)
d_cred_team = dict(id=cred_team.pk, name='x', sudo_password='blippy', team=cred_team.team.pk)
edit_creds1 = reverse('main:credential_detail', args=(cred_user.pk,))
edit_creds2 = reverse('main:credential_detail', args=(cred_team.pk,))
edit_creds1 = reverse('api:credential_detail', args=(cred_user.pk,))
edit_creds2 = reverse('api:credential_detail', args=(cred_team.pk,))
self.put(edit_creds1, data=d_cred_user, expect=401)
self.put(edit_creds1, data=d_cred_user, expect=401, auth=self.get_invalid_credentials())
@ -517,13 +517,13 @@ class ProjectsTest(BaseTest):
self.put(edit_creds2, data=d_cred_team, expect=403, auth=self.get_other_credentials())
cred_put_t['disassociate'] = 1
team_url = reverse('main:team_credentials_list', args=(cred_put_t['team'],))
team_url = reverse('api:team_credentials_list', args=(cred_put_t['team'],))
self.post(team_url, data=cred_put_t, expect=204, auth=self.get_normal_credentials())
# can remove credentials from a user (via disassociate) - this will delete the credential.
cred_put_u['disassociate'] = 1
url = cred_put_u['url']
user_url = reverse('main:user_credentials_list', args=(cred_put_u['user'],))
user_url = reverse('api:user_credentials_list', args=(cred_put_u['user'],))
self.post(user_url, data=cred_put_u, expect=204, auth=self.get_normal_credentials())
# can delete a credential directly -- probably won't be used too often
@ -560,13 +560,13 @@ class ProjectsTest(BaseTest):
permission_type=PERM_INVENTORY_DEPLOY
)
url = reverse('main:user_permissions_list', args=(user.pk,))
url = reverse('api:user_permissions_list', args=(user.pk,))
posted = self.post(url, user_permission, expect=201, auth=self.get_super_credentials())
url2 = posted['url']
got = self.get(url2, expect=200, auth=self.get_other_credentials())
# cannot add permissions that apply to both team and user
url = reverse('main:user_permissions_list', args=(user.pk,))
url = reverse('api:user_permissions_list', args=(user.pk,))
user_permission['name'] = 'user permission 2'
user_permission['team'] = team.pk
self.post(url, user_permission, expect=400, auth=self.get_super_credentials())
@ -584,26 +584,26 @@ class ProjectsTest(BaseTest):
self.post(url, user_permission, expect=400, auth=self.get_super_credentials())
# can add permissions on a team
url = reverse('main:team_permissions_list', args=(team.pk,))
url = reverse('api:team_permissions_list', args=(team.pk,))
posted = self.post(url, team_permission, expect=201, auth=self.get_super_credentials())
url2 = posted['url']
# check we can get that permission back
got = self.get(url2, expect=200, auth=self.get_other_credentials())
# cannot add permissions that apply to both team and user
url = reverse('main:team_permissions_list', args=(team.pk,))
url = reverse('api:team_permissions_list', args=(team.pk,))
team_permission['name'] += '2'
team_permission['user'] = user.pk
self.post(url, team_permission, expect=400, auth=self.get_super_credentials())
# can list permissions on a user
url = reverse('main:user_permissions_list', args=(user.pk,))
url = reverse('api:user_permissions_list', args=(user.pk,))
got = self.get(url, expect=200, auth=self.get_super_credentials())
got = self.get(url, expect=200, auth=self.get_other_credentials())
got = self.get(url, expect=403, auth=self.get_nobody_credentials())
# can list permissions on a team
url = reverse('main:team_permissions_list', args=(team.pk,))
url = reverse('api:team_permissions_list', args=(team.pk,))
got = self.get(url, expect=200, auth=self.get_super_credentials())
got = self.get(url, expect=200, auth=self.get_other_credentials())
got = self.get(url, expect=403, auth=self.get_nobody_credentials())
@ -1335,7 +1335,7 @@ class ProjectUpdatesTest(BaseTransactionTest):
scm_username='nobody',
scm_password='ASK',
)
url = reverse('main:project_update_view', args=(project.pk,))
url = reverse('api:project_update_view', args=(project.pk,))
with self.current_user(self.super_django_user):
response = self.get(url, expect=200)
self.assertTrue(response['can_update'])
@ -1359,7 +1359,7 @@ class ProjectUpdatesTest(BaseTransactionTest):
scm_key_data=TEST_SSH_KEY_DATA_LOCKED,
scm_key_unlock='ASK',
)
url = reverse('main:project_update_view', args=(project.pk,))
url = reverse('api:project_update_view', args=(project.pk,))
with self.current_user(self.super_django_user):
response = self.get(url, expect=200)
self.assertTrue(response['can_update'])

View File

@ -23,7 +23,7 @@ __all__ = ['UsersTest', 'LdapTest']
class UsersTest(BaseTest):
def collection(self):
return reverse('main:user_list')
return reverse('api:user_list')
def setUp(self):
super(UsersTest, self).setUp()
@ -34,7 +34,7 @@ class UsersTest(BaseTest):
self.organizations[0].users.add(self.normal_django_user)
def test_only_super_user_or_org_admin_can_add_users(self):
url = reverse('main:user_list')
url = reverse('api:user_list')
new_user = dict(username='blippy')
new_user2 = dict(username='blippy2')
self.post(url, expect=401, data=new_user, auth=None)
@ -46,7 +46,7 @@ class UsersTest(BaseTest):
self.post(url, expect=400, data=new_user2, auth=self.get_normal_credentials())
def test_auth_token_login(self):
auth_token_url = reverse('main:auth_token_view')
auth_token_url = reverse('api:auth_token_view')
# Always returns a 405 for any GET request, regardless of credentials.
self.get(auth_token_url, expect=405, auth=None)
@ -69,7 +69,7 @@ class UsersTest(BaseTest):
auth_token = response['token']
# Verify we can access our own user information with the auth token.
response = self.get(reverse('main:user_me_list'), expect=200,
response = self.get(reverse('api:user_me_list'), expect=200,
auth=auth_token)
self.assertEquals(response['results'][0]['username'], 'normal')
self.assertEquals(response['count'], 1)
@ -77,7 +77,7 @@ class UsersTest(BaseTest):
# If we simulate a different remote address, should not be able to use
# the first auth token.
remote_addr = '127.0.0.2'
response = self.get(reverse('main:user_me_list'), expect=401,
response = self.get(reverse('api:user_me_list'), expect=401,
auth=auth_token, remote_addr=remote_addr)
self.assertEqual(response['detail'], 'Invalid token')
@ -97,28 +97,28 @@ class UsersTest(BaseTest):
# Verify we can access our own user information with the second auth
# token from the other remote address.
response = self.get(reverse('main:user_me_list'), expect=200,
response = self.get(reverse('api:user_me_list'), expect=200,
auth=auth_token2, remote_addr=remote_addr)
self.assertEquals(response['results'][0]['username'], 'normal')
self.assertEquals(response['count'], 1)
# The second auth token also can't be used from the first address, but
# the first auth token is still valid from its address.
response = self.get(reverse('main:user_me_list'), expect=401,
response = self.get(reverse('api:user_me_list'), expect=401,
auth=auth_token2)
self.assertEqual(response['detail'], 'Invalid token')
response_header = response.response.get('WWW-Authenticate', '')
self.assertEqual(response_header.split()[0], 'Token')
response = self.get(reverse('main:user_me_list'), expect=200,
response = self.get(reverse('api:user_me_list'), expect=200,
auth=auth_token)
# A request without authentication should ask for Basic by default.
response = self.get(reverse('main:user_me_list'), expect=401)
response = self.get(reverse('api:user_me_list'), expect=401)
response_header = response.response.get('WWW-Authenticate', '')
self.assertEqual(response_header.split()[0], 'Basic')
# A request that attempts Basic auth should request Basic auth again.
response = self.get(reverse('main:user_me_list'), expect=401,
response = self.get(reverse('api:user_me_list'), expect=401,
auth=('invalid', 'password'))
response_header = response.response.get('WWW-Authenticate', '')
self.assertEqual(response_header.split()[0], 'Basic')
@ -126,21 +126,21 @@ class UsersTest(BaseTest):
# Invalidate a key (simulate expiration), now token auth should fail
# with the first token, but still work with the second.
self.normal_django_user.auth_tokens.get(key=auth_token).invalidate()
response = self.get(reverse('main:user_me_list'), expect=401,
response = self.get(reverse('api:user_me_list'), expect=401,
auth=auth_token)
self.assertEqual(response['detail'], 'Token is expired')
response = self.get(reverse('main:user_me_list'), expect=200,
response = self.get(reverse('api:user_me_list'), expect=200,
auth=auth_token2, remote_addr=remote_addr)
# Token auth should be denied if the user is inactive.
self.normal_django_user.mark_inactive()
response = self.get(reverse('main:user_me_list'), expect=401,
response = self.get(reverse('api:user_me_list'), expect=401,
auth=auth_token2, remote_addr=remote_addr)
self.assertEqual(response['detail'], 'User inactive or deleted')
def test_ordinary_user_can_modify_some_fields_about_himself_but_not_all_and_passwords_work(self):
detail_url = reverse('main:user_detail', args=(self.other_django_user.pk,))
detail_url = reverse('api:user_detail', args=(self.other_django_user.pk,))
data = self.get(detail_url, expect=200, auth=self.get_other_credentials())
# can't change first_name, last_name, etc
@ -182,7 +182,7 @@ class UsersTest(BaseTest):
def test_user_created_with_password_can_login(self):
# this is something an org admin can do...
url = reverse('main:user_list')
url = reverse('api:user_list')
data = dict(username='username', password='password')
data2 = dict(username='username2', password='password2')
data = self.post(url, expect=201, data=data, auth=self.get_normal_credentials())
@ -206,16 +206,16 @@ class UsersTest(BaseTest):
self.assertTrue(orig.username != 'change')
def test_password_not_shown_in_get_operations_for_list_or_detail(self):
url = reverse('main:user_detail', args=(self.super_django_user.pk,))
url = reverse('api:user_detail', args=(self.super_django_user.pk,))
data = self.get(url, expect=200, auth=self.get_super_credentials())
self.assertTrue('password' not in data)
url = reverse('main:user_list')
url = reverse('api:user_list')
data = self.get(url, expect=200, auth=self.get_super_credentials())
self.assertTrue('password' not in data['results'][0])
def test_user_list_filtered(self):
url = reverse('main:user_list')
url = reverse('api:user_list')
data3 = self.get(url, expect=200, auth=self.get_super_credentials())
self.assertEquals(data3['count'], 4)
data2 = self.get(url, expect=200, auth=self.get_normal_credentials())
@ -225,22 +225,22 @@ class UsersTest(BaseTest):
def test_super_user_can_delete_a_user_but_only_marked_inactive(self):
user_pk = self.normal_django_user.pk
url = reverse('main:user_detail', args=(user_pk,))
url = reverse('api:user_detail', args=(user_pk,))
data = self.delete(url, expect=204, auth=self.get_super_credentials())
data = self.get(url, expect=404, auth=self.get_super_credentials())
obj = User.objects.get(pk=user_pk)
self.assertEquals(obj.is_active, False)
def test_non_org_admin_user_cannot_delete_any_user_including_himself(self):
url1 = reverse('main:user_detail', args=(self.super_django_user.pk,))
url2 = reverse('main:user_detail', args=(self.normal_django_user.pk,))
url3 = reverse('main:user_detail', args=(self.other_django_user.pk,))
url1 = reverse('api:user_detail', args=(self.super_django_user.pk,))
url2 = reverse('api:user_detail', args=(self.normal_django_user.pk,))
url3 = reverse('api:user_detail', args=(self.other_django_user.pk,))
data = self.delete(url1, expect=403, auth=self.get_other_credentials())
data = self.delete(url2, expect=403, auth=self.get_other_credentials())
data = self.delete(url3, expect=403, auth=self.get_other_credentials())
def test_there_exists_an_obvious_url_where_a_user_may_find_his_user_record(self):
url = reverse('main:user_me_list')
url = reverse('api:user_me_list')
data = self.get(url, expect=401, auth=None)
data = self.get(url, expect=401, auth=self.get_invalid_credentials())
data = self.get(url, expect=200, auth=self.get_normal_credentials())
@ -254,7 +254,7 @@ class UsersTest(BaseTest):
self.assertEquals(data['count'], 1)
def test_superuser_can_change_admin_only_fields_about_himself(self):
url = reverse('main:user_detail', args=(self.super_django_user.pk,))
url = reverse('api:user_detail', args=(self.super_django_user.pk,))
data = self.get(url, expect=200, auth=self.get_super_credentials())
data['username'] += '2'
data['first_name'] += ' Awesome'
@ -267,7 +267,7 @@ class UsersTest(BaseTest):
def test_user_related_resources(self):
# organizations the user is a member of, should be 1
url = reverse('main:user_organizations_list',
url = reverse('api:user_organizations_list',
args=(self.normal_django_user.pk,))
data = self.get(url, expect=200, auth=self.get_normal_credentials())
self.assertEquals(data['count'], 1)
@ -280,7 +280,7 @@ class UsersTest(BaseTest):
data = self.get(url, expect=403, auth=self.get_nobody_credentials())
# organizations the user is an admin of, should be 1
url = reverse('main:user_admin_of_organizations_list',
url = reverse('api:user_admin_of_organizations_list',
args=(self.normal_django_user.pk,))
data = self.get(url, expect=200, auth=self.get_normal_credentials())
self.assertEquals(data['count'], 1)
@ -293,7 +293,7 @@ class UsersTest(BaseTest):
data = self.get(url, expect=403, auth=self.get_nobody_credentials())
# teams the user is on, should be 0
url = reverse('main:user_teams_list', args=(self.normal_django_user.pk,))
url = reverse('api:user_teams_list', args=(self.normal_django_user.pk,))
data = self.get(url, expect=200, auth=self.get_normal_credentials())
self.assertEquals(data['count'], 0)
# also accessible via superuser
@ -305,15 +305,15 @@ class UsersTest(BaseTest):
data = self.get(url, expect=403, auth=self.get_nobody_credentials())
# verify org admin can still read other user data too
url = reverse('main:user_organizations_list',
url = reverse('api:user_organizations_list',
args=(self.other_django_user.pk,))
data = self.get(url, expect=200, auth=self.get_normal_credentials())
self.assertEquals(data['count'], 1)
url = reverse('main:user_admin_of_organizations_list',
url = reverse('api:user_admin_of_organizations_list',
args=(self.other_django_user.pk,))
data = self.get(url, expect=200, auth=self.get_normal_credentials())
self.assertEquals(data['count'], 0)
url = reverse('main:user_teams_list',
url = reverse('api:user_teams_list',
args=(self.other_django_user.pk,))
data = self.get(url, expect=200, auth=self.get_normal_credentials())
self.assertEquals(data['count'], 0)
@ -323,7 +323,7 @@ class UsersTest(BaseTest):
# FIXME: add test that shows posting a projects w/o id to /organizations/2/projects/ can create a new one & associate
def test_user_list_ordering(self):
base_url = reverse('main:user_list')
base_url = reverse('api:user_list')
base_qs = User.objects.distinct()
# Check list view with ordering by name.
@ -351,7 +351,7 @@ class UsersTest(BaseTest):
def test_user_list_filtering(self):
# Also serves as general-purpose testing for custom API filters.
base_url = reverse('main:user_list')
base_url = reverse('api:user_list')
base_qs = User.objects.distinct()
# Filter by username.
@ -651,7 +651,7 @@ class UsersTest(BaseTest):
self.check_get_list(url, self.super_django_user, base_qs, expect=400)
def test_user_list_pagination(self):
base_url = reverse('main:user_list')
base_url = reverse('api:user_list')
base_qs = User.objects.distinct()
# Check list view with page size of 1.
@ -682,7 +682,7 @@ class UsersTest(BaseTest):
# limit=0)
def test_user_list_searching(self):
base_url = reverse('main:user_list')
base_url = reverse('api:user_list')
base_qs = User.objects.distinct()
# Check search query parameter.
@ -826,12 +826,12 @@ class LdapTest(BaseTest):
self.use_test_setting(name)
user = self.check_login()
self.setup_users()
url = reverse('main:api_v1_config_view')
url = reverse('api:api_v1_config_view')
with self.current_user(self.super_django_user):
response = self.get(url, expect=200)
user_ldap_fields = response.get('user_ldap_fields', [])
self.assertTrue(user_ldap_fields)
url = reverse('main:user_detail', args=(user.pk,))
url = reverse('api:user_detail', args=(user.pk,))
for user_field in user_ldap_fields:
with self.current_user(self.super_django_user):
data = self.get(url, expect=200)

View File

@ -1,170 +1,7 @@
# Copyright (c) 2013 AnsibleWorks, Inc.
# All Rights Reserved.
from django.conf.urls import include, patterns, url as original_url
from django.conf import settings
from django.conf.urls import *
def url(regex, view, kwargs=None, name=None, prefix=''):
# Set default name from view name (if a string).
if isinstance(view, basestring) and name is None:
name = view
return original_url(regex, view, kwargs, name, prefix)
organization_urls = patterns('awx.main.views',
url(r'^$', 'organization_list'),
url(r'^(?P<pk>[0-9]+)/$', 'organization_detail'),
url(r'^(?P<pk>[0-9]+)/users/$', 'organization_users_list'),
url(r'^(?P<pk>[0-9]+)/admins/$', 'organization_admins_list'),
url(r'^(?P<pk>[0-9]+)/inventories/$', 'organization_inventories_list'),
url(r'^(?P<pk>[0-9]+)/projects/$', 'organization_projects_list'),
url(r'^(?P<pk>[0-9]+)/teams/$', 'organization_teams_list'),
)
user_urls = patterns('awx.main.views',
url(r'^$', 'user_list'),
url(r'^(?P<pk>[0-9]+)/$', 'user_detail'),
url(r'^(?P<pk>[0-9]+)/teams/$', 'user_teams_list'),
url(r'^(?P<pk>[0-9]+)/organizations/$', 'user_organizations_list'),
url(r'^(?P<pk>[0-9]+)/admin_of_organizations/$', 'user_admin_of_organizations_list'),
url(r'^(?P<pk>[0-9]+)/projects/$', 'user_projects_list'),
url(r'^(?P<pk>[0-9]+)/credentials/$', 'user_credentials_list'),
url(r'^(?P<pk>[0-9]+)/permissions/$', 'user_permissions_list'),
)
project_urls = patterns('awx.main.views',
url(r'^$', 'project_list'),
url(r'^(?P<pk>[0-9]+)/$', 'project_detail'),
url(r'^(?P<pk>[0-9]+)/playbooks/$', 'project_playbooks'),
url(r'^(?P<pk>[0-9]+)/organizations/$', 'project_organizations_list'),
url(r'^(?P<pk>[0-9]+)/teams/$', 'project_teams_list'),
url(r'^(?P<pk>[0-9]+)/update/$', 'project_update_view'),
url(r'^(?P<pk>[0-9]+)/project_updates/$', 'project_updates_list'),
)
project_update_urls = patterns('awx.main.views',
url(r'^(?P<pk>[0-9]+)/$', 'project_update_detail'),
url(r'^(?P<pk>[0-9]+)/cancel/$', 'project_update_cancel'),
)
team_urls = patterns('awx.main.views',
url(r'^$', 'team_list'),
url(r'^(?P<pk>[0-9]+)/$', 'team_detail'),
url(r'^(?P<pk>[0-9]+)/projects/$', 'team_projects_list'),
url(r'^(?P<pk>[0-9]+)/users/$', 'team_users_list'),
url(r'^(?P<pk>[0-9]+)/credentials/$', 'team_credentials_list'),
url(r'^(?P<pk>[0-9]+)/permissions/$', 'team_permissions_list'),
)
inventory_urls = patterns('awx.main.views',
url(r'^$', 'inventory_list'),
url(r'^(?P<pk>[0-9]+)/$', 'inventory_detail'),
url(r'^(?P<pk>[0-9]+)/hosts/$', 'inventory_hosts_list'),
url(r'^(?P<pk>[0-9]+)/groups/$', 'inventory_groups_list'),
url(r'^(?P<pk>[0-9]+)/root_groups/$', 'inventory_root_groups_list'),
url(r'^(?P<pk>[0-9]+)/variable_data/$', 'inventory_variable_data'),
url(r'^(?P<pk>[0-9]+)/script/$', 'inventory_script_view'),
url(r'^(?P<pk>[0-9]+)/tree/$', 'inventory_tree_view'),
url(r'^(?P<pk>[0-9]+)/inventory_sources/$', 'inventory_inventory_sources_list'),
)
host_urls = patterns('awx.main.views',
url(r'^$', 'host_list'),
url(r'^(?P<pk>[0-9]+)/$', 'host_detail'),
url(r'^(?P<pk>[0-9]+)/variable_data/$', 'host_variable_data'),
url(r'^(?P<pk>[0-9]+)/groups/$', 'host_groups_list'),
url(r'^(?P<pk>[0-9]+)/all_groups/$', 'host_all_groups_list'),
url(r'^(?P<pk>[0-9]+)/job_events/', 'host_job_events_list'),
url(r'^(?P<pk>[0-9]+)/job_host_summaries/$', 'host_job_host_summaries_list'),
#url(r'^(?P<pk>[0-9]+)/inventory_sources/$', 'host_inventory_sources_list'),
)
group_urls = patterns('awx.main.views',
url(r'^$', 'group_list'),
url(r'^(?P<pk>[0-9]+)/$', 'group_detail'),
url(r'^(?P<pk>[0-9]+)/children/$', 'group_children_list'),
url(r'^(?P<pk>[0-9]+)/hosts/$', 'group_hosts_list'),
url(r'^(?P<pk>[0-9]+)/all_hosts/$', 'group_all_hosts_list'),
url(r'^(?P<pk>[0-9]+)/variable_data/$', 'group_variable_data'),
url(r'^(?P<pk>[0-9]+)/job_events/$', 'group_job_events_list'),
url(r'^(?P<pk>[0-9]+)/job_host_summaries/$', 'group_job_host_summaries_list'),
url(r'^(?P<pk>[0-9]+)/potential_children/$', 'group_potential_children_list'),
#url(r'^(?P<pk>[0-9]+)/inventory_sources/$', 'group_inventory_sources_list'),
)
inventory_source_urls = patterns('awx.main.views',
url(r'^$', 'inventory_source_list'),
url(r'^(?P<pk>[0-9]+)/$', 'inventory_source_detail'),
url(r'^(?P<pk>[0-9]+)/update/$', 'inventory_source_update_view'),
url(r'^(?P<pk>[0-9]+)/inventory_updates/$', 'inventory_source_updates_list'),
#url(r'^(?P<pk>[0-9]+)/groups/$', 'inventory_source_groups_list'),
#url(r'^(?P<pk>[0-9]+)/hosts/$', 'inventory_source_hosts_list'),
)
inventory_update_urls = patterns('awx.main.views',
url(r'^(?P<pk>[0-9]+)/$', 'inventory_update_detail'),
url(r'^(?P<pk>[0-9]+)/cancel/$', 'inventory_update_cancel'),
)
credential_urls = patterns('awx.main.views',
url(r'^$', 'credential_list'),
url(r'^(?P<pk>[0-9]+)/$', 'credential_detail'),
# See also credentials resources on users/teams.
)
permission_urls = patterns('awx.main.views',
url(r'^(?P<pk>[0-9]+)/$', 'permission_detail'),
)
job_template_urls = patterns('awx.main.views',
url(r'^$', 'job_template_list'),
url(r'^(?P<pk>[0-9]+)/$', 'job_template_detail'),
url(r'^(?P<pk>[0-9]+)/jobs/$', 'job_template_jobs_list'),
url(r'^(?P<pk>[0-9]+)/callback/$', 'job_template_callback'),
)
job_urls = patterns('awx.main.views',
url(r'^$', 'job_list'),
url(r'^(?P<pk>[0-9]+)/$', 'job_detail'),
url(r'^(?P<pk>[0-9]+)/start/$', 'job_start'),
url(r'^(?P<pk>[0-9]+)/cancel/$', 'job_cancel'),
url(r'^(?P<pk>[0-9]+)/job_host_summaries/$', 'job_job_host_summaries_list'),
url(r'^(?P<pk>[0-9]+)/job_events/$', 'job_job_events_list'),
)
job_host_summary_urls = patterns('awx.main.views',
url(r'^(?P<pk>[0-9]+)/$', 'job_host_summary_detail'),
)
job_event_urls = patterns('awx.main.views',
url(r'^$', 'job_event_list'),
url(r'^(?P<pk>[0-9]+)/$', 'job_event_detail'),
url(r'^(?P<pk>[0-9]+)/children/$', 'job_event_children_list'),
url(r'^(?P<pk>[0-9]+)/hosts/$', 'job_event_hosts_list'),
)
v1_urls = patterns('awx.main.views',
url(r'^$', 'api_v1_root_view'),
url(r'^config/$', 'api_v1_config_view'),
url(r'^authtoken/$', 'auth_token_view'),
url(r'^me/$', 'user_me_list'),
url(r'^organizations/', include(organization_urls)),
url(r'^users/', include(user_urls)),
url(r'^projects/', include(project_urls)),
url(r'^project_updates/', include(project_update_urls)),
url(r'^teams/', include(team_urls)),
url(r'^inventories/', include(inventory_urls)),
url(r'^hosts/', include(host_urls)),
url(r'^groups/', include(group_urls)),
url(r'^inventory_sources/', include(inventory_source_urls)),
url(r'^inventory_updates/', include(inventory_update_urls)),
url(r'^credentials/', include(credential_urls)),
url(r'^permissions/', include(permission_urls)),
url(r'^job_templates/', include(job_template_urls)),
url(r'^jobs/', include(job_urls)),
url(r'^job_host_summaries/', include(job_host_summary_urls)),
url(r'^job_events/', include(job_event_urls)),
)
urlpatterns = patterns('awx.main.views',
url(r'^$', 'api_root_view'),
url(r'^v1/', include(v1_urls)),
)
urlpatterns = patterns()

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +0,0 @@
# Copyright (c) 2013 AnsibleWorks, Inc.
# All Rights Reserved.
import traceback
from django.http import HttpResponse
class ExceptionMiddleware(object):
def process_exception(self, request, exception):
if request.path.startswith('/api/'):
# FIXME: For GA, we shouldn't provide this level of detail to the
# end user.
return HttpResponse(traceback.format_exc(exception), content_type="text/plain", status=500)

View File

@ -130,28 +130,29 @@ INSTALLED_APPS = (
'kombu.transport.django',
'taggit',
'awx.main',
'awx.api',
'awx.ui',
)
INTERNAL_IPS = ('127.0.0.1',)
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_SERIALIZER_CLASS': 'awx.main.pagination.PaginationSerializer',
'DEFAULT_PAGINATION_SERIALIZER_CLASS': 'awx.api.pagination.PaginationSerializer',
'PAGINATE_BY': 25,
'PAGINATE_BY_PARAM': 'page_size',
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication',
'awx.main.authentication.TokenAuthentication',
'awx.api.authentication.TokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'awx.main.permissions.ModelAccessPermission',
'awx.api.permissions.ModelAccessPermission',
),
'DEFAULT_FILTER_BACKENDS': (
'awx.main.filters.ActiveOnlyBackend',
'awx.main.filters.FieldLookupBackend',
'awx.api.filters.ActiveOnlyBackend',
'awx.api.filters.FieldLookupBackend',
'rest_framework.filters.SearchFilter',
'awx.main.filters.OrderByBackend',
'awx.api.filters.OrderByBackend',
),
'DEFAULT_PARSER_CLASSES': (
'rest_framework.parsers.JSONParser',
@ -160,10 +161,10 @@ REST_FRAMEWORK = {
),
'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.JSONRenderer',
'awx.main.renderers.BrowsableAPIRenderer',
'awx.api.renderers.BrowsableAPIRenderer',
),
'VIEW_NAME_FUNCTION': 'awx.main.base_views.get_view_name',
'VIEW_DESCRIPTION_FUNCTION': 'awx.main.base_views.get_view_description',
'VIEW_NAME_FUNCTION': 'awx.api.generics.get_view_name',
'VIEW_DESCRIPTION_FUNCTION': 'awx.api.generics.get_view_description',
}
AUTHENTICATION_BACKENDS = (
@ -250,7 +251,7 @@ DEVSERVER_MODULES = (
try:
import django_jenkins
INSTALLED_APPS += ('django_jenkins',)
PROJECT_APPS = ('awx.main',)
PROJECT_APPS = ('awx.main', 'awx.api',)
except ImportError:
pass
@ -303,7 +304,7 @@ LOGGING = {
'()': 'django.utils.log.RequireDebugFalse',
},
'require_debug_true': {
'()': 'awx.main.compat.RequireDebugTrue',
'()': 'awx.lib.compat.RequireDebugTrue',
},
'require_debug_true_or_test': {
'()': 'awx.main.utils.RequireDebugTrueOrTest',
@ -360,11 +361,11 @@ LOGGING = {
'handlers': ['null'],
'propagate': False,
},
'awx.main.permissions': {
'awx.main.signals': {
'handlers': ['null'],
'propagate': False,
},
'awx.main.signals': {
'awx.api.permissions': {
'handlers': ['null'],
'propagate': False,
},

View File

@ -10,7 +10,7 @@ handler500 = 'awx.main.views.handle_500'
urlpatterns = patterns('',
url(r'', include('awx.ui.urls', namespace='ui', app_name='ui')),
url(r'^api/', include('awx.main.urls', namespace='main', app_name='main')),
url(r'^api/', include('awx.api.urls', namespace='api', app_name='api')),
)
if 'django.contrib.admin' in settings.INSTALLED_APPS: