Merge ~sylvain-pineau/checkbox-ng:launchpad_transport_removal into checkbox-ng:master

Proposed by Sylvain Pineau
Status: Merged
Approved by: Sylvain Pineau
Approved revision: a545a048948695daae0fac71d26562a2dc405a64
Merged at revision: 4c41422dae3b33a37457bebf6e0adace10f37199
Proposed branch: ~sylvain-pineau/checkbox-ng:launchpad_transport_removal
Merge into: checkbox-ng:master
Diff against target: 345 lines (+0/-269)
6 files modified
checkbox_ng/commands/newcli.py (+0/-45)
checkbox_ng/config.py (+0/-11)
dev/null (+0/-204)
requirements/container-tests-checkbox-ng-unit (+0/-5)
requirements/remove-deb-core.txt (+0/-1)
setup.py (+0/-3)
Reviewer Review Type Date Requested Status
Sylvain Pineau (community) Approve
Pierre Equoy Approve
Review via email: mp+308533@code.launchpad.net

Description of the change

We still have the ability to submit results to lp. This endpoint is never used in practice. Let's stop bundling this entry point in checkbox-ng.

Note we should also fix the packaging to remove checkbox-support.

To post a comment you must log in.
Revision history for this message
Pierre Equoy (pieq) wrote :

+1

Less code is better code!

(Do you have a separate MR for the packaging part?)

review: Approve
Revision history for this message
Sylvain Pineau (sylvain-pineau) wrote :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/checkbox_ng/commands/newcli.py b/checkbox_ng/commands/newcli.py
2index eeb781c..8d359c0 100644
3--- a/checkbox_ng/commands/newcli.py
4+++ b/checkbox_ng/commands/newcli.py
5@@ -415,51 +415,6 @@ class CliInvocation2(RunInvocation):
6 # Automatically try to submit results if the secure_id is
7 # valid
8 self.submit_certification_results()
9- elif self.launcher.submit_to == 'launchpad':
10- if self.config.email_address is Unset:
11- again = True
12- if not self.is_interactive:
13- again = False
14- while again:
15- if self.ask_for_confirmation(
16- _("\nSubmit results to launchpad.net/+hwdb?")):
17- self.config.email_address = input(
18- _("Email address: "))
19- again = False
20- self.submit_launchpad_results()
21- else:
22- again = False
23- else:
24- # Automatically try to submit results if the email_address
25- # is valid
26- self.submit_launchpad_results()
27-
28- def submit_launchpad_results(self):
29- transport_cls = get_all_transports().get('launchpad')
30- options_string = "field.emailaddress={}".format(
31- self.config.email_address)
32- transport = transport_cls(self.config.lp_url, options_string)
33- # TRANSLATORS: Do not translate the {} format markers.
34- print(_("Submitting results to {0} for email_address {1}").format(
35- self.config.lp_url, self.config.email_address))
36- with open(self.submission_file, encoding='utf-8') as stream:
37- try:
38- # NOTE: don't pass the file-like object to this transport
39- json = transport.send(
40- stream.read(),
41- self.config,
42- session_state=self.manager.state)
43- if json.get('url'):
44- # TRANSLATORS: Do not translate the {} format marker.
45- print(_("Submission uploaded to: {0}".format(json['url'])))
46- elif json.get('status'):
47- print(json['status'])
48- else:
49- # TRANSLATORS: Do not translate the {} format marker.
50- print(
51- _("Bad response from {0} transport".format(transport)))
52- except TransportError as exc:
53- print(str(exc))
54
55 def submit_certification_results(self):
56 from checkbox_ng.certification import InvalidSecureIDError
57diff --git a/checkbox_ng/config.py b/checkbox_ng/config.py
58index 92ded84..7107dc0 100644
59--- a/checkbox_ng/config.py
60+++ b/checkbox_ng/config.py
61@@ -50,23 +50,12 @@ class CheckBoxConfig(PlainBoxConfig):
62 help_text=_("Whether to also send the submission data to HEXR"),
63 kind=bool)
64
65- # TODO: Add a validator to check if email looks fine
66- email_address = config.Variable(
67- section="sru",
68- help_text=_("Email address to log into the Launchpad HWDB"))
69-
70 # TODO: Add a validator to check if URL looks fine
71 c3_url = config.Variable(
72 section="sru",
73 help_text=_("URL of the certification website"),
74 default="https://certification.canonical.com/submissions/submit/")
75
76- # TODO: Add a validator to check if URL looks fine
77- lp_url = config.Variable(
78- section="sru",
79- help_text=_("URL of the launchpad hardware database"),
80- default="https://launchpad.net/+hwdb/+submit")
81-
82 fallback_file = config.Variable(
83 section="sru",
84 help_text=_("Location of the fallback file"))
85diff --git a/checkbox_ng/launchpad.py b/checkbox_ng/launchpad.py
86deleted file mode 100644
87index e6e6725..0000000
88--- a/checkbox_ng/launchpad.py
89+++ /dev/null
90@@ -1,204 +0,0 @@
91-# This file is part of Checkbox.
92-#
93-# Copyright 2014 Canonical Ltd.
94-# Written by:
95-# Brendan Donegan <brendan.donegan@canonical.com>
96-#
97-# Checkbox is free software: you can redistribute it and/or modify
98-# it under the terms of the GNU General Public License version 3,
99-# as published by the Free Software Foundation.
100-
101-#
102-# Checkbox is distributed in the hope that it will be useful,
103-# but WITHOUT ANY WARRANTY; without even the implied warranty of
104-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
105-# GNU General Public License for more details.
106-#
107-# You should have received a copy of the GNU General Public License
108-# along with Checkbox. If not, see <http://www.gnu.org/licenses/>.
109-
110-"""
111-:mod:`checkbox_ng.launchpad` -- plainbox transport to Launchpad database
112-=============================================================================
113-
114-This module contains a PlainBox transport that knows how to send the
115-submission XML data to the Launchpad hardware database.
116-"""
117-from datetime import datetime
118-from gettext import gettext as _
119-from io import BytesIO
120-from logging import getLogger
121-from socket import gethostname
122-import bz2
123-import hashlib
124-
125-import requests
126-
127-from checkbox_support.lib.dmi import Dmi
128-from plainbox.impl.secure.config import Unset
129-from plainbox.impl.transport import TransportBase, TransportError
130-
131-logger = getLogger("checkbox.ng.launchpad")
132-
133-
134-class InvalidSubmissionDataError(TransportError):
135- def __init__(self, value):
136- self.value = value
137-
138- def __str__(self):
139- return repr(self.value)
140-
141-
142-class LaunchpadTransport(TransportBase):
143- """
144- Transport for sending data to Launchpad database.
145- - POSTs data to a http(s) endpoint
146- - Adds a header with a hardware identifier
147- - Data is expected to be in checkbox xml-compatible format.
148- This means it will work best with a stream produced by the
149- xml exporter.
150- """
151-
152- def _get_resource_attr(self, session_state, resource, attr):
153- resource_result = session_state.resource_map.get(resource)
154- if not resource_result:
155- raise InvalidSubmissionDataError(
156- _("Cannot get {0} resource job").format(resource))
157- attr_value = getattr(resource_result[0], attr)
158- if attr_value is None:
159- raise InvalidSubmissionDataError(
160- _("{0} has no attribute {1}").format(resource, attr))
161- return attr_value
162-
163- def _get_launchpad_form_fields(self, session_state):
164- form_fields = {}
165- form_fields['field.private'] = 'False'
166- form_fields['field.contactable'] = 'False'
167- form_fields['field.live_cd'] = 'False'
168- form_fields['field.format'] = 'VERSION_1'
169- form_fields['field.actions.upload'] = 'Upload'
170- form_fields['field.date_created'] = datetime.utcnow().strftime(
171- "%Y-%m-%dT%H:%M:%S")
172- arch = self._get_resource_attr(
173- session_state, '2013.com.canonical.certification::dpkg',
174- 'architecture')
175- form_fields['field.architecture'] = arch
176- distro = self._get_resource_attr(
177- session_state, '2013.com.canonical.certification::lsb',
178- 'distributor_id')
179- form_fields['field.distribution'] = distro
180- series = self._get_resource_attr(
181- session_state, '2013.com.canonical.certification::lsb', 'codename')
182- form_fields['field.distroseries'] = series
183- dmi_resources = session_state.resource_map.get(
184- '2013.com.canonical.certification::dmi')
185- if dmi_resources is None:
186- raise InvalidSubmissionDataError(
187- _("DMI resources not found"))
188- system_id = ""
189- for resource in dmi_resources:
190- if resource.category == 'CHASSIS':
191- chassis_type = Dmi.chassis_name_to_type[resource.product]
192- vendor = getattr(resource, 'vendor', "")
193- model = getattr(resource, 'model', "")
194- fingerprint = hashlib.md5()
195- for field in ["Computer", "unknown", chassis_type,
196- vendor, model]:
197- fingerprint.update(field.encode('utf-8'))
198- system_id = fingerprint.hexdigest()
199- if not system_id:
200- raise InvalidSubmissionDataError(_("System ID not found"))
201- form_fields['field.system'] = system_id
202- fingerprint = hashlib.md5()
203- fingerprint.update(system_id.encode('utf-8'))
204- fingerprint.update(str(datetime.utcnow()).encode('utf-8'))
205- form_fields['field.submission_key'] = fingerprint.hexdigest()
206- return form_fields
207-
208- def send(self, data, config=None, session_state=None):
209- """ Sends data to the specified server.
210-
211- :param data:
212- Data containing the xml dump to be sent to the server. This can be
213- either bytes or a file-like object (BytesIO works fine too). If
214- this is a file-like object, it will be read and streamed "on the
215- fly".
216- :param config:
217- An optional PlainBoxConfig object. If http_proxy and https_proxy
218- values are set in this config object, they will be used to send
219- data via the specified protocols. Note that the transport also
220- honors the http_proxy and https_proxy environment variables.
221- Proxy string format is http://[user:password@]<proxy-ip>:port
222- :param session_state:
223- ?
224- :returns:
225- A dictionary with responses from the server if submission was
226- successful and empty dictionary otherwise.
227- :raises ValueError:
228- If no session state was provided.
229- :raises TransportError:
230- - If sending timed out.
231- - If connection failed outright.
232- - If the server returned
233- a non-success result code
234- - If a required resource job is missing from the submission
235- or a resource job is missing a required attribute. The following
236- resource/attribute pairs are needed:
237- - dpkg: architecture
238- - lsb: distributor_id
239- - lsb: codename
240- - dmi: product
241- """
242- proxies = None
243- if config and config.environment is not Unset:
244- proxies = {
245- proto[:-len("_proxy")]: config.environment[proto]
246- for proto in ['http_proxy', 'https_proxy']
247- if proto in config.environment
248- }
249-
250- if session_state is None:
251- raise ValueError("LaunchpadTransport requires a session "
252- "state to be provided.")
253-
254- logger.debug("Sending to %s, email is %s",
255- self.url, self.options['field.emailaddress'])
256- lp_headers = {"x-launchpad-hwdb-submission": ""}
257-
258- form_fields = self._get_launchpad_form_fields(session_state)
259- form_fields['field.emailaddress'] = self.options['field.emailaddress']
260-
261- compressed_payload = bz2.compress(data.encode('utf-8'))
262- file = BytesIO(compressed_payload)
263- file.name = "{}.xml.bz2".format(gethostname())
264- file.size = len(compressed_payload)
265- submission_data = {'field.submission_data': file}
266- try:
267- response = requests.post(self.url, data=form_fields,
268- files=submission_data,
269- headers=lp_headers,
270- proxies=proxies)
271- except requests.exceptions.Timeout as exc:
272- raise TransportError(
273- _("Request to {0} timed out: {1}").format(self.url, exc))
274- except requests.exceptions.InvalidSchema as exc:
275- raise TransportError(
276- _("Invalid destination URL: {0}").format(exc))
277- except requests.exceptions.ConnectionError as exc:
278- raise TransportError(
279- _("Unable to connect to {0}: {1}").format(self.url, exc))
280- if response is not None:
281- try:
282- # This will raise HTTPError for status != 20x
283- response.raise_for_status()
284- except requests.exceptions.RequestException as exc:
285- raise TransportError(str(exc))
286- logger.debug(_("Success! Server said %s"), response.text)
287- status = _('The submission was uploaded to Launchpad successfully')
288- if (response.headers['x-launchpad-hwdb-submission'] != (
289- 'OK data stored')):
290- status = response.headers['x-launchpad-hwdb-submission']
291- return {'status': status}
292-
293- # ISessionStateTransport.send must return dictionary
294- return {}
295diff --git a/requirements/container-tests-checkbox-ng-unit b/requirements/container-tests-checkbox-ng-unit
296index f08f8a8..5d99ea2 100755
297--- a/requirements/container-tests-checkbox-ng-unit
298+++ b/requirements/container-tests-checkbox-ng-unit
299@@ -2,7 +2,6 @@
300
301 function finish {
302 rm -rf ./plainbox
303- rm -rf ./checkbox-support
304 }
305 trap finish EXIT
306
307@@ -12,8 +11,4 @@ git clone git://git.launchpad.net/plainbox
308 echo "I: running 'develop' on plainbox"
309 ( cd ./plainbox/ && python3 setup.py develop --quiet | sed -e 's/^/I (develop output) /' )
310
311-git clone git://git.launchpad.net/checkbox-support
312-echo "I: running 'develop' on checkbox-support"
313-( cd ./checkbox-support/ && python3 setup.py develop --quiet | sed -e 's/^/I (develop output) /' )
314-
315 python3 setup.py test
316diff --git a/requirements/remove-deb-core.txt b/requirements/remove-deb-core.txt
317index 0d3e59d..fc8e225 100644
318--- a/requirements/remove-deb-core.txt
319+++ b/requirements/remove-deb-core.txt
320@@ -1,4 +1,3 @@
321 checkbox-cli
322 checkbox-ng
323-checkbox-ng-service
324 python3-chekbox-ng
325diff --git a/setup.py b/setup.py
326index afd6396..9278d8e 100755
327--- a/setup.py
328+++ b/setup.py
329@@ -47,7 +47,6 @@ if on_rtd:
330 install_requires = ['plainbox >= 0.5.3',]
331 else:
332 install_requires = [
333- 'checkbox-support >= 0.2',
334 'guacamole >= 0.9',
335 'plainbox >= 0.5.3',
336 'requests >= 1.0',
337@@ -75,8 +74,6 @@ setup(
338 'plainbox.transport': [
339 'certification='
340 'checkbox_ng.certification:CertificationTransport',
341- 'launchpad='
342- 'checkbox_ng.launchpad:LaunchpadTransport',
343 ],
344 },
345 include_package_data=True)

Subscribers

People subscribed via source and target branches