def test_remove_unused_dependencies_new_unused_only(self): apt.apt_pkg.config.set("APT::VersionedKernelPackages::", "linux-image") apt.apt_pkg.config.set("APT::VersionedKernelPackages::", ".*-modules") apt.apt_pkg.config.set("APT::VersionedKernelPackages::", "linux-headers") apt_conf = os.path.join(self.rootdir, "etc", "apt", "apt.conf") with open(apt_conf, "w") as fp: fp.write(""" Unattended-Upgrade::Keep-Debs-After-Install "true"; Unattended-Upgrade::Allowed-Origins { "Ubuntu:lucid-security"; }; Unattended-Upgrade::Remove-New-Unused-Dependencies "true"; Unattended-Upgrade::Skip-Updates-On-Metered-Connections "false"; """) options = MockOptions() unattended_upgrade.LOCK_FILE = "./u-u.lock" unattended_upgrade.main( options, rootdir="./root.unused-deps") with open(self.log) as f: # ensure its only exactly one package that is removed needle = "Packages that were successfully auto-removed: "\ "test-package-dependency" haystack = f.read() self.assertTrue(needle in haystack, "Can not find '%s' in '%s'" % (needle, haystack))
def test_do_not_run_on_devrelease(self): self.write_config("false") # run it options = MockOptions() unattended_upgrade.DISTRO_DESC = "Artful Aardvark (development branch)" unattended_upgrade.main(options, rootdir=self.rootdir) # read the log to see what happend with open(self.log) as f: needle = "Not running on the development release" haystack = f.read() self.assertTrue(needle in haystack, "Can not find '%s' in '%s'" % (needle, haystack))
def test_remove_unused_dependencies(self): options = MockOptions() unattended_upgrade.main( options, rootdir="./root.unused-deps") log = os.path.join( self.rootdir, "var", "log", "unattended-upgrades", "unattended-upgrades.log") with open(log) as f: needle = "Packages that are auto removed: "\ "'test-package-dependency'" haystack = f.read() self.assertTrue(needle in haystack, "Can not find '%s' in '%s'" % (needle, haystack))
def test_untrusted_check_without_conffile_check(self): # ensure there is no conffile_prompt check apt.apt_pkg.config.set("DPkg::Options::", "--force-confold") # run it options = MockOptions() unattended_upgrade.main(options, rootdir=self.rootdir) # read the log to see what happend with open(self.log) as f: needle = "DEBUG InstCount=0 DelCount=0 BrokenCount=0" haystack = f.read() self.assertTrue(needle in haystack, "Can not find '%s' in '%s'" % (needle, haystack)) self.assertTrue("pkg 'test-package' is untrusted" in haystack)
def test_untrusted_check_without_conffile_check(self): # ensure there is no conffile_prompt check apt.apt_pkg.config.set("DPkg::Options::", "--force-confold") # run it options = MockOptions() unattended_upgrade.DISTRO_DESC = "Ubuntu 10.04" unattended_upgrade.LOCK_FILE = "./u-u.lock" unattended_upgrade.main(options, rootdir=self.rootdir) # read the log to see what happend with open(self.log) as f: haystack = f.read() self.assertTrue( "pkg test-package is not from a trusted origin" in haystack)
def test_against_real_archive(self): # create mock options options = MockOptions(dry_run=False, debug=True) # run unattended-upgrades against fake system logdir = os.path.abspath("./aptroot/var/log/") logfile = os.path.join(logdir, "unattended-upgrades.log") apt_pkg.config.set("APT::UnattendedUpgrades::LogDir", logdir) # main res = unattended_upgrade.main(options, os.path.abspath("./aptroot")) logging.debug(res) # check if the log file exists self.assertTrue(os.path.exists(logfile)) with open(logfile) as fp: log = fp.read() # check that stuff worked self.assertFalse(" ERROR " in log, log) # check if we actually have the expected ugprade in it self.assertTrue( re.search("INFO Packages that will be upgraded:.*awstats", log)) # apt-doc has a higher version in -updates than in -security # and no other dependencies so its a perfect test self.assertTrue( re.search("INFO Packages that will be upgraded:.*apt-doc", log)) self.assertFalse( re.search("INFO Packages that will be upgraded:.*ant-doc", log)) self.assertTrue( re.search("DEBUG skipping blacklisted package 'ant-doc'", log))
def test_against_real_archive(self): # get a lucid based cache (test good for 5y) cache = apt.Cache(rootdir="./aptroot") cache.update() del cache # create mock options options = MockOptions(debug=True) # ensure apt does not do any post-invoke stuff that fails # (because we are not root) apt_pkg.config.clear("DPkg::Post-Invoke") # run unattended-upgrades against fake system logdir = os.path.abspath("./aptroot/var/log/") logfile = os.path.join(logdir, "unattended-upgrades.log") apt_pkg.config.set("APT::UnattendedUpgrades::LogDir", logdir) unattended_upgrade.DISTRO_CODENAME = "lucid" res = unattended_upgrade.main(options, os.path.abspath("./aptroot")) # check if the log file exists self.assertTrue(os.path.exists(logfile)) log = open(logfile).read() # check that stuff worked self.assertFalse(" ERROR " in log) # check if we actually have the expected ugprade in it self.assertTrue( re.search("INFO Packages that are upgraded:.*awstats", log)) # apt-doc has a higher version in -updates than in -security # and no other dependencies so its a perfect test self.assertTrue( re.search("INFO Packages that are upgraded:.*apt-doc", log)) self.assertFalse( re.search("INFO Packages that are upgraded:.*ant-doc", log)) self.assertTrue( re.search("DEBUG skipping blacklisted package 'ant-doc'", log))
def test_exception(self, mock_run): exception_string = "Test exception for email" mock_run.side_effect = Exception(exception_string) # run it options = MockOptions() unattended_upgrade.LOCK_FILE = "./u-u.lock" exception_raised = False try: unattended_upgrade.main(options) except Exception as e: self.assertEqual(str(e), exception_string) exception_raised = True self.assertTrue(exception_raised) with open(os.path.join(self.tmpdir, "mail.txt"), "rb") as fp: mail_txt = fp.read().decode("utf-8") self.assertTrue(exception_string in mail_txt)
def test_norelease_devrelease(self): """The devel series has no release update, so do updates""" self.write_config("auto") # run it unattended_upgrade.distro_info = MockDistroInfoModule(MockDistroNoAuto) options = MockOptions() unattended_upgrade.DISTRO_DESC = "Artful Aardvark (development branch)" unattended_upgrade.DISTRO_CODENAME = "artful" unattended_upgrade.DISTRO_ID = "ubuntu" unattended_upgrade.main(options, rootdir=self.rootdir) # read the log to see what happend with open(self.log) as f: # Check that we could have run needle = "Running on the development release" haystack = f.read() self.assertTrue(needle in haystack, "Can not find '%s' in '%s'" % (needle, haystack))
def test_auto_devrelease(self): """We are not ready to auto upgrade just yet""" self.write_config("auto") # run it unattended_upgrade.distro_info = MockDistroInfoModule(MockDistroAuto) options = MockOptions() unattended_upgrade.DISTRO_DESC = "Artful Aardvark (development branch)" unattended_upgrade.DISTRO_CODENAME = "artful" unattended_upgrade.DISTRO_ID = "ubuntu" unattended_upgrade.main(options, rootdir=self.rootdir) # read the log to see what happend with open(self.log) as f: needle = ("Not running on this development release before %s" % MockDistroAuto.start_updates) haystack = f.read() self.assertTrue(needle in haystack, "Can not find '%s' in '%s'" % (needle, haystack))
def test_remove_unused_dependencies_new_unused_only(self): apt_conf = os.path.join(self.rootdir, "etc", "apt", "apt.conf") with open(apt_conf, "w") as fp: fp.write(""" Unattended-Upgrade::Keep-Debs-After-Install "true"; Unattended-Upgrade::Allowed-Origins { "Ubuntu:lucid-security"; }; Unattended-Upgrade::Remove-New-Unused-Dependencies "true"; """) options = MockOptions() unattended_upgrade.main( options, rootdir="./root.unused-deps") with open(self.log) as f: # ensure its only exactly one package that is removed needle = "Packages that are auto removed: "\ "'test-package-dependency'" haystack = f.read() self.assertTrue(needle in haystack, "Can not find '%s' in '%s'" % (needle, haystack))
def test_remove_unused_dependencies(self): apt_conf = os.path.join(self.rootdir, "etc", "apt", "apt.conf") with open(apt_conf, "w") as fp: fp.write(""" Unattended-Upgrade::Keep-Debs-After-Install "true"; Unattended-Upgrade::Allowed-Origins { "Ubuntu:lucid-security"; }; Unattended-Upgrade::Remove-Unused-Dependencies "true"; """) options = MockOptions() unattended_upgrade.LOCK_FILE = "./u-u.lock" unattended_upgrade.main(options, rootdir="./root.unused-deps") with open(self.log) as f: # both the new and the old unused dependency are removed needle = "Packages that were successfully auto-removed: "\ "old-unused-dependency test-package-dependency" haystack = f.read() self.assertTrue(needle in haystack, "Can not find '%s' in '%s'" % (needle, haystack))
def test_on_battery(self): # ensure there is no conffile_prompt check # run it options = MockOptions() unattended_upgrade.LOCK_FILE = "./u-u.lock" ret = unattended_upgrade.main(options, rootdir=self.rootdir) self.assertTrue(ret == 1) # read the log to see what happend with open(self.log) as f: needle = "System is on battery power, stopping" haystack = f.read() self.assertTrue(needle in haystack, "Can not find '%s' in '%s'" % (needle, haystack))
def test_remove_unused_dependencies_new_unused_only(self): apt.apt_pkg.config.set("APT::VersionedKernelPackages::", "linux-image") apt.apt_pkg.config.set("APT::VersionedKernelPackages::", ".*-modules") apt.apt_pkg.config.set("APT::VersionedKernelPackages::", "linux-headers") apt_conf = os.path.join(self.rootdir, "etc", "apt", "apt.conf") with open(apt_conf, "w") as fp: fp.write(""" Unattended-Upgrade::Keep-Debs-After-Install "true"; Unattended-Upgrade::Allowed-Origins { "Ubuntu:lucid-security"; }; Unattended-Upgrade::Remove-New-Unused-Dependencies "true"; Unattended-Upgrade::Skip-Updates-On-Metered-Connections "false"; """) options = MockOptions() unattended_upgrade.DISTRO_DESC = "Ubuntu 10.04" unattended_upgrade.LOCK_FILE = "./u-u.lock" unattended_upgrade.main( options, rootdir="./root.unused-deps") with open(self.log) as f: # ensure its only exactly one package that is removed needle_kernel_bad = "Removing unused kernel packages: "\ "any-old-unused-modules\n" needle_kernel_good = "Removing unused kernel packages: "\ "linux-image-4.05.0-1021-kvm\n" needle = "Packages that were successfully auto-removed: "\ "test-package-dependency\n" haystack = f.read() self.assertTrue(needle in haystack, "Can not find '%s' in '%s'" % (needle, haystack)) self.assertTrue(needle_kernel_good in haystack, "Can not find '%s' in '%s'" % (needle_kernel_good, haystack)) self.assertFalse(needle_kernel_bad in haystack, "Found '%s' in '%s'" % (needle_kernel_bad, haystack))
def test_on_battery(self): # ensure there is no conffile_prompt check # run it options = MockOptions() unattended_upgrade.DISTRO_DESC = "Ubuntu 10.04" unattended_upgrade.LOCK_FILE = "./u-u.lock" ret = unattended_upgrade.main(options, rootdir=self.rootdir) self.assertTrue(ret == 1) # read the log to see what happend with open(self.log) as f: needle = "System is on battery power, stopping" haystack = f.read() self.assertTrue(needle in haystack, "Can not find '%s' in '%s'" % (needle, haystack))
def test_remove_unused_dependencies(self): apt_conf = os.path.join(self.rootdir, "etc", "apt", "apt.conf") with open(apt_conf, "w") as fp: fp.write(""" Unattended-Upgrade::Keep-Debs-After-Install "true"; Unattended-Upgrade::Allowed-Origins { "Ubuntu:lucid-security"; }; Unattended-Upgrade::Remove-Unused-Dependencies "true"; Unattended-Upgrade::Skip-Updates-On-Metered-Connections "false"; """) options = MockOptions() unattended_upgrade.DISTRO_DESC = "Ubuntu 10.04" unattended_upgrade.LOCK_FILE = "./u-u.lock" unattended_upgrade.main( options, rootdir="./root.unused-deps") with open(self.log) as f: # both the new and the old unused dependency are removed needle = "Packages that were successfully auto-removed: "\ "any-old-unused-modules linux-image-4.05.0-1021-kvm "\ "old-unused-dependency test-package-dependency\n" haystack = f.read() self.assertTrue(needle in haystack, "Can not find '%s' in '%s'" % (needle, haystack))
def _run_upgrade_test_in_real_chroot(self, options, clean_chroot=True): """ helper that runs the unattended-upgrade in a chroot and does some basic verifications """ if os.getuid() != 0: print("Skipping because uid != 0") return # clear to avoid pollution in the chroot apt.apt_pkg.config.clear("Acquire::http::ProxyAutoDetect") # create chroot target = "./test-chroot.%s" % DISTRO # setup chroot if needed if clean_chroot: self._setup_chroot(target) # ensure we have /dev/pts in the chroot ret = subprocess.call(["mount", "-t", "devpts", "devptsfs", os.path.join(target, "dev", "pts")]) if ret != 0: raise Exception("Failed to mount %s/proc" % target) self.addCleanup( lambda: subprocess.call( ["umount", os.path.join(target, "dev", "pts")])) # and run the upgrade test pid = os.fork() if pid == 0: # chroot os.chroot(target) os.chdir("/") if not os.path.exists("/var/log/unattended-upgrades/"): os.makedirs("/var/log/unattended-upgrades/") # make sure we are up-to-date subprocess.call(["apt-get", "update", "-q", "-q"]) # run it apt.apt_pkg.config.clear("Unattended-Upgrade::Allowed-Origins") apt.apt_pkg.config.clear("Unattended-Upgrade::Origins-Pattern") apt.apt_pkg.config.set( "Unattended-Upgrade::Origins-Pattern::", ORIGINS_PATTERN) unattended_upgrade.DISTRO_CODENAME = DISTRO unattended_upgrade.main(options) os._exit(0) else: has_progress = False all_progress = "" last_progress = "" progress_log = os.path.join( target, "var/run/unattended-upgrades.progress") while True: time.sleep(0.01) if os.path.exists(progress_log): progress = open(progress_log).read() if progress and progress != last_progress: has_progress = progress.startswith("Progress") last_progress = progress all_progress += progress # check exit status (apid, status) = os.waitpid(pid, os.WNOHANG) if pid == apid: ret = os.WEXITSTATUS(status) break #print("*******************", all_progress) self.assertEqual(ret, 0) # this number is a bit random, we just want to be sure we have # progress data self.assertTrue(has_progress, True) self.assertTrue(len(all_progress) > 5) return target
def _run_upgrade_test_in_real_chroot(self, options, clean_chroot=True): """ helper that runs the unattended-upgrade in a chroot and does some basic verifications """ if os.getuid() != 0: print("Skipping because uid != 0") return # clear to avoid pollution in the chroot apt.apt_pkg.config.clear("Acquire::http::ProxyAutoDetect") # create chroot target = "./test-chroot.%s" % DISTRO # setup chroot if needed if clean_chroot: self._setup_chroot(target) # ensure we have /dev/pts in the chroot ret = subprocess.call([ "mount", "-t", "devpts", "devptsfs", os.path.join(target, "dev", "pts") ]) if ret != 0: raise Exception("Failed to mount %s/proc" % target) self.addCleanup(lambda: subprocess.call( ["umount", os.path.join(target, "dev", "pts")])) # and run the upgrade test pid = os.fork() if pid == 0: # chroot os.chroot(target) os.chdir("/") if not os.path.exists("/var/log/unattended-upgrades/"): os.makedirs("/var/log/unattended-upgrades/") # make sure we are up-to-date subprocess.call(["apt-get", "update", "-q", "-q"]) # run it apt.apt_pkg.config.clear("Unattended-Upgrade::Allowed-Origins") apt.apt_pkg.config.clear("Unattended-Upgrade::Origins-Pattern") apt.apt_pkg.config.set("Unattended-Upgrade::Origins-Pattern::", ORIGINS_PATTERN) unattended_upgrade.DISTRO_CODENAME = DISTRO unattended_upgrade.main(options) os._exit(0) else: has_progress = False all_progress = "" last_progress = "" progress_log = os.path.join( target, "var/run/unattended-upgrades.progress") while True: time.sleep(0.01) if os.path.exists(progress_log): progress = open(progress_log).read() if progress and progress != last_progress: has_progress = progress.startswith("Progress") last_progress = progress all_progress += progress # check exit status (apid, status) = os.waitpid(pid, os.WNOHANG) if pid == apid: ret = os.WEXITSTATUS(status) break #print("*******************", all_progress) self.assertEqual(ret, 0) # this number is a bit random, we just want to be sure we have # progress data self.assertTrue(has_progress, True) self.assertTrue(len(all_progress) > 5) return target