From b9aaa446a86fea931e3eecde8b840416f72b9b22 Mon Sep 17 00:00:00 2001 From: Fedor Zhadaev Date: Mon, 30 Jan 2017 19:28:06 +0400 Subject: [PATCH] Add ability to specify NO_PROXY variable Add ability to bypass proxies for some domains by adding them to NO_PROXY list. Change-Id: I4b1e63918d467d6ee6bb90f69fc0cbf5b7be4961 Closes-Bug:#1534505 --- fuelmenu/modules/bootstrapimg.py | 26 ++++--- fuelmenu/tests/test_modules_bootstrapimg.py | 86 +++++++++++++++++++++ 2 files changed, 103 insertions(+), 9 deletions(-) create mode 100644 fuelmenu/tests/test_modules_bootstrapimg.py diff --git a/fuelmenu/modules/bootstrapimg.py b/fuelmenu/modules/bootstrapimg.py index a48362c..2795c63 100644 --- a/fuelmenu/modules/bootstrapimg.py +++ b/fuelmenu/modules/bootstrapimg.py @@ -14,6 +14,7 @@ # under the License. import copy import logging +import os import re import requests import types @@ -35,6 +36,7 @@ localhost_pattern = re.compile(r'(127.0.0.1|localhost)') BOOTSTRAP_HTTP_PROXY_KEY = "BOOTSTRAP/http_proxy" BOOTSTRAP_HTTPS_PROXY_KEY = "BOOTSTRAP/https_proxy" +BOOTSTRAP_NO_PROXY_KEY = "BOOTSTRAP/no_proxy" BOOTSTRAP_REPOS_KEY = "BOOTSTRAP/repos" BOOTSTRAP_SKIP_BUILD_KEY = "BOOTSTRAP/skip_default_img_build" @@ -59,6 +61,7 @@ class BootstrapImage(urwid.WidgetWrap): modulehelper.BLANK_KEY, BOOTSTRAP_HTTP_PROXY_KEY, BOOTSTRAP_HTTPS_PROXY_KEY, + BOOTSTRAP_NO_PROXY_KEY, modulehelper.BLANK_KEY, BOOTSTRAP_REPOS_KEY, ADD_REPO_BUTTON_KEY @@ -101,6 +104,10 @@ class BootstrapImage(urwid.WidgetWrap): "label": "HTTPS proxy", "tooltip": "Use this proxy when building the bootstrap image", "value": ""}, + BOOTSTRAP_NO_PROXY_KEY: { + "label": "Bypass proxy for", + "tooltip": "Bypass proxy for domains from this list", + "value": ""}, BOOTSTRAP_REPOS_KEY: { "label": "List of repositories", "type": modulehelper.WidgetType.LIST, @@ -158,11 +165,12 @@ class BootstrapImage(urwid.WidgetWrap): http_proxy = responses[BOOTSTRAP_HTTP_PROXY_KEY].strip() https_proxy = responses[BOOTSTRAP_HTTPS_PROXY_KEY].strip() + no_proxy = responses[BOOTSTRAP_NO_PROXY_KEY].strip() - proxies = { - 'http': http_proxy, - 'https': https_proxy - } + # Set up proxy settings + os.environ['HTTP_PROXY'] = http_proxy + os.environ['HTTPS_PROXY'] = https_proxy + os.environ['NO_PROXY'] = no_proxy repos = responses.get(BOOTSTRAP_REPOS_KEY) @@ -186,7 +194,7 @@ class BootstrapImage(urwid.WidgetWrap): "'deb uri distribution [component1] [...]'." .format(name)) continue - if not self._check_repo(repo['uri'], repo['suite'], proxies): + if not self._check_repo(repo['uri'], repo['suite']): errors.append("URL for repository {0} is not accessible." .format(name)) @@ -343,16 +351,16 @@ class BootstrapImage(urwid.WidgetWrap): # Update self.defaults self._update_defaults(self.defaults, self.parent.settings) - def check_url(self, url, proxies): + def check_url(self, url): try: - resp = requests.get(url, proxies=proxies, verify=False) + resp = requests.get(url, verify=False) except (requests.exceptions.RequestException, requests.exceptions.BaseHTTPError) as e: log.error(e) return False return resp.ok - def _check_repo(self, base_url, suite, proxies): + def _check_repo(self, base_url, suite): release_url = '{base_url}/dists/{suite}/Release'.format( base_url=base_url, suite=suite) host = urlparse.urlparse(release_url).netloc.split(':')[0] @@ -366,7 +374,7 @@ class BootstrapImage(urwid.WidgetWrap): 'repository: {}'.format(release_url)) return True - return self.check_url(release_url, proxies) + return self.check_url(release_url) def refresh(self): pass diff --git a/fuelmenu/tests/test_modules_bootstrapimg.py b/fuelmenu/tests/test_modules_bootstrapimg.py new file mode 100644 index 0000000..c952eea --- /dev/null +++ b/fuelmenu/tests/test_modules_bootstrapimg.py @@ -0,0 +1,86 @@ +# Copyright 2017 Mirantis, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import os + +from mock import patch +from requests import adapters + +from fuelmenu.modules import bootstrapimg +from fuelmenu.tests import base + + +class TestBootstrapImg(base.BaseModuleTests): + + def setUp(self, responses=None): + super(TestBootstrapImg, self).setUp() + if responses: + self.responses = responses + self.module = bootstrapimg.BootstrapImage(self.parent) + # unset proxy settings before start + os.environ['HTTP_PROXY'] = '' + os.environ['NO_PROXY'] = '' + os.environ['HTTPS_PROXY'] = '' + + @patch.object(adapters.HTTPAdapter, 'send') + def test_check_url_without_proxies(self, send_mock): + self.module.check_url('http://some_url') + + call_args = send_mock.call_args_list + self.assertEqual(1, len(call_args)) + call_args = call_args[0] + + args, kwargs = call_args + self.assertIn('proxies', kwargs) + self.assertNotIn('http', kwargs['proxies']) + self.assertNotIn('https', kwargs['proxies']) + + @patch.object(adapters.HTTPAdapter, 'send') + def test_check_url_with_proxies(self, send_mock): + http_proxy_url = 'http://http_proxy_url' + https_proxy_url = 'https://https_proxy_url' + os.environ['HTTP_PROXY'] = http_proxy_url + os.environ['HTTPS_PROXY'] = https_proxy_url + self.module.check_url('http://some_url') + + call_args = send_mock.call_args_list + self.assertEqual(1, len(call_args)) + call_args = call_args[0] + + args, kwargs = call_args + self.assertIn('proxies', kwargs) + self.assertIn('http', kwargs['proxies']) + self.assertIn('https', kwargs['proxies']) + self.assertEqual(kwargs['proxies']['http'], + http_proxy_url) + self.assertEqual(kwargs['proxies']['https'], + https_proxy_url) + + @patch.object(adapters.HTTPAdapter, 'send') + def test_check_url_with_no_proxy(self, send_mock): + http_proxy_url = 'http://http_proxy_url' + https_proxy_url = 'https://https_proxy_url' + os.environ['HTTP_PROXY'] = http_proxy_url + os.environ['HTTPS_PROXY'] = https_proxy_url + os.environ['NO_PROXY'] = 'direct_url' + self.module.check_url('http://direct_url') + + call_args = send_mock.call_args_list + self.assertEqual(1, len(call_args)) + call_args = call_args[0] + + args, kwargs = call_args + self.assertIn('proxies', kwargs) + self.assertNotIn('http', kwargs['proxies']) + self.assertNotIn('https', kwargs['proxies'])