Merge lp:~sbaldassin/snappy-ecosystem-tests/merge_builder_snapd into lp:snappy-ecosystem-tests

Proposed by Santiago Baldassin
Status: Merged
Approved by: Heber Parrucci
Approved revision: 50
Merged at revision: 49
Proposed branch: lp:~sbaldassin/snappy-ecosystem-tests/merge_builder_snapd
Merge into: lp:snappy-ecosystem-tests
Diff against target: 467 lines (+135/-182)
7 files modified
snappy_ecosystem_tests/helpers/snapcraft/build_snap.py (+0/-161)
snappy_ecosystem_tests/helpers/snapcraft/client.py (+123/-4)
snappy_ecosystem_tests/helpers/snapd/snapd.py (+5/-5)
snappy_ecosystem_tests/helpers/test_base.py (+0/-1)
snappy_ecosystem_tests/tests/test_install_private_snap.py (+2/-7)
snappy_ecosystem_tests/utils/ssh.py (+5/-3)
snappy_ecosystem_tests/utils/user.py (+0/-1)
To merge this branch: bzr merge lp:~sbaldassin/snappy-ecosystem-tests/merge_builder_snapd
Reviewer Review Type Date Requested Status
Heber Parrucci (community) Approve
platform-qa-bot continuous-integration Approve
Review via email: mp+320163@code.launchpad.net

Commit message

Merge Snapcraft and SnapBuilder in a single class

Description of the change

This mp merge Snapcraft and SnapBuilder in a single class as they represent the same class. We'll need to instantiate two different objects, pointing to the builder container and the snapcraft container respectively

To post a comment you must log in.
Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Heber Parrucci (heber013) wrote :

Looks good. One comment inline

review: Needs Fixing
48. By Santiago Baldassin

Addressing comments from the reviews

Revision history for this message
Santiago Baldassin (sbaldassin) wrote :

Thanks Heber. Comments addressed

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Heber Parrucci (heber013) wrote :

There are some tests failing in this branch that pass on trunk, see log http://paste.ubuntu.com/24215045/

Seems that the time between snaps registration is broken.

review: Needs Fixing
49. By Santiago Baldassin

Merge from trunk

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Approve (continuous-integration)
50. By Santiago Baldassin

Merge from trunk

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Heber Parrucci (heber013) wrote :

Tests are passing properly now http://paste.ubuntu.com/24269814/.
Let's land it.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== removed file 'snappy_ecosystem_tests/helpers/snapcraft/build_snap.py'
2--- snappy_ecosystem_tests/helpers/snapcraft/build_snap.py 2017-03-16 11:40:13 +0000
3+++ snappy_ecosystem_tests/helpers/snapcraft/build_snap.py 1970-01-01 00:00:00 +0000
4@@ -1,161 +0,0 @@
5-# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
6-
7-#
8-# Snappy Ecosystem Tests
9-# Copyright (C) 2017 Canonical
10-#
11-# This program is free software: you can redistribute it and/or modify
12-# it under the terms of the GNU General Public License as published by
13-# the Free Software Foundation, either version 3 of the License, or
14-# (at your option) any later version.
15-#
16-# This program is distributed in the hope that it will be useful,
17-# but WITHOUT ANY WARRANTY; without even the implied warranty of
18-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19-# GNU General Public License for more details.
20-#
21-# You should have received a copy of the GNU General Public License
22-# along with this program. If not, see <http://www.gnu.org/licenses/>.
23-#
24-
25-"""Module to build a snap in a remote machine."""
26-
27-import os
28-from pathlib import PurePath
29-
30-from snappy_ecosystem_tests.utils.ssh import SSHManager
31-
32-COMMANDS_SETUP = [
33- 'apt update',
34- 'apt dist-upgrade -y',
35- 'apt install snapcraft -y'
36-]
37-SNAPCRAFT_YAML = """\
38-name: {snap_name}
39-version: {version}
40-summary: {summary}
41-description: |
42- {description}
43-
44-grade: {grade}
45-confinement: {confinement}
46-
47-parts:
48- {snap_name}:
49- plugin: nil
50-
51-apps:
52- {snap_name}:
53- command: echo ok
54-"""
55-SUMMARY_SNAP_DEFAULT = 'A test snap.'
56-DESCRIPTION_SNAP_DEFAULT = 'A very awesome test snap.'
57-GRADE_SNAP_DEFAULT = 'stable'
58-CONFINEMENT_SNAP_DEFAULT = 'strict'
59-
60-
61-class SnapBuilder:
62- """Class to build a snap on a remote machine and download its content."""
63- def __init__(self, hostname, username, port=22):
64- self.hostname = hostname
65- self.username = username
66- self.port = port
67-
68- @property
69- def ssh(self):
70- """Property tu ensure we get an active connection for every command
71- execution over ssh"""
72- return SSHManager.get_instance(self.hostname, self.username, self.port)
73-
74- def run_command_ssh(self, command, cwd=''):
75- """Run command over ssh with optional cwd."""
76- if cwd:
77- command = 'cd {}; {}'.format(cwd, command)
78- return self.ssh.exec_command(command)
79-
80- def is_host_setup(self):
81- """Return bool representing whether the remote host is setup by
82- checking if snapcraft package is installed."""
83- try:
84- self.ssh.exec_command('which snapcraft')
85- return True
86- except ValueError:
87- return False
88-
89- def setup_host(self):
90- """Setup the host to build a snap, currently only installs
91- snapcraft."""
92- for command in COMMANDS_SETUP:
93- self.ssh.exec_command(command)
94-
95- def build(self, name, version, summary=SUMMARY_SNAP_DEFAULT,
96- description=DESCRIPTION_SNAP_DEFAULT, grade=GRADE_SNAP_DEFAULT,
97- confinement=CONFINEMENT_SNAP_DEFAULT):
98- """Build a new snap in the remote host and return its remote path.
99-
100- :param name: name of the snap to build.
101- :param version: version number for the snap to build.
102- :param summary: short summary of the snap to build.
103- :param description: long description of the snap.
104- :param grade: stability grade of the snap e.g. stable or devel.
105- :param confinement: confinement policy for the snap e.g.
106- classic, devmode or strict.
107- :raises ValueError: If an error is occurred during snap build.
108- :return: Remote path of the newly build snap package.
109- """
110- if not self.is_host_setup():
111- self.setup_host()
112- tempdir = self.ssh.exec_command('mktemp -d')
113- self.run_command_ssh('mkdir snap', cwd=tempdir)
114- self.run_command_ssh('echo "{}" > snap/snapcraft.yaml'.format(
115- SNAPCRAFT_YAML.format(
116- snap_name=name,
117- version=version,
118- summary=summary,
119- description=description,
120- grade=grade,
121- confinement=confinement
122- )
123- ), cwd=tempdir)
124- self.run_command_ssh('snapcraft', cwd=tempdir)
125- return os.path.join(
126- tempdir,
127- '{name}_{version}_{arch}.snap'.format(
128- name=name,
129- version=version,
130- arch=self.ssh.exec_command('dpkg --print-architecture')
131- )
132- )
133-
134- def build_and_pull(self, name, version, summary=SUMMARY_SNAP_DEFAULT,
135- description=DESCRIPTION_SNAP_DEFAULT,
136- grade=GRADE_SNAP_DEFAULT,
137- confinement=CONFINEMENT_SNAP_DEFAULT,
138- output_location='.'):
139- """Build a snap based on the provided arguments and download it.
140-
141- :param name: name of the snap to build.
142- :param version: version number for the snap to build.
143- :param summary: short summary of the snap to build.
144- :param description: long description of the snap.
145- :param grade: stability grade of the snap e.g. stable or devel.
146- :param confinement: confinement policy for the snap e.g.
147- classic, devmode or strict.
148- :param output_location: Local location to download the newly built
149- snap to. Defaults to pwd.
150- :raises ValueError: If an error is occurred during snap build.
151- :return: Local path of the newly built and downloaded snap package.
152- """
153- remote_snap_path = self.build(
154- name=name,
155- version=version,
156- summary=summary,
157- description=description,
158- grade=grade,
159- confinement=confinement
160- )
161- output_path_absolute = os.path.abspath(
162- os.path.join(output_location, PurePath(remote_snap_path).name)
163- )
164- self.ssh.pull(remote_snap_path, output_path_absolute)
165- return output_path_absolute
166
167=== modified file 'snappy_ecosystem_tests/helpers/snapcraft/client.py'
168--- snappy_ecosystem_tests/helpers/snapcraft/client.py 2017-03-16 16:42:44 +0000
169+++ snappy_ecosystem_tests/helpers/snapcraft/client.py 2017-03-22 12:29:23 +0000
170@@ -21,9 +21,12 @@
171 """Snapcraft client helpers"""
172
173 import logging
174+import os
175 import subprocess
176 import time
177
178+from pathlib import PurePath
179+
180 from snappy_ecosystem_tests.models.snap import Snap
181 from snappy_ecosystem_tests.utils.commands import build_command
182 from snappy_ecosystem_tests.utils.filters import filter_list
183@@ -61,6 +64,34 @@
184 SNAPCRAFT_CONFIG_FILE_PATH = '~/.config/snapcraft/snapcraft.cfg'
185
186
187+COMMANDS_SETUP = [
188+ 'apt update',
189+ 'apt dist-upgrade -y',
190+ 'apt install snapcraft -y'
191+]
192+SNAPCRAFT_YAML = """\
193+name: {snap_name}
194+version: {version}
195+summary: {summary}
196+description: |
197+ {description}
198+
199+grade: {grade}
200+confinement: {confinement}
201+
202+parts:
203+ {snap_name}:
204+ plugin: nil
205+
206+apps:
207+ {snap_name}:
208+ command: echo ok
209+"""
210+SUMMARY_SNAP_DEFAULT = 'A test snap.'
211+DESCRIPTION_SNAP_DEFAULT = 'A very awesome test snap.'
212+GRADE_SNAP_DEFAULT = 'stable'
213+CONFINEMENT_SNAP_DEFAULT = 'strict'
214+
215 class Snapcraft:
216 """Contain Snapcraft specific functionality to use via command
217 line interface"""
218@@ -75,7 +106,22 @@
219 execution over ssh"""
220 return SSHManager.get_instance(HOSTNAME, USERNAME, PORT)
221
222- def _run_snapcraft_command_ssh(self, command, debug=True):
223+ def is_host_setup(self):
224+ """Return bool representing whether the remote host is setup by
225+ checking if snapcraft package is installed."""
226+ try:
227+ self.ssh.run_command('which snapcraft')
228+ return True
229+ except ValueError:
230+ return False
231+
232+ def setup_host(self):
233+ """Setup the host to build a snap, currently only installs
234+ snapcraft."""
235+ for command in COMMANDS_SETUP:
236+ self.ssh.run_command(command)
237+
238+ def _run_snapcraft_command_ssh(self, command='', debug=True, cwd=''):
239 """
240 Run snapcraft command via ssh
241 :param command: the command to be executed.
242@@ -87,7 +133,7 @@
243 command = build_snapcraft_command(command)
244 if debug:
245 command += ' -d'
246- return self.ssh.exec_command(command)
247+ return self.ssh.run_command(command, cwd=cwd)
248
249 def assert_logged_in(self):
250 """Assert that an user is logged.
251@@ -100,7 +146,7 @@
252 def is_logged_in(self):
253 """Return bool representing if the user is logged into snapcraft."""
254 try:
255- output = self.ssh.exec_command(
256+ output = self.ssh.run_command(
257 'cat %s' % SNAPCRAFT_CONFIG_FILE_PATH)
258 return output is not ''
259 except ValueError:
260@@ -123,7 +169,7 @@
261 :param email: the SSO email
262 :param password: the email password
263 """
264- self.ssh.exec_command(
265+ self.ssh.run_command(
266 COMMANDS_LOGIN.format(email=email, password=password,
267 snapcraft=PATH_SNAPCRAFT))
268 return self.is_logged_in()
269@@ -185,6 +231,79 @@
270 LOGGER.info('Snap %s registered successfully!!!', snap_name)
271 return True
272
273+ def build(self, name, version, summary=SUMMARY_SNAP_DEFAULT,
274+ description=DESCRIPTION_SNAP_DEFAULT, grade=GRADE_SNAP_DEFAULT,
275+ confinement=CONFINEMENT_SNAP_DEFAULT):
276+ """Build a new snap in the remote host and return its remote path.
277+
278+ :param name: name of the snap to build.
279+ :param version: version number for the snap to build.
280+ :param summary: short summary of the snap to build.
281+ :param description: long description of the snap.
282+ :param grade: stability grade of the snap e.g. stable or devel.
283+ :param confinement: confinement policy for the snap e.g.
284+ classic, devmode or strict.
285+ :raises ValueError: If an error is occurred during snap build.
286+ :return: Remote path of the newly build snap package.
287+ """
288+ if not self.is_host_setup():
289+ self.setup_host()
290+ tempdir = self.ssh.run_command('mktemp -d')
291+ self.ssh.run_command('mkdir snap', cwd=tempdir)
292+ self.ssh.run_command(
293+ 'echo "{}" > snap/snapcraft.yaml'.format(
294+ SNAPCRAFT_YAML.format(
295+ snap_name=name,
296+ version=version,
297+ summary=summary,
298+ description=description,
299+ grade=grade,
300+ confinement=confinement
301+ )
302+ ), cwd=tempdir)
303+ self._run_snapcraft_command_ssh(cwd=tempdir)
304+ return os.path.join(
305+ tempdir,
306+ '{name}_{version}_{arch}.snap'.format(
307+ name=name,
308+ version=version,
309+ arch=self.ssh.run_command('dpkg --print-architecture')
310+ )
311+ )
312+
313+ def build_and_pull(self, name, version, summary=SUMMARY_SNAP_DEFAULT,
314+ description=DESCRIPTION_SNAP_DEFAULT,
315+ grade=GRADE_SNAP_DEFAULT,
316+ confinement=CONFINEMENT_SNAP_DEFAULT,
317+ output_location='.'):
318+ """Build a snap based on the provided arguments and download it.
319+
320+ :param name: name of the snap to build.
321+ :param version: version number for the snap to build.
322+ :param summary: short summary of the snap to build.
323+ :param description: long description of the snap.
324+ :param grade: stability grade of the snap e.g. stable or devel.
325+ :param confinement: confinement policy for the snap e.g.
326+ classic, devmode or strict.
327+ :param output_location: Local location to download the newly built
328+ snap to. Defaults to pwd.
329+ :raises ValueError: If an error is occurred during snap build.
330+ :return: Local path of the newly built and downloaded snap package.
331+ """
332+ remote_snap_path = self.build(
333+ name=name,
334+ version=version,
335+ summary=summary,
336+ description=description,
337+ grade=grade,
338+ confinement=confinement
339+ )
340+ output_path_absolute = os.path.abspath(
341+ os.path.join(output_location, PurePath(remote_snap_path).name)
342+ )
343+ self.ssh.pull(remote_snap_path, output_path_absolute)
344+ return output_path_absolute
345+
346
347 def build_snapcraft_command(*args, base_command=PATH_SNAPCRAFT):
348 """
349
350=== modified file 'snappy_ecosystem_tests/helpers/snapd/snapd.py'
351--- snappy_ecosystem_tests/helpers/snapd/snapd.py 2017-03-19 15:27:11 +0000
352+++ snappy_ecosystem_tests/helpers/snapd/snapd.py 2017-03-22 12:29:23 +0000
353@@ -74,7 +74,7 @@
354 command = '{} {}'.format(PATH_SNAP, command)
355 if cwd:
356 command = '{}; {}'.format(cwd, command)
357- return self.ssh.exec_command(command)
358+ return self.ssh.run_command(command)
359
360 def login(self, email, password):
361 """Login to snapd.
362@@ -82,15 +82,15 @@
363 :param email: Ubuntu SSO account email address.
364 :param password: Ubuntu SSO account password.
365 """
366- self.ssh.exec_command(COMMANDS_LOGIN.format(email=email,
367- password=password))
368+ self.ssh.run_command(COMMANDS_LOGIN.format(email=email,
369+ password=password))
370 return self.is_logged_in(email)
371
372 def is_logged_in(self, email):
373 """Return bool representing if the user is logged into snapd."""
374 try:
375 return json.loads(
376- self.ssh.exec_command(
377+ self.ssh.run_command(
378 'cat ~/.snap/auth.json')).get('email') == email
379 except ValueError:
380 return False
381@@ -108,7 +108,7 @@
382 """
383 command = COMMAND_DOWNLOAD.format(snap=snap, channel=channel)
384 self.run_snapd_command_ssh(command,
385- cwd=self.ssh.exec_command('mktemp -d'))
386+ cwd=self.ssh.run_command('mktemp -d'))
387
388 def install(self, snap, channel=CHANNEL_STABLE):
389 """Install the requested snap."""
390
391=== modified file 'snappy_ecosystem_tests/helpers/test_base.py'
392--- snappy_ecosystem_tests/helpers/test_base.py 2017-03-08 17:29:20 +0000
393+++ snappy_ecosystem_tests/helpers/test_base.py 2017-03-22 12:29:23 +0000
394@@ -15,7 +15,6 @@
395 # along with this program. If not, see <http://www.gnu.org/licenses/>.
396
397 """Base Snappy Ecosystem test"""
398-
399 import testscenarios
400 import testtools
401
402
403=== modified file 'snappy_ecosystem_tests/tests/test_install_private_snap.py'
404--- snappy_ecosystem_tests/tests/test_install_private_snap.py 2017-03-17 20:50:55 +0000
405+++ snappy_ecosystem_tests/tests/test_install_private_snap.py 2017-03-22 12:29:23 +0000
406@@ -19,16 +19,12 @@
407 #
408
409 """Tests for Installing private snaps."""
410-
411+from snappy_ecosystem_tests.helpers.snapcraft.client import Snapcraft
412 from snappy_ecosystem_tests.helpers.snapd.snapd import Snapd
413 from snappy_ecosystem_tests.helpers.store_apis.rest_apis import Store
414-from snappy_ecosystem_tests.helpers.snapcraft.build_snap import SnapBuilder
415 from snappy_ecosystem_tests.helpers.test_base import SnappyEcosystemTestCase
416 from snappy_ecosystem_tests.tests.commons import get_random_snap_name
417 from snappy_ecosystem_tests.utils.storeconfig import get_store_credentials
418-from snappy_ecosystem_tests.utils.user import (
419- get_snapcraft_remote_host_credentials
420-)
421
422
423 class RegisterInstallPrivateSnapTestCase(SnappyEcosystemTestCase):
424@@ -42,8 +38,7 @@
425 self.addCleanup(self.snapd.logout, email)
426 self.store.login(email, password)
427 self.addCleanup(self.store.logout)
428- self.snap_builder = SnapBuilder(
429- *get_snapcraft_remote_host_credentials())
430+ self.snap_builder = Snapcraft()
431
432 def test_upload_and_install_private_snap(self):
433 """Test to register and upload a private snap via the REST API
434
435=== modified file 'snappy_ecosystem_tests/utils/ssh.py'
436--- snappy_ecosystem_tests/utils/ssh.py 2017-03-09 17:24:06 +0000
437+++ snappy_ecosystem_tests/utils/ssh.py 2017-03-22 12:29:23 +0000
438@@ -30,12 +30,14 @@
439 class SSHClient(paramiko.SSHClient):
440 """Extended SSHClient."""
441
442- def exec_command(self, command, bufsize=-1, timeout=None, get_pty=False,
443- environment=None):
444+ def run_command(self, command, bufsize=-1, timeout=None,
445+ get_pty=False, cwd=''):
446 """Execute the given command over ssh."""
447+ if cwd:
448+ command = 'cd {}; {}'.format(cwd, command)
449 _, stdout, stderr = super().exec_command(
450 command, bufsize, timeout,
451- get_pty, environment=environment)
452+ get_pty)
453 if stdout.channel.recv_exit_status() != 0:
454 raise ValueError(stderr.read().decode().strip())
455 response = stdout.read().decode().strip()
456
457=== modified file 'snappy_ecosystem_tests/utils/user.py'
458--- snappy_ecosystem_tests/utils/user.py 2017-03-09 10:41:13 +0000
459+++ snappy_ecosystem_tests/utils/user.py 2017-03-22 12:29:23 +0000
460@@ -27,7 +27,6 @@
461
462 MANAGER = get_manager(os.environ['target'])
463
464-
465 def get_snapd_remote_host_credentials():
466 """Return credentials for snapd remote machine, to run commands on."""
467 _ip = MANAGER.driver.get_ip(USER_CONFIG_STACK.get(

Subscribers

People subscribed via source and target branches

to all changes: