patchman 3.0.13__tar.gz → 3.0.14__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {patchman-3.0.13 → patchman-3.0.14}/INSTALL.md +2 -2
- {patchman-3.0.13 → patchman-3.0.14}/PKG-INFO +13 -3
- patchman-3.0.14/VERSION.txt +1 -0
- {patchman-3.0.13 → patchman-3.0.14}/hosts/serializers.py +2 -2
- {patchman-3.0.13 → patchman-3.0.14}/hosts/templates/hosts/host_detail.html +2 -4
- patchman-3.0.14/modules/utils.py +69 -0
- {patchman-3.0.13 → patchman-3.0.14}/patchman.egg-info/PKG-INFO +13 -3
- {patchman-3.0.13 → patchman-3.0.14}/patchman.egg-info/SOURCES.txt +1 -0
- {patchman-3.0.13 → patchman-3.0.14}/patchman.egg-info/requires.txt +1 -1
- {patchman-3.0.13 → patchman-3.0.14}/repos/models.py +15 -4
- {patchman-3.0.13 → patchman-3.0.14}/repos/templates/repos/repo_detail.html +1 -3
- {patchman-3.0.13 → patchman-3.0.14}/repos/utils.py +2 -24
- {patchman-3.0.13 → patchman-3.0.14}/requirements.txt +1 -1
- {patchman-3.0.13 → patchman-3.0.14}/setup.cfg +1 -0
- {patchman-3.0.13 → patchman-3.0.14}/util/__init__.py +27 -24
- {patchman-3.0.13 → patchman-3.0.14}/util/templates/objectlist.html +1 -1
- {patchman-3.0.13 → patchman-3.0.14}/util/templates/searchbar.html +1 -1
- {patchman-3.0.13 → patchman-3.0.14}/util/templatetags/common.py +4 -8
- patchman-3.0.13/VERSION.txt +0 -1
- {patchman-3.0.13 → patchman-3.0.14}/AUTHORS +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/COPYING +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/MANIFEST.in +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/README.md +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/arch/__init__.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/arch/admin.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/arch/apps.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/arch/migrations/0001_initial.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/arch/migrations/__init__.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/arch/models.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/arch/serializers.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/arch/views.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/domains/__init__.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/domains/admin.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/domains/apps.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/domains/migrations/0001_initial.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/domains/migrations/__init__.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/domains/models.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/domains/serializers.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/domains/views.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/etc/patchman/apache.conf.example +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/etc/patchman/local_settings.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/hosts/__init__.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/hosts/admin.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/hosts/apps.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/hosts/forms.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/hosts/managers.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/hosts/migrations/0001_initial.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/hosts/migrations/0002_initial.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/hosts/migrations/0003_host_modules.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/hosts/migrations/__init__.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/hosts/models.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/hosts/templates/hosts/host_delete.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/hosts/templates/hosts/host_edit.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/hosts/templates/hosts/host_list.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/hosts/templates/hosts/host_table.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/hosts/templatetags/__init__.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/hosts/templatetags/report_alert.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/hosts/urls.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/hosts/utils.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/hosts/views.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/modules/__init__.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/modules/admin.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/modules/apps.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/modules/managers.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/modules/migrations/0001_initial.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/modules/migrations/0002_auto_20240204_2214.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/modules/migrations/0003_alter_module_options.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/modules/migrations/__init__.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/modules/models.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/modules/serializers.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/modules/templates/modules/module_detail.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/modules/templates/modules/module_list.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/modules/templates/modules/module_table.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/modules/urls.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/modules/views.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/operatingsystems/__init__.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/operatingsystems/admin.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/operatingsystems/apps.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/operatingsystems/forms.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/operatingsystems/migrations/0001_initial.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/operatingsystems/migrations/0002_initial.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/operatingsystems/migrations/__init__.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/operatingsystems/models.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/operatingsystems/serializers.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/operatingsystems/templates/operatingsystems/operatingsystem_table.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/operatingsystems/templates/operatingsystems/operatingsystemgroup_table.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/operatingsystems/templates/operatingsystems/os_delete.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/operatingsystems/templates/operatingsystems/os_detail.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/operatingsystems/templates/operatingsystems/os_list.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/operatingsystems/templates/operatingsystems/osgroup_delete.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/operatingsystems/templates/operatingsystems/osgroup_detail.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/operatingsystems/templates/operatingsystems/osgroup_list.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/operatingsystems/urls.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/operatingsystems/views.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/packages/__init__.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/packages/admin.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/packages/apps.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/packages/managers.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/packages/migrations/0001_initial.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/packages/migrations/__init__.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/packages/models.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/packages/serializers.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/packages/templates/packages/package_detail.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/packages/templates/packages/package_list.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/packages/templates/packages/package_table.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/packages/urls.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/packages/utils.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/packages/views.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/patchman/__init__.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/patchman/celery.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/patchman/receivers.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/patchman/settings.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/patchman/signals.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/patchman/static/css/base.css +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/patchman/static/img/icon-alert.gif +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/patchman/static/img/icon-no.gif +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/patchman/static/img/icon-yes.gif +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/patchman/static/js/ajax-jquery.js +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/patchman/static/js/button-post.js +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/patchman/urls.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/patchman/wsgi.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/patchman.egg-info/dependency_links.txt +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/patchman.egg-info/top_level.txt +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/reports/__init__.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/reports/admin.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/reports/apps.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/reports/migrations/0001_initial.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/reports/migrations/0002_report_modules.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/reports/migrations/__init__.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/reports/models.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/reports/tasks.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/reports/templates/reports/report.txt +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/reports/templates/reports/report_delete.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/reports/templates/reports/report_detail.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/reports/templates/reports/report_list.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/reports/templates/reports/report_table.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/reports/urls.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/reports/utils.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/reports/views.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/repos/__init__.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/repos/admin.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/repos/apps.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/repos/forms.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/repos/managers.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/repos/migrations/0001_initial.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/repos/migrations/__init__.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/repos/serializers.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/repos/templates/repos/mirror_delete.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/repos/templates/repos/mirror_detail.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/repos/templates/repos/mirror_edit.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/repos/templates/repos/mirror_edit_repo.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/repos/templates/repos/mirror_list.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/repos/templates/repos/mirror_table.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/repos/templates/repos/mirror_with_repo_list.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/repos/templates/repos/repo_delete.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/repos/templates/repos/repo_edit.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/repos/templates/repos/repo_list.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/repos/templates/repos/repository_table.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/repos/templatetags/__init__.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/repos/templatetags/repo_buttons.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/repos/urls.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/repos/views.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/sbin/patchman +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/sbin/patchman-manage +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/sbin/patchman-set-secret-key +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/scripts/clear-django-logs.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/scripts/create_graph.sh +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/scripts/rpm-install.sh +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/scripts/rpm-post-install.sh +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/setup.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/util/apps.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/util/filterspecs.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/util/templates/404.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/util/templates/500.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/util/templates/base.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/util/templates/dashboard.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/util/templates/navbar.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/util/templates/registration/login.html +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/util/templatetags/__init__.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/util/urls.py +0 -0
- {patchman-3.0.13 → patchman-3.0.14}/util/views.py +0 -0
|
@@ -63,8 +63,8 @@ apt -y install gcc libxml2-dev libxslt1-dev virtualenv python3-dev zlib1g-dev #
|
|
|
63
63
|
dnf -y install gcc libxml2-devel libxslt-devel python3-virtualenv # (centos/rocky/alma)
|
|
64
64
|
mkdir /srv/patchman
|
|
65
65
|
cd /srv/patchman
|
|
66
|
-
|
|
67
|
-
. bin/activate
|
|
66
|
+
python3 -m venv .venv
|
|
67
|
+
. .venv/bin/activate
|
|
68
68
|
pip install --upgrade pip
|
|
69
69
|
pip install patchman gunicorn whitenoise==3.3.1
|
|
70
70
|
patchman-manage migrate
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: patchman
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.14
|
|
4
4
|
Summary: Django based patch status monitoring tool for linux systems
|
|
5
5
|
Home-page: http://patchman.openbytes.ie/
|
|
6
6
|
Author: Marcus Furlong
|
|
@@ -21,7 +21,7 @@ Requires-Dist: django-extensions==3.2.1
|
|
|
21
21
|
Requires-Dist: django-bootstrap3==23.1
|
|
22
22
|
Requires-Dist: progressbar==2.5
|
|
23
23
|
Requires-Dist: python-debian==0.1.49
|
|
24
|
-
Requires-Dist: lxml==
|
|
24
|
+
Requires-Dist: lxml==5.2.2
|
|
25
25
|
Requires-Dist: defusedxml==0.7.1
|
|
26
26
|
Requires-Dist: PyYAML==6.0.1
|
|
27
27
|
Requires-Dist: chardet==4.0.0
|
|
@@ -33,6 +33,16 @@ Requires-Dist: humanize==3.13.1
|
|
|
33
33
|
Requires-Dist: version-utils==0.3.0
|
|
34
34
|
Requires-Dist: python-magic==0.4.25
|
|
35
35
|
Requires-Dist: pymemcache==4.0.0
|
|
36
|
+
Dynamic: author
|
|
37
|
+
Dynamic: author-email
|
|
38
|
+
Dynamic: classifier
|
|
39
|
+
Dynamic: description
|
|
40
|
+
Dynamic: description-content-type
|
|
41
|
+
Dynamic: home-page
|
|
42
|
+
Dynamic: keywords
|
|
43
|
+
Dynamic: license
|
|
44
|
+
Dynamic: requires-dist
|
|
45
|
+
Dynamic: summary
|
|
36
46
|
|
|
37
47
|
# Patchman
|
|
38
48
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.0.14
|
|
@@ -31,10 +31,10 @@ class HostSerializer(serializers.HyperlinkedModelSerializer):
|
|
|
31
31
|
'updated_at', 'bugfix_update_count', 'security_update_count')
|
|
32
32
|
|
|
33
33
|
def get_bugfix_update_count(self, obj):
|
|
34
|
-
return
|
|
34
|
+
return obj.updates.filter(security=False).count()
|
|
35
35
|
|
|
36
36
|
def get_security_update_count(self, obj):
|
|
37
|
-
return
|
|
37
|
+
return obj.updates.filter(security=True).count()
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
class HostRepoSerializer(serializers.HyperlinkedModelSerializer):
|
|
@@ -138,9 +138,7 @@
|
|
|
138
138
|
|
|
139
139
|
<div class="tab-pane fade in" id="host_modules">
|
|
140
140
|
<div class="well well-sm">
|
|
141
|
-
|
|
142
|
-
{% gen_table host.modules.all %}
|
|
143
|
-
</div>
|
|
141
|
+
{% gen_table host.modules.all %}
|
|
144
142
|
</div>
|
|
145
143
|
</div>
|
|
146
144
|
|
|
@@ -148,7 +146,7 @@
|
|
|
148
146
|
<div class="well well-sm">
|
|
149
147
|
<button class="btn btn-primary btn-sm" data-toggle="collapse" data-target="#packages">Show/Hide Installed Packages</button>
|
|
150
148
|
<div id="packages" class="collapse">
|
|
151
|
-
<div class="well">
|
|
149
|
+
<div class="well well-sm">
|
|
152
150
|
{% for package in host.packages.select_related %}
|
|
153
151
|
<span class="label label-brick {% cycle 'bg-info' 'bg-success' %}">
|
|
154
152
|
<a href="{{ package.name.get_absolute_url }}"> {{ package }} </a>
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Copyright 2024 Marcus Furlong <furlongm@gmail.com>
|
|
2
|
+
#
|
|
3
|
+
# This file is part of Patchman.
|
|
4
|
+
#
|
|
5
|
+
# Patchman is free software: you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
|
7
|
+
# the Free Software Foundation, version 3 only.
|
|
8
|
+
#
|
|
9
|
+
# Patchman is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
# GNU General Public License for more details.
|
|
13
|
+
#
|
|
14
|
+
# You should have received a copy of the GNU General Public License
|
|
15
|
+
# along with Patchman. If not, see <http://www.gnu.org/licenses/>
|
|
16
|
+
|
|
17
|
+
from django.db import IntegrityError, DatabaseError, transaction
|
|
18
|
+
from patchman.signals import error_message
|
|
19
|
+
|
|
20
|
+
from modules.models import Module
|
|
21
|
+
from arch.models import PackageArchitecture
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def get_or_create_module(name, stream, version, context, arch, repo):
|
|
25
|
+
""" Get or create a module object
|
|
26
|
+
Returns the module and a boolean for created
|
|
27
|
+
"""
|
|
28
|
+
created = False
|
|
29
|
+
with transaction.atomic():
|
|
30
|
+
m_arch, c = PackageArchitecture.objects.get_or_create(name=arch)
|
|
31
|
+
try:
|
|
32
|
+
with transaction.atomic():
|
|
33
|
+
module, created = Module.objects.get_or_create(
|
|
34
|
+
name=name,
|
|
35
|
+
stream=stream,
|
|
36
|
+
version=version,
|
|
37
|
+
context=context,
|
|
38
|
+
arch=m_arch,
|
|
39
|
+
repo=repo,
|
|
40
|
+
)
|
|
41
|
+
except IntegrityError as e:
|
|
42
|
+
error_message.send(sender=None, text=e)
|
|
43
|
+
module = Module.objects.get(
|
|
44
|
+
name=name,
|
|
45
|
+
stream=stream,
|
|
46
|
+
version=version,
|
|
47
|
+
context=context,
|
|
48
|
+
arch=m_arch,
|
|
49
|
+
repo=repo,
|
|
50
|
+
)
|
|
51
|
+
except DatabaseError as e:
|
|
52
|
+
error_message.send(sender=None, text=e)
|
|
53
|
+
return module, created
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def get_matching_modules(name, stream, version, context, arch):
|
|
57
|
+
""" Return modules that match name, stream, version, context, and arch,
|
|
58
|
+
regardless of repo
|
|
59
|
+
"""
|
|
60
|
+
with transaction.atomic():
|
|
61
|
+
m_arch, c = PackageArchitecture.objects.get_or_create(name=arch)
|
|
62
|
+
modules = Module.objects.filter(
|
|
63
|
+
name=name,
|
|
64
|
+
stream=stream,
|
|
65
|
+
version=version,
|
|
66
|
+
context=context,
|
|
67
|
+
arch=m_arch,
|
|
68
|
+
)
|
|
69
|
+
return modules
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: patchman
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.14
|
|
4
4
|
Summary: Django based patch status monitoring tool for linux systems
|
|
5
5
|
Home-page: http://patchman.openbytes.ie/
|
|
6
6
|
Author: Marcus Furlong
|
|
@@ -21,7 +21,7 @@ Requires-Dist: django-extensions==3.2.1
|
|
|
21
21
|
Requires-Dist: django-bootstrap3==23.1
|
|
22
22
|
Requires-Dist: progressbar==2.5
|
|
23
23
|
Requires-Dist: python-debian==0.1.49
|
|
24
|
-
Requires-Dist: lxml==
|
|
24
|
+
Requires-Dist: lxml==5.2.2
|
|
25
25
|
Requires-Dist: defusedxml==0.7.1
|
|
26
26
|
Requires-Dist: PyYAML==6.0.1
|
|
27
27
|
Requires-Dist: chardet==4.0.0
|
|
@@ -33,6 +33,16 @@ Requires-Dist: humanize==3.13.1
|
|
|
33
33
|
Requires-Dist: version-utils==0.3.0
|
|
34
34
|
Requires-Dist: python-magic==0.4.25
|
|
35
35
|
Requires-Dist: pymemcache==4.0.0
|
|
36
|
+
Dynamic: author
|
|
37
|
+
Dynamic: author-email
|
|
38
|
+
Dynamic: classifier
|
|
39
|
+
Dynamic: description
|
|
40
|
+
Dynamic: description-content-type
|
|
41
|
+
Dynamic: home-page
|
|
42
|
+
Dynamic: keywords
|
|
43
|
+
Dynamic: license
|
|
44
|
+
Dynamic: requires-dist
|
|
45
|
+
Dynamic: summary
|
|
36
46
|
|
|
37
47
|
# Patchman
|
|
38
48
|
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
# You should have received a copy of the GNU General Public License
|
|
16
16
|
# along with Patchman. If not, see <http://www.gnu.org/licenses/>
|
|
17
17
|
|
|
18
|
+
from django.conf import settings
|
|
18
19
|
from django.db import models
|
|
19
20
|
from django.urls import reverse
|
|
20
21
|
|
|
@@ -154,15 +155,25 @@ class Mirror(models.Model):
|
|
|
154
155
|
|
|
155
156
|
def fail(self):
|
|
156
157
|
""" Records that the mirror has failed
|
|
157
|
-
Disables refresh on a mirror if it fails more than
|
|
158
|
+
Disables refresh on a mirror if it fails more than MAX_MIRROR_FAILURES times
|
|
159
|
+
Set MAX_MIRROR_FAILURES to -1 to disable marking mirrors as failures
|
|
160
|
+
Default is 28
|
|
158
161
|
"""
|
|
159
162
|
text = f'No usable mirror found at {self.url!s}'
|
|
160
163
|
error_message.send(sender=None, text=text)
|
|
164
|
+
default_max_mirror_failures = 28
|
|
165
|
+
if hasattr(settings, 'MAX_MIRROR_FAILURES') and \
|
|
166
|
+
isinstance(settings.MAX_MIRROR_FAILURES, int):
|
|
167
|
+
max_mirror_failures = settings.MAX_MIRROR_FAILURES
|
|
168
|
+
else:
|
|
169
|
+
max_mirror_failures = default_max_mirror_failures
|
|
161
170
|
self.fail_count = self.fail_count + 1
|
|
162
|
-
if
|
|
171
|
+
if max_mirror_failures == -1:
|
|
172
|
+
text = f'Mirror has failed {self.fail_count} times, but MAX_MIRROR_FAILURES=-1, not disabling refresh'
|
|
173
|
+
elif self.fail_count > max_mirror_failures:
|
|
163
174
|
self.refresh = False
|
|
164
|
-
text = 'Mirror has failed
|
|
165
|
-
|
|
175
|
+
text = f'Mirror has failed {self.fail_count} times (max={max_mirror_failures}), disabling refresh'
|
|
176
|
+
error_message.send(sender=None, text=text)
|
|
166
177
|
|
|
167
178
|
def update_packages(self, packages):
|
|
168
179
|
""" Update the packages associated with a mirror
|
|
@@ -311,10 +311,6 @@ def extract_module_metadata(data, url, repo):
|
|
|
311
311
|
raw_packages = modulemd.get('artifacts', {}).get('rpms', '')
|
|
312
312
|
# raw_profiles = list(modulemd.get('profiles', {}).keys())
|
|
313
313
|
|
|
314
|
-
package_arches = PackageArchitecture.objects.all()
|
|
315
|
-
with transaction.atomic():
|
|
316
|
-
m_arch, c = package_arches.get_or_create(name=arch)
|
|
317
|
-
|
|
318
314
|
packages = set()
|
|
319
315
|
p_type = Package.RPM
|
|
320
316
|
for pkg_str in raw_packages:
|
|
@@ -322,26 +318,8 @@ def extract_module_metadata(data, url, repo):
|
|
|
322
318
|
package = get_or_create_package(p_name, p_epoch, p_ver, p_rel, p_arch, p_type)
|
|
323
319
|
packages.add(package)
|
|
324
320
|
|
|
325
|
-
from modules.
|
|
326
|
-
|
|
327
|
-
try:
|
|
328
|
-
with transaction.atomic():
|
|
329
|
-
module, c = all_modules.get_or_create(name=m_name,
|
|
330
|
-
stream=m_stream,
|
|
331
|
-
version=m_version,
|
|
332
|
-
context=m_context,
|
|
333
|
-
arch=m_arch,
|
|
334
|
-
repo=repo)
|
|
335
|
-
except IntegrityError as e:
|
|
336
|
-
error_message.send(sender=None, text=e)
|
|
337
|
-
module = all_modules.get(name=m_name,
|
|
338
|
-
stream=m_stream,
|
|
339
|
-
version=m_version,
|
|
340
|
-
context=m_context,
|
|
341
|
-
arch=m_arch,
|
|
342
|
-
repo=repo)
|
|
343
|
-
except DatabaseError as e:
|
|
344
|
-
error_message.send(sender=None, text=e)
|
|
321
|
+
from modules.utils import get_or_create_module
|
|
322
|
+
module, created = get_or_create_module(m_name, m_stream, m_version, m_context, arch, repo)
|
|
345
323
|
|
|
346
324
|
package_ids = []
|
|
347
325
|
for package in packages:
|
|
@@ -25,7 +25,7 @@ from colorama import Fore, Style
|
|
|
25
25
|
from enum import Enum
|
|
26
26
|
from hashlib import md5, sha1, sha256, sha512
|
|
27
27
|
from progressbar import Bar, ETA, Percentage, ProgressBar
|
|
28
|
-
from patchman.signals import error_message
|
|
28
|
+
from patchman.signals import error_message, info_message
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
if ProgressBar.__dict__.get('maxval'):
|
|
@@ -52,12 +52,12 @@ def set_verbosity(value):
|
|
|
52
52
|
verbose = value
|
|
53
53
|
|
|
54
54
|
|
|
55
|
-
def create_pbar(ptext, plength, **kwargs):
|
|
55
|
+
def create_pbar(ptext, plength, ljust=35, **kwargs):
|
|
56
56
|
""" Create a global progress bar if global verbose is True
|
|
57
57
|
"""
|
|
58
58
|
global pbar, verbose
|
|
59
59
|
if verbose and plength > 0:
|
|
60
|
-
jtext = str(ptext).ljust(
|
|
60
|
+
jtext = str(ptext).ljust(ljust)
|
|
61
61
|
if pbar2:
|
|
62
62
|
pbar = ProgressBar(widgets=[Style.RESET_ALL + Fore.YELLOW + jtext,
|
|
63
63
|
Percentage(), Bar(), ETA()],
|
|
@@ -79,34 +79,37 @@ def update_pbar(index, **kwargs):
|
|
|
79
79
|
pmax = pbar.max_value
|
|
80
80
|
else:
|
|
81
81
|
pmax = pbar.maxval
|
|
82
|
-
if index
|
|
82
|
+
if index >= pmax:
|
|
83
83
|
pbar.finish()
|
|
84
84
|
print_nocr(Fore.RESET)
|
|
85
85
|
pbar = None
|
|
86
86
|
|
|
87
87
|
|
|
88
|
-
def download_url(res, text=''):
|
|
88
|
+
def download_url(res, text='', ljust=35):
|
|
89
89
|
""" Display a progress bar to download the request content if verbose is
|
|
90
90
|
True. Otherwise, just return the request content
|
|
91
91
|
"""
|
|
92
92
|
global verbose
|
|
93
|
-
if verbose
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
93
|
+
if verbose:
|
|
94
|
+
content_length = res.headers.get('content-length')
|
|
95
|
+
if content_length:
|
|
96
|
+
clen = int(content_length)
|
|
97
|
+
create_pbar(text, clen, ljust)
|
|
98
|
+
chunk_size = 16384
|
|
99
|
+
i = 0
|
|
100
|
+
data = b''
|
|
101
|
+
for chunk in res.iter_content(chunk_size=chunk_size,
|
|
102
|
+
decode_unicode=False):
|
|
103
|
+
i += len(chunk)
|
|
104
|
+
if i > clen:
|
|
105
|
+
update_pbar(clen)
|
|
106
|
+
else:
|
|
107
|
+
update_pbar(i)
|
|
108
|
+
data += chunk
|
|
109
|
+
return data
|
|
110
|
+
else:
|
|
111
|
+
info_message.send(sender=None, text=text)
|
|
112
|
+
return res.content
|
|
110
113
|
|
|
111
114
|
|
|
112
115
|
def print_nocr(text):
|
|
@@ -116,12 +119,12 @@ def print_nocr(text):
|
|
|
116
119
|
sys.stdout.softspace = False
|
|
117
120
|
|
|
118
121
|
|
|
119
|
-
def get_url(url):
|
|
122
|
+
def get_url(url, headers={}, params={}):
|
|
120
123
|
""" Perform a http GET on a URL. Return None on error.
|
|
121
124
|
"""
|
|
122
125
|
res = None
|
|
123
126
|
try:
|
|
124
|
-
res = requests.get(url, stream=True)
|
|
127
|
+
res = requests.get(url, headers=headers, params=params, stream=True)
|
|
125
128
|
except requests.exceptions.Timeout:
|
|
126
129
|
error_message.send(sender=None, text=f'Timeout - {url!s}')
|
|
127
130
|
except requests.exceptions.TooManyRedirects:
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<div>
|
|
3
3
|
<form method="get">
|
|
4
4
|
<div class="input-group">
|
|
5
|
-
<input type="text" class="form-control input-sm" placeholder="Search" name="search" value="{{ terms }}"
|
|
5
|
+
<input type="text" class="form-control input-sm" placeholder="Search" name="search" id="search" value="{{ terms }}">
|
|
6
6
|
<div class="input-group-btn">
|
|
7
7
|
<button class="btn btn-primary btn-sm" type="submit">{% bootstrap_icon "search" %}</button>
|
|
8
8
|
</div>
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
from humanize import naturaltime
|
|
20
20
|
from datetime import datetime, timedelta
|
|
21
|
+
from urllib.parse import urlencode
|
|
21
22
|
|
|
22
23
|
from django.conf import settings
|
|
23
24
|
from django.template import Library
|
|
@@ -26,11 +27,6 @@ from django.utils.html import format_html
|
|
|
26
27
|
from django.templatetags.static import static
|
|
27
28
|
from django.core.paginator import Paginator
|
|
28
29
|
|
|
29
|
-
try:
|
|
30
|
-
from urllib.parse import urlencode
|
|
31
|
-
except ImportError:
|
|
32
|
-
from urllib import urlencode
|
|
33
|
-
|
|
34
30
|
register = Library()
|
|
35
31
|
|
|
36
32
|
|
|
@@ -67,7 +63,7 @@ def no_yes_img(boolean, alt_yes='Not Required', alt_no='Required'):
|
|
|
67
63
|
|
|
68
64
|
@register.simple_tag
|
|
69
65
|
def gen_table(object_list, template_name=None):
|
|
70
|
-
if object_list
|
|
66
|
+
if not object_list:
|
|
71
67
|
return ''
|
|
72
68
|
if not template_name:
|
|
73
69
|
app_label = object_list.model._meta.app_label
|
|
@@ -97,9 +93,9 @@ def get_querystring(request):
|
|
|
97
93
|
|
|
98
94
|
|
|
99
95
|
@register.simple_tag
|
|
100
|
-
def searchform():
|
|
96
|
+
def searchform(terms):
|
|
101
97
|
template = get_template('searchbar.html')
|
|
102
|
-
html = template.render({'post_url': '.'})
|
|
98
|
+
html = template.render({'post_url': '.', 'terms': terms})
|
|
103
99
|
return html
|
|
104
100
|
|
|
105
101
|
|
patchman-3.0.13/VERSION.txt
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
3.0.13
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{patchman-3.0.13 → patchman-3.0.14}/operatingsystems/templates/operatingsystems/os_delete.html
RENAMED
|
File without changes
|
{patchman-3.0.13 → patchman-3.0.14}/operatingsystems/templates/operatingsystems/os_detail.html
RENAMED
|
File without changes
|
{patchman-3.0.13 → patchman-3.0.14}/operatingsystems/templates/operatingsystems/os_list.html
RENAMED
|
File without changes
|
{patchman-3.0.13 → patchman-3.0.14}/operatingsystems/templates/operatingsystems/osgroup_delete.html
RENAMED
|
File without changes
|
{patchman-3.0.13 → patchman-3.0.14}/operatingsystems/templates/operatingsystems/osgroup_detail.html
RENAMED
|
File without changes
|
{patchman-3.0.13 → patchman-3.0.14}/operatingsystems/templates/operatingsystems/osgroup_list.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|