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 = [] template_list = []
for klass in inspect.getmro(type(self)): for klass in inspect.getmro(type(self)):
template_basename = camelcase_to_underscore(klass.__name__) 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() context = self.get_description_context()
return render_to_string(template_list, 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.models import *
from awx.main.utils import get_object_or_400 from awx.main.utils import get_object_or_400
logger = logging.getLogger('awx.main.permissions') logger = logging.getLogger('awx.api.permissions')
__all__ = ['ModelAccessPermission', 'JobTemplateCallbackPermission', __all__ = ['ModelAccessPermission', 'JobTemplateCallbackPermission',
'JobTaskPermission'] 'JobTaskPermission']

View File

@@ -132,14 +132,14 @@ class BaseSerializer(serializers.ModelSerializer):
if obj is None: if obj is None:
return '' return ''
elif isinstance(obj, User): elif isinstance(obj, User):
return reverse('main:user_detail', args=(obj.pk,)) return reverse('api:user_detail', args=(obj.pk,))
else: else:
return obj.get_absolute_url() return obj.get_absolute_url()
def get_related(self, obj): def get_related(self, obj):
res = SortedDict() res = SortedDict()
if getattr(obj, 'created_by', None): 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 return res
def get_summary_fields(self, obj): def get_summary_fields(self, obj):
@@ -237,12 +237,12 @@ class UserSerializer(BaseSerializer):
return {} return {}
res = super(UserSerializer, self).get_related(obj) res = super(UserSerializer, self).get_related(obj)
res.update(dict( res.update(dict(
teams = reverse('main:user_teams_list', args=(obj.pk,)), teams = reverse('api:user_teams_list', args=(obj.pk,)),
organizations = reverse('main:user_organizations_list', args=(obj.pk,)), organizations = reverse('api:user_organizations_list', args=(obj.pk,)),
admin_of_organizations = reverse('main:user_admin_of_organizations_list', args=(obj.pk,)), admin_of_organizations = reverse('api:user_admin_of_organizations_list', args=(obj.pk,)),
projects = reverse('main:user_projects_list', args=(obj.pk,)), projects = reverse('api:user_projects_list', args=(obj.pk,)),
credentials = reverse('main:user_credentials_list', args=(obj.pk,)), credentials = reverse('api:user_credentials_list', args=(obj.pk,)),
permissions = reverse('main:user_permissions_list', args=(obj.pk,)), permissions = reverse('api:user_permissions_list', args=(obj.pk,)),
)) ))
return res return res
@@ -286,13 +286,13 @@ class OrganizationSerializer(BaseSerializer):
return {} return {}
res = super(OrganizationSerializer, self).get_related(obj) res = super(OrganizationSerializer, self).get_related(obj)
res.update(dict( res.update(dict(
#audit_trail = reverse('main:organization_audit_trail_list', args=(obj.pk,)), #audit_trail = reverse('api:organization_audit_trail_list', args=(obj.pk,)),
projects = reverse('main:organization_projects_list', args=(obj.pk,)), projects = reverse('api:organization_projects_list', args=(obj.pk,)),
inventories = reverse('main:organization_inventories_list', args=(obj.pk,)), inventories = reverse('api:organization_inventories_list', args=(obj.pk,)),
users = reverse('main:organization_users_list', args=(obj.pk,)), users = reverse('api:organization_users_list', args=(obj.pk,)),
admins = reverse('main:organization_admins_list', args=(obj.pk,)), admins = reverse('api:organization_admins_list', args=(obj.pk,)),
#tags = reverse('main:organization_tags_list', args=(obj.pk,)), #tags = reverse('api:organization_tags_list', args=(obj.pk,)),
teams = reverse('main:organization_teams_list', args=(obj.pk,)), teams = reverse('api:organization_teams_list', args=(obj.pk,)),
)) ))
return res return res
@@ -314,20 +314,20 @@ class ProjectSerializer(BaseSerializer):
return {} return {}
res = super(ProjectSerializer, self).get_related(obj) res = super(ProjectSerializer, self).get_related(obj)
res.update(dict( res.update(dict(
organizations = reverse('main:project_organizations_list', args=(obj.pk,)), organizations = reverse('api:project_organizations_list', args=(obj.pk,)),
teams = reverse('main:project_teams_list', args=(obj.pk,)), teams = reverse('api:project_teams_list', args=(obj.pk,)),
playbooks = reverse('main:project_playbooks', args=(obj.pk,)), playbooks = reverse('api:project_playbooks', args=(obj.pk,)),
update = reverse('main:project_update_view', args=(obj.pk,)), update = reverse('api:project_update_view', args=(obj.pk,)),
project_updates = reverse('main:project_updates_list', args=(obj.pk,)), project_updates = reverse('api:project_updates_list', args=(obj.pk,)),
)) ))
if obj.credential: if obj.credential:
res['credential'] = reverse('main:credential_detail', res['credential'] = reverse('api:credential_detail',
args=(obj.credential.pk,)) args=(obj.credential.pk,))
if obj.current_update: 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,)) args=(obj.current_update.pk,))
if obj.last_update: 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,)) args=(obj.last_update.pk,))
return res return res
@@ -433,8 +433,8 @@ class ProjectUpdateSerializer(BaseSerializer):
return {} return {}
res = super(ProjectUpdateSerializer, self).get_related(obj) res = super(ProjectUpdateSerializer, self).get_related(obj)
res.update(dict( res.update(dict(
project = reverse('main:project_detail', args=(obj.project.pk,)), project = reverse('api:project_detail', args=(obj.project.pk,)),
cancel = reverse('main:project_update_cancel', args=(obj.pk,)), cancel = reverse('api:project_update_cancel', args=(obj.pk,)),
)) ))
return res return res
@@ -467,14 +467,14 @@ class InventorySerializer(BaseSerializerWithVariables):
return {} return {}
res = super(InventorySerializer, self).get_related(obj) res = super(InventorySerializer, self).get_related(obj)
res.update(dict( res.update(dict(
hosts = reverse('main:inventory_hosts_list', args=(obj.pk,)), hosts = reverse('api:inventory_hosts_list', args=(obj.pk,)),
groups = reverse('main:inventory_groups_list', args=(obj.pk,)), groups = reverse('api:inventory_groups_list', args=(obj.pk,)),
root_groups = reverse('main:inventory_root_groups_list', args=(obj.pk,)), root_groups = reverse('api:inventory_root_groups_list', args=(obj.pk,)),
variable_data = reverse('main:inventory_variable_data', args=(obj.pk,)), variable_data = reverse('api:inventory_variable_data', args=(obj.pk,)),
script = reverse('main:inventory_script_view', args=(obj.pk,)), script = reverse('api:inventory_script_view', args=(obj.pk,)),
tree = reverse('main:inventory_tree_view', args=(obj.pk,)), tree = reverse('api:inventory_tree_view', args=(obj.pk,)),
organization = reverse('main:organization_detail', args=(obj.organization.pk,)), organization = reverse('api:organization_detail', args=(obj.organization.pk,)),
inventory_sources = reverse('main:inventory_inventory_sources_list', args=(obj.pk,)), inventory_sources = reverse('api:inventory_inventory_sources_list', args=(obj.pk,)),
)) ))
return res return res
@@ -491,18 +491,18 @@ class HostSerializer(BaseSerializerWithVariables):
return {} return {}
res = super(HostSerializer, self).get_related(obj) res = super(HostSerializer, self).get_related(obj)
res.update(dict( res.update(dict(
variable_data = reverse('main:host_variable_data', args=(obj.pk,)), variable_data = reverse('api:host_variable_data', args=(obj.pk,)),
inventory = reverse('main:inventory_detail', args=(obj.inventory.pk,)), inventory = reverse('api:inventory_detail', args=(obj.inventory.pk,)),
groups = reverse('main:host_groups_list', args=(obj.pk,)), groups = reverse('api:host_groups_list', args=(obj.pk,)),
all_groups = reverse('main:host_all_groups_list', args=(obj.pk,)), all_groups = reverse('api:host_all_groups_list', args=(obj.pk,)),
job_events = reverse('main:host_job_events_list', args=(obj.pk,)), job_events = reverse('api:host_job_events_list', args=(obj.pk,)),
job_host_summaries = reverse('main:host_job_host_summaries_list', args=(obj.pk,)), job_host_summaries = reverse('api:host_job_host_summaries_list', args=(obj.pk,)),
#inventory_sources = reverse('main:host_inventory_sources_list', args=(obj.pk,)), #inventory_sources = reverse('api:host_inventory_sources_list', args=(obj.pk,)),
)) ))
if obj.last_job: 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: 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 return res
def get_summary_fields(self, obj): def get_summary_fields(self, obj):
@@ -589,16 +589,16 @@ class GroupSerializer(BaseSerializerWithVariables):
return {} return {}
res = super(GroupSerializer, self).get_related(obj) res = super(GroupSerializer, self).get_related(obj)
res.update(dict( res.update(dict(
variable_data = reverse('main:group_variable_data', args=(obj.pk,)), variable_data = reverse('api:group_variable_data', args=(obj.pk,)),
hosts = reverse('main:group_hosts_list', args=(obj.pk,)), hosts = reverse('api:group_hosts_list', args=(obj.pk,)),
potential_children = reverse('main:group_potential_children_list', args=(obj.pk,)), potential_children = reverse('api:group_potential_children_list', args=(obj.pk,)),
children = reverse('main:group_children_list', args=(obj.pk,)), children = reverse('api:group_children_list', args=(obj.pk,)),
all_hosts = reverse('main:group_all_hosts_list', args=(obj.pk,)), all_hosts = reverse('api:group_all_hosts_list', args=(obj.pk,)),
inventory = reverse('main:inventory_detail', args=(obj.inventory.pk,)), inventory = reverse('api:inventory_detail', args=(obj.inventory.pk,)),
job_events = reverse('main:group_job_events_list', args=(obj.pk,)), job_events = reverse('api:group_job_events_list', args=(obj.pk,)),
job_host_summaries = reverse('main:group_job_host_summaries_list', args=(obj.pk,)), job_host_summaries = reverse('api:group_job_host_summaries_list', args=(obj.pk,)),
inventory_source = reverse('main:inventory_source_detail', args=(obj.inventory_source.pk,)), inventory_source = reverse('api:inventory_source_detail', args=(obj.inventory_source.pk,)),
#inventory_sources = reverse('main:group_inventory_sources_list', args=(obj.pk,)), #inventory_sources = reverse('api:group_inventory_sources_list', args=(obj.pk,)),
)) ))
return res return res
@@ -676,23 +676,23 @@ class InventorySourceSerializer(BaseSerializer):
return {} return {}
res = super(InventorySourceSerializer, self).get_related(obj) res = super(InventorySourceSerializer, self).get_related(obj)
res.update(dict( res.update(dict(
update = reverse('main:inventory_source_update_view', args=(obj.pk,)), update = reverse('api:inventory_source_update_view', args=(obj.pk,)),
inventory_updates = reverse('main:inventory_source_updates_list', args=(obj.pk,)), inventory_updates = reverse('api:inventory_source_updates_list', args=(obj.pk,)),
#hosts = reverse('main:inventory_source_hosts_list', args=(obj.pk,)), #hosts = reverse('api:inventory_source_hosts_list', args=(obj.pk,)),
#groups = reverse('main:inventory_source_groups_list', args=(obj.pk,)), #groups = reverse('api:inventory_source_groups_list', args=(obj.pk,)),
)) ))
if obj.inventory: 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: 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: if obj.credential:
res['credential'] = reverse('main:credential_detail', res['credential'] = reverse('api:credential_detail',
args=(obj.credential.pk,)) args=(obj.credential.pk,))
if obj.current_update: 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,)) args=(obj.current_update.pk,))
if obj.last_update: 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,)) args=(obj.last_update.pk,))
return res return res
@@ -741,8 +741,8 @@ class InventoryUpdateSerializer(BaseSerializer):
return {} return {}
res = super(InventoryUpdateSerializer, self).get_related(obj) res = super(InventoryUpdateSerializer, self).get_related(obj)
res.update(dict( res.update(dict(
inventory_source = reverse('main:inventory_source_detail', args=(obj.inventory_source.pk,)), inventory_source = reverse('api:inventory_source_detail', args=(obj.inventory_source.pk,)),
cancel = reverse('main:inventory_update_cancel', args=(obj.pk,)), cancel = reverse('api:inventory_update_cancel', args=(obj.pk,)),
)) ))
return res return res
@@ -757,11 +757,11 @@ class TeamSerializer(BaseSerializer):
return {} return {}
res = super(TeamSerializer, self).get_related(obj) res = super(TeamSerializer, self).get_related(obj)
res.update(dict( res.update(dict(
projects = reverse('main:team_projects_list', args=(obj.pk,)), projects = reverse('api:team_projects_list', args=(obj.pk,)),
users = reverse('main:team_users_list', args=(obj.pk,)), users = reverse('api:team_users_list', args=(obj.pk,)),
credentials = reverse('main:team_credentials_list', args=(obj.pk,)), credentials = reverse('api:team_credentials_list', args=(obj.pk,)),
organization = reverse('main:organization_detail', args=(obj.organization.pk,)), organization = reverse('api:organization_detail', args=(obj.organization.pk,)),
permissions = reverse('main:team_permissions_list', args=(obj.pk,)), permissions = reverse('api:team_permissions_list', args=(obj.pk,)),
)) ))
return res return res
@@ -777,13 +777,13 @@ class PermissionSerializer(BaseSerializer):
return {} return {}
res = super(PermissionSerializer, self).get_related(obj) res = super(PermissionSerializer, self).get_related(obj)
if obj.user: 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: 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: 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: 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 return res
def validate(self, attrs): def validate(self, attrs):
@@ -837,9 +837,9 @@ class CredentialSerializer(BaseSerializer):
return {} return {}
res = super(CredentialSerializer, self).get_related(obj) res = super(CredentialSerializer, self).get_related(obj)
if obj.user: 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: 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 return res
class JobTemplateSerializer(BaseSerializer): class JobTemplateSerializer(BaseSerializer):
@@ -855,14 +855,14 @@ class JobTemplateSerializer(BaseSerializer):
return {} return {}
res = super(JobTemplateSerializer, self).get_related(obj) res = super(JobTemplateSerializer, self).get_related(obj)
res.update(dict( res.update(dict(
inventory = reverse('main:inventory_detail', args=(obj.inventory.pk,)), inventory = reverse('api:inventory_detail', args=(obj.inventory.pk,)),
project = reverse('main:project_detail', args=(obj.project.pk,)), project = reverse('api:project_detail', args=(obj.project.pk,)),
jobs = reverse('main:job_template_jobs_list', args=(obj.pk,)), jobs = reverse('api:job_template_jobs_list', args=(obj.pk,)),
)) ))
if obj.credential: 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: 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 return res
def validate_playbook(self, attrs, source): def validate_playbook(self, attrs, source):
@@ -892,18 +892,18 @@ class JobSerializer(BaseSerializer):
return {} return {}
res = super(JobSerializer, self).get_related(obj) res = super(JobSerializer, self).get_related(obj)
res.update(dict( res.update(dict(
inventory = reverse('main:inventory_detail', args=(obj.inventory.pk,)), inventory = reverse('api:inventory_detail', args=(obj.inventory.pk,)),
project = reverse('main:project_detail', args=(obj.project.pk,)), project = reverse('api:project_detail', args=(obj.project.pk,)),
credential = reverse('main:credential_detail', args=(obj.credential.pk,)), credential = reverse('api:credential_detail', args=(obj.credential.pk,)),
job_events = reverse('main:job_job_events_list', args=(obj.pk,)), job_events = reverse('api:job_job_events_list', args=(obj.pk,)),
job_host_summaries = reverse('main:job_job_host_summaries_list', args=(obj.pk,)), job_host_summaries = reverse('api:job_job_host_summaries_list', args=(obj.pk,)),
)) ))
if obj.job_template: 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: 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: 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 return res
def from_native(self, data, files): def from_native(self, data, files):
@@ -942,8 +942,8 @@ class JobHostSummarySerializer(BaseSerializer):
return {} return {}
res = super(JobHostSummarySerializer, self).get_related(obj) res = super(JobHostSummarySerializer, self).get_related(obj)
res.update(dict( res.update(dict(
job=reverse('main:job_detail', args=(obj.job.pk,)), job=reverse('api:job_detail', args=(obj.job.pk,)),
host=reverse('main:host_detail', args=(obj.host.pk,)) host=reverse('api:host_detail', args=(obj.host.pk,))
)) ))
return res return res
@@ -975,17 +975,17 @@ class JobEventSerializer(BaseSerializer):
return {} return {}
res = super(JobEventSerializer, self).get_related(obj) res = super(JobEventSerializer, self).get_related(obj)
res.update(dict( res.update(dict(
job = reverse('main:job_detail', args=(obj.job.pk,)), job = reverse('api:job_detail', args=(obj.job.pk,)),
#children = reverse('main:job_event_children_list', args=(obj.pk,)), #children = reverse('api:job_event_children_list', args=(obj.pk,)),
)) ))
if obj.parent: 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(): 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: 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(): 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 return res
def get_summary_fields(self, obj): 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: Each {{ model_verbose_name }} data structure includes the following fields:
{% include "main/_result_fields_common.md" %} {% include "api/_result_fields_common.md" %}
## Sorting ## 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 {{ model_verbose_name_plural }} directly or indirectly belonging to this
{{ parent_model_verbose_name }}. {{ 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 {{ model_verbose_name_plural }} available to be added as children of the
current {{ parent_model_verbose_name }}. 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 {{ model_verbose_name_plural }} of which the selected
{{ parent_model_verbose_name }} is directly or indirectly a member. {{ 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 {{ model_verbose_name_plural }} associated with this
{{ parent_model_verbose_name }}. {{ 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. The response status code will be 202 if successful, or 405 if the
update cannot be canceled. 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 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. 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: 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 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 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 %} {% block post_create %}
Any fields not explicitly provided for the new job (except `name` and 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 Make a GET request to this resource to retrieve the list of
{{ model_verbose_name_plural }}. {{ 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 }}: # 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 }}: fields to create a new {{ model_verbose_name }}:
{% with write_only=1 %} {% with write_only=1 %}
{% include "main/_result_fields_common.md" %} {% include "api/_result_fields_common.md" %}
{% endwith %} {% 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" %} {% 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 %} {% 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. The response status code will be 202 if successful, or 405 if the
update cannot be canceled. 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 are not provided, a 400 status code will be returned. If the project cannot be
updated, a 405 status code will be returned. 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 }} Make GET request to this resource to retrieve a single {{ model_verbose_name }}
record containing the following fields: 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 }}: # 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: {{ model_verbose_name }}. The following fields may be modified:
{% with write_only=1 %} {% with write_only=1 %}
{% include "main/_result_fields_common.md" %} {% include "api/_result_fields_common.md" %}
{% endwith %} {% endwith %}
For a PUT request, include **all** fields in the request. For a PUT request, include **all** fields in the request.
For a PATCH request, include only the fields that are being modified. 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 }}: # 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: {{ model_verbose_name }}. The following fields may be modified:
{% with write_only=1 %} {% with write_only=1 %}
{% include "main/_result_fields_common.md" %} {% include "api/_result_fields_common.md" %}
{% endwith %} {% endwith %}
For a PUT request, include **all** fields in the request. 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 }}. 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 {{ model_verbose_name_plural }} associated with the selected
{{ parent_model_verbose_name }}. {{ 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 }}: # 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 }}. {{ parent_model_verbose_name }}.
{% with write_only=1 %} {% with write_only=1 %}
{% include "main/_result_fields_common.md" %} {% include "api/_result_fields_common.md" %}
{% endwith %} {% endwith %}
{% block post_create %}{% endblock %} {% 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 }}. without deleting the {{ model_verbose_name }}.
{% endif %} {% 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 {{ model_verbose_name_plural }} of which the selected
{{ parent_model_verbose_name }} is an admin. {{ 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: 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. 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.models import User
from django.contrib.auth.admin import UserAdmin 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.models import *
from awx.main.forms import * from awx.main.forms import *

View File

@@ -35,7 +35,7 @@ from taggit.managers import TaggableManager
from djcelery.models import TaskMeta from djcelery.models import TaskMeta
# AWX # AWX
from awx.main.compat import slugify from awx.lib.compat import slugify
from awx.main.fields import AutoOneToOneField from awx.main.fields import AutoOneToOneField
from awx.main.utils import encrypt_field, decrypt_field 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') projects = models.ManyToManyField('Project', blank=True, related_name='organizations')
def get_absolute_url(self): def get_absolute_url(self):
return reverse('main:organization_detail', args=(self.pk,)) return reverse('api:organization_detail', args=(self.pk,))
def __unicode__(self): def __unicode__(self):
return self.name return self.name
@@ -412,7 +412,7 @@ class Inventory(CommonModel):
) )
def get_absolute_url(self): 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): def mark_inactive(self, save=True):
''' '''
@@ -537,7 +537,7 @@ class Host(CommonModelNameNotUnique):
return self.name return self.name
def get_absolute_url(self): 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): def mark_inactive(self, save=True):
''' '''
@@ -667,7 +667,7 @@ class Group(CommonModelNameNotUnique):
return self.name return self.name
def get_absolute_url(self): 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): def mark_inactive(self, save=True):
''' '''
@@ -938,7 +938,7 @@ class InventorySource(PrimordialModel):
return inventory_update return inventory_update
def get_absolute_url(self): 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): class InventoryUpdate(CommonTask):
''' '''
@@ -972,7 +972,7 @@ class InventoryUpdate(CommonTask):
return self.inventory_source return self.inventory_source
def get_absolute_url(self): 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): def _get_task_class(self):
from awx.main.tasks import RunInventoryUpdate from awx.main.tasks import RunInventoryUpdate
@@ -1087,7 +1087,7 @@ class Credential(CommonModelNameNotUnique):
return needed return needed
def get_absolute_url(self): def get_absolute_url(self):
return reverse('main:credential_detail', args=(self.pk,)) return reverse('api:credential_detail', args=(self.pk,))
def clean(self): def clean(self):
if self.user and self.team: 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') organization = models.ForeignKey('Organization', blank=False, null=True, on_delete=SET_NULL, related_name='teams')
def get_absolute_url(self): def get_absolute_url(self):
return reverse('main:team_detail', args=(self.pk,)) return reverse('api:team_detail', args=(self.pk,))
class Project(CommonModel): class Project(CommonModel):
''' '''
@@ -1377,7 +1377,7 @@ class Project(CommonModel):
return project_update return project_update
def get_absolute_url(self): 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): def get_project_path(self, check_if_exists=True):
local_path = os.path.basename(self.local_path) local_path = os.path.basename(self.local_path)
@@ -1435,7 +1435,7 @@ class ProjectUpdate(CommonTask):
) )
def get_absolute_url(self): 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): def _get_parent_instance(self):
return self.project return self.project
@@ -1507,7 +1507,7 @@ class Permission(CommonModelNameNotUnique):
)) ))
def get_absolute_url(self): 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) # TODO: other job types (later)
@@ -1607,7 +1607,7 @@ class JobTemplate(CommonModel):
return job return job
def get_absolute_url(self): 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): def can_start_without_user_input(self):
''' '''
@@ -1719,7 +1719,7 @@ class Job(CommonTask):
) )
def get_absolute_url(self): 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) extra_vars_dict = VarsDictProperty('extra_vars', True)
@@ -1829,7 +1829,7 @@ class JobHostSummary(models.Model):
self.processed, self.skipped) self.processed, self.skipped)
def get_absolute_url(self): 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): def save(self, *args, **kwargs):
self.failed = bool(self.dark or self.failures) self.failed = bool(self.dark or self.failures)
@@ -1982,7 +1982,7 @@ class JobEvent(models.Model):
) )
def get_absolute_url(self): 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): def __unicode__(self):
return u'%s @ %s' % (self.get_event_display(), self.created.isoformat()) 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): def test_get_inventory_list(self):
url = reverse('main:inventory_list') url = reverse('api:inventory_list')
qs = Inventory.objects.filter(active=True).distinct() qs = Inventory.objects.filter(active=True).distinct()
# Check list view with invalid authentication. # Check list view with invalid authentication.
@@ -66,7 +66,7 @@ class InventoryTest(BaseTest):
self.check_get_list(url, self.nobody_django_user, nobody_qs) self.check_get_list(url, self.nobody_django_user, nobody_qs)
def test_post_inventory_list(self): def test_post_inventory_list(self):
url = reverse('main:inventory_list') url = reverse('api:inventory_list')
# Check post to list view with invalid authentication. # Check post to list view with invalid authentication.
new_inv_0 = dict(name='inventory-c', description='baz', organization=self.organizations[0].pk) 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) data = self.post(url, data=new_inv_denied, expect=403)
def test_get_inventory_detail(self): def test_get_inventory_detail(self):
url_a = reverse('main:inventory_detail', args=(self.inventory_a.pk,)) url_a = reverse('api:inventory_detail', args=(self.inventory_a.pk,))
url_b = reverse('main:inventory_detail', args=(self.inventory_b.pk,)) url_b = reverse('api:inventory_detail', args=(self.inventory_b.pk,))
# Check detail view with invalid authentication. # Check detail view with invalid authentication.
self.check_invalid_auth(url_a) self.check_invalid_auth(url_a)
@@ -125,8 +125,8 @@ class InventoryTest(BaseTest):
data = self.get(url_b, expect=403) data = self.get(url_b, expect=403)
def test_put_inventory_detail(self): def test_put_inventory_detail(self):
url_a = reverse('main:inventory_detail', args=(self.inventory_a.pk,)) url_a = reverse('api:inventory_detail', args=(self.inventory_a.pk,))
url_b = reverse('main:inventory_detail', args=(self.inventory_b.pk,)) url_b = reverse('api:inventory_detail', args=(self.inventory_b.pk,))
# Check put to detail view with invalid authentication. # Check put to detail view with invalid authentication.
self.check_invalid_auth(url_a, methods=('put',)) self.check_invalid_auth(url_a, methods=('put',))
@@ -178,7 +178,7 @@ class InventoryTest(BaseTest):
# Via AC-376: # Via AC-376:
# Create an inventory. Leave the description empty. # Create an inventory. Leave the description empty.
# Edit the new inventory, change the Name, click Save. # 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='', new_data = dict(name='inventory-c', description='',
organization=self.organizations[0].pk) organization=self.organizations[0].pk)
new_id = max(Inventory.objects.values_list('pk', flat=True)) + 1 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) data = self.post(list_url, data=new_data, expect=201)
self.assertEqual(data['id'], new_id) self.assertEqual(data['id'], new_id)
self.assertEqual(data['description'], '') 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) data = self.get(url_c, expect=200)
self.assertEqual(data['description'], '') self.assertEqual(data['description'], '')
data['description'] = None data['description'] = None
@@ -194,8 +194,8 @@ class InventoryTest(BaseTest):
self.put(url_c, data, expect=200) self.put(url_c, data, expect=200)
def test_delete_inventory_detail(self): def test_delete_inventory_detail(self):
url_a = reverse('main:inventory_detail', args=(self.inventory_a.pk,)) url_a = reverse('api:inventory_detail', args=(self.inventory_a.pk,))
url_b = reverse('main:inventory_detail', args=(self.inventory_b.pk,)) url_b = reverse('api:inventory_detail', args=(self.inventory_b.pk,))
# Create test hosts and groups within each inventory. # Create test hosts and groups within each inventory.
self.inventory_a.hosts.create(name='host-a') self.inventory_a.hosts.create(name='host-a')
@@ -246,11 +246,11 @@ class InventoryTest(BaseTest):
def test_main_line(self): def test_main_line(self):
# some basic URLs... # some basic URLs...
inventories = reverse('main:inventory_list') inventories = reverse('api:inventory_list')
inventories_1 = reverse('main:inventory_detail', args=(self.inventory_a.pk,)) inventories_1 = reverse('api:inventory_detail', args=(self.inventory_a.pk,))
inventories_2 = reverse('main:inventory_detail', args=(self.inventory_b.pk,)) inventories_2 = reverse('api:inventory_detail', args=(self.inventory_b.pk,))
hosts = reverse('main:host_list') hosts = reverse('api:host_list')
groups = reverse('main:group_list') groups = reverse('api:group_list')
# a super user can add hosts (but inventory ID is required) # 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_c = dict(name='web4', inventory=inv.pk)
new_group_d = dict(name='web5', inventory=inv.pk) new_group_d = dict(name='web5', inventory=inv.pk)
new_group_e = dict(name='web6', 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=invalid, expect=400, auth=self.get_super_credentials())
data0 = self.post(groups, data=new_group_a, expect=201, 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 # 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_a = dict(name='web100.example.com')
new_host_b = dict(name='web101.example.com') new_host_b = dict(name='web101.example.com')
new_host_c = dict(name='web102.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()) 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 # 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()) 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()) got = self.get(url5, expect=200, auth=self.get_other_credentials())
self.assertEquals(got['count'], 4) self.assertEquals(got['count'], 4)
@@ -392,9 +392,9 @@ class InventoryTest(BaseTest):
################################################## ##################################################
# GROUPS->inventories POST via subcollection # 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_a = dict(name='web100')
new_group_b = dict(name='web101') new_group_b = dict(name='web101')
new_group_c = dict(name='web102') 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()) 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 # 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()) added_by_collection = self.post(url5, data=new_group_d, expect=201, auth=self.get_other_credentials())
# make sure duplicates give 400s # make sure duplicates give 400s
self.post(url5, data=new_group_d, expect=400, auth=self.get_other_credentials()) 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))) 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 # 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()) got = self.get(vdata_url, expect=200, auth=self.get_super_credentials())
self.assertEquals(got, {}) 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))) vars_c = dict(asdf=9999, dog='pluto', cat='five', unstructured=dict(a=[3,3,3],b=dict(z=5)))
groups = Group.objects.all() groups = Group.objects.all()
vdata1_url = reverse('main:group_variable_data', args=(groups[0].pk,)) vdata1_url = reverse('api:group_variable_data', args=(groups[0].pk,))
vdata2_url = reverse('main:group_variable_data', args=(groups[1].pk,)) vdata2_url = reverse('api:group_variable_data', args=(groups[1].pk,))
# a super user can associate variable objects with groups # a super user can associate variable objects with groups
got = self.get(vdata1_url, expect=200, auth=self.get_super_credentials()) 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_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))) 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 # a super user can associate variable objects with inventory
got = self.get(vdata_url, expect=200, auth=self.get_super_credentials()) got = self.get(vdata_url, expect=200, auth=self.get_super_credentials())
@@ -536,14 +536,14 @@ class InventoryTest(BaseTest):
groups[0].save() groups[0].save()
# access # 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()) data = self.get(url1, expect=200, auth=self.get_normal_credentials())
self.assertEquals(data['count'], 2) self.assertEquals(data['count'], 2)
self.assertTrue(host1.pk in [x['id'] for x in data['results']]) self.assertTrue(host1.pk in [x['id'] for x in data['results']])
self.assertTrue(host3.pk in [x['id'] for x in data['results']]) self.assertTrue(host3.pk in [x['id'] for x in data['results']])
# addition # 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()) got = self.get(url, expect=200, auth=self.get_normal_credentials())
self.assertEquals(got['id'], host2.pk) self.assertEquals(got['id'], host2.pk)
posted = self.post(url1, data=got, expect=204, auth=self.get_normal_credentials()) posted = self.post(url1, data=got, expect=204, auth=self.get_normal_credentials())
@@ -596,15 +596,15 @@ class InventoryTest(BaseTest):
g2.save() g2.save()
# a super user can set subgroups # 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,)) 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,)) 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,)) 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,)) 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,)) args=(Group.objects.get(name='web101').pk,))
got = self.get(child_url, expect=200, auth=self.get_super_credentials()) 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()) 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 # a group can't be it's own grandparent
subsub = posted2['related']['children'] subsub = posted2['related']['children']
# this is the grandparent # 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()) parent_data = self.get(original_url, expect=200, auth=self.get_super_credentials())
# now posting to kid's children collection... # now posting to kid's children collection...
self.post(subsub, data=parent_data, expect=403, auth=self.get_super_credentials()) self.post(subsub, data=parent_data, expect=403, auth=self.get_super_credentials())
@@ -648,7 +648,7 @@ class InventoryTest(BaseTest):
# slight detour # slight detour
# can see all hosts under a group, even if it has subgroups # can see all hosts under a group, even if it has subgroups
# this URL is NOT postable # 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,)) args=(Group.objects.get(name='web2').pk,))
self.assertEqual(Group.objects.get(name='web2').hosts.count(), 3) self.assertEqual(Group.objects.get(name='web2').hosts.count(), 3)
data = self.get(all_hosts, expect=200, auth=self.get_normal_credentials()) 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.parents.count())
self.assertTrue(removed_group.active) self.assertTrue(removed_group.active)
for parent in removed_group.parents.all(): 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} data = {'id': removed_group.pk, 'disassociate': 1}
self.post(parent_children_url, data, expect=204, auth=self.get_super_credentials()) self.post(parent_children_url, data, expect=204, auth=self.get_super_credentials())
removed_group = Group.objects.get(pk=result['id']) 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 # Removing a group from a hierarchy should migrate its children to the
# parent. The group itself will be deleted (marked inactive), and all # parent. The group itself will be deleted (marked inactive), and all
# relationships removed. # relationships removed.
url = reverse('main:group_children_list', args=(gx2.pk,)) url = reverse('api:group_children_list', args=(gx2.pk,))
data = { data = {
'id': gx3.pk, 'id': gx3.pk,
'disassociate': 1, 'disassociate': 1,
@@ -691,7 +691,7 @@ class InventoryTest(BaseTest):
#self.assertTrue(gx4 in gx2.children.all()) #self.assertTrue(gx4 in gx2.children.all())
# Try with invalid hostnames and invalid IPs. # 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. invalid_expect = 400 # hostname validation is disabled for now.
data = dict(name='', inventory=inv.pk) data = dict(name='', inventory=inv.pk)
with self.current_user(self.super_django_user): with self.current_user(self.super_django_user):
@@ -752,7 +752,7 @@ class InventoryTest(BaseTest):
h_d.groups.add(g_d) h_d.groups.add(g_d)
# Old, slow 1.2 way. # 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): with self.current_user(self.super_django_user):
response = self.get(url, expect=200) response = self.get(url, expect=200)
self.assertTrue('all' in response) self.assertTrue('all' in response)
@@ -772,7 +772,7 @@ class InventoryTest(BaseTest):
self.assertEqual(response, h.variables_dict) self.assertEqual(response, h.variables_dict)
# New 1.3 way. # 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 url = '%s?hostvars=1' % url
with self.current_user(self.super_django_user): with self.current_user(self.super_django_user):
response = self.get(url, expect=200) response = self.get(url, expect=200)
@@ -792,7 +792,7 @@ class InventoryTest(BaseTest):
g_d = self.inventory_a.groups.create(name='D') g_d = self.inventory_a.groups.create(name='D')
g_d.parents.add(g_c) 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): with self.current_user(self.super_django_user):
response = self.get(url, expect=200) response = self.get(url, expect=200)

View File

@@ -436,7 +436,7 @@ class JobTemplateTest(BaseJobTestMixin, django.test.TestCase):
'job_tags', 'host_config_key',) 'job_tags', 'host_config_key',)
def test_get_job_template_list(self): def test_get_job_template_list(self):
url = reverse('main:job_template_list') url = reverse('api:job_template_list')
qs = JobTemplate.objects.distinct() qs = JobTemplate.objects.distinct()
fields = self.JOB_TEMPLATE_FIELDS fields = self.JOB_TEMPLATE_FIELDS
@@ -474,7 +474,7 @@ class JobTemplateTest(BaseJobTestMixin, django.test.TestCase):
# FIXME: Check with other credentials. # FIXME: Check with other credentials.
def test_post_job_template_list(self): def test_post_job_template_list(self):
url = reverse('main:job_template_list') url = reverse('api:job_template_list')
data = dict( data = dict(
name = 'new job template', name = 'new job template',
job_type = PERM_INVENTORY_DEPLOY, job_type = PERM_INVENTORY_DEPLOY,
@@ -489,7 +489,7 @@ class JobTemplateTest(BaseJobTestMixin, django.test.TestCase):
# sue can always add job templates. # sue can always add job templates.
with self.current_user(self.user_sue): with self.current_user(self.user_sue):
response = self.post(url, data, expect=201) response = self.post(url, data, expect=201)
detail_url = reverse('main:job_template_detail', detail_url = reverse('api:job_template_detail',
args=(response['id'],)) args=(response['id'],))
self.assertEquals(response['url'], detail_url) self.assertEquals(response['url'], detail_url)
@@ -530,7 +530,7 @@ class JobTemplateTest(BaseJobTestMixin, django.test.TestCase):
def test_get_job_template_detail(self): def test_get_job_template_detail(self):
jt = self.jt_eng_run 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. # Test with no auth and with invalid login.
self.check_invalid_auth(url) self.check_invalid_auth(url)
@@ -551,7 +551,7 @@ class JobTemplateTest(BaseJobTestMixin, django.test.TestCase):
def test_put_job_template_detail(self): def test_put_job_template_detail(self):
jt = self.jt_eng_run 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. # Test with no auth and with invalid login.
self.check_invalid_auth(url, methods=('put',))# 'patch')) 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): def test_get_job_template_job_list(self):
jt = self.jt_eng_run 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. # Test with no auth and with invalid login.
self.check_invalid_auth(url) self.check_invalid_auth(url)
@@ -586,7 +586,7 @@ class JobTemplateTest(BaseJobTestMixin, django.test.TestCase):
def test_post_job_template_job_list(self): def test_post_job_template_job_list(self):
jt = self.jt_eng_run 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( data = dict(
name='new job from template', name='new job from template',
credential=self.cred_bob.pk, credential=self.cred_bob.pk,
@@ -604,7 +604,7 @@ class JobTemplateTest(BaseJobTestMixin, django.test.TestCase):
class JobTest(BaseJobTestMixin, django.test.TestCase): class JobTest(BaseJobTestMixin, django.test.TestCase):
def test_get_job_list(self): def test_get_job_list(self):
url = reverse('main:job_list') url = reverse('api:job_list')
# Test with no auth and with invalid login. # Test with no auth and with invalid login.
self.check_invalid_auth(url) self.check_invalid_auth(url)
@@ -622,7 +622,7 @@ class JobTest(BaseJobTestMixin, django.test.TestCase):
# FIXME: Check with other credentials. # FIXME: Check with other credentials.
def test_post_job_list(self): def test_post_job_list(self):
url = reverse('main:job_list') url = reverse('api:job_list')
data = dict( data = dict(
name='new job without template', name='new job without template',
job_type=PERM_INVENTORY_DEPLOY, job_type=PERM_INVENTORY_DEPLOY,
@@ -652,7 +652,7 @@ class JobTest(BaseJobTestMixin, django.test.TestCase):
def test_get_job_detail(self): def test_get_job_detail(self):
job = self.job_ops_east_run 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. # Test with no auth and with invalid login.
self.check_invalid_auth(url) self.check_invalid_auth(url)
@@ -668,7 +668,7 @@ class JobTest(BaseJobTestMixin, django.test.TestCase):
def test_put_job_detail(self): def test_put_job_detail(self):
job = self.job_ops_west_run 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. # Test with no auth and with invalid login.
self.check_invalid_auth(url, methods=('put',))# 'patch')) 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. # FIXME: Check with other credentials and readonly fields.
def _test_mainline(self): def _test_mainline(self):
url = reverse('main:job_list') url = reverse('api:job_list')
# job templates # job templates
data = self.get('/api/v1/job_templates/', expect=401) data = self.get('/api/v1/job_templates/', expect=401)
@@ -769,7 +769,7 @@ class JobStartCancelTest(BaseJobTestMixin, django.test.LiveServerTestCase):
def test_job_start(self): def test_job_start(self):
job = self.job_ops_east_run 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. # Test with no auth and with invalid login.
self.check_invalid_auth(url) 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. # Test with a job that prompts for SSH and sudo passwords.
job = self.job_sup_run 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): with self.current_user(self.user_sue):
response = self.get(url) response = self.get(url)
self.assertTrue(response['can_start']) self.assertTrue(response['can_start'])
@@ -821,7 +821,7 @@ class JobStartCancelTest(BaseJobTestMixin, django.test.LiveServerTestCase):
credential=self.cred_greg, credential=self.cred_greg,
created_by=self.user_sue, 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): with self.current_user(self.user_sue):
response = self.get(url) response = self.get(url)
self.assertTrue(response['can_start']) self.assertTrue(response['can_start'])
@@ -841,7 +841,7 @@ class JobStartCancelTest(BaseJobTestMixin, django.test.LiveServerTestCase):
credential=self.cred_greg, credential=self.cred_greg,
created_by=self.user_sue, 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): with self.current_user(self.user_sue):
response = self.get(url) response = self.get(url)
self.assertTrue(response['can_start']) self.assertTrue(response['can_start'])
@@ -858,7 +858,7 @@ class JobStartCancelTest(BaseJobTestMixin, django.test.LiveServerTestCase):
def test_job_cancel(self): def test_job_cancel(self):
job = self.job_ops_east_run 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. # Test with no auth and with invalid login.
self.check_invalid_auth(url) self.check_invalid_auth(url)
@@ -887,7 +887,7 @@ class JobStartCancelTest(BaseJobTestMixin, django.test.LiveServerTestCase):
job.start() job.start()
# Check that the job detail has been updated. # 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): with self.current_user(self.user_sue):
response = self.get(url) response = self.get(url)
self.assertEqual(response['status'], 'successful', self.assertEqual(response['status'], 'successful',
@@ -895,7 +895,7 @@ class JobStartCancelTest(BaseJobTestMixin, django.test.LiveServerTestCase):
self.assertTrue(response['result_stdout']) self.assertTrue(response['result_stdout'])
# Test job events for completed job. # 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): with self.current_user(self.user_sue):
response = self.get(url) response = self.get(url)
qs = job.job_events.all() qs = job.job_events.all()
@@ -908,13 +908,13 @@ class JobStartCancelTest(BaseJobTestMixin, django.test.LiveServerTestCase):
for job_event in job.job_events.all(): for job_event in job.job_events.all():
if job_event.host: if job_event.host:
host_ids.add(job_event.host.pk) 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): with self.current_user(self.user_sue):
response = self.get(url) response = self.get(url)
# Also test job event list for each host. # Also test job event list for each host.
for host in Host.objects.filter(pk__in=host_ids): 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): with self.current_user(self.user_sue):
response = self.get(url) response = self.get(url)
qs = host.job_events.all() qs = host.job_events.all()
@@ -924,7 +924,7 @@ class JobStartCancelTest(BaseJobTestMixin, django.test.LiveServerTestCase):
# Test job event list for groups. # Test job event list for groups.
for group in self.inv_ops_east.groups.all(): 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): with self.current_user(self.user_sue):
response = self.get(url) response = self.get(url)
qs = group.job_events.all() qs = group.job_events.all()
@@ -933,7 +933,7 @@ class JobStartCancelTest(BaseJobTestMixin, django.test.LiveServerTestCase):
self.check_list_ids(response, qs) self.check_list_ids(response, qs)
# Test global job event list. # Test global job event list.
url = reverse('main:job_event_list') url = reverse('api:job_event_list')
with self.current_user(self.user_sue): with self.current_user(self.user_sue):
response = self.get(url) response = self.get(url)
qs = JobEvent.objects.all() qs = JobEvent.objects.all()
@@ -942,7 +942,7 @@ class JobStartCancelTest(BaseJobTestMixin, django.test.LiveServerTestCase):
self.check_list_ids(response, qs) self.check_list_ids(response, qs)
# Test job host summaries for completed job. # 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): with self.current_user(self.user_sue):
response = self.get(url) response = self.get(url)
qs = job.job_host_summaries.all() qs = job.job_host_summaries.all()
@@ -956,14 +956,14 @@ class JobStartCancelTest(BaseJobTestMixin, django.test.LiveServerTestCase):
# Test individual job host summary records. # Test individual job host summary records.
for job_host_summary in job.job_host_summaries.all(): 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,)) args=(job_host_summary.pk,))
with self.current_user(self.user_sue): with self.current_user(self.user_sue):
response = self.get(url) response = self.get(url)
# Test job host summaries for each host. # Test job host summaries for each host.
for host in Host.objects.filter(pk__in=host_ids): 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): with self.current_user(self.user_sue):
response = self.get(url) response = self.get(url)
qs = host.job_host_summaries.all() qs = host.job_host_summaries.all()
@@ -973,7 +973,7 @@ class JobStartCancelTest(BaseJobTestMixin, django.test.LiveServerTestCase):
# Test job host summaries for groups. # Test job host summaries for groups.
for group in self.inv_ops_east.groups.all(): 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): with self.current_user(self.user_sue):
response = self.get(url) response = self.get(url)
qs = group.job_host_summaries.all() qs = group.job_host_summaries.all()
@@ -1115,7 +1115,7 @@ class JobTemplateCallbackTest(BaseJobTestMixin, django.test.LiveServerTestCase):
job_template = jt job_template = jt
break break
self.assertTrue(job_template) 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) data = dict(host_config_key=job_template.host_config_key)
# Test a POST to start a new job. # Test a POST to start a new job.
@@ -1254,7 +1254,7 @@ class JobTemplateCallbackTest(BaseJobTestMixin, django.test.LiveServerTestCase):
job_template = jt job_template = jt
break break
self.assertTrue(job_template) 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) data = dict(host_config_key=job_template.host_config_key)
# Should get an error when multiple hosts match to the same IP. # 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 job_template = jt
break break
self.assertTrue(job_template) 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) data = dict(host_config_key=job_template.host_config_key)
# Test POST to start a new job when the template has no credential. # 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 job_template = jt
break break
self.assertTrue(job_template) 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) data = dict(host_config_key=job_template.host_config_key)
# Test POST to start a new job when the credential would require user # 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): class OrganizationsTest(BaseTest):
def collection(self): def collection(self):
return reverse('main:organization_list') return reverse('api:organization_list')
def setUp(self): def setUp(self):
super(OrganizationsTest, self).setUp() super(OrganizationsTest, self).setUp()
@@ -53,7 +53,7 @@ class OrganizationsTest(BaseTest):
self.organizations[1].admins.add(self.normal_django_user) self.organizations[1].admins.add(self.normal_django_user)
def test_get_organization_list(self): def test_get_organization_list(self):
url = reverse('main:organization_list') url = reverse('api:organization_list')
# no credentials == 401 # no credentials == 401
self.options(url, expect=401) self.options(url, expect=401)
@@ -280,7 +280,7 @@ class OrganizationsTest(BaseTest):
def test_post_item_subobjects_users(self): 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()) users = self.get(url, expect=200, auth=self.get_normal_credentials())
self.assertEqual(users['count'], 2) self.assertEqual(users['count'], 2)
self.post(url, dict(id=self.normal_django_user.pk), expect=204, auth=self.get_normal_credentials()) 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 # post a completely new user to verify we can add users to the subcollection directly
new_user = dict(username='NewUser9000') new_user = dict(username='NewUser9000')
which_org = self.normal_django_user.admin_of_organizations.all()[0] 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()) 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()) 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): 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()) admins = self.get(url, expect=200, auth=self.get_normal_credentials())
self.assertEqual(admins['count'], 2) self.assertEqual(admins['count'], 2)
self.post(url, dict(id=self.other_django_user.pk), expect=204, auth=self.get_normal_credentials()) 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()) self.delete(self.collection(), expect=405, auth=self.get_super_credentials())
def test_invalid_post_data(self): 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. # 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=None, auth=self.get_super_credentials())
self.post(url, expect=400, data=99, 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=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=True, auth=self.get_super_credentials())
self.post(url, expect=400, data=[1,2,3], 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=None, auth=self.get_super_credentials())
self.post(url, expect=400, data=99, 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()) 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 # tests for users, projects, and teams
def collection(self): def collection(self):
return reverse('main:project_list') return reverse('api:project_list')
def setUp(self): def setUp(self):
super(ProjectsTest, self).setUp() super(ProjectsTest, self).setUp()
@@ -148,7 +148,7 @@ class ProjectsTest(BaseTest):
def test_api_config(self): def test_api_config(self):
# superuser can read all config data. # 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()) response = self.get(url, expect=200, auth=self.get_super_credentials())
self.assertTrue('project_base_dir' in response) self.assertTrue('project_base_dir' in response)
self.assertEqual(response['project_base_dir'], settings.PROJECTS_ROOT) self.assertEqual(response['project_base_dir'], settings.PROJECTS_ROOT)
@@ -188,7 +188,7 @@ class ProjectsTest(BaseTest):
# PROJECTS - LISTING # PROJECTS - LISTING
# can get projects list # can get projects list
projects = reverse('main:project_list') projects = reverse('api:project_list')
# invalid auth # invalid auth
self.get(projects, expect=401) self.get(projects, expect=401)
self.get(projects, expect=401, auth=self.get_invalid_credentials()) self.get(projects, expect=401, auth=self.get_invalid_credentials())
@@ -217,7 +217,7 @@ class ProjectsTest(BaseTest):
auth=self.get_super_credentials()) auth=self.get_super_credentials())
# can edit project using same local path. # 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, project_data = self.get(project_detail, expect=200,
auth=self.get_super_credentials()) auth=self.get_super_credentials())
response = self.put(project_detail, project_data, expect=200, response = self.put(project_detail, project_data, expect=200,
@@ -235,7 +235,7 @@ class ProjectsTest(BaseTest):
# ===================================================================== # =====================================================================
# PROJECTS - ACCESS # 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_super_credentials())
self.get(project, expect=200, auth=self.get_normal_credentials()) self.get(project, expect=200, auth=self.get_normal_credentials())
self.get(project, expect=200, auth=self.get_other_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()) self.get(project, expect=404, auth=self.get_normal_credentials())
# can list playbooks for projects # 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()) got = self.get(proj_playbooks, expect=200, auth=self.get_super_credentials())
self.assertEqual(got, self.projects[2].playbooks) self.assertEqual(got, self.projects[2].playbooks)
# can list member organizations for projects # 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 # 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_normal_credentials())
got = self.get(proj_orgs, expect=200, auth=self.get_super_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.get(proj_orgs, expect=403, auth=self.get_other_credentials())
self.assertEquals(got['count'], 1) 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. # post to create new org associated with this project.
self.post(proj_orgs, data={'name': 'New Org'}, expect=201, auth=self.get_super_credentials()) self.post(proj_orgs, data={'name': 'New Org'}, expect=201, auth=self.get_super_credentials())
@@ -267,8 +267,8 @@ class ProjectsTest(BaseTest):
# ===================================================================== # =====================================================================
# TEAMS # TEAMS
all_teams = reverse('main:team_list') all_teams = reverse('api:team_list')
team1 = reverse('main:team_detail', args=(self.team1.pk,)) team1 = reverse('api:team_detail', args=(self.team1.pk,))
# can list teams # can list teams
got = self.get(all_teams, expect=200, auth=self.get_super_credentials()) got = self.get(all_teams, expect=200, auth=self.get_super_credentials())
@@ -277,7 +277,7 @@ class ProjectsTest(BaseTest):
# can get teams # can get teams
got = self.get(team1, expect=200, auth=self.get_super_credentials()) 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=200, auth=self.get_normal_credentials())
got = self.get(team1, expect=403, auth=self.get_other_credentials()) got = self.get(team1, expect=403, auth=self.get_other_credentials())
self.team1.users.add(User.objects.get(username='other')) self.team1.users.add(User.objects.get(username='other'))
@@ -303,7 +303,7 @@ class ProjectsTest(BaseTest):
url5 = posted1['url'] url5 = posted1['url']
new_team = Team.objects.create(name='newTeam4', organization=self.organizations[1]) 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 # can delete teams
self.delete(url, expect=401) self.delete(url, expect=401)
@@ -316,7 +316,7 @@ class ProjectsTest(BaseTest):
# ORGANIZATION TEAMS # ORGANIZATION TEAMS
# can list organization teams (filtered by user) -- this is an org admin function # 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) data1 = self.get(org_teams, expect=401)
data2 = self.get(org_teams, expect=403, auth=self.get_nobody_credentials()) data2 = self.get(org_teams, expect=403, auth=self.get_nobody_credentials())
data3 = self.get(org_teams, expect=403, auth=self.get_other_credentials()) data3 = self.get(org_teams, expect=403, auth=self.get_other_credentials())
@@ -346,7 +346,7 @@ class ProjectsTest(BaseTest):
# TEAM PROJECTS # TEAM PROJECTS
team = Team.objects.filter(active=True, organization__pk=self.organizations[1].pk)[0] 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] p1 = self.projects[0]
team.projects.add(p1) team.projects.add(p1)
@@ -363,7 +363,7 @@ class ProjectsTest(BaseTest):
# TEAMS USER MEMBERSHIP # TEAMS USER MEMBERSHIP
team = Team.objects.filter(active=True, organization__pk=self.organizations[1].pk)[0] 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(): for x in team.users.all():
team.users.remove(x) team.users.remove(x)
team.save() team.save()
@@ -377,7 +377,7 @@ class ProjectsTest(BaseTest):
self.get(team_users, expect=200, auth=self.get_super_credentials()) self.get(team_users, expect=200, auth=self.get_super_credentials())
# can add users to teams (but only users I can see) # 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']: 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=403, auth=self.get_nobody_credentials())
self.post(team_users, data=x, expect=204, auth=self.get_normal_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) # from a user, can see what teams they are on (related resource)
other = User.objects.get(username = 'other') 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)
self.get(url, expect=401, auth=self.get_invalid_credentials()) self.get(url, expect=401, auth=self.get_invalid_credentials())
self.get(url, expect=403, auth=self.get_nobody_credentials()) self.get(url, expect=403, auth=self.get_nobody_credentials())
@@ -413,7 +413,7 @@ class ProjectsTest(BaseTest):
# ===================================================================== # =====================================================================
# USER PROJECTS # 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 # from a user, can see what projects they can see based on team association
# though this resource doesn't do anything else # though this resource doesn't do anything else
@@ -427,8 +427,8 @@ class ProjectsTest(BaseTest):
# ===================================================================== # =====================================================================
# CREDENTIALS # CREDENTIALS
other_creds = reverse('main:user_credentials_list', args=(other.pk,)) other_creds = reverse('api:user_credentials_list', args=(other.pk,))
team_creds = reverse('main:team_credentials_list', args=(team.pk,)) team_creds = reverse('api:team_credentials_list', args=(team.pk,))
new_credentials = dict( new_credentials = dict(
name = 'credential', name = 'credential',
@@ -476,7 +476,7 @@ class ProjectsTest(BaseTest):
self.get(team_creds, expect=403, auth=self.get_nobody_credentials()) self.get(team_creds, expect=403, auth=self.get_nobody_credentials())
# Check /api/v1/credentials (GET) # Check /api/v1/credentials (GET)
url = reverse('main:credential_list') url = reverse('api:credential_list')
with self.current_user(self.super_django_user): with self.current_user(self.super_django_user):
self.options(url) self.options(url)
self.head(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_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_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) 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_creds1 = reverse('api:credential_detail', args=(cred_user.pk,))
edit_creds2 = reverse('main:credential_detail', args=(cred_team.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)
self.put(edit_creds1, data=d_cred_user, expect=401, auth=self.get_invalid_credentials()) 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()) self.put(edit_creds2, data=d_cred_team, expect=403, auth=self.get_other_credentials())
cred_put_t['disassociate'] = 1 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()) 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. # can remove credentials from a user (via disassociate) - this will delete the credential.
cred_put_u['disassociate'] = 1 cred_put_u['disassociate'] = 1
url = cred_put_u['url'] 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()) 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 # can delete a credential directly -- probably won't be used too often
@@ -560,13 +560,13 @@ class ProjectsTest(BaseTest):
permission_type=PERM_INVENTORY_DEPLOY 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()) posted = self.post(url, user_permission, expect=201, auth=self.get_super_credentials())
url2 = posted['url'] url2 = posted['url']
got = self.get(url2, expect=200, auth=self.get_other_credentials()) got = self.get(url2, expect=200, auth=self.get_other_credentials())
# cannot add permissions that apply to both team and user # 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['name'] = 'user permission 2'
user_permission['team'] = team.pk user_permission['team'] = team.pk
self.post(url, user_permission, expect=400, auth=self.get_super_credentials()) 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()) self.post(url, user_permission, expect=400, auth=self.get_super_credentials())
# can add permissions on a team # 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()) posted = self.post(url, team_permission, expect=201, auth=self.get_super_credentials())
url2 = posted['url'] url2 = posted['url']
# check we can get that permission back # check we can get that permission back
got = self.get(url2, expect=200, auth=self.get_other_credentials()) got = self.get(url2, expect=200, auth=self.get_other_credentials())
# cannot add permissions that apply to both team and user # 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['name'] += '2'
team_permission['user'] = user.pk team_permission['user'] = user.pk
self.post(url, team_permission, expect=400, auth=self.get_super_credentials()) self.post(url, team_permission, expect=400, auth=self.get_super_credentials())
# can list permissions on a user # 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_super_credentials())
got = self.get(url, expect=200, auth=self.get_other_credentials()) got = self.get(url, expect=200, auth=self.get_other_credentials())
got = self.get(url, expect=403, auth=self.get_nobody_credentials()) got = self.get(url, expect=403, auth=self.get_nobody_credentials())
# can list permissions on a team # 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_super_credentials())
got = self.get(url, expect=200, auth=self.get_other_credentials()) got = self.get(url, expect=200, auth=self.get_other_credentials())
got = self.get(url, expect=403, auth=self.get_nobody_credentials()) got = self.get(url, expect=403, auth=self.get_nobody_credentials())
@@ -1335,7 +1335,7 @@ class ProjectUpdatesTest(BaseTransactionTest):
scm_username='nobody', scm_username='nobody',
scm_password='ASK', 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): with self.current_user(self.super_django_user):
response = self.get(url, expect=200) response = self.get(url, expect=200)
self.assertTrue(response['can_update']) self.assertTrue(response['can_update'])
@@ -1359,7 +1359,7 @@ class ProjectUpdatesTest(BaseTransactionTest):
scm_key_data=TEST_SSH_KEY_DATA_LOCKED, scm_key_data=TEST_SSH_KEY_DATA_LOCKED,
scm_key_unlock='ASK', 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): with self.current_user(self.super_django_user):
response = self.get(url, expect=200) response = self.get(url, expect=200)
self.assertTrue(response['can_update']) self.assertTrue(response['can_update'])

View File

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

View File

@@ -1,170 +1,7 @@
# Copyright (c) 2013 AnsibleWorks, Inc. # Copyright (c) 2013 AnsibleWorks, Inc.
# All Rights Reserved. # 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=''): urlpatterns = patterns()
# 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)),
)

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

View File

@@ -10,7 +10,7 @@ handler500 = 'awx.main.views.handle_500'
urlpatterns = patterns('', urlpatterns = patterns('',
url(r'', include('awx.ui.urls', namespace='ui', app_name='ui')), 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: if 'django.contrib.admin' in settings.INSTALLED_APPS: