Merge lp:~mbruzek/charms/trusty/fail2ban/trunk into lp:~lazypower/charms/trusty/fail2ban/trunk
- Trusty Tahr (14.04)
- trunk
- Merge into trunk
Proposed by
Matt Bruzek
Status: | Needs review |
---|---|
Proposed branch: | lp:~mbruzek/charms/trusty/fail2ban/trunk |
Merge into: | lp:~lazypower/charms/trusty/fail2ban/trunk |
Diff against target: |
584 lines (+121/-71) 12 files modified
lib/charmhelpers/core/fstab.py (+10/-8) lib/charmhelpers/core/hookenv.py (+9/-7) lib/charmhelpers/core/host.py (+12/-11) lib/charmhelpers/core/services/helpers.py (+9/-5) lib/charmhelpers/core/templating.py (+2/-1) lib/charmhelpers/fetch/__init__.py (+20/-16) lib/charmhelpers/fetch/archiveurl.py (+44/-16) lib/charmhelpers/fetch/bzrurl.py (+5/-1) lib/charmhelpers/fetch/giturl.py (+6/-2) metadata.yaml (+2/-2) templates/jail.local (+1/-1) tests/00-setup (+1/-1) |
To merge this branch: | bzr merge lp:~mbruzek/charms/trusty/fail2ban/trunk |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Charles Butler | Pending | ||
Review via email:
|
Commit message
Description of the change
Found some things that needed to be updated in trusty.
jail.local template
metadata.yaml
00-setup
sync charm-tools
To post a comment you must log in.
Unmerged revisions
- 5. By Matt Bruzek
-
Added maxretries to the ssh section in template, updated the metadata with the security tag, synchronized charm helpers.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/charmhelpers/core/fstab.py' |
2 | --- lib/charmhelpers/core/fstab.py 2014-10-22 04:18:26 +0000 |
3 | +++ lib/charmhelpers/core/fstab.py 2014-11-24 15:36:56 +0000 |
4 | @@ -3,10 +3,11 @@ |
5 | |
6 | __author__ = 'Jorge Niedbalski R. <jorge.niedbalski@canonical.com>' |
7 | |
8 | +import io |
9 | import os |
10 | |
11 | |
12 | -class Fstab(file): |
13 | +class Fstab(io.FileIO): |
14 | """This class extends file in order to implement a file reader/writer |
15 | for file `/etc/fstab` |
16 | """ |
17 | @@ -24,8 +25,8 @@ |
18 | options = "defaults" |
19 | |
20 | self.options = options |
21 | - self.d = d |
22 | - self.p = p |
23 | + self.d = int(d) |
24 | + self.p = int(p) |
25 | |
26 | def __eq__(self, o): |
27 | return str(self) == str(o) |
28 | @@ -45,7 +46,7 @@ |
29 | self._path = path |
30 | else: |
31 | self._path = self.DEFAULT_PATH |
32 | - file.__init__(self, self._path, 'r+') |
33 | + super(Fstab, self).__init__(self._path, 'rb+') |
34 | |
35 | def _hydrate_entry(self, line): |
36 | # NOTE: use split with no arguments to split on any |
37 | @@ -58,8 +59,9 @@ |
38 | def entries(self): |
39 | self.seek(0) |
40 | for line in self.readlines(): |
41 | + line = line.decode('us-ascii') |
42 | try: |
43 | - if not line.startswith("#"): |
44 | + if line.strip() and not line.startswith("#"): |
45 | yield self._hydrate_entry(line) |
46 | except ValueError: |
47 | pass |
48 | @@ -75,14 +77,14 @@ |
49 | if self.get_entry_by_attr('device', entry.device): |
50 | return False |
51 | |
52 | - self.write(str(entry) + '\n') |
53 | + self.write((str(entry) + '\n').encode('us-ascii')) |
54 | self.truncate() |
55 | return entry |
56 | |
57 | def remove_entry(self, entry): |
58 | self.seek(0) |
59 | |
60 | - lines = self.readlines() |
61 | + lines = [l.decode('us-ascii') for l in self.readlines()] |
62 | |
63 | found = False |
64 | for index, line in enumerate(lines): |
65 | @@ -97,7 +99,7 @@ |
66 | lines.remove(line) |
67 | |
68 | self.seek(0) |
69 | - self.write(''.join(lines)) |
70 | + self.write(''.join(lines).encode('us-ascii')) |
71 | self.truncate() |
72 | return True |
73 | |
74 | |
75 | === modified file 'lib/charmhelpers/core/hookenv.py' |
76 | --- lib/charmhelpers/core/hookenv.py 2014-10-22 04:18:26 +0000 |
77 | +++ lib/charmhelpers/core/hookenv.py 2014-11-24 15:36:56 +0000 |
78 | @@ -9,9 +9,11 @@ |
79 | import yaml |
80 | import subprocess |
81 | import sys |
82 | -import UserDict |
83 | from subprocess import CalledProcessError |
84 | |
85 | +import six |
86 | +from six.moves import UserDict |
87 | + |
88 | CRITICAL = "CRITICAL" |
89 | ERROR = "ERROR" |
90 | WARNING = "WARNING" |
91 | @@ -67,12 +69,12 @@ |
92 | subprocess.call(command) |
93 | |
94 | |
95 | -class Serializable(UserDict.IterableUserDict): |
96 | +class Serializable(UserDict): |
97 | """Wrapper, an object that can be serialized to yaml or json""" |
98 | |
99 | def __init__(self, obj): |
100 | # wrap the object |
101 | - UserDict.IterableUserDict.__init__(self) |
102 | + UserDict.__init__(self) |
103 | self.data = obj |
104 | |
105 | def __getattr__(self, attr): |
106 | @@ -218,7 +220,7 @@ |
107 | prev_keys = [] |
108 | if self._prev_dict is not None: |
109 | prev_keys = self._prev_dict.keys() |
110 | - return list(set(prev_keys + dict.keys(self))) |
111 | + return list(set(prev_keys + list(dict.keys(self)))) |
112 | |
113 | def load_previous(self, path=None): |
114 | """Load previous copy of config from disk. |
115 | @@ -269,7 +271,7 @@ |
116 | |
117 | """ |
118 | if self._prev_dict: |
119 | - for k, v in self._prev_dict.iteritems(): |
120 | + for k, v in six.iteritems(self._prev_dict): |
121 | if k not in self: |
122 | self[k] = v |
123 | with open(self.path, 'w') as f: |
124 | @@ -306,7 +308,7 @@ |
125 | return json.loads(subprocess.check_output(_args)) |
126 | except ValueError: |
127 | return None |
128 | - except CalledProcessError, e: |
129 | + except CalledProcessError as e: |
130 | if e.returncode == 2: |
131 | return None |
132 | raise |
133 | @@ -318,7 +320,7 @@ |
134 | relation_cmd_line = ['relation-set'] |
135 | if relation_id is not None: |
136 | relation_cmd_line.extend(('-r', relation_id)) |
137 | - for k, v in (relation_settings.items() + kwargs.items()): |
138 | + for k, v in (list(relation_settings.items()) + list(kwargs.items())): |
139 | if v is None: |
140 | relation_cmd_line.append('{}='.format(k)) |
141 | else: |
142 | |
143 | === modified file 'lib/charmhelpers/core/host.py' |
144 | --- lib/charmhelpers/core/host.py 2014-10-22 04:18:26 +0000 |
145 | +++ lib/charmhelpers/core/host.py 2014-11-24 15:36:56 +0000 |
146 | @@ -14,11 +14,12 @@ |
147 | import subprocess |
148 | import hashlib |
149 | from contextlib import contextmanager |
150 | - |
151 | from collections import OrderedDict |
152 | |
153 | -from hookenv import log |
154 | -from fstab import Fstab |
155 | +import six |
156 | + |
157 | +from .hookenv import log |
158 | +from .fstab import Fstab |
159 | |
160 | |
161 | def service_start(service_name): |
162 | @@ -130,7 +131,7 @@ |
163 | subprocess.check_call(cmd) |
164 | |
165 | |
166 | -def mkdir(path, owner='root', group='root', perms=0555, force=False): |
167 | +def mkdir(path, owner='root', group='root', perms=0o555, force=False): |
168 | """Create a directory""" |
169 | log("Making dir {} {}:{} {:o}".format(path, owner, group, |
170 | perms)) |
171 | @@ -146,7 +147,7 @@ |
172 | os.chown(realpath, uid, gid) |
173 | |
174 | |
175 | -def write_file(path, content, owner='root', group='root', perms=0444): |
176 | +def write_file(path, content, owner='root', group='root', perms=0o444): |
177 | """Create or overwrite a file with the contents of a string""" |
178 | log("Writing file {} {}:{} {:o}".format(path, owner, group, perms)) |
179 | uid = pwd.getpwnam(owner).pw_uid |
180 | @@ -177,7 +178,7 @@ |
181 | cmd_args.extend([device, mountpoint]) |
182 | try: |
183 | subprocess.check_output(cmd_args) |
184 | - except subprocess.CalledProcessError, e: |
185 | + except subprocess.CalledProcessError as e: |
186 | log('Error mounting {} at {}\n{}'.format(device, mountpoint, e.output)) |
187 | return False |
188 | |
189 | @@ -191,7 +192,7 @@ |
190 | cmd_args = ['umount', mountpoint] |
191 | try: |
192 | subprocess.check_output(cmd_args) |
193 | - except subprocess.CalledProcessError, e: |
194 | + except subprocess.CalledProcessError as e: |
195 | log('Error unmounting {}\n{}'.format(mountpoint, e.output)) |
196 | return False |
197 | |
198 | @@ -218,8 +219,8 @@ |
199 | """ |
200 | if os.path.exists(path): |
201 | h = getattr(hashlib, hash_type)() |
202 | - with open(path, 'r') as source: |
203 | - h.update(source.read()) # IGNORE:E1101 - it does have update |
204 | + with open(path, 'rb') as source: |
205 | + h.update(source.read()) |
206 | return h.hexdigest() |
207 | else: |
208 | return None |
209 | @@ -297,7 +298,7 @@ |
210 | if length is None: |
211 | length = random.choice(range(35, 45)) |
212 | alphanumeric_chars = [ |
213 | - l for l in (string.letters + string.digits) |
214 | + l for l in (string.ascii_letters + string.digits) |
215 | if l not in 'l0QD1vAEIOUaeiou'] |
216 | random_chars = [ |
217 | random.choice(alphanumeric_chars) for _ in range(length)] |
218 | @@ -306,7 +307,7 @@ |
219 | |
220 | def list_nics(nic_type): |
221 | '''Return a list of nics of given type(s)''' |
222 | - if isinstance(nic_type, basestring): |
223 | + if isinstance(nic_type, six.string_types): |
224 | int_types = [nic_type] |
225 | else: |
226 | int_types = nic_type |
227 | |
228 | === modified file 'lib/charmhelpers/core/services/helpers.py' |
229 | --- lib/charmhelpers/core/services/helpers.py 2014-10-22 04:18:26 +0000 |
230 | +++ lib/charmhelpers/core/services/helpers.py 2014-11-24 15:36:56 +0000 |
231 | @@ -196,7 +196,7 @@ |
232 | if not os.path.isabs(file_name): |
233 | file_name = os.path.join(hookenv.charm_dir(), file_name) |
234 | with open(file_name, 'w') as file_stream: |
235 | - os.fchmod(file_stream.fileno(), 0600) |
236 | + os.fchmod(file_stream.fileno(), 0o600) |
237 | yaml.dump(config_data, file_stream) |
238 | |
239 | def read_context(self, file_name): |
240 | @@ -211,15 +211,19 @@ |
241 | |
242 | class TemplateCallback(ManagerCallback): |
243 | """ |
244 | - Callback class that will render a Jinja2 template, for use as a ready action. |
245 | - |
246 | - :param str source: The template source file, relative to `$CHARM_DIR/templates` |
247 | + Callback class that will render a Jinja2 template, for use as a ready |
248 | + action. |
249 | + |
250 | + :param str source: The template source file, relative to |
251 | + `$CHARM_DIR/templates` |
252 | + |
253 | :param str target: The target to write the rendered template to |
254 | :param str owner: The owner of the rendered file |
255 | :param str group: The group of the rendered file |
256 | :param int perms: The permissions of the rendered file |
257 | """ |
258 | - def __init__(self, source, target, owner='root', group='root', perms=0444): |
259 | + def __init__(self, source, target, |
260 | + owner='root', group='root', perms=0o444): |
261 | self.source = source |
262 | self.target = target |
263 | self.owner = owner |
264 | |
265 | === modified file 'lib/charmhelpers/core/templating.py' |
266 | --- lib/charmhelpers/core/templating.py 2014-10-22 04:18:26 +0000 |
267 | +++ lib/charmhelpers/core/templating.py 2014-11-24 15:36:56 +0000 |
268 | @@ -4,7 +4,8 @@ |
269 | from charmhelpers.core import hookenv |
270 | |
271 | |
272 | -def render(source, target, context, owner='root', group='root', perms=0444, templates_dir=None): |
273 | +def render(source, target, context, owner='root', group='root', |
274 | + perms=0o444, templates_dir=None): |
275 | """ |
276 | Render a template. |
277 | |
278 | |
279 | === modified file 'lib/charmhelpers/fetch/__init__.py' |
280 | --- lib/charmhelpers/fetch/__init__.py 2014-11-20 21:55:44 +0000 |
281 | +++ lib/charmhelpers/fetch/__init__.py 2014-11-24 15:36:56 +0000 |
282 | @@ -5,10 +5,6 @@ |
283 | from charmhelpers.core.host import ( |
284 | lsb_release |
285 | ) |
286 | -from urlparse import ( |
287 | - urlparse, |
288 | - urlunparse, |
289 | -) |
290 | import subprocess |
291 | from charmhelpers.core.hookenv import ( |
292 | config, |
293 | @@ -16,6 +12,9 @@ |
294 | ) |
295 | import os |
296 | |
297 | +import six |
298 | +from six.moves.urllib.parse import urlparse, urlunparse |
299 | + |
300 | |
301 | CLOUD_ARCHIVE = """# Ubuntu Cloud Archive |
302 | deb http://ubuntu-cloud.archive.canonical.com/ubuntu {} main |
303 | @@ -69,11 +68,16 @@ |
304 | |
305 | # The order of this list is very important. Handlers should be listed in from |
306 | # least- to most-specific URL matching. |
307 | -FETCH_HANDLERS = ( |
308 | - 'charmhelpers.fetch.archiveurl.ArchiveUrlFetchHandler', |
309 | - 'charmhelpers.fetch.bzrurl.BzrUrlFetchHandler', |
310 | - 'charmhelpers.fetch.giturl.GitUrlFetchHandler', |
311 | -) |
312 | +if six.PY2: |
313 | + FETCH_HANDLERS = ( |
314 | + 'charmhelpers.fetch.archiveurl.ArchiveUrlFetchHandler', |
315 | + 'charmhelpers.fetch.bzrurl.BzrUrlFetchHandler', |
316 | + 'charmhelpers.fetch.giturl.GitUrlFetchHandler', |
317 | + ) |
318 | +else: |
319 | + FETCH_HANDLERS = ( |
320 | + 'charmhelpers.fetch.archiveurl.ArchiveUrlFetchHandler', |
321 | + ) |
322 | |
323 | APT_NO_LOCK = 100 # The return code for "couldn't acquire lock" in APT. |
324 | APT_NO_LOCK_RETRY_DELAY = 10 # Wait 10 seconds between apt lock checks. |
325 | @@ -149,7 +153,7 @@ |
326 | cmd = ['apt-get', '--assume-yes'] |
327 | cmd.extend(options) |
328 | cmd.append('install') |
329 | - if isinstance(packages, basestring): |
330 | + if isinstance(packages, six.string_types): |
331 | cmd.append(packages) |
332 | else: |
333 | cmd.extend(packages) |
334 | @@ -182,7 +186,7 @@ |
335 | def apt_purge(packages, fatal=False): |
336 | """Purge one or more packages""" |
337 | cmd = ['apt-get', '--assume-yes', 'purge'] |
338 | - if isinstance(packages, basestring): |
339 | + if isinstance(packages, six.string_types): |
340 | cmd.append(packages) |
341 | else: |
342 | cmd.extend(packages) |
343 | @@ -193,7 +197,7 @@ |
344 | def apt_hold(packages, fatal=False): |
345 | """Hold one or more packages""" |
346 | cmd = ['apt-mark', 'hold'] |
347 | - if isinstance(packages, basestring): |
348 | + if isinstance(packages, six.string_types): |
349 | cmd.append(packages) |
350 | else: |
351 | cmd.extend(packages) |
352 | @@ -260,7 +264,7 @@ |
353 | |
354 | if key: |
355 | if '-----BEGIN PGP PUBLIC KEY BLOCK-----' in key: |
356 | - with NamedTemporaryFile() as key_file: |
357 | + with NamedTemporaryFile('w+') as key_file: |
358 | key_file.write(key) |
359 | key_file.flush() |
360 | key_file.seek(0) |
361 | @@ -297,14 +301,14 @@ |
362 | sources = safe_load((config(sources_var) or '').strip()) or [] |
363 | keys = safe_load((config(keys_var) or '').strip()) or None |
364 | |
365 | - if isinstance(sources, basestring): |
366 | + if isinstance(sources, six.string_types): |
367 | sources = [sources] |
368 | |
369 | if keys is None: |
370 | for source in sources: |
371 | add_source(source, None) |
372 | else: |
373 | - if isinstance(keys, basestring): |
374 | + if isinstance(keys, six.string_types): |
375 | keys = [keys] |
376 | |
377 | if len(sources) != len(keys): |
378 | @@ -401,7 +405,7 @@ |
379 | while result is None or result == APT_NO_LOCK: |
380 | try: |
381 | result = subprocess.check_call(cmd, env=env) |
382 | - except subprocess.CalledProcessError, e: |
383 | + except subprocess.CalledProcessError as e: |
384 | retry_count = retry_count + 1 |
385 | if retry_count > APT_NO_LOCK_RETRY_COUNT: |
386 | raise |
387 | |
388 | === modified file 'lib/charmhelpers/fetch/archiveurl.py' |
389 | --- lib/charmhelpers/fetch/archiveurl.py 2014-10-22 04:18:26 +0000 |
390 | +++ lib/charmhelpers/fetch/archiveurl.py 2014-11-24 15:36:56 +0000 |
391 | @@ -1,8 +1,14 @@ |
392 | import os |
393 | -import urllib2 |
394 | -from urllib import urlretrieve |
395 | -import urlparse |
396 | import hashlib |
397 | +import re |
398 | + |
399 | +import six |
400 | +from six.moves.urllib.request import ( |
401 | + build_opener, install_opener, urlopen, urlretrieve, |
402 | + HTTPPasswordMgrWithDefaultRealm, HTTPBasicAuthHandler, |
403 | +) |
404 | +from six.moves.urllib.parse import urlparse, urlunparse, parse_qs |
405 | +from six.moves.urllib.error import URLError |
406 | |
407 | from charmhelpers.fetch import ( |
408 | BaseFetchHandler, |
409 | @@ -15,6 +21,24 @@ |
410 | from charmhelpers.core.host import mkdir, check_hash |
411 | |
412 | |
413 | +def splituser(host): |
414 | + '''urllib.splituser(), but six's support of this seems broken''' |
415 | + _userprog = re.compile('^(.*)@(.*)$') |
416 | + match = _userprog.match(host) |
417 | + if match: |
418 | + return match.group(1, 2) |
419 | + return None, host |
420 | + |
421 | + |
422 | +def splitpasswd(user): |
423 | + '''urllib.splitpasswd(), but six's support of this is missing''' |
424 | + _passwdprog = re.compile('^([^:]*):(.*)$', re.S) |
425 | + match = _passwdprog.match(user) |
426 | + if match: |
427 | + return match.group(1, 2) |
428 | + return user, None |
429 | + |
430 | + |
431 | class ArchiveUrlFetchHandler(BaseFetchHandler): |
432 | """ |
433 | Handler to download archive files from arbitrary URLs. |
434 | @@ -42,20 +66,20 @@ |
435 | """ |
436 | # propogate all exceptions |
437 | # URLError, OSError, etc |
438 | - proto, netloc, path, params, query, fragment = urlparse.urlparse(source) |
439 | + proto, netloc, path, params, query, fragment = urlparse(source) |
440 | if proto in ('http', 'https'): |
441 | - auth, barehost = urllib2.splituser(netloc) |
442 | + auth, barehost = splituser(netloc) |
443 | if auth is not None: |
444 | - source = urlparse.urlunparse((proto, barehost, path, params, query, fragment)) |
445 | - username, password = urllib2.splitpasswd(auth) |
446 | - passman = urllib2.HTTPPasswordMgrWithDefaultRealm() |
447 | + source = urlunparse((proto, barehost, path, params, query, fragment)) |
448 | + username, password = splitpasswd(auth) |
449 | + passman = HTTPPasswordMgrWithDefaultRealm() |
450 | # Realm is set to None in add_password to force the username and password |
451 | # to be used whatever the realm |
452 | passman.add_password(None, source, username, password) |
453 | - authhandler = urllib2.HTTPBasicAuthHandler(passman) |
454 | - opener = urllib2.build_opener(authhandler) |
455 | - urllib2.install_opener(opener) |
456 | - response = urllib2.urlopen(source) |
457 | + authhandler = HTTPBasicAuthHandler(passman) |
458 | + opener = build_opener(authhandler) |
459 | + install_opener(opener) |
460 | + response = urlopen(source) |
461 | try: |
462 | with open(dest, 'w') as dest_file: |
463 | dest_file.write(response.read()) |
464 | @@ -91,17 +115,21 @@ |
465 | url_parts = self.parse_url(source) |
466 | dest_dir = os.path.join(os.environ.get('CHARM_DIR'), 'fetched') |
467 | if not os.path.exists(dest_dir): |
468 | - mkdir(dest_dir, perms=0755) |
469 | + mkdir(dest_dir, perms=0o755) |
470 | dld_file = os.path.join(dest_dir, os.path.basename(url_parts.path)) |
471 | try: |
472 | self.download(source, dld_file) |
473 | - except urllib2.URLError as e: |
474 | + except URLError as e: |
475 | raise UnhandledSource(e.reason) |
476 | except OSError as e: |
477 | raise UnhandledSource(e.strerror) |
478 | - options = urlparse.parse_qs(url_parts.fragment) |
479 | + options = parse_qs(url_parts.fragment) |
480 | for key, value in options.items(): |
481 | - if key in hashlib.algorithms: |
482 | + if six.PY2: |
483 | + algorithms = hashlib.algorithms |
484 | + else: |
485 | + algorithms = hashlib.algorithms_available |
486 | + if key in algorithms: |
487 | check_hash(dld_file, value, key) |
488 | if checksum: |
489 | check_hash(dld_file, checksum, hash_type) |
490 | |
491 | === modified file 'lib/charmhelpers/fetch/bzrurl.py' |
492 | --- lib/charmhelpers/fetch/bzrurl.py 2014-10-22 04:18:26 +0000 |
493 | +++ lib/charmhelpers/fetch/bzrurl.py 2014-11-24 15:36:56 +0000 |
494 | @@ -5,6 +5,10 @@ |
495 | ) |
496 | from charmhelpers.core.host import mkdir |
497 | |
498 | +import six |
499 | +if six.PY3: |
500 | + raise ImportError('bzrlib does not support Python3') |
501 | + |
502 | try: |
503 | from bzrlib.branch import Branch |
504 | except ImportError: |
505 | @@ -42,7 +46,7 @@ |
506 | dest_dir = os.path.join(os.environ.get('CHARM_DIR'), "fetched", |
507 | branch_name) |
508 | if not os.path.exists(dest_dir): |
509 | - mkdir(dest_dir, perms=0755) |
510 | + mkdir(dest_dir, perms=0o755) |
511 | try: |
512 | self.branch(source, dest_dir) |
513 | except OSError as e: |
514 | |
515 | === modified file 'lib/charmhelpers/fetch/giturl.py' |
516 | --- lib/charmhelpers/fetch/giturl.py 2014-10-22 04:18:26 +0000 |
517 | +++ lib/charmhelpers/fetch/giturl.py 2014-11-24 15:36:56 +0000 |
518 | @@ -5,6 +5,10 @@ |
519 | ) |
520 | from charmhelpers.core.host import mkdir |
521 | |
522 | +import six |
523 | +if six.PY3: |
524 | + raise ImportError('GitPython does not support Python 3') |
525 | + |
526 | try: |
527 | from git import Repo |
528 | except ImportError: |
529 | @@ -17,7 +21,7 @@ |
530 | """Handler for git branches via generic and github URLs""" |
531 | def can_handle(self, source): |
532 | url_parts = self.parse_url(source) |
533 | - #TODO (mattyw) no support for ssh git@ yet |
534 | + # TODO (mattyw) no support for ssh git@ yet |
535 | if url_parts.scheme not in ('http', 'https', 'git'): |
536 | return False |
537 | else: |
538 | @@ -36,7 +40,7 @@ |
539 | dest_dir = os.path.join(os.environ.get('CHARM_DIR'), "fetched", |
540 | branch_name) |
541 | if not os.path.exists(dest_dir): |
542 | - mkdir(dest_dir, perms=0755) |
543 | + mkdir(dest_dir, perms=0o755) |
544 | try: |
545 | self.clone(source, dest_dir, branch) |
546 | except OSError as e: |
547 | |
548 | === modified file 'metadata.yaml' |
549 | --- metadata.yaml 2014-11-21 16:00:12 +0000 |
550 | +++ metadata.yaml 2014-11-24 15:36:56 +0000 |
551 | @@ -13,8 +13,8 @@ |
552 | file. All filters and actions are given in the config files, thus |
553 | fail2ban can be adopted to be used with a variety of files and |
554 | firewalls. |
555 | -categories: |
556 | - - misc |
557 | +tags: |
558 | + - security |
559 | subordinate: true |
560 | requires: |
561 | juju-info: |
562 | |
563 | === modified file 'templates/jail.local' |
564 | --- templates/jail.local 2014-10-22 04:18:26 +0000 |
565 | +++ templates/jail.local 2014-11-24 15:36:56 +0000 |
566 | @@ -95,7 +95,7 @@ |
567 | port = ssh |
568 | filter = sshd |
569 | logpath = /var/log/auth.log |
570 | -maxretry = 6 |
571 | +maxretry = {{maxretry}} |
572 | |
573 | [dropbear] |
574 | |
575 | |
576 | === modified file 'tests/00-setup' |
577 | --- tests/00-setup 2014-11-20 21:55:44 +0000 |
578 | +++ tests/00-setup 2014-11-24 15:36:56 +0000 |
579 | @@ -2,4 +2,4 @@ |
580 | |
581 | sudo add-apt-repository ppa:juju/stable -y |
582 | sudo apt-get update -qq |
583 | -sudo apt-get install amulet python3-requests -y |
584 | +sudo apt-get install amulet -y |