From 56c88cafd1b3606e814069a79f4ec265fc427c87 Mon Sep 17 00:00:00 2001
From: James Falcon <james.falcon@canonical.com>
Date: Thu, 23 Mar 2023 10:21:56 -0500
Subject: [PATCH] Don't change permissions of netrules target (#2076)

Set permissions if file doesn't exist. Leave them if it does.

LP: #2011783

Co-authored-by: Chad Smith <chad.smith@canonical.com>
---
 cloudinit/net/eni.py                           |  3 ++-
 cloudinit/net/sysconfig.py                     |  2 +-
 tests/unittests/test_distros/test_netconfig.py | 17 ++++++++++++++---
 3 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/cloudinit/net/eni.py b/cloudinit/net/eni.py
index a89e5ad..2ce7c4f 100644
--- a/cloudinit/net/eni.py
+++ b/cloudinit/net/eni.py
@@ -525,7 +525,8 @@ class Renderer(renderer.Renderer):
             netrules = subp.target_path(target, self.netrules_path)
             util.ensure_dir(os.path.dirname(netrules))
             util.write_file(netrules,
-                            self._render_persistent_net(network_state))
+                            self._render_persistent_net(network_state),
+                            preserve_mode=True,)
 
 
 def network_state_to_eni(network_state, header=None, render_hwaddress=False):
diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py
index aa24303..afc9ca6 100644
--- a/cloudinit/net/sysconfig.py
+++ b/cloudinit/net/sysconfig.py
@@ -930,7 +930,7 @@ class Renderer(renderer.Renderer):
         if self.netrules_path:
             netrules_content = self._render_persistent_net(network_state)
             netrules_path = subp.target_path(target, self.netrules_path)
-            util.write_file(netrules_path, netrules_content, file_mode)
+            util.write_file(netrules_path, netrules_content, file_mode, preserve_mode=True)
         if available_nm(target=target):
             enable_ifcfg_rh(subp.target_path(
                 target, path=NM_CFG_FILE
diff --git a/tests/unittests/test_distros/test_netconfig.py b/tests/unittests/test_distros/test_netconfig.py
index 416667d..3f82d54 100644
--- a/tests/unittests/test_distros/test_netconfig.py
+++ b/tests/unittests/test_distros/test_netconfig.py
@@ -366,15 +366,22 @@ class TestNetCfgDistroUbuntuEni(TestNetCfgDistroBase):
     def eni_path(self):
         return '/etc/network/interfaces.d/50-cloud-init.cfg'
 
+    def rules_path(self):
+        return "/etc/udev/rules.d/70-persistent-net.rules"
+
     def _apply_and_verify_eni(self, apply_fn, config, expected_cfgs=None,
-                              bringup=False):
+                              bringup=False, previous_files=()):
         if not expected_cfgs:
             raise ValueError('expected_cfg must not be None')
 
         tmpd = None
         with mock.patch('cloudinit.net.eni.available') as m_avail:
             m_avail.return_value = True
+            path_modes = {}
             with self.reRooted(tmpd) as tmpd:
+                for previous_path, content, mode in previous_files:
+                    util.write_file(previous_path, content, mode=mode)
+                    path_modes[previous_path] = mode
                 apply_fn(config, bringup)
 
         results = dir2dict(tmpd)
@@ -385,15 +392,19 @@ class TestNetCfgDistroUbuntuEni(TestNetCfgDistroBase):
             print(results[cfgpath])
             print("----------")
             self.assertEqual(expected, results[cfgpath])
-            self.assertEqual(0o644, get_mode(cfgpath, tmpd))
+            self.assertEqual(
+                    path_modes.get(cfgpath, 0o644), get_mode(cfgpath, tmpd)
+            )
 
     def test_apply_network_config_eni_ub(self):
         expected_cfgs = {
             self.eni_path(): V1_NET_CFG_OUTPUT,
+            self.rules_path(): "",
         }
         self._apply_and_verify_eni(self.distro.apply_network_config,
                                    V1_NET_CFG,
-                                   expected_cfgs=expected_cfgs.copy())
+                                   expected_cfgs=expected_cfgs.copy(),
+                                   previous_files=((self.rules_path(), "something", 0o660),),)
 
     def test_apply_network_config_ipv6_ub(self):
         expected_cfgs = {
-- 
2.33.0

