Merge lp:~simpoir/landscape-client/bug_1531150_package_reporter_proxy into lp:~landscape/landscape-client/trunk

Proposed by Simon Poirier
Status: Merged
Approved by: Simon Poirier
Approved revision: 917
Merged at revision: 919
Proposed branch: lp:~simpoir/landscape-client/bug_1531150_package_reporter_proxy
Merge into: lp:~landscape/landscape-client/trunk
Diff against target: 247 lines (+121/-8)
5 files modified
apt-update/apt-update.c (+19/-1)
landscape/lib/fetch.py (+5/-1)
landscape/lib/tests/test_fetch.py (+8/-0)
landscape/package/reporter.py (+17/-2)
landscape/package/tests/test_reporter.py (+72/-4)
To merge this branch: bzr merge lp:~simpoir/landscape-client/bug_1531150_package_reporter_proxy
Reviewer Review Type Date Requested Status
Adam Collard (community) Approve
🤖 Landscape Builder test results Approve
Eric Snow (community) Approve
Review via email: mp+301774@code.launchpad.net

Commit message

Add proxy handling to package reporter.

Description of the change

Add proxy handling to package reporter.

To post a comment you must log in.
Revision history for this message
🤖 Landscape Builder (landscape-builder) :
review: Abstain (executing tests)
Revision history for this message
🤖 Landscape Builder (landscape-builder) wrote :

Command: TRIAL_ARGS=-j4 make check
Result: Success
Revno: 916
Branch: lp:~simpoir/landscape-client/bug_1531150_package_reporter_proxy
Jenkins: https://ci.lscape.net/job/latch-test/5865/

review: Approve (test results)
Revision history for this message
Eric Snow (ericsnowcurrently) wrote :

Aside from a couple small issues and a few questions, LGTM.

Just to make sure I understand, currently there are 2 separate situations where package-reporter ignores the landscape-configured proxy values: the apt-update helper and fetching the hash-id-database. Are there other situations where package-reporter is handling the proxy correctly?

Also, you're solving the apt-update problem by passing the proxy settings from the config into the env vars under which the apt-update helper runs. For the fetch issue, you're passing the proxy in to fetch() and on to curl. Is all that right?

review: Needs Information
Revision history for this message
Simon Poirier (simpoir) :
917. By Simon Poirier

address some comments from ericsnow

Revision history for this message
🤖 Landscape Builder (landscape-builder) :
review: Abstain (executing tests)
Revision history for this message
🤖 Landscape Builder (landscape-builder) wrote :

Command: TRIAL_ARGS=-j4 make check
Result: Success
Revno: 917
Branch: lp:~simpoir/landscape-client/bug_1531150_package_reporter_proxy
Jenkins: https://ci.lscape.net/job/latch-test/6189/

review: Approve (test results)
Revision history for this message
Eric Snow (ericsnowcurrently) wrote :

+1

review: Approve
Revision history for this message
🤖 Landscape Builder (landscape-builder) :
review: Abstain (executing tests)
Revision history for this message
🤖 Landscape Builder (landscape-builder) wrote :

Command: TRIAL_ARGS=-j4 make check
Result: Success
Revno: 917
Branch: lp:~simpoir/landscape-client/bug_1531150_package_reporter_proxy
Jenkins: https://ci.lscape.net/job/latch-test/6578/

review: Approve (test results)
Revision history for this message
Adam Collard (adam-collard) :
review: Needs Information
Revision history for this message
🤖 Landscape Builder (landscape-builder) :
review: Abstain (executing tests)
Revision history for this message
🤖 Landscape Builder (landscape-builder) wrote :

Command: TRIAL_ARGS=-j4 make check
Result: Success
Revno: 917
Branch: lp:~simpoir/landscape-client/bug_1531150_package_reporter_proxy
Jenkins: https://ci.lscape.net/job/latch-test/7166/

review: Approve (test results)
Revision history for this message
🤖 Landscape Builder (landscape-builder) :
review: Abstain (executing tests)
Revision history for this message
🤖 Landscape Builder (landscape-builder) wrote :

Command: TRIAL_ARGS=-j4 make check
Result: Success
Revno: 917
Branch: lp:~simpoir/landscape-client/bug_1531150_package_reporter_proxy
Jenkins: https://ci.lscape.net/job/latch-test/7455/

review: Approve (test results)
Revision history for this message
🤖 Landscape Builder (landscape-builder) :
review: Abstain (executing tests)
Revision history for this message
🤖 Landscape Builder (landscape-builder) wrote :

Command: TRIAL_ARGS=-j4 make check
Result: Success
Revno: 917
Branch: lp:~simpoir/landscape-client/bug_1531150_package_reporter_proxy
Jenkins: https://ci.lscape.net/job/latch-test/7832/

review: Approve (test results)
Revision history for this message
🤖 Landscape Builder (landscape-builder) :
review: Abstain (executing tests)
Revision history for this message
🤖 Landscape Builder (landscape-builder) wrote :

Command: TRIAL_ARGS=-j4 make check
Result: Success
Revno: 917
Branch: lp:~simpoir/landscape-client/bug_1531150_package_reporter_proxy
Jenkins: https://ci.lscape.net/job/latch-test/7845/

review: Approve (test results)
Revision history for this message
🤖 Landscape Builder (landscape-builder) :
review: Abstain (executing tests)
Revision history for this message
🤖 Landscape Builder (landscape-builder) wrote :

Command: TRIAL_ARGS=-j4 make check
Result: Success
Revno: 917
Branch: lp:~simpoir/landscape-client/bug_1531150_package_reporter_proxy
Jenkins: https://ci.lscape.net/job/latch-test/7890/

review: Approve (test results)
Revision history for this message
Simon Poirier (simpoir) :
Revision history for this message
🤖 Landscape Builder (landscape-builder) :
review: Abstain (executing tests)
Revision history for this message
🤖 Landscape Builder (landscape-builder) wrote :

Command: TRIAL_ARGS=-j4 make check
Result: Success
Revno: 917
Branch: lp:~simpoir/landscape-client/bug_1531150_package_reporter_proxy
Jenkins: https://ci.lscape.net/job/latch-test/7929/

review: Approve (test results)
Revision history for this message
Adam Collard (adam-collard) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'apt-update/apt-update.c'
2--- apt-update/apt-update.c 2011-11-08 10:54:08 +0000
3+++ apt-update/apt-update.c 2016-08-04 16:13:30 +0000
4@@ -19,7 +19,7 @@
5 int main(int argc, char *argv[], char *envp[])
6 {
7 char *apt_argv[] = {"/usr/bin/apt-get", "-q", "update", NULL};
8- char *apt_envp[] = {"PATH=/bin:/usr/bin", NULL, NULL};
9+ char *apt_envp[] = {"PATH=/bin:/usr/bin", NULL, NULL, NULL, NULL};
10
11 // Set the HOME environment variable
12 struct passwd *pwd = getpwuid(geteuid());
13@@ -33,6 +33,24 @@
14 exit(1);
15 }
16
17+ // Pass proxy environment variables
18+ int proxy_arg = 2;
19+ char *http_proxy = getenv("http_proxy");
20+ if (http_proxy) {
21+ if (asprintf(&apt_envp[proxy_arg], "http_proxy=%s", http_proxy) == -1) {
22+ perror("error: Unable to set http_proxy environment variable");
23+ exit(1);
24+ }
25+ proxy_arg++;
26+ }
27+ char *https_proxy = getenv("https_proxy");
28+ if (https_proxy) {
29+ if (asprintf(&apt_envp[proxy_arg], "https_proxy=%s", https_proxy) == -1) {
30+ perror("error: Unable to set https_proxy environment variable");
31+ exit(1);
32+ }
33+ }
34+
35 // Drop any supplementary group
36 if (setgroups(0, NULL) == -1) {
37 perror("error: Unable to set supplementary groups IDs");
38
39=== modified file 'landscape/lib/fetch.py'
40--- landscape/lib/fetch.py 2014-12-04 09:48:07 +0000
41+++ landscape/lib/fetch.py 2016-08-04 16:13:30 +0000
42@@ -45,7 +45,7 @@
43
44 def fetch(url, post=False, data="", headers={}, cainfo=None, curl=None,
45 connect_timeout=30, total_timeout=600, insecure=False, follow=True,
46- user_agent=None):
47+ user_agent=None, proxy=None):
48 """Retrieve a URL and return the content.
49
50 @param url: The url to be fetched.
51@@ -61,6 +61,7 @@
52 during autodiscovery)
53 @param follow: If True, follow HTTP redirects (default True).
54 @param user_agent: The user-agent to set in the request.
55+ @param proxy: The proxy url to use for the request.
56 """
57 import pycurl
58 output = StringIO(data)
59@@ -94,6 +95,9 @@
60 if user_agent is not None:
61 curl.setopt(pycurl.USERAGENT, user_agent)
62
63+ if proxy is not None:
64+ curl.setopt(pycurl.PROXY, proxy)
65+
66 curl.setopt(pycurl.MAXREDIRS, 5)
67 curl.setopt(pycurl.CONNECTTIMEOUT, connect_timeout)
68 curl.setopt(pycurl.LOW_SPEED_LIMIT, 1)
69
70=== modified file 'landscape/lib/tests/test_fetch.py'
71--- landscape/lib/tests/test_fetch.py 2015-06-08 08:16:10 +0000
72+++ landscape/lib/tests/test_fetch.py 2016-08-04 16:13:30 +0000
73@@ -286,6 +286,14 @@
74 self.assertEqual(result, "result")
75 self.assertEqual("user-agent", curl.options[pycurl.USERAGENT])
76
77+ def test_pycurl_proxy(self):
78+ """If provided, the proxy is set in the request."""
79+ curl = CurlStub("result")
80+ proxy = "http://my.little.proxy"
81+ result = fetch("http://example.com", curl=curl, proxy=proxy)
82+ self.assertEqual("result", result)
83+ self.assertEqual(proxy, curl.options[pycurl.PROXY])
84+
85 def test_create_curl(self):
86 curls = []
87
88
89=== modified file 'landscape/package/reporter.py'
90--- landscape/package/reporter.py 2015-01-12 12:53:36 +0000
91+++ landscape/package/reporter.py 2016-08-04 16:13:30 +0000
92@@ -37,6 +37,10 @@
93 parser.add_option("--force-apt-update", default=False,
94 action="store_true",
95 help="Force running apt-update.")
96+ parser.add_option("--http-proxy", metavar="URL",
97+ help="The URL of the HTTP proxy, if one is needed.")
98+ parser.add_option("--https-proxy", metavar="URL",
99+ help="The URL of the HTTPS proxy, if one is needed.")
100 return parser
101
102
103@@ -132,8 +136,14 @@
104 logging.warning("Couldn't download hash=>id database: %s" %
105 str(exception))
106
107+ if url.startswith("https"):
108+ proxy = self._config.get("https_proxy")
109+ else:
110+ proxy = self._config.get("http_proxy")
111+
112 result = fetch_async(url,
113- cainfo=self._config.get("ssl_public_key"))
114+ cainfo=self._config.get("ssl_public_key"),
115+ proxy=proxy)
116 result.addCallback(fetch_ok)
117 result.addErrback(fetch_error)
118
119@@ -261,7 +271,12 @@
120 Run apt-update using the passed in deferred, which allows for callers
121 to inspect the result code.
122 """
123- result = spawn_process(self.apt_update_filename)
124+ env = {}
125+ if self._config.http_proxy:
126+ env["http_proxy"] = self._config.http_proxy
127+ if self._config.https_proxy:
128+ env["https_proxy"] = self._config.https_proxy
129+ result = spawn_process(self.apt_update_filename, env=env)
130
131 def callback((out, err, code), deferred):
132 return deferred.callback((out, err, code))
133
134=== modified file 'landscape/package/tests/test_reporter.py'
135--- landscape/package/tests/test_reporter.py 2016-06-16 22:52:21 +0000
136+++ landscape/package/tests/test_reporter.py 2016-08-04 16:13:30 +0000
137@@ -300,7 +300,35 @@
138
139 logging_mock.assert_called_once_with(
140 "Downloaded hash=>id database from %s" % hash_id_db_url)
141- mock_fetch_async.assert_called_once_with(hash_id_db_url, cainfo=None)
142+ mock_fetch_async.assert_called_once_with(
143+ hash_id_db_url, cainfo=None, proxy=None)
144+ return result
145+
146+ @mock.patch("landscape.package.reporter.fetch_async",
147+ return_value=succeed("hash-ids"))
148+ @mock.patch("logging.info", return_value=None)
149+ def test_fetch_hash_id_db_with_proxy(self, logging_mock, mock_fetch_async):
150+ """fetching hash-id-db uses proxy settings"""
151+ # Assume package_hash_id_url is set
152+ self.config.data_path = self.makeDir()
153+ self.config.package_hash_id_url = "https://fake.url/path/"
154+ os.makedirs(os.path.join(self.config.data_path, "package", "hash-id"))
155+
156+ # Fake uuid, codename and arch
157+ message_store = self.broker_service.message_store
158+ message_store.set_server_uuid("uuid")
159+ self.reporter.lsb_release_filename = self.makeFile(SAMPLE_LSB_RELEASE)
160+ self.facade.set_arch("arch")
161+
162+ # Let's say fetch_async is successful
163+ hash_id_db_url = self.config.package_hash_id_url + "uuid_codename_arch"
164+
165+ # set proxy settings
166+ self.config.https_proxy = "http://helloproxy:8000"
167+
168+ result = self.reporter.fetch_hash_id_db()
169+ mock_fetch_async.assert_called_once_with(
170+ hash_id_db_url, cainfo=None, proxy="http://helloproxy:8000")
171 return result
172
173 @mock.patch("landscape.package.reporter.fetch_async")
174@@ -409,7 +437,8 @@
175 self.assertTrue(os.path.exists(hash_id_db_filename))
176 self.assertEqual(open(hash_id_db_filename).read(), "hash-ids")
177 result.addCallback(callback)
178- mock_fetch_async.assert_called_once_with(hash_id_db_url, cainfo=None)
179+ mock_fetch_async.assert_called_once_with(
180+ hash_id_db_url, cainfo=None, proxy=None)
181 return result
182
183 @mock.patch("landscape.package.reporter.fetch_async",
184@@ -443,7 +472,8 @@
185
186 logging_mock.assert_called_once_with(
187 "Couldn't download hash=>id database: fetch error")
188- mock_fetch_async.assert_called_once_with(hash_id_db_url, cainfo=None)
189+ mock_fetch_async.assert_called_once_with(
190+ hash_id_db_url, cainfo=None, proxy=None)
191 return result
192
193 @mock.patch("logging.warning", return_value=None)
194@@ -497,7 +527,7 @@
195 # Now go!
196 result = self.reporter.fetch_hash_id_db()
197 mock_fetch_async.assert_called_once_with(
198- hash_id_db_url, cainfo=self.config.ssl_public_key)
199+ hash_id_db_url, cainfo=self.config.ssl_public_key, proxy=None)
200
201 return result
202
203@@ -1473,6 +1503,44 @@
204 reactor.callWhenRunning(do_test)
205 return deferred
206
207+ @mock.patch("landscape.package.reporter.spawn_process",
208+ return_value=succeed(("", "", 0)))
209+ def test_run_apt_update_honors_http_proxy(self, mock_spawn_process):
210+ """
211+ The PackageReporter.run_apt_update method honors the http_proxy
212+ config when calling the apt-update wrapper.
213+ """
214+ self.config.http_proxy = "http://proxy_server:8080"
215+ self.reporter.sources_list_filename = "/I/Dont/Exist"
216+
217+ update_result = self.reporter.run_apt_update()
218+ # run_apt_update uses reactor.call_later so advance a bit
219+ self.reactor.advance(0)
220+ self.successResultOf(update_result)
221+
222+ mock_spawn_process.assert_called_once_with(
223+ self.reporter.apt_update_filename,
224+ env={"http_proxy": "http://proxy_server:8080"})
225+
226+ @mock.patch("landscape.package.reporter.spawn_process",
227+ return_value=succeed(("", "", 0)))
228+ def test_run_apt_update_honors_https_proxy(self, mock_spawn_process):
229+ """
230+ The PackageReporter.run_apt_update method honors the https_proxy
231+ config when calling the apt-update wrapper.
232+ """
233+ self.config.https_proxy = "http://proxy_server:8443"
234+ self.reporter.sources_list_filename = "/I/Dont/Exist"
235+
236+ update_result = self.reporter.run_apt_update()
237+ # run_apt_update uses reactor.call_later, so advance a bit
238+ self.reactor.advance(0)
239+ self.successResultOf(update_result)
240+
241+ mock_spawn_process.assert_called_once_with(
242+ self.reporter.apt_update_filename,
243+ env={"https_proxy": "http://proxy_server:8443"})
244+
245 def test_run_apt_update_error_on_cache_file(self):
246 """
247 L{PackageReporter.run_apt_update} succeeds if the command fails because

Subscribers

People subscribed via source and target branches

to all changes: