-
Notifications
You must be signed in to change notification settings - Fork 266
/
push.py
executable file
·187 lines (133 loc) · 5.62 KB
/
push.py
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#!/usr/bin/env python
"""
<Program Name>
push.py
<Author>
Vladimir Diaz <vladimir.v.diaz@gmail.com>
<Started>
August 2012. Based on a previous version by Geremy Condra.
<Copyright>
See LICENSE for licensing information.
<Purpose>
This script provides a way for developers to push a signed targets metadata
file (i.e., 'targets.txt') and the referenced targets to a repository. The
repository adds these files to the repository by running the
'tuf/pushtools/receivetools/receive.py' script.
'push.py' is not a required module of The Update Framework, but is provided
to allow developers to remotely update the target files served by a
repository. The actual file transfers are completed by a separate command
available on the client machine. The 'SCP' (secure copy) command is currently
supported. This script may be viewed as a front-end to the python transfer
modules (e.g., 'tuf.pushtools.transfer.scp'). A configuration file can be
specified allowing the user to customize the transfer and supply the locations
of targets and metadata.
Usage:
$ python push.py --config <config path>
Example:
$ python push.py --config ./push.cfg
Details of the 'push.py' script:
The developer provides the path to a configuration file that lists:
* The path to the targets metadata file.
* The name of the transfer module to use for transferring the
files to the repository (e.g., 'scp').
* Configuration information that is specific to the transfer
module.
See the 'push.cfg.sample' file for an example configuration file.
The transfer module needs the following functionality:
* A way to transfer target files and the new metadata file to the
repository. The 'scp' transfer modules is currently supported.
The transfer module may also include the following functionality:
* A way to determine whether the repository has rejected the push and, if
so, the reason for the rejection.
"""
import os
import sys
import optparse
import tuf
import tuf.formats
import tuf.pushtools.pushtoolslib
import tuf.pushtools.transfer.scp
def push(config_filepath):
"""
<Purpose>
Perform a push/transfer of target files to a host. The configuration file
'config_filepath' provides the required settings needed by the transfer
command. In the case of an 'scp' configuration file, the configuration
file would contain 'host', 'user', 'identity file', and 'remote directory'
entries.
<Arguments>
config_filepath:
The push configuration file (i.e., 'push.cfg').
<Exceptions>
tuf.FormatError, if any of the arguments are incorrectly formatted.
tuf.Error, if there was an error while processing the push.
<Side Effects>
The 'config_filepath' file is read and its contents stored, the files
in the targets directory (specified in the config file) are copied,
and the copied targets transfered to a specified host.
<Returns>
None.
"""
# Do the arguments have the correct format?
# Raise 'tuf.FormatError' if there is a mismatch.
tuf.formats.PATH_SCHEMA.check_match(config_filepath)
# Is the path to the configuration file valid?
if not os.path.isfile(config_filepath):
message = 'The configuration file path is invalid.'
raise tuf.Error(message)
config_filepath = os.path.abspath(config_filepath)
# Retrieve the push configuration settings required by the transfer
# modules. Raise ('tuf.FormatError', 'tuf.Error') if a valid
# configuration file cannot be retrieved.
config_dict = tuf.pushtools.pushtoolslib.read_config_file(config_filepath, 'push')
# Extract the transfer module identified in the configuration file.
transfer_module = config_dict['general']['transfer_module']
# 'scp' is the only transfer module currently supported. Perform
# an scp-transfer of the targets located in the targets directory as
# listed in the configuration file.
if transfer_module == 'scp':
tuf.pushtools.transfer.scp.transfer(config_dict)
else:
message = 'Cannot perform a transfer using '+repr(transfer_module)
raise tuf.Error(message)
def parse_options():
"""
<Purpose>
Parse the command-line options. 'push.py' expects the '--config'
option to be set by the user.
Example:
$ python push.py --config ./push.cfg
The '--config' option accepts a path argument to the push configuration
file (i.e., 'push.cfg'). If the required option is unset, a parser error
is printed and the script exits.
<Arguments>
None.
<Exceptions>
None.
<Side Effects>
None.
<Returns>
The options object returned by the parser's parse_args() method.
"""
usage = 'usage: %prog --config <config path>'
option_parser = optparse.OptionParser(usage=usage)
# Add the options supported by 'push.py' to the option parser.
option_parser.add_option('--config', action='store', type='string',
help='Specify the "push.cfg" configuration file.')
(options, remaining_arguments) = option_parser.parse_args()
# Ensure the '--config' option is set. If the required option is unset,
# option_parser.error() will print an error message and exit.
if options.config is None:
message = '"--config" must be set on the command-line.'
option_parser.error(message)
return options
if __name__ == '__main__':
options = parse_options()
# Perform a 'push' of the target files specified in the configuration file.
try:
push(options.config)
except (tuf.FormatError, tuf.Error), e:
sys.stderr.write('Error: '+str(e)+'\n')
sys.exit(1)
# The 'push' and command-line options were processed successfully.
sys.exit(0)