From 79af13544c1dadad33e42853caad498b8456e010 Mon Sep 17 00:00:00 2001 From: Eric Ball Date: Wed, 21 Jul 2021 16:13:45 -0700 Subject: [PATCH] Fix: Nexus release logic and naming, add unit test nexus.release_staging_repos was failing with an error due to an undeclared variable. Several other issues were identified and fixed (see release note for details), and a unit test has been added to help prevent similar issues in the future. Issue: RELENG-3804 Change-Id: I8b7e4adf4561541acffa1dc81dbeba35d7783e51 Signed-off-by: Eric Ball --- lftools/nexus/cmd.py | 35 +++++++------- .../notes/fix-nexus-release-01c462b4c2ff2741.yaml | 16 +++++++ tests/fixtures/nexus/staging_activities_closed.xml | 34 +++++++++++++ .../fixtures/nexus/staging_activities_released.xml | 56 ++++++++++++++++++++++ tests/test_nexus.py | 29 +++++++++++ 5 files changed, 153 insertions(+), 17 deletions(-) create mode 100644 releasenotes/notes/fix-nexus-release-01c462b4c2ff2741.yaml create mode 100644 tests/fixtures/nexus/staging_activities_closed.xml create mode 100644 tests/fixtures/nexus/staging_activities_released.xml diff --git a/lftools/nexus/cmd.py b/lftools/nexus/cmd.py index 1bd9843c..d2d6c1f4 100644 --- a/lftools/nexus/cmd.py +++ b/lftools/nexus/cmd.py @@ -503,23 +503,24 @@ def release_staging_repos(repos, verify, nexus_url=""): else: log.info("Nexus is now working on releasing {}".format(str(repo))) - # Hang out until the repo is fully closed + # Hang out until the repo is fully released log.info("Waiting for Nexus to complete releasing {}".format(str(repo))) - closed = False + released = False wait_seconds = 20 - wait_itteration = 0 + wait_iteration = 0 activity_url = "{}/staging/repository/{}/activity".format(_nexus.baseurl, repo) - while closed is False: - sleep(wait_seconds) - wait_itteration = wait_itteration + 1 - log.info("Still waiting... {:>4d} seconds gone".format(total_wait_seconds * wait_itteration)) - if (wait_itteration % 2) != 0: - response = requests.get(activity_url, auth=_nexus.auth).text - root = et.fromstring(response) # nosec - events = root.findall("./stagingActivity") - for event in events: - name = event.find("name") - if name.text == "close": - stopped = event.find("stopped") - log.info("Repo released and closed at: {}".format(stopped.text)) - closed = True + sleep(5) # Quick sleep to allow small repos to release. + while released is False: + response = requests.get(activity_url, auth=_nexus.auth).text + root = et.fromstring(response) # nosec + events = root.findall("./stagingActivity") + for event in events: + name = event.find("name") + if name.text == "release": + stopped = event.find("stopped") + log.info("Repo released at: {}".format(stopped.text)) + released = True + if not released: + sleep(wait_seconds) + wait_iteration += 1 + log.info("Still waiting... {:>4d} seconds gone".format(wait_seconds * wait_iteration)) diff --git a/releasenotes/notes/fix-nexus-release-01c462b4c2ff2741.yaml b/releasenotes/notes/fix-nexus-release-01c462b4c2ff2741.yaml new file mode 100644 index 00000000..d4f66cd2 --- /dev/null +++ b/releasenotes/notes/fix-nexus-release-01c462b4c2ff2741.yaml @@ -0,0 +1,16 @@ +--- +fixes: + - | + nexus.release_staging_repos was failing with an error due to an undeclared + variable. Upon inspection, there were several other issues at play as well: + * No unit test (which would have caught an undeclared variable). + * Initial sleep of 20s is significantly longer than many repos take to + release. + * Only checked release status every 40s, while printing every 20s. + * Rather than checking release status, we were checking for "close" + status. Nexus closes repos before releasing them, so this is not the + correct status to look for when waiting for the repo to release. + + A unit test has been added, several variables issues have been corrected, + timing was adjusted (waiting just 5 seconds before the initial check for + success), and the code will now check for "release" status. diff --git a/tests/fixtures/nexus/staging_activities_closed.xml b/tests/fixtures/nexus/staging_activities_closed.xml new file mode 100644 index 00000000..b94ea84d --- /dev/null +++ b/tests/fixtures/nexus/staging_activities_closed.xml @@ -0,0 +1,34 @@ + + + open + + + 2021-01-01T01:01:01.000Z + repositoryCreated + 0 + + + id + test-release-repo + + + + + + + close + + + 2021-01-01T01:01:02.000Z + repositoryClosed + 0 + + + id + test-release-repo + + + + + + diff --git a/tests/fixtures/nexus/staging_activities_released.xml b/tests/fixtures/nexus/staging_activities_released.xml new file mode 100644 index 00000000..fc2025bb --- /dev/null +++ b/tests/fixtures/nexus/staging_activities_released.xml @@ -0,0 +1,56 @@ + + + open + 2021-01-01T01:01:00.000Z + 2021-01-01T01:01:01.000Z + + + 2021-01-01T01:01:01.000Z + repositoryCreated + 0 + + + id + test-release-repo + + + + + + + close + 2021-01-01T01:01:02.000Z + 2021-01-01T01:01:03.000Z + + + 2021-01-01T01:01:02.000Z + repositoryClosed + 0 + + + id + test-release-repo + + + + + + + release + 2021-01-01T01:01:04.000Z + 2021-01-01T01:01:05.000Z + + + 2021-01-01T01:01:04.000Z + repositoryReleased + 0 + + + id + test-release-repo + + + + + + diff --git a/tests/test_nexus.py b/tests/test_nexus.py index 0d05ec81..7c3930ce 100644 --- a/tests/test_nexus.py +++ b/tests/test_nexus.py @@ -21,6 +21,13 @@ from lftools.nexus import util FIXTURE_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "fixtures") +@pytest.fixture +def mock_get_credentials(mocker): + rtn = {"nexus": "http://nexus.localhost", "user": "user", "password": "password"} + mocker.patch("lftools.nexus.cmd.get_credentials", return_value=rtn) + mocker.patch("time.sleep", return_value=True) + + @pytest.fixture def nexus2_obj_create(responses): """Create the proper responses for the init of a nexus object""" @@ -50,6 +57,28 @@ def test_create_roles(datafiles, responses, nexus2_obj_create): cmd.create_roles("role_config-good.yaml", "settings.yaml") +@pytest.mark.datafiles(os.path.join(FIXTURE_DIR, "nexus")) +def test_release_staging_repos(datafiles, responses, nexus2_obj_create, mock_get_credentials): + """Test create_roles() method with good config.""" + os.chdir(str(datafiles)) + baseurl = "http://nexus.localhost/service/local" + repos = ["test-release-repo"] + activity_url = "{}/staging/repository/{}/activity".format(baseurl, repos[0]) + request_url = "{}/staging/bulk/promote".format(baseurl) + + closed_return = open("staging_activities_closed.xml", "r").read() + released_return = open("staging_activities_released.xml", "r").read() + + responses.add(responses.GET, activity_url, closed_return, status=200) + responses.add(responses.POST, request_url, status=201) + # While checking for the "release" activity, we return once without it in + # order to exercise the code for "if not released". + responses.add(responses.GET, activity_url, closed_return, status=200) + responses.add(responses.GET, activity_url, released_return, status=200) + + cmd.release_staging_repos(repos, False) + + def test_create_repo_target_regex(): """Test create_repo_target_regex() command.""" -- 2.16.6