From 7e59cb3d7536d847a5138fe3702909c7af0812de Mon Sep 17 00:00:00 2001
From: Shreenidhi Shedi <53473811+sshedi@users.noreply.github.com>
Date: Fri, 25 Feb 2022 05:04:54 +0530
Subject: [PATCH 2/8] check for existing symlink while force creating symlink
 (#1281)

Reference:https://github.com/canonical/cloud-init/commit/2e17a0d626d41147b7d0822013e80179b3a81ee4
Conflict:(1)change cloudinit/tests/test_util.py not tests/unittests/test_util.py
(2) add "import os" in test

If a dead symlink by the same name is present, os.path.exists returns
false, use os.path.lexists instead.

Signed-off-by: Shreenidhi Shedi <sshedi@vmware.com>
---
 cloudinit/tests/test_util.py | 47 ++++++++++++++++++++++++++++++++++++
 cloudinit/util.py            |  2 +-
 2 files changed, 48 insertions(+), 1 deletion(-)

diff --git a/cloudinit/tests/test_util.py b/cloudinit/tests/test_util.py
index ab5eb35..671b8bc 100644
--- a/cloudinit/tests/test_util.py
+++ b/cloudinit/tests/test_util.py
@@ -7,6 +7,7 @@ import logging
 import json
 import platform
 import pytest
+import os
 
 import cloudinit.util as util
 from cloudinit import subp
@@ -312,6 +313,52 @@ class TestUtil(CiTestCase):
         self.assertEqual(is_rw, False)
 
 
+class TestSymlink(CiTestCase):
+    def test_sym_link_simple(self):
+        tmpd = self.tmp_dir()
+        link = self.tmp_path("link", tmpd)
+        target = self.tmp_path("target", tmpd)
+        util.write_file(target, "hello")
+
+        util.sym_link(target, link)
+        self.assertTrue(os.path.exists(link))
+        self.assertTrue(os.path.islink(link))
+
+    def test_sym_link_source_exists(self):
+        tmpd = self.tmp_dir()
+        link = self.tmp_path("link", tmpd)
+        target = self.tmp_path("target", tmpd)
+        util.write_file(target, "hello")
+
+        util.sym_link(target, link)
+        self.assertTrue(os.path.exists(link))
+
+        util.sym_link(target, link, force=True)
+        self.assertTrue(os.path.exists(link))
+
+    def test_sym_link_dangling_link(self):
+        tmpd = self.tmp_dir()
+        link = self.tmp_path("link", tmpd)
+        target = self.tmp_path("target", tmpd)
+
+        util.sym_link(target, link)
+        self.assertTrue(os.path.islink(link))
+        self.assertFalse(os.path.exists(link))
+
+        util.sym_link(target, link, force=True)
+        self.assertTrue(os.path.islink(link))
+        self.assertFalse(os.path.exists(link))
+
+    def test_sym_link_create_dangling(self):
+        tmpd = self.tmp_dir()
+        link = self.tmp_path("link", tmpd)
+        target = self.tmp_path("target", tmpd)
+
+        util.sym_link(target, link)
+        self.assertTrue(os.path.islink(link))
+        self.assertFalse(os.path.exists(link))
+
+
 class TestUptime(CiTestCase):
 
     @mock.patch('cloudinit.util.boottime')
diff --git a/cloudinit/util.py b/cloudinit/util.py
index 68c12f9..ef1b588 100644
--- a/cloudinit/util.py
+++ b/cloudinit/util.py
@@ -1779,7 +1779,7 @@ def is_link(path):
 
 def sym_link(source, link, force=False):
     LOG.debug("Creating symbolic link from %r => %r", link, source)
-    if force and os.path.exists(link):
+    if force and os.path.lexists(link):
         del_file(link)
     os.symlink(source, link)
 
-- 
2.40.0

