Merge "Allow using role 'master' in conjunction with other"
This commit is contained in:
commit
c4b2864014
|
@ -18,6 +18,8 @@
|
|||
|
||||
import itertools
|
||||
|
||||
import six
|
||||
|
||||
from nailgun import consts
|
||||
from nailgun.errors import errors
|
||||
from nailgun.logger import logger
|
||||
|
@ -148,7 +150,7 @@ class PluginsPreDeploymentHooksSerializer(BasePluginDeploymentHooksSerializer):
|
|||
# plugin tasks
|
||||
tasks_to_process = plugin.tasks + plugin.deployment_tasks
|
||||
|
||||
roles = []
|
||||
roles = set()
|
||||
for task in tasks_to_process:
|
||||
# plugin tasks may store information about node
|
||||
# role not only in `role` key but also in `groups`
|
||||
|
@ -156,15 +158,10 @@ class PluginsPreDeploymentHooksSerializer(BasePluginDeploymentHooksSerializer):
|
|||
if task_role == consts.TASK_ROLES.all:
|
||||
# just return all nodes
|
||||
return self.role_resolver.resolve(consts.TASK_ROLES.all)
|
||||
elif task_role == consts.TASK_ROLES.master:
|
||||
# NOTE(aroma): pre-deployment tasks should not be executed on
|
||||
# master node because in some cases it leads to errors due to
|
||||
# commands need to be run are not compatible with master node
|
||||
# OS (CentOS). E.g. of such situation - create repository
|
||||
# executes `apt-get update` which fails on CentOS
|
||||
continue
|
||||
elif isinstance(task_role, list):
|
||||
roles.extend(task_role)
|
||||
elif isinstance(task_role, six.string_types):
|
||||
roles.add(task_role)
|
||||
elif isinstance(task_role, (list, tuple)):
|
||||
roles.update(task_role)
|
||||
# if task has 'skipped' status it is allowed that 'roles' and
|
||||
# 'groups' are not be specified
|
||||
elif task['type'] != consts.ORCHESTRATOR_TASK_TYPES.skipped:
|
||||
|
@ -174,7 +171,14 @@ class PluginsPreDeploymentHooksSerializer(BasePluginDeploymentHooksSerializer):
|
|||
'a list of roles or "*"',
|
||||
task)
|
||||
|
||||
return self.role_resolver.resolve(roles)
|
||||
# NOTE(aroma): pre-deployment tasks should not be executed on
|
||||
# master node because in some cases it leads to errors due to
|
||||
# commands need to be run are not compatible with master node
|
||||
# OS (CentOS). E.g. of such situation - create repository
|
||||
# executes `apt-get update` which fails on CentOS
|
||||
roles.discard(consts.TASK_ROLES.master)
|
||||
|
||||
return list(self.role_resolver.resolve(roles))
|
||||
|
||||
def create_repositories(self, plugins):
|
||||
operating_system = self.cluster.release.operating_system
|
||||
|
|
|
@ -93,9 +93,9 @@ class StandardConfigRolesHook(ExpressionBasedTask):
|
|||
self.role_resolver = role_resolver or RoleResolver(nodes)
|
||||
|
||||
def get_uids(self):
|
||||
return self.role_resolver.resolve(
|
||||
return list(self.role_resolver.resolve(
|
||||
self.task.get('role', self.task.get('groups'))
|
||||
)
|
||||
))
|
||||
|
||||
def serialize(self):
|
||||
uids = self.get_uids()
|
||||
|
@ -113,7 +113,7 @@ class UploadMOSRepo(GenericRolesHook):
|
|||
identity = 'upload_core_repos'
|
||||
|
||||
def get_uids(self):
|
||||
return self.role_resolver.resolve(consts.TASK_ROLES.all)
|
||||
return list(self.role_resolver.resolve(consts.TASK_ROLES.all))
|
||||
|
||||
def serialize(self):
|
||||
uids = self.get_uids()
|
||||
|
@ -157,7 +157,7 @@ class RsyncPuppet(GenericRolesHook):
|
|||
identity = 'rsync_core_puppet'
|
||||
|
||||
def get_uids(self):
|
||||
return self.role_resolver.resolve(consts.TASK_ROLES.all)
|
||||
return list(self.role_resolver.resolve(consts.TASK_ROLES.all))
|
||||
|
||||
def serialize(self):
|
||||
src_path = self.task['parameters']['src'].format(
|
||||
|
|
|
@ -66,17 +66,25 @@ class TestPatternBasedRoleResolver(BaseUnitTest):
|
|||
|
||||
def test_resolve_master(self):
|
||||
resolver = role_resolver.RoleResolver(self.nodes)
|
||||
self.assertEqual(
|
||||
self.assertItemsEqual(
|
||||
[consts.MASTER_NODE_UID],
|
||||
resolver.resolve(consts.TASK_ROLES.master)
|
||||
)
|
||||
self.assertItemsEqual(
|
||||
[consts.MASTER_NODE_UID, '2', '3'],
|
||||
resolver.resolve([consts.TASK_ROLES.master, 'controller'])
|
||||
)
|
||||
|
||||
def test_resolve_any(self):
|
||||
resolver = role_resolver.RoleResolver(self.nodes)
|
||||
all_nodes = resolver.resolve("*", consts.NODE_RESOLVE_POLICY.all)
|
||||
self.assertItemsEqual(
|
||||
all_nodes,
|
||||
(n.uid for n in self.nodes)
|
||||
)
|
||||
any_node = resolver.resolve("*", consts.NODE_RESOLVE_POLICY.any)
|
||||
self.assertEqual(1, len(any_node))
|
||||
self.assertIn(any_node[0], all_nodes)
|
||||
self.assertTrue(any_node.issubset(all_nodes))
|
||||
|
||||
|
||||
class TestNullResolver(BaseUnitTest):
|
||||
|
|
|
@ -40,7 +40,7 @@ class BaseRoleResolver(object):
|
|||
any means need to return any node from resolved
|
||||
all means need to return all resolved nodes
|
||||
:type policy: str
|
||||
:return: the list of nodes
|
||||
:return: the unique set of nodes
|
||||
"""
|
||||
|
||||
|
||||
|
@ -79,35 +79,40 @@ class RoleResolver(BaseRoleResolver):
|
|||
self.__mapping[r].add(node.uid)
|
||||
|
||||
def resolve(self, roles, policy=None):
|
||||
if isinstance(roles, six.string_types) and roles in self.SPECIAL_ROLES:
|
||||
result = self.SPECIAL_ROLES[roles]
|
||||
elif roles == consts.TASK_ROLES.all:
|
||||
result = list(set(
|
||||
result = set()
|
||||
if roles == consts.TASK_ROLES.all:
|
||||
# optimization
|
||||
result = {
|
||||
uid for nodes in six.itervalues(self.__mapping)
|
||||
for uid in nodes
|
||||
))
|
||||
elif isinstance(roles, (list, tuple)):
|
||||
result = set()
|
||||
for role in roles:
|
||||
pattern = NameMatchingPolicy.create(role)
|
||||
for node_role, nodes_ids in six.iteritems(self.__mapping):
|
||||
if pattern.match(node_role):
|
||||
result.update(nodes_ids)
|
||||
result = list(result)
|
||||
}
|
||||
else:
|
||||
# TODO(fix using wrong format for roles in tasks.yaml)
|
||||
# After it will be allowed to raise exception here
|
||||
logger.warn(
|
||||
'Wrong roles format, `roles` should be a list or "*": %s',
|
||||
roles
|
||||
)
|
||||
return []
|
||||
if isinstance(roles, six.string_types):
|
||||
roles = [roles]
|
||||
|
||||
if not isinstance(roles, (list, tuple, set)):
|
||||
# TODO(bgaifullin) fix wrong format for roles in tasks.yaml
|
||||
# After it will be allowed to raise exception here
|
||||
logger.warn(
|
||||
'Wrong roles format, `roles` should be a list or "*": %s',
|
||||
roles
|
||||
)
|
||||
return result
|
||||
|
||||
for role in roles:
|
||||
if role in self.SPECIAL_ROLES:
|
||||
result.update(self.SPECIAL_ROLES[role])
|
||||
else:
|
||||
pattern = NameMatchingPolicy.create(role)
|
||||
for node_role, nodes_ids in six.iteritems(self.__mapping):
|
||||
if pattern.match(node_role):
|
||||
result.update(nodes_ids)
|
||||
|
||||
# in some cases need only one any node from pool
|
||||
# for example if need only one any controller.
|
||||
# to distribute load select first node from pool
|
||||
if result and policy == consts.NODE_RESOLVE_POLICY.any:
|
||||
result = result[0:1]
|
||||
result = {next(iter(result))}
|
||||
|
||||
logger.debug(
|
||||
"Role '%s' and policy '%s' was resolved to: %s",
|
||||
|
|
Loading…
Reference in New Issue