Merge ~suligap/snapstore-client:airgap-related-bugfixes into snapstore-client:master

Proposed by Przemysław Suliga
Status: Merged
Approved by: Przemysław Suliga
Approved revision: 9c22a4221a0a608f0bf150a9c0434ba8119c8d61
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~suligap/snapstore-client:airgap-related-bugfixes
Merge into: snapstore-client:master
Diff against target: 179 lines (+71/-13)
3 files modified
snapstore_client/logic/push.py (+29/-6)
snapstore_client/logic/tests/test-snap-assert.assert (+1/-1)
snapstore_client/logic/tests/test_push.py (+41/-6)
Reviewer Review Type Date Requested Status
Simon Davy (community) Approve
Review via email: mp+381974@code.launchpad.net

Commit message

Fixes for remote airgap snap uploads

- missing utf-8 encoding of assertions payload
- ignore missing revisions when uploading snap files
- missing package_type field in various API calls

Description of the change

Tested this locally against an airgap proxy built from recent snapstore-snap master.

To post a comment you must log in.
Revision history for this message
Simon Davy (bloodearnest) wrote :

LGTM. If you think snap-store-proxy has not had attention, the client is worse :(

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/snapstore_client/logic/push.py b/snapstore_client/logic/push.py
index abd06e8..1a91bbb 100644
--- a/snapstore_client/logic/push.py
+++ b/snapstore_client/logic/push.py
@@ -40,6 +40,7 @@ def _push_ident(store, password, downloaded_map):
40 snap_details = downloaded_map['snap']40 snap_details = downloaded_map['snap']
41 push_details = {41 push_details = {
42 'snap_id': snap_id,42 'snap_id': snap_id,
43 'package_type': 'snap',
43 'snap_name': snap_details['name'],44 'snap_name': snap_details['name'],
44 'private': False, # If you're pushing to your own proxy45 'private': False, # If you're pushing to your own proxy
45 'stores': ['ubuntu'], # ditto46 'stores': ['ubuntu'], # ditto
@@ -84,6 +85,7 @@ def _push_revs(store, password, downloaded_map):
84 # create the revision85 # create the revision
85 rev = {86 rev = {
86 'snap_id': snap_id,87 'snap_id': snap_id,
88 'package_type': 'snap',
87 'revision': instance['revision'],89 'revision': instance['revision'],
88 'version': instance['version'],90 'version': instance['version'],
89 'confinement': instance['confinement'],91 'confinement': instance['confinement'],
@@ -118,10 +120,19 @@ def _push_channelmap(store, password, downloaded_map, force_push=False):
118120
119 snap_id = downloaded_map['snap-id']121 snap_id = downloaded_map['snap-id']
120122
123 filter_payload = {
124 'filters': [
125 {
126 'series': '16',
127 'package_type': 'snap',
128 'snap_id': snap_id,
129 },
130 ],
131 }
121 # Check if we have an existing channel map132 # Check if we have an existing channel map
122 existing = requests.post(133 existing = requests.post(
123 store_url + '/channelmaps/filter',134 store_url + '/channelmaps/filter',
124 json={'filters': [{'series': '16', 'snap_id': snap_id}]},135 json=filter_payload,
125 auth=requests.auth.HTTPBasicAuth(USERNAME, password))136 auth=requests.auth.HTTPBasicAuth(USERNAME, password))
126 if existing.status_code != 200:137 if existing.status_code != 200:
127 raise pushException("Error retrieving current channelmap")138 raise pushException("Error retrieving current channelmap")
@@ -140,6 +151,7 @@ def _push_channelmap(store, password, downloaded_map, force_push=False):
140 'developer_id': downloaded_map['snap']['publisher']['id'],151 'developer_id': downloaded_map['snap']['publisher']['id'],
141 'release_requests': [152 'release_requests': [
142 {153 {
154 'package_type': 'snap',
143 'snap_id': snap_id,155 'snap_id': snap_id,
144 'channel': [156 'channel': [
145 track,157 track,
@@ -204,7 +216,7 @@ def _add_assertion_to_service(store, password, list_assertions):
204 continue216 continue
205 response = requests.post(217 response = requests.post(
206 store_url + '/v1/assertions',218 store_url + '/v1/assertions',
207 '\n'.join(assertion),219 '\n'.join(assertion).encode('utf-8'),
208 headers={'Content-Type': 'application/x.ubuntu.assertion'},220 headers={'Content-Type': 'application/x.ubuntu.assertion'},
209 auth=requests.auth.HTTPBasicAuth(USERNAME, password))221 auth=requests.auth.HTTPBasicAuth(USERNAME, password))
210 if response.status_code != 201:222 if response.status_code != 201:
@@ -278,10 +290,21 @@ def _push(store, tar_file, password, force_channel_map=False):
278 snap_name, instance['revision'])290 snap_name, instance['revision'])
279 snap_path = str(json_path.parent / snap_file_name)291 snap_path = str(json_path.parent / snap_file_name)
280 assert_path = str(json_path.parent / assert_file_name)292 assert_path = str(json_path.parent / assert_file_name)
281 _push_file_to_nginx_cache(293 try:
282 store, password, snap_path,294 _push_file_to_nginx_cache(
283 downloaded_map['snap-id'], instance['revision'])295 store, password, snap_path,
284 _push_assertions(store, password, assert_path)296 downloaded_map['snap-id'], instance['revision'],
297 )
298 except FileNotFoundError as exc:
299 logger.warning(
300 'Skipping revision %s (%s/%s) as %s not found',
301 instance['revision'],
302 instance['channel']['name'],
303 instance['channel']['architecture'],
304 exc.filename,
305 )
306 else:
307 _push_assertions(store, password, assert_path)
285308
286309
287def push_snap(args):310def push_snap(args):
diff --git a/snapstore_client/logic/tests/test-snap-assert.assert b/snapstore_client/logic/tests/test-snap-assert.assert
index b6b2ebd..4eda67a 100644
--- a/snapstore_client/logic/tests/test-snap-assert.assert
+++ b/snapstore_client/logic/tests/test-snap-assert.assert
@@ -42,7 +42,7 @@ oG3Ie3WOHrVjCLXIdYslpL1O4nadqR6Xv58pHj6k
42type: account42type: account
43authority-id: canonical43authority-id: canonical
44account-id: 1RgHGj7Zp3nyycrGa5sODDbZznzJAwAX44account-id: 1RgHGj7Zp3nyycrGa5sODDbZznzJAwAX
45display-name: Tom Wardill45display-name: Tom Wardill (Ω)
46timestamp: 2018-02-06T09:22:49.118291Z46timestamp: 2018-02-06T09:22:49.118291Z
47username: twom47username: twom
48validation: unproven48validation: unproven
diff --git a/snapstore_client/logic/tests/test_push.py b/snapstore_client/logic/tests/test_push.py
index 7fedbbd..cda240c 100644
--- a/snapstore_client/logic/tests/test_push.py
+++ b/snapstore_client/logic/tests/test_push.py
@@ -37,9 +37,15 @@ class pushTests(TestCase):
3737
38 _push_ident(self.store, 'test', self.snap_map)38 _push_ident(self.store, 'test', self.snap_map)
3939
40 request = responses.calls[0].request
41 payload = json.loads(request.body.decode('utf-8'))
42
40 self.assertEqual(43 self.assertEqual(
41 'Basic YWRtaW46dGVzdA==',44 payload['snaps'][0]['package_type'], 'snap',
42 responses.calls[0].request.headers['Authorization'])45 )
46 self.assertEqual(
47 'Basic YWRtaW46dGVzdA==', request.headers['Authorization'],
48 )
4349
44 @responses.activate50 @responses.activate
45 def test_push_ident_failed(self):51 def test_push_ident_failed(self):
@@ -56,9 +62,13 @@ class pushTests(TestCase):
5662
57 _push_revs(self.store, 'test', self.snap_map)63 _push_revs(self.store, 'test', self.snap_map)
5864
65 request = responses.calls[0].request
66 payload = json.loads(request.body.decode('utf-8'))
67
68 self.assertEqual(payload[0]['package_type'], 'snap')
59 self.assertEqual(69 self.assertEqual(
60 'Basic YWRtaW46dGVzdA==',70 'Basic YWRtaW46dGVzdA==', request.headers['Authorization'],
61 responses.calls[0].request.headers['Authorization'])71 )
6272
63 @responses.activate73 @responses.activate
64 def test_push_revs_unexpected_status_code(self):74 def test_push_revs_unexpected_status_code(self):
@@ -85,9 +95,30 @@ class pushTests(TestCase):
8595
86 _push_channelmap(self.store, 'test', self.snap_map)96 _push_channelmap(self.store, 'test', self.snap_map)
8797
98 filter_request = responses.calls[0].request
99 filter_payload = json.loads(filter_request.body.decode('utf-8'))
88 self.assertEqual(100 self.assertEqual(
89 'Basic YWRtaW46dGVzdA==',101 filter_payload['filters'],
90 responses.calls[0].request.headers['Authorization'])102 [
103 {
104 'series': '16',
105 'package_type': 'snap',
106 'snap_id': self.snap_map['snap-id'],
107 },
108 ],
109 )
110 self.assertEqual(
111 'Basic YWRtaW46dGVzdA==', filter_request.headers['Authorization'],
112 )
113
114 chanmap_update_request = responses.calls[1].request
115 chanmap_update_payload = json.loads(
116 chanmap_update_request.body.decode('utf-8'),
117 )
118 self.assertEqual(
119 chanmap_update_payload['release_requests'][0]['package_type'],
120 'snap',
121 )
91122
92 @responses.activate123 @responses.activate
93 def test_push_map_failed(self):124 def test_push_map_failed(self):
@@ -144,6 +175,10 @@ class pushTests(TestCase):
144 split_assertions = _split_assertions(self.snap_assert)175 split_assertions = _split_assertions(self.snap_assert)
145 _add_assertion_to_service(self.store, 'test', split_assertions)176 _add_assertion_to_service(self.store, 'test', split_assertions)
146177
178 self.assertIn(
179 'display-name: Tom Wardill (Ω)',
180 responses.calls[0].request.body.decode('utf-8'),
181 )
147 self.assertEqual(182 self.assertEqual(
148 'Basic YWRtaW46dGVzdA==',183 'Basic YWRtaW46dGVzdA==',
149 responses.calls[0].request.headers['Authorization'])184 responses.calls[0].request.headers['Authorization'])

Subscribers

People subscribed via source and target branches

to all changes: