def test_package_parse_str(self): p1 = Package("foo") p2 = Package("~foo:x86_64") p3 = Package("[email protected]") p4 = Package("baz#[email protected]:x86_64") self.assertEqual("foo", p1.name) self.assertEqual(Package.ACTION_INCLUDE, p1.action) self.assertEqual(None, p1.epoch) self.assertEqual(None, p1.version) self.assertEqual(None, p1.release) self.assertEqual(None, p1.arch) self.assertEqual("foo", p2.name) self.assertEqual(Package.ACTION_EXCLUDE, p2.action) self.assertEqual(None, p2.epoch) self.assertEqual(None, p2.version) self.assertEqual(None, p2.release) self.assertEqual("x86_64", p2.arch) self.assertEqual("bar", p3.name) self.assertEqual(Package.ACTION_INCLUDE, p3.action) self.assertEqual(None, p3.epoch) self.assertEqual("2.1.4", p3.version) self.assertEqual("0", p3.release) self.assertEqual(None, p3.arch) self.assertEqual("baz", p4.name) self.assertEqual(Package.ACTION_INCLUDE, p4.action) self.assertEqual("1", p4.epoch) self.assertEqual("2.1", p4.version) self.assertEqual("3", p4.release) self.assertEqual("x86_64", p4.arch)
def test_template_add_includes_obj(self): t1 = Template("foo:bar") t2 = Template("bar:baz") t3 = Template("baz:daz") p1 = Package("foo") p2 = Package("bar") p3 = Package("baz") p4 = Package("~baz") t1.add_package(p1) t2.add_package(p2) t2.add_package(p3) t3.add_package(p4) # check includes t1.includes = [t2] self.assertEqual(["bar:baz"], t1.includes) # check includes (rebuild) t1.includes = [t2, t3] self.assertEqual(["bar:baz", "baz:daz"], t1.includes) # check package resolution t1.includes = [t2] self.assertEqual(PackageSet([p1, p2, p3]), t1.packages_all) # check package resolution (ordered) t1.includes = [t2, t3] self.assertEqual(PackageSet([p1, p2, p3]), t1.packages_all) t1.includes = [t3, t2] self.assertEqual(PackageSet([p1, p2, p4]), t1.packages_all)
def test_package_parse(self): p1 = Package({'n':'testpackage'}) self.assertEqual('testpackage', p1.name) self.assertEqual(None, p1.epoch) self.assertEqual(None, p1.version) self.assertEqual(None, p1.release) self.assertEqual(None, p1.arch) # empty packages will have a default action of include self.assertEqual({'n':'testpackage', 'z': Package.ACTION_INCLUDE}, p1.to_object())
def test_package_parse_empty(self): p1 = Package({}) self.assertEqual(None, p1.name) self.assertEqual(None, p1.epoch) self.assertEqual(None, p1.version) self.assertEqual(None, p1.release) self.assertEqual(None, p1.arch) # empty packages will have a default action of include self.assertEqual({'z': 1}, p1.to_object())
def test_package_parse_str_valid_epoc(self): # Standard format try: p = Package("bar#[email protected]") except ValueError: self.fail("Package raised ValueError on valid epoc") # Multiple digits are acceptable try: p = Package("bar#[email protected]") except ValueError: self.fail("Package raised ValueError on valid epoc")
def test_package_parse_str_invalid_version(self): # Release is required with self.assertRaises(ValueError): Package("bar@1") with self.assertRaises(ValueError): Package("bar@1-") # Must have version, release is not enough with self.assertRaises(ValueError): Package("bar@-2") # Multiple release specifiers with self.assertRaises(ValueError): Package("[email protected]")
def test_package_to_object(self): p1 = Package({'n': 'foo', 'e': '1', 'v': '1.2.3', 'r': '2', 'a': 'x86_64', 'z': Package.ACTION_EXCLUDE}) p2 = Package({'n': 'foo', 'a': 'x86_64', 'z': Package.ACTION_EXCLUDE}) self.assertEqual(p1.to_object(), {'n': 'foo', 'e': '1', 'v': '1.2.3', 'r': '2', 'a': 'x86_64', 'z': Package.ACTION_EXCLUDE}) self.assertEqual(p2.to_object(), {'n': 'foo', 'a': 'x86_64', 'z': Package.ACTION_EXCLUDE})
def test_package_to_pkg(self): db = dnf.Base() try: db.fill_sack() except OSError as e: pass p_list = db.sack.query().installed().filter(name=["python3-nose"]) # Valid p1 = Package(p_list[0]) pkg1 = p1.to_pkg() pkg2 = p1.to_pkg(db) self.assertEqual(p_list[0], pkg1) self.assertEqual(pkg1, pkg2)
def _parse_template(self, template): # parse the string short form if isinstance(template, str): parts = template.split(':') if len(parts) == 1: self._name = parts[0] elif len(parts) == 2: self._user = parts[0] self._name = parts[1] # parse the dict form, the most common form and directly # relates to the json structures returned by canvas server elif isinstance(template, dict): self._uuid = template.get('uuid', None) self._user = template.get('user', template.get('username', None)) self._name = template.get('stub', None) self._title = template.get('name', self._name) self._description = template.get('description', None) self._includes = template.get('includes', []) self._includes_resolved = template.get('includes_resolved', []) self._meta = template.get('meta', {}) self._repos = {Repository(r) for r in template.get('repos', [])} self._packages = {Package(p) for p in template.get('packages', [])} # resolve includes self._flatten()
def test_package_strip_evr(self): p1 = Package({'n': 'foo', 'e': '1', 'v': '1.2.3', 'r': '1', 'a': 'x86_64'}, evr=False) self.assertEqual('foo', p1.name) self.assertEqual(None, p1.epoch) self.assertEqual(None, p1.version) self.assertEqual(None, p1.release) self.assertEqual('x86_64', p1.arch)
def test_package_equality(self): p1 = Package({'n': 'foo'}) p2 = Package({'n': 'foo', 'a': 'x86_64'}) p3 = Package({'n': 'foo', 'a': 'x86_64', 'v': '1.0', 'r': '1'}) p4 = Package({'n': 'foo', 'a': 'i386'}) # If arch is missing from one or both then they are equal self.assertEqual(p1, p2) # Version does not matter self.assertEqual(p2, p3) # Arch differ self.assertNotEqual(p2, p4) # Not a package self.assertNotEqual(p3, 'str')
def test_package_parse_str_invalid_format(self): # Dangling separators with self.assertRaises(ValueError): Package("bar#@1.2-3") # Dangling epoc sign with self.assertRaises(ValueError): Package("bar#@") # Cannot have version without release with self.assertRaises(ValueError): Package("[email protected]") # Epoc requires version to be specified with self.assertRaises(ValueError): Package("bar#1") with self.assertRaises(TypeError): Package(1)
def test_packageset_uniqueness(self): p1 = Package({'n': 'foo'}) p2 = Package({'n': 'foo', 'a': 'x'}) p3 = Package({'n': 'foo', 'a': 'y'}) l1 = PackageSet() l1.add(p1) self.assertTrue(len(l1) == 1) # adding second package of same name with arch defined should overwrite # existing package with undefined arch l1.add(p2) self.assertTrue(len(l1) == 1) self.assertEqual(l1[0].arch, 'x') l1.add(p3) self.assertTrue(len(l1) == 2)
def test_package_parse_dict(self): p1 = Package({'n': 'foo', 'e': '1', 'v': '1.2.3', 'r': '2', 'a': 'x86_64', 'z': Package.ACTION_EXCLUDE}) self.assertEqual('foo', p1.name) self.assertEqual('1', p1.epoch) self.assertEqual('1.2.3', p1.version) self.assertEqual('2', p1.release) self.assertEqual('x86_64', p1.arch) self.assertEqual(p1.action, Package.ACTION_EXCLUDE)
def test_package_parse_str_valid_version(self): # Standard format try: Package("bar@1-2") except ValueError: self.fail("Package raised ValueError on valid package version") # Point releases are acceptable try: Package("[email protected]") except ValueError: self.fail("Package raised ValueError on valid package version") # Large version numbers try: p = Package("bar@1234-2") except ValueError: self.fail("Package raised ValueError on valid package version")
def test_packageset_update(self): p1 = Package({'n': 'foo'}) p2 = Package({'n': 'foo', 'a': 'x'}) p3 = Package({'n': 'foo', 'a': 'y'}) l1 = PackageSet() l2 = PackageSet() l1.add(p2) l1.add(p3) self.assertEqual(PackageSet([p2, p3]), l1) l2.add(p1) self.assertEqual(PackageSet([p1]), l2) l2.update(l1) self.assertEqual(PackageSet([p2, p3]), l2)
def test_packageset_equality(self): p1 = Package({'n': 'foo'}) p2 = Package({'n': 'foo', 'a': 'x'}) p3 = Package({'n': 'foo', 'a': 'y'}) l1 = PackageSet() l2 = PackageSet() # p1 has a no arch defined is loosely equal to an explict arch being # defined for the same name l1.add(p1) l2.add(p2) self.assertEqual(l1, l2) # p3 has an explicit arch which will overwrite the undefined arch for the # package of the same name, result in the two lists each having an explicit # defined arch which are not equal l1.add(p3) self.assertNotEqual(l1, l2)
def test_package_parse_str_invalid_epoc(self): # Must have version/release with self.assertRaises(ValueError): Package("bar#1") # Must have version/release with self.assertRaises(ValueError): Package("bar#@1.2-4") # Adding arch, we still need version and release with self.assertRaises(ValueError): Package("bar#1:i586") # Must be numeric with self.assertRaises(ValueError): Package("bar#[email protected]") # Must be integer with self.assertRaises(ValueError): Package("bar#[email protected]")
def test_package_parse_dnf(self): db = dnf.Base() try: db.fill_sack() except OSError as e: pass p_list = db.sack.query().installed().filter(name=["python3-nose"]) # Valid p1 = Package(p_list[0])
def run_add(self): t = Template(self.args.template, user=self.args.username) try: t = self.cs.template_get(t) except ServiceException as e: print(e) return 1 for p in self.args.package: try: pkg = Package(p) except TypeError as e: print(e) return 1 t.add_package(pkg) packages = list(t.packages_delta) packages.sort(key=lambda x: x.name) # describe process for dry runs if self.args.dry_run: if len(packages): print( 'The following would be added to the template: {0}'.format( t.name)) for p in packages: print(' - ' + str(p)) print() print('Summary:') print(' - Package(s): %d' % (len(packages))) print() else: print('No template changes required.') print('No action peformed during this dry-run.') return 0 if not len(packages): print('info: no changes detected, template up to date.') return 0 # push our updated template try: res = self.cs.template_update(t) except ServiceException as e: print(e) return 1
def test_package_to_pkg_spec(self): p1 = Package('foo') p2 = Package('foo:x86_64') p3 = Package('[email protected]:x86_64') p4 = Package('[email protected]') p5 = Package('the_silver_searcher#[email protected]:x86_64') # Basic "name" self.assertEqual(p1.to_pkg_spec(), "foo") # "name.arch" self.assertEqual(p2.to_pkg_spec(), "foo.x86_64") # "name-version-release.arch" self.assertRegexpMatches(p3.to_pkg_spec(), r'^foo-1.0-1.fc\d{2}.x86_64$') # "name-version-release" self.assertRegexpMatches(p4.to_pkg_spec(), r'^foo_bar-1.2.3-1.fc\d{2}$') # "name-epoc:version-release.arch" self.assertRegexpMatches(p5.to_pkg_spec(), r'^the_silver_searcher-0:0.31.0-1.fc\d{2}.x86_64$')
def run_rm(self): t = Template(self.args.template, user=self.args.username) try: t = self.cs.template_get(t) except ServiceException as e: print(e) return 1 packages = [] for p in self.args.package: p = Package(p) if t.remove_package(p): packages.append(p) packages.sort(key=lambda x: x.name) # describe process for dry runs if self.args.dry_run: if len(packages): print('The following would be removed from the template: {0}'. format(t.name)) for p in packages: print(' - ' + str(p)) print() print('Summary:') print(' - Package(s): %d' % (len(packages))) print() else: print('No template changes required.') print('No action peformed during this dry-run.') return 0 if not len(packages): print('info: no changes detected, template up to date.') return 0 # push our updated template try: res = self.cs.template_update(t) except ServiceException as e: print(e) return 1
def from_system(self, all=False): db = dnf.Base() try: db.fill_sack() except OSError as e: pass p_list = db.iter_userinstalled() if all: p_list = db.sack.query().installed() for p in p_list: self.add_package(Package(p, evr=False)) for r in db.repos.enabled(): self.add_repo(Repository(r))
def _parse_template(self, template): # parse the string short form if isinstance(template, str): (user, name, version) = self._parse_unv(template) if user: self._user = user if name: self._name = name if version: self._version = version if not self._user or len(self._user) == 0: raise ValueError("template format invalid") if not self._name or len(self._name) == 0: raise ValueError("template format invalid") # parse the dict form, the most common form and directly # relates to the json structures returned by canvas server elif isinstance(template, dict): self._uuid = template.get('uuid', None) self._user = template.get('user', template.get('username', None)) self._name = template.get('stub', None) self._version = template.get('version', None) self._title = template.get('name', self._name) self._description = template.get('description', None) self._includes = template.get('includes', []) self._repos = RepoSet( Repository(r, template=self.unv) for r in template.get('repos', [])) self._packages = PackageSet( Package(p, template=self.unv) for p in template.get('packages', [])) self._stores = template.get('stores', []) self._objects = ObjectSet( Object(o) for o in template.get('objects', [])) self._meta = template.get('meta', {})
def run_update(self): t = Template(self.args.template, user=self.args.username) try: t = self.cs.template_get(t) except ServiceException as e: print(e) return 1 # track updates to determine server update updated = False for p in self.args.package: # parse new and find old pn = Package(p) print(pn) if pn not in t.packages: print('warn: package is not defined in template.') continue # update with new and track if t.update_package(pn): updated = True if not updated: print('info: no changes detected.') return 0 # push our updated template try: res = self.cs.template_update(t) except ServiceException as e: print(e) return 1 print('info: package(s) updated.') return 0
def from_system(cls, all=False): system_template = cls('local:system') db = dnf.Base() try: db.fill_sack() except OSError as e: pass if all: p_list = db.sack.query().installed() else: p_list = db.iter_userinstalled() for p in p_list: system_template.add_package(Package(p, evr=False)) for r in db.repos.enabled(): system_template.add_repo(Repository(r)) return system_template
def test_packageset_difference(self): p1 = Package({'n': 'foo'}) p2 = Package({'n': 'foo', 'a': 'x'}) p3 = Package({'n': 'bar'}) p4 = Package({'n': 'bar', 'a': 'y'}) p5 = Package({'n': 'baz'}) p6 = Package({'n': 'car'}) l1 = PackageSet([p1, p3, p5]) l2 = PackageSet([p2, p4, p6]) (luniq1, luniq2) = l1.difference(l2) self.assertEqual(PackageSet([p5]), luniq1) self.assertEqual(PackageSet([p6]), luniq2)
def test_package_parse_str_valid_name(self): # Hyphen is acceptable try: Package("abc-xyz") except ValueError: self.fail("Package raised ValueError on valid package name") # Numbers are acceptable try: Package("foobar3") except ValueError: self.fail("Package raised ValueError on valid package name") try: Package("lemon3.3") except ValueError: self.fail("Package raised ValueError on valid package name") # Underscore is acceptable try: Package("foo_bar") except ValueError: self.fail("Package raised ValueError on valid package name") # Plus is acceptable try: Package("pie++") except ValueError: self.fail("Package raised ValueError on valid package name") # Groups are acceptable try: Package("@Development Tools") except ValueError: self.fail("Package raised ValueError on valid package name")
def test_package_group(self): p1 = Package({'n':'notgroup'}) p2 = Package({'n': '@foo'}) self.assertNotEqual(p1.action, Package.ACTION_INCLUDE | Package.ACTION_GROUP) self.assertEqual(p2.action, Package.ACTION_INCLUDE | Package.ACTION_GROUP)
def test_package_parse_dnf_invalid(self): with self.assertRaises(TypeError): Package.parse_dnf("notvalid")
def test_package_pinned(self): # Release is required p1 = Package("foo") self.assertEqual(False, p1.pinned()) p1.action |= Package.ACTION_PIN self.assertEqual(True, p1.pinned())
def test_package_included(self): # Release is required p1 = Package("foo") self.assertEqual(False, p1.excluded()) self.assertEqual(True, p1.included())
def _parse_kickstart(self, path): """ Loads the template with information from the supplied kickstart path. Kickstarts predominately populate the meta tag, similar to the following: 'kickstart': { 'platform': '', 'version': 'DEVEL', 'language': 'en_US.UTF-8', 'keyboard': 'us' 'timezone': 'US/Eastern' 'auth': '--useshadow --passalgo=sha512 'selinux': '--enforcing' 'firewall': '--enabled --service=mdns 'xconfig': '--startxonboot' 'part': '/ --size 4096 --fstype ext4', 'services': '--enabled=NetworkManager,ModemManager --disabled=network,sshd' 'commands': [ ], }, } Currently scripts are converted to canvas objects, repo commands are converted to canvas repos and packages are converted to canvas packages. Args: path: Path to existing kickstart file. Returns: Nothing. Raises: IOError: An error occurred accessing the kickstart file. """ ksversion = makeVersion(DEVEL) ksparser = pykickstart.parser.KickstartParser(ksversion) try: ksparser.readKickstart(path) except IOError as msg: print("Failed to read kickstart file '{0}' : {1}".format( path, msg)) return except pykickstart.errors.KickstartError as e: print("Failed to parse kickstart file '{0}' : {1}".format( path, msg)) return handler = ksparser.handler meta = {} if handler.platform: meta['platform'] = handler.platform meta['version'] = versionToString(handler.version) lst = list(handler._writeOrder.keys()) lst.sort() for prio in lst: for c in handler._writeOrder[prio]: # we don't store null commands (why pykickstart? why?) if c.currentCmd.strip() == '': continue # store repo commands as canvas templates elif c.currentCmd == 'repo': for r in c.__str__().split('\n'): # ignore blank lines if len(r.strip()) == 0: continue self.add_repo(Repository(r)) # otherwise store commands as canvas objects else: self.add_object(Object(c)) # convert scripts into canvas objects # sort on line number seen for s in sorted(handler.scripts, key=lambda x: x.lineno): self.add_object(Object(s)) # parse pykickstart packages packages = handler.packages meta['packages'] = { 'default': packages.default, 'exclude_docs': packages.excludeDocs, 'no_base': not packages.addBase, 'no_core': packages.nocore, 'handle_missing': (packages.handleMissing == pykickstart.constants.KS_MISSING_IGNORE ), 'install_langs': packages.instLangs, 'multi_lib': packages.multiLib } if not packages.default: if packages.environment: meta['package']['environment'] = "@^{0}".format( packages.environment) grps = packages.groupList grps.sort() for g in grps: self.add_package(Package({'n': g.__str__(), 'z': 1})) pkgs = packages.packageList pkgs.sort() for p in pkgs: self.add_package(Package({'n': p.__str__(), 'z': 1})) grps = packages.excludedGroupList grps.sort() for g in grps: self.add_package(Package({'n': g.__str__(), 'z': 0})) pkgs = packages.excludedList pkgs.sort() for p in pkgs: self.add_package(Package({'n': p.__str__(), 'z': 0})) self._meta['kickstart'] = meta
def test_package_parse_str_invalid(self): with self.assertRaises(TypeError): Package.parse_str(1)
def test_package_parse_str_invalid_name(self): # Release is required with self.assertRaises(ValueError): Package("foo##")