Skip to content

Commit 30f8fb7

Browse files
authored
Merge pull request alphagov#231 from alphagov/which-puppet-is-where
Which version of puppet is running where
2 parents a8de299 + 08c294c commit 30f8fb7

File tree

4 files changed

+174
-0
lines changed

4 files changed

+174
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
*.pyc
22
.ssh/*
3+
*.sqlite

bin/puppet_versions.sh

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/bin/sh
2+
3+
set -e
4+
5+
PS3='Please enter your choice: '
6+
options=("integration" "staging" "production" "quit")
7+
select opt in "${options[@]}"
8+
do
9+
case $opt in
10+
"integration")
11+
environment="integration"
12+
break
13+
;;
14+
"staging")
15+
environment="staging"
16+
break
17+
;;
18+
"production")
19+
environment="production"
20+
break
21+
;;
22+
"quit")
23+
exit 0
24+
;;
25+
*) echo invalid option;;
26+
esac
27+
done
28+
29+
echo "Querying all servers, this will take a while..."
30+
fab $environment all -P -z 10 puppet.config_version | grep -E "\[(.*)\] out: (.+)" | tr -d '[]' | awk -F ' out: ' ' { print $1 "," $2; }' > out.csv
31+
32+
echo "Processing server results..."
33+
python bin/show_puppet_versions.py $environment out.csv
34+
35+
echo "Removing remporary file..."
36+
rm out.csv
37+
38+
echo "Done!"

bin/show_puppet_versions.py

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
import os
2+
import sys
3+
import csv
4+
import time
5+
import requests
6+
import requests_cache
7+
requests_cache.install_cache('github_cache')
8+
9+
10+
def group_data_per_server(data):
11+
"""
12+
Given the rows produced by the fab script, it creates a map of server names
13+
to puppet details.
14+
The input looks like this:
15+
16+
api-1.api,sha:0a64d38e6cf4ede6b43fb39fba048c263ad78498
17+
api-1.api,time:1481023751
18+
api-2.api,sha:0a64d38e6cf4ede6b43fb39fba048c263ad78498
19+
...
20+
21+
And results in this:
22+
23+
{
24+
'api-1.api': {
25+
'sha': '0a64d38e6cf4ede6b43fb39fba048c263ad78498',
26+
'time': '1481023751'
27+
},
28+
...
29+
}
30+
31+
"""
32+
server_mapping = {}
33+
for data_entry in data:
34+
server_name, metric = data_entry
35+
puppet_information = server_mapping.get(server_name) or {}
36+
metric_data = metric.split(':')
37+
if len(metric_data) == 2:
38+
metric_name, metric_value = metric_data
39+
puppet_information[metric_name] = metric_value
40+
server_mapping[server_name] = puppet_information
41+
42+
return server_mapping
43+
44+
45+
def enhance_with_release_number(server_mapping):
46+
"""
47+
Given the mapping generated by group_data_per_server, it calls the GitHub
48+
API in order to fetch the name of the release tag based on the SHA stored on
49+
each of the servers.
50+
51+
Note that this needs a valid GitHub Access token in the environment.
52+
Because many of the SHAs will be the same, there is caching in place to
53+
avoid unnecessary calls.
54+
"""
55+
access_token = os.environ.get('GITHUB_ACCESS_TOKEN')
56+
if access_token is None:
57+
raise ValueError("Please set GITHUB_ACCESS_TOKEN in order to continue")
58+
59+
for server_name, puppet_information in server_mapping.iteritems():
60+
sha = puppet_information.get('sha')
61+
url = "https://api.github.com/repos/alphagov/govuk-puppet/git/tags/{}".format(sha)
62+
response = requests.get(url, headers={'Authorization': "token {}".format(access_token)})
63+
response_data = response.json()
64+
puppet_information['release'] = response_data.get(u'tag')
65+
server_mapping[server_name] = puppet_information
66+
67+
return server_mapping
68+
69+
70+
def validate_environment(environment):
71+
"""
72+
Given an environment, makes sure it is valid.
73+
"""
74+
valid_environments = ['integration', 'staging', 'production']
75+
76+
if environment not in valid_environments:
77+
error = "Invalid environment '{}'. It should be one of: {}".format(
78+
environment,
79+
', '.join(valid_environments)
80+
)
81+
raise ValueError(error)
82+
83+
84+
def read_input_file(data_file):
85+
"""
86+
Reads the input file produced by the fab script
87+
"""
88+
with open(data_file, 'rb') as f:
89+
reader = csv.reader(f)
90+
fab_output = list(reader)
91+
92+
return fab_output
93+
94+
95+
def print_current_releases(server_mapping, environment):
96+
print "\n==> The following releases are live in {}\n".format(environment)
97+
releases = [puppet_information.get('release')
98+
for server_name, puppet_information in server_mapping.iteritems()]
99+
for release in set(releases):
100+
print release
101+
102+
103+
def print_puppet_details_per_server(server_mapping, environment):
104+
print "\n==> Puppet details per server\n"
105+
for server_name, puppet_information in server_mapping.iteritems():
106+
print "{}.{}".format(server_name, environment)
107+
print " Current release: {}".format(puppet_information['release'])
108+
109+
if puppet_information.get('time'):
110+
time_string = time.ctime(int(puppet_information.get('time')))
111+
else:
112+
time_string = 'could not determine, please try again'
113+
print " Last puppet run: {}".format(time_string)
114+
115+
116+
if __name__ == '__main__':
117+
arguments = sys.argv[1:]
118+
environment = arguments[0]
119+
data_file = arguments[1]
120+
121+
validate_environment(environment)
122+
fab_output = read_input_file(data_file)
123+
124+
server_mapping = group_data_per_server(fab_output)
125+
server_mapping = enhance_with_release_number(server_mapping)
126+
127+
print_current_releases(server_mapping, environment)
128+
print_puppet_details_per_server(server_mapping, environment)

puppet.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,10 @@ def sign_certificates():
5858
with settings(hide('running'), ok_ret_codes=[0, 24]):
5959
sudo('puppet cert sign --all')
6060
sleep(10)
61+
62+
63+
@task
64+
def config_version():
65+
"""Fetch the current puppet config version"""
66+
sudo("awk '/config:/ { print \"sha:\" $2 }' /var/lib/puppet/state/last_run_summary.yaml | tr -d '\"'")
67+
sudo("awk '/last_run:/ { print \"time:\" $2 }' /var/lib/puppet/state/last_run_summary.yaml | tr -d '\"'")

0 commit comments

Comments
 (0)