From a5a4cf1efc8490f4f622a9a91cb043a6d297894f Mon Sep 17 00:00:00 2001 From: Daniel Roschka Date: Tue, 26 Jul 2016 08:58:22 +0200 Subject: [PATCH 1/2] Adds support for Python 3. --- dogpush/dogpush.py | 79 +++++++++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 39 deletions(-) diff --git a/dogpush/dogpush.py b/dogpush/dogpush.py index 71fd701..8f16789 100755 --- a/dogpush/dogpush.py +++ b/dogpush/dogpush.py @@ -1,5 +1,7 @@ #!/usr/bin/env python +from __future__ import print_function + import argparse import calendar import copy @@ -17,7 +19,6 @@ import bcolors - PROGNAME = 'dogpush' @@ -96,25 +97,25 @@ def _canonical_monitor(original, default_team=None, **kwargs): m.pop(field, None) for field in IGNORE_OPTIONS: m.get('options', {}).pop(field, None) - option_defaults = (DATADOG_DEFAULT_OPTIONS.items() + - CONFIG['default_rule_options'].items()) + option_defaults = (list(DATADOG_DEFAULT_OPTIONS.items()) + + list(CONFIG['default_rule_options'].items())) for (field, value) in option_defaults: if m.get('options', {}).get(field) == value: del m['options'][field] - for (field, value) in CONFIG['default_rules'].items(): + for (field, value) in list(CONFIG['default_rules'].items()): if m.get(field) == value: del m[field] # If options is {'thresholds': {'critical': x}}, then it is redundant. if not m.get('options'): m.pop('options', None) - elif m['options'].keys() == ['thresholds'] and m['options']['thresholds'].keys() == ['critical']: + elif list(m['options'].keys()) == ['thresholds'] and list(m['options']['thresholds'].keys()) == ['critical']: del m['options'] m['name'] = m['name'].strip() original_team = original.get('team') team = original_team if original_team is not None else default_team severity = original.get('severity') or 'CRITICAL' if team: - if isinstance(team, basestring): + if isinstance(team, str): team = [team] m['message'] = m.get('message', '') for t in team: @@ -151,14 +152,14 @@ def _check_monitor_names_unique(monitors): for name in names: counts[name] = counts.get(name, 0) + 1 if counts[name] > 1: - print >> sys.stderr, "Duplicate name: %s" % name + print("Duplicate name: %s" % name, file=sys.stderr) return False return True def _check_monitor(monitor, location): name = monitor.get('name', '') - if isinstance(name, basestring): + if isinstance(name, str): name = name.strip() if not name: raise DogPushException('%s: found monitor without a name' % location) @@ -193,11 +194,11 @@ def get_local_monitors(): def _prepare_monitor(m): obj = copy.deepcopy(m['obj']) - for (key, value) in CONFIG['default_rule_options'].items(): + for (key, value) in list(CONFIG['default_rule_options'].items()): obj['options'] = obj.get('options', {}) if key not in obj['options']: obj['options'][key] = value - for (key, value) in CONFIG['default_rules'].items(): + for (key, value) in list(CONFIG['default_rules'].items()): obj[key] = obj.get(key, value) return obj @@ -212,11 +213,11 @@ def _is_changed(local, remote): def command_init(): - remote_monitors = [m['obj'] for m in get_datadog_monitors().values()] + remote_monitors = [m['obj'] for m in list(get_datadog_monitors().values())] monitors = {'alerts': remote_monitors} - print '# team: TEAMNAME' - print - print _pretty_yaml(monitors) + print('# team: TEAMNAME') + print() + print(_pretty_yaml(monitors)) def command_push(): @@ -225,7 +226,7 @@ def command_push(): only_local = set(local_monitors.keys()) - set(remote_monitors.keys()) if only_local: - print "Pushing %d new monitors." % len(only_local) + print("Pushing %d new monitors." % len(only_local)) for name in only_local: datadog.api.Monitor.create(**_prepare_monitor(local_monitors[name])) @@ -233,7 +234,7 @@ def command_push(): changed = [name for name in common_names if _is_changed(local_monitors[name], remote_monitors[name])] if changed: - print "Updating %d modified alerts" % len(changed) + print("Updating %d modified alerts" % len(changed)) for name in changed: datadog.api.Monitor.update( remote_monitors[name]['id'], @@ -267,7 +268,7 @@ def command_mute(): mute_tags = {} now = datetime.datetime.now(pytz.UTC) - for tag_key, tag_value in CONFIG.get('mute_tags', {}).items(): + for tag_key, tag_value in list(CONFIG.get('mute_tags', {}).items()): tz = pytz.timezone(tag_value['timezone']) if _should_mute(tag_value['expr'], tz, now): next_active_time = _mute_until(tag_value['expr'], tz, now) @@ -278,18 +279,18 @@ def command_mute(): else: mute_tags[tag_key] = None - for monitor in local_monitors.values(): + for monitor in list(local_monitors.values()): if monitor['mute_when']: remote = remote_monitors[monitor['name']] if remote['is_silenced']: - print "Alert '%s' is already muted. Skipping." % monitor['name'] + print("Alert '%s' is already muted. Skipping." % monitor['name']) continue mute_until = mute_tags[monitor['mute_when']] if mute_until: id = remote['id'] datadog.api.Monitor.mute(id, end=mute_until['timestamp']) - print "Muting alert '%s' until %s" % (monitor['name'], - mute_until['datetime']) + print("Muting alert '%s' until %s" % (monitor['name'], + mute_until['datetime'])) def command_diff(): @@ -305,21 +306,21 @@ def command_diff(): if only_local: sys.stdout.write(bcolors.WARNING) - print '---------------------------------------------------------' - print ' NEW MONITORS. These monitors are currently missing in' - print ' datadog and can be pushed using "%s push"' % PROGNAME - print '---------------------------------------------------------' + print('---------------------------------------------------------') + print(' NEW MONITORS. These monitors are currently missing in') + print(' datadog and can be pushed using "%s push"' % PROGNAME) + print('---------------------------------------------------------') sys.stdout.write(bcolors.ENDC) monitors = [local_monitors[name]['obj'] for name in only_local] - print _pretty_yaml(monitors) + print(_pretty_yaml(monitors)) if changed: sys.stdout.write(bcolors.WARNING) - print '---------------------------------------------------------' - print ' TO BE UPDATED. These monitors exist in datadog, but are' - print ' different than the local version. Use "%s push"' % PROGNAME - print ' to push them to datadog.' - print '---------------------------------------------------------' - print + print('---------------------------------------------------------') + print(' TO BE UPDATED. These monitors exist in datadog, but are') + print(' different than the local version. Use "%s push"' % PROGNAME) + print(' to push them to datadog.') + print('---------------------------------------------------------') + print() sys.stdout.write(bcolors.ENDC) for name in changed: remote_name = 'datadog:%s' % name @@ -338,16 +339,16 @@ def command_diff(): sys.stdout.write(line) if only_remote: sys.stdout.write(bcolors.WARNING) - print '------------------------------------------------------------' - print ' UNTRACKED MONITORS. These monitors are only in datadog ' - print ' and needed to be MANUALLY added to a local file or removed ' - print ' from datadog. ' - print '------------------------------------------------------------' + print('------------------------------------------------------------') + print(' UNTRACKED MONITORS. These monitors are only in datadog ') + print(' and needed to be MANUALLY added to a local file or removed ') + print(' from datadog. ') + print('------------------------------------------------------------') sys.stdout.write(bcolors.ENDC) monitors = [remote_monitors[name]['obj'] for name in only_remote] - print _pretty_yaml(monitors) + print(_pretty_yaml(monitors)) sys.stdout.write(bcolors.FAIL) - print "*** FAILED *** Untracked monitors found." + print("*** FAILED *** Untracked monitors found.") sys.stdout.write(bcolors.ENDC) sys.exit(1) From 284501ef76933a30766ed34fa3ef2a9c3fe54b14 Mon Sep 17 00:00:00 2001 From: Daniel Roschka Date: Wed, 27 Jul 2016 08:40:58 +0200 Subject: [PATCH 2/2] Fixes broken unicode handling with Python 2. --- dogpush/dogpush.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/dogpush/dogpush.py b/dogpush/dogpush.py index 8f16789..8952b04 100755 --- a/dogpush/dogpush.py +++ b/dogpush/dogpush.py @@ -22,6 +22,13 @@ PROGNAME = 'dogpush' +# To check for unicode strings use basestring for Python 2 and str for Python 3. +try: + basestring +except NameError: + basestring = str + + class DogPushException(Exception): pass @@ -115,7 +122,7 @@ def _canonical_monitor(original, default_team=None, **kwargs): team = original_team if original_team is not None else default_team severity = original.get('severity') or 'CRITICAL' if team: - if isinstance(team, str): + if isinstance(team, basestring): team = [team] m['message'] = m.get('message', '') for t in team: @@ -159,7 +166,7 @@ def _check_monitor_names_unique(monitors): def _check_monitor(monitor, location): name = monitor.get('name', '') - if isinstance(name, str): + if isinstance(name, basestring): name = name.strip() if not name: raise DogPushException('%s: found monitor without a name' % location)