~nskaggs/juju-release-tools/generate-release-notes

230.1.1 by Aaron Bentley
Implement making agents.
1
#!/usr/bin/env python
2
from argparse import ArgumentParser
231.1.1 by Aaron Bentley
Support multiple series.
3
from copy import deepcopy
231.1.6 by Aaron Bentley
Updates from review.
4
from datetime import datetime
230.1.1 by Aaron Bentley
Implement making agents.
5
import hashlib
6
import os
284.1.1 by Aaron Bentley
Support building gui json.
7
import re
230.1.1 by Aaron Bentley
Implement making agents.
8
import sys
9
251.1.1 by Aaron Bentley
Remove obsolete functionality.
10
from simplestreams.generate_simplestreams import json_dump
11
231.1.4 by Aaron Bentley
Support using one agent for all living ubuntu.
12
from build_package import juju_series
230.1.1 by Aaron Bentley
Implement making agents.
13
284.1.1 by Aaron Bentley
Support building gui json.
14
__metaclass__ = type
15
230.1.1 by Aaron Bentley
Implement making agents.
16
231.1.6 by Aaron Bentley
Updates from review.
17
supported_windows_releases = (
262.1.3 by Curtis Hovey
Add win2016 and win2016nano.
18
    'win2012', 'win2012hv', 'win2012hvr2', 'win2012r2', 'win2016',
19
    'win2016nano', 'win7', 'win81', 'win8', 'win10',
231.1.6 by Aaron Bentley
Updates from review.
20
    )
21
22
230.1.1 by Aaron Bentley
Implement making agents.
23
def parse_args():
24
    parser = ArgumentParser()
25
    parsers = parser.add_subparsers(dest='command')
26
    ubuntu = parsers.add_parser('ubuntu')
231.1.4 by Aaron Bentley
Support using one agent for all living ubuntu.
27
    living_ubuntu = parsers.add_parser('living-ubuntu')
231.1.2 by Aaron Bentley
Support Windows.
28
    windows = parsers.add_parser('windows')
231.1.3 by Aaron Bentley
Support Centos.
29
    centos = parsers.add_parser('centos')
231.1.4 by Aaron Bentley
Support using one agent for all living ubuntu.
30
    for subparser in [ubuntu, living_ubuntu, windows, centos]:
231.1.5 by Aaron Bentley
Unify argument order.
31
        subparser.add_argument('tarfile')
32
        subparser.add_argument('revision_build')
231.1.2 by Aaron Bentley
Support Windows.
33
        subparser.add_argument('version')
231.1.5 by Aaron Bentley
Unify argument order.
34
    for subparser in [ubuntu, living_ubuntu]:
35
        subparser.add_argument('arch')
36
    ubuntu.add_argument('release')
37
    ubuntu.add_argument('series')
284.1.1 by Aaron Bentley
Support building gui json.
38
    gui = parsers.add_parser('gui')
39
    gui.add_argument('tarfile')
284.1.4 by Aaron Bentley
Remove incorrect agent references.
40
    gui.add_argument('stream')
230.1.1 by Aaron Bentley
Implement making agents.
41
    return parser.parse_args()
42
43
284.1.5 by Aaron Bentley
Cleanup.
44
class FileStanzaWriter:
45
    """Base class to write stanzas about files."""
284.1.1 by Aaron Bentley
Support building gui json.
46
284.1.4 by Aaron Bentley
Remove incorrect agent references.
47
    def __init__(self, filename, stream, version, ftype, tarfile,
48
                 path):
284.1.1 by Aaron Bentley
Support building gui json.
49
        self.filename = filename
284.1.4 by Aaron Bentley
Remove incorrect agent references.
50
        self.stream = stream
284.1.1 by Aaron Bentley
Support building gui json.
51
        self.version = version
52
        self.tarfile = tarfile
284.1.4 by Aaron Bentley
Remove incorrect agent references.
53
        self.path = path
284.1.1 by Aaron Bentley
Support building gui json.
54
        self.version_name = datetime.utcnow().strftime('%Y%m%d')
55
        self.ftype = ftype
56
284.1.2 by Aaron Bentley
Make product_name and item_name make_path_stanza parameters.
57
    def make_path_stanza(self, product_name, item_name, hashes, size):
284.1.5 by Aaron Bentley
Cleanup.
58
        """Make a path stanza.
59
60
        :param product_name: The simplestreams product name.
61
        :param item_name: The simplestream item name.
62
        :param hahes: A dict mapping hash name to the hash of the file with
63
            that hash.  hashlib names (e.g. "sha256") should be used.
64
        """
284.1.1 by Aaron Bentley
Support building gui json.
65
        stanza = {
66
            'content_id': self.content_id,
284.1.2 by Aaron Bentley
Make product_name and item_name make_path_stanza parameters.
67
            'product_name': product_name,
68
            'item_name': item_name,
284.1.1 by Aaron Bentley
Support building gui json.
69
            'version_name': self.version_name,
284.1.4 by Aaron Bentley
Remove incorrect agent references.
70
            'path': self.path,
284.1.1 by Aaron Bentley
Support building gui json.
71
            'size': size,
72
            'version': self.version,
73
            'format': 'products:1.0',
74
            'ftype': self.ftype,
75
            }
76
        stanza.update(deepcopy(hashes))
77
        return stanza
78
79
    def write_stanzas(self):
284.1.5 by Aaron Bentley
Cleanup.
80
        """Write stanzas about the file to the filename.
81
82
        This calculates the hashes as part of the procedure.
83
        """
284.1.1 by Aaron Bentley
Support building gui json.
84
        with open(self.tarfile) as tarfile_fp:
85
            content = tarfile_fp.read()
86
        hashes = {}
87
        for hash_algorithm in self.hash_algorithms:
88
            hash_obj = hashlib.new(hash_algorithm)
89
            hash_obj.update(content)
90
            hashes[hash_algorithm] = hash_obj.hexdigest()
91
        stanzas = list(self.make_stanzas(hashes, len(content)))
92
        json_dump(stanzas, self.filename)
93
94
284.1.5 by Aaron Bentley
Cleanup.
95
class StanzaWriter(FileStanzaWriter):
231.1.1 by Aaron Bentley
Support multiple series.
96
259.1.7 by Aaron Bentley
Use specified agent-streams.
97
    def __init__(self, releases, arch, version, tarfile, filename,
98
                 revision_build=None, agent_stream=None):
99
        if agent_stream is None:
284.1.1 by Aaron Bentley
Support building gui json.
100
            agent_stream = 'revision-build-{}'.format(revision_build)
259.1.7 by Aaron Bentley
Use specified agent-streams.
101
        if revision_build is None:
284.1.4 by Aaron Bentley
Remove incorrect agent references.
102
            path = 'agent/{}/{}'.format(
259.1.7 by Aaron Bentley
Use specified agent-streams.
103
                version, os.path.basename(tarfile))
104
        else:
284.1.4 by Aaron Bentley
Remove incorrect agent references.
105
            path = 'agent/revision-build-{}/{}'.format(
259.1.7 by Aaron Bentley
Use specified agent-streams.
106
                revision_build, os.path.basename(tarfile))
284.1.1 by Aaron Bentley
Support building gui json.
107
        super(StanzaWriter, self).__init__(filename, agent_stream, version,
284.1.4 by Aaron Bentley
Remove incorrect agent references.
108
                                           'tar.gz', tarfile, path)
284.1.1 by Aaron Bentley
Support building gui json.
109
        self.releases = releases
110
        self.arch = arch
231.1.1 by Aaron Bentley
Support multiple series.
111
        self.filename = filename
112
284.1.5 by Aaron Bentley
Cleanup.
113
    hash_algorithms = frozenset(['sha256', 'md5'])
284.1.1 by Aaron Bentley
Support building gui json.
114
115
    @property
116
    def content_id(self):
284.1.4 by Aaron Bentley
Remove incorrect agent references.
117
        return 'com.ubuntu.juju:{}:tools'.format(self.stream)
284.1.1 by Aaron Bentley
Support building gui json.
118
231.1.1 by Aaron Bentley
Support multiple series.
119
    @classmethod
259.1.7 by Aaron Bentley
Use specified agent-streams.
120
    def for_ubuntu(cls, release, series, arch, version, tarfile,
121
                   revision_build=None, agent_stream=None):
122
        if revision_build is None:
123
            filename = '{}-{}-{}-{}.json'.format(
124
                agent_stream, version, series, arch)
125
        else:
126
            filename = 'revision-build-{}-{}-{}.json'.format(
127
                revision_build, series, arch)
231.1.1 by Aaron Bentley
Support multiple series.
128
        return cls(
259.1.7 by Aaron Bentley
Use specified agent-streams.
129
            [(release, series)], arch, version, tarfile, filename,
130
            revision_build, agent_stream)
231.1.1 by Aaron Bentley
Support multiple series.
131
231.1.2 by Aaron Bentley
Support Windows.
132
    @classmethod
259.1.10 by Aaron Bentley
Support agent-streams for make_agent_json.
133
    def for_living_ubuntu(cls, arch, version, tarfile, revision_build=None,
134
                          agent_stream=None):
135
        if revision_build is None:
136
            filename = '{}-{}-ubuntu-{}.json'.format(
308 by Curtis Hovey
Added install-deps target.
137
                agent_stream, version, arch)
259.1.10 by Aaron Bentley
Support agent-streams for make_agent_json.
138
        else:
139
            filename = 'revision-build-{}-ubuntu-{}.json'.format(
308 by Curtis Hovey
Added install-deps target.
140
                revision_build, arch)
231.1.4 by Aaron Bentley
Support using one agent for all living ubuntu.
141
        releases = [
142
            (juju_series.get_version(name), name) for name
143
            in juju_series.get_living_names()]
144
        return cls(
259.1.10 by Aaron Bentley
Support agent-streams for make_agent_json.
145
            releases, arch, version, tarfile, filename, revision_build,
146
            agent_stream)
231.1.4 by Aaron Bentley
Support using one agent for all living ubuntu.
147
148
    @classmethod
259.1.10 by Aaron Bentley
Support agent-streams for make_agent_json.
149
    def for_windows(cls, version, tarfile, revision_build=None,
150
                    agent_stream=None):
151
        if revision_build is None:
152
            filename = '{}-{}-windows.json'.format(agent_stream, version)
153
        else:
154
            filename = 'revision-build-{}-windows.json'.format(
155
                revision_build)
231.1.6 by Aaron Bentley
Updates from review.
156
        releases = [(r, r) for r in supported_windows_releases]
259.1.7 by Aaron Bentley
Use specified agent-streams.
157
        return cls(releases, 'amd64', version, tarfile, filename,
259.1.10 by Aaron Bentley
Support agent-streams for make_agent_json.
158
                   revision_build, agent_stream)
231.1.2 by Aaron Bentley
Support Windows.
159
231.1.3 by Aaron Bentley
Support Centos.
160
    @classmethod
259.1.10 by Aaron Bentley
Support agent-streams for make_agent_json.
161
    def for_centos(cls, version, tarfile, revision_build=None,
162
                   agent_stream=None):
163
        if revision_build is None:
164
            filename = '{}-{}-centos.json'.format(agent_stream, version)
165
        else:
166
            filename = 'revision-build-{}-centos.json'.format(revision_build)
259.1.7 by Aaron Bentley
Use specified agent-streams.
167
        return cls([('centos7', 'centos7')], 'amd64', version, tarfile,
259.1.10 by Aaron Bentley
Support agent-streams for make_agent_json.
168
                   filename, revision_build, agent_stream)
231.1.3 by Aaron Bentley
Support Centos.
169
259.1.7 by Aaron Bentley
Use specified agent-streams.
170
    def make_stanzas(self, hashes, size):
231.1.1 by Aaron Bentley
Support multiple series.
171
        for release, series in self.releases:
284.1.2 by Aaron Bentley
Make product_name and item_name make_path_stanza parameters.
172
            item_name = '{}-{}-{}'.format(self.version, series, self.arch)
173
            product_name = 'com.ubuntu.juju:{}:{}'.format(release, self.arch)
174
            stanza = self.make_path_stanza(product_name, item_name, hashes,
175
                                           size)
284.1.1 by Aaron Bentley
Support building gui json.
176
            stanza.update({
231.1.1 by Aaron Bentley
Support multiple series.
177
                'arch': self.arch,
178
                'release': series,
284.1.1 by Aaron Bentley
Support building gui json.
179
                })
231.1.1 by Aaron Bentley
Support multiple series.
180
            yield stanza
230.1.1 by Aaron Bentley
Implement making agents.
181
182
284.1.5 by Aaron Bentley
Cleanup.
183
class GUIStanzaWriter(FileStanzaWriter):
284.1.1 by Aaron Bentley
Support building gui json.
184
284.1.5 by Aaron Bentley
Cleanup.
185
    hash_algorithms = frozenset(['sha256', 'sha1', 'md5'])
284.1.1 by Aaron Bentley
Support building gui json.
186
187
    @property
188
    def content_id(self):
284.1.4 by Aaron Bentley
Remove incorrect agent references.
189
        return 'com.canonical.streams:{}:gui'.format(self.stream)
284.1.1 by Aaron Bentley
Support building gui json.
190
191
    @classmethod
284.1.4 by Aaron Bentley
Remove incorrect agent references.
192
    def from_tarfile(cls, tarfile, stream):
284.1.5 by Aaron Bentley
Cleanup.
193
        """Use a tarfile and stream to instantiate this class."""
284.1.1 by Aaron Bentley
Support building gui json.
194
        tar_base = os.path.basename(tarfile)
285.1.1 by Aaron Bentley
Update to match real jujugui tarball name.
195
        version = re.match('jujugui-(.*).tar.bz2', tar_base).group(1)
284.1.4 by Aaron Bentley
Remove incorrect agent references.
196
        filename = 'juju-gui-{}-{}.json'.format(stream, version)
197
        path = '/'.join(['gui', version, tar_base])
285.1.1 by Aaron Bentley
Update to match real jujugui tarball name.
198
        return cls(filename, stream, version, 'tar.bz2', tarfile,
284.1.4 by Aaron Bentley
Remove incorrect agent references.
199
                   path)
284.1.1 by Aaron Bentley
Support building gui json.
200
201
    def make_stanzas(self, hashes, size):
284.1.5 by Aaron Bentley
Cleanup.
202
        """Return a single stanza for the gui.
203
204
        The GUI is arch/os independent, so only one stanza is needed.
205
        """
286.1.1 by Aaron Bentley
Add juju-version to juju-gui metadata.
206
        stanza = self.make_path_stanza(
207
            'com.canonical.streams:gui', self.version, hashes, size)
208
        stanza['juju-version'] = 2
209
        return [stanza]
284.1.1 by Aaron Bentley
Support building gui json.
210
211
230.1.1 by Aaron Bentley
Implement making agents.
212
def main():
213
    args = parse_args()
214
    kwargs = dict(args.__dict__)
215
    del kwargs['command']
231.1.1 by Aaron Bentley
Support multiple series.
216
    if args.command == 'ubuntu':
217
        writer = StanzaWriter.for_ubuntu(**kwargs)
231.1.4 by Aaron Bentley
Support using one agent for all living ubuntu.
218
    if args.command == 'living-ubuntu':
219
        writer = StanzaWriter.for_living_ubuntu(**kwargs)
231.1.3 by Aaron Bentley
Support Centos.
220
    elif args.command == 'windows':
231.1.2 by Aaron Bentley
Support Windows.
221
        writer = StanzaWriter.for_windows(**kwargs)
231.1.3 by Aaron Bentley
Support Centos.
222
    elif args.command == 'centos':
223
        writer = StanzaWriter.for_centos(**kwargs)
284.1.1 by Aaron Bentley
Support building gui json.
224
    elif args.command == 'gui':
225
        writer = GUIStanzaWriter.from_tarfile(**kwargs)
231.1.1 by Aaron Bentley
Support multiple series.
226
    writer.write_stanzas()
230.1.1 by Aaron Bentley
Implement making agents.
227
228
if __name__ == '__main__':
229
    sys.exit(main())