207.2.1
by Curtis Hovey
Added script to publish_streams. |
1 |
#!/usr/bin/python
|
2 |
||
3 |
from __future__ import print_function |
|
4 |
||
5 |
from argparse import ArgumentParser |
|
207.2.3
by Curtis Hovey
Save point. |
6 |
import difflib |
207.2.1
by Curtis Hovey
Added script to publish_streams. |
7 |
import os |
8 |
import sys |
|
9 |
import traceback |
|
207.2.2
by Curtis Hovey
Added get_remote_file. |
10 |
import urllib2 |
207.2.1
by Curtis Hovey
Added script to publish_streams. |
11 |
|
12 |
||
221.1.1
by Aaron Bentley
Fix lint. |
13 |
__metaclass__ = type |
14 |
||
15 |
||
207.2.10
by Curtis Hovey
simplify the CPCS dict. |
16 |
CPCS = { |
17 |
'aws': "http://juju-dist.s3.amazonaws.com", |
|
18 |
'azure': "https://jujutools.blob.core.windows.net/juju-tools", |
|
19 |
'canonistack': ( |
|
207.2.8
by Curtis Hovey
Added tests for calls to verify_metadata. |
20 |
"https://swift.canonistack.canonical.com"
|
207.2.10
by Curtis Hovey
simplify the CPCS dict. |
21 |
"/v1/AUTH_526ad877f3e3464589dc1145dfeaac60/juju-dist"), |
22 |
'joyent': ( |
|
23 |
"https://us-east.manta.joyent.com/cpcjoyentsupport/public/juju-dist"), |
|
24 |
}
|
|
207.2.1
by Curtis Hovey
Added script to publish_streams. |
25 |
|
26 |
||
207.2.2
by Curtis Hovey
Added get_remote_file. |
27 |
def get_remote_file(url): |
207.2.11
by Curtis Hovey
Updated docstrings. |
28 |
"""Return the content of a remote file."""
|
207.2.2
by Curtis Hovey
Added get_remote_file. |
29 |
response = urllib2.urlopen(url) |
30 |
content = response.read() |
|
31 |
return content |
|
32 |
||
33 |
||
207.2.5
by Curtis Hovey
Added verify_metadata. |
34 |
def diff_files(local, remote): |
207.2.11
by Curtis Hovey
Updated docstrings. |
35 |
"""Return the difference of a local and a remote file.
|
36 |
||
37 |
:return: a tuple of identical (True, None) or different (False, str).
|
|
38 |
"""
|
|
207.2.3
by Curtis Hovey
Save point. |
39 |
with open(local, 'r') as f: |
40 |
local_lines = f.read().splitlines() |
|
207.2.5
by Curtis Hovey
Added verify_metadata. |
41 |
remote_lines = get_remote_file(remote).splitlines() |
42 |
diff_gen = difflib.unified_diff(local_lines, remote_lines, local, remote) |
|
207.2.11
by Curtis Hovey
Updated docstrings. |
43 |
diff = '\n'.join(list(diff_gen)) |
207.2.3
by Curtis Hovey
Save point. |
44 |
if diff: |
45 |
return False, diff |
|
46 |
return True, None |
|
47 |
||
48 |
||
207.2.8
by Curtis Hovey
Added tests for calls to verify_metadata. |
49 |
def verify_metadata(location, remote_stream, verbose=False): |
207.2.11
by Curtis Hovey
Updated docstrings. |
50 |
"""Verify all the streams metadata in a cloud matches the local metadata.
|
51 |
||
52 |
||
53 |
This verifies all the streams, not a single stream, to ensure the cloud
|
|
54 |
has exactly the same metadata as the local instance.
|
|
55 |
"""
|
|
207.2.5
by Curtis Hovey
Added verify_metadata. |
56 |
local_metadata = os.path.join(location, 'tools', 'streams', 'v1') |
207.2.8
by Curtis Hovey
Added tests for calls to verify_metadata. |
57 |
remote_metadata = '{}/tools/streams/v1'.format(remote_stream) |
207.2.5
by Curtis Hovey
Added verify_metadata. |
58 |
if verbose: |
59 |
print('comparing {} to {}'.format(local_metadata, remote_metadata)) |
|
60 |
for data_file in os.listdir(local_metadata): |
|
61 |
if data_file.endswith('.json'): |
|
62 |
local_file = os.path.join(local_metadata, data_file) |
|
63 |
remote_file = '{}/{}'.format(remote_metadata, data_file) |
|
64 |
if verbose: |
|
65 |
print('comparing {}'.format(data_file)) |
|
66 |
identical, diff = diff_files(local_file, remote_file) |
|
67 |
if not identical: |
|
68 |
return False, diff |
|
69 |
if verbose: |
|
70 |
print('All json matches') |
|
207.2.2
by Curtis Hovey
Added get_remote_file. |
71 |
return True, None |
72 |
||
73 |
||
207.2.1
by Curtis Hovey
Added script to publish_streams. |
74 |
def publish(stream, location, cloud, |
75 |
remote_root=None, dry_run=False, verbose=False): |
|
207.2.11
by Curtis Hovey
Updated docstrings. |
76 |
"""Publish a stream to a cloud and verify it."""
|
207.2.8
by Curtis Hovey
Added tests for calls to verify_metadata. |
77 |
if remote_root: |
207.2.10
by Curtis Hovey
simplify the CPCS dict. |
78 |
remote_stream = '{}/{}'.format(CPCS[cloud], remote_root) |
207.2.8
by Curtis Hovey
Added tests for calls to verify_metadata. |
79 |
else: |
80 |
remote_stream = CPCS.get(cloud) |
|
81 |
verify_metadata(location, remote_stream, verbose=verbose) |
|
207.2.1
by Curtis Hovey
Added script to publish_streams. |
82 |
|
83 |
||
207.2.10
by Curtis Hovey
simplify the CPCS dict. |
84 |
def parse_args(argv=None): |
207.2.1
by Curtis Hovey
Added script to publish_streams. |
85 |
"""Return the argument parser for this program."""
|
86 |
parser = ArgumentParser("Publish streams to a cloud.") |
|
87 |
parser.add_argument( |
|
207.2.11
by Curtis Hovey
Updated docstrings. |
88 |
'-d', '--dry-run', action="store_true", help='Do not make changes.') |
89 |
parser.add_argument( |
|
90 |
'-v', '--verbose', action="store_true", help='Increase verbosity.') |
|
91 |
parser.add_argument( |
|
92 |
'-r', '--remote-root', |
|
207.2.1
by Curtis Hovey
Added script to publish_streams. |
93 |
help='An alternate root to publish to such as testing or weekly.') |
94 |
parser.add_argument( |
|
207.2.2
by Curtis Hovey
Added get_remote_file. |
95 |
'stream', help='The agent-stream to publish.', |
207.2.1
by Curtis Hovey
Added script to publish_streams. |
96 |
choices=['released', 'proposed', 'devel']) |
97 |
parser.add_argument( |
|
98 |
'location', type=os.path.expanduser, |
|
99 |
help='The path to the local tree of all streams (tools/).') |
|
100 |
parser.add_argument( |
|
101 |
'cloud', help='The destination cloud.', |
|
244
by Curtis Hovey
Remove HP from publication. |
102 |
choices=['streams', 'aws', 'azure', 'joyent', 'canonistack']) |
207.2.10
by Curtis Hovey
simplify the CPCS dict. |
103 |
return parser.parse_args(argv) |
207.2.1
by Curtis Hovey
Added script to publish_streams. |
104 |
|
105 |
||
106 |
def main(argv): |
|
207.2.11
by Curtis Hovey
Updated docstrings. |
107 |
"""Publish streams to a cloud."""
|
207.2.1
by Curtis Hovey
Added script to publish_streams. |
108 |
args = parse_args(argv) |
109 |
try: |
|
110 |
publish( |
|
111 |
args.stream, args.location, args.cloud, |
|
112 |
remote_root=args.remote_root, dry_run=args.dry_run, |
|
113 |
verbose=args.verbose) |
|
114 |
except Exception as e: |
|
207.2.11
by Curtis Hovey
Updated docstrings. |
115 |
print('{}: {}'.format(e.__class__.__name__, e)) |
207.2.1
by Curtis Hovey
Added script to publish_streams. |
116 |
if args.verbose: |
117 |
traceback.print_tb(sys.exc_info()[2]) |
|
118 |
return 2 |
|
119 |
if args.verbose: |
|
120 |
print("Done.") |
|
121 |
return 0 |
|
122 |
||
123 |
||
124 |
if __name__ == '__main__': |
|
125 |
sys.exit(main(sys.argv[1:])) |