From 3b8b46926b7ef46ac0ee73d51285dd274906e4f3 Mon Sep 17 00:00:00 2001 From: d1r3ct0r Date: Fri, 3 Feb 2023 05:08:22 +0300 Subject: cloud-id: better handling of change in datasource files Stop deleting cloud-id- unless there is a change in discovered datasource cloud-id. LP: #1998998 --- cloudinit/sources/__init__.py | 11 +++++++---- tests/integration_tests/modules/test_combined.py | 17 +++++++++++++++++ tests/unittests/sources/test_init.py | 10 +++++++--- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/cloudinit/sources/__init__.py b/cloudinit/sources/__init__.py index 85e094ac..12430401 100644 --- a/cloudinit/sources/__init__.py +++ b/cloudinit/sources/__init__.py @@ -435,12 +435,15 @@ class DataSource(CloudInitPickleMixin, metaclass=abc.ABCMeta): cloud_id = instance_data["v1"].get("cloud_id", "none") cloud_id_file = os.path.join(self.paths.run_dir, "cloud-id") util.write_file(f"{cloud_id_file}-{cloud_id}", f"{cloud_id}\n") + # cloud-id not found, then no previous cloud-id fle + prev_cloud_id_file = None + new_cloud_id_file = f"{cloud_id_file}-{cloud_id}" + # cloud-id found, then the prev cloud-id file is source of symlink if os.path.exists(cloud_id_file): prev_cloud_id_file = os.path.realpath(cloud_id_file) - else: - prev_cloud_id_file = cloud_id_file - util.sym_link(f"{cloud_id_file}-{cloud_id}", cloud_id_file, force=True) - if prev_cloud_id_file != cloud_id_file: + + util.sym_link(new_cloud_id_file, cloud_id_file, force=True) + if prev_cloud_id_file and prev_cloud_id_file != new_cloud_id_file: util.del_file(prev_cloud_id_file) write_json(json_sensitive_file, processed_data, mode=0o600) json_file = self.paths.get_runpath("instance_data") diff --git a/tests/integration_tests/modules/test_combined.py b/tests/integration_tests/modules/test_combined.py index 3c1013eb..647e8728 100644 --- a/tests/integration_tests/modules/test_combined.py +++ b/tests/integration_tests/modules/test_combined.py @@ -424,6 +424,23 @@ class TestCombined: assert v1_data["instance_id"] == client.instance.instance_id assert v1_data["local_hostname"] == client.instance.name + @pytest.mark.lxd_container + @pytest.mark.azure + @pytest.mark.gce + @pytest.mark.ec2 + def test_instance_cloud_id_across_reboot( + self, class_client: IntegrationInstance + ): + client = class_client + platform = client.settings.PLATFORM + cloud_id_alias = {"ec2": "aws", "lxd_container": "lxd"} + cloud_file = f"cloud-id-{cloud_id_alias.get(platform, platform)}" + assert client.execute(f"test -f /run/cloud-init/{cloud_file}").ok + assert client.execute("test -f /run/cloud-init/cloud-id").ok + client.restart() + assert client.execute(f"test -f /run/cloud-init/{cloud_file}").ok + assert client.execute("test -f /run/cloud-init/cloud-id").ok + @pytest.mark.user_data(USER_DATA) class TestCombinedNoCI: diff --git a/tests/unittests/sources/test_init.py b/tests/unittests/sources/test_init.py index a81c33a2..0447e02c 100644 --- a/tests/unittests/sources/test_init.py +++ b/tests/unittests/sources/test_init.py @@ -716,9 +716,13 @@ class TestDataSource(CiTestCase): "cloudinit.sources.canonical_cloud_id", return_value="my-cloud" ): datasource.get_data() - self.assertEqual("my-cloud\n", util.load_file(cloud_id_link)) - # A symlink with the generic /run/cloud-init/cloud-id link is present - self.assertTrue(util.is_link(cloud_id_link)) + self.assertEqual("my-cloud\n", util.load_file(cloud_id_link)) + # A symlink with the generic /run/cloud-init/cloud-id + # link is present + self.assertTrue(util.is_link(cloud_id_link)) + datasource.persist_instance_data() + # cloud-id not deleted: no cloud-id change + self.assertTrue(os.path.exists(cloud_id_file)) # When cloud-id changes, symlink and content change with mock.patch( "cloudinit.sources.canonical_cloud_id", return_value="my-cloud2" -- cgit v1.2.1