def populate(db): """ Create some data for tests to use. Args: db (sqlalchemy.orm.session.Session): The database session. """ user = User(name=u'guest') db.add(user) anonymous = User(name=u'anonymous') db.add(anonymous) provenpackager = Group(name=u'provenpackager') db.add(provenpackager) packager = Group(name=u'packager') db.add(packager) user.groups.append(packager) release = Release(name=u'F17', long_name=u'Fedora 17', id_prefix=u'FEDORA', version=u'17', dist_tag=u'f17', stable_tag=u'f17-updates', testing_tag=u'f17-updates-testing', candidate_tag=u'f17-updates-candidate', pending_signing_tag=u'f17-updates-testing-signing', pending_testing_tag=u'f17-updates-testing-pending', pending_stable_tag=u'f17-updates-pending', override_tag=u'f17-override', branch=u'f17', state=ReleaseState.current) db.add(release) db.flush() update = create_update(db, [u'bodhi-2.0-1.fc17']) update.type = UpdateType.bugfix update.severity = UpdateSeverity.medium bug = Bug(bug_id=12345) db.add(bug) update.bugs.append(bug) cve = CVE(cve_id=u"CVE-1985-0110") db.add(cve) update.cves.append(cve) comment = Comment(karma=1, text=u"wow. amaze.") db.add(comment) comment.user = user update.comments.append(comment) comment = Comment(karma=0, text=u"srsly. pretty good.", anonymous=True) comment.user = anonymous db.add(comment) update.comments.append(comment) with mock.patch(target='uuid.uuid4', return_value='wat'): update.assign_alias() db.add(update) db.commit()
def populate(db): """ Create some data for tests to use. Args: db (sqlalchemy.orm.session.Session): The database session. """ user = User(name='guest') db.add(user) anonymous = User(name='anonymous') db.add(anonymous) provenpackager = Group(name='provenpackager') db.add(provenpackager) packager = Group(name='packager') db.add(packager) user.groups.append(packager) release = Release(name='F17', long_name='Fedora 17', id_prefix='FEDORA', version='17', dist_tag='f17', stable_tag='f17-updates', testing_tag='f17-updates-testing', candidate_tag='f17-updates-candidate', pending_signing_tag='f17-updates-signing-pending', pending_testing_tag='f17-updates-testing-pending', pending_stable_tag='f17-updates-pending', override_tag='f17-override', branch='f17', state=ReleaseState.current, create_automatic_updates=True, package_manager=PackageManager.unspecified, testing_repository=None) db.add(release) db.flush() # This mock will help us generate a consistent update alias. with mock.patch(target='uuid.uuid4', return_value='wat'): update = create_update(db, ['bodhi-2.0-1.fc17']) update.type = UpdateType.bugfix update.severity = UpdateSeverity.medium bug = Bug(bug_id=12345) db.add(bug) update.bugs.append(bug) comment = Comment(karma=1, text="wow. amaze.") db.add(comment) comment.user = user update.comments.append(comment) comment = Comment(karma=0, text="srsly. pretty good.") comment.user = anonymous db.add(comment) update.comments.append(comment) db.add(update) db.commit()
def test_list_comments_with_multiple_ignore_user(self): another_user = User(name='aUser') self.db.add(another_user) update = Update( user=another_user, request=UpdateRequest.testing, type=UpdateType.enhancement, notes='Just another update.', date_submitted=datetime(1981, 10, 11), requirements='rpmlint', stable_karma=3, unstable_karma=-3, release=Release.query.one() ) self.db.add(update) comment = Comment(karma=1, text='Cool! 😃') comment.user = another_user self.db.add(comment) update.comments.append(comment) self.db.flush() res = self.app.get('/comments/', {"ignore_user": "******"}) body = res.json_body self.assertEqual(len(body['comments']), 1) self.assertNotIn('errors', body) self.assertEqual(body['comments'][0]['text'], 'Cool! 😃')
def test_list_comments_by_multiple_usernames(self): nvr = u'just-testing-1.0-2.fc17' update = Update( title=nvr, request=UpdateRequest.testing, type=UpdateType.enhancement, notes=u'Just another update.', date_submitted=datetime(1981, 10, 11), requirements=u'rpmlint', stable_karma=3, unstable_karma=-3, ) update.release = Release.query.one() self.db.add(update) another_user = User(name=u'aUser') self.db.add(another_user) comment = Comment(karma=1, text=u'Cool! 😃') comment.user = another_user self.db.add(comment) update.comments.append(comment) self.db.flush() res = self.app.get('/comments/', {"user": "******"}) body = res.json_body self.assertEqual(len(body['comments']), 2) self.assertEqual(body['comments'][0]['text'], u'Cool! 😃') self.assertEqual(body['comments'][1]['text'], u'wow. amaze.')
def test_list_comments_by_multiple_update_owners(self): another_user = User(name='aUser') self.db.add(another_user) update = Update( user=another_user, request=UpdateRequest.testing, type=UpdateType.enhancement, notes='Just another update.', date_submitted=datetime(1981, 10, 11), requirements='rpmlint', stable_karma=3, unstable_karma=-3, release=Release.query.one() ) self.db.add(update) comment = Comment(karma=1, text='Cool! 😃') comment.user = another_user self.db.add(comment) update.comments.append(comment) self.db.flush() res = self.app.get('/comments/', {"update_owner": "guest,aUser"}) body = res.json_body self.assertEqual(len(body['comments']), 3) comment = body['comments'][0] self.assertEqual(comment['text'], 'Cool! 😃') comment = body['comments'][1] self.assertEqual(comment['text'], 'srsly. pretty good.')
def test_list_comments_by_multiple_usernames(self): update = Update(request=UpdateRequest.testing, type=UpdateType.enhancement, notes='Just another update.', date_submitted=datetime(1981, 10, 11), requirements='rpmlint', stable_karma=3, unstable_karma=-3, release=Release.query.one()) self.db.add(update) another_user = User(name='aUser') self.db.add(another_user) comment = Comment(karma=1, text='Cool! 😃') comment.user = another_user self.db.add(comment) update.comments.append(comment) self.db.flush() res = self.app.get('/comments/', {"user": "******"}) body = res.json_body assert len(body['comments']) == 2 assert body['comments'][0]['text'] == 'Cool! 😃' assert body['comments'][1]['text'] == 'wow. amaze.'
def setUp(self, *args, **kwargs): super(TestCommentsService, self).setUp(*args, **kwargs) # Add a second update owned by somebody else so we can test karma # policy stuff user2 = User(name='lmacken') self.db.flush() self.db.add(user2) release = self.db.query(Release).filter_by(name='F17').one() update = Update( user=user2, request=UpdateRequest.testing, type=UpdateType.enhancement, notes='Useful details!', release=release, date_submitted=datetime(1984, 11, 2), requirements='rpmlint', stable_karma=3, unstable_karma=-3, ) self.db.add(update) build = RpmBuild(nvr=up2, update=update, package=RpmPackage.query.filter_by(name='bodhi').one()) self.db.add(build) self.db.flush()
def test_list_overrides_by_multiple_usernames(self): release = Release.get('F17') package = RpmPackage(name='just-testing') self.db.add(package) build = RpmBuild(nvr='just-testing-1.0-2.fc17', package=package, release=release) self.db.add(build) another_user = User(name='aUser') self.db.add(another_user) expiration_date = datetime.utcnow() + timedelta(days=1) override = BuildrootOverride(build=build, submitter=another_user, notes='Crazy! 😱', expiration_date=expiration_date) self.db.add(override) self.db.flush() res = self.app.get('/overrides/', {"user": "******"}) body = res.json_body self.assertEqual(len(body['overrides']), 2) override_fake = body['overrides'][0] self.assertEqual(override_fake['build']['nvr'], 'just-testing-1.0-2.fc17') self.assertEqual(override_fake['submitter']['name'], 'aUser') self.assertEqual(override_fake['notes'], 'Crazy! 😱') override_orig = body['overrides'][1] self.assertEqual(override_orig['build']['nvr'], 'bodhi-2.0-1.fc17') self.assertEqual(override_orig['submitter']['name'], 'guest') self.assertEqual(override_orig['notes'], 'blah blah blah')
def test_list_comments_by_update_owner_with_none(self): user = User(name='ralph') self.db.add(user) self.db.flush() res = self.app.get('/comments/', {"update_owner": "ralph"}) body = res.json_body self.assertEqual(len(body['comments']), 0) self.assertNotIn('errors', body)
def test_list_overrides_by_username_without_override(self): self.db.add(User(name='bochecha')) self.db.flush() res = self.app.get('/overrides/', {'user': '******'}) body = res.json_body self.assertEqual(len(body['overrides']), 0)
def test_get_single_user_with_nonstandard_characters(self): """Test that we don't receive a 404 page with bot usernames.""" user = User(name='bot/a.bad.name') self.db.add(user) self.db.flush() res = self.app.get('/users/bot/a.bad.name') assert res.json_body['user']['name'] == 'bot/a.bad.name'
def test_list_comments_by_update_owner_with_none(self): user = User(name='ralph') self.db.add(user) self.db.flush() res = self.app.get('/comments/', {"update_owner": "ralph"}) body = res.json_body assert len(body['comments']) == 0 assert 'errors' not in body
def test_edit_stack_with_no_user_privs(self, *args): user = User(name=u'bob') self.db.add(user) self.db.add(RpmPackage(name=u'gnome-music')) self.db.commit() self.stack.users.append(user) self.db.commit() attrs = {'name': 'GNOME', 'packages': 'gnome-music gnome-shell', 'csrf_token': self.get_csrf_token()} res = self.app.post("/stacks/", attrs, status=403) body = res.json_body self.assertEquals(body['status'], 'error') self.assertEquals(body['errors'][0]['description'], 'guest does not have privileges to modify the GNOME stack')
def test_existing_user(self, caplog): """Test Koji build user existing in DB.""" caplog.set_level(logging.DEBUG) expected_username = base.buildsys.DevBuildsys._build_data['owner_name'] # ensure user with expected name exists user = self.db.query(User).filter_by(name=expected_username).first() if not user: user = User(name=expected_username) self.db.add(user) self.db.flush() assert (f"Creating bodhi user for '{expected_username}'." not in caplog.messages)
def create_or_update_user(db, username, email, groups): """Create or update a user in the database. Args: db (sqlalchemy.orm.session.Session): The database session. username (str): The username to create or update email (str): The user's email address groups (list(str)): A list of group names the user belongs to, that will be synced. Returns: bodhi.server.models.User: The user instance. """ # Find the user in our database. Create it if it doesn't exist. user = db.query(User).filter_by(name=username).first() if not user: user = User(name=username, email=email) db.add(user) db.flush() else: # Update email address if the address changed if user.email != email: user.email = email db.flush() # Keep track of what groups the user is a member of for group_name in groups: # Drop empty group names https://github.com/fedora-infra/bodhi/issues/306 if not group_name.strip(): continue group = db.query(Group).filter_by(name=group_name).first() if not group: group = Group(name=group_name) db.add(group) db.flush() if group not in user.groups: log.info('Adding %s to %s group', user.name, group.name) user.groups.append(group) # See if the user was removed from any groups for group in user.groups: if group.name not in groups: log.info('Removing %s from %s group', user.name, group.name) user.groups.remove(group) return user
def test_existing_user(self, caplog): """Test Koji build user existing in DB.""" caplog.set_level(logging.DEBUG) expected_username = base.buildsys.DevBuildsys._build_data['owner_name'] # ensure user with expected name exists user = self.db.query(User).filter_by(name=expected_username).first() if not user: user = User(name=expected_username) self.db.add(user) self.db.flush() with mock.patch('bodhi.server.models.handle_update'): with mock_sends(update_schemas.UpdateReadyForTestingV1): self.handler(self.sample_message) assert (f"Creating bodhi user for '{expected_username}'." not in caplog.messages)
def setUp(self): super(TestUsersService, self).setUp() user = User(name=u'bodhi') self.db.add(user) self.db.flush()
def setUp(self, *args, **kwargs): super(TestFrontpageView, self).setUp(*args, **kwargs) def _add_updates(updateslist, user, release, packagesuffix): """Private method that adds updates to the database for testing """ count = 0 for i in updateslist: for j in i[1]: for k in range(0, j[1]): update = Update( title=u'bodhi-2.0-1%s.%s' % (str(count), packagesuffix), user=user, status=i[0], type=j[0], notes=u'Useful details!', release=release, date_submitted=datetime(1984, 11, 2), requirements=u'rpmlint', stable_karma=3, unstable_karma=-3, ) self.db.add(update) self.db.flush() count = count + 1 user2 = User(name=u'dudemcpants') self.db.flush() self.db.add(user2) release = Release(name=u'F18', long_name=u'Fedora 18', id_prefix=u'FEDORA', version=u'18', dist_tag=u'f18', stable_tag=u'f18-updates', testing_tag=u'f18-updates-testing', candidate_tag=u'f18-updates-candidate', pending_signing_tag=u'f18-updates-testing-signing', pending_testing_tag=u'f18-updates-testing-pending', pending_stable_tag=u'f18-updates-pending', override_tag=u'f18-override', branch=u'f18', state=ReleaseState.pending) self.db.add(release) currentrelease = self.db.query(Release).filter_by(name=u'F17').one() addedupdates = [[ UpdateStatus.pending, [[UpdateType.security, 5], [UpdateType.bugfix, 4], [UpdateType.enhancement, 3], [UpdateType.newpackage, 2]] ], [ UpdateStatus.testing, [[UpdateType.security, 15], [UpdateType.bugfix, 14], [UpdateType.enhancement, 13], [UpdateType.newpackage, 12]] ], [ UpdateStatus.stable, [[UpdateType.security, 25], [UpdateType.bugfix, 24], [UpdateType.enhancement, 23], [UpdateType.newpackage, 22]] ]] _add_updates(addedupdates, user2, currentrelease, "fc17") pendingrelease = self.db.query(Release).filter_by(name=u'F18').one() addedupdates2 = [[ UpdateStatus.pending, [[UpdateType.security, 2], [UpdateType.bugfix, 2], [UpdateType.enhancement, 2], [UpdateType.newpackage, 2]] ], [ UpdateStatus.testing, [[UpdateType.security, 3], [UpdateType.bugfix, 3], [UpdateType.enhancement, 3], [UpdateType.newpackage, 3]] ], [ UpdateStatus.stable, [[UpdateType.security, 4], [UpdateType.bugfix, 4], [UpdateType.enhancement, 4], [UpdateType.newpackage, 4]] ]] _add_updates(addedupdates2, user2, pendingrelease, "fc18") self.db.flush() Release._tag_cache = None
def setup_method(self, method): super(TestUsersService, self).setup_method(method) user = User(name='bodhi') self.db.add(user) self.db.flush()
def __call__(self, message: fedora_messaging.api.Message) -> None: """Create updates from appropriately tagged builds. Args: message: The message we are processing. """ body = message.body missing = [] for mandatory in ('tag', 'build_id', 'name', 'version', 'release'): if mandatory not in body: missing.append(mandatory) if missing: log.debug( f"Received incomplete tag message. Missing: {', '.join(missing)}" ) return btag = body['tag'] bnvr = '{name}-{version}-{release}'.format(**body) koji = buildsys.get_session() kbuildinfo = koji.getBuild(bnvr) if not kbuildinfo: log.debug(f"Can't find Koji build for {bnvr}.") return if 'nvr' not in kbuildinfo: log.debug(f"Koji build info for {bnvr} doesn't contain 'nvr'.") return if 'owner_name' not in kbuildinfo: log.debug( f"Koji build info for {bnvr} doesn't contain 'owner_name'.") return if kbuildinfo['owner_name'] in config.get( 'automatic_updates_blacklist'): log.debug( f"{bnvr} owned by {kbuildinfo['owner_name']} who is listed in " "automatic_updates_blacklist, skipping.") return # some APIs want the Koji build info, some others want the same # wrapped in a larger (request?) structure rbuildinfo = { 'info': kbuildinfo, 'nvr': kbuildinfo['nvr'].rsplit('-', 2), } with self.db_factory() as dbsession: rel = dbsession.query(Release).filter_by( create_automatic_updates=True, candidate_tag=btag).first() if not rel: log.debug( f"Ignoring build being tagged into {btag!r}, no release configured for " "automatic updates for it found.") return bcls = ContentType.infer_content_class(Build, kbuildinfo) build = bcls.get(bnvr) if build and build.update: log.info( f"Build, active update for {bnvr} exists already, skipping." ) return if not build: log.debug(f"Build for {bnvr} doesn't exist yet, creating.") # Package.get_or_create() infers content type already log.debug("Getting/creating related package object.") pkg = Package.get_or_create(dbsession, rbuildinfo) log.debug("Creating build object, adding it to the DB.") build = bcls(nvr=bnvr, package=pkg, release=rel) dbsession.add(build) owner_name = kbuildinfo['owner_name'] user = User.get(owner_name) if not user: log.debug(f"Creating bodhi user for '{owner_name}'.") # Leave email, groups blank, these will be filled # in or updated when they log into Bodhi next time, see # bodhi.server.security:remember_me(). user = User(name=owner_name) dbsession.add(user) log.debug(f"Creating new update for {bnvr}.") changelog = build.get_changelog(lastupdate=True) if changelog: notes = f"""Automatic update for {bnvr}. ##### **Changelog** ``` {changelog} ```""" else: notes = f"Automatic update for {bnvr}." update = Update( release=rel, builds=[build], notes=notes, type=UpdateType.unspecified, stable_karma=3, unstable_karma=-3, autokarma=False, user=user, status=UpdateStatus.pending, ) # Comment on the update that it was automatically created. update.comment( dbsession, str("This update was automatically created"), author="bodhi", ) update.add_tag(update.release.pending_signing_tag) log.debug("Adding new update to the database.") dbsession.add(update) log.debug("Committing changes to the database.") dbsession.commit()
def setUp(self, *args, **kwargs): super(TestReleasesHTML, self).setUp(*args, **kwargs) def _add_updates(updateslist, user, release, packagesuffix): """Private method that adds updates to the database for testing """ count = 0 for i in updateslist: for j in i[1]: for k in range(0, j[1]): update = Update( user=user, status=i[0], type=j[0], notes='Useful details!', release=release, date_submitted=datetime(1984, 11, 2), requirements='rpmlint', stable_karma=3, unstable_karma=-3, ) self.db.add(update) self.db.commit() count = count + 1 user2 = User(name='dudemcpants') self.db.flush() self.db.add(user2) release = Release(name='F18', long_name='Fedora 18', id_prefix='FEDORA', version='18', dist_tag='f18', stable_tag='f18-updates', testing_tag='f18-updates-testing', candidate_tag='f18-updates-candidate', pending_signing_tag='f18-updates-testing-signing', pending_testing_tag='f18-updates-testing-pending', pending_stable_tag='f18-updates-pending', override_tag='f18-override', branch='f18', state=ReleaseState.pending) self.db.add(release) currentrelease = self.db.query(Release).filter_by(name='F17').one() addedupdates = [[ UpdateStatus.pending, [[UpdateType.security, 5], [UpdateType.bugfix, 4], [UpdateType.enhancement, 3], [UpdateType.newpackage, 2]] ], [ UpdateStatus.testing, [[UpdateType.security, 15], [UpdateType.bugfix, 14], [UpdateType.enhancement, 13], [UpdateType.newpackage, 12]] ], [ UpdateStatus.stable, [[UpdateType.security, 25], [UpdateType.bugfix, 24], [UpdateType.enhancement, 23], [UpdateType.newpackage, 22]] ]] with fml_testing.mock_sends(*[api.Message] * 54): _add_updates(addedupdates, user2, currentrelease, "fc17") pendingrelease = self.db.query(Release).filter_by(name='F18').one() addedupdates2 = [[ UpdateStatus.pending, [[UpdateType.security, 2], [UpdateType.bugfix, 2], [UpdateType.enhancement, 2], [UpdateType.newpackage, 2]] ], [ UpdateStatus.testing, [[UpdateType.security, 3], [UpdateType.bugfix, 3], [UpdateType.enhancement, 3], [UpdateType.newpackage, 3]] ], [ UpdateStatus.stable, [[UpdateType.security, 4], [UpdateType.bugfix, 4], [UpdateType.enhancement, 4], [UpdateType.newpackage, 4]] ]] with fml_testing.mock_sends(*[api.Message] * 12): _add_updates(addedupdates2, user2, pendingrelease, "fc18") self.db.flush() # Clear the caches Release._tag_cache = None generic._generate_home_page_stats.invalidate()
def __call__(self, message: fedora_messaging.api.Message) -> None: """Create updates from appropriately tagged builds. Args: message: The message we are processing. """ body = message.body missing = [] for mandatory in ('tag', 'build_id', 'name', 'version', 'release'): if mandatory not in body: missing.append(mandatory) if missing: log.debug( f"Received incomplete tag message. Missing: {', '.join(missing)}" ) return btag = body['tag'] bnvr = '{name}-{version}-{release}'.format(**body) koji = buildsys.get_session() kbuildinfo = koji.getBuild(bnvr) if not kbuildinfo: log.debug(f"Can't find Koji build for {bnvr}.") return if 'nvr' not in kbuildinfo: log.debug(f"Koji build info for {bnvr} doesn't contain 'nvr'.") return if 'owner_name' not in kbuildinfo: log.debug( f"Koji build info for {bnvr} doesn't contain 'owner_name'.") return if kbuildinfo['owner_name'] in config.get( 'automatic_updates_blacklist'): log.debug( f"{bnvr} owned by {kbuildinfo['owner_name']} who is listed in " "automatic_updates_blacklist, skipping.") return # some APIs want the Koji build info, some others want the same # wrapped in a larger (request?) structure rbuildinfo = { 'info': kbuildinfo, 'nvr': kbuildinfo['nvr'].rsplit('-', 2), } with self.db_factory() as dbsession: rel = dbsession.query(Release).filter_by( create_automatic_updates=True, candidate_tag=btag).first() if not rel: log.debug( f"Ignoring build being tagged into {btag!r}, no release configured for " "automatic updates for it found.") return bcls = ContentType.infer_content_class(Build, kbuildinfo) build = bcls.get(bnvr) if build and build.update: log.info( f"Build, active update for {bnvr} exists already, skipping." ) return if not build: log.debug(f"Build for {bnvr} doesn't exist yet, creating.") # Package.get_or_create() infers content type already log.debug("Getting/creating related package object.") pkg = Package.get_or_create(dbsession, rbuildinfo) log.debug("Creating build object, adding it to the DB.") build = bcls(nvr=bnvr, package=pkg, release=rel) dbsession.add(build) owner_name = kbuildinfo['owner_name'] user = User.get(owner_name) if not user: log.debug(f"Creating bodhi user for '{owner_name}'.") # Leave email, groups blank, these will be filled # in or updated when they log into Bodhi next time, see # bodhi.server.security:remember_me(). user = User(name=owner_name) dbsession.add(user) log.debug(f"Creating new update for {bnvr}.") try: changelog = build.get_changelog(lastupdate=True) except ValueError: # Often due to bot-generated builds # https://github.com/fedora-infra/bodhi/issues/4146 changelog = None except Exception: # Re-raise exception, so that the message can be re-queued raise closing_bugs = [] if changelog: log.debug("Adding changelog to update notes.") notes = f"""Automatic update for {bnvr}. ##### **Changelog** ``` {changelog} ```""" if rel.name not in config.get('bz_exclude_rels'): for b in re.finditer(config.get('bz_regex'), changelog, re.IGNORECASE): idx = int(b.group(1)) log.debug(f'Adding bug #{idx} to the update.') bug = Bug.get(idx) if bug is None: bug = Bug(bug_id=idx) dbsession.add(bug) dbsession.flush() if bug not in closing_bugs: closing_bugs.append(bug) else: notes = f"Automatic update for {bnvr}." update = Update( release=rel, builds=[build], bugs=closing_bugs, notes=notes, type=UpdateType.unspecified, stable_karma=3, unstable_karma=-3, autokarma=False, user=user, status=UpdateStatus.pending, critpath=Update.contains_critpath_component([build], rel.branch), ) # Comment on the update that it was automatically created. update.comment( dbsession, str("This update was automatically created"), author="bodhi", ) update.add_tag(update.release.pending_signing_tag) log.debug("Adding new update to the database.") dbsession.add(update) log.debug("Flushing changes to the database.") dbsession.flush() # Obsolete older updates which may be stuck in testing due to failed gating try: update.obsolete_older_updates(dbsession) except Exception as e: log.error(f'Problem obsoleting older updates: {e}') alias = update.alias buglist = [b.bug_id for b in update.bugs] # This must be run after dbsession is closed so changes are committed to db work_on_bugs_task.delay(alias, buglist)