Merge pull request #3679 from AlanCoding/3677

Fixes for manual groups/projects
This commit is contained in:
Alan Rominger 2016-11-22 11:46:34 -05:00 committed by GitHub
commit 69f1e2d24c
5 changed files with 26 additions and 9 deletions

View File

@ -2833,6 +2833,8 @@ class ScheduleSerializer(BaseSerializer):
def validate_unified_job_template(self, value):
if type(value) == InventorySource and value.source not in SCHEDULEABLE_PROVIDERS:
raise serializers.ValidationError(_('Inventory Source must be a cloud resource.'))
elif type(value) == Project and value.scm_type == '':
raise serializers.ValidationError(_('Manual Project can not have a schedule set.'))
return value
# We reject rrules if:

View File

@ -305,16 +305,21 @@ class BaseAccess(object):
if display_method not in method_list:
continue
# Validation consistency checks
# Actions not possible for reason unrelated to RBAC
# Cannot copy with validation errors, or update a manual group/project
if display_method == 'copy' and isinstance(obj, JobTemplate):
validation_errors, resources_needed_to_start = obj.resource_validation_data()
if validation_errors:
user_capabilities[display_method] = False
continue
elif display_method == 'start' and isinstance(obj, Group):
elif display_method in ['start', 'schedule'] and isinstance(obj, Group):
if obj.inventory_source and not obj.inventory_source._can_update():
user_capabilities[display_method] = False
continue
elif display_method in ['start', 'schedule'] and isinstance(obj, (Project)):
if obj.scm_type == '':
user_capabilities[display_method] = False
continue
# Grab the answer from the cache, if available
if hasattr(obj, 'capabilities_cache') and display_method in obj.capabilities_cache:
@ -341,10 +346,6 @@ class BaseAccess(object):
elif display_method == 'copy' and isinstance(obj, (Group, Host)):
user_capabilities['copy'] = user_capabilities['edit']
continue
elif display_method == 'start' and isinstance(obj, (Project)) and obj.scm_type == '':
# Special case to return False for a manual project
user_capabilities['start'] = False
continue
# Preprocessing before the access method is called
data = {}

View File

@ -320,6 +320,7 @@ def test_prefetch_jt_copy_capability(job_template, project, inventory, machine_c
def test_manual_projects_no_update(project, get, admin_user):
response = get(reverse('api:project_detail', args=[project.pk]), admin_user, expect=200)
assert not response.data['summary_fields']['user_capabilities']['start']
assert not response.data['summary_fields']['user_capabilities']['schedule']
@pytest.mark.django_db
@ -333,13 +334,15 @@ def test_group_update_capabilities_possible(group, inventory_source, admin_user)
@pytest.mark.django_db
def test_group_update_capabilities_impossible(group, inventory_source, admin_user):
"Manual groups can not be updated or scheduled"
inventory_source.source = ""
inventory_source.save()
group.inventory_source = inventory_source
group.save()
capabilities = get_user_capabilities(admin_user, group, method_list=['start'])
capabilities = get_user_capabilities(admin_user, group, method_list=['edit', 'start', 'schedule'])
assert not capabilities['start']
assert not capabilities['schedule']
@pytest.mark.django_db

View File

@ -136,3 +136,13 @@ def test_patch_project_null_organization(patch, organization, project, admin):
@pytest.mark.django_db()
def test_patch_project_null_organization_xfail(patch, project, org_admin):
patch(reverse('api:project_detail', args=(project.id,)), { 'name': 't', 'organization': None}, org_admin, expect=400)
@pytest.mark.django_db
def test_cannot_schedule_manual_project(project, admin_user, post):
response = post(
reverse('api:project_schedules_list', args=(project.pk,)),
{"name": "foo", "description": "", "enabled": True,
"rrule": "DTSTART:20160926T040000Z RRULE:FREQ=HOURLY;INTERVAL=1",
"extra_data": {}}, admin_user, expect=400)
assert 'Manual' in response.data['unified_job_template'][0]

View File

@ -233,7 +233,8 @@ class ProjectsTest(BaseTransactionTest):
'name': 'My Test Project',
'description': 'Does amazing things',
'local_path': os.path.basename(project_dir),
'scm_type': None,
'scm_type': 'git', # must not be manual in order to schedule
'scm_url': 'http://192.168.100.128.git',
'scm_update_on_launch': '',
'scm_delete_on_update': None,
'scm_clean': False,
@ -244,7 +245,7 @@ class ProjectsTest(BaseTransactionTest):
# or an empty string for False, but save the value as a boolean.
response = self.post(projects, project_data, expect=201,
auth=self.get_super_credentials())
self.assertEqual(response['scm_type'], u'')
self.assertEqual(response['scm_type'], u'git')
self.assertEqual(response['scm_update_on_launch'], False)
self.assertEqual(response['scm_delete_on_update'], False)
self.assertEqual(response['scm_clean'], False)