def test_persist_instance_data_writes_network_json_when_set(self): """When network_data.json class attribute is set, persist to json.""" tmp = self.tmp_dir() datasource = DataSourceTestSubclassNet(self.sys_cfg, self.distro, Paths({"run_dir": tmp})) datasource.get_data() json_file = self.tmp_path(INSTANCE_JSON_FILE, tmp) instance_data = util.load_json(util.load_file(json_file)) self.assertNotIn("network_json", instance_data["ds"]) datasource.network_json = {"network_json": "is good"} datasource.persist_instance_data() instance_data = util.load_json(util.load_file(json_file)) self.assertEqual({"network_json": "is good"}, instance_data["ds"]["network_json"])
def test_get_hostname_without_metadata_returns_none(self): """Datasource.gethostname returns None when metadata_only and no MD.""" tmp = self.tmp_dir() datasource = DataSourceTestSubclassNet(self.sys_cfg, self.distro, Paths({"run_dir": tmp})) self.assertEqual({}, datasource.metadata) mock_fqdn = "cloudinit.sources.util.get_fqdn_from_hosts" with mock.patch("cloudinit.sources.util.get_hostname") as m_gethost: with mock.patch(mock_fqdn) as m_fqdn: self.assertIsNone(datasource.get_hostname(metadata_only=True)) self.assertIsNone( datasource.get_hostname(fqdn=True, metadata_only=True)) self.assertEqual([], m_gethost.call_args_list) self.assertEqual([], m_fqdn.call_args_list)
def test_get_hostname_without_metadata_prefers_etc_hosts(self): """Datasource.gethostname prefers /etc/hosts to util.get_hostname.""" tmp = self.tmp_dir() datasource = DataSourceTestSubclassNet(self.sys_cfg, self.distro, Paths({'run_dir': tmp})) self.assertEqual({}, datasource.metadata) mock_fqdn = 'cloudinit.sources.util.get_fqdn_from_hosts' with mock.patch('cloudinit.sources.util.get_hostname') as m_gethost: with mock.patch(mock_fqdn) as m_fqdn: m_gethost.return_value = 'systemhostname.domain.com' m_fqdn.return_value = 'fqdnhostname.domain.com' self.assertEqual('fqdnhostname', datasource.get_hostname()) self.assertEqual('fqdnhostname.domain.com', datasource.get_hostname(fqdn=True))
def test_get_hostname_without_metadata_uses_system_hostname(self): """Datasource.gethostname runs util.get_hostname when no metadata.""" tmp = self.tmp_dir() datasource = DataSourceTestSubclassNet(self.sys_cfg, self.distro, Paths({'run_dir': tmp})) self.assertEqual({}, datasource.metadata) mock_fqdn = 'cloudinit.sources.util.get_fqdn_from_hosts' with mock.patch('cloudinit.sources.util.get_hostname') as m_gethost: with mock.patch(mock_fqdn) as m_fqdn: m_gethost.return_value = 'systemhostname.domain.com' m_fqdn.return_value = None # No maching fqdn in /etc/hosts self.assertEqual('systemhostname', datasource.get_hostname()) self.assertEqual('systemhostname.domain.com', datasource.get_hostname(fqdn=True))
def test_get_data_calls_subclass__get_data(self): """Datasource.get_data uses the subclass' version of _get_data.""" tmp = self.tmp_dir() datasource = DataSourceTestSubclassNet(self.sys_cfg, self.distro, Paths({'run_dir': tmp})) self.assertTrue(datasource.get_data()) self.assertEqual( { 'availability_zone': 'myaz', 'local-hostname': 'test-subclass-hostname', 'region': 'myregion' }, datasource.metadata) self.assertEqual('userdata_raw', datasource.userdata_raw) self.assertEqual('vendordata_raw', datasource.vendordata_raw)
def test_get_data_handles_bytes_values(self): """On py2 get_data handles bytes values without having to b64encode.""" tmp = self.tmp_dir() datasource = DataSourceTestSubclassNet( self.sys_cfg, self.distro, Paths({'run_dir': tmp}), custom_userdata={'key1': 'val1', 'key2': {'key2.1': b'\x123'}}) self.assertTrue(datasource.get_data()) json_file = self.tmp_path(INSTANCE_JSON_FILE, tmp) content = util.load_file(json_file) instance_json = util.load_json(content) self.assertEqual([], instance_json['base64-encoded-keys']) self.assertEqual( {'key1': 'val1', 'key2': {'key2.1': '\x123'}}, instance_json['ds']['user-data'])
def test_get_data_writes_json_instance_data_sensitive(self): """ get_data writes unmodified data to sensitive file as root-readonly. """ tmp = self.tmp_dir() datasource = DataSourceTestSubclassNet( self.sys_cfg, self.distro, Paths({'run_dir': tmp}), custom_metadata={ 'availability_zone': 'myaz', 'local-hostname': 'test-subclass-hostname', 'region': 'myregion', 'some': {'security-credentials': { 'cred1': 'sekret', 'cred2': 'othersekret'}}}) self.assertEqual( ('security-credentials',), datasource.sensitive_metadata_keys) datasource.get_data() sensitive_json_file = self.tmp_path(INSTANCE_JSON_SENSITIVE_FILE, tmp) content = util.load_file(sensitive_json_file) expected = { 'base64_encoded_keys': [], 'sensitive_keys': ['ds/meta_data/some/security-credentials'], 'v1': { '_beta_keys': ['subplatform'], 'availability-zone': 'myaz', 'availability_zone': 'myaz', 'cloud-name': 'subclasscloudname', 'cloud_name': 'subclasscloudname', 'instance-id': 'iid-datasource', 'instance_id': 'iid-datasource', 'local-hostname': 'test-subclass-hostname', 'local_hostname': 'test-subclass-hostname', 'platform': 'mytestsubclass', 'public_ssh_keys': [], 'region': 'myregion', 'subplatform': 'unknown'}, 'ds': { '_doc': EXPERIMENTAL_TEXT, 'meta_data': { 'availability_zone': 'myaz', 'local-hostname': 'test-subclass-hostname', 'region': 'myregion', 'some': { 'security-credentials': {'cred1': 'sekret', 'cred2': 'othersekret'}}}} } self.assertEqual(expected, util.load_json(content)) file_stat = os.stat(sensitive_json_file) self.assertEqual(0o600, stat.S_IMODE(file_stat.st_mode)) self.assertEqual(expected, util.load_json(content))
def test_get_data_cloudinit_metadata_not_valid(self): """Test metadata is not JSON or YAML format.""" paths = Paths({"cloud_dir": self.tdir}) ds = self.datasource( sys_cfg={"disable_vmware_customization": True}, distro={}, paths=paths, ) # Prepare the conf file conf_file = self.tmp_path("test-cust", self.tdir) conf_content = dedent( """\ [CLOUDINIT] METADATA = test-meta """ ) util.write_file(conf_file, conf_content) # Prepare the meta data file metadata_file = self.tmp_path("test-meta", self.tdir) metadata_content = "[This is not json or yaml format]a=b" util.write_file(metadata_file, metadata_content) with mock.patch( MPATH + "set_customization_status", return_value=("msg", b"") ): with self.assertRaises(YAMLError) as context: wrap_and_call( "cloudinit.sources.DataSourceOVF", { "dmi.read_dmi_data": "vmware", "util.del_dir": True, "search_file": self.tdir, "wait_for_imc_cfg_file": conf_file, "collect_imc_file_paths": [ self.tdir + "/test-meta", "", "", ], "get_nics_to_enable": "", }, ds.get_data, ) self.assertIn( "expected '<document start>', but found '<scalar>'", str(context.exception), )
def test_persist_instance_data_writes_ec2_metadata_when_set(self): """When ec2_metadata class attribute is set, persist to json.""" tmp = self.tmp_dir() datasource = DataSourceTestSubclassNet(self.sys_cfg, self.distro, Paths({'run_dir': tmp})) datasource.ec2_metadata = UNSET datasource.get_data() json_file = self.tmp_path(INSTANCE_JSON_FILE, tmp) instance_data = util.load_json(util.load_file(json_file)) self.assertNotIn('ec2_metadata', instance_data['ds']) datasource.ec2_metadata = {'ec2stuff': 'is good'} datasource.persist_instance_data() instance_data = util.load_json(util.load_file(json_file)) self.assertEqual({'ec2stuff': 'is good'}, instance_data['ds']['ec2_metadata'])
def test_get_data_no_vmware_customization_disabled(self): """When vmware customization is disabled via sys_cfg log a message.""" paths = Paths({'cloud_dir': self.tdir}) ds = self.datasource(sys_cfg={'disable_vmware_customization': True}, distro={}, paths=paths) retcode = wrap_and_call( 'cloudinit.sources.DataSourceOVF', { 'dmi.read_dmi_data': 'vmware', 'transport_iso9660': NOT_FOUND, 'transport_vmware_guestinfo': NOT_FOUND }, ds.get_data) self.assertFalse(retcode, 'Expected False return from ds.get_data') self.assertIn('DEBUG: Customization for VMware platform is disabled.', self.logs.getvalue())
def test_get_data_cloudinit_metadata_yaml(self): """Test metadata can be loaded to cloud-init metadata and network. The metadata format is yaml. """ paths = Paths({'cloud_dir': self.tdir}) ds = self.datasource(sys_cfg={'disable_vmware_customization': True}, distro={}, paths=paths) # Prepare the conf file conf_file = self.tmp_path('test-cust', self.tdir) conf_content = dedent("""\ [CLOUDINIT] METADATA = test-meta """) util.write_file(conf_file, conf_content) # Prepare the meta data file metadata_file = self.tmp_path('test-meta', self.tdir) metadata_content = dedent("""\ instance-id: cloud-vm local-hostname: my-host.domain.com network: version: 2 ethernets: nics: match: name: ens* dhcp4: yes """) util.write_file(metadata_file, metadata_content) with mock.patch(MPATH + 'set_customization_status', return_value=('msg', b'')): result = wrap_and_call( 'cloudinit.sources.DataSourceOVF', { 'dmi.read_dmi_data': 'vmware', 'util.del_dir': True, 'search_file': self.tdir, 'wait_for_imc_cfg_file': conf_file, 'collect_imc_file_paths': [self.tdir + '/test-meta', '', ''], 'get_nics_to_enable': '' }, ds._get_data) self.assertTrue(result) self.assertEqual("cloud-vm", ds.metadata['instance-id']) self.assertEqual("my-host.domain.com", ds.metadata['local-hostname']) self.assertEqual(2, ds.network_config['version']) self.assertTrue(ds.network_config['ethernets']['nics']['dhcp4'])
def test_get_data_calls_subclass__get_data(self): """Datasource.get_data uses the subclass' version of _get_data.""" tmp = self.tmp_dir() datasource = DataSourceTestSubclassNet(self.sys_cfg, self.distro, Paths({"run_dir": tmp})) self.assertTrue(datasource.get_data()) self.assertEqual( { "availability_zone": "myaz", "local-hostname": "test-subclass-hostname", "region": "myregion", }, datasource.metadata, ) self.assertEqual("userdata_raw", datasource.userdata_raw) self.assertEqual("vendordata_raw", datasource.vendordata_raw)
def test_get_data_base64encodes_unserializable_bytes(self): """On py3, get_data base64encodes any unserializable content.""" tmp = self.tmp_dir() datasource = DataSourceTestSubclassNet( self.sys_cfg, self.distro, Paths({'run_dir': tmp}), custom_metadata={'key1': 'val1', 'key2': {'key2.1': b'\x123'}}) self.assertTrue(datasource.get_data()) json_file = self.tmp_path(INSTANCE_JSON_FILE, tmp) content = util.load_file(json_file) instance_json = util.load_json(content) self.assertCountEqual( ['ds/meta_data/key2/key2.1'], instance_json['base64_encoded_keys']) self.assertEqual( {'key1': 'val1', 'key2': {'key2.1': 'EjM='}}, instance_json['ds']['meta_data'])
def test_handle_args_root_uses_sensitive_instance_data( self, m_paths, tmpdir): """When root user, and no instance-data arg, use sensitive.json.""" user_data = tmpdir.join("user-data") write_file(user_data, "##template: jinja\nrendering: {{ my_var }}") run_dir = tmpdir.join("run_dir") ensure_dir(run_dir) json_sensitive = run_dir.join(INSTANCE_JSON_SENSITIVE_FILE) write_file(json_sensitive, '{"my-var": "jinja worked"}') m_paths.return_value = Paths({"run_dir": run_dir}) args = self.Args(user_data=user_data, instance_data=None, debug=False) with mock.patch("sys.stdout", new_callable=StringIO) as m_stdout: with mock.patch("os.getuid") as m_getuid: m_getuid.return_value = 0 assert render.handle_args("anyname", args) == 0 assert "rendering: jinja worked" in m_stdout.getvalue()
def test_handle_args_defaults_instance_data(self): """When no instance_data argument, default to configured run_dir.""" user_data = self.tmp_path('user-data', dir=self.tmp) run_dir = self.tmp_path('run_dir', dir=self.tmp) ensure_dir(run_dir) paths = Paths({'run_dir': run_dir}) self.add_patch('cloudinit.cmd.devel.render.read_cfg_paths', 'm_paths') self.m_paths.return_value = paths args = self.args( user_data=user_data, instance_data=None, debug=False) with mock.patch('sys.stderr', new_callable=StringIO): self.assertEqual(1, render.handle_args('anyname', args)) json_file = os.path.join(run_dir, INSTANCE_JSON_FILE) self.assertIn( 'Missing instance-data.json file: %s' % json_file, self.logs.getvalue())
def test_get_data_cloudinit_userdata_not_found(self): """Test userdata file can't be found. """ paths = Paths({'cloud_dir': self.tdir}) ds = self.datasource(sys_cfg={'disable_vmware_customization': True}, distro={}, paths=paths) # Prepare the conf file conf_file = self.tmp_path('test-cust', self.tdir) conf_content = dedent("""\ [CLOUDINIT] METADATA = test-meta USERDATA = test-user """) util.write_file(conf_file, conf_content) # Prepare the meta data file metadata_file = self.tmp_path('test-meta', self.tdir) metadata_content = dedent("""\ instance-id: cloud-vm local-hostname: my-host.domain.com network: version: 2 ethernets: nics: match: name: ens* dhcp4: yes """) util.write_file(metadata_file, metadata_content) # Don't prepare the user data file with mock.patch(MPATH + 'set_customization_status', return_value=('msg', b'')): with self.assertRaises(FileNotFoundError) as context: wrap_and_call( 'cloudinit.sources.DataSourceOVF', { 'dmi.read_dmi_data': 'vmware', 'util.del_dir': True, 'search_file': self.tdir, 'wait_for_imc_cfg_file': conf_file, 'get_nics_to_enable': '' }, ds.get_data) self.assertIn('is not found', str(context.exception))
def test_get_hostname_without_metadata_prefers_etc_hosts(self): """Datasource.gethostname prefers /etc/hosts to util.get_hostname.""" tmp = self.tmp_dir() datasource = DataSourceTestSubclassNet(self.sys_cfg, self.distro, Paths({"run_dir": tmp})) self.assertEqual({}, datasource.metadata) mock_fqdn = "cloudinit.sources.util.get_fqdn_from_hosts" with mock.patch("cloudinit.sources.util.get_hostname") as m_gethost: with mock.patch(mock_fqdn) as m_fqdn: m_gethost.return_value = "systemhostname.domain.com" m_fqdn.return_value = "fqdnhostname.domain.com" self.assertEqual("fqdnhostname", datasource.get_hostname().hostname) self.assertEqual( "fqdnhostname.domain.com", datasource.get_hostname(fqdn=True).hostname, )
def test_handle_args_root_fallback_from_sensitive_instance_data( self, m_paths, caplog, tmpdir): """When root user defaults to sensitive.json.""" user_data = tmpdir.join("user-data") run_dir = tmpdir.join("run_dir") ensure_dir(run_dir) m_paths.return_value = Paths({"run_dir": run_dir}) args = self.Args(user_data=user_data, instance_data=None, debug=False) with mock.patch("sys.stderr", new_callable=StringIO): with mock.patch("os.getuid") as m_getuid: m_getuid.return_value = 0 assert render.handle_args("anyname", args) == 1 json_file = run_dir.join(INSTANCE_JSON_FILE) json_sensitive = run_dir.join(INSTANCE_JSON_SENSITIVE_FILE) assert ("Missing root-readable %s. Using redacted %s" % (json_sensitive, json_file) in caplog.text) assert "Missing instance-data.json file: %s" % json_file in caplog.text
def test_get_data_handles_redacted_unserializable_content(self): """get_data warns unserializable content in INSTANCE_JSON_FILE.""" tmp = self.tmp_dir() datasource = DataSourceTestSubclassNet( self.sys_cfg, self.distro, Paths({'run_dir': tmp}), custom_metadata={'key1': 'val1', 'key2': {'key2.1': self.paths}}) datasource.get_data() json_file = self.tmp_path(INSTANCE_JSON_FILE, tmp) content = util.load_file(json_file) expected_metadata = { 'key1': 'val1', 'key2': { 'key2.1': "Warning: redacted unserializable type <class" " 'cloudinit.helpers.Paths'>"}} instance_json = util.load_json(content) self.assertEqual( expected_metadata, instance_json['ds']['meta_data'])
def test_non_utf8_encoding_gets_b64encoded(self): """When non-utf-8 values exist in py2 instance-data is b64encoded.""" tmp = self.tmp_dir() datasource = DataSourceTestSubclassNet(self.sys_cfg, self.distro, Paths({'run_dir': tmp}), custom_metadata={ 'key1': 'val1', 'key2': { 'key2.1': b'ab\xaadef' } }) self.assertTrue(datasource.get_data()) json_file = self.tmp_path(INSTANCE_JSON_FILE, tmp) instance_json = util.load_json(util.load_file(json_file)) key21_value = instance_json['ds']['meta_data']['key2']['key2.1'] self.assertEqual('ci-b64:' + util.b64e(b'ab\xaadef'), key21_value)
def test_get_data_false_on_none_dmi_data(self): """When dmi for system-product-name is None, get_data returns False.""" paths = Paths({"cloud_dir": self.tdir}) ds = self.datasource(sys_cfg={}, distro={}, paths=paths) retcode = wrap_and_call( "cloudinit.sources.DataSourceOVF", { "dmi.read_dmi_data": None, "transport_iso9660": NOT_FOUND, "transport_vmware_guestinfo": NOT_FOUND, }, ds.get_data, ) self.assertFalse(retcode, "Expected False return from ds.get_data") self.assertIn( "DEBUG: No system-product-name found", self.logs.getvalue() )
def test_get_data_cust_script_disabled(self): """If custom script is disabled by VMware tools configuration, raise a RuntimeError. """ paths = Paths({"cloud_dir": self.tdir}) ds = self.datasource( sys_cfg={"disable_vmware_customization": False}, distro={}, paths=paths, ) # Prepare the conf file conf_file = self.tmp_path("test-cust", self.tdir) conf_content = dedent( """\ [CUSTOM-SCRIPT] SCRIPT-NAME = test-script [MISC] MARKER-ID = 12345346 """ ) util.write_file(conf_file, conf_content) # Prepare the custom sript customscript = self.tmp_path("test-script", self.tdir) util.write_file(customscript, "This is the post cust script") with mock.patch(MPATH + "get_tools_config", return_value="invalid"): with mock.patch( MPATH + "set_customization_status", return_value=("msg", b"") ): with self.assertRaises(RuntimeError) as context: wrap_and_call( "cloudinit.sources.DataSourceOVF", { "dmi.read_dmi_data": "vmware", "util.del_dir": True, "search_file": self.tdir, "wait_for_imc_cfg_file": conf_file, "get_nics_to_enable": "", }, ds.get_data, ) self.assertIn( "Custom script is disabled by VM Administrator", str(context.exception), )
def test_get_data_cust_script_enabled(self): """If custom script is enabled by VMware tools configuration, execute the script. """ paths = Paths({"cloud_dir": self.tdir}) ds = self.datasource( sys_cfg={"disable_vmware_customization": False}, distro={}, paths=paths, ) # Prepare the conf file conf_file = self.tmp_path("test-cust", self.tdir) conf_content = dedent( """\ [CUSTOM-SCRIPT] SCRIPT-NAME = test-script [MISC] MARKER-ID = 12345346 """ ) util.write_file(conf_file, conf_content) # Mock custom script is enabled by return true when calling # get_tools_config with mock.patch(MPATH + "get_tools_config", return_value="true"): with mock.patch( MPATH + "set_customization_status", return_value=("msg", b"") ): with self.assertRaises(CustomScriptNotFound) as context: wrap_and_call( "cloudinit.sources.DataSourceOVF", { "dmi.read_dmi_data": "vmware", "util.del_dir": True, "search_file": self.tdir, "wait_for_imc_cfg_file": conf_file, "get_nics_to_enable": "", }, ds.get_data, ) # Verify custom script is trying to be executed customscript = self.tmp_path("test-script", self.tdir) self.assertIn( "Script %s not found!!" % customscript, str(context.exception) )
def test_handle_args_root_uses_sensitive_instance_data(self): """When root user, and no instance-data arg, use sensitive.json.""" user_data = self.tmp_path('user-data', dir=self.tmp) write_file(user_data, '##template: jinja\nrendering: {{ my_var }}') run_dir = self.tmp_path('run_dir', dir=self.tmp) ensure_dir(run_dir) json_sensitive = os.path.join(run_dir, INSTANCE_JSON_SENSITIVE_FILE) write_file(json_sensitive, '{"my-var": "jinja worked"}') paths = Paths({'run_dir': run_dir}) self.add_patch('cloudinit.cmd.devel.render.read_cfg_paths', 'm_paths') self.m_paths.return_value = paths args = self.args(user_data=user_data, instance_data=None, debug=False) with mock.patch('sys.stderr', new_callable=StringIO): with mock.patch('sys.stdout', new_callable=StringIO) as m_stdout: with mock.patch('os.getuid') as m_getuid: m_getuid.return_value = 0 self.assertEqual(0, render.handle_args('anyname', args)) self.assertIn('rendering: jinja worked', m_stdout.getvalue())
def test_get_data_force_run_post_script_is_yes(self): """If DEFAULT-RUN-POST-CUST-SCRIPT is yes, custom script could run if enable-custom-scripts is not defined in VM Tools configuration """ paths = Paths({'cloud_dir': self.tdir}) ds = self.datasource(sys_cfg={'disable_vmware_customization': False}, distro={}, paths=paths) # Prepare the conf file conf_file = self.tmp_path('test-cust', self.tdir) # set DEFAULT-RUN-POST-CUST-SCRIPT = yes so that enable-custom-scripts # default value is TRUE conf_content = dedent("""\ [CUSTOM-SCRIPT] SCRIPT-NAME = test-script [MISC] MARKER-ID = 12345346 DEFAULT-RUN-POST-CUST-SCRIPT = yes """) util.write_file(conf_file, conf_content) # Mock get_tools_config(section, key, defaultVal) to return # defaultVal def my_get_tools_config(*args, **kwargs): return args[2] with mock.patch(MPATH + 'get_tools_config', side_effect=my_get_tools_config): with mock.patch(MPATH + 'set_customization_status', return_value=('msg', b'')): with self.assertRaises(CustomScriptNotFound) as context: wrap_and_call( 'cloudinit.sources.DataSourceOVF', { 'dmi.read_dmi_data': 'vmware', 'util.del_dir': True, 'search_file': self.tdir, 'wait_for_imc_cfg_file': conf_file, 'get_nics_to_enable': '' }, ds.get_data) # Verify custom script still runs although it is # disabled by VMware Tools customscript = self.tmp_path('test-script', self.tdir) self.assertIn('Script %s not found!!' % customscript, str(context.exception))
def test_get_data_allow_raw_data_disabled(self): """When allow_raw_data is disabled via ds_cfg and meta data is found, log a message. """ paths = Paths({"cloud_dir": self.tdir}) ds = self.datasource( sys_cfg={ "disable_vmware_customization": False, "datasource": {"OVF": {"allow_raw_data": False}}, }, distro={}, paths=paths, ) # Prepare the conf file conf_file = self.tmp_path("test-cust", self.tdir) conf_content = dedent( """\ [CLOUDINIT] METADATA = test-meta """ ) util.write_file(conf_file, conf_content) # Prepare the meta data file metadata_file = self.tmp_path("test-meta", self.tdir) util.write_file(metadata_file, "This is meta data") retcode = wrap_and_call( "cloudinit.sources.DataSourceOVF", { "dmi.read_dmi_data": "vmware", "transport_iso9660": NOT_FOUND, "transport_vmware_guestinfo": NOT_FOUND, "util.del_dir": True, "search_file": self.tdir, "wait_for_imc_cfg_file": conf_file, "collect_imc_file_paths": [self.tdir + "/test-meta", "", ""], }, ds.get_data, ) self.assertFalse(retcode, "Expected False return from ds.get_data") self.assertIn( "DEBUG: Customization using raw data is disabled.", self.logs.getvalue(), )
def test_non_utf8_encoding_logs_warning(self): """When non-utf-8 values exist in py2 instance-data is not written.""" tmp = self.tmp_dir() datasource = DataSourceTestSubclassNet(self.sys_cfg, self.distro, Paths({'run_dir': tmp}), custom_userdata={ 'key1': 'val1', 'key2': { 'key2.1': b'ab\xaadef' } }) self.assertTrue(datasource.get_data()) json_file = self.tmp_path(INSTANCE_JSON_FILE, tmp) self.assertFalse(os.path.exists(json_file)) self.assertIn( "WARNING: Error persisting instance-data.json: 'utf8' codec can't" " decode byte 0xaa in position 2: invalid start byte", self.logs.getvalue())
def test_get_data_non_vmware_seed_platform_info(self): """Platform info properly reports when on non-vmware platforms.""" paths = Paths({'cloud_dir': self.tdir, 'run_dir': self.tdir}) # Write ovf-env.xml seed file seed_dir = self.tmp_path('seed', dir=self.tdir) ovf_env = self.tmp_path('ovf-env.xml', dir=seed_dir) util.write_file(ovf_env, OVF_ENV_CONTENT) ds = self.datasource(sys_cfg={}, distro={}, paths=paths) self.assertEqual('ovf', ds.cloud_name) self.assertEqual('ovf', ds.platform_type) with mock.patch(MPATH + 'dmi.read_dmi_data', return_value='!VMware'): with mock.patch(MPATH + 'transport_vmware_guestinfo') as m_guestd: with mock.patch(MPATH + 'transport_iso9660') as m_iso9660: m_iso9660.return_value = NOT_FOUND m_guestd.return_value = NOT_FOUND self.assertTrue(ds.get_data()) self.assertEqual('ovf (%s/seed/ovf-env.xml)' % self.tdir, ds.subplatform)
def test_handle_args_defaults_instance_data(self): """When no instance_data argument, default to configured run_dir.""" args = self.args( debug=False, dump_all=True, format=None, instance_data=None, list_keys=False, user_data=None, vendor_data=None, varname=None) run_dir = self.tmp_path('run_dir', dir=self.tmp) ensure_dir(run_dir) paths = Paths({'run_dir': run_dir}) self.add_patch('cloudinit.cmd.query.read_cfg_paths', 'm_paths') self.m_paths.return_value = paths with mock.patch('sys.stderr', new_callable=StringIO) as m_stderr: self.assertEqual(1, query.handle_args('anyname', args)) json_file = os.path.join(run_dir, INSTANCE_JSON_FILE) self.assertIn( 'ERROR: Missing instance-data file: %s' % json_file, self.logs.getvalue()) self.assertIn( 'ERROR: Missing instance-data file: %s' % json_file, m_stderr.getvalue())
def test_get_data_cloudinit_metadata_not_valid(self): """Test metadata is not JSON or YAML format. """ paths = Paths({'cloud_dir': self.tdir}) ds = self.datasource(sys_cfg={'disable_vmware_customization': True}, distro={}, paths=paths) # Prepare the conf file conf_file = self.tmp_path('test-cust', self.tdir) conf_content = dedent("""\ [CLOUDINIT] METADATA = test-meta """) util.write_file(conf_file, conf_content) # Prepare the meta data file metadata_file = self.tmp_path('test-meta', self.tdir) metadata_content = "[This is not json or yaml format]a=b" util.write_file(metadata_file, metadata_content) with mock.patch(MPATH + 'set_customization_status', return_value=('msg', b'')): with self.assertRaises(YAMLError) as context: wrap_and_call( 'cloudinit.sources.DataSourceOVF', { 'dmi.read_dmi_data': 'vmware', 'util.del_dir': True, 'search_file': self.tdir, 'wait_for_imc_cfg_file': conf_file, 'collect_imc_file_paths': [self.tdir + '/test-meta', '', ''], 'get_nics_to_enable': '' }, ds.get_data) self.assertIn("expected '<document start>', but found '<scalar>'", str(context.exception))