def _wrap_attribute(cls, attr_name, attribute, node_name, node_type): """ Wrap a Node attribute into the correct descriptor class. """ # The Hosts definition (should be a Hosts class ore RoleMapping) if attr_name == 'Hosts': # Validate 'Hosts' value if not isinstance(attribute, RoleMapping): if isclass(attribute): # Try to initialize a HostContainer. If that fails, something is wrong. HostsContainer.from_definition(attribute) else: raise Exception( 'Node.Hosts should be a class definition or a RoleMapping instance.' ) return attribute # Wrap functions into an ActionDescriptor elif isfunction(attribute) and attr_name not in ('__getitem__', '__iter__', '__new__', '__init__'): return ActionDescriptor(attr_name, attribute) # Wrap Nodes into a ChildNodeDescriptor elif isclass(attribute) and issubclass(attribute, Node): # Check the node nesting rules. if not NodeNestingRules.check(node_type, attribute._node_type): raise Exception( 'Invalid nesting of %s in %s (%r in %r).' % (attribute._node_type, node_type, attribute, node_name)) if not NodeNestingRules.check_mapping( node_type, attribute._node_type, bool(attribute.Hosts)): raise Exception( 'The Node-attribute %s of type %s does not have a valid role_mapping.' % (attr_name, attribute._node_type)) return ChildNodeDescriptor(attr_name, attribute) # Properties should be wrapped again in an Action # descriptor elif isinstance(attribute, property): if isinstance(attribute, required_property): attribute.name = attr_name attribute.owner = node_name return PropertyDescriptor(attr_name, attribute) # Query objects are like properties and should also be # wrapped into a descriptor elif isinstance(attribute, Query): return QueryDescriptor(node_name, attr_name, attribute) else: return attribute
def _wrap_attribute(cls, attr_name, attribute, node_name, node_type): """ Wrap a Node attribute into the correct descriptor class. """ # The Hosts definition (should be a Hosts class ore RoleMapping) if attr_name == 'Hosts': # Validate 'Hosts' value if not isinstance(attribute, RoleMapping): if isclass(attribute): # Try to initialize a HostContainer. If that fails, something is wrong. HostsContainer.from_definition(attribute) else: raise Exception('Node.Hosts should be a class definition or a RoleMapping instance.') return attribute # Wrap functions into an ActionDescriptor elif isfunction(attribute) and attr_name not in ('__getitem__', '__iter__', '__new__', '__init__'): return ActionDescriptor(attr_name, attribute) # Wrap Nodes into a ChildNodeDescriptor elif isclass(attribute) and issubclass(attribute, Node): # Check the node nesting rules. if not NodeNestingRules.check(node_type, attribute._node_type): raise Exception('Invalid nesting of %s in %s (%r in %r).' % ( attribute._node_type, node_type, attribute, node_name)) if not NodeNestingRules.check_mapping(node_type, attribute._node_type, bool(attribute.Hosts)): raise Exception('The Node-attribute %s of type %s does not have a valid role_mapping.' % (attr_name, attribute._node_type)) return ChildNodeDescriptor(attr_name, attribute) # Properties should be wrapped again in an Action # descriptor elif isinstance(attribute, property): if isinstance(attribute, required_property): attribute.name = attr_name attribute.owner = node_name return PropertyDescriptor(attr_name, attribute) # Query objects are like properties and should also be # wrapped into a descriptor elif isinstance(attribute, Query): return QueryDescriptor(node_name, attr_name, attribute) else: return attribute
def __init__(self, node, pty=None, logger=None, is_sandbox=False): assert isinstance(node, Node) self._node = node self._pty = pty or DummyPty() self._logger = logger or DummyLoggerInterface() self._is_sandbox = is_sandbox # When the node is callable (when it has a default action), # make sure that this env becomes collable as well. if callable(self._node): # Per instance overriding def call(self, *a, **kw): return self.__getattr__('__call__')(*a, **kw) self.__class__ = type(self.__class__.__name__, (self.__class__, ), {'__call__': call}) # Create a new HostsContainer object which is identical to the one of # the Node object, but add pty/logger/sandbox settings. (So, this # doesn't create new Host instances, only a new container.) # (do this in this constructor. Each call to Env.hosts should return # the same host container instance.) self._hosts = HostsContainer(self._node.hosts.get_hosts_as_dict(), pty=self._pty, logger=self._logger, is_sandbox=is_sandbox) # Lock Env self._lock_env = True
def get_definition(self): class Hosts: role1 = LocalHost1, LocalHost2 role2 = LocalHost3, LocalHost4, LocalHost5 role3 = LocalHost1 return HostsContainer.from_definition(Hosts, pty=DummyPty())
def get_definition(self): hosts = self.get_hosts() class Hosts: role1 = { hosts.h1, hosts.h2} role2 = { hosts.h3, hosts.h4, hosts.h5 } role3 = { hosts.h1 } return HostsContainer.from_definition(Hosts, pty=DummyPty())
def __init__(self, parent=None): #: Reference to the parent :class:`~deployer.node.base.Node`. #: (This is always assigned in the constructor. You should never override it.) self.parent = parent if self._node_type in (NodeTypes.SIMPLE_ARRAY, NodeTypes.SIMPLE_ONE) and not parent: raise Exception( 'Cannot initialize a node of type %s without a parent' % self._node_type) # Create host container (from hosts definition, or mapping from parent hosts.) Hosts = self.Hosts or DefaultRoleMapping() if isinstance(Hosts, RoleMapping): self.hosts = Hosts.apply(parent) if parent else HostsContainer({}) else: self.hosts = HostsContainer.from_definition(Hosts)
def Connect(self): """ Open interactive SSH connection with this host. """ from deployer.contrib.services import connect from deployer.host_container import HostsContainer c = connect.Connect(HostsContainer({ 'host': self.service.hosts._all })) # Run as any other action. (Nice exception handling, e.g. in case of NoInput on host selection.) Action(c.with_host, self.shell, False)()
def __init__(self, parent=None): self.parent = parent if self._node_type in (NodeTypes.SIMPLE_ARRAY, NodeTypes.SIMPLE_ONE) and not parent: raise Exception('Cannot initialize a node of type %s without a parent' % self._node_type) # Create host container (from hosts definition, or mapping from parent hosts.) Hosts = self.Hosts or DefaultRoleMapping() if isinstance(Hosts, RoleMapping): self.hosts = Hosts.apply(parent) if parent else HostsContainer({ }) else: self.hosts = HostsContainer.from_definition(Hosts)
def __init__(self, parent=None): #: Reference to the parent :class:`~deployer.node.base.Node`. #: (This is always assigned in the constructor. You should never override it.) self.parent = parent if self._node_type in (NodeTypes.SIMPLE_ARRAY, NodeTypes.SIMPLE_ONE) and not parent: raise Exception('Cannot initialize a node of type %s without a parent' % self._node_type) # Create host container (from hosts definition, or mapping from parent hosts.) Hosts = self.Hosts or DefaultRoleMapping() if isinstance(Hosts, RoleMapping): self.hosts = Hosts.apply(parent) if parent else HostsContainer({ }) else: self.hosts = HostsContainer.from_definition(Hosts)
def apply(self, parent_node_instance): """ Map roles from the parent to the child node and create a new :class:`HostsContainer` instance by applying it. """ parent_container = parent_node_instance.hosts def get(f): if f == ALL_HOSTS: return parent_container.get_hosts() else: assert isinstance(f, tuple), TypeError( 'Invalid value found in mapping: %r' % f) return parent_container.filter(*f).get_hosts() return HostsContainer( {role: get(f) for role, f in self._mappings.items()}, pty=parent_container._pty, logger=parent_container._logger, is_sandbox=parent_container._sandbox)
def test_host_container(self): hosts = self.get_hosts() hosts_container = self.get_definition() # (fuzzy) __repr__ self.assertIn('role1', repr(hosts_container)) self.assertIn('role2', repr(hosts_container)) self.assertIn('role3', repr(hosts_container)) # __eq__ of get_hosts_as_dict # (__eq__ of HostsContainer itself is not supported anymore.) self.assertEqual(hosts_container.get_hosts_as_dict(), self.get_definition().get_hosts_as_dict()) # __len__ (One host appeared in two roles, both will be counted, so 6) self.assertEqual(len(hosts_container), 6) # __nonzero__ self.assertEqual(bool(hosts_container), True) # roles self.assertEqual(hosts_container.roles, ['role1', 'role2', 'role3']) # # __contains__ # self.assertIn(LocalHost3, hosts_container) # Filter self.assertEqual(len(hosts_container.filter('role1')), 2) self.assertEqual(len(hosts_container.filter('role2')), 3) self.assertEqual(len(hosts_container.filter('role3')), 1) # Non string filter should raise exception. self.assertRaises(TypeError, HostsContainer.filter, 123) class MyHosts1: role1 = { hosts.h1, hosts.h2 } class MyHosts2: role2 = { hosts.h3, hosts.h4, hosts.h5 } self.assertIsInstance(hosts_container.filter('role1'), HostsContainer) self.assertIsInstance(hosts_container.filter('role2'), HostsContainer) self.assertEqual(hosts_container.filter('role1').get_hosts(), set(MyHosts1.role1)) self.assertEqual(hosts_container.filter('role2').get_hosts(), set(MyHosts2.role2)) self.assertEqual(hosts_container.filter('role1').get_hosts_as_dict(), HostsContainer.from_definition(MyHosts1).get_hosts_as_dict()) self.assertEqual(hosts_container.filter('role2').get_hosts_as_dict(), HostsContainer.from_definition(MyHosts2).get_hosts_as_dict()) self.assertNotEqual(hosts_container.filter('role1').get_hosts_as_dict(), HostsContainer.from_definition(MyHosts2).get_hosts_as_dict()) self.assertNotEqual(hosts_container.filter('role2').get_hosts_as_dict(), HostsContainer.from_definition(MyHosts1).get_hosts_as_dict()) # Filter on two roles. class MyHosts1_and_2: role1 = { hosts.h1, hosts.h2 } role2 = { hosts.h3, hosts.h4, hosts.h5 } self.assertEqual(hosts_container.filter('role1', 'role2').get_hosts_as_dict(), HostsContainer.from_definition(MyHosts1_and_2).get_hosts_as_dict()) # __iter__ (will yield 6 items: when several roles contain the same # host, it are different instances.) count = 0 for i in hosts_container: self.assertIsInstance(i, HostContainer) count += 1 self.assertEqual(count, 6)
def test_host_container(self): hosts_container = self.get_definition() # (fuzzy) __repr__ self.assertIn('role1', repr(hosts_container)) self.assertIn('role2', repr(hosts_container)) self.assertIn('role3', repr(hosts_container)) # __eq__ self.assertEqual(hosts_container, self.get_definition()) # __len__ self.assertEqual(len(hosts_container), 5) # __nonzero__ self.assertEqual(bool(hosts_container), True) # roles self.assertEqual(hosts_container.roles, ['role1', 'role2', 'role3']) # # __contains__ # print hosts_container._all # print LocalHost3 in hosts_container._all # print LocalHost3 == LocalHost3 # self.assertIn(LocalHost3, hosts_container) # get_from_slug self.assertEqual(hosts_container.get_from_slug('localhost2')._host, LocalHost2) # contains_host_with_slug self.assertEqual(hosts_container.contains_host_with_slug('localhost2'), True) self.assertEqual(hosts_container.contains_host_with_slug('unknown-host'), False) # Filter self.assertEqual(len(hosts_container.filter('role1')), 2) self.assertEqual(len(hosts_container.filter('role2')), 3) self.assertEqual(len(hosts_container.filter('role3')), 1) # Filter-* self.assertEqual(len(hosts_container.filter('*')), 5) class MyHosts1: role1 = LocalHost1, LocalHost2 class MyHosts2: role2 = LocalHost3, LocalHost4, LocalHost5 self.assertEqual(hosts_container.filter('role1'), HostsContainer.from_definition(MyHosts1)) self.assertEqual(hosts_container.filter('role2'), HostsContainer.from_definition(MyHosts2)) self.assertNotEqual(hosts_container.filter('role1'), HostsContainer.from_definition(MyHosts2)) self.assertNotEqual(hosts_container.filter('role2'), HostsContainer.from_definition(MyHosts1)) # Filter on two roles. class MyHosts1_and_2: role1 = LocalHost1, LocalHost2 role2 = LocalHost3, LocalHost4, LocalHost5 self.assertEqual(hosts_container.filter('role1', 'role2'), HostsContainer.from_definition(MyHosts1_and_2)) self.assertNotEqual(hosts_container.filter('role1', 'role2'), HostsContainer.from_definition(MyHosts1)) # get self.assertRaises(AttributeError, hosts_container.get, 'role1') # Role with multiple hosts self.assertRaises(AttributeError, hosts_container.get, 'unknown-role') self.assertEqual(hosts_container.get('role3')._host, LocalHost1) # __iter__ count = 0 for i in hosts_container: self.assertIsInstance(i, HostContainer) count += 1 self.assertEqual(count, 5)