Blame cloudinit/sources/tests/test_init.py

Packit Service a04d08
# This file is part of cloud-init. See LICENSE file for license information.
Packit Service a04d08
Packit Service a04d08
import copy
Packit Service a04d08
import inspect
Packit Service a04d08
import os
Packit Service a04d08
import stat
Packit Service a04d08
Packit Service a04d08
from cloudinit.event import EventType
Packit Service a04d08
from cloudinit.helpers import Paths
Packit Service a04d08
from cloudinit import importer
Packit Service a04d08
from cloudinit.sources import (
Packit Service a04d08
    EXPERIMENTAL_TEXT, INSTANCE_JSON_FILE, INSTANCE_JSON_SENSITIVE_FILE,
Packit Service a04d08
    METADATA_UNKNOWN, REDACT_SENSITIVE_VALUE, UNSET, DataSource,
Packit Service a04d08
    canonical_cloud_id, redact_sensitive_keys)
Packit Service 751c4a
from cloudinit.tests.helpers import CiTestCase, mock
Packit Service a04d08
from cloudinit.user_data import UserDataProcessor
Packit Service a04d08
from cloudinit import util
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
class DataSourceTestSubclassNet(DataSource):
Packit Service a04d08
Packit Service a04d08
    dsname = 'MyTestSubclass'
Packit Service a04d08
    url_max_wait = 55
Packit Service a04d08
Packit Service a04d08
    def __init__(self, sys_cfg, distro, paths, custom_metadata=None,
Packit Service a04d08
                 custom_userdata=None, get_data_retval=True):
Packit Service a04d08
        super(DataSourceTestSubclassNet, self).__init__(
Packit Service a04d08
            sys_cfg, distro, paths)
Packit Service a04d08
        self._custom_userdata = custom_userdata
Packit Service a04d08
        self._custom_metadata = custom_metadata
Packit Service a04d08
        self._get_data_retval = get_data_retval
Packit Service a04d08
Packit Service a04d08
    def _get_cloud_name(self):
Packit Service a04d08
        return 'SubclassCloudName'
Packit Service a04d08
Packit Service a04d08
    def _get_data(self):
Packit Service a04d08
        if self._custom_metadata:
Packit Service a04d08
            self.metadata = self._custom_metadata
Packit Service a04d08
        else:
Packit Service a04d08
            self.metadata = {'availability_zone': 'myaz',
Packit Service a04d08
                             'local-hostname': 'test-subclass-hostname',
Packit Service a04d08
                             'region': 'myregion'}
Packit Service a04d08
        if self._custom_userdata:
Packit Service a04d08
            self.userdata_raw = self._custom_userdata
Packit Service a04d08
        else:
Packit Service a04d08
            self.userdata_raw = 'userdata_raw'
Packit Service a04d08
        self.vendordata_raw = 'vendordata_raw'
Packit Service a04d08
        return self._get_data_retval
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
class InvalidDataSourceTestSubclassNet(DataSource):
Packit Service a04d08
    pass
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
class TestDataSource(CiTestCase):
Packit Service a04d08
Packit Service a04d08
    with_logs = True
Packit Service 751c4a
    maxDiff = None
Packit Service a04d08
Packit Service a04d08
    def setUp(self):
Packit Service a04d08
        super(TestDataSource, self).setUp()
Packit Service a04d08
        self.sys_cfg = {'datasource': {'_undef': {'key1': False}}}
Packit Service a04d08
        self.distro = 'distrotest'  # generally should be a Distro object
Packit Service a04d08
        self.paths = Paths({})
Packit Service a04d08
        self.datasource = DataSource(self.sys_cfg, self.distro, self.paths)
Packit Service a04d08
Packit Service a04d08
    def test_datasource_init(self):
Packit Service a04d08
        """DataSource initializes metadata attributes, ds_cfg and ud_proc."""
Packit Service a04d08
        self.assertEqual(self.paths, self.datasource.paths)
Packit Service a04d08
        self.assertEqual(self.sys_cfg, self.datasource.sys_cfg)
Packit Service a04d08
        self.assertEqual(self.distro, self.datasource.distro)
Packit Service a04d08
        self.assertIsNone(self.datasource.userdata)
Packit Service a04d08
        self.assertEqual({}, self.datasource.metadata)
Packit Service a04d08
        self.assertIsNone(self.datasource.userdata_raw)
Packit Service a04d08
        self.assertIsNone(self.datasource.vendordata)
Packit Service a04d08
        self.assertIsNone(self.datasource.vendordata_raw)
Packit Service a04d08
        self.assertEqual({'key1': False}, self.datasource.ds_cfg)
Packit Service a04d08
        self.assertIsInstance(self.datasource.ud_proc, UserDataProcessor)
Packit Service a04d08
Packit Service a04d08
    def test_datasource_init_gets_ds_cfg_using_dsname(self):
Packit Service a04d08
        """Init uses DataSource.dsname for sourcing ds_cfg."""
Packit Service a04d08
        sys_cfg = {'datasource': {'MyTestSubclass': {'key2': False}}}
Packit Service a04d08
        distro = 'distrotest'  # generally should be a Distro object
Packit Service a04d08
        datasource = DataSourceTestSubclassNet(sys_cfg, distro, self.paths)
Packit Service a04d08
        self.assertEqual({'key2': False}, datasource.ds_cfg)
Packit Service a04d08
Packit Service a04d08
    def test_str_is_classname(self):
Packit Service a04d08
        """The string representation of the datasource is the classname."""
Packit Service a04d08
        self.assertEqual('DataSource', str(self.datasource))
Packit Service a04d08
        self.assertEqual(
Packit Service a04d08
            'DataSourceTestSubclassNet',
Packit Service a04d08
            str(DataSourceTestSubclassNet('', '', self.paths)))
Packit Service a04d08
Packit Service a04d08
    def test_datasource_get_url_params_defaults(self):
Packit Service a04d08
        """get_url_params default url config settings for the datasource."""
Packit Service a04d08
        params = self.datasource.get_url_params()
Packit Service a04d08
        self.assertEqual(params.max_wait_seconds, self.datasource.url_max_wait)
Packit Service a04d08
        self.assertEqual(params.timeout_seconds, self.datasource.url_timeout)
Packit Service a04d08
        self.assertEqual(params.num_retries, self.datasource.url_retries)
Packit Service a04d08
Packit Service a04d08
    def test_datasource_get_url_params_subclassed(self):
Packit Service a04d08
        """Subclasses can override get_url_params defaults."""
Packit Service a04d08
        sys_cfg = {'datasource': {'MyTestSubclass': {'key2': False}}}
Packit Service a04d08
        distro = 'distrotest'  # generally should be a Distro object
Packit Service a04d08
        datasource = DataSourceTestSubclassNet(sys_cfg, distro, self.paths)
Packit Service a04d08
        expected = (datasource.url_max_wait, datasource.url_timeout,
Packit Service a04d08
                    datasource.url_retries)
Packit Service a04d08
        url_params = datasource.get_url_params()
Packit Service a04d08
        self.assertNotEqual(self.datasource.get_url_params(), url_params)
Packit Service a04d08
        self.assertEqual(expected, url_params)
Packit Service a04d08
Packit Service a04d08
    def test_datasource_get_url_params_ds_config_override(self):
Packit Service a04d08
        """Datasource configuration options can override url param defaults."""
Packit Service a04d08
        sys_cfg = {
Packit Service a04d08
            'datasource': {
Packit Service a04d08
                'MyTestSubclass': {
Packit Service a04d08
                    'max_wait': '1', 'timeout': '2', 'retries': '3'}}}
Packit Service a04d08
        datasource = DataSourceTestSubclassNet(
Packit Service a04d08
            sys_cfg, self.distro, self.paths)
Packit Service a04d08
        expected = (1, 2, 3)
Packit Service a04d08
        url_params = datasource.get_url_params()
Packit Service a04d08
        self.assertNotEqual(
Packit Service a04d08
            (datasource.url_max_wait, datasource.url_timeout,
Packit Service a04d08
             datasource.url_retries),
Packit Service a04d08
            url_params)
Packit Service a04d08
        self.assertEqual(expected, url_params)
Packit Service a04d08
Packit Service a04d08
    def test_datasource_get_url_params_is_zero_or_greater(self):
Packit Service a04d08
        """get_url_params ignores timeouts with a value below 0."""
Packit Service a04d08
        # Set an override that is below 0 which gets ignored.
Packit Service a04d08
        sys_cfg = {'datasource': {'_undef': {'timeout': '-1'}}}
Packit Service a04d08
        datasource = DataSource(sys_cfg, self.distro, self.paths)
Packit Service a04d08
        (_max_wait, timeout, _retries) = datasource.get_url_params()
Packit Service a04d08
        self.assertEqual(0, timeout)
Packit Service a04d08
Packit Service a04d08
    def test_datasource_get_url_uses_defaults_on_errors(self):
Packit Service a04d08
        """On invalid system config values for url_params defaults are used."""
Packit Service a04d08
        # All invalid values should be logged
Packit Service a04d08
        sys_cfg = {'datasource': {
Packit Service a04d08
            '_undef': {
Packit Service a04d08
                'max_wait': 'nope', 'timeout': 'bug', 'retries': 'nonint'}}}
Packit Service a04d08
        datasource = DataSource(sys_cfg, self.distro, self.paths)
Packit Service a04d08
        url_params = datasource.get_url_params()
Packit Service a04d08
        expected = (datasource.url_max_wait, datasource.url_timeout,
Packit Service a04d08
                    datasource.url_retries)
Packit Service a04d08
        self.assertEqual(expected, url_params)
Packit Service a04d08
        logs = self.logs.getvalue()
Packit Service a04d08
        expected_logs = [
Packit Service a04d08
            "Config max_wait 'nope' is not an int, using default '-1'",
Packit Service a04d08
            "Config timeout 'bug' is not an int, using default '10'",
Packit Service a04d08
            "Config retries 'nonint' is not an int, using default '5'",
Packit Service a04d08
        ]
Packit Service a04d08
        for log in expected_logs:
Packit Service a04d08
            self.assertIn(log, logs)
Packit Service a04d08
Packit Service a04d08
    @mock.patch('cloudinit.sources.net.find_fallback_nic')
Packit Service a04d08
    def test_fallback_interface_is_discovered(self, m_get_fallback_nic):
Packit Service a04d08
        """The fallback_interface is discovered via find_fallback_nic."""
Packit Service a04d08
        m_get_fallback_nic.return_value = 'nic9'
Packit Service a04d08
        self.assertEqual('nic9', self.datasource.fallback_interface)
Packit Service a04d08
Packit Service a04d08
    @mock.patch('cloudinit.sources.net.find_fallback_nic')
Packit Service a04d08
    def test_fallback_interface_logs_undiscovered(self, m_get_fallback_nic):
Packit Service a04d08
        """Log a warning when fallback_interface can not discover the nic."""
Packit Service a04d08
        self.datasource._cloud_name = 'MySupahCloud'
Packit Service a04d08
        m_get_fallback_nic.return_value = None  # Couldn't discover nic
Packit Service a04d08
        self.assertIsNone(self.datasource.fallback_interface)
Packit Service a04d08
        self.assertEqual(
Packit Service a04d08
            'WARNING: Did not find a fallback interface on MySupahCloud.\n',
Packit Service a04d08
            self.logs.getvalue())
Packit Service a04d08
Packit Service a04d08
    @mock.patch('cloudinit.sources.net.find_fallback_nic')
Packit Service a04d08
    def test_wb_fallback_interface_is_cached(self, m_get_fallback_nic):
Packit Service a04d08
        """The fallback_interface is cached and won't be rediscovered."""
Packit Service a04d08
        self.datasource._fallback_interface = 'nic10'
Packit Service a04d08
        self.assertEqual('nic10', self.datasource.fallback_interface)
Packit Service a04d08
        m_get_fallback_nic.assert_not_called()
Packit Service a04d08
Packit Service a04d08
    def test__get_data_unimplemented(self):
Packit Service a04d08
        """Raise an error when _get_data is not implemented."""
Packit Service a04d08
        with self.assertRaises(NotImplementedError) as context_manager:
Packit Service a04d08
            self.datasource.get_data()
Packit Service a04d08
        self.assertIn(
Packit Service a04d08
            'Subclasses of DataSource must implement _get_data',
Packit Service a04d08
            str(context_manager.exception))
Packit Service a04d08
        datasource2 = InvalidDataSourceTestSubclassNet(
Packit Service a04d08
            self.sys_cfg, self.distro, self.paths)
Packit Service a04d08
        with self.assertRaises(NotImplementedError) as context_manager:
Packit Service a04d08
            datasource2.get_data()
Packit Service a04d08
        self.assertIn(
Packit Service a04d08
            'Subclasses of DataSource must implement _get_data',
Packit Service a04d08
            str(context_manager.exception))
Packit Service a04d08
Packit Service a04d08
    def test_get_data_calls_subclass__get_data(self):
Packit Service a04d08
        """Datasource.get_data uses the subclass' version of _get_data."""
Packit Service a04d08
        tmp = self.tmp_dir()
Packit Service a04d08
        datasource = DataSourceTestSubclassNet(
Packit Service a04d08
            self.sys_cfg, self.distro, Paths({'run_dir': tmp}))
Packit Service a04d08
        self.assertTrue(datasource.get_data())
Packit Service a04d08
        self.assertEqual(
Packit Service a04d08
            {'availability_zone': 'myaz',
Packit Service a04d08
             'local-hostname': 'test-subclass-hostname',
Packit Service a04d08
             'region': 'myregion'},
Packit Service a04d08
            datasource.metadata)
Packit Service a04d08
        self.assertEqual('userdata_raw', datasource.userdata_raw)
Packit Service a04d08
        self.assertEqual('vendordata_raw', datasource.vendordata_raw)
Packit Service a04d08
Packit Service a04d08
    def test_get_hostname_strips_local_hostname_without_domain(self):
Packit Service a04d08
        """Datasource.get_hostname strips metadata local-hostname of domain."""
Packit Service a04d08
        tmp = self.tmp_dir()
Packit Service a04d08
        datasource = DataSourceTestSubclassNet(
Packit Service a04d08
            self.sys_cfg, self.distro, Paths({'run_dir': tmp}))
Packit Service a04d08
        self.assertTrue(datasource.get_data())
Packit Service a04d08
        self.assertEqual(
Packit Service a04d08
            'test-subclass-hostname', datasource.metadata['local-hostname'])
Packit Service a04d08
        self.assertEqual('test-subclass-hostname', datasource.get_hostname())
Packit Service a04d08
        datasource.metadata['local-hostname'] = 'hostname.my.domain.com'
Packit Service a04d08
        self.assertEqual('hostname', datasource.get_hostname())
Packit Service a04d08
Packit Service a04d08
    def test_get_hostname_with_fqdn_returns_local_hostname_with_domain(self):
Packit Service a04d08
        """Datasource.get_hostname with fqdn set gets qualified hostname."""
Packit Service a04d08
        tmp = self.tmp_dir()
Packit Service a04d08
        datasource = DataSourceTestSubclassNet(
Packit Service a04d08
            self.sys_cfg, self.distro, Paths({'run_dir': tmp}))
Packit Service a04d08
        self.assertTrue(datasource.get_data())
Packit Service a04d08
        datasource.metadata['local-hostname'] = 'hostname.my.domain.com'
Packit Service a04d08
        self.assertEqual(
Packit Service a04d08
            'hostname.my.domain.com', datasource.get_hostname(fqdn=True))
Packit Service a04d08
Packit Service a04d08
    def test_get_hostname_without_metadata_uses_system_hostname(self):
Packit Service a04d08
        """Datasource.gethostname runs util.get_hostname when no metadata."""
Packit Service a04d08
        tmp = self.tmp_dir()
Packit Service a04d08
        datasource = DataSourceTestSubclassNet(
Packit Service a04d08
            self.sys_cfg, self.distro, Paths({'run_dir': tmp}))
Packit Service a04d08
        self.assertEqual({}, datasource.metadata)
Packit Service a04d08
        mock_fqdn = 'cloudinit.sources.util.get_fqdn_from_hosts'
Packit Service a04d08
        with mock.patch('cloudinit.sources.util.get_hostname') as m_gethost:
Packit Service a04d08
            with mock.patch(mock_fqdn) as m_fqdn:
Packit Service a04d08
                m_gethost.return_value = 'systemhostname.domain.com'
Packit Service a04d08
                m_fqdn.return_value = None  # No maching fqdn in /etc/hosts
Packit Service a04d08
                self.assertEqual('systemhostname', datasource.get_hostname())
Packit Service a04d08
                self.assertEqual(
Packit Service a04d08
                    'systemhostname.domain.com',
Packit Service a04d08
                    datasource.get_hostname(fqdn=True))
Packit Service a04d08
Packit Service a04d08
    def test_get_hostname_without_metadata_returns_none(self):
Packit Service a04d08
        """Datasource.gethostname returns None when metadata_only and no MD."""
Packit Service a04d08
        tmp = self.tmp_dir()
Packit Service a04d08
        datasource = DataSourceTestSubclassNet(
Packit Service a04d08
            self.sys_cfg, self.distro, Paths({'run_dir': tmp}))
Packit Service a04d08
        self.assertEqual({}, datasource.metadata)
Packit Service a04d08
        mock_fqdn = 'cloudinit.sources.util.get_fqdn_from_hosts'
Packit Service a04d08
        with mock.patch('cloudinit.sources.util.get_hostname') as m_gethost:
Packit Service a04d08
            with mock.patch(mock_fqdn) as m_fqdn:
Packit Service a04d08
                self.assertIsNone(datasource.get_hostname(metadata_only=True))
Packit Service a04d08
                self.assertIsNone(
Packit Service a04d08
                    datasource.get_hostname(fqdn=True, metadata_only=True))
Packit Service a04d08
        self.assertEqual([], m_gethost.call_args_list)
Packit Service a04d08
        self.assertEqual([], m_fqdn.call_args_list)
Packit Service a04d08
Packit Service a04d08
    def test_get_hostname_without_metadata_prefers_etc_hosts(self):
Packit Service a04d08
        """Datasource.gethostname prefers /etc/hosts to util.get_hostname."""
Packit Service a04d08
        tmp = self.tmp_dir()
Packit Service a04d08
        datasource = DataSourceTestSubclassNet(
Packit Service a04d08
            self.sys_cfg, self.distro, Paths({'run_dir': tmp}))
Packit Service a04d08
        self.assertEqual({}, datasource.metadata)
Packit Service a04d08
        mock_fqdn = 'cloudinit.sources.util.get_fqdn_from_hosts'
Packit Service a04d08
        with mock.patch('cloudinit.sources.util.get_hostname') as m_gethost:
Packit Service a04d08
            with mock.patch(mock_fqdn) as m_fqdn:
Packit Service a04d08
                m_gethost.return_value = 'systemhostname.domain.com'
Packit Service a04d08
                m_fqdn.return_value = 'fqdnhostname.domain.com'
Packit Service a04d08
                self.assertEqual('fqdnhostname', datasource.get_hostname())
Packit Service a04d08
                self.assertEqual('fqdnhostname.domain.com',
Packit Service a04d08
                                 datasource.get_hostname(fqdn=True))
Packit Service a04d08
Packit Service a04d08
    def test_get_data_does_not_write_instance_data_on_failure(self):
Packit Service a04d08
        """get_data does not write INSTANCE_JSON_FILE on get_data False."""
Packit Service a04d08
        tmp = self.tmp_dir()
Packit Service a04d08
        datasource = DataSourceTestSubclassNet(
Packit Service a04d08
            self.sys_cfg, self.distro, Paths({'run_dir': tmp}),
Packit Service a04d08
            get_data_retval=False)
Packit Service a04d08
        self.assertFalse(datasource.get_data())
Packit Service a04d08
        json_file = self.tmp_path(INSTANCE_JSON_FILE, tmp)
Packit Service a04d08
        self.assertFalse(
Packit Service a04d08
            os.path.exists(json_file), 'Found unexpected file %s' % json_file)
Packit Service a04d08
Packit Service a04d08
    def test_get_data_writes_json_instance_data_on_success(self):
Packit Service a04d08
        """get_data writes INSTANCE_JSON_FILE to run_dir as world readable."""
Packit Service a04d08
        tmp = self.tmp_dir()
Packit Service a04d08
        datasource = DataSourceTestSubclassNet(
Packit Service a04d08
            self.sys_cfg, self.distro, Paths({'run_dir': tmp}))
Packit Service 751c4a
        sys_info = {
Packit Service 751c4a
            "python": "3.7",
Packit Service 751c4a
            "platform":
Packit Service 751c4a
                "Linux-5.4.0-24-generic-x86_64-with-Ubuntu-20.04-focal",
Packit Service 751c4a
            "uname": ["Linux", "myhost", "5.4.0-24-generic", "SMP blah",
Packit Service 751c4a
                      "x86_64"],
Packit Service 751c4a
            "variant": "ubuntu", "dist": ["ubuntu", "20.04", "focal"]}
Packit Service 751c4a
        with mock.patch("cloudinit.util.system_info", return_value=sys_info):
Packit Service 751c4a
            datasource.get_data()
Packit Service a04d08
        json_file = self.tmp_path(INSTANCE_JSON_FILE, tmp)
Packit Service a04d08
        content = util.load_file(json_file)
Packit Service a04d08
        expected = {
Packit Service a04d08
            'base64_encoded_keys': [],
Packit Service 751c4a
            'merged_cfg': REDACT_SENSITIVE_VALUE,
Packit Service 751c4a
            'sensitive_keys': ['merged_cfg'],
Packit Service 751c4a
            'sys_info': sys_info,
Packit Service a04d08
            'v1': {
Packit Service a04d08
                '_beta_keys': ['subplatform'],
Packit Service a04d08
                'availability-zone': 'myaz',
Packit Service a04d08
                'availability_zone': 'myaz',
Packit Service a04d08
                'cloud-name': 'subclasscloudname',
Packit Service a04d08
                'cloud_name': 'subclasscloudname',
Packit Service 751c4a
                'distro': 'ubuntu',
Packit Service 751c4a
                'distro_release': 'focal',
Packit Service 751c4a
                'distro_version': '20.04',
Packit Service a04d08
                'instance-id': 'iid-datasource',
Packit Service a04d08
                'instance_id': 'iid-datasource',
Packit Service a04d08
                'local-hostname': 'test-subclass-hostname',
Packit Service a04d08
                'local_hostname': 'test-subclass-hostname',
Packit Service 751c4a
                'kernel_release': '5.4.0-24-generic',
Packit Service 751c4a
                'machine': 'x86_64',
Packit Service a04d08
                'platform': 'mytestsubclass',
Packit Service a04d08
                'public_ssh_keys': [],
Packit Service 751c4a
                'python_version': '3.7',
Packit Service a04d08
                'region': 'myregion',
Packit Service 751c4a
                'system_platform':
Packit Service 751c4a
                    'Linux-5.4.0-24-generic-x86_64-with-Ubuntu-20.04-focal',
Packit Service 751c4a
                'subplatform': 'unknown',
Packit Service 751c4a
                'variant': 'ubuntu'},
Packit Service a04d08
            'ds': {
Packit Service 751c4a
Packit Service a04d08
                '_doc': EXPERIMENTAL_TEXT,
Packit Service a04d08
                'meta_data': {'availability_zone': 'myaz',
Packit Service a04d08
                              'local-hostname': 'test-subclass-hostname',
Packit Service a04d08
                              'region': 'myregion'}}}
Packit Service a04d08
        self.assertEqual(expected, util.load_json(content))
Packit Service a04d08
        file_stat = os.stat(json_file)
Packit Service a04d08
        self.assertEqual(0o644, stat.S_IMODE(file_stat.st_mode))
Packit Service a04d08
        self.assertEqual(expected, util.load_json(content))
Packit Service a04d08
Packit Service 751c4a
    def test_get_data_writes_redacted_public_json_instance_data(self):
Packit Service 751c4a
        """get_data writes redacted content to public INSTANCE_JSON_FILE."""
Packit Service a04d08
        tmp = self.tmp_dir()
Packit Service a04d08
        datasource = DataSourceTestSubclassNet(
Packit Service a04d08
            self.sys_cfg, self.distro, Paths({'run_dir': tmp}),
Packit Service a04d08
            custom_metadata={
Packit Service a04d08
                'availability_zone': 'myaz',
Packit Service a04d08
                'local-hostname': 'test-subclass-hostname',
Packit Service a04d08
                'region': 'myregion',
Packit Service a04d08
                'some': {'security-credentials': {
Packit Service a04d08
                    'cred1': 'sekret', 'cred2': 'othersekret'}}})
Packit Service 751c4a
        self.assertCountEqual(
Packit Service 751c4a
            ('merged_cfg', 'security-credentials',),
Packit Service 751c4a
            datasource.sensitive_metadata_keys)
Packit Service 751c4a
        sys_info = {
Packit Service 751c4a
            "python": "3.7",
Packit Service 751c4a
            "platform":
Packit Service 751c4a
                "Linux-5.4.0-24-generic-x86_64-with-Ubuntu-20.04-focal",
Packit Service 751c4a
            "uname": ["Linux", "myhost", "5.4.0-24-generic", "SMP blah",
Packit Service 751c4a
                      "x86_64"],
Packit Service 751c4a
            "variant": "ubuntu", "dist": ["ubuntu", "20.04", "focal"]}
Packit Service 751c4a
        with mock.patch("cloudinit.util.system_info", return_value=sys_info):
Packit Service 751c4a
            datasource.get_data()
Packit Service 11b429
        json_file = self.tmp_path(INSTANCE_JSON_FILE, tmp)
Packit Service 11b429
        redacted = util.load_json(util.load_file(json_file))
Packit Service a04d08
        expected = {
Packit Service a04d08
            'base64_encoded_keys': [],
Packit Service 751c4a
            'merged_cfg': REDACT_SENSITIVE_VALUE,
Packit Service 751c4a
            'sensitive_keys': [
Packit Service 751c4a
                'ds/meta_data/some/security-credentials', 'merged_cfg'],
Packit Service 751c4a
            'sys_info': sys_info,
Packit Service a04d08
            'v1': {
Packit Service a04d08
                '_beta_keys': ['subplatform'],
Packit Service a04d08
                'availability-zone': 'myaz',
Packit Service a04d08
                'availability_zone': 'myaz',
Packit Service a04d08
                'cloud-name': 'subclasscloudname',
Packit Service a04d08
                'cloud_name': 'subclasscloudname',
Packit Service 751c4a
                'distro': 'ubuntu',
Packit Service 751c4a
                'distro_release': 'focal',
Packit Service 751c4a
                'distro_version': '20.04',
Packit Service a04d08
                'instance-id': 'iid-datasource',
Packit Service a04d08
                'instance_id': 'iid-datasource',
Packit Service a04d08
                'local-hostname': 'test-subclass-hostname',
Packit Service a04d08
                'local_hostname': 'test-subclass-hostname',
Packit Service 751c4a
                'kernel_release': '5.4.0-24-generic',
Packit Service 751c4a
                'machine': 'x86_64',
Packit Service a04d08
                'platform': 'mytestsubclass',
Packit Service a04d08
                'public_ssh_keys': [],
Packit Service 751c4a
                'python_version': '3.7',
Packit Service a04d08
                'region': 'myregion',
Packit Service 751c4a
                'system_platform':
Packit Service 751c4a
                    'Linux-5.4.0-24-generic-x86_64-with-Ubuntu-20.04-focal',
Packit Service 751c4a
                'subplatform': 'unknown',
Packit Service 751c4a
                'variant': 'ubuntu'},
Packit Service a04d08
            'ds': {
Packit Service a04d08
                '_doc': EXPERIMENTAL_TEXT,
Packit Service a04d08
                'meta_data': {
Packit Service a04d08
                    'availability_zone': 'myaz',
Packit Service a04d08
                    'local-hostname': 'test-subclass-hostname',
Packit Service a04d08
                    'region': 'myregion',
Packit Service 11b429
                    'some': {'security-credentials': REDACT_SENSITIVE_VALUE}}}
Packit Service a04d08
        }
Packit Service 751c4a
        self.assertCountEqual(expected, redacted)
Packit Service 751c4a
        file_stat = os.stat(json_file)
Packit Service 751c4a
        self.assertEqual(0o644, stat.S_IMODE(file_stat.st_mode))
Packit Service 751c4a
Packit Service 751c4a
    def test_get_data_writes_json_instance_data_sensitive(self):
Packit Service 751c4a
        """
Packit Service 751c4a
        get_data writes unmodified data to sensitive file as root-readonly.
Packit Service 751c4a
        """
Packit Service 751c4a
        tmp = self.tmp_dir()
Packit Service 751c4a
        datasource = DataSourceTestSubclassNet(
Packit Service 751c4a
            self.sys_cfg, self.distro, Paths({'run_dir': tmp}),
Packit Service 751c4a
            custom_metadata={
Packit Service 751c4a
                'availability_zone': 'myaz',
Packit Service 751c4a
                'local-hostname': 'test-subclass-hostname',
Packit Service 751c4a
                'region': 'myregion',
Packit Service 751c4a
                'some': {'security-credentials': {
Packit Service 751c4a
                    'cred1': 'sekret', 'cred2': 'othersekret'}}})
Packit Service 751c4a
        sys_info = {
Packit Service 751c4a
            "python": "3.7",
Packit Service 751c4a
            "platform":
Packit Service 751c4a
                "Linux-5.4.0-24-generic-x86_64-with-Ubuntu-20.04-focal",
Packit Service 751c4a
            "uname": ["Linux", "myhost", "5.4.0-24-generic", "SMP blah",
Packit Service 751c4a
                      "x86_64"],
Packit Service 751c4a
            "variant": "ubuntu", "dist": ["ubuntu", "20.04", "focal"]}
Packit Service 751c4a
Packit Service 751c4a
        self.assertCountEqual(
Packit Service 751c4a
            ('merged_cfg', 'security-credentials',),
Packit Service 751c4a
            datasource.sensitive_metadata_keys)
Packit Service 751c4a
        with mock.patch("cloudinit.util.system_info", return_value=sys_info):
Packit Service 751c4a
            datasource.get_data()
Packit Service 751c4a
        sensitive_json_file = self.tmp_path(INSTANCE_JSON_SENSITIVE_FILE, tmp)
Packit Service 751c4a
        content = util.load_file(sensitive_json_file)
Packit Service 751c4a
        expected = {
Packit Service 751c4a
            'base64_encoded_keys': [],
Packit Service 751c4a
            'merged_cfg': {
Packit Service 751c4a
                '_doc': (
Packit Service 751c4a
                    'Merged cloud-init system config from '
Packit Service 751c4a
                    '/etc/cloud/cloud.cfg and /etc/cloud/cloud.cfg.d/'
Packit Service 751c4a
                ),
Packit Service 751c4a
                'datasource': {'_undef': {'key1': False}}},
Packit Service 751c4a
            'sensitive_keys': [
Packit Service 751c4a
                'ds/meta_data/some/security-credentials', 'merged_cfg'],
Packit Service 751c4a
            'sys_info': sys_info,
Packit Service 751c4a
            'v1': {
Packit Service 751c4a
                '_beta_keys': ['subplatform'],
Packit Service 751c4a
                'availability-zone': 'myaz',
Packit Service 751c4a
                'availability_zone': 'myaz',
Packit Service 751c4a
                'cloud-name': 'subclasscloudname',
Packit Service 751c4a
                'cloud_name': 'subclasscloudname',
Packit Service 751c4a
                'distro': 'ubuntu',
Packit Service 751c4a
                'distro_release': 'focal',
Packit Service 751c4a
                'distro_version': '20.04',
Packit Service 751c4a
                'instance-id': 'iid-datasource',
Packit Service 751c4a
                'instance_id': 'iid-datasource',
Packit Service 751c4a
                'kernel_release': '5.4.0-24-generic',
Packit Service 751c4a
                'local-hostname': 'test-subclass-hostname',
Packit Service 751c4a
                'local_hostname': 'test-subclass-hostname',
Packit Service 751c4a
                'machine': 'x86_64',
Packit Service 751c4a
                'platform': 'mytestsubclass',
Packit Service 751c4a
                'public_ssh_keys': [],
Packit Service 751c4a
                'python_version': '3.7',
Packit Service 751c4a
                'region': 'myregion',
Packit Service 751c4a
                'subplatform': 'unknown',
Packit Service 751c4a
                'system_platform':
Packit Service 751c4a
                    'Linux-5.4.0-24-generic-x86_64-with-Ubuntu-20.04-focal',
Packit Service 751c4a
                'variant': 'ubuntu'},
Packit Service 751c4a
            'ds': {
Packit Service 751c4a
                '_doc': EXPERIMENTAL_TEXT,
Packit Service 751c4a
                'meta_data': {
Packit Service 751c4a
                    'availability_zone': 'myaz',
Packit Service 751c4a
                    'local-hostname': 'test-subclass-hostname',
Packit Service 751c4a
                    'region': 'myregion',
Packit Service 751c4a
                    'some': {
Packit Service 751c4a
                        'security-credentials':
Packit Service 751c4a
                            {'cred1': 'sekret', 'cred2': 'othersekret'}}}}
Packit Service 751c4a
        }
Packit Service 751c4a
        self.assertCountEqual(expected, util.load_json(content))
Packit Service a04d08
        file_stat = os.stat(sensitive_json_file)
Packit Service a04d08
        self.assertEqual(0o600, stat.S_IMODE(file_stat.st_mode))
Packit Service a04d08
        self.assertEqual(expected, util.load_json(content))
Packit Service a04d08
Packit Service a04d08
    def test_get_data_handles_redacted_unserializable_content(self):
Packit Service a04d08
        """get_data warns unserializable content in INSTANCE_JSON_FILE."""
Packit Service a04d08
        tmp = self.tmp_dir()
Packit Service a04d08
        datasource = DataSourceTestSubclassNet(
Packit Service a04d08
            self.sys_cfg, self.distro, Paths({'run_dir': tmp}),
Packit Service a04d08
            custom_metadata={'key1': 'val1', 'key2': {'key2.1': self.paths}})
Packit Service a04d08
        datasource.get_data()
Packit Service a04d08
        json_file = self.tmp_path(INSTANCE_JSON_FILE, tmp)
Packit Service a04d08
        content = util.load_file(json_file)
Packit Service a04d08
        expected_metadata = {
Packit Service a04d08
            'key1': 'val1',
Packit Service a04d08
            'key2': {
Packit Service a04d08
                'key2.1': "Warning: redacted unserializable type 
Packit Service a04d08
                          " 'cloudinit.helpers.Paths'>"}}
Packit Service a04d08
        instance_json = util.load_json(content)
Packit Service a04d08
        self.assertEqual(
Packit Service a04d08
            expected_metadata, instance_json['ds']['meta_data'])
Packit Service a04d08
Packit Service a04d08
    def test_persist_instance_data_writes_ec2_metadata_when_set(self):
Packit Service a04d08
        """When ec2_metadata class attribute is set, persist to json."""
Packit Service a04d08
        tmp = self.tmp_dir()
Packit Service a04d08
        datasource = DataSourceTestSubclassNet(
Packit Service a04d08
            self.sys_cfg, self.distro, Paths({'run_dir': tmp}))
Packit Service a04d08
        datasource.ec2_metadata = UNSET
Packit Service a04d08
        datasource.get_data()
Packit Service a04d08
        json_file = self.tmp_path(INSTANCE_JSON_FILE, tmp)
Packit Service a04d08
        instance_data = util.load_json(util.load_file(json_file))
Packit Service a04d08
        self.assertNotIn('ec2_metadata', instance_data['ds'])
Packit Service a04d08
        datasource.ec2_metadata = {'ec2stuff': 'is good'}
Packit Service a04d08
        datasource.persist_instance_data()
Packit Service a04d08
        instance_data = util.load_json(util.load_file(json_file))
Packit Service a04d08
        self.assertEqual(
Packit Service a04d08
            {'ec2stuff': 'is good'},
Packit Service a04d08
            instance_data['ds']['ec2_metadata'])
Packit Service a04d08
Packit Service a04d08
    def test_persist_instance_data_writes_network_json_when_set(self):
Packit Service a04d08
        """When network_data.json class attribute is set, persist to json."""
Packit Service a04d08
        tmp = self.tmp_dir()
Packit Service a04d08
        datasource = DataSourceTestSubclassNet(
Packit Service a04d08
            self.sys_cfg, self.distro, Paths({'run_dir': tmp}))
Packit Service a04d08
        datasource.get_data()
Packit Service a04d08
        json_file = self.tmp_path(INSTANCE_JSON_FILE, tmp)
Packit Service a04d08
        instance_data = util.load_json(util.load_file(json_file))
Packit Service a04d08
        self.assertNotIn('network_json', instance_data['ds'])
Packit Service a04d08
        datasource.network_json = {'network_json': 'is good'}
Packit Service a04d08
        datasource.persist_instance_data()
Packit Service a04d08
        instance_data = util.load_json(util.load_file(json_file))
Packit Service a04d08
        self.assertEqual(
Packit Service a04d08
            {'network_json': 'is good'},
Packit Service a04d08
            instance_data['ds']['network_json'])
Packit Service a04d08
Packit Service a04d08
    def test_get_data_base64encodes_unserializable_bytes(self):
Packit Service a04d08
        """On py3, get_data base64encodes any unserializable content."""
Packit Service a04d08
        tmp = self.tmp_dir()
Packit Service a04d08
        datasource = DataSourceTestSubclassNet(
Packit Service a04d08
            self.sys_cfg, self.distro, Paths({'run_dir': tmp}),
Packit Service a04d08
            custom_metadata={'key1': 'val1', 'key2': {'key2.1': b'\x123'}})
Packit Service a04d08
        self.assertTrue(datasource.get_data())
Packit Service a04d08
        json_file = self.tmp_path(INSTANCE_JSON_FILE, tmp)
Packit Service a04d08
        content = util.load_file(json_file)
Packit Service a04d08
        instance_json = util.load_json(content)
Packit Service 751c4a
        self.assertCountEqual(
Packit Service a04d08
            ['ds/meta_data/key2/key2.1'],
Packit Service a04d08
            instance_json['base64_encoded_keys'])
Packit Service a04d08
        self.assertEqual(
Packit Service a04d08
            {'key1': 'val1', 'key2': {'key2.1': 'EjM='}},
Packit Service a04d08
            instance_json['ds']['meta_data'])
Packit Service a04d08
Packit Service a04d08
    def test_get_hostname_subclass_support(self):
Packit Service a04d08
        """Validate get_hostname signature on all subclasses of DataSource."""
Packit Service 751c4a
        base_args = inspect.getfullargspec(DataSource.get_hostname)
Packit Service a04d08
        # Import all DataSource subclasses so we can inspect them.
Packit Service a04d08
        modules = util.find_modules(os.path.dirname(os.path.dirname(__file__)))
Packit Service a04d08
        for _loc, name in modules.items():
Packit Service a04d08
            mod_locs, _ = importer.find_module(name, ['cloudinit.sources'], [])
Packit Service a04d08
            if mod_locs:
Packit Service a04d08
                importer.import_module(mod_locs[0])
Packit Service a04d08
        for child in DataSource.__subclasses__():
Packit Service a04d08
            if 'Test' in child.dsname:
Packit Service a04d08
                continue
Packit Service a04d08
            self.assertEqual(
Packit Service a04d08
                base_args,
Packit Service 751c4a
                inspect.getfullargspec(child.get_hostname),
Packit Service a04d08
                '%s does not implement DataSource.get_hostname params'
Packit Service a04d08
                % child)
Packit Service a04d08
            for grandchild in child.__subclasses__():
Packit Service a04d08
                self.assertEqual(
Packit Service a04d08
                    base_args,
Packit Service 751c4a
                    inspect.getfullargspec(grandchild.get_hostname),
Packit Service a04d08
                    '%s does not implement DataSource.get_hostname params'
Packit Service a04d08
                    % grandchild)
Packit Service a04d08
Packit Service a04d08
    def test_clear_cached_attrs_resets_cached_attr_class_attributes(self):
Packit Service a04d08
        """Class attributes listed in cached_attr_defaults are reset."""
Packit Service a04d08
        count = 0
Packit Service a04d08
        # Setup values for all cached class attributes
Packit Service a04d08
        for attr, value in self.datasource.cached_attr_defaults:
Packit Service a04d08
            setattr(self.datasource, attr, count)
Packit Service a04d08
            count += 1
Packit Service a04d08
        self.datasource._dirty_cache = True
Packit Service a04d08
        self.datasource.clear_cached_attrs()
Packit Service a04d08
        for attr, value in self.datasource.cached_attr_defaults:
Packit Service a04d08
            self.assertEqual(value, getattr(self.datasource, attr))
Packit Service a04d08
Packit Service a04d08
    def test_clear_cached_attrs_noops_on_clean_cache(self):
Packit Service a04d08
        """Class attributes listed in cached_attr_defaults are reset."""
Packit Service a04d08
        count = 0
Packit Service a04d08
        # Setup values for all cached class attributes
Packit Service a04d08
        for attr, _ in self.datasource.cached_attr_defaults:
Packit Service a04d08
            setattr(self.datasource, attr, count)
Packit Service a04d08
            count += 1
Packit Service a04d08
        self.datasource._dirty_cache = False   # Fake clean cache
Packit Service a04d08
        self.datasource.clear_cached_attrs()
Packit Service a04d08
        count = 0
Packit Service a04d08
        for attr, _ in self.datasource.cached_attr_defaults:
Packit Service a04d08
            self.assertEqual(count, getattr(self.datasource, attr))
Packit Service a04d08
            count += 1
Packit Service a04d08
Packit Service a04d08
    def test_clear_cached_attrs_skips_non_attr_class_attributes(self):
Packit Service a04d08
        """Skip any cached_attr_defaults which aren't class attributes."""
Packit Service a04d08
        self.datasource._dirty_cache = True
Packit Service a04d08
        self.datasource.clear_cached_attrs()
Packit Service a04d08
        for attr in ('ec2_metadata', 'network_json'):
Packit Service a04d08
            self.assertFalse(hasattr(self.datasource, attr))
Packit Service a04d08
Packit Service a04d08
    def test_clear_cached_attrs_of_custom_attrs(self):
Packit Service a04d08
        """Custom attr_values can be passed to clear_cached_attrs."""
Packit Service a04d08
        self.datasource._dirty_cache = True
Packit Service a04d08
        cached_attr_name = self.datasource.cached_attr_defaults[0][0]
Packit Service a04d08
        setattr(self.datasource, cached_attr_name, 'himom')
Packit Service a04d08
        self.datasource.myattr = 'orig'
Packit Service a04d08
        self.datasource.clear_cached_attrs(
Packit Service a04d08
            attr_defaults=(('myattr', 'updated'),))
Packit Service a04d08
        self.assertEqual('himom', getattr(self.datasource, cached_attr_name))
Packit Service a04d08
        self.assertEqual('updated', self.datasource.myattr)
Packit Service a04d08
Packit Service a04d08
    def test_update_metadata_only_acts_on_supported_update_events(self):
Packit Service a04d08
        """update_metadata won't get_data on unsupported update events."""
Packit Service a04d08
        self.datasource.update_events['network'].discard(EventType.BOOT)
Packit Service a04d08
        self.assertEqual(
Packit Service a04d08
            {'network': set([EventType.BOOT_NEW_INSTANCE])},
Packit Service a04d08
            self.datasource.update_events)
Packit Service a04d08
Packit Service a04d08
        def fake_get_data():
Packit Service a04d08
            raise Exception('get_data should not be called')
Packit Service a04d08
Packit Service a04d08
        self.datasource.get_data = fake_get_data
Packit Service a04d08
        self.assertFalse(
Packit Service a04d08
            self.datasource.update_metadata(
Packit Service a04d08
                source_event_types=[EventType.BOOT]))
Packit Service a04d08
Packit Service a04d08
    def test_update_metadata_returns_true_on_supported_update_event(self):
Packit Service a04d08
        """update_metadata returns get_data response on supported events."""
Packit Service a04d08
Packit Service a04d08
        def fake_get_data():
Packit Service a04d08
            return True
Packit Service a04d08
Packit Service a04d08
        self.datasource.get_data = fake_get_data
Packit Service a04d08
        self.datasource._network_config = 'something'
Packit Service a04d08
        self.datasource._dirty_cache = True
Packit Service a04d08
        self.assertTrue(
Packit Service a04d08
            self.datasource.update_metadata(
Packit Service a04d08
                source_event_types=[
Packit Service a04d08
                    EventType.BOOT, EventType.BOOT_NEW_INSTANCE]))
Packit Service a04d08
        self.assertEqual(UNSET, self.datasource._network_config)
Packit Service a04d08
        self.assertIn(
Packit Service a04d08
            "DEBUG: Update datasource metadata and network config due to"
Packit Service a04d08
            " events: New instance first boot",
Packit Service a04d08
            self.logs.getvalue())
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
class TestRedactSensitiveData(CiTestCase):
Packit Service a04d08
Packit Service a04d08
    def test_redact_sensitive_data_noop_when_no_sensitive_keys_present(self):
Packit Service a04d08
        """When sensitive_keys is absent or empty from metadata do nothing."""
Packit Service a04d08
        md = {'my': 'data'}
Packit Service a04d08
        self.assertEqual(
Packit Service a04d08
            md, redact_sensitive_keys(md, redact_value='redacted'))
Packit Service a04d08
        md['sensitive_keys'] = []
Packit Service a04d08
        self.assertEqual(
Packit Service a04d08
            md, redact_sensitive_keys(md, redact_value='redacted'))
Packit Service a04d08
Packit Service a04d08
    def test_redact_sensitive_data_redacts_exact_match_name(self):
Packit Service a04d08
        """Only exact matched sensitive_keys are redacted from metadata."""
Packit Service a04d08
        md = {'sensitive_keys': ['md/secure'],
Packit Service a04d08
              'md': {'secure': 's3kr1t', 'insecure': 'publik'}}
Packit Service a04d08
        secure_md = copy.deepcopy(md)
Packit Service a04d08
        secure_md['md']['secure'] = 'redacted'
Packit Service a04d08
        self.assertEqual(
Packit Service a04d08
            secure_md,
Packit Service a04d08
            redact_sensitive_keys(md, redact_value='redacted'))
Packit Service a04d08
Packit Service a04d08
    def test_redact_sensitive_data_does_redacts_with_default_string(self):
Packit Service a04d08
        """When redact_value is absent, REDACT_SENSITIVE_VALUE is used."""
Packit Service a04d08
        md = {'sensitive_keys': ['md/secure'],
Packit Service a04d08
              'md': {'secure': 's3kr1t', 'insecure': 'publik'}}
Packit Service a04d08
        secure_md = copy.deepcopy(md)
Packit Service a04d08
        secure_md['md']['secure'] = 'redacted for non-root user'
Packit Service a04d08
        self.assertEqual(
Packit Service a04d08
            secure_md,
Packit Service a04d08
            redact_sensitive_keys(md))
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
class TestCanonicalCloudID(CiTestCase):
Packit Service a04d08
Packit Service a04d08
    def test_cloud_id_returns_platform_on_unknowns(self):
Packit Service a04d08
        """When region and cloud_name are unknown, return platform."""
Packit Service a04d08
        self.assertEqual(
Packit Service a04d08
            'platform',
Packit Service a04d08
            canonical_cloud_id(cloud_name=METADATA_UNKNOWN,
Packit Service a04d08
                               region=METADATA_UNKNOWN,
Packit Service a04d08
                               platform='platform'))
Packit Service a04d08
Packit Service a04d08
    def test_cloud_id_returns_platform_on_none(self):
Packit Service a04d08
        """When region and cloud_name are unknown, return platform."""
Packit Service a04d08
        self.assertEqual(
Packit Service a04d08
            'platform',
Packit Service a04d08
            canonical_cloud_id(cloud_name=None,
Packit Service a04d08
                               region=None,
Packit Service a04d08
                               platform='platform'))
Packit Service a04d08
Packit Service a04d08
    def test_cloud_id_returns_cloud_name_on_unknown_region(self):
Packit Service a04d08
        """When region is unknown, return cloud_name."""
Packit Service a04d08
        for region in (None, METADATA_UNKNOWN):
Packit Service a04d08
            self.assertEqual(
Packit Service a04d08
                'cloudname',
Packit Service a04d08
                canonical_cloud_id(cloud_name='cloudname',
Packit Service a04d08
                                   region=region,
Packit Service a04d08
                                   platform='platform'))
Packit Service a04d08
Packit Service a04d08
    def test_cloud_id_returns_platform_on_unknown_cloud_name(self):
Packit Service a04d08
        """When region is set but cloud_name is unknown return cloud_name."""
Packit Service a04d08
        self.assertEqual(
Packit Service a04d08
            'platform',
Packit Service a04d08
            canonical_cloud_id(cloud_name=METADATA_UNKNOWN,
Packit Service a04d08
                               region='region',
Packit Service a04d08
                               platform='platform'))
Packit Service a04d08
Packit Service a04d08
    def test_cloud_id_aws_based_on_region_and_cloud_name(self):
Packit Service a04d08
        """When cloud_name is aws, return proper cloud-id based on region."""
Packit Service a04d08
        self.assertEqual(
Packit Service a04d08
            'aws-china',
Packit Service a04d08
            canonical_cloud_id(cloud_name='aws',
Packit Service a04d08
                               region='cn-north-1',
Packit Service a04d08
                               platform='platform'))
Packit Service a04d08
        self.assertEqual(
Packit Service a04d08
            'aws',
Packit Service a04d08
            canonical_cloud_id(cloud_name='aws',
Packit Service a04d08
                               region='us-east-1',
Packit Service a04d08
                               platform='platform'))
Packit Service a04d08
        self.assertEqual(
Packit Service a04d08
            'aws-gov',
Packit Service a04d08
            canonical_cloud_id(cloud_name='aws',
Packit Service a04d08
                               region='us-gov-1',
Packit Service a04d08
                               platform='platform'))
Packit Service a04d08
        self.assertEqual(  # Overrideen non-aws cloud_name is returned
Packit Service a04d08
            '!aws',
Packit Service a04d08
            canonical_cloud_id(cloud_name='!aws',
Packit Service a04d08
                               region='us-gov-1',
Packit Service a04d08
                               platform='platform'))
Packit Service a04d08
Packit Service a04d08
    def test_cloud_id_azure_based_on_region_and_cloud_name(self):
Packit Service a04d08
        """Report cloud-id when cloud_name is azure and region is in china."""
Packit Service a04d08
        self.assertEqual(
Packit Service a04d08
            'azure-china',
Packit Service a04d08
            canonical_cloud_id(cloud_name='azure',
Packit Service a04d08
                               region='chinaeast',
Packit Service a04d08
                               platform='platform'))
Packit Service a04d08
        self.assertEqual(
Packit Service a04d08
            'azure',
Packit Service a04d08
            canonical_cloud_id(cloud_name='azure',
Packit Service a04d08
                               region='!chinaeast',
Packit Service a04d08
                               platform='platform'))
Packit Service a04d08
Packit Service a04d08
# vi: ts=4 expandtab