feat(proxy): add proxy support to armada/Chart/v1 for git clone

Support proxy for installing armada/Chart/v1, as data.source.proxy_server when data.source.type = 'git'.

Closes #191

Change-Id: I9bfd7dbd63c86f65b24b27bd5eec547f862e2311
This commit is contained in:
Marshall Margenau 2018-02-01 15:30:17 -06:00
parent b95ed7fbc4
commit c117b945ad
4 changed files with 58 additions and 19 deletions

View File

@ -18,17 +18,29 @@ from armada.exceptions import base_exception
class SourceException(base_exception.ArmadaBaseException):
'''Base class for Git exceptions and error handling.'''
message = 'An unknown error occured while accessing a chart source'
message = 'An unknown error occurred while accessing a chart source.'
class GitLocationException(SourceException):
'''Exception that occurs when an error occurs cloning a Git repository.'''
class GitException(SourceException):
'''Exception when an error occurs cloning a Git repository.'''
def __init__(self, location):
self._location = location
self._message = self._location + ' is not a valid git repository.'
self._message = ('Git exception occurred, [', self._location,
'] may not be a valid git repository.')
super(GitLocationException, self).__init__(self._message)
super(GitException, self).__init__(self._message)
class GitProxyException(SourceException):
'''Exception when an error occurs cloning a Git repository
through a proxy.'''
def __init__(self, location):
self._location = location
self._message = ('Could not resolve proxy [', self._location, '].')
super(GitProxyException, self).__init__(self._message)
class SourceCleanupException(SourceException):

View File

@ -165,6 +165,7 @@ class Armada(object):
location = ch.get('chart').get('source').get('location')
ct_type = ch.get('chart').get('source').get('type')
subpath = ch.get('chart').get('source').get('subpath', '.')
proxy_server = ch.get('chart').get('source').get('proxy_server')
if ct_type == 'local':
ch.get('chart')['source_dir'] = (location, subpath)
@ -187,9 +188,11 @@ class Armada(object):
if repo_branch not in repos:
try:
LOG.info('Cloning repo: %s branch: %s', *repo_branch)
repo_dir = source.git_clone(*repo_branch)
if proxy_server:
LOG.info('Using proxy to clone: %s', proxy_server)
repo_dir = source.git_clone(*repo_branch, proxy_server)
except Exception:
raise source_exceptions.GitLocationException(
raise source_exceptions.GitException(
'{} reference: {}'.format(*repo_branch))
repos[repo_branch] = repo_dir
ch.get('chart')['source_dir'] = (repo_dir, subpath)

View File

@ -81,22 +81,31 @@ class GitTestCase(testtools.TestCase):
is_connected(), 'git clone requires network connectivity.')
def test_git_clone_empty_url(self):
url = ''
error_re = '%s is not a valid git repository.' % url
# error_re = '%s is not a valid git repository.' % url
with self.assertRaisesRegexp(
source_exceptions.GitLocationException, error_re):
source.git_clone(url)
self.assertRaises(source_exceptions.GitException,
source.git_clone, url)
@test_utils.attr(type=['negative'])
@testtools.skipUnless(
is_connected(), 'git clone requires network connectivity.')
def test_git_clone_bad_url(self):
url = 'http://github.com/dummy/armada'
error_re = '%s is not a valid git repository.' % url
with self.assertRaisesRegexp(
source_exceptions.GitLocationException, error_re):
source.git_clone(url)
self.assertRaises(source_exceptions.GitException,
source.git_clone, url)
# TODO need to design a positive proxy test,
# difficult to achieve behind a corporate proxy
@test_utils.attr(type=['negative'])
@testtools.skipUnless(
is_connected(), 'git clone requires network connectivity.')
def test_git_clone_fake_proxy(self):
url = 'http://github.com/att-comdev/armada'
self.assertRaises(source_exceptions.GitProxyException,
source.git_clone, url,
proxy_server='http://not.a.proxy:8080')
@mock.patch('armada.utils.source.tempfile')
@mock.patch('armada.utils.source.requests')

View File

@ -30,27 +30,42 @@ from armada.exceptions import source_exceptions
LOG = logging.getLogger(__name__)
def git_clone(repo_url, ref='master'):
def git_clone(repo_url, ref='master', proxy_server=None):
'''Clone a git repository from ``repo_url`` using the reference ``ref``.
:params repo_url: URL of git repo to clone.
:params ref: branch, commit or reference in the repo to clone.
:params proxy_server: optional, HTTP proxy to use while cloning the repo.
:returns: Path to the cloned repo.
'''
if repo_url == '':
raise source_exceptions.GitLocationException(repo_url)
raise source_exceptions.GitException(repo_url)
os.environ['GIT_TERMINAL_PROMPT'] = '0'
_tmp_dir = tempfile.mkdtemp(prefix='armada')
try:
repo = Repo.clone_from(repo_url, _tmp_dir)
if proxy_server:
LOG.info('Cloning [%s] with proxy [%s]', repo_url, proxy_server)
repo = Repo.clone_from(repo_url, _tmp_dir,
config='http.proxy=%s' % proxy_server)
else:
LOG.info('Cloning [%s]', repo_url)
repo = Repo.clone_from(repo_url, _tmp_dir)
repo.remotes.origin.fetch(ref)
g = Git(repo.working_dir)
g.checkout('FETCH_HEAD')
except git_exc.GitCommandError as e:
LOG.exception('Encountered GitCommandError during clone.')
if 'Could not resolve proxy' in e.stderr:
raise source_exceptions.GitProxyException(proxy_server)
else:
raise source_exceptions.GitException(repo_url)
except Exception:
raise source_exceptions.GitLocationException(repo_url)
LOG.exception('Encountered unknown Exception during clone.')
raise source_exceptions.GitException(repo_url)
return _tmp_dir