diff --git a/awx/api/urls/execution_environments.py b/awx/api/urls/execution_environments.py index 08f852be08..99b9cb3ddc 100644 --- a/awx/api/urls/execution_environments.py +++ b/awx/api/urls/execution_environments.py @@ -4,6 +4,7 @@ from awx.api.views import ( ExecutionEnvironmentList, ExecutionEnvironmentDetail, ExecutionEnvironmentJobTemplateList, + ExecutionEnvironmentCopy, ExecutionEnvironmentActivityStreamList, ) @@ -12,6 +13,7 @@ urls = [ url(r'^$', ExecutionEnvironmentList.as_view(), name='execution_environment_list'), url(r'^(?P[0-9]+)/$', ExecutionEnvironmentDetail.as_view(), name='execution_environment_detail'), url(r'^(?P[0-9]+)/unified_job_templates/$', ExecutionEnvironmentJobTemplateList.as_view(), name='execution_environment_job_template_list'), + url(r'^(?P[0-9]+)/copy/$', ExecutionEnvironmentCopy.as_view(), name='execution_environment_copy'), url(r'^(?P[0-9]+)/activity_stream/$', ExecutionEnvironmentActivityStreamList.as_view(), name='execution_environment_activity_stream_list'), ] diff --git a/awx/api/views/__init__.py b/awx/api/views/__init__.py index 855d9e54e0..2d29519de8 100644 --- a/awx/api/views/__init__.py +++ b/awx/api/views/__init__.py @@ -710,6 +710,12 @@ class ExecutionEnvironmentJobTemplateList(SubListAPIView): relationship = 'unifiedjobtemplates' +class ExecutionEnvironmentCopy(CopyAPIView): + + model = models.ExecutionEnvironment + copy_return_serializer_class = serializers.ExecutionEnvironmentSerializer + + class ExecutionEnvironmentActivityStreamList(SubListAPIView): model = models.ActivityStream diff --git a/awx/main/models/execution_environments.py b/awx/main/models/execution_environments.py index eabd0cce7c..b0fd2bb857 100644 --- a/awx/main/models/execution_environments.py +++ b/awx/main/models/execution_environments.py @@ -3,6 +3,7 @@ from django.utils.translation import ugettext_lazy as _ from awx.api.versioning import reverse from awx.main.models.base import CommonModel +from awx.main.utils import copy_model_by_class, copy_m2m_relationships __all__ = ['ExecutionEnvironment'] @@ -49,5 +50,21 @@ class ExecutionEnvironment(CommonModel): help_text=_('Pull image before running?'), ) + def copy_execution_environment(self): + ''' + Returns saved object, including related fields. + Create a copy of this unified job template. + ''' + execution_environment_class = self.__class__ + fields = (f.name for f in self.Meta.fields) + execution_environment_copy = copy_model_by_class(self, execution_environment_class, fields, {}) + + time_now = now() + execution_environment_copy.name = execution_environment_copy.name.split('@', 1)[0] + ' @ ' + time_now.strftime('%I:%M:%S %p') + + execution_environment_copy.save() + copy_m2m_relationships(self, execution_environment_copy, fields) + return execution_environment_copy + def get_absolute_url(self, request=None): return reverse('api:execution_environment_detail', kwargs={'pk': self.pk}, request=request) diff --git a/awx/main/tests/functional/test_rbac_team.py b/awx/main/tests/functional/test_rbac_team.py index a18a69a94b..ed76e7e4a8 100644 --- a/awx/main/tests/functional/test_rbac_team.py +++ b/awx/main/tests/functional/test_rbac_team.py @@ -2,7 +2,7 @@ import pytest from unittest import mock from awx.main.access import TeamAccess -from awx.main.models import Project, Organization, Team +from awx.main.models import Project, Organization, Team, ExecutionEnvironment @pytest.mark.django_db @@ -143,6 +143,12 @@ def test_team_member_org_role_access_inventory(team, rando, inventory, organizat team.member_role.children.add(organization.inventory_admin_role) assert rando in inventory.admin_role +# @pytest.mark.django_db +# def test_team_member_org_role_access_execution_environment(team, rando, execution_environment, organization): +# team.member_role.members.add(rando) +# assert rando not in execution_environment.read_role +# team.member_role.children.add(organization.execution_environment_admin_role) +# assert rando in execution_environment.admin_role @pytest.mark.django_db def test_org_admin_team_access(organization, team, user, project): diff --git a/awx/main/tests/functional/test_rbac_user.py b/awx/main/tests/functional/test_rbac_user.py index b62a0db25f..376272bdfe 100644 --- a/awx/main/tests/functional/test_rbac_user.py +++ b/awx/main/tests/functional/test_rbac_user.py @@ -4,7 +4,7 @@ from unittest import mock from django.test import TransactionTestCase from awx.main.access import UserAccess, RoleAccess, TeamAccess -from awx.main.models import User, Organization, Inventory, Role +from awx.main.models import User, Organization, Inventory, Role, ExecutionEnvironment class TestSysAuditorTransactional(TransactionTestCase): diff --git a/awxkit/awxkit/api/pages/execution_environments.py b/awxkit/awxkit/api/pages/execution_environments.py index 94f53c1094..0471b1f1d3 100644 --- a/awxkit/awxkit/api/pages/execution_environments.py +++ b/awxkit/awxkit/api/pages/execution_environments.py @@ -1,6 +1,6 @@ import logging -from awxkit.api.mixins import DSAdapter, HasCreate +from awxkit.api.mixins import DSAdapter, HasCreate, HasCopy from awxkit.api.pages import ( Credential, Organization, @@ -15,7 +15,7 @@ from . import page log = logging.getLogger(__name__) -class ExecutionEnvironment(HasCreate, base.Base): +class ExecutionEnvironment(HasCreate, HasCopy, base.Base): dependencies = [Organization, Credential] NATURAL_KEY = ('name',)