def testEqualWithIgnoreKeysReturningFalse(self): """Tests Equal() false.""" pl = plist.ApplePlist() pl._plist = {'foo': 1, 'bar': True} other = plist.ApplePlist() other._plist = {'foo': 2, 'bar': True} self.assertFalse(pl.Equal(other, ignore_keys=['bar']))
def testEqual(self): """Tests Equal().""" pl = plist.ApplePlist() pl._plist = {'foo': 1, 'bar': True} other = plist.ApplePlist() other._plist = {'foo': 1, 'bar': True} self.assertTrue(pl.Equal(other))
def _GetSystemProfile(self): sp_xml = self._GetSystemProfilerOutput() p = plist.ApplePlist(sp_xml) try: p.Parse() except plist.Error, e: raise SystemProfilerError('plist Parse() error: %s' % str(e))
def _ProcessCatalogAndNotifyAdmins(cls, catalog, os_version): """Wrapper method to process a catalog and notify admin of changes. Args: catalog: models.AppleSUSCatalog object to process. os_version: str OS version like 10.5, 10.6, 10.7, etc. """ catalog_plist = plist.ApplePlist(catalog.plist) try: catalog_plist.Parse() except plist.Error: logging.exception('Error parsing Apple Updates catalog: %s', catalog.key().name()) return new_products = cls._UpdateProductDataFromCatalog(catalog_plist) deprecated_products = cls._DeprecateOrphanedProducts() cls._NotifyAdminsOfCatalogSync(catalog, new_products, deprecated_products) # Regenerate the unstable catalog, including new updates but excluding # any that were previously manually disabled. applesus.GenerateAppleSUSCatalog(os_version, common.UNSTABLE) models.AdminAppleSUSProductLog.Log(new_products, 'new for %s' % os_version) models.AdminAppleSUSProductLog.Log(deprecated_products, 'deprecated for %s' % os_version)
def _DeprecateOrphanedProducts(self): """Deprecates products in Datastore that no longer exist in any catalogs. Returns: List of AppleSUSProduct objects that were marked deprecated. """ # Loop over all catalogs, generating a dict of all unique product ids. catalog_products = set() for os_version in applesus.OS_VERSIONS: for track in common.TRACKS + ['untouched']: key = '%s_%s' % (os_version, track) catalog_obj = models.AppleSUSCatalog.get_by_key_name(key) if not catalog_obj: logging.error('Catalog does not exist: %s', key) continue catalog_plist = plist.ApplePlist(catalog_obj.plist) try: catalog_plist.Parse() except plist.Error: logging.exception( 'Error parsing Apple Updates catalog: %s', key) continue for product in catalog_plist.get('Products', []): catalog_products.add(product) deprecated = [] # Loop over Datastore products, deprecating all that aren't in any catalogs. for p in models.AppleSUSProduct.all().filter('deprecated =', False): if p.product_id not in catalog_products: p.deprecated = True p.put() deprecated.append(p) return deprecated
def PackageInfoTemplateHook(self, input_pkginfo, open_=open): """Allow a template to supply values into the pkginfo. The template is loaded. Its values are overlaid onto a new pkginfo instance with values copied from the one that is supplied as input_pkginfo. Note this means callers to this method will not have their input_pkginfo modified, rather a new pkginfo is received as output if any values changed. Args: input_pkginfo: plist.MunkiPackageInfoPlist, input pkginfo to use as base values Returns: a different plist.MunkiPackageInfoPlist instance with potentially new values populated Raises: CliError: an error occurs reading the template """ pkginfo = input_pkginfo.copy() try: plist_xml = open_(self.config['template_pkginfo'], 'r').read() template = plist.ApplePlist(plist_xml) template.Parse() except IOError: raise CliError('I/O error %s' % self.config['template_pkginfo']) except plist.Error, e: raise CliError('Error parsing %s: %s' % (self.config['template_pkginfo'], str(e)))
def GenerateAppleSUSCatalog( os_version, track, datetime_=datetime.datetime, catalog_lock=None): """Generates an Apple SUS catalog for a given os_version and track. This function loads the untouched/raw Apple SUS catalog, removes any products/updates that are not approved for the given track, then saves a new catalog (plist/xml) to Datastore for client consumption. Args: os_version: str OS version to generate the catalog for. track: str track name to generate the catalog for. datetime_: datetime module; only used for stub during testing. catalog_lock: datastore_lock.DatastoreLock; If provided, the lock to release upon completion of the operation. Returns: tuple, new models.AppleSUSCatalog object and plist.ApplePlist object. Or, if there is no "untouched" catalog for the os_version, then (None, None) is returned. """ logging.info('Generating catalog: %s_%s', os_version, track) catalog_key = '%s_untouched' % os_version untouched_catalog_obj = models.AppleSUSCatalog.get_by_key_name(catalog_key) if not untouched_catalog_obj: logging.warning('Apple Update catalog does not exist: %s', catalog_key) if catalog_lock: catalog_lock.Release() return None, None untouched_catalog_plist = plist.ApplePlist(untouched_catalog_obj.plist) untouched_catalog_plist.Parse() approved_product_ids = set() products_query = models.AppleSUSProduct.AllActive().filter('tracks =', track) for product in products_query: approved_product_ids.add(product.product_id) product_ids = untouched_catalog_plist.get('Products', {}).keys() new_plist = untouched_catalog_plist for product_id in product_ids: if product_id not in approved_product_ids: del new_plist['Products'][product_id] catalog_plist_xml = new_plist.GetXml() # Save the catalog using a time-specific key for rollback purposes. now = datetime_.utcnow() now_str = now.strftime('%Y-%m-%d-%H-%M-%S') backup = models.AppleSUSCatalog( key_name='backup_%s_%s_%s' % (os_version, track, now_str)) backup.plist = catalog_plist_xml backup.put() # Overwrite the catalog being served for this os_version/track pair. c = models.AppleSUSCatalog(key_name='%s_%s' % (os_version, track)) c.plist = catalog_plist_xml c.put() if catalog_lock: catalog_lock.Release() return c, new_plist
def _GetPkginfoPlist(self): """Returns a pkginfo plist for an Apple Update Product.""" d = { 'installer_type': 'apple_update_metadata', 'name': self.product_id, } if self.unattended: d['unattended_install'] = self.unattended if self.force_install_after_date: d['force_install_after_date'] = self.force_install_after_date d['version'] = '1.0' # TODO(user): find out if this is needed. plist = plist_lib.ApplePlist() plist.SetContents(d) return plist
def testBasicNested(self): xml = ('%s <dict>\n <key>foo</key>\n <string>bar</string>\n ' '</dict>%s' % (plist.PLIST_HEAD, plist.PLIST_FOOT)) xml2 = ( '%s <dict>\n <key>subway</key>\n <string>BDFM</string>\n ' '</dict>%s' % (plist.PLIST_HEAD, plist.PLIST_FOOT)) nested_xml = ('%s <dict>\n <key>foo</key>\n <dict>\n' ' <key>subway</key>\n' ' <string>BDFM</string>\n' ' </dict>\n' ' </dict>%s' % (plist.PLIST_HEAD, plist.PLIST_FOOT)) plist2 = plist.ApplePlist(xml2) plist2.Parse() self.PlistTest(xml, {'foo': 'bar'}) self.apl.GetContents()['foo'] = plist2 self.assertEqual(nested_xml, self.apl.GetXml())
def GenerateAppleSUSCatalog(os_version, track, _datetime=datetime.datetime): """Generates an Apple SUS catalog for a given os_version and track. This function loads the untouched/raw Apple SUS catalog, removes any products/updates that are not approved for the given track, then saves a new catalog (plist/xml) to Datastore for client consumption. Args: os_version: str OS version to generate the catalog for. track: str track name to generate the catalog for. _datetime: datetime module; only used for stub during testing. Returns: tuple, new models.AppleSUSCatalog object and plist.ApplePlist object. """ logging.info('Generating catalog: %s_%s', os_version, track) approved_product_ids = {} products_query = models.AppleSUSProduct.all().filter('tracks =', track) for product in products_query: approved_product_ids[product.product_id] = True untouched_catalog_obj = models.AppleSUSCatalog.get_by_key_name( '%s_untouched' % os_version) untouched_catalog_plist = plist.ApplePlist(untouched_catalog_obj.plist) untouched_catalog_plist.Parse() product_ids = untouched_catalog_plist.get('Products', {}).keys() new_plist = untouched_catalog_plist for product_id in product_ids: if product_id not in approved_product_ids: del new_plist['Products'][product_id] catalog_plist_xml = new_plist.GetXml() # Save the catalog using a time-specific key for rollback purposes. now = _datetime.utcnow() now_str = now.strftime('%Y-%m-%d-%H-%M-%S') backup = models.AppleSUSCatalog(key_name='backup_%s_%s_%s' % (os_version, track, now_str)) backup.plist = catalog_plist_xml backup.put() # Overwrite the catalog being served for this os_version/track pair. c = models.AppleSUSCatalog(key_name='%s_%s' % (os_version, track)) c.plist = catalog_plist_xml c.put() return c, new_plist
def setUp(self): mox.MoxTestBase.setUp(self) self.stubs = stubout.StubOutForTesting() self.apl = plist.ApplePlist()
def testBasicEmptyString(self): xml = '%s<dict><key>foo</key><string></string><key>bar</key><string/></dict>%s' % ( plist.PLIST_HEAD, plist.PLIST_FOOT) plist2 = plist.ApplePlist(xml) plist2.Parse() self.PlistTest(xml, {'foo': '', 'bar': ''})