From 6cdbb8eef1e179ff778b5b9089247b372ada5876 Mon Sep 17 00:00:00 2001 From: adrian-turjak Date: Mon, 19 Dec 2016 17:30:11 +1300 Subject: [PATCH] Restructure of the actions configuration * Cleaned up some of the code that gets the action settings. * Added the option of per task action settings just in case a given task needs to reuse an action with different settings. Change-Id: I8194cd3155ac3db3faaf0de8b87617f3891d0b10 --- conf/conf.yaml | 101 +++++++++++++++++---------- stacktask/actions/v1/base.py | 14 ++++ stacktask/actions/v1/projects.py | 13 ++-- stacktask/actions/v1/resources.py | 9 +-- stacktask/actions/v1/serializers.py | 2 +- stacktask/actions/v1/users.py | 6 +- stacktask/settings.py | 6 +- stacktask/test_settings.py | 102 ++++++++++++++++------------ stacktask/utils.py | 9 +-- 9 files changed, 156 insertions(+), 106 deletions(-) diff --git a/conf/conf.yaml b/conf/conf.yaml index 5b51b82..53185c5 100644 --- a/conf/conf.yaml +++ b/conf/conf.yaml @@ -123,6 +123,70 @@ DEFAULT_TASK_SETTINGS: password: password template: notification.txt +# Default Action settings: +# These can be overriden at a per task level below in the +# task settings so that multiple tasks can use the same actions +# slightly differently. +# +# TASK_SETTINGS: +# : +# .... +# .... +# action_settings: +# : +# .... +DEFAULT_ACTION_SETTINGS: + NewProjectAction: + default_roles: + - project_admin + - project_mod + - heat_stack_owner + - _member_ + NewProjectWithUserAction: + default_roles: + - project_admin + - project_mod + - heat_stack_owner + - _member_ + NewUserAction: + allowed_roles: + - project_admin + - project_mod + - heat_stack_owner + - _member_ + ResetUserPasswordAction: + blacklisted_roles: + - admin + NewDefaultNetworkAction: + RegionOne: + network_name: default_network + subnet_name: default_subnet + router_name: default_router + public_network: 3cb50d61-5bce-4c03-96e6-8e262e12bb35 + DNS_NAMESERVERS: + - 193.168.1.2 + - 193.168.1.3 + SUBNET_CIDR: 192.168.1.0/24 + NewProjectDefaultNetworkAction: + RegionOne: + network_name: default_network + subnet_name: default_subnet + router_name: default_router + public_network: 3cb50d61-5bce-4c03-96e6-8e262e12bb35 + DNS_NAMESERVERS: + - 193.168.1.2 + - 193.168.1.3 + SUBNET_CIDR: 192.168.1.0/24 + AddDefaultUsersToProjectAction: + default_users: + - admin + default_roles: + - admin + SetProjectQuotaAction: + regions: + RegionOne: + quota_size: small + # These are cascading overrides for the default settings: TASK_SETTINGS: signup: @@ -206,43 +270,6 @@ TASK_SETTINGS: role_blacklist: - admin -# Action settings: -ACTION_SETTINGS: - NewProjectAction: - default_roles: - - project_admin - - project_mod - - heat_stack_owner - - _member_ - NewUserAction: - allowed_roles: - - project_admin - - project_mod - - heat_stack_owner - - _member_ - ResetUserPasswordAction: - blacklisted_roles: - - admin - NewDefaultNetworkAction: - RegionOne: - network_name: default_network - subnet_name: default_subnet - router_name: default_router - public_network: 3cb50d61-5bce-4c03-96e6-8e262e12bb35 - DNS_NAMESERVERS: - - 193.168.1.2 - - 193.168.1.3 - SUBNET_CIDR: 192.168.1.0/24 - AddDefaultUsersToProjectAction: - default_users: - - admin - default_roles: - - admin - SetProjectQuotaAction: - regions: - RegionOne: - quota_size: small - # mapping between roles and managable roles ROLES_MAPPING: admin: diff --git a/stacktask/actions/v1/base.py b/stacktask/actions/v1/base.py index 77fbbe3..23c028c 100644 --- a/stacktask/actions/v1/base.py +++ b/stacktask/actions/v1/base.py @@ -123,6 +123,20 @@ class BaseAction(object): self.action.task.add_action_note( str(self), note) + @property + def settings(self): + """Get my settings. + + Returns a dict of the settings for this action. + """ + try: + task_conf = settings.TASK_SETTINGS[self.action.task.task_type] + return task_conf['action_settings'].get( + self.__class__.__name__, {}) + except KeyError: + return settings.DEFAULT_ACTION_SETTINGS.get( + self.__class__.__name__, {}) + def pre_approve(self): return self._pre_approve() diff --git a/stacktask/actions/v1/projects.py b/stacktask/actions/v1/projects.py index 5d9110b..a75e75b 100644 --- a/stacktask/actions/v1/projects.py +++ b/stacktask/actions/v1/projects.py @@ -14,7 +14,6 @@ from uuid import uuid4 -from django.conf import settings from django.utils import timezone from stacktask.actions import user_store @@ -87,8 +86,7 @@ class NewProjectAction(BaseAction, ProjectMixin, UserMixin): self.action.task.cache['user_id'] = user_id self.add_note("User already given roles.") else: - default_roles = settings.ACTION_SETTINGS.get( - 'NewProjectAction', {}).get("default_roles", {}) + default_roles = self.settings.get("default_roles", {}) project_id = self.get_cache('project_id') keystone_user = self.action.task.keystone_user @@ -241,8 +239,7 @@ class NewProjectWithUserAction(UserNameAction, ProjectMixin, UserMixin): def _create_user_for_project(self): id_manager = user_store.IdentityManager() - default_roles = settings.ACTION_SETTINGS.get( - 'NewProjectAction', {}).get("default_roles", {}) + default_roles = self.settings.get("default_roles", {}) project_id = self.get_cache('project_id') @@ -396,11 +393,9 @@ class AddDefaultUsersToProjectAction(BaseAction, ProjectMixin, UserMixin): ] def __init__(self, *args, **kwargs): - self.users = settings.ACTION_SETTINGS.get( - 'AddDefaultUsersToProjectAction', {}).get('default_users', []) - self.roles = settings.ACTION_SETTINGS.get( - 'AddDefaultUsersToProjectAction', {}).get('default_roles', []) super(AddDefaultUsersToProjectAction, self).__init__(*args, **kwargs) + self.users = self.settings.get('default_users', []) + self.roles = self.settings.get('default_roles', []) def _validate_users(self): id_manager = user_store.IdentityManager() diff --git a/stacktask/actions/v1/resources.py b/stacktask/actions/v1/resources.py index bce9559..a71a301 100644 --- a/stacktask/actions/v1/resources.py +++ b/stacktask/actions/v1/resources.py @@ -49,8 +49,7 @@ class NewDefaultNetworkAction(BaseAction, ProjectMixin): return True def _validate_defaults(self): - defaults = settings.ACTION_SETTINGS.get( - 'NewDefaultNetworkAction', {}).get(self.region, {}) + defaults = self.settings.get(self.region, {}) if not defaults: self.add_note('ERROR: No default settings for region %s.' % @@ -76,8 +75,7 @@ class NewDefaultNetworkAction(BaseAction, ProjectMixin): def _create_network(self): neutron = openstack_clients.get_neutronclient(region=self.region) - defaults = settings.ACTION_SETTINGS.get( - 'NewDefaultNetworkAction', {}).get(self.region, {}) + defaults = self.settings.get(self.region, {}) if not self.get_cache('network_id'): try: @@ -289,8 +287,7 @@ class SetProjectQuotaAction(BaseAction): return # update quota for each openstack service - regions_dict = settings.ACTION_SETTINGS.get( - 'SetProjectQuotaAction', {}).get('regions', {}) + regions_dict = self.settings.get('regions', {}) for region_name, region_settings in six.iteritems(regions_dict): quota_size = region_settings.get('quota_size') quota_settings = settings.PROJECT_QUOTA_SIZES.get(quota_size, {}) diff --git a/stacktask/actions/v1/serializers.py b/stacktask/actions/v1/serializers.py index 8abdc25..3e21e8e 100644 --- a/stacktask/actions/v1/serializers.py +++ b/stacktask/actions/v1/serializers.py @@ -16,7 +16,7 @@ from rest_framework import serializers from django.conf import settings -role_options = settings.ACTION_SETTINGS.get("NewUserAction", {}).get( +role_options = settings.DEFAULT_ACTION_SETTINGS.get("NewUserAction", {}).get( "allowed_roles", []) diff --git a/stacktask/actions/v1/users.py b/stacktask/actions/v1/users.py index dd88b6e..cb16898 100644 --- a/stacktask/actions/v1/users.py +++ b/stacktask/actions/v1/users.py @@ -12,7 +12,6 @@ # License for the specific language governing permissions and limitations # under the License. -from django.conf import settings from django.db import models from stacktask.actions import user_store @@ -163,8 +162,9 @@ class ResetUserPasswordAction(UserNameAction, UserMixin): 'email' ] - blacklist = settings.ACTION_SETTINGS.get( - 'ResetUserPasswordAction', {}).get("blacklisted_roles", {}) + def __init__(self, *args, **kwargs): + super(ResetUserPasswordAction, self).__init__(*args, **kwargs) + self.blacklist = self.settings.get("blacklisted_roles", {}) def _validate_user_roles(self): id_manager = user_store.IdentityManager() diff --git a/stacktask/settings.py b/stacktask/settings.py index 44d63fd..e503348 100644 --- a/stacktask/settings.py +++ b/stacktask/settings.py @@ -159,12 +159,14 @@ TOKEN_SUBMISSION_URL = CONFIG['TOKEN_SUBMISSION_URL'] TOKEN_EXPIRE_TIME = CONFIG['TOKEN_EXPIRE_TIME'] +DEFAULT_ACTION_SETTINGS = CONFIG['DEFAULT_ACTION_SETTINGS'] + TASK_SETTINGS = setup_task_settings( CONFIG['DEFAULT_TASK_SETTINGS'], + CONFIG['DEFAULT_ACTION_SETTINGS'], CONFIG['TASK_SETTINGS']) -DEFAULT_TASK_SETTINGS = CONFIG['DEFAULT_TASK_SETTINGS'] -ACTION_SETTINGS = CONFIG['ACTION_SETTINGS'] +DEFAULT_TASK_SETTINGS = CONFIG['DEFAULT_TASK_SETTINGS'] PLUGIN_SETTINGS = CONFIG.get('PLUGIN_SETTINGS', {}) diff --git a/stacktask/test_settings.py b/stacktask/test_settings.py index 13fabe9..855bf11 100644 --- a/stacktask/test_settings.py +++ b/stacktask/test_settings.py @@ -108,6 +108,63 @@ DEFAULT_TASK_SETTINGS = { } } +DEFAULT_ACTION_SETTINGS = { + 'NewProjectAction': { + 'default_roles': { + "project_admin", "project_mod", "_member_", "heat_stack_owner" + }, + }, + 'NewProjectWithUserAction': { + 'default_roles': { + "project_admin", "project_mod", "_member_", "heat_stack_owner" + }, + }, + 'NewUserAction': { + 'allowed_roles': ['project_mod', 'project_admin', "_member_"] + }, + 'ResetUserPasswordAction': { + 'blacklisted_roles': ['admin'] + }, + 'NewDefaultNetworkAction': { + 'RegionOne': { + 'DNS_NAMESERVERS': ['193.168.1.2', '193.168.1.3'], + 'SUBNET_CIDR': '192.168.1.0/24', + 'network_name': 'somenetwork', + 'public_network': '3cb50f61-5bce-4c03-96e6-8e262e12bb35', + 'router_name': 'somerouter', + 'subnet_name': 'somesubnet' + }, + }, + 'NewProjectDefaultNetworkAction': { + 'RegionOne': { + 'DNS_NAMESERVERS': ['193.168.1.2', '193.168.1.3'], + 'SUBNET_CIDR': '192.168.1.0/24', + 'network_name': 'somenetwork', + 'public_network': '3cb50f61-5bce-4c03-96e6-8e262e12bb35', + 'router_name': 'somerouter', + 'subnet_name': 'somesubnet' + }, + }, + 'AddDefaultUsersToProjectAction': { + 'default_users': [ + 'admin', + ], + 'default_roles': [ + 'admin', + ], + }, + 'SetProjectQuotaAction': { + 'regions': { + 'RegionOne': { + 'quota_size': 'small' + }, + 'RegionTwo': { + 'quota_size': 'large' + } + }, + }, +} + TASK_SETTINGS = { 'invite_user': { 'emails': { @@ -172,49 +229,6 @@ TASK_SETTINGS = { } } -ACTION_SETTINGS = { - 'NewProjectAction': { - 'default_roles': { - "project_admin", "project_mod", "_member_", "heat_stack_owner" - }, - }, - 'NewUserAction': { - 'allowed_roles': ['project_mod', 'project_admin', "_member_"] - }, - 'ResetUserPasswordAction': { - 'blacklisted_roles': ['admin'] - }, - 'NewDefaultNetworkAction': { - 'RegionOne': { - 'DNS_NAMESERVERS': ['193.168.1.2', '193.168.1.3'], - 'SUBNET_CIDR': '192.168.1.0/24', - 'network_name': 'somenetwork', - 'public_network': '3cb50f61-5bce-4c03-96e6-8e262e12bb35', - 'router_name': 'somerouter', - 'subnet_name': 'somesubnet' - }, - }, - 'AddDefaultUsersToProjectAction': { - 'default_users': [ - 'admin', - ], - 'default_roles': [ - 'admin', - ], - }, - 'SetProjectQuotaAction': { - 'regions': { - 'RegionOne': { - 'quota_size': 'small' - }, - 'RegionTwo': { - 'quota_size': 'large' - } - }, - }, - -} - ROLES_MAPPING = { 'admin': [ 'project_admin', 'project_mod', '_member_', 'heat_stack_owner' @@ -280,7 +294,7 @@ conf_dict = { "ACTIVE_TASKVIEWS": ACTIVE_TASKVIEWS, "DEFAULT_TASK_SETTINGS": DEFAULT_TASK_SETTINGS, "TASK_SETTINGS": TASK_SETTINGS, - "ACTION_SETTINGS": ACTION_SETTINGS, + "DEFAULT_ACTION_SETTINGS": DEFAULT_ACTION_SETTINGS, "TOKEN_SUBMISSION_URL": TOKEN_SUBMISSION_URL, "TOKEN_EXPIRE_TIME": TOKEN_EXPIRE_TIME, "ROLES_MAPPING": ROLES_MAPPING, diff --git a/stacktask/utils.py b/stacktask/utils.py index 494fdf8..b28a585 100644 --- a/stacktask/utils.py +++ b/stacktask/utils.py @@ -26,20 +26,21 @@ def dict_merge(a, b): result = deepcopy(a) for k, v in b.iteritems(): if k in result and isinstance(result[k], dict): - result[k] = dict_merge(result[k], v) + result[k] = dict_merge(result[k], v) else: result[k] = deepcopy(v) return result -def setup_task_settings(default, task_settings): +def setup_task_settings(task_defaults, action_defaults, task_settings): """ Cascading merge of the default settings, and the settings for each task_type. """ new_task_settings = {} - for task, settings in task_settings.iteritems(): - new_task_settings[task] = dict_merge(default, settings) + task_setting = deepcopy(task_defaults) + task_setting['action_settings'] = deepcopy(action_defaults) + new_task_settings[task] = dict_merge(task_setting, settings) return new_task_settings