Blame SOURCES/0053-plugins-prefix-target-paths-with-self.sysroot.patch

0cd6dc
From c1557088c243d848b395e33b3becf61614c11bf1 Mon Sep 17 00:00:00 2001
0cd6dc
From: "Bryn M. Reeves" <bmr@redhat.com>
0cd6dc
Date: Fri, 23 Jan 2015 23:17:34 +0000
0cd6dc
Subject: [PATCH 53/93] [plugins] prefix target paths with self.sysroot
0cd6dc
0cd6dc
Prefix copyspecs with self.sysroot when using an alternate root
0cd6dc
path. Prefixes are applied before expanding copyspecs and the
0cd6dc
prefixed paths are stored as the 'srcpath' attribute in the
0cd6dc
archive. Destination paths in the report archive do not include
0cd6dc
the prefix.
0cd6dc
0cd6dc
Signed-off-by: Bryn M. Reeves <bmr@redhat.com>
0cd6dc
---
0cd6dc
 sos/plugins/__init__.py | 52 +++++++++++++++++++++++++++++++++++---------
0cd6dc
 tests/option_tests.py   |  3 ++-
0cd6dc
 tests/plugin_tests.py   | 57 ++++++++++++++++++++++++++++++++-----------------
0cd6dc
 3 files changed, 82 insertions(+), 30 deletions(-)
0cd6dc
0cd6dc
diff --git a/sos/plugins/__init__.py b/sos/plugins/__init__.py
0cd6dc
index 4fd85be..14136b4 100644
0cd6dc
--- a/sos/plugins/__init__.py
0cd6dc
+++ b/sos/plugins/__init__.py
0cd6dc
@@ -101,6 +101,7 @@ class Plugin(object):
0cd6dc
     files = ()
0cd6dc
     archive = None
0cd6dc
     profiles = ()
0cd6dc
+    sysroot = '/'
0cd6dc
 
0cd6dc
     def __init__(self, commons):
0cd6dc
         if not getattr(self, "option_list", False):
0cd6dc
@@ -117,6 +118,7 @@ class Plugin(object):
0cd6dc
         self.copy_paths = set()
0cd6dc
         self.copy_strings = []
0cd6dc
         self.collect_cmds = []
0cd6dc
+        self.sysroot = commons['sysroot']
0cd6dc
 
0cd6dc
         self.soslog = self.commons['soslog'] if 'soslog' in self.commons \
0cd6dc
             else logging.getLogger('sos')
0cd6dc
@@ -154,6 +156,19 @@ class Plugin(object):
0cd6dc
     def policy(self):
0cd6dc
         return self.commons["policy"]
0cd6dc
 
0cd6dc
+    def join_sysroot(self, path):
0cd6dc
+        if path[0] == os.sep:
0cd6dc
+            path = path[1:]
0cd6dc
+        return os.path.join(self.sysroot, path)
0cd6dc
+
0cd6dc
+    def strip_sysroot(self, path):
0cd6dc
+        if path.startswith(self.sysroot):
0cd6dc
+            return path[len(self.sysroot):]
0cd6dc
+        return path
0cd6dc
+
0cd6dc
+    def use_sysroot(self):
0cd6dc
+        return self.sysroot != os.path.abspath(os.sep)
0cd6dc
+
0cd6dc
     def is_installed(self, package_name):
0cd6dc
         '''Is the package $package_name installed?'''
0cd6dc
         return self.policy().pkg_by_name(package_name) is not None
0cd6dc
@@ -207,6 +222,7 @@ class Plugin(object):
0cd6dc
         '''
0cd6dc
         try:
0cd6dc
             path = self._get_dest_for_srcpath(srcpath)
0cd6dc
+            self._log_debug("substituting scrpath '%s'" % srcpath)
0cd6dc
             self._log_debug("substituting '%s' for '%s' in '%s'"
0cd6dc
                             % (subst, regexp, path))
0cd6dc
             if not path:
0cd6dc
@@ -257,8 +273,9 @@ class Plugin(object):
0cd6dc
         self._log_debug("copying link '%s' pointing to '%s' with isdir=%s"
0cd6dc
                         % (srcpath, linkdest, os.path.isdir(absdest)))
0cd6dc
 
0cd6dc
+        dstpath = self.strip_sysroot(srcpath)
0cd6dc
         # use the relative target path in the tarball
0cd6dc
-        self.archive.add_link(reldest, srcpath)
0cd6dc
+        self.archive.add_link(reldest, dstpath)
0cd6dc
 
0cd6dc
         if os.path.isdir(absdest):
0cd6dc
             self._log_debug("link '%s' is a directory, skipping..." % linkdest)
0cd6dc
@@ -268,10 +285,10 @@ class Plugin(object):
0cd6dc
         # to absolute paths to pass to _do_copy_path.
0cd6dc
         self._log_debug("normalized link target '%s' as '%s'"
0cd6dc
                         % (linkdest, absdest))
0cd6dc
-        self._do_copy_path(absdest)
0cd6dc
+        self._do_copy_path(self.join_sysroot(absdest))
0cd6dc
 
0cd6dc
         self.copied_files.append({'srcpath': srcpath,
0cd6dc
-                                  'dstpath': srcpath,
0cd6dc
+                                  'dstpath': dstpath,
0cd6dc
                                   'symlink': "yes",
0cd6dc
                                   'pointsto': linkdest})
0cd6dc
 
0cd6dc
@@ -282,6 +299,8 @@ class Plugin(object):
0cd6dc
             self._do_copy_path(os.path.join(srcpath, afile), dest=None)
0cd6dc
 
0cd6dc
     def _get_dest_for_srcpath(self, srcpath):
0cd6dc
+        if self.use_sysroot():
0cd6dc
+            srcpath = self.join_sysroot(srcpath)
0cd6dc
         for copied in self.copied_files:
0cd6dc
             if srcpath == copied["srcpath"]:
0cd6dc
                 return copied["dstpath"]
0cd6dc
@@ -309,6 +328,9 @@ class Plugin(object):
0cd6dc
         if not dest:
0cd6dc
             dest = srcpath
0cd6dc
 
0cd6dc
+        if self.use_sysroot():
0cd6dc
+            dest = self.strip_sysroot(dest)
0cd6dc
+
0cd6dc
         try:
0cd6dc
             st = os.lstat(srcpath)
0cd6dc
         except (OSError, IOError):
0cd6dc
@@ -327,7 +349,7 @@ class Plugin(object):
0cd6dc
         if not (stat.S_ISREG(st.st_mode) or stat.S_ISDIR(st.st_mode)):
0cd6dc
             ntype = _node_type(st)
0cd6dc
             self._log_debug("creating %s node at archive:'%s'"
0cd6dc
-                            % (ntype, srcpath))
0cd6dc
+                            % (ntype, dest))
0cd6dc
             self._copy_node(srcpath, st)
0cd6dc
             return
0cd6dc
 
0cd6dc
@@ -341,9 +363,11 @@ class Plugin(object):
0cd6dc
         else:
0cd6dc
             self.archive.add_file(srcpath, dest)
0cd6dc
 
0cd6dc
-        self.copied_files.append({'srcpath': srcpath,
0cd6dc
-                                  'dstpath': dest,
0cd6dc
-                                  'symlink': "no"})
0cd6dc
+        self.copied_files.append({
0cd6dc
+            'srcpath': srcpath,
0cd6dc
+            'dstpath': dest,
0cd6dc
+            'symlink': "no"
0cd6dc
+        })
0cd6dc
 
0cd6dc
     def add_forbidden_path(self, forbiddenPath):
0cd6dc
         """Specify a path to not copy, even if it's part of a copy_specs[]
0cd6dc
@@ -410,6 +434,9 @@ class Plugin(object):
0cd6dc
         except Exception:
0cd6dc
             return default
0cd6dc
 
0cd6dc
+    def _add_copy_paths(self, copy_paths):
0cd6dc
+        self.copy_paths.update(copy_paths)
0cd6dc
+
0cd6dc
     def add_copy_spec_limit(self, copyspec, sizelimit=None, tailit=True):
0cd6dc
         """Add a file or glob but limit it to sizelimit megabytes. If fname is
0cd6dc
         a single file the file will be tailed to meet sizelimit. If the first
0cd6dc
@@ -418,10 +445,13 @@ class Plugin(object):
0cd6dc
         if not (copyspec and len(copyspec)):
0cd6dc
             return False
0cd6dc
 
0cd6dc
+        if self.use_sysroot():
0cd6dc
+            copyspec = self.join_sysroot(copyspec)
0cd6dc
         files = glob.glob(copyspec)
0cd6dc
         files.sort()
0cd6dc
         if len(files) == 0:
0cd6dc
             return
0cd6dc
+
0cd6dc
         current_size = 0
0cd6dc
         limit_reached = False
0cd6dc
         sizelimit *= 1024 * 1024  # in MB
0cd6dc
@@ -432,7 +462,7 @@ class Plugin(object):
0cd6dc
             if sizelimit and current_size > sizelimit:
0cd6dc
                 limit_reached = True
0cd6dc
                 break
0cd6dc
-            self.add_copy_spec(_file)
0cd6dc
+            self._add_copy_paths([_file])
0cd6dc
 
0cd6dc
         if limit_reached and tailit:
0cd6dc
             file_name = _file
0cd6dc
@@ -453,12 +483,14 @@ class Plugin(object):
0cd6dc
         if isinstance(copyspecs, six.string_types):
0cd6dc
             copyspecs = [copyspecs]
0cd6dc
         for copyspec in copyspecs:
0cd6dc
+            if self.use_sysroot():
0cd6dc
+                copyspec = self.join_sysroot(copyspec)
0cd6dc
             if not (copyspec and len(copyspec)):
0cd6dc
                 self._log_warn("added null or empty copy spec")
0cd6dc
                 return False
0cd6dc
             copy_paths = self._expand_copy_spec(copyspec)
0cd6dc
-            self.copy_paths.update(copy_paths)
0cd6dc
-            self._log_info("added copyspec '%s'" % copyspec)
0cd6dc
+            self._add_copy_paths(copy_paths)
0cd6dc
+            self._log_info("added copyspec '%s'" % copy_paths)
0cd6dc
 
0cd6dc
     def get_command_output(self, prog, timeout=300, runat=None):
0cd6dc
         result = sos_get_command_output(prog, timeout=timeout, runat=runat)
0cd6dc
diff --git a/tests/option_tests.py b/tests/option_tests.py
0cd6dc
index 3185bce..32f8e03 100644
0cd6dc
--- a/tests/option_tests.py
0cd6dc
+++ b/tests/option_tests.py
0cd6dc
@@ -8,10 +8,11 @@ class GlobalOptionTest(unittest.TestCase):
0cd6dc
 
0cd6dc
     def setUp(self):
0cd6dc
         self.commons = {
0cd6dc
+            'sysroot': '/',
0cd6dc
             'global_plugin_options': {
0cd6dc
                 'test_option': 'foobar',
0cd6dc
                 'baz': None,
0cd6dc
-                'empty_global': True,
0cd6dc
+                'empty_global': True
0cd6dc
             },
0cd6dc
         }
0cd6dc
         self.plugin = Plugin(self.commons)
0cd6dc
diff --git a/tests/plugin_tests.py b/tests/plugin_tests.py
0cd6dc
index 7364eff..2fd0fff 100644
0cd6dc
--- a/tests/plugin_tests.py
0cd6dc
+++ b/tests/plugin_tests.py
0cd6dc
@@ -127,50 +127,53 @@ class PluginToolTests(unittest.TestCase):
0cd6dc
 
0cd6dc
 class PluginTests(unittest.TestCase):
0cd6dc
 
0cd6dc
+    sysroot = os.getcwd()
0cd6dc
+
0cd6dc
     def setUp(self):
0cd6dc
         self.mp = MockPlugin({
0cd6dc
-            'cmdlineopts': MockOptions()
0cd6dc
+            'cmdlineopts': MockOptions(),
0cd6dc
+            'sysroot': self.sysroot
0cd6dc
         })
0cd6dc
         self.mp.archive = MockArchive()
0cd6dc
 
0cd6dc
     def test_plugin_default_name(self):
0cd6dc
-        p = MockPlugin({})
0cd6dc
+        p = MockPlugin({'sysroot': self.sysroot})
0cd6dc
         self.assertEquals(p.name(), "mockplugin")
0cd6dc
 
0cd6dc
     def test_plugin_set_name(self):
0cd6dc
-        p = NamedMockPlugin({})
0cd6dc
+        p = NamedMockPlugin({'sysroot': self.sysroot})
0cd6dc
         self.assertEquals(p.name(), "testing")
0cd6dc
 
0cd6dc
     def test_plugin_no_descrip(self):
0cd6dc
-        p = MockPlugin({})
0cd6dc
+        p = MockPlugin({'sysroot': self.sysroot})
0cd6dc
         self.assertEquals(p.get_description(), "<no description available>")
0cd6dc
 
0cd6dc
     def test_plugin_no_descrip(self):
0cd6dc
-        p = NamedMockPlugin({})
0cd6dc
+        p = NamedMockPlugin({'sysroot': self.sysroot})
0cd6dc
         self.assertEquals(p.get_description(), "This plugin has a description.")
0cd6dc
 
0cd6dc
     def test_set_plugin_option(self):
0cd6dc
-        p = MockPlugin({})
0cd6dc
+        p = MockPlugin({'sysroot': self.sysroot})
0cd6dc
         p.set_option("opt", "testing")
0cd6dc
         self.assertEquals(p.get_option("opt"), "testing")
0cd6dc
 
0cd6dc
     def test_set_nonexistant_plugin_option(self):
0cd6dc
-        p = MockPlugin({})
0cd6dc
+        p = MockPlugin({'sysroot': self.sysroot})
0cd6dc
         self.assertFalse(p.set_option("badopt", "testing"))
0cd6dc
 
0cd6dc
     def test_get_nonexistant_plugin_option(self):
0cd6dc
-        p = MockPlugin({})
0cd6dc
+        p = MockPlugin({'sysroot': self.sysroot})
0cd6dc
         self.assertEquals(p.get_option("badopt"), 0)
0cd6dc
 
0cd6dc
     def test_get_unset_plugin_option(self):
0cd6dc
-        p = MockPlugin({})
0cd6dc
+        p = MockPlugin({'sysroot': self.sysroot})
0cd6dc
         self.assertEquals(p.get_option("opt"), 0)
0cd6dc
 
0cd6dc
     def test_get_unset_plugin_option_with_default(self):
0cd6dc
         # this shows that even when we pass in a default to get,
0cd6dc
         # we'll get the option's default as set in the plugin
0cd6dc
         # this might not be what we really want
0cd6dc
-        p = MockPlugin({})
0cd6dc
+        p = MockPlugin({'sysroot': self.sysroot})
0cd6dc
         self.assertEquals(p.get_option("opt", True), True)
0cd6dc
 
0cd6dc
     def test_get_unset_plugin_option_with_default_not_none(self):
0cd6dc
@@ -178,20 +181,20 @@ class PluginTests(unittest.TestCase):
0cd6dc
         # if the plugin default is not None
0cd6dc
         # we'll get the option's default as set in the plugin
0cd6dc
         # this might not be what we really want
0cd6dc
-        p = MockPlugin({})
0cd6dc
+        p = MockPlugin({'sysroot': self.sysroot})
0cd6dc
         self.assertEquals(p.get_option("opt2", True), False)
0cd6dc
 
0cd6dc
     def test_get_option_as_list_plugin_option(self):
0cd6dc
-        p = MockPlugin({})
0cd6dc
+        p = MockPlugin({'sysroot': self.sysroot})
0cd6dc
         p.set_option("opt", "one,two,three")
0cd6dc
         self.assertEquals(p.get_option_as_list("opt"), ['one', 'two', 'three'])
0cd6dc
 
0cd6dc
     def test_get_option_as_list_plugin_option_default(self):
0cd6dc
-        p = MockPlugin({})
0cd6dc
+        p = MockPlugin({'sysroot': self.sysroot})
0cd6dc
         self.assertEquals(p.get_option_as_list("opt", default=[]), [])
0cd6dc
 
0cd6dc
     def test_get_option_as_list_plugin_option_not_list(self):
0cd6dc
-        p = MockPlugin({})
0cd6dc
+        p = MockPlugin({'sysroot': self.sysroot})
0cd6dc
         p.set_option("opt", "testing")
0cd6dc
         self.assertEquals(p.get_option_as_list("opt"), ['testing'])
0cd6dc
 
0cd6dc
@@ -205,7 +208,8 @@ class PluginTests(unittest.TestCase):
0cd6dc
 
0cd6dc
     def test_copy_dir_forbidden_path(self):
0cd6dc
         p = ForbiddenMockPlugin({
0cd6dc
-            'cmdlineopts': MockOptions()
0cd6dc
+            'cmdlineopts': MockOptions(),
0cd6dc
+            'sysroot': self.sysroot
0cd6dc
         })
0cd6dc
         p.archive = MockArchive()
0cd6dc
         p.setup()
0cd6dc
@@ -219,12 +223,18 @@ class AddCopySpecTests(unittest.TestCase):
0cd6dc
 
0cd6dc
     def setUp(self):
0cd6dc
         self.mp = MockPlugin({
0cd6dc
-            'cmdlineopts': MockOptions()
0cd6dc
+            'cmdlineopts': MockOptions(),
0cd6dc
+            'sysroot': os.getcwd()
0cd6dc
         })
0cd6dc
         self.mp.archive = MockArchive()
0cd6dc
 
0cd6dc
     def assert_expect_paths(self):
0cd6dc
-        self.assertEquals(self.mp.copy_paths, self.expect_paths)
0cd6dc
+        def pathmunge(path):
0cd6dc
+            if path[0] == '/':
0cd6dc
+                path = path[1:]
0cd6dc
+            return os.path.join(self.mp.sysroot, path)
0cd6dc
+        expected_paths = set(map(pathmunge, self.expect_paths))
0cd6dc
+        self.assertEquals(self.mp.copy_paths, expected_paths)
0cd6dc
         
0cd6dc
     # add_copy_spec()
0cd6dc
 
0cd6dc
@@ -242,6 +252,7 @@ class AddCopySpecTests(unittest.TestCase):
0cd6dc
     # add_copy_spec_limit()
0cd6dc
 
0cd6dc
     def test_single_file_over_limit(self):
0cd6dc
+        self.mp.sysroot = '/'
0cd6dc
         fn = create_file(2) # create 2MB file, consider a context manager
0cd6dc
         self.mp.add_copy_spec_limit(fn, 1)
0cd6dc
         content, fname = self.mp.copy_strings[0]
0cd6dc
@@ -252,10 +263,12 @@ class AddCopySpecTests(unittest.TestCase):
0cd6dc
         os.unlink(fn)
0cd6dc
 
0cd6dc
     def test_bad_filename(self):
0cd6dc
+        self.mp.sysroot = '/'
0cd6dc
         self.assertFalse(self.mp.add_copy_spec_limit('', 1))
0cd6dc
         self.assertFalse(self.mp.add_copy_spec_limit(None, 1))
0cd6dc
 
0cd6dc
     def test_glob_file_over_limit(self):
0cd6dc
+        self.mp.sysroot = '/'
0cd6dc
         # assume these are in /tmp
0cd6dc
         fn = create_file(2)
0cd6dc
         fn2 = create_file(2)
0cd6dc
@@ -271,7 +284,10 @@ class AddCopySpecTests(unittest.TestCase):
0cd6dc
 class CheckEnabledTests(unittest.TestCase):
0cd6dc
 
0cd6dc
     def setUp(self):
0cd6dc
-        self.mp = EnablerPlugin({'policy': sos.policies.load()})
0cd6dc
+        self.mp = EnablerPlugin({
0cd6dc
+            'policy': sos.policies.load(),
0cd6dc
+            'sysroot': os.getcwd()
0cd6dc
+        })
0cd6dc
 
0cd6dc
     def test_checks_for_file(self):
0cd6dc
         f = j("tail_test.txt")
0cd6dc
@@ -296,7 +312,8 @@ class RegexSubTests(unittest.TestCase):
0cd6dc
 
0cd6dc
     def setUp(self):
0cd6dc
         self.mp = MockPlugin({
0cd6dc
-            'cmdlineopts': MockOptions()
0cd6dc
+            'cmdlineopts': MockOptions(),
0cd6dc
+            'sysroot': os.getcwd()
0cd6dc
         })
0cd6dc
         self.mp.archive = MockArchive()
0cd6dc
 
0cd6dc
@@ -310,6 +327,8 @@ class RegexSubTests(unittest.TestCase):
0cd6dc
         self.assertEquals(0, replacements)
0cd6dc
 
0cd6dc
     def test_replacements(self):
0cd6dc
+        # test uses absolute paths
0cd6dc
+        self.mp.sysroot = '/'
0cd6dc
         self.mp.add_copy_spec(j("tail_test.txt"))
0cd6dc
         self.mp.collect()
0cd6dc
         replacements = self.mp.do_file_sub(j("tail_test.txt"), r"(tail)", "foobar")
0cd6dc
-- 
0cd6dc
1.9.3
0cd6dc