Skip to content

Commit

Permalink
Fix: Nexus release logic and naming, add unit test
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
eb-oss committed Jul 22, 2021
1 parent 3996380 commit 79af135
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 17 deletions.
35 changes: 18 additions & 17 deletions lftools/nexus/cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -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))
16 changes: 16 additions & 0 deletions releasenotes/notes/fix-nexus-release-01c462b4c2ff2741.yaml
Original file line number Diff line number Diff line change
@@ -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.
34 changes: 34 additions & 0 deletions tests/fixtures/nexus/staging_activities_closed.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<list>
<stagingActivity>
<name>open</name>
<events>
<stagingActivityEvent>
<timestamp>2021-01-01T01:01:01.000Z</timestamp>
<name>repositoryCreated</name>
<severity>0</severity>
<properties>
<stagingProperty>
<name>id</name>
<value>test-release-repo</value>
</stagingProperty>
</properties>
</stagingActivityEvent>
</events>
</stagingActivity>
<stagingActivity>
<name>close</name>
<events>
<stagingActivityEvent>
<timestamp>2021-01-01T01:01:02.000Z</timestamp>
<name>repositoryClosed</name>
<severity>0</severity>
<properties>
<stagingProperty>
<name>id</name>
<value>test-release-repo</value>
</stagingProperty>
</properties>
</stagingActivityEvent>
</events>
</stagingActivity>
</list>
56 changes: 56 additions & 0 deletions tests/fixtures/nexus/staging_activities_released.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<list>
<stagingActivity>
<name>open</name>
<started>2021-01-01T01:01:00.000Z</started>
<stopped>2021-01-01T01:01:01.000Z</stopped>
<events>
<stagingActivityEvent>
<timestamp>2021-01-01T01:01:01.000Z</timestamp>
<name>repositoryCreated</name>
<severity>0</severity>
<properties>
<stagingProperty>
<name>id</name>
<value>test-release-repo</value>
</stagingProperty>
</properties>
</stagingActivityEvent>
</events>
</stagingActivity>
<stagingActivity>
<name>close</name>
<started>2021-01-01T01:01:02.000Z</started>
<stopped>2021-01-01T01:01:03.000Z</stopped>
<events>
<stagingActivityEvent>
<timestamp>2021-01-01T01:01:02.000Z</timestamp>
<name>repositoryClosed</name>
<severity>0</severity>
<properties>
<stagingProperty>
<name>id</name>
<value>test-release-repo</value>
</stagingProperty>
</properties>
</stagingActivityEvent>
</events>
</stagingActivity>
<stagingActivity>
<name>release</name>
<started>2021-01-01T01:01:04.000Z</started>
<stopped>2021-01-01T01:01:05.000Z</stopped>
<events>
<stagingActivityEvent>
<timestamp>2021-01-01T01:01:04.000Z</timestamp>
<name>repositoryReleased</name>
<severity>0</severity>
<properties>
<stagingProperty>
<name>id</name>
<value>test-release-repo</value>
</stagingProperty>
</properties>
</stagingActivityEvent>
</events>
</stagingActivity>
</list>
29 changes: 29 additions & 0 deletions tests/test_nexus.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@
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"""
Expand Down Expand Up @@ -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."""

Expand Down

0 comments on commit 79af135

Please sign in to comment.