def _default_handlers(self, opts=None): if opts is None: opts = {} opts.update( { "paths": self.paths, "datasource": self.datasource, } ) # TODO(harlowja) Hmmm, should we dynamically import these?? cloudconfig_handler = CloudConfigPartHandler(**opts) shellscript_handler = ShellScriptPartHandler(**opts) def_handlers = [ cloudconfig_handler, shellscript_handler, ShellScriptByFreqPartHandler(PER_ALWAYS, **opts), ShellScriptByFreqPartHandler(PER_INSTANCE, **opts), ShellScriptByFreqPartHandler(PER_ONCE, **opts), BootHookPartHandler(**opts), UpstartJobPartHandler(**opts), ] opts.update( {"sub_handlers": [cloudconfig_handler, shellscript_handler]} ) def_handlers.append(JinjaTemplatePartHandler(**opts)) return def_handlers
def test_jinja_template_handle_renders_jinja_content_missing_keys(self): """When specified jinja variable is undefined, log a warning.""" script_handler = ShellScriptPartHandler(self.paths) instance_json = os.path.join(self.run_dir, INSTANCE_DATA_FILE) instance_data = {"topkey": {"subkey": "echo himom"}} util.write_file(instance_json, util.json_dumps(instance_data)) h = JinjaTemplatePartHandler(self.paths, sub_handlers=[script_handler]) h.handle_part( data="data", ctype="!" + handlers.CONTENT_START, filename="part01", payload="## template: jinja \n#!/bin/bash\n{{ goodtry }}", frequency="freq", headers="headers", ) script_file = os.path.join(script_handler.script_dir, "part01") self.assertTrue( os.path.exists(script_file), "Missing expected file %s" % script_file, ) self.assertIn( "WARNING: Could not render jinja template variables in file" " 'part01': 'goodtry'\n", self.logs.getvalue(), )
def test_jinja_template_handle_errors_on_unreadable_instance_data(self): """If instance-data is unreadable, raise an error from handle_part.""" script_handler = ShellScriptPartHandler(self.paths) instance_json = os.path.join(self.run_dir, INSTANCE_DATA_FILE) util.write_file(instance_json, util.json_dumps({})) h = JinjaTemplatePartHandler(self.paths, sub_handlers=[script_handler]) with mock.patch(self.mpath + "load_file") as m_load: with self.assertRaises(RuntimeError) as context_manager: m_load.side_effect = OSError(errno.EACCES, "Not allowed") h.handle_part( data="data", ctype="!" + handlers.CONTENT_START, filename="part01", payload="## template: jinja \n#!/bin/bash\necho himom", frequency="freq", headers="headers", ) script_file = os.path.join(script_handler.script_dir, "part01") self.assertEqual( "Cannot render jinja template vars. No read permission on " "'{}/{}'. Try sudo".format(self.run_dir, INSTANCE_DATA_FILE), str(context_manager.exception), ) self.assertFalse( os.path.exists(script_file), "Unexpected file created %s" % script_file, )
def test_jinja_template_handle_renders_jinja_content(self): """When present, render jinja variables from instance data""" script_handler = ShellScriptPartHandler(self.paths) instance_json = os.path.join(self.run_dir, INSTANCE_DATA_FILE) instance_data = {"topkey": {"subkey": "echo himom"}} util.write_file(instance_json, util.json_dumps(instance_data)) h = JinjaTemplatePartHandler(self.paths, sub_handlers=[script_handler]) h.handle_part( data="data", ctype="!" + handlers.CONTENT_START, filename="part01", payload=("## template: jinja \n" "#!/bin/bash\n" '{{ topkey.subkey|default("nosubkey") }}'), frequency="freq", headers="headers", ) script_file = os.path.join(script_handler.script_dir, "part01") self.assertNotIn( "Instance data not yet present at {}/{}".format( self.run_dir, INSTANCE_DATA_FILE), self.logs.getvalue(), ) self.assertEqual("#!/bin/bash\necho himom", util.load_file(script_file))
def test_jinja_template_part_handler_looks_up_subhandler_types(self): """When sub_handlers are passed, init lists types of subhandlers.""" script_handler = ShellScriptPartHandler(self.paths) cloudconfig_handler = CloudConfigPartHandler(self.paths) h = JinjaTemplatePartHandler( self.paths, sub_handlers=[script_handler, cloudconfig_handler]) self.assertCountEqual([ 'text/cloud-config', 'text/cloud-config-jsonp', 'text/x-shellscript' ], h.sub_handlers)
def test_jinja_template_handle_noop_on_content_signals(self): """Perform no part handling when content type is CONTENT_SIGNALS.""" script_handler = ShellScriptPartHandler(self.paths) h = JinjaTemplatePartHandler( self.paths, sub_handlers=[script_handler]) with mock.patch.object(script_handler, 'handle_part') as m_handle_part: h.handle_part( data='data', ctype=handlers.CONTENT_START, filename='part-1', payload='## template: jinja\n#!/bin/bash\necho himom', frequency='freq', headers='headers') m_handle_part.assert_not_called()
def test_jinja_template_handle_errors_on_missing_instance_data_json(self): """If instance-data is absent, raise an error from handle_part.""" script_handler = ShellScriptPartHandler(self.paths) h = JinjaTemplatePartHandler(self.paths, sub_handlers=[script_handler]) with self.assertRaises(RuntimeError) as context_manager: h.handle_part( data='data', ctype="!" + handlers.CONTENT_START, filename='part01', payload='## template: jinja \n#!/bin/bash\necho himom', frequency='freq', headers='headers') script_file = os.path.join(script_handler.script_dir, 'part01') self.assertEqual( 'Cannot render jinja template vars. Instance data not yet present' ' at {}/instance-data.json'.format(self.run_dir), str(context_manager.exception)) self.assertFalse(os.path.exists(script_file), 'Unexpected file created %s' % script_file)
def test_jinja_template_handle_renders_jinja_content_missing_keys(self): """When specified jinja variable is undefined, log a warning.""" script_handler = ShellScriptPartHandler(self.paths) instance_json = os.path.join(self.run_dir, 'instance-data.json') instance_data = {'topkey': {'subkey': 'echo himom'}} util.write_file(instance_json, util.json_dumps(instance_data)) h = JinjaTemplatePartHandler(self.paths, sub_handlers=[script_handler]) h.handle_part( data='data', ctype="!" + handlers.CONTENT_START, filename='part01', payload='## template: jinja \n#!/bin/bash\n{{ goodtry }}', frequency='freq', headers='headers') script_file = os.path.join(script_handler.script_dir, 'part01') self.assertTrue(os.path.exists(script_file), 'Missing expected file %s' % script_file) self.assertIn( "WARNING: Could not render jinja template variables in file" " 'part01': 'goodtry'\n", self.logs.getvalue())
def test_jinja_template_handle_subhandler_v2_with_clean_payload(self): """Call version 2 subhandler.handle_part with stripped payload.""" script_handler = ShellScriptPartHandler(self.paths) self.assertEqual(2, script_handler.handler_version) # Create required instance-data.json file instance_json = os.path.join(self.run_dir, 'instance-data.json') instance_data = {'topkey': 'echo himom'} util.write_file(instance_json, util.json_dumps(instance_data)) h = JinjaTemplatePartHandler( self.paths, sub_handlers=[script_handler]) with mock.patch.object(script_handler, 'handle_part') as m_part: # ctype with leading '!' not in handlers.CONTENT_SIGNALS h.handle_part( data='data', ctype="!" + handlers.CONTENT_START, filename='part01', payload='## template: jinja \t \n#!/bin/bash\n{{ topkey }}', frequency='freq', headers='headers') m_part.assert_called_once_with( 'data', '!__begin__', 'part01', '#!/bin/bash\necho himom', 'freq')
def _default_handlers(self, opts=None): if opts is None: opts = {} opts.update({ 'paths': self.paths, 'datasource': self.datasource, }) # TODO(harlowja) Hmmm, should we dynamically import these?? cloudconfig_handler = CloudConfigPartHandler(**opts) shellscript_handler = ShellScriptPartHandler(**opts) def_handlers = [ cloudconfig_handler, shellscript_handler, BootHookPartHandler(**opts), UpstartJobPartHandler(**opts), ] opts.update( {'sub_handlers': [cloudconfig_handler, shellscript_handler]}) def_handlers.append(JinjaTemplatePartHandler(**opts)) return def_handlers
def test_jinja_template_handle_renders_jinja_content(self): """When present, render jinja variables from instance-data.json.""" script_handler = ShellScriptPartHandler(self.paths) instance_json = os.path.join(self.run_dir, 'instance-data.json') instance_data = {'topkey': {'subkey': 'echo himom'}} util.write_file(instance_json, util.json_dumps(instance_data)) h = JinjaTemplatePartHandler(self.paths, sub_handlers=[script_handler]) h.handle_part(data='data', ctype="!" + handlers.CONTENT_START, filename='part01', payload=('## template: jinja \n' '#!/bin/bash\n' '{{ topkey.subkey|default("nosubkey") }}'), frequency='freq', headers='headers') script_file = os.path.join(script_handler.script_dir, 'part01') self.assertNotIn( 'Instance data not yet present at {}/instance-data.json'.format( self.run_dir), self.logs.getvalue()) self.assertEqual('#!/bin/bash\necho himom', util.load_file(script_file))
def test_jinja_template_handle_subhandler_v2_with_clean_payload(self): """Call version 2 subhandler.handle_part with stripped payload.""" script_handler = ShellScriptPartHandler(self.paths) self.assertEqual(2, script_handler.handler_version) # Create required instance data json file instance_json = os.path.join(self.run_dir, INSTANCE_DATA_FILE) instance_data = {"topkey": "echo himom"} util.write_file(instance_json, util.json_dumps(instance_data)) h = JinjaTemplatePartHandler(self.paths, sub_handlers=[script_handler]) with mock.patch.object(script_handler, "handle_part") as m_part: # ctype with leading '!' not in handlers.CONTENT_SIGNALS h.handle_part( data="data", ctype="!" + handlers.CONTENT_START, filename="part01", payload="## template: jinja \t \n#!/bin/bash\n{{ topkey }}", frequency="freq", headers="headers", ) m_part.assert_called_once_with("data", "!__begin__", "part01", "#!/bin/bash\necho himom", "freq")
def test_jinja_template_handle_errors_on_missing_instance_data_json(self): """If instance-data is absent, raise an error from handle_part.""" script_handler = ShellScriptPartHandler(self.paths) h = JinjaTemplatePartHandler(self.paths, sub_handlers=[script_handler]) with self.assertRaises(RuntimeError) as context_manager: h.handle_part( data="data", ctype="!" + handlers.CONTENT_START, filename="part01", payload="## template: jinja \n#!/bin/bash\necho himom", frequency="freq", headers="headers", ) script_file = os.path.join(script_handler.script_dir, "part01") self.assertEqual( "Cannot render jinja template vars. Instance data not yet present" " at {}/{}".format(self.run_dir, INSTANCE_DATA_FILE), str(context_manager.exception), ) self.assertFalse( os.path.exists(script_file), "Unexpected file created %s" % script_file, )
def test_jinja_template_handle_errors_on_unreadable_instance_data(self): """If instance-data is unreadable, raise an error from handle_part.""" script_handler = ShellScriptPartHandler(self.paths) instance_json = os.path.join(self.run_dir, 'instance-data.json') util.write_file(instance_json, util.json_dumps({})) h = JinjaTemplatePartHandler(self.paths, sub_handlers=[script_handler]) with mock.patch(self.mpath + 'load_file') as m_load: with self.assertRaises(RuntimeError) as context_manager: m_load.side_effect = OSError(errno.EACCES, 'Not allowed') h.handle_part( data='data', ctype="!" + handlers.CONTENT_START, filename='part01', payload='## template: jinja \n#!/bin/bash\necho himom', frequency='freq', headers='headers') script_file = os.path.join(script_handler.script_dir, 'part01') self.assertEqual( 'Cannot render jinja template vars. No read permission on' " '{rdir}/instance-data.json'. Try sudo".format(rdir=self.run_dir), str(context_manager.exception)) self.assertFalse(os.path.exists(script_file), 'Unexpected file created %s' % script_file)