Merge lp:~patrick-hetu/jrapi/ssh-master-key into lp:jrapi

Proposed by Patrick Hetu on 2012-08-26
Status: Needs review
Proposed branch: lp:~patrick-hetu/jrapi/ssh-master-key
Merge into: lp:jrapi
Diff against target: 400 lines (+46/-151)
6 files modified
debian/jrapi.postinst (+6/-0)
jrapi/api/base.py (+1/-10)
jrapi/api/environment.py (+23/-28)
jrapi/storage/dummy.py (+1/-4)
jrapi/storage/filesystem.py (+9/-82)
tests/test_environment.py (+6/-27)
To merge this branch: bzr merge lp:~patrick-hetu/jrapi/ssh-master-key
Reviewer Review Type Date Requested Status
Juan L. Negron 2012-08-26 Pending
Review via email: mp+121345@code.launchpad.net

Description of the change

1. Minor fix to get the environment tests to work
2. Use an ssh master key for bootstraping

To post a comment you must log in.

Unmerged revisions

80. By Patrick Hetu on 2012-08-26

use a master ssh key for bootstraping

79. By Patrick Hetu on 2012-08-26

fix environment tests

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/jrapi.postinst'
2--- debian/jrapi.postinst 2012-05-25 20:48:33 +0000
3+++ debian/jrapi.postinst 2012-08-26 19:06:19 +0000
4@@ -35,11 +35,17 @@
5 usermod -g jrapi jrapi
6 fi
7
8+ if [ ! -e /var/lib/jrapi/.ssh/ ]; then
9+ mkdir /var/lib/jrapi/.ssh/
10+ ssh-keygen -q -t rsa -f /var/lib/jrapi/.ssh/id_rsa -C 'juju_master_key' -N ''
11+ fi
12+
13 if [ -z "$2" ]; then
14 # New install - blanket permissions
15 chown -R jrapi:jrapi /var/lib/jrapi/ /etc/jrapi /var/log/jrapi
16 fi
17
18+
19 chmod 0600 /etc/jrapi/jrapi.conf
20 chmod 0700 /etc/jrapi
21 chmod 0700 /var/log/jrapi
22
23=== modified file 'jrapi/api/base.py'
24--- jrapi/api/base.py 2012-07-20 00:14:50 +0000
25+++ jrapi/api/base.py 2012-08-26 19:06:19 +0000
26@@ -45,17 +45,8 @@
27 :param failure: The failure object ( type )
28 :param request: The twisted request object
29 '''
30- if failure.type == errors.EnvironmentNotFound:
31- error_type = "EnvironmentNotFound"
32- msg = failure.getErrorMessage()
33- request.setResponseCode(404)
34- else:
35- error_type = "Unknown"
36- msg = failure.getErrorMessage()
37- request.setResponseCode(500)
38-
39+ msg = failure.getErrorMessage()
40 logging.error(msg)
41- request.write(jsonify({"error": {error_type: msg}}))
42
43 request.finish()
44
45
46=== modified file 'jrapi/api/environment.py'
47--- jrapi/api/environment.py 2012-07-24 17:17:20 +0000
48+++ jrapi/api/environment.py 2012-08-26 19:06:19 +0000
49@@ -60,7 +60,8 @@
50 try:
51 env_conf_yaml = storage.get_environment(username, name)
52 except IOError:
53- raise EnvironmentNotFound('Environment not found.')
54+ request.setResponseCode(404, "Environment not found")
55+ raise EnvironmentNotFound("Environment not found.")
56
57 env_config = EnvironmentsConfig()
58
59@@ -82,19 +83,18 @@
60
61 # continue when we will have a dns_name
62 dns_name = machine.dns_name
63+
64 LOG.debug("Got dns_name: %s" % dns_name)
65
66 if not dns_name:
67 request.setResponseCode(503)
68 raise EnvironmentNotFound("Environment not ready yet.")
69
70+ environment.dns_name = dns_name
71+
72 # get the fingerprint
73 LOG.debug("add_known_host")
74- storage.add_known_host(username, name, dns_name) # #@UndefinedVariable
75-
76- LOG.debug("add_ssh_config")
77- # add ssh config for the new host
78- storage.add_ssh_config(username, name, dns_name) # #@UndefinedVariable
79+ storage.add_known_host(username, name, dns_name)
80
81 returnValue(environment)
82
83@@ -161,6 +161,7 @@
84 return self
85 else:
86 deferred = get_environment(request, name, self.username)
87+ deferred.addErrback(self._errorRender, request)
88 environment = Environment(deferred, name, self.username)
89 return environment
90
91@@ -186,20 +187,13 @@
92 if not hasattr(conf, 'admin-secret'):
93 conf['admin-secret'] = uuid.uuid4().hex
94
95- # upload/create ssh private/public key
96- private_key_path = storage.add_sshkey( # @UndefinedVariable
97- self.username, conf['name'])
98-
99- LOG.debug('Setting private_key_path to : %s' % \
100- private_key_path + '.pub')
101- conf['authorized-keys-path'] = private_key_path + '.pub'
102+ if 'authorized-keys' in conf.keys():
103+ conf['authorized-keys'] += '\n %s' % (open('/var/lib/jrapi/.ssh/id_rsa.pub').read())
104+ else:
105+ conf['authorized-keys'] = open('/var/lib/jrapi/.ssh/id_rsa.pub').read()
106
107 env_conf_yaml = yaml.safe_dump({'environments': {conf['name']: conf}})
108
109- LOG.debug("Add environment: %s" % env_conf_yaml)
110- storage.add_environment(self.username, # #@UndefinedVariable
111- conf['name'], env_conf_yaml)
112-
113 env_config = EnvironmentsConfig()
114
115 LOG.debug("Configuring the environment")
116@@ -217,6 +211,9 @@
117 LOG.debug("Launch the actual bootstrap")
118 yield provider.bootstrap(my_constraints)
119
120+ LOG.debug("Save the environment: %s" % env_conf_yaml)
121+ storage.add_environment(self.username, conf['name'], env_conf_yaml)
122+
123 request.setResponseCode(201)
124
125
126@@ -255,9 +252,10 @@
127 '''
128 LOG.debug("Received an environment details request")
129
130- result = self._get(request)
131-
132- return jsonify(result)
133+ self.deferred.addCallback(self._get, request)
134+ self.deferred.addCallback(self._delayedRender, request)
135+ self.deferred.addErrback(self._errorRender, request)
136+ return NOT_DONE_YET
137
138 def render_DELETE(self, request):
139 '''
140@@ -277,7 +275,7 @@
141 LOG.debug('Envrionment getChild with name: "%s"' % name)
142 return self
143
144- def _get(self, request):
145+ def _get(self, environment, request):
146 '''
147 Returns the details of a single environment
148 :param request: A Twisted request object
149@@ -286,9 +284,9 @@
150
151 try:
152 env_conf_yaml = storage.get_environment(self.username, self.name)
153- except EnvironmentNotFound:
154- request.setResponseCode(404)
155- return {'error': {'EnvironmentNotFound': "Environment not found"}}
156+ except IOError:
157+ request.setResponseCode(404, "Environment not found")
158+ raise EnvironmentNotFound("Environment not ready yet.")
159
160 env_conf = yaml.load(env_conf_yaml)
161
162@@ -297,8 +295,6 @@
163 env_conf['environments'][self.name]}
164 single_environment['environment']['name'] = self.name
165
166- del single_environment['environment']['authorized-keys-path']
167-
168 request.setResponseCode(200)
169 return single_environment
170
171@@ -312,7 +308,6 @@
172 provider = environment.get_machine_provider()
173 yield provider.destroy_environment()
174
175- storage.delete_environment( # #@UndefinedVariable
176- self.username, self.name)
177+ storage.delete_environment(self.username, environment.name, environment.dns_name)
178
179 request.setResponseCode(204)
180
181=== modified file 'jrapi/storage/dummy.py'
182--- jrapi/storage/dummy.py 2012-07-14 14:53:32 +0000
183+++ jrapi/storage/dummy.py 2012-08-26 19:06:19 +0000
184@@ -16,14 +16,11 @@
185 # You should have received a copy of the GNU Affero General Public License
186 # along with this program. If not, see <http://www.gnu.org/licenses/>.
187
188-from juju import errors
189-
190 DUMMY_ENV = """
191 environments:
192 dummy:
193 type: dummy
194 foo: bar
195- authorized-keys-path: /should/not/see/id_rsa
196 """
197
198 DUMMY_ENV_JSON ="""{
199@@ -44,7 +41,7 @@
200 if env_name == 'dummy':
201 return DUMMY_ENV
202 else:
203- raise errors.EnvironmentNotFound('Environment Not found')
204+ raise IOError
205
206 def get_environments(self, username):
207 return [{'name':'sample'}]
208
209=== modified file 'jrapi/storage/filesystem.py'
210--- jrapi/storage/filesystem.py 2012-07-24 17:17:20 +0000
211+++ jrapi/storage/filesystem.py 2012-08-26 19:06:19 +0000
212@@ -22,7 +22,6 @@
213 import subprocess
214
215 from jrapi.config import CONF
216-from jrapi.common import ssh_keygen
217 from jrapi.openstack.common import cfg
218
219 from jrapi.storage.errors import BadStoreConfiguration
220@@ -71,12 +70,12 @@
221 # LOG.error(reason)
222 # raise IOError
223
224-# try:
225-# os.makedirs(env_path)
226-# except IOError:
227-# reason = _("Unable to create user dir: %s") % user_path
228-# LOG.error(reason)
229-# raise
230+ try:
231+ os.makedirs(env_path)
232+ except IOError:
233+ reason = _("Unable to create user dir: %s") % user_path
234+ LOG.error(reason)
235+ raise
236
237
238 env_conf_file = os.path.join(env_path, "environments.yaml")
239@@ -118,15 +117,14 @@
240
241 return environments
242
243-
244- def delete_environment(self, username, env_name):
245+ def delete_environment(self, username, env_name, ip):
246 user_path = self._get_user_path(username)
247 env_path = os.path.join(user_path, env_name)
248
249 user_known_host_file = os.path.join(env_path, "known_host")
250 user_identity_file = os.path.join(env_path, "id_rsa")
251
252- self.remove_ssh_config(username, env_name)
253+ subprocess.Popen('ssh-keygen -R %s' % ip)
254
255 if os.path.exists(env_path):
256 try:
257@@ -145,45 +143,8 @@
258 LOG.error(reason)
259 raise IOError
260
261-
262-
263- def add_sshkey(self, username, env_name):
264- user_path = self._get_user_path(username)
265- env_path = os.path.join(user_path, env_name)
266- key_file = os.path.join(user_path, env_name, "id_rsa")
267-
268- try:
269- os.makedirs(env_path)
270- except IOError:
271- reason = "Unable to create user dir: %s" % user_path
272- LOG.error(reason)
273- raise
274-
275- if not os.path.exists(key_file):
276- key_dict = ssh_keygen()
277-
278- private_key_fp = open("%s/id_rsa" % env_path, "w")
279- private_key_fp.write(key_dict['private_key'])
280- private_key_fp.close()
281-
282- public_key_fp = open("%s/id_rsa.pub" % env_path, "w")
283- public_key_fp.write(key_dict['public_key'])
284- public_key_fp.close()
285-
286- os.chmod("%s/id_rsa" % env_path, 0600)
287- os.chmod("%s/id_rsa.pub" % env_path, 0600)
288-
289- return key_file
290-
291-
292 def add_known_host(self, username, env_name, ip):
293- user_path = self._get_user_path(username)
294- env_path = os.path.join(user_path, env_name)
295-
296- known_host_file = os.path.join(env_path, "known_host")
297-
298- if os.path.exists(known_host_file):
299- return
300+ known_host_file = os.path.join(self.datadir, ".ssh/known_host")
301
302 output = subprocess.check_output(
303 ["ssh-keyscan", "-H", "-t", "ecdsa-sha2-nistp256", ip],
304@@ -195,37 +156,3 @@
305 except IOError as e:
306 raise
307
308- def add_ssh_config(self, username, env_name, ip):
309- user_path = self._get_user_path(username)
310- env_path = os.path.join(user_path, env_name)
311-
312- ssh_config_file = os.path.join(self.datadir, ".ssh/config")
313- user_known_host_file = os.path.join(env_path, "known_host")
314- user_identity_file = os.path.join(env_path, "id_rsa")
315-
316- config_block = """Host %s
317- UserKnownHostsFile=%s
318- IdentityFile=%s
319-""" % (ip, user_known_host_file, user_identity_file)
320-
321- with open(ssh_config_file, "r+") as f:
322- old = f.readlines() # read everything in the file
323- if "Host %s\n" % ip in old:
324- return
325- else:
326- f.seek(0) # rewind
327- f.write(config_block + "".join(old))
328-
329- def remove_ssh_config(self, username, env_name):
330- user_path = self._get_user_path(username)
331- env_path = os.path.join(user_path, env_name)
332-
333- ssh_config_file = os.path.join(self.datadir, ".ssh/config")
334- user_known_host_file = os.path.join(env_path, "known_host")
335- user_identity_file = os.path.join(env_path, "id_rsa")
336-
337- with open(ssh_config_file, "r+") as f:
338- old = f.read()
339- old = re.sub(r'.* #%s' % env_path, '', old)
340- f.seek(0)
341- f.write(old)
342
343=== modified file 'tests/test_environment.py'
344--- tests/test_environment.py 2012-07-14 14:53:32 +0000
345+++ tests/test_environment.py 2012-08-26 19:06:19 +0000
346@@ -2,7 +2,6 @@
347
348 from juju.environment.tests.test_config import EnvironmentsConfigTestBase
349
350-from jrapi.auth import JRAPIAuthSessionWrapper
351 from jrapi.apiroot import APIRoot
352 from jrapi.storage.dummy import DUMMY_ENV, DUMMY_ENV_JSON
353
354@@ -14,16 +13,11 @@
355 @inlineCallbacks
356 def setUp(self):
357 yield super(EnvironmentTest, self).setUp()
358- self.web = DummySite(JRAPIAuthSessionWrapper(APIRoot()))
359+ self.web = DummySite(APIRoot())
360 self.write_config(DUMMY_ENV)
361 self.config.load()
362
363 @inlineCallbacks
364- def test_bootstrap(self):
365- response = yield self.web.put("/environments/", content=DUMMY_ENV_JSON)
366- self.assertEqual(response.responseCode, 201),
367-
368- @inlineCallbacks
369 def test_list(self):
370 response = yield self.web.get("/environments/")
371 self.assertEqual(response.responseCode, 200),
372@@ -45,23 +39,8 @@
373 def test_get_not_existing(self):
374 response = yield self.web.get("/environments/not_existing/")
375 self.assertEqual(response.responseCode, 404),
376- self.assertEqual(response.value(), """{
377- "error": {
378- "EnvironmentNotFound": "Environment not found"
379- }
380-}""")
381-
382-# @inlineCallbacks
383-# def test_zdestroy(self):
384-# response = yield self.web.delete("/environments/dummy/")
385-# self.assertEqual(response.responseCode, 204),
386-
387-# @inlineCallbacks
388-# def test_zdestroy_not_existing(self):
389-# response = yield self.web.delete("/environments/not_existing/")
390-# self.assertEqual(response.responseCode, 404),
391-# self.assertEqual(response.value(), """{
392-# "error": {
393-# "EnvironmentNotFound": "juju environment not found: Environment ready yet."
394-# }
395-#}""")
396+
397+ @inlineCallbacks
398+ def test_zdestroy_not_existing(self):
399+ response = yield self.web.delete("/environments/not_existing/")
400+ self.assertEqual(response.responseCode, 404),

Subscribers

People subscribed via source and target branches