14.1.1
by David Britton
add update-charm-revision-numbers here. |
1 |
#!/usr/bin/python3
|
2 |
||
3 |
import argparse |
|
4 |
import fileinput |
|
47.1.1
by Adam Collard
Port update-charm-revisions script to (snap'd) charm CLI |
5 |
from glob import glob |
6 |
import json |
|
14.1.1
by David Britton
add update-charm-revision-numbers here. |
7 |
import re |
47.1.1
by Adam Collard
Port update-charm-revisions script to (snap'd) charm CLI |
8 |
import subprocess |
14.1.1
by David Britton
add update-charm-revision-numbers here. |
9 |
import sys |
10 |
||
11 |
||
12 |
class Charm(object): |
|
13 |
||
14 |
def __init__(self, charm_name, series): |
|
15 |
"""Create a charm object.
|
|
16 |
@param charm_name: name of charm
|
|
17 |
"""
|
|
18 |
reference = "cs:{}/{}".format(series, charm_name) |
|
47.1.1
by Adam Collard
Port update-charm-revisions script to (snap'd) charm CLI |
19 |
json_info = subprocess.check_output( |
20 |
["charm", "show", "--format=json", reference, "id"]) |
|
21 |
charm_data = json.loads(json_info) |
|
22 |
self.revision = charm_data.get("id", {}).get("Revision") |
|
23 |
if self.revision is None: |
|
24 |
raise IOError("{}: {}".format(charm_name, charm_data)) |
|
14.1.1
by David Britton
add update-charm-revision-numbers here. |
25 |
self.name = charm_name |
47.1.1
by Adam Collard
Port update-charm-revisions script to (snap'd) charm CLI |
26 |
self.store_url = charm_data.get("id", {}).get("Id") |
14.1.1
by David Britton
add update-charm-revision-numbers here. |
27 |
|
28 |
||
29 |
def _get_charm(charm_name, series): |
|
30 |
"""
|
|
31 |
Small wrapper to try to get the series charm you specify. Falls back
|
|
32 |
to precise if you specified something else
|
|
33 |
"""
|
|
34 |
try: |
|
35 |
return Charm(charm_name, series) |
|
36 |
except IOError as e: |
|
2.2.9
by Andreas Hasenack
Fallback to trusty charms, not precise. |
37 |
if series != "trusty": |
14.1.1
by David Britton
add update-charm-revision-numbers here. |
38 |
try: |
2.2.9
by Andreas Hasenack
Fallback to trusty charms, not precise. |
39 |
return Charm(charm_name, series="trusty") |
40 |
except IOError as trusty_e: |
|
14.1.3
by David Britton
ack[diff]: mostly nits |
41 |
raise IOError( |
2.2.9
by Andreas Hasenack
Fallback to trusty charms, not precise. |
42 |
"%s: not found? (even tried trusty): {}, {}".format( |
43 |
charm_name, e, trusty_e)) |
|
14.1.1
by David Britton
add update-charm-revision-numbers here. |
44 |
raise
|
45 |
||
46 |
||
47 |
def replace_in_config(filename, charms, series): |
|
48 |
"""
|
|
49 |
Iterate over each charm, replacing all occurences of old charm store
|
|
50 |
urls with new versions. Intent is to leave file in a state that can
|
|
51 |
be tested and checked in if successful.
|
|
52 |
||
53 |
Look for lines like:
|
|
54.1.1
by Simon Poirier
update-charm-revisions regexp to match current charm Id scheme. |
54 |
charm: cs:juju-gui-83
|
14.1.1
by David Britton
add update-charm-revision-numbers here. |
55 |
|
56 |
Or:
|
|
57 |
series: trusty
|
|
58 |
"""
|
|
59 |
for line in fileinput.input(filename, inplace=1): |
|
60 |
pattern = "^(\s*)series:\s.*$" |
|
61 |
line = re.sub(pattern, r"\1series: %s" % series, line) |
|
62 |
for charm in charms: |
|
54.1.1
by Simon Poirier
update-charm-revisions regexp to match current charm Id scheme. |
63 |
pattern = "cs:{}-[0-9]+".format(charm.name) |
14.1.1
by David Britton
add update-charm-revision-numbers here. |
64 |
line = re.sub(pattern, charm.store_url, line) |
65 |
sys.stdout.write(line) |
|
66 |
||
67 |
print("# Config written, use `bzr diff %s` to see any changes" % filename) |
|
68 |
||
69 |
||
70 |
def get_options(): |
|
71 |
"""Parse and return command line options."""
|
|
72 |
description = "Put new charmstore descriptors into a deployer file." |
|
73 |
parser = argparse.ArgumentParser(description=description) |
|
74 |
parser.add_argument("charms", help="List charms to update", nargs='*') |
|
43.1.1
by Simon Poirier
add bionic to series |
75 |
parser.add_argument("--series", help="Charm series", default="bionic") |
14.1.1
by David Britton
add update-charm-revision-numbers here. |
76 |
return parser.parse_args() |
77 |
||
78 |
||
79 |
def main(): |
|
80 |
options = get_options() |
|
81 |
charms = [] |
|
82 |
if len(options.charms): |
|
83 |
print("# Latest upstream versions of charms ({}):".format( |
|
84 |
options.series)) |
|
85 |
for charm_name in options.charms: |
|
86 |
charm = _get_charm(charm_name, series=options.series) |
|
87 |
print("# {}: {}".format(charm_name, charm.revision)) |
|
88 |
charms.append(charm) |
|
89 |
||
90 |
for filename in glob("*.jinja2"): |
|
91 |
replace_in_config(filename, charms, series=options.series) |
|
92 |
||
93 |
||
94 |
if __name__ == "__main__": |
|
47.1.2
by Adam Collard
Minor cleanup |
95 |
sys.exit(main()) |