Check for existing symlink while force creating symlink#1281
Conversation
Traceback (most recent call last): |
|
Minimal program to reproduce the issue: |
|
@blackboxsw / @TheRealFalcon - Can you please take a look at this PR? |
smoser
left a comment
There was a problem hiding this comment.
I have a couple thoughts here.
- you might just be fixing a symptom of a different root cause issue
- It seems that create_symlink with force should do what you’re wanting it to.
- this may be related to some of the bugs referenced from https://bugs.launchpad.net/cloud-init/+bug/1883903
- your unit test is really testing 3 different behaviors all in one. We should split that test up into multiple tests with specific names. (source_exists, target_exists, source_exists_dangling …)
|
Possibly better test cases, or at least 4 of them vs 2: diff --git a/tests/unittests/test_util.py b/tests/unittests/test_util.py
index 53f322ed6..23439ccac 100644
--- a/tests/unittests/test_util.py
+++ b/tests/unittests/test_util.py
@@ -360,51 +360,47 @@ class TestUtil(CiTestCase):
is_rw = util.mount_is_read_write("/")
self.assertEqual(is_rw, False)
- def sym_link_test_helper(self):
- link = tempfile.mktemp()
- _, src = tempfile.mkstemp()
- util.del_file(link)
- util.sym_link(src, link)
- return link, src
+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")
- def test_sym_link_source_exists(self):
- exception = False
- link, src = self.sym_link_test_helper()
-
- # recreate symlink
- try:
- util.sym_link(src, link)
- except FileExistsError:
- exception = True
+ util.sym_link(target, link)
+ self.assertTrue(os.path.exists(link))
+ self.assertTrue(os.path.islink(link))
- assert exception
+ def test_sym_link_source_exists(self):
+ tmpd = self.tmp_dir()
+ oldlink = self.tmp_path("link", tmpd)
+ newlink = self.tmp_path("newlink", tmpd)
+ target = self.tmp_path("target", tmpd)
+ util.write_file(target, "hello")
+ os.symlink(target, oldlink)
- # force create
- try:
- util.sym_link(src, link, force=True)
- finally:
- util.del_file(link)
- util.del_file(src)
+ util.sym_link(target, newlink, force=True)
+ self.assertTrue(os.path.exists(newlink))
def test_sym_link_dangling_link(self):
- exception = False
- link, src = self.sym_link_test_helper()
-
- # make symlink dangling & recreate
- util.del_file(src)
- try:
- util.sym_link(src, link)
- except FileExistsError:
- exception = True
-
- assert exception
-
- # force recreate
- try:
- util.sym_link(src, link, force=True)
- finally:
- util.del_file(link)
+ tmpd = self.tmp_dir()
+ oldlink = self.tmp_path("link", tmpd)
+ newlink = self.tmp_path("newlink", tmpd)
+ target = self.tmp_path("target", tmpd)
+ os.symlink(target, oldlink)
+
+ util.sym_link(target, newlink, force=True)
+ self.assertTrue(os.path.islink(newlink))
+
+ 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): |
|
@smoser thanks for the assistance. I have updated the tests like you suggested. |
smoser
left a comment
There was a problem hiding this comment.
These changes seem sane to me.
|
Why not use |
holmanb
left a comment
There was a problem hiding this comment.
Could you please add a test that demonstrates how former behavior was flawed? I'd like to see a test that fails with the current (flawed) upstream behavior but succeeds with your "fix". If I revert your change in cloudinit/util.py but leave your new tests, none of the tests fail.
Fixed the tests. Please check now. |
If a dead symlink by the same name is present, os.path.exists returns false. Signed-off-by: Shreenidhi Shedi <sshedi@vmware.com> Signed-off-by: Shreenidhi Shedi <yesshedi@vmware.com>
blackboxsw
left a comment
There was a problem hiding this comment.
Agreed, this traceback would affect any system which detects a new or different datasource as the sym_link(force=True) would have failed with this traceback. Not an ideal failure path. and I agree with the fix and test coverage here.
|
Closed and re-opened to retrigger CI |
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>
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>
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>
If a dead symlink by the same name is present, os.path.exists returns
false.
Signed-off-by: Shreenidhi Shedi sshedi@vmware.com
Signed-off-by: Shreenidhi Shedi yesshedi@vmware.com
Proposed Commit Message
Additional Context
Test Steps
Checklist: