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
|
# Copyright (C) 2014 Codethink Limited
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import collections
import logging
import re
import urllib2
import urlparse
import cliapp
import lorrycontroller
class GitanoCommandFailure(Exception):
def __init__(self, trovehost, command, stderr):
Exception.__init__(
self,
'Failed to run "%s" on Gitano on %s\n%s' %
(command, trovehost, stderr))
class GitanoCommand(object):
'''Run a Gitano command on a Trove.'''
def __init__(self, trovehost, protocol, username, password):
self.trovehost = trovehost
self.protocol = protocol
self.username = username
self.password = password
if protocol == 'ssh':
self._command = self._ssh_command
elif protocol in ('http', 'https'):
self._command = self._http_command
else:
raise GitanoCommandFailure(
self.trovehost, '__init__', 'unknown protocol %s' % protocol)
def whoami(self):
return self._command(['whoami'])
def create(self, repo_path):
self._command(['create', repo_path])
def get_gitano_config(self, repo_path):
stdout = self._command(['config', repo_path, 'show'])
# "config REPO show" outputs a sequence of lines of the form "key: value".
# Extract those into a collections.defaultdict.
result = collections.defaultdict(str)
for line in stdout.splitlines():
m = re.match(r'^([^:])+:\s*(.*)$', line)
if m:
result[m.group(0)] = m.group(1).strip()
return result
def set_gitano_config(self, path, key, value):
self._command(['config', path, 'set', key, value])
def ls(self):
return self._command(['ls'])
def _ssh_command(self, gitano_args):
quoted_args = [cliapp.shell_quote(x) for x in gitano_args]
exit, stdout, stderr = cliapp.runcmd_unchecked(
['ssh', 'git@%s' % self.trovehost] + quoted_args)
if exit != 0:
logging.error(
'Failed to run "%s" for %s:\n%s',
self.trovehost, stdout + stderr)
raise GitanoCommandFailure(
self.trovehost,
' '.join(gitano_args),
stdout + stderr)
return stdout
def _http_command(self, gitano_args):
quoted_args = urllib2.quote(' '.join(gitano_args))
url = urlparse.urlunsplit((
self.protocol,
self.trovehost,
'/gitano-command.cgi',
'cmd=%s' % quoted_args,
''))
logging.debug('url=%r', url)
try:
request = urllib2.Request(url, None, {})
logging.debug('request=%r', request.get_full_url())
if self.username and self.password:
password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
password_mgr.add_password(None, url, self.username, self.password)
auth_handler = urllib2.HTTPBasicAuthHandler(password_mgr)
opener = urllib2.build_opener(auth_handler)
response = opener.open(url)
else:
response = urllib2.urlopen(request)
except urllib2.URLError as e:
raise GitanoCommandFailure(
self.trovehost, ' '.join(gitano_args), str(e))
return response.read()
|