From: Bengt Thuree Date: Thu, 1 Nov 2018 23:20:12 +0000 (-0400) Subject: Refactor Deploy Nexus Zip command to Python X-Git-Tag: v0.19.0~15 X-Git-Url: https://gerrit.linuxfoundation.org/infra/gitweb?a=commitdiff_plain;h=de342e6c2e5197934377fb610e9dbb4019aec792;p=releng%2Flftools.git Refactor Deploy Nexus Zip command to Python Refactor the deploy nexus zip command for better portability with Windows systems. Issue: RELENG-1372 Change-Id: I58ea1d7703b626f791dcd74e63251c4f3261ca7d Co-Authored-By: Thanh Ha Signed-off-by: Thanh Ha Signed-off-by: Bengt Thuree --- diff --git a/lftools/cli/deploy.py b/lftools/cli/deploy.py index 520ac3f1..224a77b1 100644 --- a/lftools/cli/deploy.py +++ b/lftools/cli/deploy.py @@ -312,8 +312,16 @@ def nexus_zip(ctx, nexus_url, nexus_repo, nexus_path, deploy_zip): Requires the Nexus Unpack plugin and permission assigned to the upload user. """ - status = subprocess.call(['deploy', 'nexus-zip', nexus_url, nexus_repo, nexus_path, deploy_zip]) - sys.exit(status) + try: + deploy_sys.deploy_nexus_zip(nexus_url, nexus_repo, nexus_path, deploy_zip) + except IOError as e: + log.error(str(e)) + sys.exit(1) + except HTTPError as e: + log.error(str(e)) + sys.exit(1) + + log.info('Zip file upload complete.') deploy.add_command(archives) diff --git a/lftools/deploy.py b/lftools/deploy.py index 098d48fe..108652f6 100644 --- a/lftools/deploy.py +++ b/lftools/deploy.py @@ -17,6 +17,7 @@ import shutil import subprocess import sys import tempfile +import zipfile import glob2 # Switch to glob when Python < 3.5 support is dropped import requests @@ -166,18 +167,7 @@ def deploy_archives(nexus_url, nexus_path, workspace, pattern=None): archives_zip = shutil.make_archive( '{}/archives'.format(workspace), 'zip') log.debug('archives zip: {}'.format(archives_zip)) - - # TODO: Update to use I58ea1d7703b626f791dcd74e63251c4f3261ca7d once it's available. - upload_files = {'upload_file': open(archives_zip, 'rb')} - url = '{}/service/local/repositories/logs/content-compressed/{}'.format( - nexus_url, nexus_path) - r = requests.post(url, files=upload_files) - log.debug('{}: {}'.format(r.status_code, r.text)) - if r.status_code != 201: - raise requests.exceptions.HTTPError( - 'Failed to upload to Nexus with status code {}.\n{}'.format( - r.status_code, r.content)) - + deploy_nexus_zip(nexus_url, 'logs', nexus_path, archives_zip) shutil.rmtree(work_dir) @@ -253,18 +243,48 @@ def deploy_logs(nexus_url, nexus_path, build_url): console_zip = tempfile.NamedTemporaryFile(prefix='lftools-dl', delete=True) log.debug('console-zip: {}'.format(console_zip.name)) shutil.make_archive(console_zip.name, 'zip', work_dir) - log.debug('listdir: {}'.format(os.listdir(work_dir))) - - # TODO: Update to use I58ea1d7703b626f791dcd74e63251c4f3261ca7d once it's available. - upload_files = {'upload_file': open('{}.zip'.format(console_zip.name), 'rb')} - url = '{}/service/local/repositories/logs/content-compressed/{}'.format( - nexus_url, nexus_path) - r = requests.post(url, files=upload_files) - log.debug('{}: {}'.format(r.status_code, r.text)) - if r.status_code != 201: - raise requests.exceptions.HTTPError( - 'Failed to upload to Nexus with status code {}.\n{}'.format( - r.status_code, r.content)) - + deploy_nexus_zip(nexus_url, 'logs', nexus_path, '{}.zip'.format(console_zip.name)) console_zip.close() shutil.rmtree(work_dir) + + +def deploy_nexus_zip(nexus_url, nexus_repo, nexus_path, zip_file): + """"Deploy zip file containing artifacts to Nexus using requests. + + This function simply takes a zip file preformatted in the correct + directory for Nexus and uploads to a specified Nexus repo using the + content-compressed URL. + + Requires the Nexus Unpack plugin and permission assigned to the upload user. + + Parameters: + + nexus_url: URL to Nexus server. (Ex: https://nexus.opendaylight.org) + nexus_repo: The repository to push to. (Ex: site) + nexus_path: The path to upload the artifacts to. Typically the + project group_id depending on if a Maven or Site repo + is being pushed. + Maven Ex: org/opendaylight/odlparent + Site Ex: org.opendaylight.odlparent + zip_file: The zip to deploy. (Ex: /tmp/artifacts.zip) + """ + url = '{}/service/local/repositories/{}/content-compressed/{}'.format( + _format_url(nexus_url), + nexus_repo, + nexus_path) + log.debug('Uploading {} to {}'.format(zip_file, url)) + + upload_file = open(zip_file, 'rb') + + files = {'file': upload_file} + resp = requests.post(url, files=files) + log.debug('{}: {}'.format(resp.status_code, resp.text)) + + if resp.status_code == 400: + raise requests.HTTPError("Repository is read only: {}".format(nexus_repo)) + elif resp.status_code == 404: + raise requests.HTTPError("Did not find repository with ID: {}".format(nexus_repo)) + + if not str(resp.status_code).startswith('20'): + raise requests.HTTPError("Failed to upload to Nexus with status code: {}.\n{}\n{}".format( + resp.status_code, resp.text, zipfile.ZipFile(zip_file).infolist())) diff --git a/releasenotes/notes/refactor-deploy-nexus-zip-018f7e5ced9f558d.yaml b/releasenotes/notes/refactor-deploy-nexus-zip-018f7e5ced9f558d.yaml new file mode 100644 index 00000000..51fe45f6 --- /dev/null +++ b/releasenotes/notes/refactor-deploy-nexus-zip-018f7e5ced9f558d.yaml @@ -0,0 +1,9 @@ +--- +features: + - | + Refactored deploy_nexus_zip() function from shell/deploy to pure Python to + be more portable with Windows systems. +deprecations: + - | + shell/deploy script's deploy_nexus_zip() function is now deprecated and will + be removed in a future release. diff --git a/tests/fixtures/deploy/zip-test-files/test.zip b/tests/fixtures/deploy/zip-test-files/test.zip new file mode 100755 index 00000000..b10a11d5 Binary files /dev/null and b/tests/fixtures/deploy/zip-test-files/test.zip differ diff --git a/tests/test_deploy.py b/tests/test_deploy.py index 54585025..be790b9a 100644 --- a/tests/test_deploy.py +++ b/tests/test_deploy.py @@ -138,6 +138,62 @@ def test_deploy_logs(cli_runner, datafiles, responses): obj={}) assert result.exit_code == 0 +@pytest.mark.datafiles( + os.path.join(FIXTURE_DIR, 'deploy'), + ) +def test_deploy_nexus_zip(cli_runner, datafiles, responses): + os.chdir(str(datafiles)) + nexus_url = 'https://nexus.example.org' + nexus_repo = 'test-repo' + nexus_path = 'test/path' + + # Test success + success_upload_url = '{}/service/local/repositories/{}/content-compressed/{}'.format( + nexus_url, + nexus_repo, + nexus_path, + ) + responses.add(responses.POST, success_upload_url, + status=201) + result = cli_runner.invoke( + cli.cli, + ['--debug', 'deploy', 'nexus-zip', 'https://nexus.example.org', 'test-repo', 'test/path', 'zip-test-files/test.zip'], + obj={}) + assert result.exit_code == 0 + + # Test repository 404 + upload_404 = """ + + 404 - Not Found + + + + + + + + + +

404 - Not Found

+

Repository with ID="logs2" not found

+ + +""" + upload_404_url = '{}/service/local/repositories/{}/content-compressed/{}'.format( + nexus_url, + 'logs2', + nexus_path, + ) + responses.add(responses.POST, upload_404_url, + body=upload_404, status=404) + result = cli_runner.invoke( + cli.cli, + ['--debug', 'deploy', 'nexus-zip', 'https://nexus.example.org', 'logs2', 'test/path', 'zip-test-files/test.zip'], + obj={}) + assert result.exit_code == 1 + def mocked_log_error(msg1=None, msg2=None): """Mock local_log_error_and_exit function. This function is modified to simply raise an Exception.