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
|
#!/usr/bin/python3
import argparse
import fileinput
from glob import glob
import json
import re
import subprocess
import sys
class Charm(object):
def __init__(self, charm_name, series):
"""Create a charm object.
@param charm_name: name of charm
"""
reference = "cs:{}/{}".format(series, charm_name)
json_info = subprocess.check_output(
["charm", "show", "--format=json", reference, "id"])
charm_data = json.loads(json_info)
self.revision = charm_data.get("id", {}).get("Revision")
if self.revision is None:
raise IOError("{}: {}".format(charm_name, charm_data))
self.name = charm_name
self.store_url = charm_data.get("id", {}).get("Id")
def _get_charm(charm_name, series):
"""
Small wrapper to try to get the series charm you specify. Falls back
to precise if you specified something else
"""
try:
return Charm(charm_name, series)
except IOError as e:
if series != "trusty":
try:
return Charm(charm_name, series="trusty")
except IOError as trusty_e:
raise IOError(
"%s: not found? (even tried trusty): {}, {}".format(
charm_name, e, trusty_e))
raise
def replace_in_config(filename, charms, series):
"""
Iterate over each charm, replacing all occurences of old charm store
urls with new versions. Intent is to leave file in a state that can
be tested and checked in if successful.
Look for lines like:
charm: cs:trusty/juju-gui-83
Or:
series: trusty
"""
for line in fileinput.input(filename, inplace=1):
pattern = "^(\s*)series:\s.*$"
line = re.sub(pattern, r"\1series: %s" % series, line)
for charm in charms:
pattern = "cs:[^/]+/{}-[0-9]+".format(charm.name)
line = re.sub(pattern, charm.store_url, line)
sys.stdout.write(line)
print("# Config written, use `bzr diff %s` to see any changes" % filename)
def get_options():
"""Parse and return command line options."""
description = "Put new charmstore descriptors into a deployer file."
parser = argparse.ArgumentParser(description=description)
parser.add_argument("charms", help="List charms to update", nargs='*')
parser.add_argument("--series", help="Charm series", default="bionic")
return parser.parse_args()
def main():
options = get_options()
charms = []
if len(options.charms):
print("# Latest upstream versions of charms ({}):".format(
options.series))
for charm_name in options.charms:
charm = _get_charm(charm_name, series=options.series)
print("# {}: {}".format(charm_name, charm.revision))
charms.append(charm)
for filename in glob("*.jinja2"):
replace_in_config(filename, charms, series=options.series)
if __name__ == "__main__":
sys.exit(main())
|