Merge lp:~canonical-platform-qa/snappy-ecosystem-tests/export-staging-variables-ssh into lp:snappy-ecosystem-tests
- export-staging-variables-ssh
- Merge into trunk
Status: | Superseded |
---|---|
Proposed branch: | lp:~canonical-platform-qa/snappy-ecosystem-tests/export-staging-variables-ssh |
Merge into: | lp:snappy-ecosystem-tests |
Diff against target: |
1658 lines (+1185/-111) 30 files modified
README.rst (+12/-7) pylint.cfg (+4/-4) requirements-unit-tests.txt (+1/-1) requirements.txt (+2/-1) run_checks (+2/-2) run_system_tests (+1/-0) snappy_ecosystem_tests/configs/ecosystem_tests.cfg (+8/-3) snappy_ecosystem_tests/environment/__init__.py (+19/-0) snappy_ecosystem_tests/environment/constants.py (+82/-0) snappy_ecosystem_tests/environment/data/__init__.py (+19/-0) snappy_ecosystem_tests/environment/data/snapcraft.py (+21/-0) snappy_ecosystem_tests/environment/data/snapd.py (+88/-0) snappy_ecosystem_tests/environment/managers.py (+142/-0) snappy_ecosystem_tests/environment/setup.py (+46/-0) snappy_ecosystem_tests/helpers/snapcraft/client.py (+164/-23) snappy_ecosystem_tests/helpers/snapd/snapd.py (+5/-1) snappy_ecosystem_tests/helpers/snapd/staging_builder.py (+11/-4) snappy_ecosystem_tests/helpers/store_apis/rest_apis.py (+51/-6) snappy_ecosystem_tests/models/__init__.py (+19/-0) snappy_ecosystem_tests/models/snap.py (+39/-0) snappy_ecosystem_tests/run.py (+24/-14) snappy_ecosystem_tests/tests/test_register_snap.py (+116/-0) snappy_ecosystem_tests/unittests/test_filters.py (+113/-0) snappy_ecosystem_tests/unittests/test_snapcraft.py (+0/-31) snappy_ecosystem_tests/utils/commands.py (+31/-0) snappy_ecosystem_tests/utils/filters.py (+51/-0) snappy_ecosystem_tests/utils/ssh.py (+7/-2) snappy_ecosystem_tests/utils/store_versions.py (+74/-0) snappy_ecosystem_tests/utils/storeconfig.py (+2/-2) snappy_ecosystem_tests/utils/user.py (+31/-10) |
To merge this branch: | bzr merge lp:~canonical-platform-qa/snappy-ecosystem-tests/export-staging-variables-ssh |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
platform-qa-bot | continuous-integration | Approve | |
Snappy ecosystem tests developer | Pending | ||
Review via email: mp+318728@code.launchpad.net |
This proposal has been superseded by a proposal from 2017-03-02.
Commit message
Export staging variables over ssh.
Description of the change
Ensure staging environment variables are available over ssh.
platform-qa-bot (platform-qa-bot) wrote : | # |
Omer Akram (om26er) wrote : | # |
By default ssh is secure and does not allow any random environment variable to be exported. So the ssh config within the container also needs to be updated to allow these variables to be exported.
That can be enabled by container setup script. We basically need to append staging environment variable names to AcceptEnv key inside /etc/ssh/
For testing just update the AcceptEnv line in the container to
AcceptEnv *
Omer Akram (om26er) wrote : | # |
(and restart the container)
- 25. By Omer Akram
-
merge with trunk
- 26. By Omer Akram
-
Finish rebase
- 27. By Omer Akram
-
fix
- 28. By Omer Akram
-
fix per suggestion
- 29. By Omer Akram
-
merge with pre-req
- 30. By Omer Akram
-
ignore arguments-differ pylint warning
- 31. By Omer Akram
-
merge with trunk
Unmerged revisions
Preview Diff
1 | === modified file 'README.rst' |
2 | --- README.rst 2017-02-22 17:40:11 +0000 |
3 | +++ README.rst 2017-03-02 10:45:12 +0000 |
4 | @@ -69,17 +69,22 @@ |
5 | [user] |
6 | user_email=^USER_NAME^ |
7 | user_password=^USER_PASSWORD^ |
8 | -hostname_remote=^SSH_HOSTNAME^ |
9 | -username_remote=^SSH_USERNAME^ |
10 | -port_remote=^SSH_PORT^ |
11 | +snapd_hostname_remote=^SNAPD_SSH_HOSTNAME^ |
12 | +snapd_username_remote=^SNAPD_SSH_USERNAME^ |
13 | +snapd_port_remote=^SNAPD_SSH_PORT^ |
14 | +snapcraft_hostname_remote=^SNAPCRAFT_SSH_HOSTNAME^ |
15 | +snapcraft_username_remote=^SNAPCRAFT_SSH_USERNAME^ |
16 | +snapcraft_port_remote=^SNAPCRAFT_SSH_PORT^ |
17 | |
18 | option 2 - Set the following environment variables: |
19 | user_email=^USER_NAME^ |
20 | user_password=^USER_PASSWORD^ |
21 | -hostname_remote=^SSH_HOSTNAME^ |
22 | -username_remote=^SSH_USERNAME^ |
23 | -port_remote=^SSH_PORT^ |
24 | - |
25 | +snapd_hostname_remote=^SNAPD_SSH_HOSTNAME^ |
26 | +snapd_username_remote=^SNAPD_SSH_USERNAME^ |
27 | +snapd_port_remote=^SNAPD_SSH_PORT^ |
28 | +snapcraft_hostname_remote=^SNAPCRAFT_SSH_HOSTNAME^ |
29 | +snapcraft_username_remote=^SNAPCRAFT_SSH_USERNAME^ |
30 | +snapcraft_port_remote=^SNAPCRAFT_SSH_PORT^ |
31 | |
32 | Changing store: |
33 | =============== |
34 | |
35 | === modified file 'pylint.cfg' |
36 | --- pylint.cfg 2017-02-21 13:46:08 +0000 |
37 | +++ pylint.cfg 2017-03-02 10:45:12 +0000 |
38 | @@ -169,10 +169,10 @@ |
39 | inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$ |
40 | |
41 | # Regular expression matching correct function names |
42 | -function-rgx=[a-z_][a-z0-9_]{2,30}$ |
43 | +function-rgx=[a-z_][a-z0-9_]{2,40}$ |
44 | |
45 | # Naming hint for function names |
46 | -function-name-hint=[a-z_][a-z0-9_]{2,30}$ |
47 | +function-name-hint=[a-z_][a-z0-9_]{2,40}$ |
48 | |
49 | # Regular expression matching correct attribute names |
50 | attr-rgx=[a-z_][a-z0-9_]{2,30}$ |
51 | @@ -181,10 +181,10 @@ |
52 | attr-name-hint=[a-z_][a-z0-9_]{2,30}$ |
53 | |
54 | # Regular expression matching correct method names |
55 | -method-rgx=[a-z_][a-z0-9_]{2,30}$|setUp|tearDown |
56 | +method-rgx=[a-z_][a-z0-9_]{2,30}$|setUp|tearDown|test_* |
57 | |
58 | # Naming hint for method names |
59 | -method-name-hint=[a-z_][a-z0-9_]{2,30}$|setUp|tearDown |
60 | +method-name-hint=[a-z_][a-z0-9_]{2,30}$|setUp|tearDown|test_* |
61 | |
62 | # Regular expression matching correct class attribute names |
63 | class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ |
64 | |
65 | === modified file 'requirements-unit-tests.txt' |
66 | --- requirements-unit-tests.txt 2017-02-10 18:18:45 +0000 |
67 | +++ requirements-unit-tests.txt 2017-03-02 10:45:12 +0000 |
68 | @@ -1,1 +1,1 @@ |
69 | -unittest2 |
70 | +testtools |
71 | |
72 | === modified file 'requirements.txt' |
73 | --- requirements.txt 2017-02-21 21:07:33 +0000 |
74 | +++ requirements.txt 2017-03-02 10:45:12 +0000 |
75 | @@ -14,7 +14,8 @@ |
76 | pexpect |
77 | pymacaroons==0.9.2 |
78 | requests-toolbelt==0.6.0 |
79 | -#chromedriver_installer |
80 | pylxd |
81 | pyyaml |
82 | +retrying |
83 | paramiko |
84 | +chromedriver_installer |
85 | |
86 | === modified file 'run_checks' |
87 | --- run_checks 2017-02-20 13:10:18 +0000 |
88 | +++ run_checks 2017-03-02 10:45:12 +0000 |
89 | @@ -51,9 +51,9 @@ |
90 | |
91 | if [ "$proxy" ]; then |
92 | echo "Using proxy: $proxy to install dependencies" |
93 | - pip install --proxy $proxy -r requirements-unit-tests.txt |
94 | + pip3 install --proxy $proxy -r requirements-unit-tests.txt |
95 | else |
96 | - pip install -r requirements-unit-tests.txt |
97 | + pip3 install -r requirements-unit-tests.txt |
98 | fi |
99 | |
100 | ve_unit_tests/bin/python3 -m unittest discover snappy_ecosystem_tests.unittests |
101 | |
102 | === modified file 'run_system_tests' |
103 | --- run_system_tests 2017-02-13 16:00:04 +0000 |
104 | +++ run_system_tests 2017-03-02 10:45:12 +0000 |
105 | @@ -20,6 +20,7 @@ |
106 | |
107 | . ./mk-venv "$@" |
108 | |
109 | +ve/bin/python3 ./snappy_ecosystem_tests/utils/store_versions.py |
110 | ve/bin/python3 ./snappy_ecosystem_tests/run.py "$@" -c snappy_ecosystem_tests/configs/pytest.cfg --ignore snappy_ecosystem_tests/unittests/ --junitxml snappy-ecosystem-results.xml |
111 | |
112 | deactivate |
113 | |
114 | === modified file 'snappy_ecosystem_tests/configs/ecosystem_tests.cfg' |
115 | --- snappy_ecosystem_tests/configs/ecosystem_tests.cfg 2017-02-10 19:20:45 +0000 |
116 | +++ snappy_ecosystem_tests/configs/ecosystem_tests.cfg 2017-03-02 10:45:12 +0000 |
117 | @@ -1,7 +1,5 @@ |
118 | -[web-ui] |
119 | +[selenium] |
120 | browser=chrome |
121 | -stage_url=https://myapps.developer.staging.ubuntu.com/ |
122 | -production_url=https://myapps.developer.ubuntu.com/ |
123 | |
124 | [store] |
125 | # store to use in tests. Possible values: staging or production |
126 | @@ -12,9 +10,16 @@ |
127 | upload=https://upload.apps.staging.ubuntu.com/ |
128 | sso=https://login.staging.ubuntu.com/api/v2/ |
129 | search=https://search.apps.staging.ubuntu.com/ |
130 | +web=https://myapps.developer.staging.ubuntu.com/ |
131 | |
132 | [production_urls] |
133 | root_api=https://myapps.developer.ubuntu.com/dev/api/ |
134 | upload=https://upload.apps.ubuntu.com/ |
135 | sso=https://login.ubuntu.com/api/v2/ |
136 | search=https://search.apps.ubuntu.com/ |
137 | +web=https://myapps.developer.ubuntu.com/ |
138 | + |
139 | +[time_between_registrations] |
140 | +# Time in seconds between each snap registration |
141 | +staging=10 |
142 | +production=180 |
143 | |
144 | === added directory 'snappy_ecosystem_tests/environment' |
145 | === added file 'snappy_ecosystem_tests/environment/__init__.py' |
146 | --- snappy_ecosystem_tests/environment/__init__.py 1970-01-01 00:00:00 +0000 |
147 | +++ snappy_ecosystem_tests/environment/__init__.py 2017-03-02 10:45:12 +0000 |
148 | @@ -0,0 +1,19 @@ |
149 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
150 | + |
151 | +# |
152 | +# Snappy Ecosystem Tests |
153 | +# Copyright (C) 2017 Canonical |
154 | +# |
155 | +# This program is free software: you can redistribute it and/or modify |
156 | +# it under the terms of the GNU General Public License as published by |
157 | +# the Free Software Foundation, either version 3 of the License, or |
158 | +# (at your option) any later version. |
159 | +# |
160 | +# This program is distributed in the hope that it will be useful, |
161 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
162 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
163 | +# GNU General Public License for more details. |
164 | +# |
165 | +# You should have received a copy of the GNU General Public License |
166 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
167 | +# |
168 | |
169 | === added file 'snappy_ecosystem_tests/environment/constants.py' |
170 | --- snappy_ecosystem_tests/environment/constants.py 1970-01-01 00:00:00 +0000 |
171 | +++ snappy_ecosystem_tests/environment/constants.py 2017-03-02 10:45:12 +0000 |
172 | @@ -0,0 +1,82 @@ |
173 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
174 | + |
175 | +# |
176 | +# Snappy Ecosystem Tests |
177 | +# Copyright (C) 2017 Canonical |
178 | +# |
179 | +# This program is free software: you can redistribute it and/or modify |
180 | +# it under the terms of the GNU General Public License as published by |
181 | +# the Free Software Foundation, either version 3 of the License, or |
182 | +# (at your option) any later version. |
183 | +# |
184 | +# This program is distributed in the hope that it will be useful, |
185 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
186 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
187 | +# GNU General Public License for more details. |
188 | +# |
189 | +# You should have received a copy of the GNU General Public License |
190 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
191 | +# |
192 | + |
193 | +"""Constants used accross the environment setup""" |
194 | + |
195 | +SNAPD = 'snapd' |
196 | +SNAPCRAFT = 'snapcraft' |
197 | + |
198 | +DEPENDENCIES = { |
199 | + SNAPD : [], |
200 | + SNAPCRAFT : [], |
201 | + "shared" : ["expect"] |
202 | +} |
203 | + |
204 | +PROFILES = { |
205 | + "staging":{ |
206 | + SNAPD:{ |
207 | + "channel": "xenial", |
208 | + "package_name": 'snapd', |
209 | + "environment_variables": [ |
210 | + { |
211 | + "name": "UBUNTU_STORE_API_ROOT_URL", |
212 | + "value": "https://myapps.developer.ubuntu.com/dev/api/" |
213 | + }, |
214 | + { |
215 | + "name": "UBUNTU_STORE_UPLOAD_ROOT_URL", |
216 | + "value": "https://upload.apps.ubuntu.com" |
217 | + }, |
218 | + { |
219 | + "name":"UBUNTU_SSO_API_ROOT_URL", |
220 | + "value":"https://login.ubuntu.com/api/v2/" |
221 | + }, |
222 | + { |
223 | + "name":"UBUNTU_STORE_SEARCH_ROOT_URL", |
224 | + "value":"https://search.apps.ubuntu.com/" |
225 | + } |
226 | + ] |
227 | + }, |
228 | + SNAPCRAFT: { |
229 | + "channel": "xenial", |
230 | + "package_name": 'snapcraft', |
231 | + "environment_variables": [ |
232 | + { |
233 | + "name": "UBUNTU_STORE_API_ROOT_URL", |
234 | + "value": "https://myapps.developer.ubuntu.com/dev/api/" |
235 | + }, |
236 | + { |
237 | + "name": "UBUNTU_STORE_UPLOAD_ROOT_URL", |
238 | + "value": "https://upload.apps.ubuntu.com" |
239 | + }, |
240 | + { |
241 | + "name":"UBUNTU_SSO_API_ROOT_URL", |
242 | + "value":"https://login.ubuntu.com/api/v2/" |
243 | + }, |
244 | + { |
245 | + "name":"UBUNTU_STORE_SEARCH_ROOT_URL", |
246 | + "value":"https://search.apps.ubuntu.com/" |
247 | + } |
248 | + ] |
249 | + }, |
250 | + "snapweb":{ |
251 | + "url": "https://myapps.developer.ubuntu.com/" |
252 | + }, |
253 | + } |
254 | +} |
255 | |
256 | === added directory 'snappy_ecosystem_tests/environment/data' |
257 | === added file 'snappy_ecosystem_tests/environment/data/__init__.py' |
258 | --- snappy_ecosystem_tests/environment/data/__init__.py 1970-01-01 00:00:00 +0000 |
259 | +++ snappy_ecosystem_tests/environment/data/__init__.py 2017-03-02 10:45:12 +0000 |
260 | @@ -0,0 +1,19 @@ |
261 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
262 | + |
263 | +# |
264 | +# Snappy Ecosystem Tests |
265 | +# Copyright (C) 2017 Canonical |
266 | +# |
267 | +# This program is free software: you can redistribute it and/or modify |
268 | +# it under the terms of the GNU General Public License as published by |
269 | +# the Free Software Foundation, either version 3 of the License, or |
270 | +# (at your option) any later version. |
271 | +# |
272 | +# This program is distributed in the hope that it will be useful, |
273 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
274 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
275 | +# GNU General Public License for more details. |
276 | +# |
277 | +# You should have received a copy of the GNU General Public License |
278 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
279 | +# |
280 | |
281 | === added file 'snappy_ecosystem_tests/environment/data/snapcraft.py' |
282 | --- snappy_ecosystem_tests/environment/data/snapcraft.py 1970-01-01 00:00:00 +0000 |
283 | +++ snappy_ecosystem_tests/environment/data/snapcraft.py 2017-03-02 10:45:12 +0000 |
284 | @@ -0,0 +1,21 @@ |
285 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
286 | + |
287 | +# |
288 | +# Snappy Ecosystem Tests |
289 | +# Copyright (C) 2017 Canonical |
290 | +# |
291 | +# This program is free software: you can redistribute it and/or modify |
292 | +# it under the terms of the GNU General Public License as published by |
293 | +# the Free Software Foundation, either version 3 of the License, or |
294 | +# (at your option) any later version. |
295 | +# |
296 | +# This program is distributed in the hope that it will be useful, |
297 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
298 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
299 | +# GNU General Public License for more details. |
300 | +# |
301 | +# You should have received a copy of the GNU General Public License |
302 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
303 | +# |
304 | +"""Snapcraft data""" |
305 | +SNAPCRAFT_CONTAINER_NAME = 'snapcraft' |
306 | |
307 | === added file 'snappy_ecosystem_tests/environment/data/snapd.py' |
308 | --- snappy_ecosystem_tests/environment/data/snapd.py 1970-01-01 00:00:00 +0000 |
309 | +++ snappy_ecosystem_tests/environment/data/snapd.py 2017-03-02 10:45:12 +0000 |
310 | @@ -0,0 +1,88 @@ |
311 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
312 | + |
313 | +# |
314 | +# Snappy Ecosystem Tests |
315 | +# Copyright (C) 2017 Canonical |
316 | +# |
317 | +# This program is free software: you can redistribute it and/or modify |
318 | +# it under the terms of the GNU General Public License as published by |
319 | +# the Free Software Foundation, either version 3 of the License, or |
320 | +# (at your option) any later version. |
321 | +# |
322 | +# This program is distributed in the hope that it will be useful, |
323 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
324 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
325 | +# GNU General Public License for more details. |
326 | +# |
327 | +# You should have received a copy of the GNU General Public License |
328 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
329 | +# |
330 | +"""snapd data""" |
331 | +SNAPD_CONTAINER_NAME = 'snapd' |
332 | + |
333 | +CONTAINER_HOME = '/root' |
334 | +DIRECTORY_CLONE = '{}/src/github.com/snapcore/snapd'.format(CONTAINER_HOME) |
335 | +DOMAIN_PING = 'ubuntu.com' |
336 | +ENV_STORE_API_ROOT = 'UBUNTU_STORE_API_ROOT_URL' |
337 | +ENV_STORE_SEARCH_ROOT = 'UBUNTU_STORE_SEARCH_ROOT_URL' |
338 | +ENV_STORE_UPLOAD_ROOT = 'UBUNTU_STORE_UPLOAD_ROOT_URL' |
339 | +ENV_SSO_API_ROOT = 'UBUNTU_SSO_API_ROOT_URL' |
340 | +PACKAGES_SNAPD = ['snapd', 'snap-confine', 'ubuntu-core-launcher'] |
341 | +COMMAND_REMOVE_SNAPD = 'apt purge -y {}'.format(' '.join(PACKAGES_SNAPD)) |
342 | +COMMAND_APT_BUILD_DEP = 'apt build-dep -y ./' |
343 | +COMMAND_APT_INSTALL = 'apt install -y {}' |
344 | +COMMAND_APT_INSTALL_STAGING_DEBS = COMMAND_APT_INSTALL.format( |
345 | + ' '.join(['../{}*.deb'.format(pkg) for pkg in PACKAGES_SNAPD])) |
346 | +COMMAND_APT_UPDATE = 'apt update' |
347 | +COMMAND_APT_UPGRADE = 'apt dist-upgrade -y' |
348 | +COMMAND_BUILD_SNAPD = 'DEB_BUILD_OPTIONS="nocheck testkeys" ' \ |
349 | + 'dpkg-buildpackage -tc -b' |
350 | +COMMAND_EXPORT_STAGING_STORE_VAR = 'echo SNAPPY_USE_STAGING_STORE=1 >> ' \ |
351 | + '/etc/environment' |
352 | +COMMAND_GET_GOVENDOR = 'go get -v github.com/kardianos/govendor' |
353 | +COMMAND_GIT_CLONE = 'git clone {} {}' |
354 | +COMMAND_GOVENDOR_SYNC = 'govendor sync' |
355 | +REPOSITORY_GIT = 'https://github.com/snapcore/snapd' |
356 | +URL_API_ROOT = 'https://myapps.developer.staging.ubuntu.com/dev/api/' |
357 | +URL_SEARCH_ROOT = 'https://search.apps.staging.ubuntu.com/' |
358 | +URL_UPLOAD_ROOT = 'https://upload.apps.staging.ubuntu.com/' |
359 | +URL_SSO_API_ROOT = 'https://login.staging.ubuntu.com/api/v2/' |
360 | + |
361 | +CONTAINER_SETUP = [ |
362 | + COMMAND_REMOVE_SNAPD, |
363 | + COMMAND_APT_UPDATE, |
364 | + # Hold open-iscsi which is causing apt upgrade errors while running |
365 | + # inside container. |
366 | + 'apt-mark hold open-iscsi', |
367 | + COMMAND_APT_UPGRADE, |
368 | + # Needed for snaps to work inside a lxd container |
369 | + # ref: https://stgraber.org/2016/12/07/running-snaps-in-lxd-containers/ |
370 | + COMMAND_APT_INSTALL.format('squashfuse'), |
371 | + COMMAND_GIT_CLONE.format(REPOSITORY_GIT, DIRECTORY_CLONE), |
372 | + {'command': COMMAND_APT_BUILD_DEP, 'cwd': DIRECTORY_CLONE}, |
373 | + {'command': COMMAND_GET_GOVENDOR, 'cwd': DIRECTORY_CLONE}, |
374 | + {'command': COMMAND_GOVENDOR_SYNC, 'cwd': DIRECTORY_CLONE}, |
375 | + {'command': COMMAND_BUILD_SNAPD, 'cwd': DIRECTORY_CLONE}, |
376 | + COMMAND_EXPORT_STAGING_STORE_VAR, |
377 | + {'command': COMMAND_APT_INSTALL_STAGING_DEBS, 'cwd': DIRECTORY_CLONE} |
378 | +] |
379 | + |
380 | +CONTAINER_ENV_VARS = { |
381 | + 'GOPATH': CONTAINER_HOME, |
382 | + 'SNAPPY_USE_STAGING_STORE': '1', |
383 | + ENV_STORE_API_ROOT: URL_API_ROOT, |
384 | + ENV_STORE_SEARCH_ROOT: URL_SEARCH_ROOT, |
385 | + ENV_STORE_UPLOAD_ROOT: URL_UPLOAD_ROOT, |
386 | + ENV_SSO_API_ROOT: URL_SSO_API_ROOT, |
387 | +} |
388 | + |
389 | +DEFAULT_CONTAINER_CONFIG = { |
390 | + "name": "snapd", |
391 | + "source": { |
392 | + "type": "image", |
393 | + "mode": "pull", |
394 | + "server": "https://cloud-images.ubuntu.com/releases", |
395 | + "protocol": "simplestreams", |
396 | + "fingerprint": "16.04" |
397 | + } |
398 | +} |
399 | |
400 | === added file 'snappy_ecosystem_tests/environment/managers.py' |
401 | --- snappy_ecosystem_tests/environment/managers.py 1970-01-01 00:00:00 +0000 |
402 | +++ snappy_ecosystem_tests/environment/managers.py 2017-03-02 10:45:12 +0000 |
403 | @@ -0,0 +1,142 @@ |
404 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
405 | + |
406 | +# |
407 | +# Ubuntu System Tests |
408 | +# Copyright (C) 2017 Canonical |
409 | +# |
410 | +# This program is free software: you can redistribute it and/or modify |
411 | +# it under the terms of the GNU General Public License as published by |
412 | +# the Free Software Foundation, either version 3 of the License, or |
413 | +# (at your option) any later version. |
414 | +# |
415 | +# This program is distributed in the hope that it will be useful, |
416 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
417 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
418 | +# GNU General Public License for more details. |
419 | +# |
420 | +# You should have received a copy of the GNU General Public License |
421 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
422 | +# |
423 | + |
424 | +"""Managers to setup the environment""" |
425 | + |
426 | +import os |
427 | +import shlex |
428 | +from pylxd import Client |
429 | +from pylxd.exceptions import NotFound, LXDAPIException |
430 | +from retrying import retry |
431 | + |
432 | +from snappy_ecosystem_tests.environment import constants |
433 | +from snappy_ecosystem_tests.environment.constants import ( |
434 | + PROFILES, DEPENDENCIES) |
435 | +from snappy_ecosystem_tests.environment.data.snapcraft import ( |
436 | + SNAPCRAFT_CONTAINER_NAME) |
437 | +from snappy_ecosystem_tests.environment.data.snapd import ( |
438 | + DEFAULT_CONTAINER_CONFIG, SNAPD_CONTAINER_NAME) |
439 | + |
440 | +def get_manager(mode): |
441 | + """Get the manager for the given mode""" |
442 | + supported_modules = { |
443 | + "lxd": LxdManager |
444 | + } |
445 | + try: |
446 | + manager = supported_modules[mode] |
447 | + return manager() |
448 | + except KeyError: |
449 | + raise RuntimeError("Mode: {} is not supported".format(mode)) |
450 | + |
451 | + |
452 | +class LxdManager: |
453 | + """Manage lxd containers""" |
454 | + |
455 | + def __init__(self): |
456 | + self.client = Client() |
457 | + |
458 | + def launch(self, container_name, release='16.04'): |
459 | + """Launch a container""" |
460 | + try: |
461 | + container = self.client.containers.get(container_name) |
462 | + if container.status == "Running": |
463 | + container.stop(wait=True) |
464 | + container.delete(wait=True) |
465 | + except NotFound: |
466 | + pass |
467 | + container_config = DEFAULT_CONTAINER_CONFIG.copy() |
468 | + container_config['source']['alias'] = release |
469 | + container_config['name'] = container_name |
470 | + container = self.client.containers.create(container_config, wait=True) |
471 | + container.start(wait=True) |
472 | + |
473 | + def execute_command(self, container_name, command): |
474 | + """execute command""" |
475 | + container = self.client.containers.get(container_name) |
476 | + container.execute(command) |
477 | + |
478 | + def install(self, container_name, packages, channel=None): |
479 | + """Install a packages""" |
480 | + container = self.client.containers.get(container_name) |
481 | + container.execute(shlex.split('apt-get update')) |
482 | + install_command = 'apt-get install {} -y'.format(packages) |
483 | + if channel: |
484 | + install_command += ' -t {}'.format(channel) |
485 | + container.execute(shlex.split(install_command)) |
486 | + |
487 | + def install_dependencies(self, container_name, container_type): |
488 | + """Install a dependencies""" |
489 | + self.install( |
490 | + container_name, |
491 | + DEPENDENCIES[container_type] + DEPENDENCIES['shared']) |
492 | + |
493 | + |
494 | + def configure(self, container_name, container_type, profile): |
495 | + """Configure a given container""" |
496 | + container = self.client.containers.get(container_name) |
497 | + for variable in \ |
498 | + PROFILES[profile][container_type]['environment_variables']: |
499 | + container.config.update({'environment.{}'.format( |
500 | + variable['name']): variable['value']}) |
501 | + container.save(wait=True) |
502 | + |
503 | + @retry(stop_max_attempt_number=5, wait_fixed=3000, |
504 | + retry_on_exception=lambda exception: isinstance( |
505 | + exception, LXDAPIException)) |
506 | + def enable_ssh(self, container_name): |
507 | + """Enable the ssh connection on the container""" |
508 | + container = self.client.containers.get(container_name) |
509 | + pub_key = open( |
510 | + os.path.expanduser('~') + '/.ssh/id_rsa.pub').read().strip('\n') |
511 | + container.files.put('/home/ubuntu/.ssh/authorized_keys', pub_key) |
512 | + |
513 | + |
514 | + def setup(self, profile): |
515 | + """setup the container based on the profile""" |
516 | + self._setup(SNAPD_CONTAINER_NAME, constants.SNAPD, profile) |
517 | + self._setup( |
518 | + SNAPCRAFT_CONTAINER_NAME, constants.SNAPCRAFT, profile) |
519 | + |
520 | + |
521 | + def _setup(self, container_name, container_type, profile): |
522 | + """ |
523 | + Launch a container, enable ssh, install dependencies |
524 | + and setup the needed environment variables |
525 | + """ |
526 | + self.launch(container_name) |
527 | + self.enable_ssh(container_name) |
528 | + self.install( |
529 | + container_name, |
530 | + packages=PROFILES[profile][container_type]["package_name"], |
531 | + channel=PROFILES[profile][container_type]["channel"]) |
532 | + self.install_dependencies(container_name, container_type) |
533 | + self.configure(container_name, container_type, profile) |
534 | + |
535 | + def get_ip(self, container_name): |
536 | + """Gets the ip address for a given container""" |
537 | + networks = self.client.containers.get( |
538 | + container_name).state().network['eth0']['addresses'] |
539 | + |
540 | + for network in networks: |
541 | + if network['address']: |
542 | + return network['address'] |
543 | + raise RuntimeError( |
544 | + "The container {} does not have an IPV4 connection".format( |
545 | + container_name)) |
546 | |
547 | === added file 'snappy_ecosystem_tests/environment/setup.py' |
548 | --- snappy_ecosystem_tests/environment/setup.py 1970-01-01 00:00:00 +0000 |
549 | +++ snappy_ecosystem_tests/environment/setup.py 2017-03-02 10:45:12 +0000 |
550 | @@ -0,0 +1,46 @@ |
551 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
552 | + |
553 | +# |
554 | +# Ubuntu System Tests |
555 | +# Copyright (C) 2017 Canonical |
556 | +# |
557 | +# This program is free software: you can redistribute it and/or modify |
558 | +# it under the terms of the GNU General Public License as published by |
559 | +# the Free Software Foundation, either version 3 of the License, or |
560 | +# (at your option) any later version. |
561 | +# |
562 | +# This program is distributed in the hope that it will be useful, |
563 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
564 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
565 | +# GNU General Public License for more details. |
566 | +# |
567 | +# You should have received a copy of the GNU General Public License |
568 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
569 | +# |
570 | + |
571 | +"""Standalone script to setup an ecosystem environment""" |
572 | + |
573 | +import argparse |
574 | + |
575 | +import logging |
576 | + |
577 | +from snappy_ecosystem_tests.environment.managers import get_manager |
578 | + |
579 | +logging.basicConfig(level=logging.DEBUG) |
580 | + |
581 | +def main(mode, profile): |
582 | + """Main script""" |
583 | + manager = get_manager(mode) |
584 | + manager.setup(profile) |
585 | + |
586 | + |
587 | +if __name__ == '__main__': |
588 | + PARSER = argparse.ArgumentParser(description= |
589 | + 'Setup a snappy ecosystem environment.') |
590 | + PARSER.add_argument('--mode', default="lxd", |
591 | + help='lxd') |
592 | + PARSER.add_argument('--profile', default="staging", |
593 | + help='Profile to configure the environment') |
594 | + ARGS = PARSER.parse_args() |
595 | + |
596 | + main(ARGS.mode, ARGS.profile) |
597 | |
598 | === modified file 'snappy_ecosystem_tests/helpers/snapcraft/client.py' |
599 | --- snappy_ecosystem_tests/helpers/snapcraft/client.py 2017-02-15 19:35:54 +0000 |
600 | +++ snappy_ecosystem_tests/helpers/snapcraft/client.py 2017-03-02 10:45:12 +0000 |
601 | @@ -20,14 +20,49 @@ |
602 | |
603 | """Snapcraft client helpers""" |
604 | |
605 | +import logging |
606 | +import subprocess |
607 | +import time |
608 | + |
609 | import pexpect |
610 | |
611 | - |
612 | -# login credentials exported by shell environment |
613 | +from snappy_ecosystem_tests.models.snap import Snap |
614 | +from snappy_ecosystem_tests.utils import ssh |
615 | +from snappy_ecosystem_tests.utils.commands import build_command |
616 | +from snappy_ecosystem_tests.utils.filters import filter_list |
617 | +from snappy_ecosystem_tests.utils.storeconfig import get_current_store |
618 | + |
619 | +from snappy_ecosystem_tests.commons.config import CONFIG_STACK |
620 | + |
621 | from snappy_ecosystem_tests.utils import storeconfig |
622 | |
623 | +# login credentials gotten from config file or shell environment |
624 | +from snappy_ecosystem_tests.utils.user import ( |
625 | + get_snapcraft_remote_host_credentials |
626 | +) |
627 | + |
628 | LOGIN_EMAIL, LOGIN_PASSWORD = storeconfig.get_store_credentials() |
629 | |
630 | +# Commands |
631 | +PATH_SNAPCRAFT = '/usr/bin/snapcraft' |
632 | +COMMANDS_LOGIN = """\ |
633 | +/usr/bin/expect \ |
634 | +-c 'spawn {snapcraft} login' \ |
635 | +-c 'expect Email:' \ |
636 | +-c 'send {email}\\r' \ |
637 | +-c 'expect Password:' \ |
638 | +-c 'send {password}\\r' \ |
639 | +-c 'interact'\ |
640 | +""" |
641 | + |
642 | +COMMAND_LOGOUT = 'logout' |
643 | +COMMAND_REGISTER = 'register' |
644 | +COMMAND_LIST_REGISTERED = 'list-registered' |
645 | + |
646 | +LOGGER = logging.getLogger(__name__) |
647 | + |
648 | +HOSTNAME, USERNAME, PORT = get_snapcraft_remote_host_credentials() |
649 | + |
650 | |
651 | class Snapcraft(object): |
652 | """Contain Snapcraft specific functionality to use via command |
653 | @@ -37,13 +72,37 @@ |
654 | self._login = False |
655 | self._cleanup() |
656 | |
657 | + @staticmethod |
658 | + def _run_snapcraft_command_ssh(command, debug=True): |
659 | + """ |
660 | + Run snapcraft command via ssh |
661 | + :param command: the command to be executed. |
662 | + Can be a single string or a list of strings |
663 | + :param debug: whether to enable debug mode |
664 | + :return: the command's output |
665 | + """ |
666 | + if not command.startswith(PATH_SNAPCRAFT): |
667 | + command = build_snapcraft_command(command) |
668 | + if debug: |
669 | + command += ' -d' |
670 | + return ssh.run_command(command, hostname=HOSTNAME, username=USERNAME, |
671 | + port=PORT) |
672 | + |
673 | + def assert_logged_in(self): |
674 | + """Assert that an user is logged. |
675 | + :raise ValueError: in case login is false |
676 | + """ |
677 | + if self._login is False: |
678 | + raise ValueError("User is not logged in, " |
679 | + "please login before using this command") |
680 | + |
681 | def _cleanup(self): |
682 | """Perform cleanup actions""" |
683 | self.logout() |
684 | |
685 | def logout(self): |
686 | """logout of snapcraft store session""" |
687 | - child = pexpect.spawn("snapcraft logout") |
688 | + child = pexpect.spawn(build_snapcraft_command(COMMAND_LOGOUT)) |
689 | err = child.expect('Credentials cleared.') |
690 | child.terminate(True) |
691 | child.wait() |
692 | @@ -52,23 +111,105 @@ |
693 | |
694 | self._login = False |
695 | |
696 | - def login(self): |
697 | - """login to store using the credential environment variables""" |
698 | - child = pexpect.spawn("snapcraft login") |
699 | - child.expect('Email: ') |
700 | - child.sendline(LOGIN_EMAIL) |
701 | - child.expect('Password:') |
702 | - child.sendline(LOGIN_PASSWORD) |
703 | - err = child.expect('Login successful') |
704 | - if err is not 0: |
705 | - raise ValueError("Failed to login") |
706 | - |
707 | - self._login = True |
708 | - |
709 | - def list_registered(self): |
710 | - """call snapcraft list-registered command, |
711 | - raise exception if not logged in""" |
712 | - if self._login is False: |
713 | - raise ValueError("User is not logged in, " |
714 | - "please login before using this command") |
715 | - return pexpect.spawnu("snapcraft list-registered").read() |
716 | + def login(self, email=LOGIN_EMAIL, password=LOGIN_PASSWORD): |
717 | + """Login to Snapcraft. If email and/or password are not provided, |
718 | + use the default ones. |
719 | + :param email: the SSO email |
720 | + :param password: the email password |
721 | + """ |
722 | + output = ssh.run_command( |
723 | + COMMANDS_LOGIN.format(email=email, password=password, |
724 | + snapcraft=PATH_SNAPCRAFT), |
725 | + hostname=HOSTNAME, username=USERNAME, port=PORT) |
726 | + self._login = 'login successful' in output.lower() |
727 | + return self._login |
728 | + |
729 | + def list_registered(self, debug=True, raw=False): |
730 | + """Call snapcraft list-registered command, |
731 | + raise exception if not logged in |
732 | + :param debug: whether to enable debug mode |
733 | + :param raw: whether to return the output as a raw. |
734 | + If False, return a list of Snap instances |
735 | + """ |
736 | + self.assert_logged_in() |
737 | + registered_snaps_output = self._run_snapcraft_command_ssh( |
738 | + COMMAND_LIST_REGISTERED, |
739 | + debug=debug) |
740 | + if raw: |
741 | + return registered_snaps_output |
742 | + else: |
743 | + snaps = registered_snaps_output.splitlines() |
744 | + # if debug is set, the first 3 lines of output are the API calls |
745 | + return parse_snaps_raw(snaps if debug is False else snaps[3:]) |
746 | + |
747 | + def filter_snaps(self, **predicates): |
748 | + """ |
749 | + Return a list of the snaps that match with all the given predicates. |
750 | + Examples: |
751 | + filter_snap() --> return all the snaps |
752 | + filter_snap(name='my_name') --> return the snaps that matches with |
753 | + name 'my_name' |
754 | + filter_snap(name='my_name', private=True) --> return the snaps that |
755 | + matches with name 'my_name' and are private. |
756 | + filter_snap(price='5') --> return the snaps with price '5'. |
757 | + :return: A list of snap instances |
758 | + """ |
759 | + return filter_list(self.list_registered(raw=False), **predicates) |
760 | + |
761 | + def register(self, snap_name, private=False, wait=True): |
762 | + """ |
763 | + Register a snap name in the store. |
764 | + :param snap_name: the snap name to register. |
765 | + :param private: whether the snap name is private. |
766 | + :param wait: wheter to wait after registration to hitting the store |
767 | + restriction on following registrations |
768 | + :return: True if the snap was registered successfully, False otherwise. |
769 | + """ |
770 | + self.assert_logged_in() |
771 | + LOGGER.info('About to register snap: %s', snap_name) |
772 | + command = build_snapcraft_command(COMMAND_REGISTER, snap_name) |
773 | + if private: |
774 | + command += ' --private' |
775 | + try: |
776 | + Snapcraft._run_snapcraft_command_ssh(command) |
777 | + except subprocess.CalledProcessError as _e: |
778 | + LOGGER.error('Unable to register snap: %s', _e.output) |
779 | + return False |
780 | + if wait: |
781 | + time.sleep(int(CONFIG_STACK.get('time_between_registrations', |
782 | + get_current_store()))) |
783 | + LOGGER.info('Snap %s registered successfully!!!', snap_name) |
784 | + return True |
785 | + |
786 | + |
787 | +def build_snapcraft_command(*args, base_command=PATH_SNAPCRAFT): |
788 | + """ |
789 | + Build a snapcraft command with arguments |
790 | + :param args: list of arguments for the command |
791 | + :param base_command: snapcraft executable that is going to be used |
792 | + :return: the snapcraft command ready to be executed |
793 | + """ |
794 | + return build_command(base_command, *args) |
795 | + |
796 | + |
797 | +def parse_snaps_raw(raw): |
798 | + """ |
799 | + Parse snaps raw output to a list of Snaps object |
800 | + :param raw: the raw that contains the snaps info. |
801 | + It assumes that the first line is the output Header like: |
802 | + (Name, Since, Price, etc.) to get the attributes order. |
803 | + :return: A list of snaps instances |
804 | + """ |
805 | + attributes_order = {} |
806 | + for _i, att in enumerate(raw[0].split()): |
807 | + attributes_order[att.lower()] = _i |
808 | + snaps = [] |
809 | + for snap_raw in raw[1:]: |
810 | + attrs = snap_raw.split() |
811 | + private = attrs[attributes_order.get('visibility')].lower() == 'private' |
812 | + snaps.append(Snap(name=attrs[attributes_order.get('name')], |
813 | + since=attrs[attributes_order.get('since')], |
814 | + private=private, |
815 | + price=attrs[attributes_order.get('price')], |
816 | + notes=attrs[attributes_order.get('notes')])) |
817 | + return snaps |
818 | |
819 | === modified file 'snappy_ecosystem_tests/helpers/snapd/snapd.py' |
820 | --- snappy_ecosystem_tests/helpers/snapd/snapd.py 2017-02-21 15:17:12 +0000 |
821 | +++ snappy_ecosystem_tests/helpers/snapd/snapd.py 2017-03-02 10:45:12 +0000 |
822 | @@ -26,6 +26,7 @@ |
823 | import yaml |
824 | |
825 | from snappy_ecosystem_tests.utils import ssh |
826 | +from snappy_ecosystem_tests.utils.user import get_snapd_remote_host_credentials |
827 | |
828 | PATH_SNAP = '/usr/bin/snap' |
829 | COMMAND_DOWNLOAD = 'download {snap} --channel={channel}' |
830 | @@ -47,6 +48,8 @@ |
831 | """ |
832 | LOGGER = logging.getLogger(__name__) |
833 | |
834 | +HOSTNAME, USERNAME, PORT = get_snapd_remote_host_credentials() |
835 | + |
836 | |
837 | def run_snapd_command_ssh(parameters, cwd=''): |
838 | """Run snapd command over ssh. |
839 | @@ -59,7 +62,8 @@ |
840 | if cwd: |
841 | return ssh.run_command( |
842 | 'cd {}; {} {}'.format(cwd, PATH_SNAP, parameters)) |
843 | - return ssh.run_command('{} {}'.format(PATH_SNAP, parameters)) |
844 | + return ssh.run_command('{} {}'.format(PATH_SNAP, parameters), |
845 | + hostname=HOSTNAME, username=USERNAME, port=PORT) |
846 | |
847 | |
848 | def login(email, password): |
849 | |
850 | === modified file 'snappy_ecosystem_tests/helpers/snapd/staging_builder.py' |
851 | --- snappy_ecosystem_tests/helpers/snapd/staging_builder.py 2017-02-21 13:46:08 +0000 |
852 | +++ snappy_ecosystem_tests/helpers/snapd/staging_builder.py 2017-03-02 10:45:12 +0000 |
853 | @@ -24,6 +24,8 @@ |
854 | import sys |
855 | from time import sleep |
856 | |
857 | +from snappy_ecosystem_tests.environment.data.snapd import ( |
858 | + CONTAINER_HOME, CONTAINER_ENV_VARS, CONTAINER_SETUP) |
859 | from snappy_ecosystem_tests.utils.lxd import Container, launch_container |
860 | |
861 | CONTAINER_HOME = '/root' |
862 | @@ -71,15 +73,20 @@ |
863 | COMMAND_EXPORT_STAGING_STORE_VAR, |
864 | {'command': COMMAND_APT_INSTALL_STAGING_DEBS, 'cwd': DIRECTORY_CLONE} |
865 | ] |
866 | - |
867 | -CONTAINER_ENV_VARS = { |
868 | - 'GOPATH': CONTAINER_HOME, |
869 | - 'SNAPPY_USE_STAGING_STORE': '1', |
870 | +SNAPCRAFT_STAGING_VARIABLES = { |
871 | ENV_STORE_API_ROOT: URL_API_ROOT, |
872 | ENV_STORE_SEARCH_ROOT: URL_SEARCH_ROOT, |
873 | ENV_STORE_UPLOAD_ROOT: URL_UPLOAD_ROOT, |
874 | ENV_SSO_API_ROOT: URL_SSO_API_ROOT, |
875 | } |
876 | +SNAPD_STAGING_VARIABLES = { |
877 | + 'SNAPPY_USE_STAGING_STORE': '1' |
878 | +} |
879 | +STAGING_VARIABLES = dict( |
880 | + SNAPCRAFT_STAGING_VARIABLES, **SNAPD_STAGING_VARIABLES) |
881 | +CONTAINER_ENV_VARS = { |
882 | + 'GOPATH': CONTAINER_HOME, |
883 | +} |
884 | |
885 | LOGGER = logging.getLogger(__name__) |
886 | |
887 | |
888 | === modified file 'snappy_ecosystem_tests/helpers/store_apis/rest_apis.py' |
889 | --- snappy_ecosystem_tests/helpers/store_apis/rest_apis.py 2017-02-17 18:41:32 +0000 |
890 | +++ snappy_ecosystem_tests/helpers/store_apis/rest_apis.py 2017-03-02 10:45:12 +0000 |
891 | @@ -45,6 +45,8 @@ |
892 | from snappy_ecosystem_tests.helpers.snapcraft.options import ProjectOptions |
893 | from snappy_ecosystem_tests.helpers.store_apis import errors |
894 | from snappy_ecosystem_tests.helpers.store_apis.upload import upload_files |
895 | +from snappy_ecosystem_tests.models.snap import Snap |
896 | +from snappy_ecosystem_tests.utils.filters import filter_list |
897 | |
898 | LOGGER = logging.getLogger(__name__) |
899 | |
900 | @@ -193,16 +195,28 @@ |
901 | """Get current account information""" |
902 | return self._refresh_if_necessary(self.sca.get_account_information) |
903 | |
904 | + def get_registered_snaps(self, series=constants.DEFAULT_SERIES): |
905 | + """Get registered snaps for current user. |
906 | + First refresh macaroon if necessary""" |
907 | + return self._refresh_if_necessary(self.sca.get_registered_snaps, |
908 | + series) |
909 | + |
910 | + def filter_snaps(self, series=constants.DEFAULT_SERIES, **predicates): |
911 | + """Filter snaps that match with given predicates |
912 | + First refresh macaroon if necessary""" |
913 | + return self._refresh_if_necessary(self.sca.filter_snaps, |
914 | + series=series, **predicates) |
915 | + |
916 | def register_key(self, account_key_request): |
917 | """Register a key for the current user""" |
918 | return self._refresh_if_necessary( |
919 | self.sca.register_key, account_key_request) |
920 | |
921 | - def register(self, snap_name, is_private=False): |
922 | + def register(self, snap_name, private=False): |
923 | """Register a package name for the current user |
924 | First refresh macaroon if necessary""" |
925 | return self._refresh_if_necessary( |
926 | - self.sca.register, snap_name, is_private, constants.DEFAULT_SERIES) |
927 | + self.sca.register, snap_name, private, constants.DEFAULT_SERIES) |
928 | |
929 | def push_precheck(self, snap_name): |
930 | """Do a snap push as a pre-check (dry_run: do not actually push) |
931 | @@ -555,6 +569,36 @@ |
932 | else: |
933 | raise errors.StoreAccountInformationError(response) |
934 | |
935 | + def get_registered_snaps(self, series=constants.DEFAULT_SERIES): |
936 | + """ |
937 | + Get the registered snaps for the current user |
938 | + :param series: get only snaps that match with this series |
939 | + :return: the list of registered snaps |
940 | + """ |
941 | + account_info = self.get_account_information() |
942 | + user_snaps = account_info.get('snaps') |
943 | + snaps_dict = user_snaps.get(series) |
944 | + snaps = [] |
945 | + for name, snap_data in snaps_dict.items(): |
946 | + snaps.append(Snap(name=name, **snap_data)) |
947 | + return snaps |
948 | + |
949 | + def filter_snaps(self, series=constants.DEFAULT_SERIES, **predicates): |
950 | + """ |
951 | + Return a list of the snaps that match with all the given predicates. |
952 | + :param: series: only look in the snaps that match with this series |
953 | + Examples: |
954 | + filter_snap() --> return all the snaps |
955 | + filter_snap(name='my_name') --> return the snaps that matches with |
956 | + name 'my_name' |
957 | + filter_snap(name='my_name', private=True) --> return the snaps that |
958 | + matches with name 'my_name' and are private. |
959 | + filter_snap(price='5') --> return the snaps that with price '5'. |
960 | + :return: A list of snap instances |
961 | + """ |
962 | + return filter_list(self.get_registered_snaps(series=series), |
963 | + **predicates) |
964 | + |
965 | def register_key(self, account_key_request): |
966 | """Register a key for a user with the given request |
967 | :param account_key_request: the key to register |
968 | @@ -568,20 +612,21 @@ |
969 | if not response.ok: |
970 | raise errors.StoreKeyRegistrationError(response) |
971 | |
972 | - def register(self, snap_name, is_private, series): |
973 | + def register(self, snap_name, private, series): |
974 | """Register a snap name in the store |
975 | :param snap_name: the name to be registered |
976 | - :param is_private: whether the snap name is private or not |
977 | + :param private: whether the snap name is private or not |
978 | :param series: the snap's series to be registered |
979 | """ |
980 | auth = _macaroon_auth(self.conf) |
981 | - data = dict(snap_name=snap_name, is_private=is_private, |
982 | + data = dict(snap_name=snap_name, is_private=private, |
983 | series=series) |
984 | response = self.post( |
985 | 'register-name/', data=json.dumps(data), |
986 | - headers=dict({'Authorization': auth}, **JSON_ACCEPT)) |
987 | + headers=dict({'Authorization': auth}, **JSON_CONTENT_TYPE)) |
988 | if not response.ok: |
989 | raise errors.StoreRegistrationError(snap_name, response) |
990 | + return True |
991 | |
992 | def snap_push_precheck(self, snap_name): |
993 | """Do a snap push pre-check (dry_run: do not actually push) |
994 | |
995 | === added directory 'snappy_ecosystem_tests/models' |
996 | === added file 'snappy_ecosystem_tests/models/__init__.py' |
997 | --- snappy_ecosystem_tests/models/__init__.py 1970-01-01 00:00:00 +0000 |
998 | +++ snappy_ecosystem_tests/models/__init__.py 2017-03-02 10:45:12 +0000 |
999 | @@ -0,0 +1,19 @@ |
1000 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
1001 | + |
1002 | +# |
1003 | +# Snappy Ecosystem Tests |
1004 | +# Copyright (C) 2017 Canonical |
1005 | +# |
1006 | +# This program is free software: you can redistribute it and/or modify |
1007 | +# it under the terms of the GNU General Public License as published by |
1008 | +# the Free Software Foundation, either version 3 of the License, or |
1009 | +# (at your option) any later version. |
1010 | +# |
1011 | +# This program is distributed in the hope that it will be useful, |
1012 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1013 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1014 | +# GNU General Public License for more details. |
1015 | +# |
1016 | +# You should have received a copy of the GNU General Public License |
1017 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1018 | +# |
1019 | |
1020 | === added file 'snappy_ecosystem_tests/models/snap.py' |
1021 | --- snappy_ecosystem_tests/models/snap.py 1970-01-01 00:00:00 +0000 |
1022 | +++ snappy_ecosystem_tests/models/snap.py 2017-03-02 10:45:12 +0000 |
1023 | @@ -0,0 +1,39 @@ |
1024 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
1025 | + |
1026 | +# |
1027 | +# Snappy Ecosystem Tests |
1028 | +# Copyright (C) 2017 Canonical |
1029 | +# |
1030 | +# This program is free software: you can redistribute it and/or modify |
1031 | +# it under the terms of the GNU General Public License as published by |
1032 | +# the Free Software Foundation, either version 3 of the License, or |
1033 | +# (at your option) any later version. |
1034 | +# |
1035 | +# This program is distributed in the hope that it will be useful, |
1036 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1037 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1038 | +# GNU General Public License for more details. |
1039 | +# |
1040 | +# You should have received a copy of the GNU General Public License |
1041 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1042 | +# |
1043 | + |
1044 | +"""Business model classes for snaps""" |
1045 | + |
1046 | + |
1047 | +class Snap: |
1048 | + """Represents a snap entity.""" |
1049 | + |
1050 | + def __init__(self, name='', price=None, private=False, since=None, |
1051 | + _id=None, status=None, notes=None, **kwargs): |
1052 | + self.name = name |
1053 | + self.price = price |
1054 | + self.private = private |
1055 | + self.since = since |
1056 | + self._id = _id or kwargs.get('snap-id') |
1057 | + self.status = status |
1058 | + self.notes = notes |
1059 | + |
1060 | + def is_private(self): |
1061 | + """Return True if the snap is private, False otherwise""" |
1062 | + return self.private |
1063 | |
1064 | === modified file 'snappy_ecosystem_tests/run.py' |
1065 | --- snappy_ecosystem_tests/run.py 2017-02-15 19:14:19 +0000 |
1066 | +++ snappy_ecosystem_tests/run.py 2017-03-02 10:45:12 +0000 |
1067 | @@ -20,28 +20,38 @@ |
1068 | |
1069 | """Entry point to run snappy ecosystem tests""" |
1070 | |
1071 | +import argparse |
1072 | +import os |
1073 | import re |
1074 | import sys |
1075 | import pytest |
1076 | |
1077 | -FILTER_ARGUMENTS = '--proxy' |
1078 | - |
1079 | - |
1080 | -def _filter_arguments(): |
1081 | - """Remove from command line arguments all the ones that are in |
1082 | - FILTER_ARGUMENTS list.""" |
1083 | - filtered_args = sys.argv[1:] |
1084 | - for i, arg in enumerate(sys.argv[1:]): |
1085 | - if arg in FILTER_ARGUMENTS: |
1086 | - filtered_args.pop(i + 1) |
1087 | - filtered_args.pop(i) |
1088 | - return filtered_args |
1089 | - |
1090 | |
1091 | def _parse_arguments(): |
1092 | """Parse and filter command line arguments to makethem pytest compatible""" |
1093 | sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) |
1094 | - return _filter_arguments() |
1095 | + parser = argparse.ArgumentParser(description= |
1096 | + 'Run snappy ecosystem tests.') |
1097 | + parser.add_argument('--proxy', |
1098 | + help='proxy to use for creating the virtual env.', |
1099 | + required=False) |
1100 | + parser.add_argument('--target', default="lxd", |
1101 | + help='Target on which tests will be executed.') |
1102 | + ecosystem_args, pytest_args = parser.parse_known_args() |
1103 | + _set_env_variables(ecosystem_args) |
1104 | + return pytest_args |
1105 | + |
1106 | + |
1107 | +def _set_env_variables(args): |
1108 | + """ |
1109 | + Set environment variables with ecosystem arguments passed |
1110 | + in the command line. |
1111 | + :param args: The arguments to store in env variables |
1112 | + """ |
1113 | + for arg in vars(args): |
1114 | + value = getattr(args, arg, None) |
1115 | + if value: |
1116 | + os.environ[arg] = value |
1117 | |
1118 | if __name__ == '__main__': |
1119 | sys.exit(pytest.main(args=_parse_arguments() + ['-p', 'no:cacheprovider'])) |
1120 | |
1121 | === added file 'snappy_ecosystem_tests/tests/test_register_snap.py' |
1122 | --- snappy_ecosystem_tests/tests/test_register_snap.py 1970-01-01 00:00:00 +0000 |
1123 | +++ snappy_ecosystem_tests/tests/test_register_snap.py 2017-03-02 10:45:12 +0000 |
1124 | @@ -0,0 +1,116 @@ |
1125 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
1126 | + |
1127 | +# |
1128 | +# Snappy Ecosystem Tests |
1129 | +# Copyright (C) 2017 Canonical |
1130 | +# |
1131 | +# This program is free software: you can redistribute it and/or modify |
1132 | +# it under the terms of the GNU General Public License as published by |
1133 | +# the Free Software Foundation, either version 3 of the License, or |
1134 | +# (at your option) any later version. |
1135 | +# |
1136 | +# This program is distributed in the hope that it will be useful, |
1137 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1138 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1139 | +# GNU General Public License for more details. |
1140 | +# |
1141 | +# You should have received a copy of the GNU General Public License |
1142 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1143 | +# |
1144 | + |
1145 | +"""Tests for Registering a snap name in the store""" |
1146 | + |
1147 | +import uuid |
1148 | + |
1149 | +from snappy_ecosystem_tests.helpers.snapcraft.client import Snapcraft |
1150 | +from snappy_ecosystem_tests.helpers.store_apis.rest_apis import Store |
1151 | +from snappy_ecosystem_tests.helpers.test_base import SnappyEcosystemTestCase |
1152 | +from snappy_ecosystem_tests.utils.storeconfig import get_store_credentials |
1153 | + |
1154 | + |
1155 | +class RegisterSnapNameTestCase(SnappyEcosystemTestCase): |
1156 | + |
1157 | + def setUp(self): |
1158 | + super().setUp() |
1159 | + self.store = Store() |
1160 | + self.snapcraft = Snapcraft() |
1161 | + self.store.login(*get_store_credentials()) |
1162 | + self.addCleanup(self.store.logout) |
1163 | + self.snapcraft.login() |
1164 | + self.addCleanup(self.snapcraft.logout) |
1165 | + |
1166 | + @staticmethod |
1167 | + def _get_random_snap_name(prefix='ecosystem-test'): |
1168 | + """Get a random snap name using uuid |
1169 | + :param prefix: the string prefix, |
1170 | + if not provided, use default one. |
1171 | + """ |
1172 | + return '{}{}'.format(prefix, int(uuid.uuid4())) |
1173 | + |
1174 | + def test_register_public_snap_name_using_snapcraft(self): |
1175 | + """Test register a public snap name via snapcraft |
1176 | + and verify it via REST API""" |
1177 | + # Register snap via Snapcraft |
1178 | + snap_name = self._get_random_snap_name() |
1179 | + self.assertTrue(self.snapcraft.register(snap_name), |
1180 | + 'Unable to register snap') |
1181 | + |
1182 | + # Verify the registered snap via REST API |
1183 | + snaps = self.store.filter_snaps(name=snap_name) |
1184 | + self.assertEqual(1, len(snaps), |
1185 | + 'Expected 1 snap with name %s but found %s' |
1186 | + % (snap_name, len(snaps))) |
1187 | + snap = snaps[0] |
1188 | + self.assertEqual(snap_name, snap.name) |
1189 | + self.assertFalse(snap.is_private()) |
1190 | + |
1191 | + def test_register_private_snap_name_using_snapcraft(self): |
1192 | + """Test register a private snap name via snapcraft |
1193 | + and verify it via REST API""" |
1194 | + # Register snap via Snapcraft |
1195 | + snap_name = self._get_random_snap_name() |
1196 | + self.assertTrue(self.snapcraft.register(snap_name, private=True), |
1197 | + 'Unable to register snap') |
1198 | + |
1199 | + # Verify the registered snap via REST API |
1200 | + snaps = self.store.filter_snaps(name=snap_name) |
1201 | + self.assertEqual(1, len(snaps), |
1202 | + 'Expected 1 snap with name %s but found %s' |
1203 | + % (snap_name, len(snaps))) |
1204 | + snap = snaps[0] |
1205 | + self.assertEqual(snap_name, snap.name) |
1206 | + self.assertTrue(snap.is_private()) |
1207 | + |
1208 | + def test_register_public_snap_name_using_api(self): |
1209 | + """Verify that snapcraft lists a new snap registered via |
1210 | + RESTful API when using the command snapcraft list-registered""" |
1211 | + # Register snap via API |
1212 | + snap_name = self._get_random_snap_name() |
1213 | + self.assertTrue(self.store.register(snap_name), |
1214 | + 'Unable to register snap') |
1215 | + |
1216 | + # Verify the registered snap via Snapcraft |
1217 | + snaps = self.snapcraft.filter_snaps(name=snap_name) |
1218 | + self.assertEqual(1, len(snaps), |
1219 | + 'Expected 1 snap with name %s but found %s' |
1220 | + % (snap_name, len(snaps))) |
1221 | + snap = snaps[0] |
1222 | + self.assertEqual(snap_name, snap.name) |
1223 | + self.assertFalse(snap.is_private()) |
1224 | + |
1225 | + def test_register_private_snap_name_using_api(self): |
1226 | + """Verify that snapcraft lists a new private snap registered via |
1227 | + RESTful API when using the command snapcraft list-registered""" |
1228 | + # Register snap via API |
1229 | + snap_name = self._get_random_snap_name() |
1230 | + self.assertTrue(self.store.register(snap_name, private=True), |
1231 | + 'Unable to register snap') |
1232 | + |
1233 | + # Verify the registered snap via Snapcraft |
1234 | + snaps = self.snapcraft.filter_snaps(name=snap_name) |
1235 | + self.assertEqual(1, len(snaps), |
1236 | + 'Expected 1 snap with name %s but found %s' |
1237 | + % (snap_name, len(snaps))) |
1238 | + snap = snaps[0] |
1239 | + self.assertEqual(snap_name, snap.name) |
1240 | + self.assertTrue(snap.is_private()) |
1241 | |
1242 | === added file 'snappy_ecosystem_tests/unittests/test_filters.py' |
1243 | --- snappy_ecosystem_tests/unittests/test_filters.py 1970-01-01 00:00:00 +0000 |
1244 | +++ snappy_ecosystem_tests/unittests/test_filters.py 2017-03-02 10:45:12 +0000 |
1245 | @@ -0,0 +1,113 @@ |
1246 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
1247 | + |
1248 | +# |
1249 | +# Snappy Ecosystem Tests |
1250 | +# Copyright (C) 2017 Canonical |
1251 | +# |
1252 | +# This program is free software: you can redistribute it and/or modify |
1253 | +# it under the terms of the GNU General Public License as published by |
1254 | +# the Free Software Foundation, either version 3 of the License, or |
1255 | +# (at your option) any later version. |
1256 | +# |
1257 | +# This program is distributed in the hope that it will be useful, |
1258 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1259 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1260 | +# GNU General Public License for more details. |
1261 | +# |
1262 | +# You should have received a copy of the GNU General Public License |
1263 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1264 | +# |
1265 | + |
1266 | +"""Unit tests cases for filter utils""" |
1267 | + |
1268 | +from testtools import ( |
1269 | + TestCase, |
1270 | + ExpectedException |
1271 | +) |
1272 | + |
1273 | +from snappy_ecosystem_tests.utils.filters import ( |
1274 | + object_filter, |
1275 | + filter_list |
1276 | +) |
1277 | + |
1278 | + |
1279 | +class DummyObject: # pylint: disable=too-few-public-methods |
1280 | + """Dummy object to be used in unit tests""" |
1281 | + |
1282 | + def __init__(self, **kwargs): |
1283 | + for _k, _v in kwargs.items(): |
1284 | + setattr(self, _k, _v) |
1285 | + |
1286 | + |
1287 | +class FilterTestCase(TestCase): |
1288 | + |
1289 | + def setUp(self): |
1290 | + super().setUp() |
1291 | + self.obj = DummyObject(name='dummy', desc='this is dummy') |
1292 | + self.obj_2 = DummyObject(name='another-dummy', |
1293 | + desc='this is another dummy') |
1294 | + self.objects = [self.obj, self.obj_2] |
1295 | + |
1296 | + def test_object_filter_with_single_argument(self): |
1297 | + """Filter successfully passing one argument""" |
1298 | + objects = list(filter(object_filter(name='dummy'), self.objects)) |
1299 | + self.assertIsNotNone(objects) |
1300 | + self.assertEqual(len(objects), 1) |
1301 | + self.assertEqual(objects[0], self.obj) |
1302 | + |
1303 | + def test_object_filter_with_multiple_arguments(self): |
1304 | + """Filter successfully passing two arguments""" |
1305 | + objects = list(filter(object_filter(name='dummy', |
1306 | + desc='this is dummy'), |
1307 | + self.objects)) |
1308 | + self.assertIsNotNone(objects) |
1309 | + self.assertEqual(len(objects), 1) |
1310 | + self.assertEqual(objects[0], self.obj) |
1311 | + |
1312 | + def test_object_filter_does_not_match(self): |
1313 | + """Return empty list when no object match criteria""" |
1314 | + objects = list(filter(object_filter(name='dummy', |
1315 | + desc='any desc'), |
1316 | + self.objects)) |
1317 | + self.assertEqual([], objects) |
1318 | + |
1319 | + def test_object_filter_return_all(self): |
1320 | + """Get all objects when no filter is provided""" |
1321 | + objects = list(filter(object_filter(), self.objects)) |
1322 | + self.assertEqual(len(objects), len(self.objects)) |
1323 | + |
1324 | + def test_object_filter_raises_attribute_error_if_invalid_filter_name(self): |
1325 | + """Object filter raises AttributeError when invalid filter |
1326 | + is provided""" |
1327 | + with ExpectedException(AttributeError): |
1328 | + list(filter(object_filter(invalid='dummy'), self.objects)) |
1329 | + |
1330 | + def test_filter_list_with_single_argument(self): |
1331 | + """Filter List successfully passing one argument""" |
1332 | + objects = filter_list(self.objects, name='dummy') |
1333 | + self.assertIsNotNone(objects) |
1334 | + self.assertEqual(len(objects), 1) |
1335 | + self.assertEqual(objects[0], self.obj) |
1336 | + |
1337 | + def test_filter_list_with_multiple_arguments(self): |
1338 | + """Filter List successfully passing multiple argument""" |
1339 | + objects = filter_list(self.objects, name='another-dummy', |
1340 | + desc='this is another dummy') |
1341 | + self.assertIsNotNone(objects) |
1342 | + self.assertEqual(len(objects), 1) |
1343 | + self.assertEqual(objects[0], self.obj_2) |
1344 | + |
1345 | + def test_filter_list_does_not_match(self): |
1346 | + """Filter List returns empty list when no object match criteria""" |
1347 | + objects = filter_list(self.objects, desc='desc does not match') |
1348 | + self.assertEqual([], objects) |
1349 | + |
1350 | + def test_filter_list_return_all(self): |
1351 | + """Filter list returns all objects when no filter is provided""" |
1352 | + objects = filter_list(self.objects) |
1353 | + self.assertEqual(len(objects), len(self.objects)) |
1354 | + |
1355 | + def test_filter_list_raises_attribute_error_if_invalid_filter_name(self): |
1356 | + """Filter list raises AttributeError when invalid filter is provided""" |
1357 | + with ExpectedException(AttributeError): |
1358 | + filter_list(self.objects, invalid='invalid filter') |
1359 | |
1360 | === removed file 'snappy_ecosystem_tests/unittests/test_snapcraft.py' |
1361 | --- snappy_ecosystem_tests/unittests/test_snapcraft.py 2017-02-13 16:00:04 +0000 |
1362 | +++ snappy_ecosystem_tests/unittests/test_snapcraft.py 1970-01-01 00:00:00 +0000 |
1363 | @@ -1,31 +0,0 @@ |
1364 | -# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
1365 | - |
1366 | -# |
1367 | -# Snappy Ecosystem Tests |
1368 | -# Copyright (C) 2017 Canonical |
1369 | -# |
1370 | -# This program is free software: you can redistribute it and/or modify |
1371 | -# it under the terms of the GNU General Public License as published by |
1372 | -# the Free Software Foundation, either version 3 of the License, or |
1373 | -# (at your option) any later version. |
1374 | -# |
1375 | -# This program is distributed in the hope that it will be useful, |
1376 | -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1377 | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1378 | -# GNU General Public License for more details. |
1379 | -# |
1380 | -# You should have received a copy of the GNU General Public License |
1381 | -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1382 | -# |
1383 | - |
1384 | -"""Unit tests cases for snapcraft""" |
1385 | - |
1386 | -from unittest2 import TestCase |
1387 | - |
1388 | - |
1389 | -class SnapcraftTestCase(TestCase): |
1390 | - |
1391 | - def test_snapcraft_dummy_test(self): |
1392 | - """Dummy test case""" |
1393 | - _a = True |
1394 | - self.assertTrue(_a) |
1395 | |
1396 | === added file 'snappy_ecosystem_tests/utils/commands.py' |
1397 | --- snappy_ecosystem_tests/utils/commands.py 1970-01-01 00:00:00 +0000 |
1398 | +++ snappy_ecosystem_tests/utils/commands.py 2017-03-02 10:45:12 +0000 |
1399 | @@ -0,0 +1,31 @@ |
1400 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
1401 | + |
1402 | +# |
1403 | +# Snappy Ecosystem Tests |
1404 | +# Copyright (C) 2017 Canonical |
1405 | +# |
1406 | +# This program is free software: you can redistribute it and/or modify |
1407 | +# it under the terms of the GNU General Public License as published by |
1408 | +# the Free Software Foundation, either version 3 of the License, or |
1409 | +# (at your option) any later version. |
1410 | +# |
1411 | +# This program is distributed in the hope that it will be useful, |
1412 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1413 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1414 | +# GNU General Public License for more details. |
1415 | +# |
1416 | +# You should have received a copy of the GNU General Public License |
1417 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1418 | +# |
1419 | + |
1420 | +"""Manage commands to be executed in a shell""" |
1421 | + |
1422 | + |
1423 | +def build_command(command, *args): |
1424 | + """ |
1425 | + Build a command with arguments |
1426 | + :param command: the executable that is going to be used |
1427 | + :param args: list of arguments for the command |
1428 | + :return: the command ready to be executed |
1429 | + """ |
1430 | + return'{c} {a}'.format(c=command, a=' '.join(args)).strip() |
1431 | |
1432 | === added file 'snappy_ecosystem_tests/utils/filters.py' |
1433 | --- snappy_ecosystem_tests/utils/filters.py 1970-01-01 00:00:00 +0000 |
1434 | +++ snappy_ecosystem_tests/utils/filters.py 2017-03-02 10:45:12 +0000 |
1435 | @@ -0,0 +1,51 @@ |
1436 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
1437 | + |
1438 | +# |
1439 | +# Snappy Ecosystem Tests |
1440 | +# Copyright (C) 2017 Canonical |
1441 | +# |
1442 | +# This program is free software: you can redistribute it and/or modify |
1443 | +# it under the terms of the GNU General Public License as published by |
1444 | +# the Free Software Foundation, either version 3 of the License, or |
1445 | +# (at your option) any later version. |
1446 | +# |
1447 | +# This program is distributed in the hope that it will be useful, |
1448 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1449 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1450 | +# GNU General Public License for more details. |
1451 | +# |
1452 | +# You should have received a copy of the GNU General Public License |
1453 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1454 | +# |
1455 | + |
1456 | +"""Filter utils""" |
1457 | + |
1458 | + |
1459 | +def object_filter(**predicates): |
1460 | + """ |
1461 | + Higher-order function to build and return an object filter function |
1462 | + :param predicates: key/values that represent |
1463 | + the conditions to look for in the object instance. |
1464 | + :return: a function to be used with filter or lambda expressions. |
1465 | + :raise: AttributeError if any of the attributes provided in predicates |
1466 | + does not exists |
1467 | + """ |
1468 | + def wrapped_filter(instance): |
1469 | + """wrapped function to be returned when calling object_filter""" |
1470 | + return all(getattr(instance, |
1471 | + param) == val for param, val in predicates.items()) |
1472 | + return wrapped_filter |
1473 | + |
1474 | + |
1475 | +def filter_list(objects_list, **predicates): |
1476 | + """ |
1477 | + Filter a list of objects with the given predicates |
1478 | + :param objects_list: the target list that contains |
1479 | + the objects to be filtered |
1480 | + :param predicates: key/values that represent |
1481 | + the conditions to look for in the object list. |
1482 | + :return: A list with the objects that match all the predicates |
1483 | + :raise: AttributeError if any of the attributes provided in predicates |
1484 | + does not exists |
1485 | + """ |
1486 | + return list(filter(object_filter(**predicates), objects_list)) |
1487 | |
1488 | === modified file 'snappy_ecosystem_tests/utils/ssh.py' |
1489 | --- snappy_ecosystem_tests/utils/ssh.py 2017-02-22 18:56:04 +0000 |
1490 | +++ snappy_ecosystem_tests/utils/ssh.py 2017-03-02 10:45:12 +0000 |
1491 | @@ -23,6 +23,8 @@ |
1492 | import paramiko |
1493 | |
1494 | from snappy_ecosystem_tests.utils.user import get_remote_host_credentials |
1495 | +from snappy_ecosystem_tests.helpers.snapd.staging_builder import ( |
1496 | + STAGING_VARIABLES) |
1497 | |
1498 | |
1499 | class SSHManager: |
1500 | @@ -83,10 +85,13 @@ |
1501 | :raises ValueError: if command exits with non-zero status. |
1502 | :return: the stdout of the command. |
1503 | """ |
1504 | - _hostname, _username, _port = get_remote_host_credentials() |
1505 | + # Take snapd remote credentials as default if they are not provided. |
1506 | + # Just arbitrary... Could have been other ones. |
1507 | + _hostname, _username, _port = get_snapd_remote_host_credentials() |
1508 | ssh = SSHManager.get_instance( |
1509 | hostname or _hostname, username or _username, port or _port) |
1510 | - _, stdout, stderr = ssh.exec_command(command) |
1511 | + _, stdout, stderr = ssh.exec_command( |
1512 | + command, environment=STAGING_VARIABLES) |
1513 | if stdout.channel.recv_exit_status() != 0: |
1514 | raise ValueError(stderr.read().decode()) |
1515 | return stdout.read().decode() |
1516 | |
1517 | === added file 'snappy_ecosystem_tests/utils/store_versions.py' |
1518 | --- snappy_ecosystem_tests/utils/store_versions.py 1970-01-01 00:00:00 +0000 |
1519 | +++ snappy_ecosystem_tests/utils/store_versions.py 2017-03-02 10:45:12 +0000 |
1520 | @@ -0,0 +1,74 @@ |
1521 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
1522 | + |
1523 | +# |
1524 | +# Snappy Ecosystem Tests |
1525 | +# Copyright (C) 2017 Canonical |
1526 | +# |
1527 | +# This program is free software: you can redistribute it and/or modify |
1528 | +# it under the terms of the GNU General Public License as published by |
1529 | +# the Free Software Foundation, either version 3 of the License, or |
1530 | +# (at your option) any later version. |
1531 | +# |
1532 | +# This program is distributed in the hope that it will be useful, |
1533 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1534 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1535 | +# GNU General Public License for more details. |
1536 | +# |
1537 | +# You should have received a copy of the GNU General Public License |
1538 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1539 | +# |
1540 | + |
1541 | +"""Utility for printing Store versions of: CPI, SCA and SSO. |
1542 | +To be called as a standalone script. |
1543 | +""" |
1544 | + |
1545 | +import requests |
1546 | + |
1547 | +DEFAULT_HEADER = "X-BZR-REVISION-NUMBER" |
1548 | + |
1549 | +SERVICES_INFO = dict( |
1550 | + CPI=('https://search.apps.ubuntu.com/api/v1', |
1551 | + 'https://search.apps.staging.ubuntu.com/api/v1'), |
1552 | + SCA=('https://myapps.developer.ubuntu.com/', |
1553 | + 'https://myapps.developer.staging.ubuntu.com/'), |
1554 | + SSO=('https://login.ubuntu.com/', |
1555 | + 'https://login.staging.ubuntu.com/'), |
1556 | +) |
1557 | + |
1558 | + |
1559 | +def get_deployed_revno(service, environment): |
1560 | + """Get revno from service.""" |
1561 | + prod, stag = SERVICES_INFO[service] |
1562 | + if environment == 'staging': |
1563 | + url = stag |
1564 | + else: |
1565 | + url = prod |
1566 | + with requests.Session() as session: |
1567 | + resp = session.get(url) |
1568 | + if resp.status_code == 200: |
1569 | + revno = resp.headers[DEFAULT_HEADER] |
1570 | + else: |
1571 | + print("{} 500'ed: {}".format(service, resp.text)) |
1572 | + revno = 0 |
1573 | + return service, environment, revno |
1574 | + |
1575 | + |
1576 | +def print_versions(): |
1577 | + """Print Store components version""" |
1578 | + coros = [] |
1579 | + for service in SERVICES_INFO: |
1580 | + coro = get_deployed_revno(service, 'staging') |
1581 | + coros.append(coro) |
1582 | + coro = get_deployed_revno(service, 'production') |
1583 | + coros.append(coro) |
1584 | + |
1585 | + data = {(service, kind): value for service, kind, value in coros} |
1586 | + print("#########################-STORE VERSIONS-#########################") |
1587 | + for service in sorted(SERVICES_INFO): |
1588 | + print("{}: Staging: {:>5}".format(service, |
1589 | + data[(service, 'staging')])) |
1590 | + print("{}: Production: {:>5}".format(service, |
1591 | + data[(service, 'production')])) |
1592 | + |
1593 | +if __name__ == '__main__': |
1594 | + print_versions() |
1595 | |
1596 | === modified file 'snappy_ecosystem_tests/utils/storeconfig.py' |
1597 | --- snappy_ecosystem_tests/utils/storeconfig.py 2017-02-15 19:14:19 +0000 |
1598 | +++ snappy_ecosystem_tests/utils/storeconfig.py 2017-03-02 10:45:12 +0000 |
1599 | @@ -27,8 +27,8 @@ |
1600 | USER_CONFIG_STACK |
1601 | ) |
1602 | |
1603 | -URL_WEB_STORE_PRODUCTION = CONFIG_STACK.get('web-ui', 'production_url') |
1604 | -URL_WEB_STORE_STAGING = CONFIG_STACK.get('web-ui', 'stage_url') |
1605 | +URL_WEB_STORE_PRODUCTION = CONFIG_STACK.get('production_urls', 'web') |
1606 | +URL_WEB_STORE_STAGING = CONFIG_STACK.get('staging_urls', 'web') |
1607 | |
1608 | |
1609 | def get_store_credentials(): |
1610 | |
1611 | === modified file 'snappy_ecosystem_tests/utils/user.py' |
1612 | --- snappy_ecosystem_tests/utils/user.py 2017-02-22 15:39:40 +0000 |
1613 | +++ snappy_ecosystem_tests/utils/user.py 2017-03-02 10:45:12 +0000 |
1614 | @@ -23,13 +23,34 @@ |
1615 | import os |
1616 | |
1617 | from snappy_ecosystem_tests.commons.config import USER_CONFIG_STACK |
1618 | - |
1619 | - |
1620 | -def get_remote_host_credentials(): |
1621 | - """Return credentials for remote machine, to run commands on.""" |
1622 | - return (USER_CONFIG_STACK.get('user', 'hostname_remote', |
1623 | - default=os.environ.get('hostname_remote')), |
1624 | - USER_CONFIG_STACK.get('user', 'username_remote', |
1625 | - default=os.environ.get('username_remote')), |
1626 | - USER_CONFIG_STACK.get('user', 'port_remote', |
1627 | - default=os.environ.get('port_remote'))) |
1628 | +from snappy_ecosystem_tests.environment.managers import get_manager |
1629 | + |
1630 | +MANAGER = get_manager(os.environ['target']) |
1631 | + |
1632 | + |
1633 | +def get_snapd_remote_host_credentials(): |
1634 | + """Return credentials for snapd remote machine, to run commands on.""" |
1635 | + _ip = MANAGER.get_ip(USER_CONFIG_STACK.get( |
1636 | + 'user', 'snapd_hostname_remote', |
1637 | + default=os.environ.get('snapd_hostname_remote'))) |
1638 | + return (_ip, |
1639 | + USER_CONFIG_STACK.get('user', 'snapd_username_remote', |
1640 | + default=os.environ.get( |
1641 | + 'snapd_username_remote')), |
1642 | + USER_CONFIG_STACK.get('user', 'snapd_port_remote', |
1643 | + default=os.environ.get( |
1644 | + 'snapd_port_remote'))) |
1645 | + |
1646 | + |
1647 | +def get_snapcraft_remote_host_credentials(): |
1648 | + """Return credentials for snapcraft remote machine, to run commands on.""" |
1649 | + _ip = MANAGER.get_ip(USER_CONFIG_STACK.get( |
1650 | + 'user', 'snapcraft_hostname_remote', |
1651 | + default=os.environ.get('snapcraft_snapcraft_remote'))) |
1652 | + return (_ip, |
1653 | + USER_CONFIG_STACK.get('user', 'snapcraft_username_remote', |
1654 | + default=os.environ.get( |
1655 | + 'snapcraft_username_remote')), |
1656 | + USER_CONFIG_STACK.get('user', 'snapcraft_port_remote', |
1657 | + default=os.environ.get( |
1658 | + 'snapcraft_port_remote'))) |
PASSED: Continuous integration, rev:24 /platform- qa-jenkins. ubuntu. com/job/ snappy- ecosystem- tests-ci/ 226/ /platform- qa-jenkins. ubuntu. com/job/ generic- update- mp/2027/ console
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild: /platform- qa-jenkins. ubuntu. com/job/ snappy- ecosystem- tests-ci/ 226/rebuild
https:/