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 testProcessCatalogAndNotifyAdmins(self, generate_catalog_mock, log_mock, deprecate_products_mock, notify_mock): """Tests _ProcessCatalogAndNotifyAdmins().""" os_version = '10.7' mock_catalog = models.AppleSUSCatalog(plist='<plist></plist>') new_products = ['new1', 'new2'] deprecated_products = ['old1', 'old2'] deprecate_products_mock.return_value = deprecated_products with mock.patch.object(applesus.AppleSUSCatalogSync, '_UpdateProductDataFromCatalog', return_value=new_products): with mock.patch.object(applesus.plist, 'ApplePlist', autospec=True): self.catalog_sync._ProcessCatalogAndNotifyAdmins( mock_catalog, os_version) generate_catalog_mock.assert_called_once_with(os_version, applesus.common.UNSTABLE) notify_mock.assert_called_once_with(mock_catalog, new_products, deprecated_products) log_mock.assert_has_calls([ mock.call(new_products, 'new for %s' % os_version), mock.call(deprecated_products, 'deprecated for %s' % os_version), ])
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 testSupplyClientIdAndTokenInUrl(self): testapp = webtest.TestApp(gae_app) plist = 'PLIST' models.AppleSUSCatalog(key_name='10.11_stable', plist=plist).put() headers = { applesus.MUNKI_CLIENT_ID_HEADER_KEY: 'track=stable|os_version=10.11'} ss = models.AuthSession(uuid='34') with mock.patch.object(gaeserver, 'DoMunkiAuth', return_value=ss): resp = testapp.post( '/applesus/', status=httplib.OK, headers=headers) resp = testapp.get('/applesus/%s' % resp.body, status=httplib.OK) self.assertEqual(plist, resp.body)