mirror of
https://github.com/ansible/awx.git
synced 2026-02-01 17:48:10 -03:30
Split out RBAC and can_user_* methods from models into access.py. Moved list/item permissions checks from the base views into RBAC. Added serializers/views/tests for jobs REST API.
This commit is contained in:
@@ -46,17 +46,6 @@ class BaseTestMixin(object):
|
||||
if os.path.exists(project_dir):
|
||||
shutil.rmtree(project_dir, True)
|
||||
|
||||
def make_user(self, username, password=None, super_user=False):
|
||||
user = None
|
||||
password = password or username
|
||||
if super_user:
|
||||
user = User.objects.create_superuser(username, "%s@example.com", password)
|
||||
else:
|
||||
user = User.objects.create_user(username, "%s@example.com", password)
|
||||
self.assertTrue(user.auth_token)
|
||||
self._user_passwords[user.username] = password
|
||||
return user
|
||||
|
||||
@contextlib.contextmanager
|
||||
def current_user(self, user_or_username, password=None):
|
||||
try:
|
||||
@@ -71,6 +60,17 @@ class BaseTestMixin(object):
|
||||
finally:
|
||||
self._current_auth = previous_auth
|
||||
|
||||
def make_user(self, username, password=None, super_user=False):
|
||||
user = None
|
||||
password = password or username
|
||||
if super_user:
|
||||
user = User.objects.create_superuser(username, "%s@example.com", password)
|
||||
else:
|
||||
user = User.objects.create_user(username, "%s@example.com", password)
|
||||
self.assertTrue(user.auth_token)
|
||||
self._user_passwords[user.username] = password
|
||||
return user
|
||||
|
||||
def make_organizations(self, created_by, count=1):
|
||||
results = []
|
||||
for x in range(0, count):
|
||||
@@ -80,35 +80,51 @@ class BaseTestMixin(object):
|
||||
))
|
||||
return results
|
||||
|
||||
def make_projects(self, created_by, count=1, playbook_content=''):
|
||||
results = []
|
||||
|
||||
def make_project(self, name, description='', created_by=None,
|
||||
playbook_content=''):
|
||||
if not os.path.exists(settings.PROJECTS_ROOT):
|
||||
os.makedirs(settings.PROJECTS_ROOT)
|
||||
# Create temp project directory.
|
||||
project_dir = tempfile.mkdtemp(dir=settings.PROJECTS_ROOT)
|
||||
self._temp_project_dirs.append(project_dir)
|
||||
# Create temp playbook in project (if playbook content is given).
|
||||
if playbook_content:
|
||||
handle, playbook_path = tempfile.mkstemp(suffix='.yml',
|
||||
dir=project_dir)
|
||||
test_playbook_file = os.fdopen(handle, 'w')
|
||||
test_playbook_file.write(playbook_content)
|
||||
test_playbook_file.close()
|
||||
return Project.objects.create(
|
||||
name=name, description=description, local_path=project_dir,
|
||||
created_by=created_by,
|
||||
#scm_type='git', default_playbook='foo.yml',
|
||||
)
|
||||
|
||||
def make_projects(self, created_by, count=1, playbook_content=''):
|
||||
results = []
|
||||
for x in range(0, count):
|
||||
self.object_ctr = self.object_ctr + 1
|
||||
# Create temp project directory.
|
||||
|
||||
project_dir = tempfile.mkdtemp(dir=settings.PROJECTS_ROOT)
|
||||
self._temp_project_dirs.append(project_dir)
|
||||
# Create temp playbook in project (if playbook content is given).
|
||||
if playbook_content:
|
||||
handle, playbook_path = tempfile.mkstemp(suffix='.yml',
|
||||
dir=project_dir)
|
||||
test_playbook_file = os.fdopen(handle, 'w')
|
||||
test_playbook_file.write(playbook_content)
|
||||
test_playbook_file.close()
|
||||
results.append(Project.objects.create(
|
||||
name="proj%s-%s" % (x, self.object_ctr), description="proj%s" % x,
|
||||
#scm_type='git', default_playbook='foo.yml',
|
||||
local_path=project_dir, created_by=created_by
|
||||
results.append(self.make_project(
|
||||
name="proj%s-%s" % (x, self.object_ctr),
|
||||
description="proj%s" % x,
|
||||
created_by=created_by,
|
||||
playbook_content=playbook_content,
|
||||
))
|
||||
return results
|
||||
|
||||
def check_pagination_and_size(self, data, desired_count, previous=None, next=None):
|
||||
self.assertEquals(data['previous'], previous)
|
||||
self.assertEquals(data['next'], next)
|
||||
self.assertTrue('results' in data)
|
||||
self.assertEqual(data['count'], desired_count)
|
||||
self.assertEqual(data['previous'], previous)
|
||||
self.assertEqual(data['next'], next)
|
||||
|
||||
def check_list_ids(self, data, queryset, check_order=False):
|
||||
data_ids = [x['id'] for x in data['results']]
|
||||
qs_ids = queryset.values_list('pk', flat=True)
|
||||
if check_order:
|
||||
self.assertEqual(data_ids, qs_ids)
|
||||
else:
|
||||
self.assertEqual(set(data_ids), set(qs_ids))
|
||||
|
||||
def setup_users(self, just_super_user=False):
|
||||
# Create a user.
|
||||
@@ -191,7 +207,7 @@ class BaseTestMixin(object):
|
||||
# TODO: this test helper function doesn't support pagination
|
||||
data = self.get(collection_url, expect=200, auth=auth)
|
||||
return [item['url'] for item in data['results']]
|
||||
|
||||
|
||||
class BaseTest(BaseTestMixin, django.test.TestCase):
|
||||
'''
|
||||
Base class for unit tests.
|
||||
|
||||
@@ -24,7 +24,7 @@ from lib.main.tests.base import BaseTest
|
||||
|
||||
__all__ = ['JobTemplateTest', 'JobTest']
|
||||
|
||||
TEST_PLAYBOOK = '''- hosts: mygroup
|
||||
TEST_PLAYBOOK = '''- hosts: all
|
||||
gather_facts: false
|
||||
tasks:
|
||||
- name: woohoo
|
||||
@@ -34,106 +34,360 @@ TEST_PLAYBOOK = '''- hosts: mygroup
|
||||
class BaseJobTest(BaseTest):
|
||||
''''''
|
||||
|
||||
def get_other2_credentials(self):
|
||||
return ('other2', 'other2')
|
||||
def _create_inventory(self, name, organization, created_by,
|
||||
groups_hosts_dict):
|
||||
'''Helper method for creating inventory with groups and hosts.'''
|
||||
inventory = organization.inventories.create(
|
||||
name=name,
|
||||
created_by=created_by,
|
||||
)
|
||||
for group_name, host_names in groups_hosts_dict.items():
|
||||
group = inventory.groups.create(
|
||||
name=group_name,
|
||||
created_by=created_by,
|
||||
)
|
||||
for host_name in host_names:
|
||||
host = inventory.hosts.create(
|
||||
name=host_name,
|
||||
created_by=created_by,
|
||||
)
|
||||
group.hosts.add(host)
|
||||
return inventory
|
||||
|
||||
def get_nobody_credentials(self):
|
||||
return ('nobody', 'nobody')
|
||||
def populate(self):
|
||||
# Here's a little story about the Ansible Bread Company, or ABC. They
|
||||
# make machines that make bread - bakers, slicers, and packagers - and
|
||||
# these machines are each controlled by a Linux boxes, which is in turn
|
||||
# managed by Ansible Commander.
|
||||
|
||||
# Sue is the super user. You don't mess with Sue or you're toast. Ha.
|
||||
self.user_sue = self.make_user('sue', super_user=True)
|
||||
|
||||
# There are three organizations in ABC using Ansible, since it's the
|
||||
# best thing for dev ops automation since, well, sliced bread.
|
||||
|
||||
# Engineering - They design and build the machines.
|
||||
self.org_eng = Organization.objects.create(
|
||||
name='engineering',
|
||||
created_by=self.user_sue,
|
||||
)
|
||||
# Support - They fix it when it's not working.
|
||||
self.org_sup = Organization.objects.create(
|
||||
name='support',
|
||||
created_by=self.user_sue,
|
||||
)
|
||||
# Operations - They implement the production lines using the machines.
|
||||
self.org_ops = Organization.objects.create(
|
||||
name='operations',
|
||||
created_by=self.user_sue,
|
||||
)
|
||||
|
||||
# Alex is Sue's IT assistant who can also administer all of the
|
||||
# organizations.
|
||||
self.user_alex = self.make_user('alex')
|
||||
self.org_eng.admins.add(self.user_alex)
|
||||
self.org_sup.admins.add(self.user_alex)
|
||||
self.org_ops.admins.add(self.user_alex)
|
||||
|
||||
# Bob is the head of engineering. He's an admin for engineering, but
|
||||
# also a user within the operations organization (so he can see the
|
||||
# results if things go wrong in production).
|
||||
self.user_bob = self.make_user('bob')
|
||||
self.org_eng.admins.add(self.user_bob)
|
||||
self.org_ops.users.add(self.user_bob)
|
||||
|
||||
# Chuck is the lead engineer. He has full reign over engineering, but
|
||||
# no other organizations.
|
||||
self.user_chuck = self.make_user('chuck')
|
||||
self.org_eng.admins.add(self.user_chuck)
|
||||
|
||||
# Doug is the other engineer working under Chuck. He can write
|
||||
# playbooks and check them, but Chuck doesn't quite think he's ready to
|
||||
# run them yet. Poor Doug.
|
||||
self.user_doug = self.make_user('doug')
|
||||
self.org_eng.users.add(self.user_doug)
|
||||
|
||||
# Eve is the head of support. She can also see what goes on in
|
||||
# operations to help them troubleshoot problems.
|
||||
self.user_eve = self.make_user('eve')
|
||||
self.org_sup.admins.add(self.user_eve)
|
||||
self.org_ops.users.add(self.user_eve)
|
||||
|
||||
# Frank is the other support guy.
|
||||
self.user_frank = self.make_user('frank')
|
||||
self.org_sup.users.add(self.user_frank)
|
||||
|
||||
# Greg is the head of operations.
|
||||
self.user_greg = self.make_user('greg')
|
||||
self.org_ops.admins.add(self.user_greg)
|
||||
|
||||
# Holly is an operations engineer.
|
||||
self.user_holly = self.make_user('holly')
|
||||
self.org_ops.users.add(self.user_holly)
|
||||
|
||||
# Iris is another operations engineer.
|
||||
self.user_iris = self.make_user('iris')
|
||||
self.org_ops.users.add(self.user_iris)
|
||||
|
||||
# Jim is the intern. He can login, but can't do anything quite yet
|
||||
# except make everyone else fresh coffee.
|
||||
self.user_jim = self.make_user('jim')
|
||||
|
||||
# There are three main projects, one each for the development, test and
|
||||
# production branches of the playbook repository. All three orgs can
|
||||
# use the production branch, support can use the production and testing
|
||||
# branches, and operations can only use the production branch.
|
||||
self.proj_dev = self.make_project('dev', 'development branch',
|
||||
self.user_sue, TEST_PLAYBOOK)
|
||||
self.org_eng.projects.add(self.proj_dev)
|
||||
self.proj_test = self.make_project('test', 'testing branch',
|
||||
self.user_sue, TEST_PLAYBOOK)
|
||||
self.org_eng.projects.add(self.proj_test)
|
||||
self.org_sup.projects.add(self.proj_test)
|
||||
self.proj_prod = self.make_project('prod', 'production branch',
|
||||
self.user_sue, TEST_PLAYBOOK)
|
||||
self.org_eng.projects.add(self.proj_prod)
|
||||
self.org_sup.projects.add(self.proj_prod)
|
||||
self.org_ops.projects.add(self.proj_prod)
|
||||
|
||||
# Operations also has 2 additional projects specific to the east/west
|
||||
# production environments.
|
||||
self.proj_prod_east = self.make_project('prod-east',
|
||||
'east production branch',
|
||||
self.user_sue, TEST_PLAYBOOK)
|
||||
self.org_ops.projects.add(self.proj_prod_east)
|
||||
self.proj_prod_west = self.make_project('prod-west',
|
||||
'west production branch',
|
||||
self.user_sue, TEST_PLAYBOOK)
|
||||
self.org_ops.projects.add(self.proj_prod_west)
|
||||
|
||||
# The engineering organization has a set of servers to use for
|
||||
# development and testing (2 bakers, 1 slicer, 1 packager).
|
||||
self.inv_eng = self._create_inventory(
|
||||
name='engineering environment',
|
||||
organization=self.org_eng,
|
||||
created_by=self.user_sue,
|
||||
groups_hosts_dict={
|
||||
'bakers': ['eng-baker1', 'eng-baker2'],
|
||||
'slicers': ['eng-slicer1'],
|
||||
'packagers': ['eng-packager1'],
|
||||
},
|
||||
)
|
||||
|
||||
# The support organization has a set of servers to use for
|
||||
# testing and reproducing problems from operations (1 baker, 1 slicer,
|
||||
# 1 packager).
|
||||
self.inv_sup = self._create_inventory(
|
||||
name='support environment',
|
||||
organization=self.org_sup,
|
||||
created_by=self.user_sue,
|
||||
groups_hosts_dict={
|
||||
'bakers': ['sup-baker1'],
|
||||
'slicers': ['sup-slicer1'],
|
||||
'packagers': ['sup-packager1'],
|
||||
},
|
||||
)
|
||||
|
||||
# The operations organization manages multiple sets of servers for the
|
||||
# east and west production facilities.
|
||||
self.inv_ops_east = self._create_inventory(
|
||||
name='east production environment',
|
||||
organization=self.org_ops,
|
||||
created_by=self.user_sue,
|
||||
groups_hosts_dict={
|
||||
'bakers': ['east-baker%d' % n for n in range(1, 4)],
|
||||
'slicers': ['east-slicer%d' % n for n in range(1, 3)],
|
||||
'packagers': ['east-packager%d' % n for n in range(1, 3)],
|
||||
},
|
||||
)
|
||||
self.inv_ops_west = self._create_inventory(
|
||||
name='west production environment',
|
||||
organization=self.org_ops,
|
||||
created_by=self.user_sue,
|
||||
groups_hosts_dict={
|
||||
'bakers': ['west-baker%d' % n for n in range(1, 6)],
|
||||
'slicers': ['west-slicer%d' % n for n in range(1, 4)],
|
||||
'packagers': ['west-packager%d' % n for n in range(1, 3)],
|
||||
},
|
||||
)
|
||||
|
||||
# Operations is divided into teams to work on the east/west servers.
|
||||
# Greg and Holly work on east, Greg and iris work on west.
|
||||
self.team_ops_east = self.org_ops.teams.create(
|
||||
name='easterners',
|
||||
created_by=self.user_sue,
|
||||
)
|
||||
self.team_ops_east.projects.add(self.proj_prod)
|
||||
self.team_ops_east.projects.add(self.proj_prod_east)
|
||||
self.team_ops_east.users.add(self.user_greg)
|
||||
self.team_ops_east.users.add(self.user_holly)
|
||||
self.team_ops_west = self.org_ops.teams.create(
|
||||
name='westerners',
|
||||
created_by=self.user_sue,
|
||||
)
|
||||
self.team_ops_west.projects.add(self.proj_prod)
|
||||
self.team_ops_west.projects.add(self.proj_prod_west)
|
||||
self.team_ops_west.users.add(self.user_greg)
|
||||
self.team_ops_west.users.add(self.user_iris)
|
||||
|
||||
# Each user has his/her own set of credentials.
|
||||
from lib.main.tests.tasks import (TEST_SSH_KEY_DATA,
|
||||
TEST_SSH_KEY_DATA_LOCKED,
|
||||
TEST_SSH_KEY_DATA_UNLOCK)
|
||||
self.cred_bob = self.user_bob.credentials.create(
|
||||
ssh_username='bob',
|
||||
ssh_password='ASK',
|
||||
created_by=self.user_sue,
|
||||
)
|
||||
self.cred_chuck = self.user_chuck.credentials.create(
|
||||
ssh_username='chuck',
|
||||
ssh_key_data=TEST_SSH_KEY_DATA,
|
||||
created_by=self.user_sue,
|
||||
)
|
||||
self.cred_doug = self.user_doug.credentials.create(
|
||||
ssh_username='doug',
|
||||
ssh_password='doug doesn\'t mind his password being saved. this '
|
||||
'is why we dont\'t let doug actually run jobs.',
|
||||
created_by=self.user_sue,
|
||||
)
|
||||
self.cred_eve = self.user_eve.credentials.create(
|
||||
ssh_username='eve',
|
||||
ssh_password='ASK',
|
||||
created_by=self.user_sue,
|
||||
)
|
||||
self.cred_frank = self.user_frank.credentials.create(
|
||||
ssh_username='frank',
|
||||
ssh_password='fr@nk the t@nk',
|
||||
created_by=self.user_sue,
|
||||
)
|
||||
self.cred_greg = self.user_greg.credentials.create(
|
||||
ssh_username='greg',
|
||||
ssh_key_data=TEST_SSH_KEY_DATA_LOCKED,
|
||||
ssh_key_unlock='ASK',
|
||||
created_by=self.user_sue,
|
||||
)
|
||||
self.cred_holly = self.user_holly.credentials.create(
|
||||
ssh_username='holly',
|
||||
ssh_password='holly rocks',
|
||||
created_by=self.user_sue,
|
||||
)
|
||||
self.cred_iris = self.user_iris.credentials.create(
|
||||
ssh_username='iris',
|
||||
ssh_password='',
|
||||
created_by=self.user_sue,
|
||||
)
|
||||
|
||||
# Each operations team also has shared credentials they can use.
|
||||
self.cred_ops_east = self.team_ops_east.credentials.create(
|
||||
ssh_username='east',
|
||||
ssh_key_data=TEST_SSH_KEY_DATA_LOCKED,
|
||||
ssh_key_unlock=TEST_SSH_KEY_DATA_UNLOCK,
|
||||
created_by = self.user_sue,
|
||||
)
|
||||
self.cred_ops_west = self.team_ops_west.credentials.create(
|
||||
ssh_username='west',
|
||||
ssh_password='Heading270',
|
||||
created_by = self.user_sue,
|
||||
)
|
||||
|
||||
# FIXME: Define explicit permissions for tests.
|
||||
# other django user is on the project team and can deploy
|
||||
#self.permission1 = Permission.objects.create(
|
||||
# inventory = self.inventory,
|
||||
# project = self.project,
|
||||
# team = self.team,
|
||||
# permission_type = PERM_INVENTORY_DEPLOY,
|
||||
# created_by = self.normal_django_user
|
||||
#)
|
||||
# individual permission granted to other2 user, can run check mode
|
||||
#self.permission2 = Permission.objects.create(
|
||||
# inventory = self.inventory,
|
||||
# project = self.project,
|
||||
# user = self.other2_django_user,
|
||||
# permission_type = PERM_INVENTORY_CHECK,
|
||||
# created_by = self.normal_django_user
|
||||
#)
|
||||
|
||||
# Engineering has job templates to check/run the dev project onto
|
||||
# their own inventory.
|
||||
self.jt_eng_check = JobTemplate.objects.create(
|
||||
name='eng-dev-check',
|
||||
job_type='check',
|
||||
inventory= self.inv_eng,
|
||||
project=self.proj_dev,
|
||||
playbook=self.proj_dev.available_playbooks[0],
|
||||
created_by=self.user_sue,
|
||||
)
|
||||
self.jt_eng_run = JobTemplate.objects.create(
|
||||
name='eng-dev-run',
|
||||
job_type='run',
|
||||
inventory= self.inv_eng,
|
||||
project=self.proj_dev,
|
||||
playbook=self.proj_dev.available_playbooks[0],
|
||||
created_by=self.user_sue,
|
||||
)
|
||||
|
||||
# Support has job templates to check/run the test project onto
|
||||
# their own inventory.
|
||||
self.jt_sup_check = JobTemplate.objects.create(
|
||||
name='sup-test-check',
|
||||
job_type='check',
|
||||
inventory= self.inv_sup,
|
||||
project=self.proj_test,
|
||||
playbook=self.proj_test.available_playbooks[0],
|
||||
created_by=self.user_sue,
|
||||
)
|
||||
self.jt_sup_run = JobTemplate.objects.create(
|
||||
name='sup-test-run',
|
||||
job_type='run',
|
||||
inventory= self.inv_sup,
|
||||
project=self.proj_test,
|
||||
playbook=self.proj_test.available_playbooks[0],
|
||||
created_by=self.user_sue,
|
||||
)
|
||||
|
||||
# Operations has job templates to check/run the prod project onto
|
||||
# both east and west inventories, by default using the team credential.
|
||||
self.jt_ops_east_check = JobTemplate.objects.create(
|
||||
name='ops-east-prod-check',
|
||||
job_type='check',
|
||||
inventory= self.inv_ops_east,
|
||||
project=self.proj_prod,
|
||||
playbook=self.proj_prod.available_playbooks[0],
|
||||
credential=self.cred_ops_east,
|
||||
created_by=self.user_sue,
|
||||
)
|
||||
self.jt_ops_east_run = JobTemplate.objects.create(
|
||||
name='ops-east-prod-run',
|
||||
job_type='run',
|
||||
inventory= self.inv_ops_east,
|
||||
project=self.proj_prod,
|
||||
playbook=self.proj_prod.available_playbooks[0],
|
||||
credential=self.cred_ops_east,
|
||||
created_by=self.user_sue,
|
||||
)
|
||||
self.jt_ops_west_check = JobTemplate.objects.create(
|
||||
name='ops-west-prod-check',
|
||||
job_type='check',
|
||||
inventory= self.inv_ops_west,
|
||||
project=self.proj_prod,
|
||||
playbook=self.proj_prod.available_playbooks[0],
|
||||
credential=self.cred_ops_west,
|
||||
created_by=self.user_sue,
|
||||
)
|
||||
self.jt_ops_west_run = JobTemplate.objects.create(
|
||||
name='ops-west-prod-run',
|
||||
job_type='run',
|
||||
inventory= self.inv_ops_west,
|
||||
project=self.proj_prod,
|
||||
playbook=self.proj_prod.available_playbooks[0],
|
||||
credential=self.cred_ops_west,
|
||||
created_by=self.user_sue,
|
||||
)
|
||||
|
||||
def setUp(self):
|
||||
super(BaseJobTest, self).setUp()
|
||||
|
||||
# Users
|
||||
self.setup_users()
|
||||
self.other2_django_user = self.make_user('other2', 'other2')
|
||||
self.nobody_django_user = self.make_user('nobody', 'nobody')
|
||||
|
||||
# Organization
|
||||
self.organization = Organization.objects.create(
|
||||
name='engineering',
|
||||
created_by=self.normal_django_user,
|
||||
)
|
||||
self.organization.admins.add(self.normal_django_user)
|
||||
self.organization.users.add(self.normal_django_user)
|
||||
self.organization.users.add(self.other_django_user)
|
||||
self.organization.users.add(self.other2_django_user)
|
||||
|
||||
# Team
|
||||
self.team = self.organization.teams.create(
|
||||
name='Tigger',
|
||||
created_by=self.normal_django_user,
|
||||
)
|
||||
self.team.users.add(self.other_django_user)
|
||||
self.team.users.add(self.other2_django_user)
|
||||
|
||||
# Project
|
||||
self.project = self.make_projects(self.normal_django_user, 1,
|
||||
playbook_content=TEST_PLAYBOOK)[0]
|
||||
self.organization.projects.add(self.project)
|
||||
|
||||
# Inventory
|
||||
self.inventory = self.organization.inventories.create(
|
||||
name = 'prod',
|
||||
created_by = self.normal_django_user,
|
||||
)
|
||||
self.group_a = self.inventory.groups.create(
|
||||
name = 'group1',
|
||||
created_by = self.normal_django_user
|
||||
)
|
||||
self.host_a = self.inventory.hosts.create(
|
||||
name = '127.0.0.1',
|
||||
created_by = self.normal_django_user
|
||||
)
|
||||
self.host_b = self.inventory.hosts.create(
|
||||
name = '127.0.0.2',
|
||||
created_by = self.normal_django_user
|
||||
)
|
||||
self.group_a.hosts.add(self.host_a)
|
||||
self.group_a.hosts.add(self.host_b)
|
||||
|
||||
# Credentials
|
||||
self.user_credential = self.other_django_user.credentials.create(
|
||||
ssh_key_data = 'xxx',
|
||||
created_by = self.normal_django_user,
|
||||
)
|
||||
self.team_credential = self.team.credentials.create(
|
||||
ssh_key_data = 'xxx',
|
||||
created_by = self.normal_django_user,
|
||||
)
|
||||
|
||||
# other django user is on the project team and can deploy
|
||||
self.permission1 = Permission.objects.create(
|
||||
inventory = self.inventory,
|
||||
project = self.project,
|
||||
team = self.team,
|
||||
permission_type = PERM_INVENTORY_DEPLOY,
|
||||
created_by = self.normal_django_user
|
||||
)
|
||||
# individual permission granted to other2 user, can run check mode
|
||||
self.permission2 = Permission.objects.create(
|
||||
inventory = self.inventory,
|
||||
project = self.project,
|
||||
user = self.other2_django_user,
|
||||
permission_type = PERM_INVENTORY_CHECK,
|
||||
created_by = self.normal_django_user
|
||||
)
|
||||
|
||||
self.job_template1 = JobTemplate.objects.create(
|
||||
name = 'job-run',
|
||||
job_type = 'run',
|
||||
inventory = self.inventory,
|
||||
credential = self.user_credential,
|
||||
project = self.project,
|
||||
created_by = self.normal_django_user,
|
||||
)
|
||||
self.job_template2 = JobTemplate.objects.create(
|
||||
name = 'job-check',
|
||||
job_type = 'check',
|
||||
inventory = self.inventory,
|
||||
credential = self.team_credential,
|
||||
project = self.project,
|
||||
created_by = self.normal_django_user,
|
||||
)
|
||||
self.populate()
|
||||
|
||||
|
||||
class JobTemplateTest(BaseJobTest):
|
||||
@@ -141,16 +395,58 @@ class JobTemplateTest(BaseJobTest):
|
||||
def setUp(self):
|
||||
super(JobTemplateTest, self).setUp()
|
||||
|
||||
def test_job_template_list(self):
|
||||
url = reverse('main:job_templates_list')
|
||||
|
||||
response = self.get(url, expect=401)
|
||||
with self.current_user(self.normal_django_user):
|
||||
response = self.get(url, expect=200)
|
||||
self.assertTrue(response['count'], JobTemplate.objects.count())
|
||||
def test_get_job_template_list(self):
|
||||
url = reverse('main:job_template_list')
|
||||
|
||||
# FIXME: Test that user can only see job templates from own organization.
|
||||
# no credentials == 401
|
||||
self.options(url, expect=401)
|
||||
self.head(url, expect=401)
|
||||
self.get(url, expect=401)
|
||||
|
||||
# wrong credentials == 401
|
||||
with self.current_user('invalid', 'password'):
|
||||
self.options(url, expect=401)
|
||||
self.head(url, expect=401)
|
||||
self.get(url, expect=401)
|
||||
|
||||
# sue's credentials (superuser) == 200, full list
|
||||
with self.current_user(self.user_sue):
|
||||
self.options(url)
|
||||
self.head(url)
|
||||
response = self.get(url)
|
||||
qs = JobTemplate.objects.all()
|
||||
self.check_pagination_and_size(response, qs.count())
|
||||
self.check_list_ids(response, qs)
|
||||
|
||||
# FIXME: Check individual job template result.
|
||||
|
||||
# alex's credentials (admin of all orgs) == 200, full list
|
||||
with self.current_user(self.user_alex):
|
||||
self.options(url)
|
||||
self.head(url)
|
||||
response = self.get(url)
|
||||
qs = JobTemplate.objects.all()
|
||||
self.check_pagination_and_size(response, qs.count())
|
||||
self.check_list_ids(response, qs)
|
||||
|
||||
# bob's credentials (admin of eng, user of ops) == 200, all from
|
||||
# engineering and operations.
|
||||
with self.current_user(self.user_bob):
|
||||
self.options(url)
|
||||
self.head(url)
|
||||
response = self.get(url)
|
||||
qs = JobTemplate.objects.filter(
|
||||
inventory__organization__in=[self.org_eng, self.org_ops],
|
||||
)
|
||||
#self.check_pagination_and_size(response, qs.count())
|
||||
#self.check_list_ids(response, qs)
|
||||
|
||||
|
||||
def test_post_job_template_list(self):
|
||||
url = reverse('main:job_template_list')
|
||||
|
||||
return # FIXME
|
||||
|
||||
# org admin can add job template
|
||||
data = dict(
|
||||
name = 'job-foo',
|
||||
@@ -158,10 +454,11 @@ class JobTemplateTest(BaseJobTest):
|
||||
inventory = self.inventory.pk,
|
||||
project = self.project.pk,
|
||||
job_type = PERM_INVENTORY_DEPLOY,
|
||||
playbook = self.project.available_playbooks[0],
|
||||
)
|
||||
with self.current_user(self.normal_django_user):
|
||||
response = self.post(url, data, expect=201)
|
||||
detail_url = reverse('main:job_templates_detail',
|
||||
detail_url = reverse('main:job_template_detail',
|
||||
args=(response['id'],))
|
||||
self.assertEquals(response['url'], detail_url)
|
||||
|
||||
@@ -192,31 +489,62 @@ class JobTemplateTest(BaseJobTest):
|
||||
data['job_type'] = PERM_INVENTORY_DEPLOY
|
||||
response = self.post(url, data, expect=403)
|
||||
|
||||
def test_job_template_detail(self):
|
||||
def test_get_job_template_detail(self):
|
||||
|
||||
return # FIXME
|
||||
|
||||
url = reverse('main:job_template_detail', args=(self.job_template1.pk,))
|
||||
|
||||
# verify we can also get the job template record
|
||||
got = self.get(url, expect=200, auth=self.get_other2_credentials())
|
||||
self.failUnlessEqual(got['url'], '/api/v1/job_templates/6/')
|
||||
with self.current_user(self.other2_django_user):
|
||||
self.options(url)
|
||||
self.head(url)
|
||||
response = self.get(url)
|
||||
self.assertEqual(response['url'], url)
|
||||
|
||||
# TODO: add more tests that show
|
||||
# the method used to START a JobTemplate follow the exact same permissions as those to create it ...
|
||||
# and that jobs come back nicely serialized with related resources and so on ...
|
||||
# that we can drill all the way down and can get at host failure lists, etc ...
|
||||
|
||||
def test_put_job_template_detail(self):
|
||||
pass
|
||||
|
||||
def test_get_job_template_job_list(self):
|
||||
pass
|
||||
|
||||
|
||||
def test_post_job_template_job_list(self):
|
||||
pass
|
||||
|
||||
class JobTest(BaseJobTest):
|
||||
|
||||
def setUp(self):
|
||||
super(JobTest, self).setUp()
|
||||
|
||||
def test_mainline(self):
|
||||
def test_get_job_list(self):
|
||||
pass
|
||||
|
||||
def test_post_job_list(self):
|
||||
pass
|
||||
|
||||
def test_get_job_detail(self):
|
||||
pass
|
||||
|
||||
def test_put_job_detail(self):
|
||||
pass
|
||||
|
||||
def test_post_job_detail(self):
|
||||
pass
|
||||
|
||||
def test_get_job_host_list(self):
|
||||
pass
|
||||
|
||||
def test_get_job_job_event_list(self):
|
||||
pass
|
||||
|
||||
def _test_mainline(self):
|
||||
url = reverse('main:job_list')
|
||||
|
||||
return # FIXME
|
||||
|
||||
# job templates
|
||||
data = self.get('/api/v1/job_templates/', expect=401)
|
||||
data = self.get('/api/v1/job_templates/', expect=200, auth=self.get_normal_credentials())
|
||||
|
||||
@@ -82,22 +82,30 @@ class OrganizationsTest(BaseTest):
|
||||
with self.current_user(self.super_django_user):
|
||||
self.options(url, expect=200)
|
||||
self.head(url, expect=200)
|
||||
data = self.get(url, expect=200)
|
||||
self.check_pagination_and_size(data, 10, previous=None, next=None)
|
||||
[self.assertTrue(key in data['results'][0]) for key in ['name', 'description', 'url', 'creation_date', 'id' ]]
|
||||
response = self.get(url, expect=200)
|
||||
self.check_pagination_and_size(response, 10, previous=None, next=None)
|
||||
self.assertEqual(len(response['results']),
|
||||
Organization.objects.count())
|
||||
for field in ['id', 'url', 'name', 'description', 'creation_date']:
|
||||
self.assertTrue(field in response['results'][0],
|
||||
'field %s not in result' % field)
|
||||
|
||||
# check that the related URL functionality works
|
||||
related = data['results'][0]['related']
|
||||
related = response['results'][0]['related']
|
||||
for x in [ 'audit_trail', 'projects', 'users', 'admins', 'tags' ]:
|
||||
self.assertTrue(x in related and related[x].endswith("/%s/" % x), "looking for %s in related" % x)
|
||||
|
||||
# normal credentials == 200, get only organizations that I am actually added to (there are 2)
|
||||
data = self.get(self.collection(), expect=200, auth=self.get_normal_credentials())
|
||||
self.check_pagination_and_size(data, 2, previous=None, next=None)
|
||||
# normal credentials == 200, get only organizations of which user is a member
|
||||
with self.current_user(self.normal_django_user):
|
||||
self.options(url, expect=200)
|
||||
self.head(url, expect=200)
|
||||
response = self.get(url, expect=200)
|
||||
self.check_pagination_and_size(response, 2, previous=None, next=None)
|
||||
|
||||
# no admin rights? get empty list
|
||||
data = self.get(self.collection(), expect=200, auth=self.get_other_credentials())
|
||||
self.check_pagination_and_size(data, 0, previous=None, next=None)
|
||||
with self.current_user(self.other_django_user):
|
||||
response = self.get(url, expect=200)
|
||||
self.check_pagination_and_size(response, 0, previous=None, next=None)
|
||||
|
||||
def test_get_item(self):
|
||||
|
||||
|
||||
Reference in New Issue
Block a user