├── src
├── webfaf
│ ├── __init__.py
│ ├── static
│ │ ├── Makefile.am
│ │ ├── icons
│ │ │ ├── hicolor_apps_16x16_abrt.png
│ │ │ ├── hicolor_apps_32x32_abrt.png
│ │ │ └── Makefile.am
│ │ ├── css
│ │ │ ├── Makefile.am
│ │ │ └── bootstrap-multiselect.css
│ │ └── js
│ │ │ ├── Makefile.am
│ │ │ ├── jquery.flot.simplelabel.js
│ │ │ └── color.js
│ ├── templates
│ │ ├── about.md.in
│ │ ├── stats
│ │ │ └── Makefile.am
│ │ ├── summary
│ │ │ ├── index_plot_data.html
│ │ │ ├── Makefile.am
│ │ │ └── index.html
│ │ ├── mdpage.html
│ │ ├── 404.html
│ │ ├── 403.html
│ │ ├── 413.html
│ │ ├── problems
│ │ │ ├── Makefile.am
│ │ │ ├── waitforit.html
│ │ │ ├── multiple_bthashes.html
│ │ │ └── list_table_rows.html
│ │ ├── celery_tasks
│ │ │ ├── Makefile.am
│ │ │ ├── results_item.html
│ │ │ ├── results_list.html
│ │ │ ├── action_run.html
│ │ │ └── schedule_item.html
│ │ ├── 500.html
│ │ ├── reports
│ │ │ ├── waitforit.html
│ │ │ ├── Makefile.am
│ │ │ ├── new.html
│ │ │ ├── attach.html
│ │ │ ├── list_table_rows.html
│ │ │ ├── associate_bug.html
│ │ │ └── diff.html
│ │ └── Makefile.am
│ ├── blueprints
│ │ ├── Makefile.am
│ │ └── __init__.py
│ ├── Makefile.am
│ ├── hub.wsgi
│ ├── config.py
│ └── login.py
├── pyfaf
│ ├── storage
│ │ ├── migrations
│ │ │ ├── __init__.py
│ │ │ ├── Makefile.am
│ │ │ ├── alembic.ini
│ │ │ ├── versions
│ │ │ │ ├── 23bab42e7be7_initial_migration.py
│ │ │ │ ├── 13557f1962e6_ureport_added_certainty.py
│ │ │ │ ├── 21345f007bdf_add_privileged_user_field.py
│ │ │ │ ├── acd3d9bf85d1_ignore_private_bz.py
│ │ │ │ ├── 729a154b1609_index_reportpackages.py
│ │ │ │ ├── 48550f308625_add_symbolsource_retrace_fail_count.py
│ │ │ │ ├── 31d0249e8d4c_create_users_table.py
│ │ │ │ ├── 82081a3c76b_rename_kb_to_sf_prefilter.py
│ │ │ │ ├── 272e6a3deea4_link_probable_fix_to_build.py
│ │ │ │ ├── bb2289ffb392_add_tz_info_to_periodictasks.py
│ │ │ │ ├── 58f44afc3a3a_drop_running_package_from_reportpackages.py
│ │ │ │ ├── 183a15e52a4f_report_history_unique.py
│ │ │ │ ├── 50d3e87e4b2a_add_reporturl.py
│ │ │ │ ├── 17d4911132f8_assigning_release_to_repo.py
│ │ │ │ ├── 71905f91e7b7_add_archived_reports.py
│ │ │ │ ├── 5695a1c595c3_reportreleasedesktops.py
│ │ │ │ ├── 133991a89da4_build_to_opsysrelease.py
│ │ │ │ ├── f43edd5b636d_enable_problem_components_reassign.py
│ │ │ │ ├── fd5dc71471cc_set_pkg_name_to_256.py
│ │ │ │ ├── Makefile.am
│ │ │ │ └── 9596a0f03838_zero_unique_reports_to_one.py
│ │ │ └── script.py.mako
│ │ ├── fixtures
│ │ │ ├── lob_download_location
│ │ │ ├── sql
│ │ │ │ ├── buildstags.sql
│ │ │ │ ├── opsys.sql
│ │ │ │ ├── builds.sql
│ │ │ │ ├── buildarchs.sql
│ │ │ │ ├── buildsys.sql
│ │ │ │ ├── opsyscomponents.sql
│ │ │ │ ├── opsysreleases.sql
│ │ │ │ ├── Makefile.am
│ │ │ │ ├── opsysreleasescomponents.sql
│ │ │ │ ├── archs.sql
│ │ │ │ └── packages.sql
│ │ │ ├── Makefile.am
│ │ │ └── randutils.py
│ │ ├── Makefile.am
│ │ ├── debug.py
│ │ ├── jsontype.py
│ │ ├── externalfaf.py
│ │ ├── user.py
│ │ ├── project.py
│ │ ├── bugtracker.py
│ │ └── events.py
│ ├── opsys
│ │ └── Makefile.am
│ ├── celery_tasks
│ │ └── Makefile.am
│ ├── solutionfinders
│ │ └── Makefile.am
│ ├── problemtypes
│ │ └── Makefile.am
│ ├── repos
│ │ └── Makefile.am
│ ├── bugtrackers
│ │ ├── Makefile.am
│ │ ├── centosmantisbt.py
│ │ ├── fedorabz.py
│ │ └── rhelbz.py
│ ├── utils
│ │ ├── Makefile.am
│ │ ├── __init__.py
│ │ ├── contextmanager.py
│ │ ├── format.py
│ │ ├── web.py
│ │ ├── date.py
│ │ ├── hash.py
│ │ └── storage.py
│ ├── Makefile.am
│ ├── local.py
│ ├── actions
│ │ ├── archlist.py
│ │ ├── opsyslist.py
│ │ ├── extfafshow.py
│ │ ├── releaselist.py
│ │ ├── pull_bug.py
│ │ ├── find_report_solution.py
│ │ ├── opsysadd.py
│ │ ├── Makefile.am
│ │ ├── archadd.py
│ │ ├── cleanup_task_results.py
│ │ ├── sar.py
│ │ ├── bugtrackerlist.py
│ │ ├── opsysdel.py
│ │ ├── init.py
│ │ ├── hash_paths.py
│ │ ├── pull_abrt_bugs.py
│ │ └── shell.py
│ └── __init__.py.in
├── Makefile.am
├── schema
│ ├── setup.cfg
│ ├── README
│ ├── Makefile.am
│ └── faf_schema
│ │ ├── __init__.py
│ │ └── tests
│ │ └── __init__.py
└── bin
│ ├── faf.bash_completion
│ ├── faf-migrate-db.bash_completion
│ └── Makefile.am
├── .tito
├── packages
│ ├── faf
│ └── .readme
├── releasers.conf
└── tito.props
├── tests
├── sample_plugin_dir
│ ├── __init__.py
│ ├── base.py
│ ├── Makefile.am
│ ├── plugin.py
│ └── _noplugin.py
├── bin
│ ├── Makefile.am
│ └── eu-addr2line
├── retrace_outputs
│ ├── last_chance_0x0
│ ├── last_chance_0x2
│ ├── last_chance_0x3
│ ├── last_chance_0x4
│ ├── last_chance_0x5
│ ├── last_chance_0x6
│ ├── last_chance_0x7
│ ├── last_chance_0x8
│ ├── last_chance_0x9
│ ├── last_chance_0xa
│ ├── last_chance_0xb
│ ├── last_chance_0xc
│ ├── last_chance_0xd
│ ├── last_chance_0xe
│ ├── last_chance_0xf
│ ├── third_full_0xf
│ ├── last_chance_0x10
│ ├── other_line_0xf
│ ├── third_full_0xe
│ ├── last_chance_0x1
│ ├── other_line_0xe
│ ├── other_source_0xf
│ ├── third_full_0xd
│ ├── other_source_0xe
│ ├── complex_0xffff
│ └── Makefile.am
├── sample_repo
│ ├── Makefile.am
│ └── dummy_repo.repo
├── test_webfaf
│ ├── webfaftests
│ │ ├── Makefile.am
│ │ └── __init__.py
│ ├── Makefile.am
│ ├── __init__.py
│ └── test_summary.py
├── sample_rpms
│ ├── Makefile.am
│ ├── sample-1.0-1.fc18.noarch.rpm
│ ├── sample2-2.0-1.fc32.noarch.rpm
│ ├── sample-broken-1-1.fc22.noarch.rpm
│ └── sample-provides-too-long-1-1.fc33.noarch.rpm
├── faftests
│ ├── Makefile.am
│ └── test_config.conf
├── sample_reports
│ ├── url_attachment
│ ├── bugzilla_attachment
│ ├── contact_email_attachment
│ ├── comment_attachment
│ ├── Makefile.am
│ ├── ureport_systemd2
│ └── ureport_systemd77
├── Makefile.am
├── test_alembic.py
├── test_common.py
├── test_checker.py
└── test_dnf.py
├── config
├── plugins
│ ├── retrace.conf
│ ├── dnf.conf
│ ├── save-reports.conf
│ ├── clonebz.conf
│ ├── symbol-transfer.conf
│ ├── pull-reports.conf
│ ├── create-problems.conf
│ ├── sf-prefilter.conf
│ ├── celery_tasks.conf
│ ├── fedmsg.conf
│ ├── retrace-remote.conf
│ ├── centosmantisbt.conf
│ ├── java.conf
│ ├── ruby.conf
│ ├── coredump.conf
│ ├── kerneloops.conf
│ ├── rhelbz.conf
│ ├── fedorabz.conf
│ ├── python.conf
│ ├── fedora.conf
│ ├── centos.conf
│ ├── Makefile.am
│ └── web.conf
├── templates
│ └── Makefile.am
├── faf
├── celery-worker-env.conf
├── celery-beat-env.conf
├── faf-logging.conf
├── Makefile.am
├── faf-web.conf.in
└── faf.conf.in
├── container
├── files
│ └── usr
│ │ ├── bin
│ │ ├── faf-entrypoint
│ │ ├── faf-celery-worker
│ │ ├── faf-celery-beat
│ │ └── run_faf
│ │ └── libexec
│ │ └── fix-permissions
├── Dockerfile_db
├── podman-compose.yaml
└── Dockerfile_local
├── autogen.sh
├── docs
├── attachment_sample
├── test_notes
├── fixture_notes
└── ureport_sample
├── mypy.ini
├── AUTHORS
├── repos
├── CentOS-Base.repo
├── fedora-updates.repo
├── fedora-rawhide.repo
├── fedora-updates-testing.repo
└── fedora.repo
├── requirements.txt
├── init-scripts
├── faf-celery-tmpfiles.conf
├── faf.conf
├── faf-celery-beat.service
└── faf-celery-worker.service
├── .git-commit-template
├── lgtm.yml
├── Makefile.am
├── .gitignore
├── faf_setup
├── m4
└── ax_python_module.m4
└── .github
└── workflows
├── test.yml
└── codeql.yml
/src/webfaf/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.tito/packages/faf:
--------------------------------------------------------------------------------
1 | 2.6.2 ./
2 |
--------------------------------------------------------------------------------
/tests/sample_plugin_dir/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/migrations/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/Makefile.am:
--------------------------------------------------------------------------------
1 | SUBDIRS = bin pyfaf webfaf schema
2 |
--------------------------------------------------------------------------------
/tests/bin/Makefile.am:
--------------------------------------------------------------------------------
1 | EXTRA_DIST = eu-addr2line
2 |
--------------------------------------------------------------------------------
/tests/retrace_outputs/last_chance_0x0:
--------------------------------------------------------------------------------
1 | ??
2 | ??:0
3 |
--------------------------------------------------------------------------------
/tests/retrace_outputs/last_chance_0x2:
--------------------------------------------------------------------------------
1 | ??
2 | ??:0
3 |
--------------------------------------------------------------------------------
/tests/retrace_outputs/last_chance_0x3:
--------------------------------------------------------------------------------
1 | ??
2 | ??:0
3 |
--------------------------------------------------------------------------------
/tests/retrace_outputs/last_chance_0x4:
--------------------------------------------------------------------------------
1 | ??
2 | ??:0
3 |
--------------------------------------------------------------------------------
/tests/retrace_outputs/last_chance_0x5:
--------------------------------------------------------------------------------
1 | ??
2 | ??:0
3 |
--------------------------------------------------------------------------------
/tests/retrace_outputs/last_chance_0x6:
--------------------------------------------------------------------------------
1 | ??
2 | ??:0
3 |
--------------------------------------------------------------------------------
/tests/retrace_outputs/last_chance_0x7:
--------------------------------------------------------------------------------
1 | ??
2 | ??:0
3 |
--------------------------------------------------------------------------------
/tests/retrace_outputs/last_chance_0x8:
--------------------------------------------------------------------------------
1 | ??
2 | ??:0
3 |
--------------------------------------------------------------------------------
/tests/retrace_outputs/last_chance_0x9:
--------------------------------------------------------------------------------
1 | ??
2 | ??:0
3 |
--------------------------------------------------------------------------------
/tests/retrace_outputs/last_chance_0xa:
--------------------------------------------------------------------------------
1 | ??
2 | ??:0
3 |
--------------------------------------------------------------------------------
/tests/retrace_outputs/last_chance_0xb:
--------------------------------------------------------------------------------
1 | ??
2 | ??:0
3 |
--------------------------------------------------------------------------------
/tests/retrace_outputs/last_chance_0xc:
--------------------------------------------------------------------------------
1 | ??
2 | ??:0
3 |
--------------------------------------------------------------------------------
/tests/retrace_outputs/last_chance_0xd:
--------------------------------------------------------------------------------
1 | ??
2 | ??:0
3 |
--------------------------------------------------------------------------------
/tests/retrace_outputs/last_chance_0xe:
--------------------------------------------------------------------------------
1 | ??
2 | ??:0
3 |
--------------------------------------------------------------------------------
/tests/retrace_outputs/last_chance_0xf:
--------------------------------------------------------------------------------
1 | ??
2 | ??:0
3 |
--------------------------------------------------------------------------------
/tests/retrace_outputs/third_full_0xf:
--------------------------------------------------------------------------------
1 | ??
2 | ??:0
3 |
--------------------------------------------------------------------------------
/src/schema/setup.cfg:
--------------------------------------------------------------------------------
1 | [bdist_wheel]
2 | universal = 1
3 |
--------------------------------------------------------------------------------
/src/webfaf/static/Makefile.am:
--------------------------------------------------------------------------------
1 | SUBDIRS = css js icons
2 |
--------------------------------------------------------------------------------
/tests/retrace_outputs/last_chance_0x10:
--------------------------------------------------------------------------------
1 | ??
2 | ??:0
3 |
--------------------------------------------------------------------------------
/config/plugins/retrace.conf:
--------------------------------------------------------------------------------
1 | [Retrace]
2 | SkipSource = yes
3 |
--------------------------------------------------------------------------------
/tests/retrace_outputs/other_line_0xf:
--------------------------------------------------------------------------------
1 | ??
2 | other_line.c:15
3 |
--------------------------------------------------------------------------------
/tests/retrace_outputs/third_full_0xe:
--------------------------------------------------------------------------------
1 | ??
2 | third_full.c:13
3 |
--------------------------------------------------------------------------------
/tests/sample_plugin_dir/base.py:
--------------------------------------------------------------------------------
1 | class Base(object):
2 | pass
3 |
--------------------------------------------------------------------------------
/tests/sample_repo/Makefile.am:
--------------------------------------------------------------------------------
1 | EXTRA_DIST = dummy_repo.repo
2 |
3 |
--------------------------------------------------------------------------------
/config/plugins/dnf.conf:
--------------------------------------------------------------------------------
1 | [dnf]
2 | metadata_expire = 24h
3 | root = /
4 |
--------------------------------------------------------------------------------
/config/plugins/save-reports.conf:
--------------------------------------------------------------------------------
1 | [Processing]
2 | HashFrames = 16
3 |
--------------------------------------------------------------------------------
/container/files/usr/bin/faf-entrypoint:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | exec "$@"
4 |
--------------------------------------------------------------------------------
/src/bin/faf.bash_completion:
--------------------------------------------------------------------------------
1 | eval "$(register-python-argcomplete faf)"
2 |
--------------------------------------------------------------------------------
/tests/retrace_outputs/last_chance_0x1:
--------------------------------------------------------------------------------
1 | last_chance
2 | last_chance.c:2
3 |
--------------------------------------------------------------------------------
/tests/retrace_outputs/other_line_0xe:
--------------------------------------------------------------------------------
1 | other_line
2 | other_line.c:14
3 |
--------------------------------------------------------------------------------
/tests/retrace_outputs/other_source_0xf:
--------------------------------------------------------------------------------
1 | ??
2 | yet_another_source.c:14
3 |
--------------------------------------------------------------------------------
/tests/retrace_outputs/third_full_0xd:
--------------------------------------------------------------------------------
1 | third_full
2 | third_full.c:13
3 |
--------------------------------------------------------------------------------
/tests/test_webfaf/webfaftests/Makefile.am:
--------------------------------------------------------------------------------
1 | EXTRA_DIST = __init__.py
2 |
--------------------------------------------------------------------------------
/config/plugins/clonebz.conf:
--------------------------------------------------------------------------------
1 | [clonebz]
2 | baseurl=http://localhost/faf
3 |
--------------------------------------------------------------------------------
/tests/retrace_outputs/other_source_0xe:
--------------------------------------------------------------------------------
1 | other_source
2 | other_source.c:14
3 |
--------------------------------------------------------------------------------
/tests/sample_rpms/Makefile.am:
--------------------------------------------------------------------------------
1 | EXTRA_DIST = sample-1.0-1.fc18.noarch.rpm
2 |
3 |
--------------------------------------------------------------------------------
/config/plugins/symbol-transfer.conf:
--------------------------------------------------------------------------------
1 | [symbol_transfer]
2 | auth_key = @SECRET_KEY@
3 |
--------------------------------------------------------------------------------
/tests/faftests/Makefile.am:
--------------------------------------------------------------------------------
1 | EXTRA_DIST = __init__.py mockzilla.py test_config.conf
2 |
--------------------------------------------------------------------------------
/src/bin/faf-migrate-db.bash_completion:
--------------------------------------------------------------------------------
1 | eval "$(register-python-argcomplete faf-migrate-db)"
2 |
--------------------------------------------------------------------------------
/config/plugins/pull-reports.conf:
--------------------------------------------------------------------------------
1 | [pullreports]
2 | Master = https://retrace.fedoraproject.org/faf
3 |
--------------------------------------------------------------------------------
/tests/sample_plugin_dir/Makefile.am:
--------------------------------------------------------------------------------
1 | EXTRA_DIST = __init__.py base.py plugin.py _noplugin.py
2 |
3 |
--------------------------------------------------------------------------------
/.tito/releasers.conf:
--------------------------------------------------------------------------------
1 | [copr]
2 | releaser = tito.release.CoprReleaser
3 | project_name = @abrt/faf-el8
4 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/fixtures/lob_download_location:
--------------------------------------------------------------------------------
1 | http://rmarko.fedorapeople.org/random/faf_fixtures_v2.tar.gz
2 |
--------------------------------------------------------------------------------
/config/plugins/create-problems.conf:
--------------------------------------------------------------------------------
1 | [Processing]
2 | CmpFrames = 16
3 | CutThreshold = 0.3
4 | Normalize = yes
5 |
--------------------------------------------------------------------------------
/config/plugins/sf-prefilter.conf:
--------------------------------------------------------------------------------
1 | [sf-prefilter]
2 | # Lower number means higher priority
3 | solution_priority = 1
4 |
--------------------------------------------------------------------------------
/src/webfaf/templates/about.md.in:
--------------------------------------------------------------------------------
1 | # Placeholder. This file is replaced with README.md from project root during build.
2 |
--------------------------------------------------------------------------------
/tests/sample_plugin_dir/plugin.py:
--------------------------------------------------------------------------------
1 | from .base import Base
2 |
3 |
4 | class Sub(Base):
5 | name = "sub-plugin"
6 |
--------------------------------------------------------------------------------
/config/plugins/celery_tasks.conf:
--------------------------------------------------------------------------------
1 | [celery_tasks]
2 | broker = redis://localhost:6379/0
3 | backend = redis://localhost:6379/0
4 |
--------------------------------------------------------------------------------
/config/plugins/fedmsg.conf:
--------------------------------------------------------------------------------
1 | [fedmsg]
2 | # Realtime notifications
3 | realtime_reports = false
4 | realtime_problems = false
5 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/fixtures/sql/buildstags.sql:
--------------------------------------------------------------------------------
1 | INSERT INTO buildstags VALUES(1,18);
2 | INSERT INTO buildstags VALUES(2,18);
3 |
--------------------------------------------------------------------------------
/autogen.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | autoreconf --install --force
4 | if [ -z "$NOCONFIGURE" ]; then
5 | ./configure "$@"
6 | fi
7 |
--------------------------------------------------------------------------------
/config/templates/Makefile.am:
--------------------------------------------------------------------------------
1 | template_DATA =
2 | templatedir = $(sysconfdir)/faf/templates
3 |
4 | EXTRA_DIST = $(template_DATA)
5 |
--------------------------------------------------------------------------------
/tests/sample_plugin_dir/_noplugin.py:
--------------------------------------------------------------------------------
1 | from .base import Base
2 |
3 |
4 | class NSub(Base):
5 | name = "should-not-be-loaded"
6 |
--------------------------------------------------------------------------------
/config/faf:
--------------------------------------------------------------------------------
1 | /var/log/faf/*.log {
2 | missingok
3 | notifempty
4 | rotate 5
5 | weekly
6 | su faf faf
7 | }
8 |
9 |
--------------------------------------------------------------------------------
/tests/sample_rpms/sample-1.0-1.fc18.noarch.rpm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/abrt/faf/HEAD/tests/sample_rpms/sample-1.0-1.fc18.noarch.rpm
--------------------------------------------------------------------------------
/tests/sample_rpms/sample2-2.0-1.fc32.noarch.rpm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/abrt/faf/HEAD/tests/sample_rpms/sample2-2.0-1.fc32.noarch.rpm
--------------------------------------------------------------------------------
/.tito/tito.props:
--------------------------------------------------------------------------------
1 | [buildconfig]
2 | builder = tito.builder.Builder
3 | tagger = abrt.Tagger
4 | lib_dir = .tito/custom
5 | tag_format = {version}
6 |
--------------------------------------------------------------------------------
/docs/attachment_sample:
--------------------------------------------------------------------------------
1 | {
2 | "type": "rhel-bugzilla",
3 | "bthash": "2dd542ba1f1e074216196b6c0bd548609bf38ebc",
4 | "data": "928318"
5 | }
6 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/fixtures/sql/opsys.sql:
--------------------------------------------------------------------------------
1 | INSERT INTO opsys VALUES (1, 'Fedora');
2 | INSERT INTO opsys VALUES (2, 'Red Hat Enterprise Linux');
3 |
--------------------------------------------------------------------------------
/src/schema/README:
--------------------------------------------------------------------------------
1 | A schema package for messages sent by FAF.
2 |
3 | To find out more information about FAF visit https://github.com/abrt/faf.
4 |
--------------------------------------------------------------------------------
/src/webfaf/static/icons/hicolor_apps_16x16_abrt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/abrt/faf/HEAD/src/webfaf/static/icons/hicolor_apps_16x16_abrt.png
--------------------------------------------------------------------------------
/src/webfaf/static/icons/hicolor_apps_32x32_abrt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/abrt/faf/HEAD/src/webfaf/static/icons/hicolor_apps_32x32_abrt.png
--------------------------------------------------------------------------------
/tests/sample_rpms/sample-broken-1-1.fc22.noarch.rpm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/abrt/faf/HEAD/tests/sample_rpms/sample-broken-1-1.fc22.noarch.rpm
--------------------------------------------------------------------------------
/config/plugins/retrace-remote.conf:
--------------------------------------------------------------------------------
1 | [retrace_remote]
2 | remote_url = http://localhost/faf/symbol_transfer/get_symbol/
3 | auth_key = @SECRET_KEY@
4 |
--------------------------------------------------------------------------------
/src/pyfaf/opsys/Makefile.am:
--------------------------------------------------------------------------------
1 | opsys_PYTHON = \
2 | __init__.py \
3 | centos.py \
4 | fedora.py
5 |
6 | opsysdir = $(pythondir)/pyfaf/opsys
7 |
--------------------------------------------------------------------------------
/tests/sample_reports/url_attachment:
--------------------------------------------------------------------------------
1 | {
2 | "type": "url",
3 | "bthash": "2dd542ba1f1e074216196b6c0bd548609bf38ebc",
4 | "data": "http://example.org"
5 | }
6 |
--------------------------------------------------------------------------------
/src/pyfaf/celery_tasks/Makefile.am:
--------------------------------------------------------------------------------
1 | celery_tasks_PYTHON = \
2 | __init__.py \
3 | schedulers.py
4 |
5 | celery_tasksdir = $(pythondir)/pyfaf/celery_tasks
6 |
--------------------------------------------------------------------------------
/tests/sample_reports/bugzilla_attachment:
--------------------------------------------------------------------------------
1 | {
2 | "type": "fedora-bugzilla",
3 | "bthash": "2dd542ba1f1e074216196b6c0bd548609bf38ebc",
4 | "data": "123456"
5 | }
6 |
--------------------------------------------------------------------------------
/tests/sample_rpms/sample-provides-too-long-1-1.fc33.noarch.rpm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/abrt/faf/HEAD/tests/sample_rpms/sample-provides-too-long-1-1.fc33.noarch.rpm
--------------------------------------------------------------------------------
/src/pyfaf/storage/fixtures/sql/builds.sql:
--------------------------------------------------------------------------------
1 | INSERT INTO builds VALUES(1,348366,NULL,2,0,'2.15','56.fc17');
2 | INSERT INTO builds VALUES(2,344069,NULL,1,0,'0.2','1.fc17');
3 |
--------------------------------------------------------------------------------
/tests/sample_reports/contact_email_attachment:
--------------------------------------------------------------------------------
1 | {
2 | "type": "email",
3 | "bthash": "2dd542ba1f1e074216196b6c0bd548609bf38ebc",
4 | "data": "h4xx0r@1337.com"
5 | }
6 |
--------------------------------------------------------------------------------
/src/webfaf/templates/stats/Makefile.am:
--------------------------------------------------------------------------------
1 | stats_templ_DATA = by_date.html
2 |
3 | stats_templdir = $(pythondir)/webfaf/templates/stats
4 |
5 | EXTRA_DIST = $(stats_templ_DATA)
6 |
--------------------------------------------------------------------------------
/.tito/packages/.readme:
--------------------------------------------------------------------------------
1 | the .tito/packages directory contains metadata files
2 | named after their packages. Each file has the latest tagged
3 | version and the project's relative directory.
4 |
--------------------------------------------------------------------------------
/src/webfaf/blueprints/Makefile.am:
--------------------------------------------------------------------------------
1 | blueprints_PYTHON = \
2 | __init__.py \
3 | celery_tasks.py \
4 | symbol_transfer.py
5 |
6 | blueprintsdir = $(pythondir)/webfaf/blueprints
7 |
--------------------------------------------------------------------------------
/src/webfaf/templates/summary/index_plot_data.html:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/tests/sample_reports/comment_attachment:
--------------------------------------------------------------------------------
1 | {
2 | "type": "comment",
3 | "bthash": "2dd542ba1f1e074216196b6c0bd548609bf38ebc",
4 | "data": "It crashed. I don't know why. Plz help."
5 | }
6 |
--------------------------------------------------------------------------------
/tests/sample_repo/dummy_repo.repo:
--------------------------------------------------------------------------------
1 | [repo1]
2 | name=Repo1
3 | baseurl=file:///some/where
4 | gpgcheck=0
5 |
6 | [repo2]
7 | name=Repo2
8 | baseurl=file:///some/other/place
9 | gpgcheck=0
10 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/fixtures/sql/buildarchs.sql:
--------------------------------------------------------------------------------
1 | INSERT INTO buildarchs VALUES(1,1);
2 | INSERT INTO buildarchs VALUES(1,2);
3 | INSERT INTO buildarchs VALUES(2,1);
4 | INSERT INTO buildarchs VALUES(2,2);
5 |
--------------------------------------------------------------------------------
/src/webfaf/templates/summary/Makefile.am:
--------------------------------------------------------------------------------
1 | summary_templ_DATA = index.html index_plot_data.html
2 |
3 | summary_templdir = $(pythondir)/webfaf/templates/summary
4 |
5 | EXTRA_DIST = $(summary_templ_DATA)
6 |
--------------------------------------------------------------------------------
/config/plugins/centosmantisbt.conf:
--------------------------------------------------------------------------------
1 | [centos-mantisbt]
2 | api_url=https://bugs.centos.org/api/soap/mantisconnect.php?wsdl
3 | web_url=https://bugs.centos.org/view.php?id=
4 | user=
5 | password=
6 | abbr=CENTOS
7 |
--------------------------------------------------------------------------------
/src/webfaf/static/icons/Makefile.am:
--------------------------------------------------------------------------------
1 | icon_DATA = \
2 | hicolor_apps_16x16_abrt.png \
3 | hicolor_apps_32x32_abrt.png
4 |
5 |
6 | icondir = $(datadir)/faf/web/static/icons/
7 |
8 | EXTRA_DIST = $(icon_DATA)
9 |
--------------------------------------------------------------------------------
/mypy.ini:
--------------------------------------------------------------------------------
1 | [mypy]
2 | disallow_untyped_calls = True
3 | pretty = True
4 | show_column_numbers = True
5 | show_error_codes = True
6 | show_error_context = True
7 | strict_equality = True
8 | warn_unreachable = True
9 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/migrations/Makefile.am:
--------------------------------------------------------------------------------
1 | SUBDIRS = versions
2 |
3 | migrations_PYTHON = \
4 | __init__.py \
5 | alembic.ini \
6 | env.py
7 |
8 | migrationsdir = $(pythondir)/pyfaf/storage/migrations
9 |
--------------------------------------------------------------------------------
/src/webfaf/templates/mdpage.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block title %}{{ mddoc.title }}{% endblock %}
4 |
5 | {% block body %}
6 | {{ mddoc.title }}
7 | {{ mddoc.body | safe }}
8 | {% endblock %}
9 |
--------------------------------------------------------------------------------
/AUTHORS:
--------------------------------------------------------------------------------
1 | Michal Toman
2 | Richard Marko
3 | Miroslav Lichvar
4 | Jakub Filak
5 | Martin Milata
6 | Marek Brysa
7 | Karel Klic
8 |
--------------------------------------------------------------------------------
/src/pyfaf/solutionfinders/Makefile.am:
--------------------------------------------------------------------------------
1 | solutionfinders_PYTHON = \
2 | __init__.py \
3 | prefilter_solution_finder.py \
4 | probable_fix_solution_finder.py
5 |
6 | solutionfindersdir = $(pythondir)/pyfaf/solutionfinders
7 |
--------------------------------------------------------------------------------
/src/webfaf/templates/404.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block title %}Page Not Found{% endblock %}
4 |
5 | {% block body %}
6 |
7 | Page not found.
8 |
9 |
10 | {% endblock %}
11 |
--------------------------------------------------------------------------------
/src/pyfaf/problemtypes/Makefile.am:
--------------------------------------------------------------------------------
1 | problemtypes_PYTHON = \
2 | __init__.py \
3 | core.py \
4 | java.py \
5 | kerneloops.py \
6 | python.py \
7 | ruby.py
8 |
9 | problemtypesdir = $(pythondir)/pyfaf/problemtypes
10 |
--------------------------------------------------------------------------------
/tests/test_webfaf/Makefile.am:
--------------------------------------------------------------------------------
1 | SUBDIRS = webfaftests
2 |
3 | TESTS = test_problems.py test_reports.py test_summary.py test_user.py
4 |
5 | check_SCRIPTS = $(TESTS)
6 |
7 | check-local: check-TESTS
8 |
9 | EXTRA_DIST = $(check_SCRIPTS)
10 |
--------------------------------------------------------------------------------
/src/pyfaf/repos/Makefile.am:
--------------------------------------------------------------------------------
1 | repos_PYTHON = \
2 | __init__.py \
3 | dnf.py \
4 | rpm_metadata.py
5 |
6 | EXTRA_DIST = $(repos_PYTHON)
7 |
8 | am__repos_PYTHON_DIST = $(repos_PYTHON)
9 |
10 | reposdir = $(pythondir)/pyfaf/repos
11 |
--------------------------------------------------------------------------------
/config/celery-worker-env.conf:
--------------------------------------------------------------------------------
1 | CELERY_APP="pyfaf.celery_tasks.celery_app"
2 | CELERYD_NODES="worker"
3 | CELERYD_OPTS=""
4 | CELERYD_PID_FILE="/run/faf-celery/faf-celery-%n.pid"
5 | CELERYD_LOG_FILE="/var/log/faf/faf-celery-%n.log"
6 | CELERYD_LOG_LEVEL="INFO"
7 |
--------------------------------------------------------------------------------
/src/bin/Makefile.am:
--------------------------------------------------------------------------------
1 | bin_SCRIPTS = faf faf-migrate-db
2 |
3 | bashcompdir = $(sysconfdir)/bash_completion.d
4 |
5 | dist_bashcomp_DATA = \
6 | faf.bash_completion \
7 | faf-migrate-db.bash_completion
8 |
9 | EXTRA_DIST = $(bin_SCRIPTS)
10 |
--------------------------------------------------------------------------------
/src/pyfaf/bugtrackers/Makefile.am:
--------------------------------------------------------------------------------
1 | bugtrackers_PYTHON = \
2 | __init__.py \
3 | bugzilla.py \
4 | fedorabz.py \
5 | mantisbt.py \
6 | centosmantisbt.py \
7 | rhelbz.py
8 |
9 | bugtrackersdir = $(pythondir)/pyfaf/bugtrackers
10 |
--------------------------------------------------------------------------------
/src/webfaf/templates/403.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block title %}Forbidden{% endblock %}
4 |
5 | {% block body %}
6 |
7 | This page is only accessible for authorized users.
8 |
9 | {% endblock %}
10 |
--------------------------------------------------------------------------------
/config/plugins/java.conf:
--------------------------------------------------------------------------------
1 | [Processing]
2 | # Uncomment whatever is necessary to override the default
3 |
4 | # JavaHashFrames = 16
5 | # JavaCmpFrames = 16
6 | # JavaCutThreshold = 0.3
7 | # JavaNormalize = yes
8 |
9 | [Retrace]
10 | # JavaSkipSource = yes
11 |
--------------------------------------------------------------------------------
/config/plugins/ruby.conf:
--------------------------------------------------------------------------------
1 | [Processing]
2 | # Uncomment whatever is necessary to override the default
3 |
4 | # RubyHashFrames = 16
5 | # RubyCmpFrames = 16
6 | # RubyCutThreshold = 0.3
7 | # RubyNormalize = yes
8 |
9 | [Retrace]
10 | # RubySkipSource = yes
11 |
--------------------------------------------------------------------------------
/config/plugins/coredump.conf:
--------------------------------------------------------------------------------
1 | [Processing]
2 | # Uncomment whatever is necessary to override the default
3 |
4 | # CoreHashFrames = 16
5 | # CoreCmpFrames = 16
6 | # CoreCutThreshold = 0.3
7 | # CoreNormalize = yes
8 |
9 | [Retrace]
10 | # CoreSkipSource = yes
11 |
--------------------------------------------------------------------------------
/config/plugins/kerneloops.conf:
--------------------------------------------------------------------------------
1 | [Processing]
2 | # Uncomment whatever is necessary to override the default
3 |
4 | # OopsHashFrames = 16
5 | # OopsCmpFrames = 16
6 | # OopsCutThreshold = 0.3
7 | # OopsNormalize = yes
8 |
9 | [Retrace]
10 | # OopsSkipSource = yes
11 |
--------------------------------------------------------------------------------
/config/plugins/rhelbz.conf:
--------------------------------------------------------------------------------
1 | [rhel-bugzilla]
2 | api_url=https://bugzilla.redhat.com/xmlrpc.cgi
3 | web_url=https://bugzilla.redhat.com/show_bug.cgi?id=
4 | new_bug_url=https://bugzilla.redhat.com/enter_bug.cgi
5 | save_comments=false
6 | save_attachments=false
7 | api_key=
8 |
--------------------------------------------------------------------------------
/config/plugins/fedorabz.conf:
--------------------------------------------------------------------------------
1 | [fedora-bugzilla]
2 | api_url=https://bugzilla.redhat.com/xmlrpc.cgi
3 | web_url=https://bugzilla.redhat.com/show_bug.cgi?id=
4 | new_bug_url=https://bugzilla.redhat.com/enter_bug.cgi
5 | save_comments=false
6 | save_attachments=false
7 | api_key=
8 |
--------------------------------------------------------------------------------
/config/plugins/python.conf:
--------------------------------------------------------------------------------
1 | [Processing]
2 | # Uncomment whatever is necessary to override the default
3 |
4 | # PythonHashFrames = 16
5 | # PythonCmpFrames = 16
6 | # PythonCutThreshold = 0.3
7 | # PythonNormalize = yes
8 |
9 | [Retrace]
10 | # PythonSkipSource = yes
11 |
--------------------------------------------------------------------------------
/src/webfaf/static/css/Makefile.am:
--------------------------------------------------------------------------------
1 | css_DATA = \
2 | bootstrap-multiselect.css \
3 | bootstrap-tagsinput.css \
4 | daterangepicker-bs3.css \
5 | style.css \
6 | typeaheadjs.css
7 |
8 | cssdir = $(datadir)/faf/web/static/css/
9 |
10 | EXTRA_DIST = $(css_DATA)
11 |
--------------------------------------------------------------------------------
/config/plugins/fedora.conf:
--------------------------------------------------------------------------------
1 | [Fedora]
2 | FedoraPDC = https://pdc.fedoraproject.org/rest_api/v1/
3 | PagureAPI = https://src.fedoraproject.org/api/0/
4 | SupportEOL = False
5 | build-aging-days = 14
6 | koji-url = https://koji.fedoraproject.org/kojihub
7 | ignored-releases = epel*, pel*, ln, l
8 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/fixtures/sql/buildsys.sql:
--------------------------------------------------------------------------------
1 | INSERT INTO buildsys VALUES (1, 'http://koji.fedoraproject.org/kojihub', 'http://kojipkgs.fedoraproject.org/packages');
2 | INSERT INTO buildsys VALUES (2, 'http://brewhub.devel.redhat.com/brewhub', 'http://porkchop.devel.redhat.com/brewroot/packages');
3 |
--------------------------------------------------------------------------------
/src/webfaf/templates/413.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block title %}File too large{% endblock %}
4 |
5 | {% block body %}
6 |
7 | File size of the uploaded file is too large and can't be processed by the server.
8 |
9 | {% endblock %}
10 |
--------------------------------------------------------------------------------
/config/celery-beat-env.conf:
--------------------------------------------------------------------------------
1 | CELERY_APP="pyfaf.celery_tasks.celery_app"
2 | CELERYD_NODES="beat"
3 | CELERYD_OPTS="-S pyfaf.celery_tasks.schedulers.DBScheduler"
4 | CELERYD_PID_FILE="/run/faf-celery/faf-celery-beat.pid"
5 | CELERYD_LOG_FILE="/var/log/faf/faf-celery-beat.log"
6 | CELERYD_LOG_LEVEL="INFO"
7 |
--------------------------------------------------------------------------------
/tests/retrace_outputs/complex_0xffff:
--------------------------------------------------------------------------------
1 | waitForMessageFilteredWithTimeout::waitForMessage() [with DataType = WTF::Function]::__lambda0> inlined at Source/WTF/wtf/MessageQueue.h:131 in _ZN7WebCore13StorageThread16threadEntryPointEv
2 | Source/WTF/wtf/MessageQueue.c:1234
3 |
--------------------------------------------------------------------------------
/src/webfaf/templates/problems/Makefile.am:
--------------------------------------------------------------------------------
1 | problems_templ_DATA = \
2 | item.html \
3 | list.html \
4 | list_table_rows.html \
5 | multiple_bthashes.html \
6 | waitforit.html
7 |
8 | problems_templdir = $(pythondir)/webfaf/templates/problems
9 |
10 | EXTRA_DIST = $(problems_templ_DATA)
11 |
--------------------------------------------------------------------------------
/tests/test_webfaf/__init__.py:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 |
4 | # alter path so we can import from webfaftests in this directory
5 | test_webfaf_path = os.path.dirname(os.path.realpath(__file__))
6 | sys.path.insert(0, test_webfaf_path)
7 | os.environ["PATH"] = "{0}:{1}".format(test_webfaf_path, os.environ["PATH"])
8 |
--------------------------------------------------------------------------------
/repos/CentOS-Base.repo:
--------------------------------------------------------------------------------
1 | [centos-base]
2 | name=CentOS-$releasever - Base
3 | baseurl=http://mirror.centos.org/centos/$releasever/os/$basearch/
4 | gpgcheck=0
5 |
6 | [centos-updates]
7 | name=CentOS-$releasever - Updates
8 | baseurl=http://mirror.centos.org/centos/$releasever/updates/$basearch/
9 | gpgcheck=0
10 |
--------------------------------------------------------------------------------
/src/pyfaf/utils/Makefile.am:
--------------------------------------------------------------------------------
1 | utils_PYTHON = \
2 | __init__.py \
3 | contextmanager.py \
4 | date.py \
5 | decorators.py \
6 | format.py \
7 | hash.py \
8 | parse.py \
9 | proc.py \
10 | storage.py \
11 | user.py \
12 | web.py
13 |
14 | utilsdir = $(pythondir)/pyfaf/utils
15 |
--------------------------------------------------------------------------------
/src/webfaf/templates/celery_tasks/Makefile.am:
--------------------------------------------------------------------------------
1 | celery_tasks_templ_DATA = \
2 | action_run.html \
3 | index.html \
4 | results_item.html \
5 | results_list.html \
6 | schedule_item.html
7 |
8 | celery_tasks_templdir = $(pythondir)/webfaf/templates/celery_tasks
9 |
10 | EXTRA_DIST = $(celery_tasks_templ_DATA)
11 |
--------------------------------------------------------------------------------
/src/webfaf/templates/problems/waitforit.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block title %}Problem has not yet been created{% endblock %}
4 |
5 | {% block body %}
6 | The problem has not yet been created
7 | Problems are generated every few hours, try refreshing this site later.
8 | {% endblock %}
9 |
--------------------------------------------------------------------------------
/container/files/usr/libexec/fix-permissions:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # Fix permissions on the given directory to allow group read/write of
3 | # regular files and execute of directories.
4 |
5 | find ${1} -exec chown faf {} \;
6 | find ${1} -exec chgrp 0 {} \;
7 | find ${1} -exec chmod g+rw {} \;
8 | find ${1} -type d -exec chmod g+x {} \;
9 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/fixtures/Makefile.am:
--------------------------------------------------------------------------------
1 | SUBDIRS = sql
2 |
3 | pyfaf_fixtures_PYTHON = \
4 | __init__.py \
5 | data.py \
6 | randutils.py
7 | pyfaf_fixturesdir = $(pythondir)/pyfaf/storage/fixtures
8 |
9 | fixture_DATA = lob_download_location
10 | fixturedir = $(datadir)/faf/fixtures/
11 |
12 | EXTRA_DIST = $(fixture_DATA)
13 |
--------------------------------------------------------------------------------
/src/webfaf/templates/500.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block title %}Internal Server Error{% endblock %}
4 |
5 | {% block body %}
6 |
7 | Internal Server Error.
8 | This error has been logged and we will take care of it soon.
9 | Sorry.
10 |
11 |
12 | {% endblock %}
13 |
--------------------------------------------------------------------------------
/src/schema/Makefile.am:
--------------------------------------------------------------------------------
1 | EXTRA_DIST = \
2 | faf_schema \
3 | README \
4 | setup.cfg \
5 | setup.py
6 |
7 | all:
8 |
9 | all-local:
10 | $(PYTHON) setup.py build --verbose
11 |
12 | install-exec-local:
13 | $(PYTHON) setup.py install --root $(DESTDIR) \
14 | --single-version-externally-managed \
15 | --verbose
16 |
--------------------------------------------------------------------------------
/src/webfaf/templates/reports/waitforit.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block title %}Report is still being processed{% endblock %}
4 |
5 | {% block body %}
6 |
The reports was not found or is still being processed
7 | Reports are processed every few minutes, try refreshing this site in a while.
8 | {% endblock %}
9 |
--------------------------------------------------------------------------------
/src/webfaf/templates/reports/Makefile.am:
--------------------------------------------------------------------------------
1 | reports_templ_DATA = \
2 | associate_bug.html \
3 | attach.html \
4 | diff.html \
5 | item.html \
6 | list.html \
7 | list_table_rows.html \
8 | new.html \
9 | waitforit.html
10 |
11 | reports_templdir = $(pythondir)/webfaf/templates/reports
12 |
13 | EXTRA_DIST = $(reports_templ_DATA)
14 |
--------------------------------------------------------------------------------
/src/webfaf/Makefile.am:
--------------------------------------------------------------------------------
1 | SUBDIRS = blueprints static templates
2 |
3 | hub_PYTHON = \
4 | __init__.py \
5 | config.py \
6 | filters.py \
7 | forms.py \
8 | hub.wsgi \
9 | login.py \
10 | problems.py \
11 | reports.py \
12 | stats.py \
13 | summary.py \
14 | user.py \
15 | utils.py \
16 | webfaf_main.py
17 |
18 | hubdir = $(pythondir)/webfaf
19 |
--------------------------------------------------------------------------------
/docs/test_notes:
--------------------------------------------------------------------------------
1 | Running tests:
2 |
3 | - to run each test: ./faf-hub test
4 | - to run test for selected component: ./faf-hub test reports
5 | - to run specific set of tests: ./faf-hub test reports.ReportsListTest
6 | - to run single test: ./faf-hub test reports.ReportsListTest.test_entries
7 |
8 |
9 | You can increase output verbosity with -v1 -v2 -v3 options (./faf-hub test -v3)
10 |
--------------------------------------------------------------------------------
/repos/fedora-updates.repo:
--------------------------------------------------------------------------------
1 | [updates]
2 | baseurl=http://download.fedoraproject.org/pub/fedora/linux/updates/$releasever/$basearch/
3 | gpgcheck=0
4 |
5 | [updates-debuginfo]
6 | baseurl=http://download.fedoraproject.org/pub/fedora/linux/updates/$releasever/$basearch/debug/
7 | gpgcheck=0
8 |
9 | [updates-source]
10 | baseurl=http://download.fedoraproject.org/pub/fedora/linux/updates/$releasever/SRPMS/
11 | gpgcheck=0
12 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/fixtures/sql/opsyscomponents.sql:
--------------------------------------------------------------------------------
1 | -- Fedora
2 | INSERT INTO opsyscomponents VALUES (1, 'will-crash', 1);
3 | INSERT INTO opsyscomponents VALUES (2, 'glibc', 1);
4 | INSERT INTO opsyscomponents VALUES (3, 'kernel', 1);
5 |
6 | -- EL
7 | INSERT INTO opsyscomponents VALUES (4, 'will-crash', 2);
8 | INSERT INTO opsyscomponents VALUES (5, 'glibc', 2);
9 | INSERT INTO opsyscomponents VALUES (6, 'kernel', 2);
10 |
--------------------------------------------------------------------------------
/repos/fedora-rawhide.repo:
--------------------------------------------------------------------------------
1 | [rawhide]
2 | baseurl=http://download.fedoraproject.org/pub/fedora/linux/development/rawhide/$basearch/os/
3 | gpgcheck=0
4 |
5 | [rawhide-debuginfo]
6 | baseurl=http://download.fedoraproject.org/pub/fedora/linux/development/rawhide/$basearch/debug/
7 | gpgcheck=0
8 |
9 | [rawhide-source]
10 | baseurl=http://download.fedoraproject.org/pub/fedora/linux/development/rawhide/source/SRPMS/
11 | gpgcheck=0
12 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | alembic ~= 1.4.2
2 | argcomplete ~= 1.12.0
3 | cachelib ~= 0.1.1
4 | celery >= 5.2.2
5 | fedora-messaging ~= 2.1.0
6 | flask ~= 1.1.2
7 | Flask-OpenID ~= 1.2.5
8 | Flask-SQLAlchemy ~= 2.4.4
9 | koji ~= 1.24.1
10 | markdown2 ~= 2.4.0
11 | munch ~= 2.5.0
12 | python-bugzilla ~= 3.0.2
13 | python-openid-teams ~= 1.1
14 | requests ~= 2.24.0
15 | SQLAlchemy ~= 1.3.24
16 | Werkzeug ~= 1.0.1
17 | WTForms ~= 2.3.3
18 | zeep ~= 3.4.0
19 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/fixtures/sql/opsysreleases.sql:
--------------------------------------------------------------------------------
1 | -- (id, opsys_id, version, releasedate, status)
2 |
3 | INSERT INTO opsysreleases VALUES (1, 1, '15', NULL, 'EOL');
4 | INSERT INTO opsysreleases VALUES (2, 1, '16', NULL, 'ACTIVE');
5 | INSERT INTO opsysreleases VALUES (3, 1, '17', NULL, 'ACTIVE');
6 | INSERT INTO opsysreleases VALUES (4, 1, 'devel', NULL, 'UNDER_DEVELOPMENT');
7 | INSERT INTO opsysreleases VALUES (5, 2, '7.0', NULL, 'ACTIVE');
8 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/migrations/alembic.ini:
--------------------------------------------------------------------------------
1 | # A generic, single database configuration.
2 |
3 | [alembic]
4 | # path to migration scripts
5 | script_location = .
6 |
7 | # template used to generate migration files
8 | # file_template = %%(rev)s_%%(slug)s
9 |
10 | # set to 'true' to run the environment during
11 | # the 'revision' command, regardless of autogenerate
12 | # revision_environment = false
13 |
14 | sqlalchemy.url = postgresql:///faf
15 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/fixtures/sql/Makefile.am:
--------------------------------------------------------------------------------
1 | fixture_sql_DATA = \
2 | archs.sql \
3 | archstags.sql \
4 | buildarchs.sql \
5 | builds.sql \
6 | buildstags.sql \
7 | buildsys.sql \
8 | opsys.sql \
9 | opsyscomponents.sql \
10 | opsysreleases.sql \
11 | opsysreleasescomponents.sql \
12 | packages.sql \
13 | taginheritances.sql \
14 | tags.sql
15 |
16 | fixture_sqldir = $(datadir)/faf/fixtures/sql/
17 |
18 | EXTRA_DIST = $(fixture_sql_DATA)
19 |
--------------------------------------------------------------------------------
/init-scripts/faf-celery-tmpfiles.conf:
--------------------------------------------------------------------------------
1 | # This file is part of faf.
2 | #
3 | # faf is free software: you can redistribute it and/or modify
4 | # it under the terms of the GNU General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version.
7 |
8 | # See tmpfiles.d(5) for details
9 |
10 | #Type Path Mode User Group Age
11 | d /run/faf-celery 0755 faf faf -
12 |
--------------------------------------------------------------------------------
/repos/fedora-updates-testing.repo:
--------------------------------------------------------------------------------
1 | [updates-testing]
2 | baseurl=http://download.fedoraproject.org/pub/fedora/linux/updates/testing/$releasever/$basearch/
3 | gpgcheck=0
4 |
5 | [updates-testing-debuginfo]
6 | baseurl=http://download.fedoraproject.org/pub/fedora/linux/updates/testing/$releasever/$basearch/debug/
7 | gpgcheck=0
8 |
9 | [updates-testing-source]
10 | baseurl=http://download.fedoraproject.org/pub/fedora/linux/updates/testing/$releasever/SRPMS/
11 | gpgcheck=0
12 |
--------------------------------------------------------------------------------
/repos/fedora.repo:
--------------------------------------------------------------------------------
1 | [fedora]
2 | failovermethod=priority
3 | baseurl=http://download.fedoraproject.org/pub/fedora/linux/releases/$releasever/Everything/$basearch/os/
4 | gpgcheck=0
5 |
6 | [fedora-debuginfo]
7 | baseurl=http://download.fedoraproject.org/pub/fedora/linux/releases/$releasever/Everything/$basearch/debug/
8 | gpgcheck=0
9 |
10 | [fedora-source]
11 | baseurl=http://download.fedoraproject.org/pub/fedora/linux/releases/$releasever/Everything/source/SRPMS/
12 | gpgcheck=0
13 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/fixtures/sql/opsysreleasescomponents.sql:
--------------------------------------------------------------------------------
1 | -- will-crash, glibc, kernel for F17
2 | INSERT INTO opsysreleasescomponents VALUES (1, 3, 1);
3 | INSERT INTO opsysreleasescomponents VALUES (2, 3, 2);
4 | INSERT INTO opsysreleasescomponents VALUES (3, 3, 3);
5 |
6 | -- will-crash, glibc, kernel for EL7
7 | INSERT INTO opsysreleasescomponents VALUES (4, 5, 4);
8 | INSERT INTO opsysreleasescomponents VALUES (5, 5, 5);
9 | INSERT INTO opsysreleasescomponents VALUES (6, 5, 6);
10 |
--------------------------------------------------------------------------------
/.git-commit-template:
--------------------------------------------------------------------------------
1 | COMPONENT: Subject
2 |
3 | Explanation
4 |
5 | Resolves:
6 | https://github.com/abrt/faf/issues/XXXX
7 | https://bugzilla.redhat.com/show_bug.cgi?id=XXXXXX
8 |
9 | # Try to keep the subject line within 52 chars ----|
10 | # Also please try to not exceed 72 characters of length for the body --|
11 | # Avoid using exact file names as COMPONENT. Use keywords such as spec,
12 | # client, dump_dir etc. You do not need to follow this template 100%.
13 | # See git log for examples.
14 |
--------------------------------------------------------------------------------
/init-scripts/faf.conf:
--------------------------------------------------------------------------------
1 | # This file is part of faf.
2 | #
3 | # faf is free software: you can redistribute it and/or modify
4 | # it under the terms of the GNU General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version.
7 |
8 | # See tmpfiles.d(5) for details
9 |
10 | #Type Path Mode User Group Age
11 | d /tmp/faf 0755 faf faf 28d
12 | d /tmp/faf/rpm 0755 faf faf 1d
13 |
--------------------------------------------------------------------------------
/src/webfaf/templates/problems/multiple_bthashes.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block title %}Multiple problems found{% endblock %}
4 |
5 | {% block body %}
6 | Multiple problems found
7 | Multiple problem have been found for the backtrace hashes you specified.
8 |
9 | {% for problem in problems %}
10 | - #{{problem.id}}
11 | {% endfor %}
12 |
13 | {% endblock %}
14 |
--------------------------------------------------------------------------------
/lgtm.yml:
--------------------------------------------------------------------------------
1 | extraction:
2 | javascript:
3 | index:
4 | exclude: "*"
5 | include: "src/webfaf/static/js/custom.js"
6 | python:
7 | prepare:
8 | packages:
9 | - autoconf
10 | - automake
11 | - autopoint
12 | - intltool
13 | - libtool
14 | - make
15 | - python3-dev
16 | after_prepare:
17 | - ./autogen.sh
18 | - make
19 | python_setup:
20 | requirements_files: false
21 | setup_py: false
22 | version: 3
23 |
--------------------------------------------------------------------------------
/src/webfaf/hub.wsgi:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 | import os
3 | import sys
4 | import logging
5 |
6 | logging.basicConfig(stream=sys.stderr)
7 | os.environ["WEBFAF_ENVIRON_PRODUCTION"] = "1"
8 | sys.path.insert(0, os.path.dirname(__file__))
9 |
10 | # We can only import from webfaf once the PYTHONPATH has been set up above.
11 | # pylint: disable=wrong-import-position
12 | from webfaf.webfaf_main import app as application
13 | from webfaf.webfaf_main import import_blueprint_plugins
14 | import_blueprint_plugins(application)
15 |
--------------------------------------------------------------------------------
/src/webfaf/templates/Makefile.am:
--------------------------------------------------------------------------------
1 | SUBDIRS = \
2 | celery_tasks \
3 | problems \
4 | reports \
5 | stats \
6 | summary
7 |
8 | template_DATA = \
9 | _helpers.html \
10 | 403.html \
11 | 404.html \
12 | 413.html \
13 | 500.html \
14 | about.md \
15 | base.html \
16 | mdpage.html
17 |
18 | templatedir = $(pythondir)/webfaf/templates
19 |
20 | # Use README.md from project root
21 | about.md: about.md.in
22 | cp ../../../README.md about.md
23 |
24 | EXTRA_DIST = $(template_DATA) about.md.in
25 |
--------------------------------------------------------------------------------
/init-scripts/faf-celery-beat.service:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=FAF Celery beat
3 | After=network.target
4 |
5 | [Service]
6 | User=faf
7 | Group=faf
8 | EnvironmentFile=/etc/faf/celery-beat-env.conf
9 | WorkingDirectory=/etc/faf
10 | ExecStart=/usr/bin/python3 -m celery -C -A $CELERY_APP beat \
11 | --pidfile=${CELERYD_PID_FILE} \
12 | --logfile=${CELERYD_LOG_FILE} \
13 | --loglevel=${CELERYD_LOG_LEVEL} \
14 | $CELERYD_OPTS
15 | PIDFile=${CELERYD_PID_FILE}
16 |
17 | [Install]
18 | WantedBy=multi-user.target
19 |
--------------------------------------------------------------------------------
/config/plugins/centos.conf:
--------------------------------------------------------------------------------
1 | [CentOS]
2 | repo-urls=http://vault.centos.org/centos/$releasever/os/Source/
3 | http://vault.centos.org/centos/$releasever/updates/Source/
4 | http://vault.centos.org/centos/$releasever/AppStream/Source/
5 | http://vault.centos.org/centos/$releasever/BaseOS/Source/
6 | http://vault.centos.org/centos/$releasever-stream/AppStream/Source/
7 | http://vault.centos.org/centos/$releasever-stream/BaseOS/Source/
8 |
9 | inactive-releases=
10 | active-releases=7
11 |
--------------------------------------------------------------------------------
/src/pyfaf/Makefile.am:
--------------------------------------------------------------------------------
1 | SUBDIRS = \
2 | actions \
3 | bugtrackers \
4 | celery_tasks \
5 | opsys \
6 | problemtypes \
7 | repos \
8 | solutionfinders \
9 | storage \
10 | utils
11 |
12 | pyfaf_PYTHON = \
13 | __init__.py \
14 | checker.py \
15 | cmdline.py \
16 | common.py \
17 | config.py \
18 | local.py \
19 | retrace.py \
20 | faf_rpm.py \
21 | queries.py \
22 | ureport.py \
23 | ureport_compat.py
24 |
25 | pyfafdir = $(pythondir)/pyfaf
26 |
27 | EXTRA_DIST = $(pyfaf_PYTHON)
28 |
--------------------------------------------------------------------------------
/src/webfaf/templates/reports/new.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 | {% from "_helpers.html" import render_field %}
3 |
4 | {% block title %}New report{% endblock %}
5 |
6 | {% block body %}
7 |
8 |
9 |
Submit uReport file
10 |
14 |
15 |
16 | {% endblock %}
17 |
--------------------------------------------------------------------------------
/src/webfaf/static/js/Makefile.am:
--------------------------------------------------------------------------------
1 | js_DATA = \
2 | bootstrap.js \
3 | bootstrap-multiselect.js \
4 | bootstrap-tagsinput.js \
5 | color.js \
6 | custom.js \
7 | daterangepicker.js \
8 | jquery.flot.axislabels.js \
9 | jquery.flot.js \
10 | jquery.flot.pie.js \
11 | jquery.flot.resize.js \
12 | jquery.flot.simplelabel.js \
13 | jquery.flot.stack.js \
14 | jquery.flot.symbol.js \
15 | jquery.flot.time.js \
16 | moment.js \
17 | typeahead.bundle.min.js
18 |
19 | jsdir = $(datadir)/faf/web/static/js/
20 |
21 | EXTRA_DIST = $(js_DATA)
22 |
--------------------------------------------------------------------------------
/src/webfaf/templates/reports/attach.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 | {% from "_helpers.html" import render_field %}
3 |
4 | {% block title %}New attachment{% endblock %}
5 |
6 | {% block body %}
7 |
8 |
9 |
Submit attachment file
10 |
14 |
15 |
16 | {% endblock %}
17 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/Makefile.am:
--------------------------------------------------------------------------------
1 | SUBDIRS = \
2 | fixtures \
3 | migrations
4 |
5 | storage_PYTHON = \
6 | __init__.py \
7 | bugzilla.py \
8 | bugtracker.py \
9 | custom_types.py \
10 | debug.py \
11 | events.py \
12 | events_fedmsg.py \
13 | externalfaf.py \
14 | generic_table.py \
15 | jsontype.py \
16 | llvm.py \
17 | opsys.py \
18 | mantisbt.py \
19 | problem.py \
20 | project.py \
21 | report.py \
22 | sf_prefilter.py \
23 | symbol.py \
24 | task.py \
25 | user.py
26 |
27 | storagedir = $(pythondir)/pyfaf/storage
28 |
--------------------------------------------------------------------------------
/tests/sample_reports/Makefile.am:
--------------------------------------------------------------------------------
1 | EXTRA_DIST = bugzilla_attachment comment_attachment contact_email_attachment \
2 | url_attachment \
3 | tainted_kernel ureport1 ureport2 ureport_f20 low_quality1 \
4 | ureport_core ureport_core1 ureport_core_invalid \
5 | ureport_java ureport_kerneloops ureport_kerneloops2 \
6 | ureport_python ureport_ruby \
7 | ureport_systemd2 ureport_systemd77 ureport_kerneloops_nouveau \
8 | ureport_duplicate ureport_duplicate2 ureport_duplicate3 \
9 | ureport_duplicate4 ureport_solution ureport_solution_99
10 |
--------------------------------------------------------------------------------
/tests/faftests/test_config.conf:
--------------------------------------------------------------------------------
1 | [Storage]
2 | ConnectString = sqlite:////tmp/faf_test_data/sqlite.db
3 | LobDir = /tmp/faf_test_data/lob
4 |
5 | [Ureport]
6 | Directory = /tmp/faf_test_data/reports/
7 | AcceptAttachments = *
8 | # allowed values for known
9 | # BUG_OS_MAJOR_VERSION BUG_OS_MINOR_VERSION EQUAL_UREPORT_EXISTS
10 | Known =
11 |
12 | [Hub]
13 | debug = True
14 | proxy_setup = False
15 | secret_key = "NO."
16 | server_name = example.org
17 |
18 | [openid]
19 | enabled=true
20 |
21 | [fakebugzilla]
22 | api_url = http://fake_test_api_url
23 | web_url = http://fake_test_web_url
24 | api_key = FAKE_API_KEY_QR43290T4V743BN
25 |
--------------------------------------------------------------------------------
/tests/retrace_outputs/Makefile.am:
--------------------------------------------------------------------------------
1 | EXTRA_DIST= \
2 | last_chance_0x0 \
3 | last_chance_0x1 \
4 | last_chance_0x2 \
5 | last_chance_0x3 \
6 | last_chance_0x4 \
7 | last_chance_0x5 \
8 | last_chance_0x6 \
9 | last_chance_0x7 \
10 | last_chance_0x8 \
11 | last_chance_0x9 \
12 | last_chance_0xa \
13 | last_chance_0xb \
14 | last_chance_0xc \
15 | last_chance_0xd \
16 | last_chance_0xe \
17 | last_chance_0xf \
18 | last_chance_0x10 \
19 | third_full_0xd \
20 | third_full_0xe \
21 | third_full_0xf \
22 | other_source_0xe \
23 | other_source_0xf \
24 | other_line_0xe \
25 | other_line_0xf \
26 | complex_0xffff
27 |
--------------------------------------------------------------------------------
/config/plugins/Makefile.am:
--------------------------------------------------------------------------------
1 | pluginconf_DATA = \
2 | centos.conf \
3 | clonebz.conf \
4 | centosmantisbt.conf \
5 | celery_tasks.conf \
6 | coredump.conf \
7 | create-problems.conf \
8 | dnf.conf \
9 | fedora.conf \
10 | fedorabz.conf \
11 | fedmsg.conf \
12 | java.conf \
13 | kerneloops.conf \
14 | pull-reports.conf \
15 | python.conf \
16 | retrace.conf \
17 | retrace-remote.conf \
18 | ruby.conf \
19 | rhelbz.conf \
20 | save-reports.conf \
21 | sf-prefilter.conf \
22 | symbol-transfer.conf \
23 | web.conf
24 |
25 | pluginconfdir = $(sysconfdir)/faf/plugins
26 |
27 | EXTRA_DIST = $(pluginconf_DATA)
28 |
--------------------------------------------------------------------------------
/tests/Makefile.am:
--------------------------------------------------------------------------------
1 | SUBDIRS = faftests sample_plugin_dir sample_reports sample_rpms test_webfaf \
2 | retrace_outputs bin sample_repo
3 |
4 | TESTS = test_actions.py \
5 | test_alembic.py \
6 | test_bugzilla.py \
7 | test_common.py \
8 | test_create_problems.py \
9 | test_checker.py \
10 | test_find_report_solution.py \
11 | test_mark_probably_fixed.py \
12 | test_queries.py \
13 | test_rpm.py \
14 | test_save_reports.py \
15 | test_storage.py \
16 | test_stats.py \
17 | test_report.py \
18 | test_ureport.py \
19 | test_utils.py \
20 | test_rpm_metadata.py \
21 | test_retrace.py \
22 | test_dnf.py
23 |
24 | check_SCRIPTS = $(TESTS)
25 |
26 | check-local: check-TESTS
27 |
28 | EXTRA_DIST = $(check_SCRIPTS)
29 |
--------------------------------------------------------------------------------
/Makefile.am:
--------------------------------------------------------------------------------
1 | ACLOCAL_AMFLAGS = -I m4
2 |
3 | SUBDIRS = config src tests
4 |
5 | EXTRA_DIST = autogen.sh faf-version faf.spec \
6 | init-scripts/faf-celery-beat.service \
7 | init-scripts/faf-celery-worker.service \
8 | init-scripts/faf-celery-tmpfiles.conf \
9 | pylintrc README.md
10 |
11 |
12 |
13 | if HAVE_SYSTEMD
14 | systemdsystemunitdir=$(prefix)/lib/systemd/system/
15 | systemdsystemunit_DATA = init-scripts/faf-celery-beat.service \
16 | init-scripts/faf-celery-worker.service
17 | systemdtmpfilesdir=$(prefix)/lib/tmpfiles.d/
18 | systemdtmpfiles_DATA = init-scripts/faf.conf \
19 | init-scripts/faf-celery-tmpfiles.conf
20 | endif
21 |
--------------------------------------------------------------------------------
/container/Dockerfile_db:
--------------------------------------------------------------------------------
1 | FROM docker.io/centos/postgresql-12-centos7
2 |
3 | USER root
4 |
5 | # Adds the semver extension on top of the official image
6 | RUN yum install --assumeyes epel-release && \
7 | yum install --assumeyes gcc make rh-postgresql12-postgresql-devel wget which && \
8 | yum clean all
9 |
10 | ENV PG_SEMVER_VERSION=0.32.0
11 | ENV PG_CONFIG=/opt/rh/rh-postgresql12/root/usr/bin/pg_config
12 | RUN cd /tmp/ && \
13 | wget https://github.com/theory/pg-semver/archive/refs/tags/v${PG_SEMVER_VERSION}.tar.gz && \
14 | tar xvf v${PG_SEMVER_VERSION}.tar.gz && \
15 | cd pg-semver-${PG_SEMVER_VERSION}/ && \
16 | make && \
17 | make install
18 |
19 | # Run the container as user postgres
20 | USER 26
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.o
2 | *.pyc
3 | *.pyo
4 | *~
5 | .deps
6 | Makefile
7 | Makefile.in
8 | /m4
9 | /missing
10 | /compile
11 | /py-compile
12 | /configure
13 | /ltmain.sh
14 | /install-sh
15 | /depcomp
16 | faf-version
17 |
18 | /*.1
19 | /*.html
20 | /*.src.rpm
21 | /*.tar.xz
22 | /*.tar.gz
23 | /aclocal.m4
24 | /autom4te.cache
25 | /config.log
26 | /config.status
27 | /config.sub
28 | /config.guess
29 | /faf-*/
30 | /faf.conf
31 | /faf.html/
32 | /faf.info
33 | /i686
34 | /libtool
35 | /noarch
36 | /stamp-vti
37 | /texinfo.tex
38 | /version.texi
39 | /x86_64
40 | /tests/**/*.trs
41 | /test-driver
42 | /config/faf.conf
43 | /config/faf-web.conf
44 | /config/faf-web.conf
45 | /tests/**/*.log
46 | src/webfaf/templates/about.md
47 |
48 | .mypy_cache/
49 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/fixtures/sql/archs.sql:
--------------------------------------------------------------------------------
1 | INSERT INTO archs VALUES (1, 'x86_64');
2 | INSERT INTO archs VALUES (2, 'i686');
3 | INSERT INTO archs VALUES (3, 'i586');
4 | INSERT INTO archs VALUES (4, 'i486');
5 | INSERT INTO archs VALUES (5, 'i386');
6 | INSERT INTO archs VALUES (6, 'ppc');
7 | INSERT INTO archs VALUES (7, 'ppc64');
8 | INSERT INTO archs VALUES (8, 'noarch');
9 | INSERT INTO archs VALUES (9, 'src');
10 | INSERT INTO archs VALUES (10, 's390x');
11 | INSERT INTO archs VALUES (11, 's390');
12 | INSERT INTO archs VALUES (12, 'ia64');
13 | INSERT INTO archs VALUES (13, 'alpha');
14 | INSERT INTO archs VALUES (14, 'sparc');
15 | INSERT INTO archs VALUES (15, 'sparc64');
16 | INSERT INTO archs VALUES (16, 'x86_x65');
17 | INSERT INTO archs VALUES (17, 'i3868');
18 |
--------------------------------------------------------------------------------
/container/podman-compose.yaml:
--------------------------------------------------------------------------------
1 | version: "3.8"
2 | services:
3 | faf-db:
4 | image: quay.io/fedoraci/faf-db:latest
5 | restart: always
6 | ports:
7 | - 5432:5432
8 | volumes:
9 | - faf-volume:/var/lib/pgsql/data:Z
10 | environment:
11 | POSTGRESQL_ADMIN_PASSWORD: scrt
12 | faf-redis:
13 | image: redis:latest
14 | restart: always
15 | ports:
16 | - 6379:6379
17 | faf:
18 | image: quay.io/fedoraci/faf:latest
19 | restart: always
20 | ports:
21 | - 8080:8080
22 | depends_on:
23 | - faf-db
24 | environment:
25 | PGHOST: faf-db
26 | PGUSER: postgres
27 | PGPASSWORD: scrt
28 | PGPORT: 5432
29 | PGDATABASE: faf
30 | RDSBROKER: "redis://faf-redis:6379/0"
31 | RDSBACKEND: "redis://faf-redis:6379/0"
32 |
--------------------------------------------------------------------------------
/container/files/usr/bin/faf-celery-worker:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | source /etc/faf/celery-worker-env.conf
4 |
5 | case $1 in
6 | start)
7 | /usr/bin/python3 -m celery -C -A $CELERY_APP multi start $CELERYD_NODES \
8 | --pidfile=${CELERYD_PID_FILE} \
9 | --logfile=${CELERYD_LOG_FILE} \
10 | --loglevel="${CELERYD_LOG_LEVEL}" \
11 | $CELERYD_OPTS &
12 | ;;
13 | stop)
14 | /usr/bin/python3 -m celery multi stopwait $CELERYD_NODES \
15 | --pidfile=${CELERYD_PID_FILE} &
16 | ;;
17 | reload)
18 | /usr/bin/python3 -m celery -C -A $CELERY_APP multi restart $CELERYD_NODES \
19 | --pidfile=${CELERYD_PID_FILE} \
20 | --logfile=${CELERYD_LOG_FILE} \
21 | --loglevel="${CELERYD_LOG_LEVEL}" \
22 | $CELERYD_OPTS &
23 | ;;
24 | esac
25 |
--------------------------------------------------------------------------------
/src/schema/faf_schema/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2018 Red Hat, Inc.
2 | #
3 | # This program is free software; you can redistribute it and/or modify
4 | # it under the terms of the GNU General Public License as published by
5 | # the Free Software Foundation; either version 2 of the License, or
6 | # (at your option) any later version.
7 | #
8 | # This program is distributed in the hope that it will be useful,
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | # GNU General Public License for more details.
12 | #
13 | # You should have received a copy of the GNU General Public License along
14 | # with this program; if not, write to the Free Software Foundation, Inc.,
15 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 |
--------------------------------------------------------------------------------
/tests/bin/eu-addr2line:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | if [ -n "$EU_ADDR2LINE_SAMPLE_DIR" ]; then
4 | FILE="${EU_ADDR2LINE_SAMPLE_DIR%/}/"
5 | fi
6 |
7 | while [ $# -gt 0 ];
8 | do
9 | case "$1" in
10 | "--executable")
11 | FILE="$FILE$2"
12 | shift
13 | ;;
14 |
15 | "0x"*)
16 | FILE="${FILE}_$1"
17 | ;;
18 |
19 | "--debuginfo-path")
20 | shift
21 | ;;
22 |
23 | "--functions")
24 | ;;
25 |
26 | *)
27 | cat 2>&1 <&1 < Optional[str]:
12 | if value is not None:
13 | value = json.dumps(value)
14 | return value
15 |
16 | # pylint: disable=unused-argument
17 | def process_result_value(self, value, dialect) -> Optional[dict]:
18 | if value is not None:
19 | value = json.loads(value)
20 | return value
21 |
22 | # pylint: disable=unused-argument
23 | def process_literal_param(self, value, dialect) -> Any:
24 | return value
25 |
26 | @property
27 | def python_type(self) -> type:
28 | return json
29 |
--------------------------------------------------------------------------------
/src/webfaf/templates/celery_tasks/results_item.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block title %}Tasks{% endblock %}
4 |
5 | {% block js %}
6 | {% endblock %}
7 |
8 | {% block body %}
9 |
10 |
11 |
Result {{task_result.id}}
12 |
13 | - Task
14 | - {{task_result.nice_task}}
15 | - Arguments
16 | {{task_result.nice_args}}
17 | - Finished
18 | - {{task_result.finished_time.strftime("%Y-%m-%d %H:%M:%S")}}
19 | - State
20 | - {{task_result.state}}
21 |
22 |
23 | - Output
24 | {{task_result.retval}}Only the last 1000 characters are saved.
25 |
26 |
27 |
28 | {% endblock %}
29 |
--------------------------------------------------------------------------------
/container/files/usr/bin/faf-celery-beat:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | source /etc/faf/celery-beat-env.conf
4 |
5 | start_beat () {
6 | /usr/bin/python3 -m celery -C -A $CELERY_APP beat \
7 | --pidfile=${CELERYD_PID_FILE} \
8 | --logfile=${CELERYD_LOG_FILE} \
9 | --loglevel="${CELERYD_LOG_LEVEL}" \
10 | $CELERYD_OPTS &
11 | }
12 |
13 | kill_beat () {
14 | if [[ -f ${CELERYD_PID_FILE} ]]; then
15 | kill $(cat ${CELERYD_PID_FILE})
16 | else
17 | echo "ERROR: Pidfile (${CELERYD_PID_FILE}) doesn't exist."
18 | echo "celery beat not running"
19 | exit 1
20 | fi
21 |
22 | }
23 |
24 | case $1 in
25 | start)
26 | start_beat
27 | ;;
28 | stop)
29 | kill_beat
30 | ;;
31 | reload)
32 | kill_beat
33 | start_beat
34 | ;;
35 | esac
36 |
--------------------------------------------------------------------------------
/init-scripts/faf-celery-worker.service:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=FAF Celery worker
3 | After=network.target
4 |
5 | [Service]
6 | Type=forking
7 | User=faf
8 | Group=faf
9 | EnvironmentFile=/etc/faf/celery-worker-env.conf
10 | WorkingDirectory=/etc/faf
11 | ExecStart=/usr/bin/python3 -m celery -C -A ${CELERY_APP} multi start $CELERYD_NODES \
12 | --pidfile=${CELERYD_PID_FILE} \
13 | --logfile=${CELERYD_LOG_FILE} \
14 | --loglevel="${CELERYD_LOG_LEVEL}" \
15 | $CELERYD_OPTS
16 | ExecStop=/usr/bin/python3 -m celery multi stopwait $CELERYD_NODES \
17 | --pidfile=${CELERYD_PID_FILE}
18 | ExecReload=/usr/bin/python3 -m celery -C -A ${CELERY_APP} multi restart $CELERYD_NODES \
19 | --pidfile=${CELERYD_PID_FILE} \
20 | --logfile=${CELERYD_LOG_FILE} \
21 | --loglevel="${CELERYD_LOG_LEVEL}" \
22 | $CELERYD_OPTS
23 |
24 | [Install]
25 | WantedBy=multi-user.target
26 |
--------------------------------------------------------------------------------
/config/faf-logging.conf:
--------------------------------------------------------------------------------
1 | [loggers]
2 | keys=root,main,thread
3 |
4 | [handlers]
5 | keys=main,thread
6 |
7 | [formatters]
8 | keys=main,thread
9 |
10 | # Used only if no other loggers are specified
11 | [logger_root]
12 | level=DEBUG
13 | handlers=main
14 |
15 | [logger_main]
16 | level=INFO
17 | handlers=main
18 | qualname=faf
19 | propagate=0
20 |
21 | [logger_thread]
22 | level=INFO
23 | handlers=thread
24 | qualname=faf.thread
25 | propagate=0
26 |
27 | [handler_main]
28 | level=DEBUG
29 | formatter=main
30 | class=StreamHandler
31 | args=[]
32 |
33 | [handler_thread]
34 | level=DEBUG
35 | formatter=thread
36 | class=StreamHandler
37 | args=[]
38 |
39 | [formatter_main]
40 | format=[%(asctime)s] %(levelname)s:%(name)s: %(message)s
41 | datefmt=%Y-%m-%d %H:%M:%S
42 |
43 | [formatter_thread]
44 | format=[%(asctime)s] %(levelname)s:%(name)s(%(threadName)s): %(message)s
45 | datefmt=%Y-%m-%d %H:%M:%S
46 |
--------------------------------------------------------------------------------
/src/pyfaf/local.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013 ABRT Team
2 | # Copyright (C) 2013 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | __all__ = ["etc", "var"]
20 |
21 | # Invalid name "xyz" for type constant
22 | # pylint: disable-msg=C0103
23 |
24 | etc = "/etc"
25 | var = "/var"
26 |
--------------------------------------------------------------------------------
/src/webfaf/static/js/jquery.flot.simplelabel.js:
--------------------------------------------------------------------------------
1 | (function ($) {
2 | function init(plot) {
3 | plot.hooks.draw.push(function (plot, ctx) {
4 | $.each(plot.getAxes(), function(axisName, axis) {
5 | if(axisName.charAt(0) == 'y') {
6 | elem = plot.getPlaceholder().parent().find('#ylabel');
7 |
8 | elem.css('top',
9 | plot.getPlaceholder().offset().top
10 | + plot.height()/2 - elem.outerHeight()/2
11 | + 'px');
12 |
13 | elem.css('left',
14 | plot.getPlaceholder().offset().left
15 | - (elem.outerWidth()/2 + 15)
16 | + 'px');
17 | }
18 | });
19 | });
20 | }
21 |
22 | $.plot.plugins.push({
23 | init: init,
24 | name: 'simplelabel',
25 | version: '0.1'
26 | });
27 |
28 | })(jQuery);
29 |
--------------------------------------------------------------------------------
/src/webfaf/templates/reports/list_table_rows.html:
--------------------------------------------------------------------------------
1 | {% for report in reports %}
2 |
3 | | {{report.id}} |
4 | {{report.component}} |
5 |
6 | {% if report.crashfn %}
7 |
8 | {{ report.crashfn }}
9 |
10 |
11 | {% endif %}
12 | |
13 | {% if not report.archived %}
14 | {% if report.problem_id %}processed{% else %}new{% endif %} |
15 | {% else %}
16 | archived |
17 | {% endif %}
18 | {{report.type}} |
19 | {{report.last_occurrence.strftime("%Y-%m-%d")}} |
20 | {{report.first_occurrence.strftime("%Y-%m-%d")}} |
21 | {{report.count|readable_int}} |
22 |
23 | {% endfor %}
24 |
--------------------------------------------------------------------------------
/tests/test_webfaf/webfaftests/__init__.py:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 |
4 | # alter path so we can import faftests
5 | faftests_path = os.path.abspath(os.path.join(__file__, "../../.."))
6 |
7 | # alter path so we can import webfaf
8 | webfaf_path = os.path.join(os.path.abspath(os.path.join(faftests_path, "..")), "src")
9 |
10 | sys.path.insert(0, faftests_path)
11 | sys.path.insert(0, webfaf_path)
12 | os.environ["PATH"] = "{0}:{1}".format(webfaf_path, os.environ["PATH"])
13 |
14 | import faftests
15 | from webfaf.webfaf_main import app
16 |
17 |
18 | class WebfafTestCase(faftests.DatabaseCase):
19 |
20 | def setUp(self):
21 | super(WebfafTestCase, self).setUp()
22 |
23 | app.config["DATABASE"] = self.postgresql.url()
24 | app.config["SQLALCHEMY_DATABASE_URI"] = self.postgresql.url()
25 | app.config["TESTING"] = True
26 | app.config["SQLALCHEMY_ECHO"] = not True
27 | self.app = app.test_client()
28 |
29 | def tearDown(self):
30 | super(WebfafTestCase, self).tearDown()
31 |
--------------------------------------------------------------------------------
/src/pyfaf/bugtrackers/centosmantisbt.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2014 ABRT Team
2 | # Copyright (C) 2014 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | from pyfaf.bugtrackers import mantisbt
20 |
21 | __all__ = ["CentosMantis"]
22 |
23 | # see https://github.com/abrt/faf/issues/695
24 | # pylint: disable=abstract-method
25 |
26 | class CentosMantis(mantisbt.Mantis):
27 | name = "centos-mantisbt"
28 |
--------------------------------------------------------------------------------
/config/Makefile.am:
--------------------------------------------------------------------------------
1 | #=============================================================================
2 | # Config
3 | #=============================================================================
4 |
5 | SUBDIRS = plugins templates
6 |
7 | config_DATA = faf.conf \
8 | faf-logging.conf
9 |
10 | if HAVE_SYSTEMD
11 | config_DATA += celery-beat-env.conf
12 | config_DATA += celery-worker-env.conf
13 | endif
14 |
15 | configdir = $(sysconfdir)/faf
16 |
17 | faf.conf: faf.conf.in
18 | sed -e 's|@localstatedir[@]|$(localstatedir)|g' \
19 | -e 's|@sysconfdir[@]|$(sysconfdir)|g' $< > $@
20 |
21 | httpdconf_DATA = faf-web.conf
22 | httpdconfdir = ${sysconfdir}/httpd/conf.d
23 |
24 | faf-web.conf: faf-web.conf.in
25 | sed -e "s|@PYTHONDIR@|$(pythondir)|g" $< > $@
26 |
27 | logrotate_DATA = faf
28 | logrotatedir = ${sysconfdir}/logrotate.d
29 |
30 | EXTRA_DIST = celery-beat-env.conf \
31 | celery-worker-env.conf \
32 | faf.conf.in \
33 | faf-logging.conf \
34 | faf-web.conf.in \
35 | faf
36 |
--------------------------------------------------------------------------------
/tests/test_webfaf/test_summary.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 | # -*- encoding: utf-8 -*-
3 | import unittest
4 | from webfaftests import WebfafTestCase
5 |
6 |
7 | class SummaryTestCase(WebfafTestCase):
8 | """
9 | Tests for webfaf.summary
10 | """
11 |
12 | def setUp(self):
13 | super(SummaryTestCase, self).setUp()
14 | self.basic_fixtures()
15 |
16 | self.save_report("ureport_f20")
17 |
18 | self.db.session.commit()
19 |
20 | def test_index_redirect(self):
21 | """
22 | Index should redirect to /summary/
23 | """
24 |
25 | r = self.app.get("/")
26 | self.assertEqual(r.status_code, 302)
27 | self.assertIn(b"/summary/", r.data)
28 |
29 | def test_summary(self):
30 | """
31 | Test presence of data on the summary page
32 | """
33 |
34 | r = self.app.get("/summary/")
35 |
36 | self.assertIn(b"Fedora 20", r.data)
37 | self.assertIn(b" 1]", r.data) # graph point
38 |
39 | if __name__ == "__main__":
40 | unittest.main()
41 |
--------------------------------------------------------------------------------
/src/pyfaf/actions/archlist.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013 ABRT Team
2 | # Copyright (C) 2013 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | from pyfaf.actions import Action
20 | from pyfaf.storage.opsys import Arch
21 |
22 |
23 | class ArchList(Action):
24 | name = "archlist"
25 |
26 |
27 | def run(self, cmdline, db) -> None:
28 | for item in db.session.query(Arch):
29 | print(item)
30 |
--------------------------------------------------------------------------------
/src/webfaf/static/css/bootstrap-multiselect.css:
--------------------------------------------------------------------------------
1 | .multiselect-container{position:absolute;list-style-type:none;margin:0;padding:0}.multiselect-container .input-group{margin:5px}.multiselect-container>li{padding:0}.multiselect-container>li>a.multiselect-all label{font-weight:700}.multiselect-container>li>label.multiselect-group{margin:0;padding:3px 20px;height:100%;font-weight:700}.multiselect-container>li>a{padding:0}.multiselect-container>li>a>label{margin:0;height:100%;cursor:pointer;font-weight:400;padding:3px 20px 3px 40px}.multiselect-container>li>a>label.radio,.multiselect-container>li>a>label.checkbox{margin:0}.multiselect-container>li>a>label>input[type=checkbox]{margin-bottom:5px}.btn-group>.btn-group:nth-child(2)>.multiselect.btn{border-top-left-radius:4px;border-bottom-left-radius:4px}.form-inline .multiselect-container label.checkbox,.form-inline .multiselect-container label.radio{padding:3px 20px 3px 40px}.form-inline .multiselect-container li a label.checkbox input[type=checkbox],.form-inline .multiselect-container li a label.radio input[type=radio]{margin-left:-20px;margin-right:0}
--------------------------------------------------------------------------------
/src/pyfaf/actions/opsyslist.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013 ABRT Team
2 | # Copyright (C) 2013 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | from pyfaf.actions import Action
20 | from pyfaf.storage.opsys import OpSys
21 |
22 |
23 | class OpSysList(Action):
24 | name = "opsyslist"
25 |
26 |
27 | def run(self, cmdline, db) -> None:
28 | for opsys in db.session.query(OpSys):
29 | print(opsys)
30 |
--------------------------------------------------------------------------------
/src/pyfaf/utils/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013 ABRT Team
2 | # Copyright (C) 2013 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | __all__ = ["date", "decorators", "format", "parse", "proc", "storage"]
20 |
21 | from pyfaf.utils import date
22 | from pyfaf.utils import decorators
23 | from pyfaf.utils import format # pylint: disable=redefined-builtin
24 | from pyfaf.utils import parse
25 | from pyfaf.utils import proc
26 | from pyfaf.utils import storage
27 |
--------------------------------------------------------------------------------
/tests/test_alembic.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 | # -*- encoding: utf-8 -*-
3 | import unittest
4 | import logging
5 |
6 | import faftests
7 |
8 | import os
9 | import inspect
10 | import sys
11 |
12 | from io import StringIO
13 |
14 | from pyfaf.storage import migrations
15 | from alembic.config import Config
16 | from alembic import command
17 |
18 |
19 | class AlembicTestCase(faftests.DatabaseCase):
20 |
21 | """
22 | Test case for migrations by alembic
23 | """
24 |
25 | def setUp(self):
26 | super(AlembicTestCase, self).setUp()
27 | self.basic_fixtures()
28 |
29 | def test_alembic_head(self):
30 | heads_ = StringIO()
31 | alembic_cfg = Config(stdout=heads_)
32 | alembic_cfg.set_main_option("script_location",
33 | os.path.dirname(inspect.getfile(migrations)))
34 | command.heads(alembic_cfg)
35 | heads = heads_.getvalue()
36 | heads = heads[:-1]
37 |
38 | self.assertNotIn('\n', heads)
39 |
40 | if __name__ == "__main__":
41 | logging.basicConfig(level=logging.INFO)
42 | unittest.main()
43 |
--------------------------------------------------------------------------------
/src/webfaf/templates/celery_tasks/results_list.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 | {% from "_helpers.html" import paginator %}
3 |
4 | {% block title %}Task results{% endblock %}
5 |
6 | {% block js %}
7 | {% endblock %}
8 |
9 | {% block body %}
10 |
11 |
12 |
Task results
13 |
Show only unsuccessful results
14 |
15 |
16 |
17 | | ID | Task | Time | State |
18 |
19 |
20 |
21 | {% for r in task_results %}
22 |
23 | | {{r.id}} |
24 | {{r.nice_task}} |
25 | {{r.finished_time.strftime("%Y-%m-%d %H:%M:%S")}} |
26 | {{r.state}} |
27 |
28 | {% endfor %}
29 |
30 |
31 | {{ paginator(pagination, task_results|length) }}
32 |
33 |
34 | {% endblock %}
35 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/migrations/versions/23bab42e7be7_initial_migration.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2014 ABRT Team
2 | # Copyright (C) 2014 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 |
20 | """
21 | Initial migration
22 |
23 | Revision ID: 23bab42e7be7
24 | Revises: None
25 | Create Date: 2014-07-31 10:20:27.506558
26 | """
27 |
28 | # revision identifiers, used by Alembic.
29 | revision = '23bab42e7be7'
30 | down_revision = None
31 |
32 |
33 | def upgrade() -> None:
34 | pass
35 |
36 |
37 | def downgrade() -> None:
38 | pass
39 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/externalfaf.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2014 ABRT Team
2 | # Copyright (C) 2014 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | from sqlalchemy.sql.schema import Column
20 | from sqlalchemy.types import Integer, String
21 |
22 | from .generic_table import GenericTable
23 |
24 |
25 | class ExternalFafInstance(GenericTable):
26 | __tablename__ = "externalfafinstances"
27 |
28 | id = Column(Integer, primary_key=True)
29 | name = Column(String(256), nullable=False, index=True)
30 | baseurl = Column(String(1024), nullable=False)
31 |
--------------------------------------------------------------------------------
/src/webfaf/templates/celery_tasks/action_run.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 | {% from "_helpers.html" import render_field %}
3 |
4 | {% block title %}Run or schedule action {{action_name}}{% endblock %}
5 |
6 | {% block body %}
7 |
8 |
9 |
Run or schedule action {{action_name}}
10 |
11 |
12 |
31 | {% endblock %}
32 |
--------------------------------------------------------------------------------
/src/webfaf/templates/reports/associate_bug.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 | {% from "_helpers.html" import render_field %}
3 |
4 | {% block title %}Associate bug with report{% endblock %}
5 |
6 | {% block body %}
7 |
8 |
16 | {% if new_bug_urls %}
17 |
18 |
19 |
By clicking the links below, you'll be taken to a pre-filled form allowing you to create a new bug for this report. After creating the bug, please copy it's ID to the form above and associate it.
20 | {% for (text, url) in new_bug_urls %}
21 |
Create new bug for {{text}}...
22 | {% endfor %}
23 |
24 |
25 | {% endif %}
26 |
27 |
28 | {% endblock %}
29 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/user.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2014 ABRT Team
2 | # Copyright (C) 2014 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | from sqlalchemy.sql.schema import Column
20 | from sqlalchemy.types import Boolean, String
21 |
22 | from .generic_table import GenericTable
23 |
24 |
25 | class User(GenericTable):
26 | __tablename__ = "users"
27 |
28 | username = Column(String(100), nullable=False, primary_key=True)
29 | mail = Column(String(150), nullable=False)
30 | admin = Column(Boolean, default=False)
31 | privileged = Column(Boolean, default=False)
32 |
--------------------------------------------------------------------------------
/src/pyfaf/utils/contextmanager.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from contextlib import contextmanager
3 | from io import StringIO
4 | from typing import Generator, Tuple
5 |
6 |
7 | @contextmanager
8 | def captured_output() -> Generator[Tuple[StringIO, StringIO], None, None]:
9 | """
10 | Capture stdout and stderr output of the executed block
11 |
12 | Example:
13 |
14 | with captured_output() as (out, err):
15 | foo()
16 | """
17 |
18 | new_out, new_err = StringIO(), StringIO()
19 | old_out, old_err = sys.stdout, sys.stderr
20 | try:
21 | sys.stdout, sys.stderr = new_out, new_err
22 | yield sys.stdout, sys.stderr
23 | finally:
24 | sys.stdout, sys.stderr = old_out, old_err
25 |
26 |
27 | @contextmanager
28 | def captured_output_combined() -> Generator[StringIO, None, None]:
29 | """
30 | Capture stdout and stderr combined output of the executed block
31 |
32 | Example:
33 |
34 | with captured_output_combined() as out:
35 | foo()
36 | """
37 |
38 | new_out = StringIO()
39 | old_out, old_err = sys.stdout, sys.stderr
40 | try:
41 | sys.stdout, sys.stderr = new_out, new_out
42 | yield sys.stdout
43 | finally:
44 | sys.stdout, sys.stderr = old_out, old_err
45 |
--------------------------------------------------------------------------------
/src/webfaf/templates/celery_tasks/schedule_item.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 | {% from "_helpers.html" import render_field %}
3 |
4 | {% block title %}Schedule item {{pt_name}}{% endblock %}
5 |
6 | {% block body %}
7 |
8 |
9 |
Schedule item {{pt_name}}
10 |
11 |
12 |
34 | {% endblock %}
35 |
--------------------------------------------------------------------------------
/docs/fixture_notes:
--------------------------------------------------------------------------------
1 | faf-fixtures
2 | -------------
3 |
4 | Generates/loads fixtures for testing purposes.
5 |
6 | Currently, there these types of fixtures are available:
7 | 1) faf-fixtures --dumb
8 | 2) faf-fixtures --realworld
9 |
10 | Dumb fixtures are only good for web UI testing,
11 | they are generated randomly and contain fake
12 | symbols, components, ...
13 |
14 | Real-world fixtures are also usable for
15 | retracing and backtrace processing, they
16 | contain real data (components, builds, rpms, tags, ..).
17 |
18 | These data are partially stored in SQL files
19 | `pyfaf/storage/fixtures/sql` directory. As we also need
20 | RPM files to test retracing and uReport handling, these
21 | are packed and stored in some other location than git.
22 | During the fixture generation process, this file
23 | is downloaded and extracted to faf lob dir.
24 |
25 | URL pointing to downloaded archive is stored in
26 | `pyfaf/storage/fixtures/lob_download_location`.
27 |
28 | To create updated version of real-world fixtures,
29 | edit and run `faf-fixtures-update-realworld` script,
30 | which downloads specified components, updates
31 | affected SQL files and packs new lob archive.
32 |
33 | When you are happy with the new version, upload the
34 | archive publicly and update `lob_download_location`
35 | respectively.
36 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/migrations/script.py.mako:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2020 ABRT Team
2 | # Copyright (C) 2020 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | """
20 | ${message}
21 |
22 | Revision ID: ${up_revision}
23 | Revises: ${down_revision}
24 | Create Date: ${create_date}
25 | """
26 |
27 | from alembic import op
28 | import sqlalchemy as sa
29 | ${imports if imports else ""}
30 |
31 | # revision identifiers, used by Alembic.
32 | revision = ${repr(up_revision)}
33 | down_revision = ${repr(down_revision)}
34 |
35 |
36 | def upgrade():
37 | ${upgrades if upgrades else "pass"}
38 |
39 |
40 | def downgrade():
41 | ${downgrades if downgrades else "pass"}
42 |
--------------------------------------------------------------------------------
/src/webfaf/templates/problems/list_table_rows.html:
--------------------------------------------------------------------------------
1 | {% from '_helpers.html' import external_bugs %}
2 | {%- for problem in problems %}
3 |
4 | |
5 |
6 | {{ problem.id }}
7 |
8 | |
9 |
10 | {%- for name in problem.unique_component_names %}
11 | {{ name }}{% if not loop.last %}, {% endif %}
12 | {%- endfor %}
13 | {%- if problem.tainted %}
14 | Tainted
15 | {%- endif %}
16 | |
17 |
18 | {% if problem.crash_function %}
19 |
20 | {{ problem.crash_function }}
21 |
22 |
23 | {% endif %}
24 | |
25 |
26 |
27 | {{ problem.status }}
28 |
29 | |
30 |
31 | {{ external_bugs(problem.id, problem.bugs, false) }}
32 | |
33 |
34 | {%- if problem.probable_fixes %}
35 | {{ problem.probable_fixes|join(", ") }}
36 | {%- endif %}
37 | |
38 | {{ problem.count|readable_int }} |
39 |
40 | {%- endfor %}
41 |
--------------------------------------------------------------------------------
/container/Dockerfile_local:
--------------------------------------------------------------------------------
1 | FROM abrt/faf
2 | # rhbz#1733043 workaround
3 | ENV TERM=linux
4 |
5 | USER root
6 |
7 | # install devel tools
8 | RUN dnf -y install git-core make rpm-build sudo tito vim which
9 |
10 | # Copy sources to the docker image
11 | COPY --chown=faf:faf . /faf/
12 |
13 | # From not on work from faf directory
14 | WORKDIR '/faf'
15 |
16 | # Change owner of /faf, clean git and install dependences
17 | RUN git clean -dfx && \
18 | dnf -y --setopt=strict=0 --setopt=tsflags=nodocs builddep faf.spec && \
19 | dnf clean all
20 |
21 | # Build as non root
22 | USER faf
23 |
24 | ENV HOME /faf
25 |
26 | # Build faf
27 | RUN tito build --rpm --test
28 |
29 | #And continue as root
30 | USER 0
31 |
32 | # Update ABRT Analytics (FAF)
33 | RUN rpm -Uvh /tmp/tito/noarch/faf-* && \
34 | sed -i -e"s/everyone_is_admin\s*=\s*false/everyone_is_admin = true/i" /etc/faf/plugins/web.conf && \
35 | echo 'Defaults env_keep = "PGHOST PGUSER PGPASSWORD PGPORT PGDATABASE RDSBROKER RDSBACKEND"' >> /etc/sudoers.d/faf && \
36 | /usr/libexec/fix-permissions /faf && \
37 | /usr/libexec/fix-permissions /run/faf-celery && \
38 | /usr/libexec/fix-permissions /var/log/faf && \
39 | /usr/libexec/fix-permissions /var/spool/faf && \
40 | /usr/libexec/fix-permissions /etc/faf/
41 |
42 | #Switch workdir back to /
43 | WORKDIR '/'
44 |
--------------------------------------------------------------------------------
/faf_setup:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 |
4 | ARCH_LIST="src noarch x86_64 i386 i486 i586 i686 armv5tel armv7hl ppc ppc64 s390 s390x"
5 | MIRROR_URL="http://mirror.karneval.cz/pub/linux/fedora/linux"
6 |
7 | # add architectures and releases
8 | # ------------------------------
9 |
10 | faf archadd $ARCH_LIST
11 | faf opsysadd Fedora
12 | faf pull-releases -o fedora
13 |
14 | # add fedora repositories
15 | # -----------------------
16 |
17 | tmpdir=$( mktemp -d )
18 | cp repos/*.repo $tmpdir
19 |
20 | # replace original URL with our selected mirror
21 | sed -i "s~http://download.fedoraproject.org/pub/fedora/linux~$MIRROR_URL~g" $tmpdir/*.repo
22 |
23 | # import repofiles
24 | for repofile in $tmpdir/*.repo; do
25 | faf repoimport dnf $repofile
26 | done
27 |
28 | # assign os/debug repositories
29 | for reponame in $( faf repolist | grep -v source ); do
30 | faf repoassign $reponame Fedora i386 x86_64
31 | done
32 |
33 | # assign source repositories
34 | for reponame in $( faf repolist | grep source ); do
35 | faf repoassign $reponame Fedora src
36 | done
37 |
38 | rm -rf $tmpdir
39 |
40 | # print result
41 | # ------------
42 |
43 | echo -e "\nSetup complete\n"
44 |
45 | echo -e "\nAdded architectures:\n"
46 | faf archlist
47 |
48 | echo -e "\nAdded releases:\n"
49 | faf releaselist
50 |
51 | echo -e "\nAdded repositories:\n"
52 | faf repolist --detailed
53 |
54 |
--------------------------------------------------------------------------------
/config/faf-web.conf.in:
--------------------------------------------------------------------------------
1 | # WSGI handler
2 | WSGIPythonOptimize 1
3 | WSGISocketPrefix /var/spool/faf/wsgi
4 | WSGIDaemonProcess faf user=faf group=faf processes=3 threads=5
5 | WSGIScriptAlias /faf @PYTHONDIR@/webfaf/hub.wsgi process-group=faf application-group=%{GLOBAL}
6 |
7 |
8 |
9 | # Apache 2.4
10 | Require all granted
11 |
12 |
13 | # Apache 2.2
14 | Order allow,deny
15 | Allow from all
16 |
17 |
18 |
19 | # project main
20 |
21 | Options Indexes
22 | IndexOptions FancyIndexing
23 |
24 | # Apache 2.4
25 | Require all granted
26 |
27 |
28 | # Apache 2.2
29 | Order allow,deny
30 | Allow from all
31 |
32 |
33 |
34 | # static
35 | Alias /faf/static "/usr/share/faf/web/static"
36 |
37 | Options Indexes
38 | IndexOptions FancyIndexing
39 |
40 | # Apache 2.4
41 | Require all granted
42 |
43 |
44 | # Apache 2.2
45 | Order allow,deny
46 | Allow from all
47 |
48 |
49 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/migrations/versions/13557f1962e6_ureport_added_certainty.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2014 ABRT Team
2 | # Copyright (C) 2014 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | """
20 | Ureport add certainty
21 |
22 | Revision ID: 13557f1962e6
23 | Revises: 2573150e1470
24 | Create Date: 2016-08-09 10:01:00.818966
25 | """
26 |
27 | from alembic.op import add_column, drop_column
28 | import sqlalchemy as sa
29 |
30 | # revision identifiers, used by Alembic.
31 | revision = "13557f1962e6"
32 | down_revision = "89d35a57f82b"
33 |
34 |
35 | def upgrade() -> None:
36 | add_column("reports", sa.Column("max_certainty", sa.Integer, nullable=True))
37 |
38 |
39 | def downgrade() -> None:
40 | drop_column("reports", "max_certainty")
41 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/migrations/versions/21345f007bdf_add_privileged_user_field.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2014 ABRT Team
2 | # Copyright (C) 2014 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | """
20 | Add privileged user field
21 |
22 | Revision ID: 21345f007bdf
23 | Revises: cef2fcd69ef
24 | Create Date: 2015-08-18 14:56:02.571419
25 | """
26 |
27 | from alembic.op import add_column, drop_column
28 | import sqlalchemy as sa
29 |
30 | # revision identifiers, used by Alembic.
31 | revision = '21345f007bdf'
32 | down_revision = 'cef2fcd69ef'
33 |
34 |
35 | def upgrade() -> None:
36 | add_column('users', sa.Column('privileged', sa.Boolean(), nullable=True))
37 |
38 |
39 | def downgrade() -> None:
40 | drop_column('users', 'privileged')
41 |
--------------------------------------------------------------------------------
/src/webfaf/blueprints/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2014 ABRT Team
2 | # Copyright (C) 2014 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | """
20 | Plugins may be placed inside this directory. All modules that don't start with _
21 | are loaded. Modules must contain `blueprint` and `url_prefix` attributes.
22 |
23 | example.py:
24 |
25 | from flask import Blueprint
26 |
27 | url_prefix = "/example"
28 |
29 | example_blueprint = Blueprint("example", __name__)
30 |
31 |
32 | @example_blueprint.route('/')
33 | def hello():
34 | return "Hello world!"
35 |
36 | blueprint = example_blueprint
37 |
38 | blueprint_menu = [{
39 | "title": "Example",
40 | "route": "example.hello",
41 | "admin_required": False,
42 | }, ]
43 |
44 | """
45 |
--------------------------------------------------------------------------------
/src/pyfaf/actions/extfafshow.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2014 ABRT Team
2 | # Copyright (C) 2014 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | from pyfaf.actions import Action
20 | from pyfaf.queries import get_external_faf_instances
21 | from pyfaf.utils.format import as_table
22 |
23 |
24 | class ExternalFafShow(Action):
25 | name = "extfafshow"
26 |
27 |
28 | def run(self, cmdline, db) -> None:
29 | header = ["ID", "Name", "Base URL"]
30 |
31 | db_instances = get_external_faf_instances(db)
32 | data = []
33 | for db_instance in sorted(db_instances, key=lambda x: x.id):
34 | data.append((db_instance.id, db_instance.name, db_instance.baseurl))
35 |
36 | print(as_table(header, data, margin=2))
37 |
--------------------------------------------------------------------------------
/src/pyfaf/actions/releaselist.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013 ABRT Team
2 | # Copyright (C) 2013 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | from pyfaf.actions import Action
20 | from pyfaf.storage.opsys import OpSysRelease
21 |
22 |
23 | class ReleaseList(Action):
24 | name = "releaselist"
25 |
26 |
27 | def run(self, cmdline, db) -> None:
28 | for opsysrelease in db.session.query(OpSysRelease):
29 | if not cmdline.all and opsysrelease.status != "ACTIVE":
30 | continue
31 |
32 | print(opsysrelease)
33 |
34 | def tweak_cmdline_parser(self, parser) -> None:
35 | parser.add_argument("--all", action="store_true",
36 | help="list all releases (non-active)")
37 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/migrations/versions/acd3d9bf85d1_ignore_private_bz.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2017 ABRT Team
2 | # Copyright (C) 2017 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | """
20 | Ignore private bugzilla bugz
21 |
22 | Revision ID: acd3d9bf85d1
23 | Revises: 168c63b81f85
24 | Create Date: 2017-07-25 09:03:53.335397
25 | """
26 |
27 | from alembic.op import add_column, drop_column
28 | import sqlalchemy as sa
29 |
30 | # revision identifiers, used by Alembic.
31 | revision = "acd3d9bf85d1"
32 | down_revision = "168c63b81f85"
33 |
34 |
35 | def upgrade() -> None:
36 | add_column("bzbugs", sa.Column("private", sa.Boolean(), nullable=False, server_default="f"))
37 |
38 |
39 | def downgrade() -> None:
40 | drop_column("bzbugs", "private")
41 |
--------------------------------------------------------------------------------
/tests/sample_reports/ureport_systemd2:
--------------------------------------------------------------------------------
1 | {
2 | "reporter": {
3 | "version": "0.13",
4 | "name": "satyr"
5 | },
6 | "reason": "Program /usr/lib/systemd/systemd-logind was terminated by signal 6",
7 | "problem": {
8 | "stacktrace": [
9 | {
10 | "crash_thread": true,
11 | "frames": [
12 | {
13 | "build_id": "c15e903efc9dd21b8a81a6539d7df9401d16e6d0",
14 | "build_id_offset": 220249,
15 | "file_name": "/lib64/libc.so.6",
16 | "address": 140701620345945,
17 | "fingerprint": "f33186a4c862fb0751bca60701f553b829210477",
18 | "function_name": "raise"
19 | }
20 | ]
21 | }
22 | ],
23 | "executable": "/usr/lib/systemd/systemd-logind",
24 | "signal": 6,
25 | "component": "systemd",
26 | "user": {
27 | "local": true,
28 | "root": false
29 | },
30 | "type": "core"
31 | },
32 | "packages": [
33 | {
34 | "name": "systemd",
35 | "epoch": 0,
36 | "version": "2",
37 | "architecture": "x86_64",
38 | "package_role": "affected",
39 | "release": "0",
40 | "install_time": 1398699808
41 | }
42 | ],
43 | "os": {
44 | "cpe": "cpe:/o:fedoraproject:fedora:20",
45 | "version": "20",
46 | "name": "fedora",
47 | "architecture": "x86_64"
48 | },
49 | "ureport_version": 2
50 | }
--------------------------------------------------------------------------------
/tests/sample_reports/ureport_systemd77:
--------------------------------------------------------------------------------
1 | {
2 | "reporter": {
3 | "version": "0.13",
4 | "name": "satyr"
5 | },
6 | "reason": "Program /usr/lib/systemd/systemd-logind was terminated by signal 6",
7 | "problem": {
8 | "stacktrace": [
9 | {
10 | "crash_thread": true,
11 | "frames": [
12 | {
13 | "build_id": "c15e903efc9dd21b8a81a6539d7df9401d16e6d0",
14 | "build_id_offset": 220249,
15 | "file_name": "/lib64/libc.so.6",
16 | "address": 140701620345945,
17 | "fingerprint": "f33186a4c862fb0751bca60701f553b829210477",
18 | "function_name": "raise"
19 | }
20 | ]
21 | }
22 | ],
23 | "executable": "/usr/lib/systemd/systemd-logind",
24 | "signal": 6,
25 | "component": "systemd",
26 | "user": {
27 | "local": true,
28 | "root": false
29 | },
30 | "type": "core"
31 | },
32 | "packages": [
33 | {
34 | "name": "systemd",
35 | "epoch": 0,
36 | "version": "77",
37 | "architecture": "x86_64",
38 | "package_role": "affected",
39 | "release": "0",
40 | "install_time": 1398699808
41 | }
42 | ],
43 | "os": {
44 | "cpe": "cpe:/o:fedoraproject:fedora:20",
45 | "version": "20",
46 | "name": "fedora",
47 | "architecture": "x86_64"
48 | },
49 | "ureport_version": 2
50 | }
--------------------------------------------------------------------------------
/tests/test_common.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 | # -*- encoding: utf-8 -*-
3 | import unittest
4 | import logging
5 |
6 | import faftests
7 |
8 | from pyfaf.common import import_dir, load_plugins, load_plugin_types
9 |
10 | from sample_plugin_dir.base import Base
11 | from sample_plugin_dir.plugin import Sub
12 |
13 |
14 | class CommonsTestCase(faftests.DatabaseCase):
15 | """
16 | Test pyfaf.common
17 | """
18 |
19 | def test_import_dir(self):
20 | """
21 | Test if import_dir imports correct files
22 | """
23 |
24 | import_dir("sample_plugin_dir", "sample_plugin_dir")
25 |
26 | self.assertEqual(len(Base.__subclasses__()), 1)
27 |
28 | def test_load_plugins(self):
29 | """
30 | Test if load_plugins returns correct results
31 | """
32 |
33 | plugins = load_plugins(Base)
34 | self.assertIn('sub-plugin', plugins)
35 | self.assertIs(isinstance(plugins['sub-plugin'], Sub), True)
36 | self.assertIs(isinstance(plugins['sub-plugin'], Base), True)
37 |
38 | def test_load_plugin_types(self):
39 | """
40 | Test if load_plugin_types loads correct classes
41 | """
42 |
43 | types = load_plugin_types(Base)
44 | self.assertIn('sub', types)
45 | self.assertIs(issubclass(types['sub'], Base), True)
46 |
47 | if __name__ == "__main__":
48 | logging.basicConfig(level=logging.INFO)
49 | unittest.main()
50 |
--------------------------------------------------------------------------------
/m4/ax_python_module.m4:
--------------------------------------------------------------------------------
1 | # ===========================================================================
2 | # http://www.gnu.org/software/autoconf-archive/ax_python_module.html
3 | # ===========================================================================
4 | #
5 | # SYNOPSIS
6 | #
7 | # AX_PYTHON_MODULE(modname[, fatal])
8 | #
9 | # DESCRIPTION
10 | #
11 | # Checks for Python module.
12 | #
13 | # If fatal is non-empty then absence of a module will trigger an error.
14 | #
15 | # LICENSE
16 | #
17 | # Copyright (c) 2008 Andrew Collier
18 | #
19 | # Copying and distribution of this file, with or without modification, are
20 | # permitted in any medium without royalty provided the copyright notice
21 | # and this notice are preserved. This file is offered as-is, without any
22 | # warranty.
23 |
24 | #serial 5
25 |
26 | AU_ALIAS([AC_PYTHON_MODULE], [AX_PYTHON_MODULE])
27 | AC_DEFUN([AX_PYTHON_MODULE],[
28 | if test -z $PYTHON;
29 | then
30 | PYTHON="python"
31 | fi
32 | PYTHON_NAME=`basename $PYTHON`
33 | AC_MSG_CHECKING($PYTHON_NAME module: $1)
34 | $PYTHON -c "import $1" 2>/dev/null
35 | if test $? -eq 0;
36 | then
37 | AC_MSG_RESULT(yes)
38 | eval AS_TR_CPP(HAVE_PYMOD_$1)=yes
39 | else
40 | AC_MSG_RESULT(no)
41 | eval AS_TR_CPP(HAVE_PYMOD_$1)=no
42 | #
43 | if test -n "$2"
44 | then
45 | AC_MSG_ERROR(failed to find required module $1)
46 | exit 1
47 | fi
48 | fi
49 | ])
50 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: Run unit tests
2 | on:
3 | pull_request:
4 | branches: [master]
5 | push:
6 | branches: [master]
7 | jobs:
8 | test:
9 | container:
10 | image: quay.io/fedora/fedora:latest
11 | runs-on: ubuntu-latest
12 | steps:
13 | - name: Check out sources
14 | uses: actions/checkout@v3
15 |
16 | - name: Install build environment
17 | run: |
18 | dnf install --assumeyes --setopt=install_weak_deps=False \
19 | autoconf automake dnf-plugins-core make
20 | dnf copr enable --assumeyes @abrt/faf-el8-devel
21 |
22 | - name: Install build dependencies
23 | run: dnf builddep --assumeyes --setopt=install_weak_deps=False --spec faf.spec
24 |
25 | - name: Generate build files
26 | run: |
27 | # We need an unprivileged user in order to run some Postgres-related tests.
28 | useradd --no-create-home runner
29 | # Doing this would be largely unnecessary had non-srcdir builds worked.
30 | chown -R runner: .
31 | sudo -u runner ./autogen.sh
32 |
33 | - name: Build
34 | run: sudo -u runner make -j
35 |
36 | - name: Run tests
37 | run: sudo -u runner make check
38 |
39 | - name: Upload test logs
40 | uses: actions/upload-artifact@v2
41 | with:
42 | name: testsuite.log
43 | path: tests/**/test-suite.log
44 | if: failure()
45 |
--------------------------------------------------------------------------------
/container/files/usr/bin/run_faf:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | USER_ID=$(id -u)
4 | GROUP_ID=$(id -g)
5 |
6 | # Openshift runs containers with user that has assigned UID >= 1000000000
7 | # Because there is no record of this user in /etc/passwd, it causes problems with some
8 | # applications. We edit the /etc/passwd so the user is assigned as faf.
9 | if [ x"$USER_ID" != x"0" -a x"$USER_ID" != x"997" ];then
10 | echo "faf:x:${USER_ID}:${GROUP_ID}::/etc/faf:/sbin/nologin" >> /etc/passwd
11 | fi
12 |
13 | # Recreate directory structure (persistent volume issue)
14 | mkdir -p /var/spool/faf/lob \
15 | /var/spool/faf/attachments/archive \
16 | /var/spool/faf/attachments/deferred \
17 | /var/spool/faf/attachments/incoming \
18 | /var/spool/faf/attachments/saved \
19 | /var/spool/faf/reports/archive \
20 | /var/spool/faf/reports/deferred \
21 | /var/spool/faf/reports/incoming \
22 | /var/spool/faf/reports/saved \
23 | || exit 1
24 |
25 | createdb
26 | if [ $? == 0 ]
27 | then
28 | psql -c "CREATE EXTENSION semver"
29 | faf-migrate-db --create-all
30 | faf-migrate-db --stamp-only
31 | faf init
32 | faf pull-releases -o fedora
33 | else
34 | faf-migrate-db
35 | fi
36 |
37 | /usr/bin/faf-celery-worker start
38 | /usr/bin/faf-celery-beat start
39 |
40 | /usr/sbin/uwsgi --ini /etc/uwsgi.ini --logto /var/log/faf/uwsgi_logs &
41 | /usr/sbin/httpd -DFOREGROUND
42 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/migrations/versions/729a154b1609_index_reportpackages.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2016 ABRT Team
2 | # Copyright (C) 2016 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | """
20 | Create index on reportpackages table
21 |
22 | Revision ID: 729a154b1609
23 | Revises: f43edd5b636d
24 | Create Date: 2018-06-12 14:53:06.150898
25 | """
26 |
27 | from alembic.op import create_index, drop_index, f
28 |
29 | # revision identifiers, used by Alembic.
30 | revision = '729a154b1609'
31 | down_revision = 'f43edd5b636d'
32 |
33 | index_name = 'ix_reportpackages_report_id_installed_package_id'
34 |
35 | def upgrade() -> None:
36 | create_index(f(index_name), 'reportpackages', ['report_id', 'installed_package_id'])
37 |
38 |
39 | def downgrade() -> None:
40 | drop_index(f(index_name), table_name='reportpackages')
41 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/migrations/versions/48550f308625_add_symbolsource_retrace_fail_count.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2014 ABRT Team
2 | # Copyright (C) 2014 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | """
20 | Add SymbolSource retrace_fail_count
21 |
22 | Revision ID: 48550f308625
23 | Revises: 1c7edfbf8941
24 | Create Date: 2015-04-27 10:26:28.975738
25 | """
26 |
27 | from alembic.op import add_column, drop_column
28 | import sqlalchemy as sa
29 |
30 | # revision identifiers, used by Alembic.
31 | revision = "48550f308625"
32 | down_revision = "1c7edfbf8941"
33 |
34 |
35 | def upgrade() -> None:
36 | add_column("symbolsources", sa.Column("retrace_fail_count", sa.Integer(),
37 | nullable=False, server_default="0"))
38 |
39 |
40 | def downgrade() -> None:
41 | drop_column("symbolsources", "retrace_fail_count")
42 |
--------------------------------------------------------------------------------
/src/pyfaf/bugtrackers/fedorabz.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013 ABRT Team
2 | # Copyright (C) 2013 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | from typing import Generator
20 |
21 | from pyfaf.bugtrackers import bugzilla
22 |
23 | __all__ = ["FedoraBugzilla"]
24 |
25 |
26 | class FedoraBugzilla(bugzilla.Bugzilla):
27 | name = "fedora-bugzilla"
28 |
29 | def list_bugs(self, *args, **kwargs) -> Generator[int, None, None]:
30 |
31 | abrt_specific = dict(
32 | status_whiteboard="abrt_hash",
33 | status_whiteboard_type="allwordssubstr",
34 | product="Fedora",
35 | )
36 |
37 | if "custom_fields" in kwargs:
38 | kwargs["custom_fields"].update(abrt_specific)
39 | else:
40 | kwargs["custom_fields"] = abrt_specific
41 |
42 | return super().list_bugs(*args, **kwargs)
43 |
--------------------------------------------------------------------------------
/tests/test_checker.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 | # -*- encoding: utf-8 -*-
3 | import unittest
4 | import logging
5 |
6 | import faftests
7 |
8 | from pyfaf.checker import *
9 |
10 |
11 |
12 | class CheckerTestCase(faftests.TestCase):
13 | """
14 | Test pyfaf.checker
15 | """
16 |
17 | def test_mandatory(self):
18 | """
19 | Test if mandatory=False is correctly handled
20 | """
21 |
22 | chk = DictChecker({
23 | "key1_mandatory": IntChecker(minval=0, mandatory=True),
24 | "key2_optional": IntChecker(minval=0, mandatory=False),
25 | "key3_mandatory": IntChecker(minval=0), #default mandatory=True
26 | })
27 |
28 | valid1 = {
29 | "key1_mandatory": 1,
30 | "key2_optional": 1,
31 | "key3_mandatory": 1,
32 | }
33 |
34 | valid2 = {
35 | "key1_mandatory": 1,
36 | "key3_mandatory": 1,
37 | }
38 |
39 | invalid1 = {
40 | "key1_mandatory": 1,
41 | "key2_optional": -1,
42 | "key3_mandatory": 1,
43 | }
44 |
45 | invalid2 = {
46 | "key1_mandatory": -1,
47 | "key3_mandatory": 1,
48 | }
49 |
50 | chk.check(valid1)
51 | chk.check(valid2)
52 | self.assertRaises(CheckError, chk.check, invalid1)
53 | self.assertRaises(CheckError, chk.check, invalid2)
54 |
55 |
56 | if __name__ == "__main__":
57 | logging.basicConfig(level=logging.INFO)
58 | unittest.main()
59 |
--------------------------------------------------------------------------------
/src/pyfaf/utils/format.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013 ABRT Team
2 | # Copyright (C) 2013 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | from functools import reduce
20 |
21 | __all__ = ["as_table"]
22 |
23 |
24 | def as_table(headers, data, margin=1, separator=" ") -> str:
25 | """
26 | Return `headers` and `data` lists formatted as table.
27 | """
28 |
29 | headers = list(map(str, headers))
30 | data = [list(map(str, x)) for x in data]
31 |
32 | widths = reduce(
33 | lambda x, y: [max(a_b[0], a_b[1]) for a_b in list(zip(x, y))],
34 | [map(len, x) for x in data] + [map(len, headers)],
35 | [0 for _ in headers])
36 |
37 | fmt = ""
38 | for num, width in enumerate(widths):
39 | fmt += "{{{0}:<{1}}}{2}".format(num, width, separator * margin)
40 | fmt += "\n"
41 |
42 | # Used * or ** magic
43 | return "".join([fmt.format(*row) for row in [headers] + data])
44 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/migrations/versions/31d0249e8d4c_create_users_table.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2014 ABRT Team
2 | # Copyright (C) 2014 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | """
20 | Create users table
21 |
22 | Revision ID: 31d0249e8d4c
23 | Revises: 7fa8b3134f0
24 | Create Date: 2014-09-24 14:49:20.793855
25 | """
26 |
27 | from alembic.op import create_table, drop_table
28 | import sqlalchemy as sa
29 |
30 | # revision identifiers, used by Alembic.
31 | revision = '31d0249e8d4c'
32 | down_revision = '7fa8b3134f0'
33 |
34 |
35 | def upgrade() -> None:
36 | create_table(
37 | 'users',
38 | sa.Column('username', sa.String(length=100), nullable=False),
39 | sa.Column('mail', sa.String(length=150), nullable=False),
40 | sa.Column('admin', sa.Boolean(), default=False),
41 | sa.PrimaryKeyConstraint('username'),
42 | )
43 |
44 |
45 | def downgrade() -> None:
46 | drop_table('users')
47 |
--------------------------------------------------------------------------------
/src/pyfaf/actions/pull_bug.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013 ABRT Team
2 | # Copyright (C) 2013 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | from pyfaf.actions import Action
20 | from pyfaf.bugtrackers import bugtrackers
21 |
22 |
23 | class PullBug(Action):
24 | name = "pull-bug"
25 |
26 | def run(self, cmdline, db) -> int:
27 | tracker = bugtrackers[cmdline.bugtracker]
28 |
29 | if not tracker.installed(db):
30 | self.log_error("Bugtracker is not installed")
31 | return 1
32 |
33 | tracker.download_bug_to_storage(db, cmdline.BUG_ID)
34 |
35 | return 0
36 |
37 | def tweak_cmdline_parser(self, parser) -> None:
38 | parser.add_bugtracker(required=True,
39 | help="pull bug from this bug tracker")
40 |
41 | parser.add_argument("BUG_ID", validators=[("InputRequired", {})],
42 | help="download bug with this ID")
43 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/fixtures/sql/packages.sql:
--------------------------------------------------------------------------------
1 | INSERT INTO packages VALUES(1,NULL,1,2,'glibc-utils','rpm');
2 | INSERT INTO packages VALUES(2,NULL,1,2,'glibc-debuginfo-common','rpm');
3 | INSERT INTO packages VALUES(3,NULL,1,2,'glibc-common','rpm');
4 | INSERT INTO packages VALUES(4,NULL,1,2,'glibc-devel','rpm');
5 | INSERT INTO packages VALUES(5,NULL,1,2,'glibc','rpm');
6 | INSERT INTO packages VALUES(6,NULL,1,2,'glibc-debuginfo','rpm');
7 | INSERT INTO packages VALUES(7,NULL,1,2,'nscd','rpm');
8 | INSERT INTO packages VALUES(8,NULL,1,2,'glibc-headers','rpm');
9 | INSERT INTO packages VALUES(9,NULL,1,2,'glibc-static','rpm');
10 | INSERT INTO packages VALUES(10,NULL,1,1,'glibc-common','rpm');
11 | INSERT INTO packages VALUES(11,NULL,1,1,'glibc-static','rpm');
12 | INSERT INTO packages VALUES(12,NULL,1,1,'glibc-debuginfo-common','rpm');
13 | INSERT INTO packages VALUES(13,NULL,1,1,'glibc-devel','rpm');
14 | INSERT INTO packages VALUES(14,NULL,1,1,'glibc-utils','rpm');
15 | INSERT INTO packages VALUES(15,NULL,1,1,'glibc-headers','rpm');
16 | INSERT INTO packages VALUES(16,NULL,1,1,'glibc-debuginfo','rpm');
17 | INSERT INTO packages VALUES(17,NULL,1,1,'glibc','rpm');
18 | INSERT INTO packages VALUES(18,NULL,1,1,'nscd','rpm');
19 | INSERT INTO packages VALUES(19,NULL,1,9,'glibc','rpm');
20 | INSERT INTO packages VALUES(20,NULL,2,2,'will-crash','rpm');
21 | INSERT INTO packages VALUES(21,NULL,2,2,'will-crash-debuginfo','rpm');
22 | INSERT INTO packages VALUES(22,NULL,2,1,'will-crash-debuginfo','rpm');
23 | INSERT INTO packages VALUES(23,NULL,2,1,'will-crash','rpm');
24 | INSERT INTO packages VALUES(24,NULL,2,9,'will-crash','rpm');
25 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/migrations/versions/82081a3c76b_rename_kb_to_sf_prefilter.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2014 ABRT Team
2 | # Copyright (C) 2014 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | """
20 | Rename Kb to SF-prefilter
21 |
22 | Revision ID: 82081a3c76b
23 | Revises: 31d0249e8d4c
24 | Create Date: 2014-10-21 12:34:28.849585
25 | """
26 |
27 | from alembic.op import rename_table
28 |
29 | # revision identifiers, used by Alembic.
30 | revision = "82081a3c76b"
31 | down_revision = "31d0249e8d4c"
32 |
33 |
34 | def upgrade() -> None:
35 | rename_table("kbsolutions", "sfprefiltersolutions")
36 | rename_table("kbbacktracepath", "sfprefilterbacktracepaths")
37 | rename_table("kbpackagename", "sfprefilterpackagenames")
38 |
39 |
40 | def downgrade() -> None:
41 | rename_table("sfprefiltersolutions", "kbsolutions")
42 | rename_table("sfprefilterbacktracepaths", "kbbacktracepath")
43 | rename_table("sfprefilterpackagenames", "kbpackagename")
44 |
--------------------------------------------------------------------------------
/.github/workflows/codeql.yml:
--------------------------------------------------------------------------------
1 | name: CodeQL analysis
2 | on:
3 | push:
4 | branches: ["master"]
5 | pull_request:
6 | branches: ["master"]
7 | schedule:
8 | - cron: "12 17 * * 3"
9 | jobs:
10 | analyze:
11 | name: Analyze
12 | container:
13 | image: fedora:latest
14 | runs-on: ubuntu-latest
15 | permissions:
16 | actions: read
17 | contents: read
18 | security-events: write
19 | strategy:
20 | fail-fast: false
21 | matrix:
22 | language: [javascript, python]
23 | steps:
24 | - name: Check out sources
25 | uses: actions/checkout@v3
26 |
27 | - name: Install dependencies (Python)
28 | if: ${{ matrix.language == 'python' }}
29 | run: |
30 | dnf --assumeyes install --setopt=install_weak_deps=False \
31 | autoconf automake dnf-plugins-core make which
32 | dnf --assumeyes copr enable @abrt/faf-el8-devel
33 | dnf --assumeyes builddep --spec faf.spec
34 | echo CODEQL_PYTHON=/usr/bin/python3 >> $GITHUB_ENV
35 |
36 | - name: Generate build files and build
37 | if: ${{ matrix.language == 'python' }}
38 | run: ./autogen.sh && make -j
39 |
40 | - name: Initialize CodeQL
41 | uses: github/codeql-action/init@v2
42 | with:
43 | languages: ${{ matrix.language }}
44 | queries: +security-and-quality
45 | setup-python-dependencies: false
46 |
47 | - name: Perform CodeQL Analysis
48 | uses: github/codeql-action/analyze@v2
49 | with:
50 | category: "/language:${{ matrix.language }}"
51 |
--------------------------------------------------------------------------------
/config/plugins/web.conf:
--------------------------------------------------------------------------------
1 | [hub]
2 | debug = false
3 | proxy_setup = false
4 | secret_key = @SECRET_KEY@
5 | require_https = true
6 | url = https://example.org/faf/
7 | # server name is the bare URL without protocols and trailing slash
8 | server_name = example.org/faf
9 | brand_title = ABRT
10 | brand_subtitle = Analytics
11 | # A simple banner to notify users of scheduled downtime etc. Fill in text as needed, no text means no banner.
12 | banner =
13 | # uncomment the following two options to enable Fedmenu
14 | # fedmenu_url = https://apps.fedoraproject.org/fedmenu
15 | # fedmenu_data_url = https://apps.fedoraproject.org/js/data.js
16 |
17 | # When OpenID login is disabled, this option can be used to override permission
18 | # checks and make everyone a package maintainer.
19 | # In that case no login is necessary to access maintainer-only actions.
20 | everyone_is_maintainer = false
21 | # When OpenID login is disabled, this option can be used to override permission
22 | # checks and make everyone an admin.
23 | # In that case no login is necessary to access admin-only actions.
24 | everyone_is_admin = false
25 |
26 | [openid]
27 | enabled = true
28 |
29 | # Comma-separated list of teams provided by OpenID via
30 | # https://github.com/puiterwijk/python-openid-teams
31 | # Members of these teams will be granted maintainer privileges
32 | # privileged_teams = provenpackager,proventesters
33 |
34 | [cache]
35 | #types:
36 | # null - no caching
37 | # simple - process-local memory cache
38 | # memcached - requires pylibmc
39 | type = simple
40 | # memcached_host = localhost
41 | # memcached_port = 11211
42 | # memcached_key_prefix = webfaf
43 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/project.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013 ABRT Team
2 | # Copyright (C) 2013 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | from sqlalchemy.orm import relationship
20 | from sqlalchemy.sql.schema import Column, ForeignKey
21 | from sqlalchemy.types import DateTime, Integer, String
22 |
23 | from .generic_table import GenericTable
24 |
25 |
26 | class Project(GenericTable):
27 | __tablename__ = "projects"
28 |
29 | id = Column(Integer, primary_key=True)
30 | name = Column(String(64), nullable=False, unique=True, index=True)
31 |
32 |
33 | class ProjRelease(GenericTable):
34 | __tablename__ = "projectreleases"
35 |
36 | id = Column(Integer, primary_key=True)
37 | project_id = Column(Integer, ForeignKey("{0}.id".format(Project.__tablename__)), nullable=False, index=True)
38 | # may be git hash
39 | version = Column(String(64), nullable=False)
40 | pubdate = Column(DateTime, nullable=False)
41 | project = relationship(Project, backref="releases")
42 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/migrations/versions/272e6a3deea4_link_probable_fix_to_build.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2014 ABRT Team
2 | # Copyright (C) 2014 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | """
20 | Link probable fix to Build
21 |
22 | Revision ID: 272e6a3deea4
23 | Revises: 82081a3c76b
24 | Create Date: 2014-12-08 14:44:00.362834
25 | """
26 |
27 | from alembic.op import add_column, drop_column
28 | import sqlalchemy as sa
29 |
30 | # revision identifiers, used by Alembic.
31 | revision = '272e6a3deea4'
32 | down_revision = '82081a3c76b'
33 |
34 |
35 | def upgrade() -> None:
36 | add_column('problemopsysreleases', sa.Column('probable_fix_build_id', sa.Integer(), nullable=True))
37 | drop_column('problemopsysreleases', u'probable_fix')
38 |
39 |
40 | def downgrade() -> None:
41 | add_column('problemopsysreleases',
42 | sa.Column(u'probable_fix', sa.VARCHAR(length=256), autoincrement=False, nullable=True))
43 | drop_column('problemopsysreleases', 'probable_fix_build_id')
44 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/migrations/versions/bb2289ffb392_add_tz_info_to_periodictasks.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2019 ABRT Team
2 | # Copyright (C) 2019 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | """
20 | add TZ info to periodictasks
21 |
22 | Revision ID: bb2289ffb392
23 | Revises: 9596a0f03838
24 | Create Date: 2019-12-12 14:59:44.743113
25 | """
26 |
27 | from alembic.op import alter_column
28 | import sqlalchemy as sa
29 |
30 |
31 | # revision identifiers, used by Alembic.
32 | revision = 'bb2289ffb392'
33 | down_revision = '9596a0f03838'
34 |
35 |
36 | def upgrade() -> None:
37 | alter_column('periodictasks', 'last_run_at', type_=sa.DateTime(timezone=True), nullable=True)
38 | alter_column('taskresult', 'finished_time', type_=sa.DateTime(timezone=True), nullable=True)
39 |
40 |
41 | def downgrade() -> None:
42 | alter_column('periodictasks', 'last_run_at', type_=sa.DateTime(timezone=False), nullable=True)
43 | alter_column('taskresult', 'finished_time', type_=sa.DateTime(timezone=False), nullable=True)
44 |
--------------------------------------------------------------------------------
/src/pyfaf/actions/find_report_solution.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013 ABRT Team
2 | # Copyright (C) 2013 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | from pyfaf.actions import Action
20 | from pyfaf.queries import get_report_opsysrelease
21 | from pyfaf.solutionfinders import find_solution
22 | from pyfaf.storage import (Report)
23 |
24 |
25 | class FindReportSolution(Action):
26 | name = "find-report-solution"
27 |
28 |
29 | def run(self, cmdline, db) -> None:
30 | db.session.autocommit = False
31 | for report in db.session.query(Report).filter(Report.max_certainty.is_(None)):
32 | osr = get_report_opsysrelease(db=db, report_id=report.id)
33 | solutions = [find_solution(report, db=db, osr=osr)]
34 |
35 | if solutions[0] is not None:
36 | report.max_certainty = max((s.certainty for s in solutions))
37 | self.log_info("Max_certainty of report '{0}' is changed to {1}".format(report.id, report.max_certainty))
38 |
39 | db.session.commit()
40 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/migrations/versions/58f44afc3a3a_drop_running_package_from_reportpackages.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2014 ABRT Team
2 | # Copyright (C) 2014 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | """
20 | Drop running_package from reportpackages
21 |
22 | Revision ID: 58f44afc3a3a
23 | Revises: 1b264b21ca91
24 | Create Date: 2015-03-03 17:56:36.903726
25 | """
26 |
27 | from alembic.op import drop_constraint, drop_column, add_column
28 | import sqlalchemy as sa
29 |
30 | # revision identifiers, used by Alembic.
31 | revision = "58f44afc3a3a"
32 | down_revision = "1b264b21ca91"
33 |
34 |
35 | def upgrade() -> None:
36 | drop_constraint("reportpackages_running_package_id_fkey",
37 | "reportpackages")
38 |
39 | drop_column("reportpackages", "running_package_id")
40 |
41 |
42 | def downgrade() -> None:
43 | add_column("reportpackages",
44 | sa.Column("running_package_id", sa.Integer(),
45 | sa.ForeignKey("packages.id"),
46 | nullable=True))
47 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/migrations/versions/183a15e52a4f_report_history_unique.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2016 ABRT Team
2 | # Copyright (C) 2016 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | """
20 | Unique column added into report history
21 |
22 | Revision ID: 183a15e52a4f
23 | Revises: 133991a89da4
24 | Create Date: 2016-09-26 14:35:00.567052
25 | """
26 |
27 | from alembic.op import add_column, drop_column
28 | import sqlalchemy as sa
29 |
30 | # revision identifiers, used by Alembic.
31 | revision = "183a15e52a4f"
32 | down_revision = "133991a89da4"
33 |
34 |
35 | def upgrade() -> None:
36 | add_column("reporthistorydaily", sa.Column("unique", sa.Integer, nullable=True))
37 | add_column("reporthistoryweekly", sa.Column("unique", sa.Integer, nullable=True))
38 | add_column("reporthistorymonthly", sa.Column("unique", sa.Integer, nullable=True))
39 |
40 |
41 | def downgrade() -> None:
42 | drop_column("reporthistorydaily", "unique")
43 | drop_column("reporthistoryweekly", "unique")
44 | drop_column("reporthistorymonthly", "unique")
45 |
--------------------------------------------------------------------------------
/src/pyfaf/actions/opsysadd.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013 ABRT Team
2 | # Copyright (C) 2013 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | from pyfaf.actions import Action
20 | from pyfaf.queries import get_opsys_by_name
21 | from pyfaf.storage.opsys import OpSys
22 |
23 |
24 | class OpSysAdd(Action):
25 | name = "opsysadd"
26 |
27 |
28 | def run(self, cmdline, db) -> int:
29 | opsys = get_opsys_by_name(db, cmdline.NAME)
30 |
31 | if opsys:
32 | self.log_error("Operating system '{0}' already defined"
33 | .format(cmdline.NAME))
34 | return 1
35 |
36 | self.log_info("Adding operating system '{0}'".format(cmdline.NAME))
37 |
38 | new = OpSys()
39 | new.name = cmdline.NAME
40 | db.session.add(new)
41 | db.session.flush()
42 | return 0
43 |
44 | def tweak_cmdline_parser(self, parser) -> None:
45 | parser.add_argument("NAME", validators=[("InputRequired", [])],
46 | help="name of new operating system")
47 |
--------------------------------------------------------------------------------
/src/pyfaf/actions/Makefile.am:
--------------------------------------------------------------------------------
1 | actions_PYTHON = \
2 | __init__.py \
3 | addcompathashes.py \
4 | archadd.py \
5 | archive_reports.py \
6 | archlist.py \
7 | assign_release_to_builds.py \
8 | attach_centos_bugs.py \
9 | bugtrackerlist.py \
10 | pull_abrt_bugs.py \
11 | pull_bug.py \
12 | update_bugs.py \
13 | c2p.py \
14 | check_repo.py \
15 | cleanup_packages.py \
16 | cleanup_task_results.py \
17 | cleanup_unassigned.py \
18 | componentadd.py \
19 | create_problems.py \
20 | delete_invalid_ureports.py \
21 | extfafadd.py \
22 | extfafclonebz.py \
23 | extfafdelete.py \
24 | extfaflink.py \
25 | extfafmodify.py \
26 | extfafshow.py \
27 | fedmsg_notify.py \
28 | find_components.py \
29 | find_crash_function.py \
30 | find_report_solution.py \
31 | hash_paths.py \
32 | init.py \
33 | mark_probably_fixed.py \
34 | pull_associates.py \
35 | pull_components.py \
36 | pull_releases.py \
37 | pull_reports.py \
38 | releaseadd.py \
39 | releasedel.py \
40 | releaselist.py \
41 | releasemod.py \
42 | repoadd.py \
43 | repoassign.py \
44 | repodel.py \
45 | repoimport.py \
46 | repoinfo.py \
47 | repolist.py \
48 | repomod.py \
49 | reposync.py \
50 | retrace.py \
51 | retrace_remote.py \
52 | sar.py \
53 | save_reports.py \
54 | sf_prefilter_soladd.py \
55 | sf_prefilter_solshow.py \
56 | sf_prefilter_patadd.py \
57 | sf_prefilter_patshow.py \
58 | shell.py \
59 | stats.py \
60 | opsysadd.py \
61 | opsysdel.py \
62 | opsyslist.py \
63 | match_unknown_packages.py
64 |
65 | actionsdir = $(pythondir)/pyfaf/actions
66 |
--------------------------------------------------------------------------------
/tests/test_dnf.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 | # -*- encoding: utf-8 -*-
3 | import unittest
4 | import os
5 | import shutil
6 | import logging
7 | import tempfile
8 |
9 | import faftests
10 |
11 | from pyfaf.repos.dnf import Dnf
12 | from pyfaf.utils.proc import popen
13 |
14 |
15 | class DnfTestCase(faftests.TestCase):
16 | """
17 | Test case for dnf repository plugin.
18 | """
19 |
20 | def test_list_packages(self):
21 | """
22 | Test whether list_packages lists our ad-hoc
23 | repository correctly.
24 | """
25 |
26 | rpm = "sample_rpms/sample-1.0-1.fc18.noarch.rpm"
27 |
28 | tmpdir = tempfile.mkdtemp()
29 | shutil.copyfile(rpm, os.path.join(tmpdir, os.path.basename(rpm)))
30 |
31 | proc = popen("createrepo_c", "--verbose", tmpdir)
32 | self.assertTrue(b"Workers Finished" in proc.stdout or b"Pool finished" in proc.stdout)
33 |
34 | dnf = Dnf("test_repo_name", tmpdir)
35 | pkgs = dnf.list_packages(["noarch"])
36 | self.assertEqual(len(pkgs), 1)
37 | pkg = pkgs.pop()
38 | self.assertEqual(pkg["name"], "sample")
39 | self.assertEqual(pkg["base_package_name"], "sample")
40 | self.assertEqual(pkg["version"], "1.0")
41 | self.assertEqual(pkg["release"], "1.fc18")
42 | self.assertEqual(pkg["arch"], "noarch")
43 |
44 | self.assertEqual(pkg["filename"], os.path.basename(rpm))
45 | self.assertEqual(pkg["url"], "file://{0}".format(
46 | os.path.join(tmpdir, os.path.basename(rpm))))
47 |
48 | self.assertEqual(pkg["type"], "rpm")
49 |
50 | shutil.rmtree(tmpdir)
51 |
52 | if __name__ == "__main__":
53 | logging.basicConfig(level=logging.INFO)
54 | unittest.main()
55 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/migrations/versions/50d3e87e4b2a_add_reporturl.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2015 ABRT Team
2 | # Copyright (C) 2015 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | """
20 | Add reporturl
21 |
22 | Revision ID: 50d3e87e4b2a
23 | Revises: 21345f007bdf
24 | Create Date: 2015-10-15 14:27:16.769105
25 | """
26 |
27 | from alembic.op import create_table, drop_table
28 | import sqlalchemy as sa
29 |
30 | # revision identifiers, used by Alembic.
31 | revision = '50d3e87e4b2a'
32 | down_revision = '21345f007bdf'
33 |
34 |
35 | def upgrade() -> None:
36 | create_table('reporturls',
37 | sa.Column('id', sa.Integer(), nullable=False),
38 | sa.Column('report_id', sa.Integer(), nullable=False),
39 | sa.Column('url', sa.String(length=1024), nullable=False),
40 | sa.Column('saved', sa.DateTime(), nullable=True),
41 | sa.ForeignKeyConstraint(['report_id'], ['reports.id'], ),
42 | sa.PrimaryKeyConstraint('id'),
43 | )
44 |
45 | def downgrade() -> None:
46 | drop_table('reporturls')
47 |
--------------------------------------------------------------------------------
/src/webfaf/templates/summary/index.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 | {% from "_helpers.html" import render_field %}
3 | {% from "_helpers.html" import paginator %}
4 |
5 | {% block title %}Summary{% endblock %}
6 |
7 | {% block js %}
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | {% endblock js %}
16 |
17 | {% block body %}
18 |
19 |
30 |
31 | {% if cached_plot %}
32 | {{ cached_plot|safe }}
33 | {% else %}
34 | {% include "summary/index_plot_data.html" with context %}
35 | {% endif %}
36 |
37 |
38 | {% endblock %}
39 |
--------------------------------------------------------------------------------
/src/pyfaf/actions/archadd.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013 ABRT Team
2 | # Copyright (C) 2013 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | from pyfaf.actions import Action
20 | from pyfaf.queries import get_arch_by_name
21 | from pyfaf.storage.opsys import Arch
22 |
23 |
24 | class ArchAdd(Action):
25 | name = "archadd"
26 |
27 |
28 | def run(self, cmdline, db) -> int:
29 | for archname in cmdline.NAME:
30 | arch = get_arch_by_name(db, archname)
31 |
32 | if arch:
33 | self.log_error("Architecture '{0}' already defined"
34 | .format(archname))
35 | return 1
36 |
37 | self.log_info("Adding architecture '{0}'".format(archname))
38 |
39 | new = Arch()
40 | new.name = archname
41 | db.session.add(new)
42 | db.session.flush()
43 | return 0
44 |
45 | def tweak_cmdline_parser(self, parser) -> None:
46 | parser.add_argument("NAME", nargs="+", validators=[("InputRequired", {})],
47 | help="name of new architecture")
48 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/migrations/versions/17d4911132f8_assigning_release_to_repo.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2014 ABRT Team
2 | # Copyright (C) 2014 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | """
20 | Assigning release to repository
21 |
22 | Revision ID: 17d4911132f8
23 | Revises: 13557f1962e6
24 | Create Date: 2016-09-08 08:49:52.450697
25 | """
26 |
27 | from alembic.op import create_table, drop_table
28 | import sqlalchemy as sa
29 |
30 | # revision identifiers, used by Alembic.
31 | revision = '17d4911132f8'
32 | down_revision = '13557f1962e6'
33 |
34 |
35 | def upgrade() -> None:
36 | create_table('opsysreleaserepo',
37 | sa.Column('opsysrelease_id', sa.Integer(), nullable=False),
38 | sa.Column('repo_id', sa.Integer(), nullable=False),
39 | sa.ForeignKeyConstraint(['opsysrelease_id'], ['opsysreleases.id'], ),
40 | sa.ForeignKeyConstraint(['repo_id'], ['repo.id'], ),
41 | sa.PrimaryKeyConstraint('opsysrelease_id', 'repo_id'),
42 | )
43 |
44 |
45 | def downgrade() -> None:
46 | drop_table('opsysreleaserepo')
47 |
--------------------------------------------------------------------------------
/src/pyfaf/__init__.py.in:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013 ABRT Team
2 | # Copyright (C) 2013 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | __all__ = ["checker", "cmdline", "common", "config", "local",
20 | "queries", "retrace", "faf_rpm", "ureport", "utils", "actions",
21 | "bugtrackers", "opsys", "problemtypes", "repos"]
22 | __version__ = "@PACKAGE_VERSION@"
23 |
24 | from . import checker
25 | from . import cmdline
26 | from . import common
27 | from . import config
28 | from . import local
29 | from . import queries
30 | # soft dep on retrace - it pulls elfutils
31 | # No exception type(s) specifiedo exception type(s) specified
32 | # pylint: disable-msg=W0702
33 | try:
34 | from . import retrace
35 | except:
36 | # Invalid name "retrace" for type constant
37 | # pylint: disable-msg=C0103
38 | retrace = None
39 | # pylint: enable-msg=C0103
40 | # pylint: enable-msg=W0702
41 | from . import faf_rpm
42 | from . import ureport
43 | from . import utils
44 |
45 | from . import actions
46 | from . import bugtrackers
47 | from . import opsys
48 | from . import problemtypes
49 | from . import repos
50 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/migrations/versions/71905f91e7b7_add_archived_reports.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2017 ABRT Team
2 | # Copyright (C) 2017 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | """
20 | Add archived reports
21 |
22 | Revision ID: 71905f91e7b7
23 | Revises: 9301a426f19d
24 | Create Date: 2017-03-08 16:56:11.355916
25 | """
26 |
27 | from alembic.op import create_table, drop_table
28 | import sqlalchemy as sa
29 |
30 | # revision identifiers, used by Alembic.
31 | revision = '71905f91e7b7'
32 | down_revision = '9301a426f19d'
33 |
34 |
35 | def upgrade() -> None:
36 | create_table(
37 | 'reportarchive',
38 | sa.Column('id', sa.Integer, primary_key=True),
39 | sa.Column('date', sa.Date, nullable=False),
40 | sa.Column('active', sa.Boolean, nullable=False),
41 | sa.Column('report_id', sa.Integer, nullable=False),
42 | sa.Column('username', sa.String(100), nullable=False),
43 | sa.ForeignKeyConstraint(['report_id'], ['reports.id'], ),
44 | sa.ForeignKeyConstraint(['username'], ['users.username'], ),
45 | )
46 |
47 |
48 | def downgrade() -> None:
49 | drop_table('reportarchive')
50 |
--------------------------------------------------------------------------------
/src/webfaf/templates/reports/diff.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 | {% from '_helpers.html' import backtrace_table_columns %}
3 |
4 | {% block title %}Reports diff #{{lhs.id}} #{{rhs.id}}{% endblock %}
5 |
6 | {% block body %}
7 |
8 |
9 | Differences between backtraces from report
10 | - {{lhs.id}}
11 | and backtrace from report
12 | + {{rhs.id}}
13 |
14 |
15 |
16 |
17 |
18 |
19 | |
20 | Frame # |
21 | Function |
22 | {% if type != 'python' %}
23 | Binary |
24 | {% endif %}
25 | Source |
26 | Line |
27 |
28 | {% for l, r in diff %}
29 | {% if l and not r %}
30 |
31 | | - |
32 | {% endif %}
33 |
34 | {% if not l and r %}
35 |
36 | | + |
37 | {% endif %}
38 |
39 | {% if not l and not r %}
40 |
41 | |
42 | {% endif %}
43 |
44 | {% if l and r %}
45 |
46 | |
47 | {% endif %}
48 |
49 | {% if l %}
50 | {{ backtrace_table_columns(l, lhs.type) }}
51 | {% endif %}
52 |
53 | {% if not l and r %}
54 | {{ backtrace_table_columns(r, rhs.type) }}
55 | {% endif %}
56 |
57 | {% if not l and not r %}
58 | |
59 | |
60 | {% if type != 'python' %}
61 | |
62 | {% endif %}
63 | |
64 | |
65 | {% endif %}
66 |
67 | {% endfor %}
68 |
69 | {% endblock %}
70 |
--------------------------------------------------------------------------------
/src/pyfaf/actions/cleanup_task_results.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2015 ABRT Team
2 | # Copyright (C) 2015 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | from datetime import datetime, timedelta
20 | from pyfaf.actions import Action
21 | from pyfaf.storage.task import TaskResult
22 |
23 |
24 | class CleanupTaskResults(Action):
25 | name = "cleanup-task-results"
26 |
27 | def run(self, cmdline, db) -> None:
28 | if cmdline.keep_days >= 0:
29 | q = (db.session.query(TaskResult)
30 | .filter(TaskResult.finished_time <
31 | datetime.now()-timedelta(days=cmdline.keep_days)))
32 | self.log_info("About to delete {0} task results older than {1} days."
33 | .format(q.count(), cmdline.keep_days))
34 | q.delete()
35 | db.session.flush()
36 | self.log_info("Task results deleted")
37 | else:
38 | self.log_warn("--keep-days must be greater or equal to 0.")
39 |
40 | def tweak_cmdline_parser(self, parser) -> None:
41 | parser.add_argument("--keep-days", help="keep results for the last D days",
42 | default=14, type=int)
43 |
--------------------------------------------------------------------------------
/src/pyfaf/actions/sar.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2018 ABRT Team
2 | # Copyright (C) 2018 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | import os
20 | from pyfaf.actions import Action
21 | from pyfaf.storage.user import User
22 | from pyfaf.utils.user import UserDataDumper
23 |
24 | class SubjectAccessRequest(Action):
25 | name = "sar"
26 |
27 | def run(self, cmdline, db) -> int:
28 | mail = os.environ.get("SAR_EMAIL", None)
29 | username = os.environ.get("SAR_USERNAME", None)
30 |
31 | if not mail and not username:
32 | print("Environment variables SAR_USERNAME, SAR_EMAIL were not set.")
33 | return 1
34 |
35 | if mail:
36 | dumper = UserDataDumper(db, mail)
37 | print(dumper.dump(pretty=True))
38 | return 0
39 |
40 | if username:
41 | usermail = db.session.query(User).filter(User.username == username).first()
42 | if usermail is not None:
43 | dumper = UserDataDumper(db, usermail.mail)
44 | print(dumper.dump(pretty=True))
45 | else:
46 | print("User '{0}' was not found.".format(username))
47 |
48 | return 0
49 |
--------------------------------------------------------------------------------
/docs/ureport_sample:
--------------------------------------------------------------------------------
1 | {
2 | "reporter": {
3 | "version": "2.0.7-2.fc16",
4 | "name": "abrt"
5 | },
6 | "selinux": {
7 | "policy_package": {
8 | "release": "2.fc16",
9 | "epoch": 0,
10 | "version": "3.10.0",
11 | "name": "selinux-policy",
12 | "architecture": "noarch"
13 | },
14 | "mode": "permissive",
15 | "context": "unconfined_u:unconfined_r:unconfined_t:s0"
16 | },
17 | "uptime": 1,
18 | "installed_package": {
19 | "release": "1.fc16",
20 | "epoch": 0,
21 | "version": "0.4",
22 | "name": "faf",
23 | "architecture": "noarch"
24 | },
25 | "user_type": "root",
26 | "reason": "TypeError",
27 | "related_packages": [
28 | {
29 | "installed_package": {
30 | "release": "4.fc16",
31 | "epoch": 0,
32 | "version": "2.7.2",
33 | "name": "python",
34 | "architecture": "x86_64"
35 | }
36 | }
37 | ],
38 | "executable": "/usr/bin/faf-btserver-cgi",
39 | "type": "python",
40 | "architecture": "x86_64",
41 | "crash_thread": 0,
42 | "os": {
43 | "version": "16",
44 | "name": "Fedora"
45 | },
46 | "core_backtrace": [
47 | {
48 | "thread": 0,
49 | "buildid": "f76f656ab6e1b558fc78d0496f1960071565b0aa",
50 | "frame": 1,
51 | "funcname": "",
52 | "offset": 24,
53 | "path": "/usr/bin/faf-btserver-cgi"
54 | },
55 | {
56 | "thread": 0,
57 | "buildid": "b07daccd370e885bf3d459984a4af09eb889360a",
58 | "frame": 2,
59 | "funcname": "compile",
60 | "offset": 190,
61 | "path": "/usr/lib64/python2.7/re.py"
62 | },
63 | {
64 | "thread": 0,
65 | "buildid": "b07daccd370e885bf3d459984a4af09eb889360a",
66 | "frame": 3,
67 | "funcname": "_compile",
68 | "offset": 241,
69 | "path": "/usr/lib64/python2.7/re.py"
70 | }
71 | ]
72 | }
73 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/fixtures/randutils.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013 ABRT Team
2 | # Copyright (C) 2013 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | from __future__ import division
20 | import os
21 | import random
22 | import hashlib
23 |
24 | from typing import Collection, Sequence, Union
25 |
26 | def pickhalf(objects) -> Union[Sequence, Collection]:
27 | '''
28 | Randomly pick half of the objects
29 | '''
30 | return random.sample(objects, len(objects)//2)
31 |
32 | def pickmost(objects) -> Union[Sequence, Collection]:
33 | '''
34 | Randomly pick 9/10 of the objects
35 | '''
36 | return random.sample(objects, len(objects)-len(objects)//10)
37 |
38 | def toss() -> bool:
39 | '''
40 | Coin toss
41 | '''
42 | return bool(random.randrange(2))
43 |
44 | def tosshigh() -> bool:
45 | '''
46 | High probability coin toss (9 of 10)
47 | '''
48 | return bool(random.randrange(10))
49 |
50 | def tosslow() -> bool:
51 | '''
52 | Low probability coin toss (1 of 10)
53 | '''
54 | return not bool(random.randrange(10))
55 |
56 | def randhash() -> str:
57 | '''
58 | Returns random sha1 hash
59 | '''
60 | return hashlib.sha1(os.urandom(30).encode("utf-8")).hexdigest()
61 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/bugtracker.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013 ABRT Team
2 | # Copyright (C) 2013 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | from typing import Optional
20 |
21 | from sqlalchemy.sql.schema import Column
22 | from sqlalchemy.types import Integer, String
23 |
24 | from pyfaf.config import config
25 |
26 | from .generic_table import GenericTable
27 |
28 |
29 | class Bugtracker(GenericTable):
30 | __tablename__ = "bugtrackers"
31 |
32 | id = Column(Integer, primary_key=True)
33 | name = Column(String(64), nullable=False)
34 |
35 | def __str__(self) -> str:
36 | return str(self.name)
37 |
38 | @property
39 | def web_url(self) -> Optional[str]:
40 | cfgstr = "{0}.web_url".format(self.name)
41 | if cfgstr in config:
42 | return config[cfgstr]
43 | return None
44 |
45 | @property
46 | def api_url(self) -> Optional[str]:
47 | cfgstr = "{0}.api_url".format(self.name)
48 | if cfgstr in config:
49 | return config[cfgstr]
50 | return None
51 |
52 | @property
53 | def abbr(self) -> str:
54 | cfgstr = "{0}.abbr".format(self.name)
55 | if cfgstr in config:
56 | return config[cfgstr]
57 | return ""
58 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/migrations/versions/5695a1c595c3_reportreleasedesktops.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2014 ABRT Team
2 | # Copyright (C) 2014 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | """
20 | Added reportreleasedesktops table
21 |
22 | Revision ID: 5695a1c595c3
23 | Revises: 23bab42e7be7
24 | Create Date: 2014-08-22 12:21:50.973673
25 | """
26 |
27 | from alembic.op import create_table, drop_table
28 | import sqlalchemy as sa
29 |
30 | # revision identifiers, used by Alembic.
31 | revision = '5695a1c595c3'
32 | down_revision = '23bab42e7be7'
33 |
34 |
35 | def upgrade() -> None:
36 | create_table('reportreleasedesktops',
37 | sa.Column('report_id', sa.Integer(), nullable=False),
38 | sa.Column('release_id', sa.Integer(), nullable=False),
39 | sa.Column('desktop', sa.String(length=256), nullable=False),
40 | sa.Column('count', sa.Integer(), nullable=False),
41 | sa.ForeignKeyConstraint(['release_id'], ['opsysreleases.id'], ),
42 | sa.ForeignKeyConstraint(['report_id'], ['reports.id'], ),
43 | sa.PrimaryKeyConstraint('report_id', 'release_id', 'desktop'),
44 | )
45 |
46 |
47 | def downgrade() -> None:
48 | drop_table('reportreleasedesktops')
49 |
--------------------------------------------------------------------------------
/config/faf.conf.in:
--------------------------------------------------------------------------------
1 | # Faf site-wide configuration file
2 | # The settings are overridden by the file specified in
3 | # FAF_CONFIG_FILE environment variable.
4 | [Main]
5 | PluginsDir = @sysconfdir@/faf/plugins/
6 | TemplatesDir = @sysconfdir@/faf/templates/
7 | AutoEnablePlugins = True
8 |
9 | [Storage]
10 | DBUser =
11 | DBPasswd =
12 | DBHost =
13 | DBPort =
14 | DBName = faf
15 | LobDir = @localstatedir@/spool/faf/lob
16 | # Using platform-specific location by default.
17 | # Uncomment and change if needed.
18 | # TmpDir = /tmp
19 |
20 |
21 | [Mail]
22 | # where to send notification emails, comma separated list
23 | Admins = root@localhost.localdomain
24 | Server = localhost
25 | Port = 25
26 | Username =
27 | Password =
28 | From = no-reply@localhost
29 |
30 | [uReport]
31 | # The directory that holds 'reports' and 'attachments' subdirectories
32 | Directory = @localstatedir@/spool/faf
33 | CreateComponents = False
34 | # attachments accepted by this server
35 | # allowed values: fedora-bugzilla rhel-bugzilla centos-mantisb comment email url
36 | # or * to allow all attachments
37 | AcceptAttachments = fedora-bugzilla rhel-bugzilla centos-mantisbt
38 |
39 | # Allow uReports without affected package - meaning that crashing code was
40 | # not packaged
41 | allow-unpackaged = False
42 |
43 | # Determines which strategy will be used for searching known or unknown ureport's
44 | # and bugzilla bug's, if known is empty, then is used BUG_OS_MINOR_VERSION
45 | #
46 | # BUG_OS_MAJOR_VERSION - The report has attached a bug with equivalent OS Major
47 | # version name
48 | # BUG_OS_MINOR_VERSION - The report has attached a bug with equivalent OS Major
49 | # version and OS Minor version name
50 | # EQUAL_UREPORT_EXISTS - Report OS Major version match AND uReport OS Minor
51 | # version match AND uReport OS Architecture match AND Packages match name
52 | #
53 | # allowed values for the Known option
54 | # BUG_OS_MAJOR_VERSION BUG_OS_MINOR_VERSION EQUAL_UREPORT_EXISTS
55 | Known =
56 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/migrations/versions/133991a89da4_build_to_opsysrelease.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2014 ABRT Team
2 | # Copyright (C) 2014 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | """
20 | Assign build to operating system, release and architecture
21 |
22 | Revision ID: 133991a89da4
23 | Revises: 17d4911132f8
24 | Create Date: 2016-09-08 09:08:26.035450
25 | """
26 |
27 | from alembic.op import create_table, drop_table
28 | import sqlalchemy as sa
29 |
30 |
31 | # revision identifiers, used by Alembic.
32 | revision = '133991a89da4'
33 | down_revision = '17d4911132f8'
34 |
35 |
36 | def upgrade() -> None:
37 | create_table('buildopsysreleasearch',
38 | sa.Column('build_id', sa.Integer(), nullable=False),
39 | sa.Column('opsysrelease_id', sa.Integer(), nullable=False),
40 | sa.Column('arch_id', sa.Integer(), nullable=False),
41 | sa.ForeignKeyConstraint(['build_id'], ['builds.id'], ),
42 | sa.ForeignKeyConstraint(['opsysrelease_id'], ['opsysreleases.id'], ),
43 | sa.ForeignKeyConstraint(['arch_id'], ['archs.id'], ),
44 | sa.PrimaryKeyConstraint('build_id', 'opsysrelease_id', 'arch_id'),
45 | )
46 |
47 |
48 | def downgrade() -> None:
49 | drop_table('buildopsysreleasearch')
50 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/migrations/versions/f43edd5b636d_enable_problem_components_reassign.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2017 ABRT Team
2 | # Copyright (C) 2017 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | """
20 | Enable problem components reassign
21 |
22 | Revision ID: f43edd5b636d
23 | Revises: 71905f91e7b7
24 | Create Date: 2017-04-09 18:04:25.575450
25 | """
26 |
27 | from alembic.op import create_table, create_index, drop_index, drop_table, f
28 | import sqlalchemy as sa
29 |
30 | # revision identifiers, used by Alembic.
31 | revision = 'f43edd5b636d'
32 | down_revision = '71905f91e7b7'
33 |
34 |
35 | def upgrade() -> None:
36 | create_table(
37 | 'problemreassign',
38 | sa.Column('id', sa.Integer, primary_key=True),
39 | sa.Column('date', sa.Date, nullable=False),
40 | sa.Column('problem_id', sa.Integer, nullable=False),
41 | sa.Column('username', sa.String(100), nullable=False),
42 | sa.ForeignKeyConstraint(['problem_id'], ['problems.id'], ),
43 | sa.ForeignKeyConstraint(['username'], ['users.username'], ),
44 | )
45 | create_index('ix_problemreassign_problem_id', 'problemreassign', ['problem_id'])
46 |
47 |
48 | def downgrade() -> None:
49 | drop_index(f('ix_problemreassign_problem_id'), table_name='problemreassign')
50 | drop_table('problemreassign')
51 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/migrations/versions/fd5dc71471cc_set_pkg_name_to_256.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2019 ABRT Team
2 | # Copyright (C) 2019 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | """
20 | set-pkg-name-to-256
21 |
22 | Revision ID: fd5dc71471cc
23 | Revises: 8ac9b3343649
24 | Create Date: 2019-08-06 14:26:17.254047
25 | """
26 |
27 | import sqlalchemy as sa
28 | from alembic.op import alter_column
29 |
30 |
31 | # revision identifiers, used by Alembic.
32 | revision = "fd5dc71471cc"
33 | down_revision = "8ac9b3343649"
34 |
35 |
36 | def upgrade() -> None:
37 | alter_column("packages", "name", type_=sa.String(length=256), nullable=False)
38 | alter_column("opsyscomponents", "name", type_=sa.String(length=256), nullable=False)
39 | alter_column("builds", "base_package_name", type_=sa.String(length=256), nullable=False)
40 | alter_column("reportunknownpackages", "name", type_=sa.String(length=256), nullable=False)
41 |
42 |
43 | def downgrade() -> None:
44 | alter_column("packages", "name", type_=sa.String(length=64), nullable=False)
45 | alter_column("opsyscomponents", "name", type_=sa.String(length=64), nullable=False)
46 | alter_column("builds", "base_package_name", type_=sa.String(length=64), nullable=False)
47 | alter_column("reportunknownpackages", "name", type_=sa.String(length=64), nullable=False)
48 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/events.py:
--------------------------------------------------------------------------------
1 | from sqlalchemy import event
2 | from sqlalchemy.orm import mapper
3 | from sqlalchemy.orm.session import Session
4 |
5 | from . import Build
6 | from . import ReportBacktrace
7 | from . import ReportBtFrame
8 |
9 |
10 | @event.listens_for(ReportBtFrame, "init")
11 | def init_btframe(target, *args, **kwargs) -> None: # pylint: disable=unused-argument
12 | """
13 | Set reliable to True so it has default set correctly
14 | before it's stored in the database
15 | """
16 | target.reliable = True
17 |
18 |
19 | @event.listens_for(Session, "before_flush")
20 | def update_backtrace_quality(session, flush_context, instances) -> None: # pylint: disable=unused-argument
21 | """
22 | Compute and store backtrace quality information
23 | """
24 |
25 | objects = session.new.union(session.dirty)
26 | for obj in [c for c in objects if isinstance(c, ReportBacktrace)]:
27 | if isinstance(obj, ReportBacktrace):
28 | obj.quality = obj.compute_quality()
29 |
30 |
31 | @event.listens_for(mapper, "before_delete")
32 | def before_delete(_, connection, target) -> None: # pylint: disable=unused-argument
33 | """
34 | Remove lobs associated with target to be deleted.
35 | """
36 |
37 | for lobname in target.__lobs__:
38 | if target.has_lob(lobname):
39 | target.del_lob(lobname)
40 |
41 |
42 | @event.listens_for(Build.version, "set")
43 | def store_semantic_version_for_build(target, value, oldvalue, initiator) -> None: # pylint: disable=unused-argument
44 | """
45 | Store semnatic version (Build.semver) converted from text version
46 | (Build.version)
47 | """
48 |
49 | target.semver = value
50 |
51 |
52 | @event.listens_for(Build.release, "set")
53 | def store_semantic_release_for_build(target, value, oldvalue, initiator) -> None: # pylint: disable=unused-argument
54 | """
55 | Store semnatic release (Build.semrel) converted from text release
56 | (Build.release)
57 | """
58 |
59 | target.semrel = value
60 |
--------------------------------------------------------------------------------
/src/pyfaf/actions/bugtrackerlist.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013 ABRT Team
2 | # Copyright (C) 2013 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | from pyfaf.actions import Action
20 | from pyfaf.queries import get_bugtracker_by_name
21 | from pyfaf.bugtrackers import bugtrackers
22 | from pyfaf.storage.bugtracker import Bugtracker
23 | from pyfaf.utils.format import as_table
24 |
25 |
26 | class BugtrackerList(Action):
27 | name = "bugtrackerlist"
28 |
29 | def run(self, cmdline, db) -> None:
30 | if cmdline.detailed:
31 | data = []
32 | header = ["Name", "Installed", "API URL", "Web URL"]
33 | for tracker in bugtrackers:
34 | db_tracker = get_bugtracker_by_name(db, tracker)
35 |
36 | installed = "No"
37 | if db_tracker:
38 | installed = "Yes"
39 | tracker = db_tracker
40 |
41 | data.append((tracker, installed, tracker.api_url,
42 | tracker.web_url))
43 |
44 | print(as_table(header, data, margin=2))
45 | else:
46 | for tracker in db.session.query(Bugtracker):
47 | print(tracker)
48 |
49 | def tweak_cmdline_parser(self, parser) -> None:
50 | parser.add_argument("--detailed", action="store_true",
51 | help="detailed view")
52 |
--------------------------------------------------------------------------------
/src/pyfaf/actions/opsysdel.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013 ABRT Team
2 | # Copyright (C) 2013 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | from pyfaf.actions import Action
20 | from pyfaf.queries import get_opsys_by_name
21 |
22 |
23 | class OpSysDel(Action):
24 | name = "opsysdel"
25 |
26 |
27 | def run(self, cmdline, db) -> int:
28 | for opsys in cmdline.OPSYS:
29 | db_opsys = get_opsys_by_name(db, opsys)
30 |
31 | if not db_opsys:
32 | self.log_warn("Operating system '{0}' not found"
33 | .format(db_opsys))
34 | continue
35 |
36 | if db_opsys.releases:
37 | self.log_warn("Unable to delete operating system with associated"
38 | " releases. Following is the list of associated "
39 | " releases:")
40 | for release in db_opsys.releases:
41 | self.log_warn(release)
42 |
43 | continue
44 |
45 | self.log_info("Removing operating system '{0}'".format(opsys))
46 |
47 | db.session.delete(db_opsys)
48 | db.session.flush()
49 |
50 | return 0
51 |
52 | def tweak_cmdline_parser(self, parser) -> None:
53 | parser.add_opsys(positional=True, required=True, multiple=True, helpstr="operating system to delete")
54 |
--------------------------------------------------------------------------------
/src/pyfaf/actions/init.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013 ABRT Team
2 | # Copyright (C) 2013 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | from pyfaf.actions import Action
20 | from pyfaf.common import Plugin, log
21 | from pyfaf.queries import get_arch_by_name
22 | from pyfaf.storage import Arch
23 |
24 |
25 | class Init(Action):
26 | name = "init"
27 |
28 | archs = ["src", "noarch", "x86_64", "i386", "i486", "i586", "i686",
29 | "armv5tel", "armv7l", "armv7hl", "armv7hnl", "ppc", "ppc64",
30 | "ppc64le", "s390", "s390x", "sparc", "sparc64", "ia64"]
31 |
32 |
33 | def run(self, cmdline, db) -> None:
34 | for arch in Init.archs:
35 | db_arch = get_arch_by_name(db, arch)
36 | if db_arch is not None:
37 | continue
38 |
39 | self.log_info("Adding architecture '{0}'".format(arch))
40 | new = Arch()
41 | new.name = arch
42 | db.session.add(new)
43 |
44 | db.session.flush()
45 |
46 | plugins = set()
47 | for cls in Plugin.__subclasses__():
48 | plugins |= set(cls.__subclasses__())
49 |
50 | for plugin in plugins:
51 | if not plugin.installed(db):
52 | plugin.install(db, logger=log.getChild(plugin.__name__))
53 |
54 | db.session.flush()
55 |
56 | def tweak_cmdline_parser(self, parser) -> None:
57 | pass
58 |
--------------------------------------------------------------------------------
/src/pyfaf/actions/hash_paths.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2015 ABRT Team
2 | # Copyright (C) 2015 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | from sqlalchemy import or_
20 |
21 | from pyfaf.actions import Action
22 | from pyfaf.storage.symbol import Symbol
23 | from pyfaf.utils.hash import hash_path
24 |
25 |
26 | class HashPaths(Action):
27 | name = "hash-paths"
28 |
29 | def __init__(self) -> None:
30 | super().__init__()
31 | self.prefixes = None
32 | self.load_config_to_self("prefixes", ["ureport.private_prefixes"],
33 | "/home /opt /usr/local /tmp /var/tmp")
34 |
35 | self.prefixes = self.prefixes.split()
36 |
37 | def run(self, cmdline, db) -> None:
38 | q = db.session.query(Symbol)
39 |
40 | filters = []
41 |
42 | for p in self.prefixes:
43 | filters.append(Symbol.normalized_path.like("{}/%".format(p)))
44 |
45 | q = q.filter(or_(*filters))
46 |
47 | total = q.count()
48 | print("Going to process {} symbols".format(total))
49 |
50 | for c, symbol in enumerate(q.yield_per(100)):
51 | symbol.normalized_path = hash_path(symbol.normalized_path,
52 | self.prefixes)
53 |
54 | if not c % 1000:
55 | db.session.flush()
56 |
57 | db.session.flush()
58 | self.log_info("Done")
59 |
--------------------------------------------------------------------------------
/src/pyfaf/utils/web.py:
--------------------------------------------------------------------------------
1 | import logging
2 |
3 | from typing import Optional
4 |
5 | from pyfaf.config import config
6 |
7 |
8 | def webfaf_installed() -> bool:
9 | """
10 | Return True if webfaf is installed
11 | """
12 |
13 | try:
14 | import webfaf # pylint: disable=unused-import, unused-variable
15 | return True
16 | except: # pylint: disable=bare-except
17 | return False
18 |
19 |
20 | def server_url() -> Optional[str]:
21 | """
22 | Return web server root URL if applicable
23 | """
24 |
25 | if webfaf_installed():
26 | return config.get("hub.url", None)
27 |
28 | logging.warning("Unable to get web server URL, webfaf not available")
29 | return None
30 |
31 |
32 | def server_name() -> Optional[str]:
33 | """
34 | Return web server root URL if applicable
35 | """
36 |
37 | if webfaf_installed():
38 | return config.get("hub.server_name", None)
39 |
40 | logging.warning("Unable to get web server name, webfaf not available")
41 | return None
42 |
43 |
44 | def require_https() -> bool:
45 | """
46 | Return if web server requires https (default true)
47 | """
48 |
49 | if webfaf_installed():
50 | from pyfaf.utils.parse import str2bool
51 | return str2bool(config.get("hub.require_https", "true"))
52 |
53 | logging.warning("Unable to get require https option, webfaf not available")
54 | return True
55 |
56 |
57 | def reverse(view, **kwargs) -> Optional[str]:
58 | """
59 | Return full URL to pointing to `view`
60 | Wrapper around django"s own reverse.
61 | """
62 |
63 | if webfaf_installed():
64 | from flask import url_for
65 | from webfaf.webfaf_main import app
66 | app.config["SERVER_NAME"] = server_name()
67 | app.config["PREFERRED_URL_SCHEME"] = "https" if require_https() else "http"
68 | with app.app_context():
69 | kwargs["_external"] = True
70 | return url_for(view, **kwargs)
71 |
72 | logging.warning("Unable to get web server URL, webfaf not available")
73 | return None
74 |
--------------------------------------------------------------------------------
/src/webfaf/config.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | from sqlalchemy.engine.url import make_url
4 |
5 | import pyfaf
6 | from pyfaf.common import get_connect_string
7 | from pyfaf.config import config, paths
8 | from pyfaf.utils.parse import str2bool
9 |
10 | dburl = make_url(get_connect_string())
11 |
12 | WEBFAF_DIR = os.path.dirname(__file__)
13 |
14 |
15 | class Config:
16 | DEBUG = False
17 | TESTING = False
18 | SECRET_KEY = "NOT_A_RANDOM_STRING"
19 | SQLALCHEMY_DATABASE_URI = dburl
20 | SQLALCHEMY_TRACK_MODIFICATIONS = False
21 | OPENID_ENABLED = str2bool(config.get("openid.enabled", "false"))
22 | OPENID_FS_STORE = os.path.join(paths["spool"], "openid_store")
23 | OPENID_PRIVILEGED_TEAMS = [s.strip() for s in config.get("openid.privileged_teams", "").split(",")]
24 | PROXY_SETUP = False
25 | TEMPLATES_DIR = os.path.join(WEBFAF_DIR, "templates")
26 | ADMINS = config.get("mail.admins", "").split(",")
27 | BRAND_TITLE = config.get("hub.brand_title", "ABRT")
28 | BRAND_SUBTITLE = config.get("hub.brand_subtitle", "Analytics")
29 | BANNER = config.get("hub.banner", "")
30 | CACHE_TYPE = config.get("cache.type", "simple")
31 | MEMCACHED_HOST = config.get("cache.memcached_host", None)
32 | MEMCACHED_PORT = config.get("cache.memcached_port", None)
33 | MEMCACHED_KEY_PREFIX = config.get("cache.memcached_key_prefix", None)
34 | EVERYONE_IS_MAINTAINER = str2bool(config.get("hub.everyone_is_maintainer", "false"))
35 | EVERYONE_IS_ADMIN = str2bool(config.get("hub.everyone_is_admin", "false"))
36 | FEDMENU_URL = config.get("hub.fedmenu_url", None)
37 | FEDMENU_DATA_URL = config.get("hub.fedmenu_data_url", None)
38 | FAF_VERSION = pyfaf.__version__
39 |
40 |
41 | class ProductionConfig(Config):
42 | DEBUG = str2bool(config["hub.debug"])
43 | PROXY_SETUP = str2bool(config.get("hub.proxy_setup", "false"))
44 | SECRET_KEY = config["hub.secret_key"]
45 |
46 |
47 | class DevelopmentConfig(Config):
48 | DEBUG = True
49 | SQLALCHEMY_ECHO = True
50 |
51 |
52 | class TestingConfig(Config):
53 | TESTING = True
54 | OPENID_FS_STORE = None
55 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/migrations/versions/Makefile.am:
--------------------------------------------------------------------------------
1 | versions_PYTHON = \
2 | 1c4d6317721a_support_mirrors.py \
3 | 133991a89da4_build_to_opsysrelease.py \
4 | 168c63b81f85_report_history_default_value.py \
5 | 17d4911132f8_assigning_release_to_repo.py \
6 | 183a15e52a4f_report_history_unique.py \
7 | 1b264b21ca91_add_semrel_to_build.py \
8 | 1c7edfbf8941_drop_reportunknownpackage_running_fields.py \
9 | 21345f007bdf_add_privileged_user_field.py \
10 | 23bab42e7be7_initial_migration.py \
11 | 272e6a3deea4_link_probable_fix_to_build.py \
12 | 2dfd5aef57ca_add_eol_bz_resolution.py \
13 | 2e5f6d8b68f5_add_contact_email_tables.py \
14 | 31d0249e8d4c_create_users_table.py \
15 | 43bd2d59838e_add_mantisbt.py \
16 | 47cf82727ed1_acl_permissions.py \
17 | 48550f308625_add_symbolsource_retrace_fail_count.py \
18 | 4ff13674a015_add_semver_to_build.py \
19 | 50d3e87e4b2a_add_reporturl.py \
20 | 5695a1c595c3_reportreleasedesktops.py \
21 | 13557f1962e6_ureport_added_certainty.py \
22 | 58f44afc3a3a_drop_running_package_from_reportpackages.py \
23 | 71905f91e7b7_add_archived_reports.py \
24 | 729a154b1609_index_reportpackages.py \
25 | 7fa8b3134f0_probable_fix_by_opsy.py \
26 | 82081a3c76b_rename_kb_to_sf_prefilter.py \
27 | cef2fcd69ef_celery_tasks.py \
28 | 89d35a57f82b_add_new_value_to_repo_types_enum.py \
29 | 9301a426f19d_associates_to_opsys.py \
30 | acd3d9bf85d1_ignore_private_bz.py \
31 | e5d5cefb8ca4_add_dnf_type.py \
32 | f43edd5b636d_enable_problem_components_reassign.py \
33 | a2b6d12819f9_drop_yum_type.py \
34 | 093be3eab7e9_add_ondelete_cascade_to_problem_tables.py \
35 | cb084388e232_add_ondelete_cascade_to_report_bt_tables.py \
36 | e17dc14292b9_add_ondelete_cascade_to_report_tables.py \
37 | cee07a513404_drop_not_used_.py \
38 | 8ac9b3343649_add_semver_semrel_to_.py \
39 | fd5dc71471cc_set_pkg_name_to_256.py \
40 | 9596a0f03838_zero_unique_reports_to_one.py \
41 | bb2289ffb392_add_tz_info_to_periodictasks.py
42 |
43 |
44 | versionsdir = $(pythondir)/pyfaf/storage/migrations/versions
45 |
--------------------------------------------------------------------------------
/src/pyfaf/utils/date.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013 ABRT Team
2 | # Copyright (C) 2013 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | import datetime
20 |
21 | from typing import Generator, List
22 |
23 | __all__ = ["daterange", "prev_days"]
24 |
25 |
26 | def daterange(a_date, b_date, step=1, desc=False) -> Generator[datetime.date, None, None]:
27 | """
28 | Generator returning dates from lower to higher
29 | date if `desc` is False or from higher to lower
30 | if `desc` is True.
31 |
32 | `a_date` and `b_date` are always included in the
33 | result.
34 | """
35 |
36 | lower = min(a_date, b_date)
37 | higher = max(a_date, b_date)
38 |
39 | if desc:
40 | for x in range(0, (higher - lower).days, step):
41 | dt = higher - datetime.timedelta(x)
42 | yield dt
43 |
44 | yield lower
45 | else:
46 | for x in range(0, (higher - lower).days, step):
47 | dt = lower + datetime.timedelta(x)
48 | yield dt
49 |
50 | yield higher
51 |
52 |
53 | def prev_days(num_days, start_from=None) -> List[datetime.date]:
54 | """
55 | Return the list of dates preceding current day by `num_days`
56 | """
57 |
58 | dlist = []
59 | if not start_from:
60 | start_from = datetime.date.today()
61 |
62 | for i in range(1, num_days + 1):
63 | dlist.append(start_from - datetime.timedelta(days=i))
64 |
65 | return list(reversed(dlist))
66 |
--------------------------------------------------------------------------------
/src/webfaf/login.py:
--------------------------------------------------------------------------------
1 | import flask
2 | from openid_teams import teams
3 | from werkzeug.wrappers import Response
4 |
5 | from pyfaf.storage.user import User
6 | from webfaf.webfaf_main import db, oid, app
7 | from webfaf.utils import fed_raw_name
8 |
9 | login = flask.Blueprint("login", __name__)
10 |
11 |
12 | @login.route("/login/", methods=["GET"])
13 | @oid.loginhandler
14 | def do_login() -> Response:
15 | if flask.g.user is not None:
16 | return flask.redirect(oid.get_next_url())
17 |
18 | teams_req = teams.TeamsRequest(app.config["OPENID_PRIVILEGED_TEAMS"])
19 | return oid.try_login("https://id.fedoraproject.org/",
20 | ask_for=["email"], extensions=[teams_req])
21 |
22 |
23 | @oid.after_login
24 | def create_or_login(resp) -> Response:
25 | flask.session["openid"] = resp.identity_url
26 | username = fed_raw_name(resp.identity_url)
27 |
28 | privileged = False
29 | # "lp" is the namespace for openid-teams
30 | if "lp" in resp.extensions and any(group in app.config["OPENID_PRIVILEGED_TEAMS"]
31 | for group in resp.extensions["lp"].teams):
32 | privileged = True
33 |
34 | user = db.session.query(User).filter(User.username == username).first()
35 | if not user: # create
36 | user = User(username=username, mail=resp.email, privileged=privileged)
37 | else:
38 | user.mail = resp.email
39 | user.privileged = privileged
40 |
41 | db.session.add(user)
42 | db.session.commit()
43 | flask.flash(u"Welcome, {0}".format(user.username))
44 | # This is okay: https://flask.palletsprojects.com/en/2.0.x/api/#flask.g
45 | # pylint: disable=assigning-non-slot
46 | flask.g.user = user
47 |
48 | if flask.request.url_root == oid.get_next_url():
49 | return flask.redirect(flask.url_for("summary.index"))
50 |
51 | return flask.redirect(oid.get_next_url())
52 |
53 |
54 | @login.route("/logout/")
55 | def do_logout() -> Response:
56 | flask.session.pop("openid", None)
57 | flask.flash(u"You were signed out")
58 | return flask.redirect(oid.get_next_url())
59 |
--------------------------------------------------------------------------------
/src/pyfaf/utils/hash.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2015 ABRT Team
2 | # Copyright (C) 2015 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | import hashlib
20 |
21 | __all__ = ["hash_list", "hash_path"]
22 |
23 |
24 | def hash_list(inlist) -> str:
25 | """
26 | Return hash digest from `inlist` list of strings.
27 |
28 | Strings are concatenated with newlines prior to hashing
29 | """
30 |
31 | merged = "\n".join(inlist)
32 | return hashlib.sha1(merged.encode("utf-8")).hexdigest()
33 |
34 |
35 | def hash_path(path, prefixes) -> str:
36 | """
37 | Returns path with part after prefixes hashed with sha256
38 |
39 | In case of paths starting with /home, ignore username.
40 |
41 | Example:
42 | hash_path("/home/user/a.out", ["/home", "/opt"]) =
43 | "/home/1816a735235f2a21efd602ff4d9b157bf060540270230597923af0aa6de780e9"
44 |
45 | hash_path("/usr/local/private/code.src", ["/usr/local"]) =
46 | "/usr/local/039580e05aa4fcec4fbb57e0532311c399453950b741041bce8e72d17698416f"
47 | """
48 |
49 | for prefix in prefixes:
50 | if path.startswith(prefix):
51 | _, rest = path.split(prefix, 1)
52 | rest = rest[1:] # remove leading /
53 |
54 | if prefix == "/home":
55 | _, rest = rest.split("/", 1)
56 |
57 | hashed = hashlib.sha256(rest.encode("utf-8")).hexdigest()
58 |
59 | return "{0}/{1}".format(prefix, hashed)
60 | return path
61 |
--------------------------------------------------------------------------------
/src/pyfaf/actions/pull_abrt_bugs.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013 ABRT Team
2 | # Copyright (C) 2013 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | from pyfaf.actions import Action
20 | from pyfaf.bugtrackers import bugtrackers
21 |
22 |
23 | class PullAbrtBugs(Action):
24 | name = "pull-abrt-bugs"
25 |
26 | def run(self, cmdline, db) -> int:
27 | if cmdline.bugtracker:
28 | tracker = bugtrackers[cmdline.bugtracker]
29 | if not tracker.installed(db):
30 | self.log_error("Bugtracker is not installed")
31 | return 1
32 |
33 | self.log_info("Processing bugtracker: {0}"
34 | .format(cmdline.bugtracker))
35 | for bug_id in tracker.list_bugs():
36 | tracker.download_bug_to_storage(db, bug_id)
37 |
38 | return 0
39 |
40 | self.log_info("Processing all bugtrackers")
41 | for name, tracker in bugtrackers.items():
42 | self.log_info("Processing bugtracker: {0}".format(name))
43 | if not tracker.installed(db):
44 | self.log_info("Bugtracker {0} not installed, skipping"
45 | .format(name))
46 | continue
47 |
48 | for bug_id in tracker.list_bugs():
49 | tracker.download_bug_to_storage(db, bug_id)
50 |
51 | return 0
52 |
53 | def tweak_cmdline_parser(self, parser) -> None:
54 | parser.add_bugtracker()
55 |
--------------------------------------------------------------------------------
/src/pyfaf/utils/storage.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2014 ABRT Team
2 | # Copyright (C) 2014 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 |
20 | # Utility functions related to faf's storage
21 |
22 | from collections import defaultdict
23 |
24 | __all__ = ["format_reason", "most_common_crash_function"]
25 |
26 |
27 | def format_reason(rtype, reason, function_name) -> str:
28 | """
29 | Return formatted `reason` of the crash according to report type `rtype`
30 | """
31 |
32 | if rtype == "core":
33 | return "Crash in {0}".format(function_name)
34 |
35 | if rtype == "python":
36 | spl = reason.split(":")
37 | if len(spl) >= 4:
38 | fname, line, loc, exception = spl[:4]
39 | if loc == "":
40 | loc = "{0}:{1}".format(fname, line)
41 | return "{0} in {1}".format(exception, loc)
42 |
43 | return "Exception"
44 |
45 | if rtype == "kerneloops":
46 | return "Kerneloops"
47 |
48 | return "Crash"
49 |
50 |
51 | def most_common_crash_function(backtraces) -> str:
52 | """
53 | Return the most common crash function among all backtraces of this
54 | report
55 | """
56 |
57 | crash_functions = defaultdict(int)
58 | crash_functions["??"] = 0
59 | for bt in backtraces:
60 | if bt.crash_function:
61 | crash_functions[bt.crash_function] += 1
62 | result = max(crash_functions.items(), key=lambda x: x[1])
63 | return result[0]
64 |
--------------------------------------------------------------------------------
/src/pyfaf/storage/migrations/versions/9596a0f03838_zero_unique_reports_to_one.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2020 ABRT Team
2 | # Copyright (C) 2020 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | """
20 | Make all report summaries contain at least one unique report
21 |
22 | Revision ID: 9596a0f03838
23 | Revises: fd5dc71471cc
24 | Create Date: 2020-01-09 09:23:53.053811
25 | """
26 |
27 | from alembic.op import execute
28 | from sqlalchemy import and_, update
29 |
30 | import pyfaf.storage as st
31 |
32 |
33 | # revision identifiers, used by Alembic.
34 | revision = '9596a0f03838'
35 | down_revision = 'fd5dc71471cc'
36 |
37 |
38 | def upgrade() -> None:
39 | # Set the unique count to one for all report summaries which have no
40 | # unique reports but have _some_ reports.
41 | execute(update(st.ReportHistoryDaily)
42 | .where(and_(st.ReportHistoryDaily.unique == 0,
43 | st.ReportHistoryDaily.count > 0))
44 | .values(unique=1))
45 | execute(update(st.ReportHistoryMonthly)
46 | .where(and_(st.ReportHistoryMonthly.unique == 0,
47 | st.ReportHistoryMonthly.count > 0))
48 | .values(unique=1))
49 | execute(update(st.ReportHistoryWeekly)
50 | .where(and_(st.ReportHistoryWeekly.unique == 0,
51 | st.ReportHistoryWeekly.count > 0))
52 | .values(unique=1))
53 |
54 |
55 | def downgrade() -> None:
56 | # It does not make sense to reverse this migration.
57 | pass
58 |
--------------------------------------------------------------------------------
/src/pyfaf/bugtrackers/rhelbz.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013 ABRT Team
2 | # Copyright (C) 2013 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | from typing import Any, Dict, Generator, Optional
20 |
21 | from pyfaf.bugtrackers import bugzilla
22 |
23 | __all__ = ["RhelBugzilla"]
24 |
25 |
26 | class RhelBugzilla(bugzilla.Bugzilla):
27 | name = "rhel-bugzilla"
28 |
29 | def list_bugs(self, *args, **kwargs) -> Generator[int, None, None]:
30 |
31 | abrt_specific = dict(
32 | status_whiteboard="abrt_hash",
33 | status_whiteboard_type="allwordssubstr",
34 | product=["Red Hat Enterprise Linux 6",
35 | "Red Hat Enterprise Linux 7",
36 | "Red Hat Enterprise Linux 8"],
37 | )
38 |
39 | if "custom_fields" in kwargs:
40 | kwargs["custom_fields"].update(abrt_specific)
41 | else:
42 | kwargs["custom_fields"] = abrt_specific
43 |
44 | return super().list_bugs(*args, **kwargs)
45 |
46 | def preprocess_bug(self, bug) -> Optional[Dict[str, Any]]:
47 | bug_dict = super().preprocess_bug(bug)
48 |
49 | # handle "Red Hat Enterprise Linux \d" product naming
50 | # by stripping the number which is redundant for our purposes
51 | # as we also have bug_dict["version"] from bugzilla
52 |
53 | if "Red Hat Enterprise Linux" in bug_dict["product"]:
54 | bug_dict["product"] = " ".join(bug_dict["product"].split()[:-1])
55 |
56 | return bug_dict
57 |
--------------------------------------------------------------------------------
/src/webfaf/static/js/color.js:
--------------------------------------------------------------------------------
1 | function getColors(neededColors){
2 | if (typeof neededColors === 'undefined'){
3 | neededColors = 1;
4 | }
5 |
6 | var colorPool = ["#edc240", "#afd8f8", "#cb4b4b", "#4da74d", "#9440ed"];
7 | var c, colors = [],
8 | colorPoolSize = colorPool.length, variation = 0;
9 |
10 | for (i = 0; i < neededColors; i++) {
11 |
12 | c = $.color.parse(colorPool[i % colorPoolSize] || "#666");
13 |
14 | // Each time we exhaust the colors in the pool we adjust
15 | // a scaling factor used to produce more variations on
16 | // those colors. The factor alternates negative/positive
17 | // to produce lighter/darker colors.
18 |
19 | // Reset the variation after every few cycles, or else
20 | // it will end up producing only white or black colors.
21 |
22 | if (i % colorPoolSize == 0 && i) {
23 | if (variation >= 0) {
24 | if (variation < 0.5) {
25 | variation = -variation - 0.2;
26 | } else variation = 0;
27 | } else variation = -variation;
28 | }
29 |
30 | colors[i] = c.scale('rgb', 1 + variation);
31 | }
32 | return colors;
33 | }
34 |
35 | function LightenDarkenColor(col, amt) {
36 |
37 | var usePound = false;
38 |
39 | if (col[0] == "#") {
40 | col = col.slice(1);
41 | usePound = true;
42 | }
43 |
44 | var num = parseInt(col,16);
45 |
46 | var r = (num >> 16) + amt;
47 |
48 | if (r > 255) r = 255;
49 | else if (r < 0) r = 0;
50 |
51 | var b = ((num >> 8) & 0x00FF) + amt;
52 |
53 | if (b > 255) b = 255;
54 | else if (b < 0) b = 0;
55 |
56 | var g = (num & 0x0000FF) + amt;
57 |
58 | if (g > 255) g = 255;
59 | else if (g < 0) g = 0;
60 |
61 | return (usePound?"#":"") + String("000000" + (g | (b << 8) | (r << 16)).toString(16)).slice(-6);
62 |
63 | }
64 |
65 | function componentToHex(c) {
66 | var hex = c.toString(16);
67 | return hex.length == 1 ? "0" + hex : hex;
68 | }
69 |
70 | function rgbToHex(r, g, b) {
71 | return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
72 | }
73 |
--------------------------------------------------------------------------------
/src/pyfaf/actions/shell.py:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2013 ABRT Team
2 | # Copyright (C) 2013 Red Hat, Inc.
3 | #
4 | # This file is part of faf.
5 | #
6 | # faf is free software: you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation, either version 3 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # faf is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with faf. If not, see .
18 |
19 | # Unused variable
20 | # pylint: disable-msg=W0612
21 |
22 | # Unused import
23 | # pylint: disable-msg=W0611
24 | # pylint: disable-msg=W0614
25 |
26 | # Wildcard import
27 | # pylint: disable-msg=W0401
28 |
29 | from typing import Optional
30 |
31 | from collections.abc import Iterable
32 | from sqlalchemy.sql.expression import func
33 |
34 | import pyfaf
35 | from pyfaf.storage import * # pylint: disable=redefined-builtin
36 | from pyfaf.actions import Action
37 |
38 |
39 | class Shell(Action):
40 | name = "shell"
41 | cmdline_only = True
42 |
43 |
44 | def run(self, cmdline, db) -> Optional[int]:
45 | session = db.session
46 |
47 | def first(obj):
48 | return session.query(obj).first()
49 |
50 | # Redefining built-in 'any'
51 | # pylint: disable-msg=W0622
52 | def any(obj):
53 | if isinstance(obj, Iterable):
54 | return __builtins__["any"](obj)
55 |
56 | return session.query(obj).order_by(func.random()).first()
57 |
58 | try:
59 | import IPython
60 | except ImportError:
61 | print("IPython required")
62 | return 1
63 |
64 | # Module 'IPython' has no 'Shell' member
65 | # pylint: disable-msg=E1101
66 | if hasattr(IPython, "embed"):
67 | IPython.embed()
68 | else:
69 | IPython.Shell.IPShellEmbed()()
70 |
--------------------------------------------------------------------------------