Merge ~jacekn/prometheus-charm:refresh into prometheus-charm:master

Proposed by Jacek Nykis
Status: Merged
Merged at revision: f1dd3fb1015af546b020f91d6cacd97808bad28c
Proposed branch: ~jacekn/prometheus-charm:refresh
Merge into: prometheus-charm:master
Diff against target: 177 lines (+87/-14)
3 files modified
config.yaml (+5/-0)
reactive/prometheus.py (+27/-14)
templates/refresh_rules.sh.j2 (+55/-0)
Reviewer Review Type Date Requested Status
Junien F Approve
Review via email: mp+318656@code.launchpad.net

Description of the change

Add script to refresh external rules

To post a comment you must log in.
Revision history for this message
Junien F (axino) wrote :

inline comments

review: Needs Fixing
Revision history for this message
Junien F (axino) wrote :

+1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/config.yaml b/config.yaml
2index 4f4a2bc..0d1e4d9 100644
3--- a/config.yaml
4+++ b/config.yaml
5@@ -109,6 +109,11 @@ options:
6 Plain text private SSH key used to for git authentication.
7 Also see "rules-repo" config option
8 default: ""
9+ rules-update-notify-email:
10+ type: string
11+ description: |
12+ Email address that will receive cronned rule update failure emails
13+ default: ""
14 external_url:
15 default: ""
16 type: string
17diff --git a/reactive/prometheus.py b/reactive/prometheus.py
18index 0fc50ba..9e6f2b2 100644
19--- a/reactive/prometheus.py
20+++ b/reactive/prometheus.py
21@@ -22,6 +22,8 @@ PROMETHEUS_YML_TMPL = 'prometheus.yml.j2'
22 PROMETHEUS_DEF_TMPL = 'etc_default_prometheus.j2'
23 PROMETHEUS_RULES_CRON = '/etc/cron.d/juju-prometheus-rules-refresh'
24 PROMETHEUS_SSH_KEYFILE = '/root/.ssh/prometheus_git_key'
25+REFRESH_RULES_SCRIPT = '/usr/local/bin/refresh_rules.sh'
26+REFRESH_RULES_SCRIPT_TMPL = 'refresh_rules.sh.j2'
27
28
29 def templates_changed(tmpl_list):
30@@ -75,28 +77,39 @@ def configure_rules():
31 set_state('prometheus.do-reconfig-yml')
32
33 if config.get('rules-repo', False):
34- cron_ssh_command = ''
35- cli_ssh_command = ''
36+ ssh_command = ''
37 if config.get('rules-update-ssh-key', False):
38 host.mkdir(os.path.dirname(PROMETHEUS_SSH_KEYFILE), perms=0o700)
39 with open(PROMETHEUS_SSH_KEYFILE, 'w') as f:
40 f.write(config['rules-update-ssh-key'])
41 os.chmod(PROMETHEUS_SSH_KEYFILE, 0o600)
42- cli_ssh_command = 'ssh -i {}'.format(PROMETHEUS_SSH_KEYFILE)
43- cron_ssh_command = 'GIT_SSH_COMMAND="{}"'.format(cli_ssh_command)
44+ ssh_command = 'ssh -i {}'.format(PROMETHEUS_SSH_KEYFILE)
45
46 rules_path = get_paths()['external_rules_path']
47 if os.path.exists(rules_path):
48- cmd = ['git', '-C', rules_path, 'pull']
49+ subprocess.check_call(['git', '-C', rules_path, 'pull'],
50+ env={'GIT_SSH_COMMAND': ssh_command})
51 else:
52 # New repo, store key during initial clone
53- cli_ssh_command += ' -o StrictHostKeyChecking=no'
54- cmd = ['git', 'clone', config['rules-repo'], rules_path]
55- subprocess.check_call(cmd, env={'GIT_SSH_COMMAND': cli_ssh_command})
56+ subprocess.check_call(['git', 'clone', config['rules-repo'], rules_path],
57+ env={'GIT_SSH_COMMAND': ssh_command + ' -o StrictHostKeyChecking=no'})
58+
59+ options = {
60+ 'prometheus_yml': get_paths()['prometheus_yml'],
61+ 'external_rules_path': get_paths()['external_rules_path'],
62+ 'promtool': get_paths()['promtool'],
63+ 'ssh_command': ssh_command,
64+ 'rules_update_notify_email': config.get('rules-update-notify-email', False),
65+ }
66+ render(source=REFRESH_RULES_SCRIPT_TMPL,
67+ target=REFRESH_RULES_SCRIPT,
68+ context=options,
69+ perms=0o755,
70+ )
71
72 schedule = config.get('rules-update-schedule', '*/10 * * * *')
73 with open(PROMETHEUS_RULES_CRON, 'w') as f:
74- f.write('{} root {} git -C {} pull\n'.format(schedule, cron_ssh_command, rules_path))
75+ f.write('{} root {} &>/dev/null\n'.format(schedule, REFRESH_RULES_SCRIPT))
76 set_state('prometheus.do-reconfig-yml')
77 remove_state('prometheus.do-reconfig-rules')
78
79@@ -168,6 +181,8 @@ def install_packages():
80 'revert install_method option to previous value')
81 return
82
83+ if not os.path.exists('/usr/sbin/sendmail'):
84+ fetch.apt_install('sendmail-bin') # Needed for cronjob email notifications
85 if source == 'snap':
86 snap.install(pkgname, channel=channel, force_dangerous=False)
87 if config.get('prometheus_registration_listen', False):
88@@ -401,7 +416,7 @@ def check_reconfig_prometheus():
89 install_opts = ('install_sources', 'install_keys', 'snap_channel',
90 'prometheus_registration_listen')
91 def_change_opts = ('daemon-args', 'external_url')
92- rules_change_opts = ('rules-repo', 'rules-update-schedule', 'rules-update-ssh-key')
93+ rules_change_opts = ('rules-repo', 'rules-update-schedule', 'rules-update-ssh-key', 'rules-update-notify-email')
94 yml_change_opts = set(config.keys()) - set(install_opts + def_change_opts + rules_change_opts)
95 if any(config.changed(opt) for opt in install_opts):
96 set_state('prometheus.do-install')
97@@ -413,10 +428,6 @@ def check_reconfig_prometheus():
98 set_state('prometheus.do-reconfig-yml')
99 if any((
100 data_changed('prometheus.target_jobs', target_jobs),
101- templates_changed([PROMETHEUS_YML_TMPL]),
102- )):
103- set_state('prometheus.do-reconfig-yml')
104- if any((
105 data_changed('prometheus.scrape_jobs', scrape_jobs),
106 templates_changed([PROMETHEUS_YML_TMPL]),
107 )):
108@@ -426,6 +437,8 @@ def check_reconfig_prometheus():
109 templates_changed([PROMETHEUS_DEF_TMPL]),
110 )):
111 set_state('prometheus.do-reconfig-def')
112+ if templates_changed([REFRESH_RULES_SCRIPT_TMPL]):
113+ set_state('prometheus.do-reconfig-rules')
114 # Cron can update rules on disk, update-status hook can trigger config update
115 if kv.get('prometheus.rule_files') != get_rule_files():
116 kv.set('prometheus.rule_files', get_rule_files())
117diff --git a/templates/refresh_rules.sh.j2 b/templates/refresh_rules.sh.j2
118new file mode 100644
119index 0000000..c880cc0
120--- /dev/null
121+++ b/templates/refresh_rules.sh.j2
122@@ -0,0 +1,55 @@
123+#!/bin/bash
124+
125+REPO_DIR={{ external_rules_path }}
126+PROMTOOL={{ promtool }}
127+PROM_YML={{ prometheus_yml }}
128+GIT_SSH_COMMAND={{ cron_ssh_command }}
129+if [ -n "${GIT_SSH_COMMAND}" ]; then
130+ export GIT_SSH_COMMAND=${GIT_SSH_COMMAND}
131+fi
132+
133+function notify_by_email {
134+{% if rules_update_notify_email %}
135+ /usr/sbin/sendmail -t << EOF
136+To: {{ rules_update_notify_email }}
137+From: {{ rules_update_notify_email }}
138+Subject: Prometheus rule update failed on ${HOSTNAME}
139+Automatic rules refresh on ${HOSTNAME} failed!
140+
141+Error: $1
142+
143+Please investigate
144+EOF
145+{% else %}
146+echo "No email set, skipping notification"
147+{% endif %}
148+}
149+
150+cd $REPO_DIR
151+echo "Running pre-update check"
152+${PROMTOOL} check-config ${PROM_YML}
153+if [ $? -eq 0 ]; then
154+ git tag -f rules_live && git fetch && git merge --quiet --ff-only FETCH_HEAD
155+ if [ $? -ne 0 ]; then
156+ echo "Problem merging new rules"
157+ notify_by_email "Problem merging new rules"
158+ exit 1
159+ fi
160+else
161+ echo "Pre-check failed, aborted refresh"
162+ notify_by_email "Pre-check failed, aborted refresh"
163+ exit 1
164+fi
165+
166+echo "Running post-update check"
167+${PROMTOOL} check-config ${PROM_YML}
168+if [ $? -eq 0 ]; then
169+ killall -HUP prometheus
170+ git tag -f rules_live
171+ echo "Update and reload complete"
172+else
173+ git reset --hard rules_live
174+ echo "New rules did not pass verification, reverted"
175+ notify_by_email "New rules did not pass verification, reverted"
176+ exit 1
177+fi

Subscribers

People subscribed via source and target branches