1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
|
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import sys
import os
import re
from debian import deb822
ALLOWED_FIELDS = ('Suggests',
'Recommends',
'Depends',
'Uploaders',
'Version',
'Homepage',
'Watch',
'Description',
'Build-Depends')
# find all plugins
__basedir__ = os.path.realpath(os.path.dirname(sys.argv[0]) + os.path.sep + '..')
__plugins__ = [p for p in os.listdir(__basedir__)
if (os.path.isdir(__basedir__ + os.path.sep + p) and p!='debian' and p!='.git' and p!='.pc' and p!='old_plugins')]
__plugins__.sort()
__uploaders_re__ = re.compile(r', *')
__shlibs_re__ = re.compile(r'shlibs:Depends=(.+)')
def __get_control_data__():
# returns (plug, parsed control field data)
# We look at the first paragraph only!
for plugin in __plugins__:
data=(plugin, [x for x in deb822.Packages.iter_paragraphs(open(__basedir__ + os.path.sep+ plugin + os.path.sep + 'control'))][0])
for key in data[1].keys():
if key not in ALLOWED_FIELDS:
raise Exception("Unknown control field in plugin %s: %s" %(data[0],key))
yield data
def generate_debian_readme_plugins():
# not needed for this package
return
plugins_depends={}
for plugin, _control in __get_control_data__():
plugins_depends[plugin]={}
# look trough keys we might want to merge
for key in ['Suggests', 'Recommends']:
if key in _control:
plugins_depends[plugin][key]=deb822.PkgRelation.parse_relations(_control[key])
# check for generated substvars files
substvarsfile = __basedir__ + os.path.sep + 'debian' + os.path.sep + plugin + os.path.sep + 'substvars'
if os.path.exists(substvarsfile):
with open(substvarsfile, 'r') as fd:
substvars = fd.read()
try:
rel = deb822.PkgRelation.parse_relations(__shlibs_re__.findall(substvars)[0])
if 'Recommends' in plugins_depends[plugin]:
plugins_depends[plugin]['Recommends'].extend(rel)
else:
plugins_depends[plugin]['Recommends']=rel
except IndexError:
pass
# generate content
result=[]
for plugin in __plugins__:
if len(plugins_depends[plugin]) > 0:
rtext = '%s:' %(plugin,)
if 'Recommends' in plugins_depends[plugin]:
rtext = '%s\n Required Packages: %s' %(
rtext,
deb822.PkgRelation.str(plugins_depends[plugin]['Recommends'])
)
if 'Suggests' in plugins_depends[plugin]:
rtext = '%s\n Optional Packages: %s' %(
rtext,
deb822.PkgRelation.str(plugins_depends[plugin]['Suggests'])
)
result.append(rtext)
readmefile=__basedir__ + os.path.sep + 'debian' + os.path.sep + 'README.Debian.plugins'
with open(readmefile + '.in', 'r') as fd:
readme=fd.read()
readme=readme.replace('#AUTO_UPDATE_README#', '\n\n'.join(result))
with open(readmefile, 'w') as fd:
fd.write(readme)
def update_control():
control_data = {
'Suggests' : [],
'Recommends' : [],
'Build-Depends' : [],
'Description' : [],
'Uploaders' : []
}
for plugin, _control in __get_control_data__():
# look trough keys we might want to merge
#if _control.has_key('Depends'):
# print "Don't use 'Depends' in %s/control - use 'Recommends' instead" %(plugin,)
# sys.exit(1)
for key in ['Build-Depends', 'Depends', 'Suggests', 'Recommends']:
if key in _control:
for rel in deb822.PkgRelation.parse_relations(_control[key]):
if not rel in control_data[key]:
control_data[key].append(rel)
# extract description
description = ' * %s' %(plugin,)
if 'Version' in _control:
description = '%s (%s)' %(description, _control['Version'])
try:
description = '%s: %s' %(description, _control['Description'].replace('\n','\n '))
except KeyError:
print('Description for plugin %s missing!' %(plugin,))
sys.exit(1)
try:
for uploader in __uploaders_re__.split(_control['Uploaders']):
if uploader not in control_data['Uploaders']:
control_data['Uploaders'].append(uploader)
except KeyError:
'Uploaders for plugin %s missing!' %(plugin,)
sys.exit(1)
# disables right now. do we want to have the homepage in the description?
# if _control.has_key('Homepage'):
# description = '%s\n Homepage: %s' %(description, _control['Homepage'])
control_data['Description'].append(description)
with open(__basedir__ + os.path.sep + 'debian' + os.path.sep + 'control.in', 'r') as f:
control_in = f.read()
for k, v in control_data.items():
if k == 'Description':
control_in = control_in.replace('#AUTO_UPDATE_Description#', '\n'.join(v))
elif k == 'Uploaders':
control_in = control_in.replace('#AUTO_UPDATE_Uploaders#', ', '.join(v))
else:
control_in = control_in.replace('#AUTO_UPDATE_%s#' %(k, ), deb822.PkgRelation.str(v))
with open(__basedir__ + os.path.sep + 'debian' + os.path.sep + 'control', 'w') as f:
f.write(control_in)
def update_copyright():
copyrights = []
for plugin, _control in __get_control_data__():
_p_copyright = '%s:\n\n' %(plugin,)
if 'Homepage' in _control:
_p_copyright = '%sThe plugin was downloaded from: \n%s\n\n' %(_p_copyright, _control['Homepage'])
try:
with open(__basedir__ + os.path.sep + plugin + os.path.sep + 'copyright', 'r') as f:
_p_copyright = '%s %s' %(_p_copyright, f.read().replace('\n','\n '))
except IOError:
print('copyright file for plugin %s missing!' %(plugin,))
sys.exit(1)
copyrights.append(_p_copyright)
with open(__basedir__ + os.path.sep + 'debian' + os.path.sep + 'copyright.in', 'r') as f:
copyright_in = f.read()
copyright_in = copyright_in.replace('#AUTO_UPDATE_Copyright#', '\n\n------------------------------------------------------------------------------\n\n'.join(copyrights))
with open(__basedir__ + os.path.sep + 'debian' + os.path.sep + 'copyright', 'w') as f:
f.write(copyright_in)
def watch():
import apt_pkg
apt_pkg.init_system()
import hashlib
import urllib.request, urllib.error, urllib.parse
url_opener = urllib.request.build_opener()
url_opener.addheaders = [('User-agent', 'Debian nagios-plugins-contrib 1.0')]
watch_re = re.compile(r'([^ ]+) (.+)')
whitespace_re = re.compile(r'\s')
for plugin, _control in __get_control_data__():
if 'Watch' not in _control:
print('WARNING: %s - missing watch information!' %(plugin,))
continue
try:
url, check = watch_re.findall(_control['Watch'])[0]
except IndexError:
print('WARNING: %s - failed to parse Watch line!' %(plugin,))
continue
try:
f=url_opener.open(url)
content = f.read()
f.close()
except IOError:
print('WARNING: %s - failed to retrieve %s !' %(plugin,url))
continue
check=check.strip()
if check.startswith('SHA1:'):
check=check.replace('SHA1:','')
new_sha=hashlib.sha1(content).hexdigest()
if check != new_sha:
print('UPDATE NECESSARY: %s - SHA1 checksum does not match! New checksum: %s' %(plugin,new_sha))
else:
print('OK: %s' %(plugin,))
else:
if 'Version' not in _control:
print('WARNING: %s - missing current version information!' %(plugin,))
continue
check_re=re.compile(check)
# check for simple matches
found_versions=check_re.findall(content)
# now also see if the regexp author added too many .* parts and the match is a bit buggy
# we replace all whitespaces with \n and try again.
for v in check_re.findall(whitespace_re.sub('\n',content)):
if not v in found_versions:
found_versions.append(v)
if not found_versions:
print("WARNING: %s - regex does not match!" %(plugin))
continue
new_version = found_versions[0]
for v in found_versions:
if (apt_pkg.version_compare(v, found_versions[0]) > 0):
new_version = v
if (apt_pkg.version_compare(new_version, _control['Version'].strip()) > 0):
print('UPDATE NECESSARY: %s - found new version %s' %(plugin, new_version))
elif (apt_pkg.version_compare(new_version, _control['Version'].strip()) < 0):
print('WARNING: %s - could not find the current version (found: %s, control says: %s)!' %(plugin, new_version, _control['Version']))
else:
print('OK: %s' %(plugin,))
if __name__ == '__main__':
from optparse import OptionParser
prog = os.path.basename(sys.argv[0])
usage = ('%s [--copyright] [--control] [--watch] [--generate-readme] [-h|--help]') %(prog,)
parser = OptionParser(usage=usage)
parser.add_option(
'--copyright',
dest='copyright',
action='store_true',
default=False,
help='Update debian/copyright'
)
parser.add_option(
'--control',
dest='control',
action='store_true',
default=False,
help='Update debian/control'
)
parser.add_option(
'--watch',
dest='watch',
action='store_true',
default=False,
help='Search for updates'
)
parser.add_option(
'--generate-readme',
dest='generate_readme',
action='store_true',
default=False,
help='Generate debian/README.Debian.plugins'
)
(options, args) = parser.parse_args()
if not (options.control or options.copyright or options.watch or options.generate_readme):
parser.print_help()
sys.exit(1)
if options.control:
update_control()
if options.copyright:
update_copyright()
if options.watch:
watch()
if options.generate_readme:
generate_debian_readme_plugins()
|