def list_information(self, node, settings, container): """ Lists information for a node if it exists :param node: the node to be polished :type node: :class:`libcloud.compute.base.Node` :param settings: the fittings plan for this node :type settings: ``dict`` :param container: the container of this node :type container: :class:`plumbery.PlumberyInfrastructure` """ environment = PlumberyNodeContext(node=node, container=container, context=self.facility) information = [] if ('information' in settings and isinstance(settings['information'], list) and len(settings['information']) > 0): for line in settings['information']: tokens = line.split(' ') if tokens[0] == 'echo': tokens.pop(0) message = ' '.join(tokens) message = PlumberyText.expand_variables( message, environment) information.append(message) return information
def _get_rubs(self, node, settings, container): """ Defines the set of actions to be done on a node :param node: the node to be polished :type node: :class:`libcloud.compute.base.Node` :param settings: the fittings plan for this node :type settings: ``dict`` :param container: the container of this node :type container: :class:`plumbery.PlumberyInfrastructure` :return: a list of actions to be performed, and related descriptions :rtype: a ``list`` of `{ 'description': ..., 'genius': ... }`` """ if not isinstance(settings, dict): return [] environment = PlumberyNodeContext(node=node, container=container, context=self.facility) rubs = [] if self.key is not None: rubs.append({ 'description': 'deploy SSH public key', 'genius': SSHKeyDeployment(self.key)}) if ('rub' in settings and isinstance(settings['rub'], list) and len(settings['rub']) > 0): logging.debug('- using rub commands') for script in settings['rub']: tokens = script.split(' ') if len(tokens) == 1: tokens.insert(0, 'run') if tokens[0] in ['run', 'run_raw']: # send and run a script script = tokens[1] if len(tokens) > 2: args = tokens[2:] else: args = [] logging.debug("- {} {} {}".format( tokens[0], script, ' '.join(args))) try: path = os.path.dirname(__file__)+'/'+script with open(path) as stream: text = stream.read() if(tokens[0] == 'run' and PlumberyText.could_expand(text)): logging.debug("- expanding script '{}'" .format(script)) text = PlumberyText.expand_variables( text, environment) if len(text) > 0: rubs.append({ 'description': ' '.join(tokens), 'genius': ScriptDeployment( script=text, args=args, name=script)}) else: logging.error("- script '{}' is empty" .format(script)) except IOError: logging.error("- unable to read script '{}'" .format(script)) elif tokens[0] in ['put', 'put_raw']: # send a file file = tokens[1] if len(tokens) > 2: destination = tokens[2] else: destination = './'+file logging.debug("- {} {} {}".format( tokens[0], file, destination)) try: source = os.path.dirname(__file__)+'/'+file with open(source) as stream: content = stream.read() if(tokens[0] == 'put' and PlumberyText.could_expand(content)): logging.debug("- expanding file '{}'" .format(file)) content = PlumberyText.expand_variables( content, environment) rubs.append({ 'description': ' '.join(tokens), 'genius': FileContentDeployment( content=content, target=destination)}) except IOError: logging.error("- unable to read file '{}'" .format(file)) else: # echo a sensible message eventually if tokens[0] == 'echo': tokens.pop(0) message = ' '.join(tokens) message = PlumberyText.expand_variables( message, environment) logging.info("- {}".format(message)) cloudConfig = copy.deepcopy(self.cloudConfig) if ('cloud-config' in settings and isinstance(settings['cloud-config'], dict) and len(settings['cloud-config']) > 0): cloudConfig.update(settings['cloud-config']) if len(cloudConfig) > 0: logging.info('- using cloud-config') # mandatory, else cloud-init will not consider user-data logging.debug('- preparing meta-data') meta_data = 'instance_id: dummy\n' destination = '/var/lib/cloud/seed/nocloud-net/meta-data' rubs.append({ 'description': 'put meta-data', 'genius': FileContentDeployment( content=meta_data, target=destination)}) logging.debug('- preparing user-data') expanded = PlumberyText.expand_variables( cloudConfig, environment) user_data = '#cloud-config\n'+expanded logging.debug(user_data) destination = '/var/lib/cloud/seed/nocloud-net/user-data' rubs.append({ 'description': 'put user-data', 'genius': FileContentDeployment( content=user_data, target=destination)}) logging.debug('- preparing remote install of cloud-init') script = 'rub.cloud-init.sh' try: path = os.path.dirname(__file__)+'/'+script with open(path) as stream: text = stream.read() if text: rubs.append({ 'description': 'run '+script, 'genius': ScriptDeployment( script=text, name=script)}) except IOError: raise PlumberyException("Error: cannot read '{}'" .format(script)) logging.debug('- preparing reboot to trigger cloud-init') rubs.append({ 'description': 'reboot node', 'genius': RebootDeployment( container=container)}) return rubs
class TestPlumberyText(unittest.TestCase): def setUp(self): self.text = PlumberyText() def tearDown(self): pass def test_dictionary(self): template = "little {{ test }} with multiple {{test}} and {{}} as well" context = PlumberyContext(dictionary={ 'test': 'toast' }) expected = "little toast with multiple toast and {{}} as well" self.assertEqual( self.text.expand_variables(template, context), expected) def test_engine(self): template = "we are running plumbery {{ plumbery.version }}" context = PlumberyContext(context=PlumberyEngine()) expected = "we are running plumbery "+__version__ self.assertEqual( self.text.expand_variables(template, context), expected) def test_input1(self): context = PlumberyContext(dictionary={ 'node.private': '12.34.56.78' }) self.assertEqual( self.text.expand_variables(input1, context), expected1) def test_input2(self): context = PlumberyContext(dictionary={}) transformed = yaml.load(self.text.expand_variables(input2, context)) unmatched = {o : (input2[o], transformed[o]) for o in input2.keys() if input2[o] != transformed[o]} if unmatched != {}: print(unmatched) self.assertEqual(len(unmatched), 0) context = PlumberyContext(dictionary={ 'node.private': '12.34.56.78' }) transformed = yaml.load(self.text.expand_variables(input2, context)) unmatched = {o : (expected2[o], transformed[o]) for o in expected2.keys() if expected2[o] != transformed[o]} if unmatched != {}: print(unmatched) self.assertEqual(len(unmatched), 0) def test_input3(self): loaded = yaml.load(input3) context = PlumberyContext(dictionary={ 'node.public': '12.34.56.78' }) transformed = yaml.load(self.text.expand_variables(loaded, context)) self.assertEqual(transformed, yaml.load(expected3)) def test_input4(self): loaded = yaml.load(input4) context = PlumberyContext(dictionary={}) transformed = yaml.load(self.text.expand_variables(loaded, context)) self.assertEqual(transformed, loaded) def test_input5(self): loaded = yaml.load(input5) context = PlumberyContext(dictionary={}) transformed = yaml.load(self.text.expand_variables(loaded, context)) self.assertEqual(transformed, loaded) def test_input6(self): loaded = yaml.load(input6) context = PlumberyContext(dict6) transformed = self.text.expand_variables(loaded, context) self.assertEqual(transformed.strip(), expected6.strip()) def test_input7(self): loaded = yaml.load(input7) context = PlumberyContext(dict7) transformed = self.text.expand_variables(loaded, context) self.assertEqual(transformed.strip(), expected7.strip()) def test_input8(self): loaded = yaml.load(input8) context = PlumberyContext(dictionary={}) expanded = self.text.expand_variables(loaded, context) self.assertEqual(expanded.strip(), input8.strip()) def test_input9(self): loaded = yaml.load(input9) context = PlumberyContext(context=PlumberyEngine()) expanded = self.text.expand_variables(loaded, context) self.assertEqual((' - |' in expanded), False) def test_input10(self): loaded = yaml.load(input10) context = PlumberyContext(dictionary={}) expanded = self.text.expand_variables(loaded, context) self.assertEqual(expanded.strip(), input10.strip()) def test_node1(self): template = "{{ mongo_mongos01.public }}" context = PlumberyNodeContext(node=FakeNode1()) expected = '168.128.12.163' self.assertEqual( self.text.expand_variables(template, context), expected) template = "{{mongo_mongos01.private }}" expected = '192.168.50.11' self.assertEqual( self.text.expand_variables(template, context), expected) template = "{{ mongo_mongos01}}" expected = '192.168.50.11' self.assertEqual( self.text.expand_variables(template, context), expected) template = "{{ mongo_mongos01.ipv6 }}" expected = '2a00:47c0:111:1136:47c9:5a6a:911d:6c7f' self.assertEqual( self.text.expand_variables(template, context), expected) def test_node2(self): template = "{{ mongo_mongos02.public }}" context = PlumberyNodeContext(node=FakeNode1(), container=FakeContainer()) expected = '168.128.12.164' self.assertEqual( self.text.expand_variables(template, context), expected) template = "{{ mongo_mongos02.private }}" expected = '192.168.50.12' self.assertEqual( self.text.expand_variables(template, context), expected) template = "{{ mongo_mongos02 }}" expected = '192.168.50.12' self.assertEqual( self.text.expand_variables(template, context), expected) template = "{{ mongo_mongos02.ipv6 }}" expected = '2a00:47c0:111:1136:47c9:5a6a:911d:6c7f' self.assertEqual( self.text.expand_variables(template, context), expected)