This command will release one or more staging repositories in Nexus.
To ensure proper functionality, this commit also includes fixes for
lftools.nexus.cmd.get_credentials and lftools.cli.nexus.list_images.
Issue: RELENG-916
Change-Id: I5fffea04e160004485e09513834825f4c08b220d
Signed-off-by: Eric Ball <eball@linuxfoundation.org>
^^^^
.. program-output:: lftools nexus docker list --help
+
+.. _nexus-release:
+
+release
+-------
+
+.. program-output:: lftools nexus release --help
Use '*' for wildcard, or begin with '!' to search for images NOT matching
the string.
"""
- if not server and 'NEXUS_URL_ENV' in environ:
- server = environ['NEXUS_URL_ENV']
+ if not server and NEXUS_URL_ENV in environ:
+ server = environ[NEXUS_URL_ENV]
images = nexuscmd.search(settings, server, repo, pattern)
if images:
nexuscmd.output_images(images, csv)
if yes or click.confirm("Would you like to delete all {} images?".format(
str(len(images)))):
nexuscmd.delete_images(settings, server, images)
+
+
+@nexus.command()
+@click.pass_context
+@click.argument('REPOS', type=str, nargs=-1)
+@click.option(
+ '-s', '--server', type=str,
+ help=('Nexus server URL. Can also be set as {} in the environment. '
+ 'This will override any URL set in settings.yaml.').format(
+ NEXUS_URL_ENV))
+def release(ctx, repos, server):
+ """Release one or more staging repositories."""
+ if not server and NEXUS_URL_ENV in environ:
+ server = environ[NEXUS_URL_ENV]
+ nexuscmd.release_staging_repos(repos, server)
import logging
import sys
+import requests
+from six.moves import configparser
import yaml
from lftools import config
elif set(['nexus', 'user', 'password']).issubset(settings):
return settings
elif url:
- user = config.get_setting("global", "username")
- password = config.get_setting("global", "password")
+ try:
+ user = config.get_setting("nexus", "username")
+ password = config.get_setting("nexus", "password")
+ except (configparser.NoOptionError,
+ configparser.NoSectionError):
+ return {"nexus": url, "user": "", "password": ""}
return {"nexus": url, "user": user, "password": password}
log.error('Please define a settings.yaml file, or include a url if using '
+ 'lftools.ini')
for image in images:
_nexus.delete_image(image)
+
+
+def release_staging_repos(repos, nexus_url=""):
+ """Release one or more staging repos.
+
+ :arg tuple repos: A tuple containing one or more repo name strings.
+ :arg str nexus_url: Optional URL of target Nexus server.
+ """
+ credentials = get_credentials(None, nexus_url)
+ _nexus = Nexus(credentials['nexus'], credentials['user'],
+ credentials['password'])
+
+ for repo in repos:
+ data = {"data": {"stagedRepositoryIds": [repo]}}
+ log.debug("Sending data: {}".format(data))
+ request_url = "{}/staging/bulk/promote".format(_nexus.baseurl)
+ log.debug("Request URL: {}".format(request_url))
+ response = requests.post(request_url, json=data)
+
+ if response.status_code != 201:
+ raise requests.HTTPError("Release failed with the following error:"
+ "\n{}: {}".format(response.status_code,
+ response.text))
+ else:
+ log.debug("Successfully released {}".format(str(repo)))
+
+ request_url = "{}/staging/bulk/drop".format(_nexus.baseurl)
+ log.debug("Request URL: {}".format(request_url))
+ response = requests.post(request_url, json=data)
+
+ if response.status_code != 201:
+ raise requests.HTTPError("Drop failed with the following error:"
+ "\n{}: {}".format(response.status_code,
+ response.text))
+ else:
+ log.debug("Successfully dropped {}".format(str(repo)))
--- /dev/null
+---
+features:
+ - |
+ Add Nexus command to release one or more staging repositories. Via the
+ Nexus 2 REST API, this command performs both a "release" and a "drop"
+ action on the repo(s), in order to best reproduce the action of manually
+ using the "Release" option in the Nexus UI.
+
+ Usage: lftools nexus release [OPTIONS] [REPOS]...
+
+ Options:
+ -s, --server TEXT Nexus server URL. Can also be set as NEXUS_URL in the
+ environment. This will override any URL set in
+ settings.yaml.
"""Test nexus command."""
import re
+import requests
import pytest
+from lftools.nexus import cmd
from lftools.nexus import util
vpp = util.create_repo_target_regex('io.fd.vpp')
vpp_regex = re.compile(vpp)
assert vpp_regex.match('/io/fd/vpp/jvpp/16.06/jvpp-16.06.jar')
+
+
+def test_release_staging_repos(responses):
+ """Test release_staging_repos() command."""
+ good_url = "https://nexus.example.org"
+ # Prepare response for Nexus initialization
+ responses.add(responses.GET,
+ "{}/service/local/repo_targets".format(good_url),
+ json=None, status=200)
+ # The responses provide implicit assertions.
+ responses.add(responses.POST, "{}/service/local/staging/bulk/promote".format(good_url),
+ json=None, status=201)
+ responses.add(responses.POST, "{}/service/local/staging/bulk/drop".format(good_url),
+ json=None, status=201)
+
+ # Test successful single release.
+ cmd.release_staging_repos(("release-1",), good_url)
+
+ # Test successful multiple release.
+ cmd.release_staging_repos(("release-1", "release-2", "release-3"),
+ good_url)
+
+ # Test promote failure
+ bad_url1 = "https://nexus-fail1.example.org"
+ responses.add(responses.GET,
+ "{}/service/local/repo_targets".format(bad_url1),
+ json=None, status=200)
+ responses.add(responses.POST,
+ "{}/service/local/staging/bulk/promote".format(bad_url1),
+ status=401)
+ with pytest.raises(requests.HTTPError):
+ cmd.release_staging_repos(("release-1",), bad_url1)
+
+ # Test drop failure
+ bad_url2 = "https://nexus-fail2.example.org"
+ responses.add(responses.GET,
+ "{}/service/local/repo_targets".format(bad_url2),
+ json=None, status=200)
+ responses.add(responses.POST,
+ "{}/service/local/staging/bulk/promote".format(bad_url2),
+ status=201)
+ responses.add(responses.POST,
+ "{}/service/local/staging/bulk/drop".format(bad_url2),
+ status=403)
+ with pytest.raises(requests.HTTPError):
+ cmd.release_staging_repos(("release-1",), bad_url2)