From 2e83b3aa78da2a71481828263626eabb540908de Mon Sep 17 00:00:00 2001 From: Thiago Figueiro Date: Sat, 22 Feb 2020 17:27:51 +1100 Subject: [PATCH] fix: ``repository create`` command on Nexus 3.21.0 --- .travis.yml | 9 +- setup.py | 2 +- src/nexuscli/api/repository/collection.py | 35 +++++++- ...nexus3-cli-repository-create_3.21.0.groovy | 87 +++++++++++++++++++ tests/conftest.py | 2 + 5 files changed, 130 insertions(+), 5 deletions(-) create mode 100644 src/nexuscli/api/script/groovy/nexus3-cli-repository-create_3.21.0.groovy diff --git a/.travis.yml b/.travis.yml index 14db76f..e734f16 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,15 @@ dist: bionic sudo: required env: +# TODO: use latest 4 images; e.g.: +# curl -s 'https://hub.docker.com/v2/repositories/sonatype/nexus3/tags/?page_size=25&page=1' -H 'Accept: application/json' --compressed -H 'Pragma: no-cache' -H 'Cache-Control: no-cache' | jq '.results[:4] | .[] | .name' +#"latest" +#"3.21.1" +#"3.21.0" +#"3.20.1" - NEXUS_VERSION=3.20.0 - NEXUS_VERSION=3.20.1 -# FIXME: sonatype introduced a breaking change in the groovy api. Again. -# - NEXUS_VERSION=3.21.1 + - NEXUS_VERSION=3.21.1 services: - docker before_install: diff --git a/setup.py b/setup.py index 579f4cf..adbfd8d 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ from setuptools import find_packages, setup package_name = 'nexus3-cli' -package_version = '3.0.1' +package_version = '3.0.2' requires = [ 'click>=7.0.0,<8', diff --git a/src/nexuscli/api/repository/collection.py b/src/nexuscli/api/repository/collection.py index 4ec8448..0bca1a9 100755 --- a/src/nexuscli/api/repository/collection.py +++ b/src/nexuscli/api/repository/collection.py @@ -1,8 +1,11 @@ import json +import pathlib +import semver from nexuscli import exception from nexuscli.api.repository import model +SCRIPT_CREATE_VERSIONS = [semver.VersionInfo(3, 21, 0)] SCRIPT_NAME_CREATE = 'nexus3-cli-repository-create' SCRIPT_NAME_DELETE = 'nexus3-cli-repository-delete' SCRIPT_NAME_GET = 'nexus3-cli-repository-get' @@ -155,6 +158,29 @@ def _repository_args_kwargs(raw_configuration): return args, kwargs +def _script_for_version(script_name, server_version, versions): + """ + Determine if a certain nexus server version requires a different version of + the given groovy script. + + :param script_name: original name of the script. + :param server_version: VersionInfo for the Nexus server. + :param versions: list of VersionInfo. Each element represents an existing + groovy script that must be used with server_version or greater. + :return: the version-specific name of script_name. + """ + if server_version is None: + return script_name + + for breaking_version in sorted(versions, reverse=True): + if server_version >= breaking_version: + script_path = pathlib.Path(script_name) + # e.g.: nexus3-cli-repository-create_3.21.0.groovy + return f'{script_path.stem}_{breaking_version}{script_path.suffix}' + + return script_name + + class RepositoryCollection: """ A class to manage Nexus 3 repositories. @@ -248,14 +274,19 @@ def create(self, repository): :type repository: Repository :raises NexusClientCreateRepositoryError: error creating repository. """ + script_name = _script_for_version( + SCRIPT_NAME_CREATE, + self._client.server_version, + SCRIPT_CREATE_VERSIONS) + if not issubclass(type(repository), model.Repository): raise TypeError(f'{repository} has type {type(repository)}' f' but must be a subclass of Repository') - self._client.scripts.create_if_missing(SCRIPT_NAME_CREATE) + self._client.scripts.create_if_missing(script_name) script_args = json.dumps(repository.configuration) - resp = self._client.scripts.run(SCRIPT_NAME_CREATE, data=script_args) + resp = self._client.scripts.run(script_name, data=script_args) result = resp.get('result') if result != 'null': diff --git a/src/nexuscli/api/script/groovy/nexus3-cli-repository-create_3.21.0.groovy b/src/nexuscli/api/script/groovy/nexus3-cli-repository-create_3.21.0.groovy new file mode 100644 index 0000000..0547f93 --- /dev/null +++ b/src/nexuscli/api/script/groovy/nexus3-cli-repository-create_3.21.0.groovy @@ -0,0 +1,87 @@ +import groovy.json.JsonSlurper +import org.sonatype.nexus.repository.config.Configuration +import org.sonatype.nexus.repository.manager.RepositoryManager + + +class Repository { + Map> properties = new HashMap() +} + +if (args != "") { + log.info("Creating repository with args [${args}]") + def rep = convertJsonFileToRepo(args) + log.debug("Got repo [${rep}]") + def output = createRepository(rep) + + return output +} + +def createRepository(Repository repo) { + def conf = createConfiguration(repo) + + try { + repository.createRepository(conf) + } + catch (Exception e) { + return e + } + + return null +} + +def convertJsonFileToRepo(String jsonData) { + def inputJson = new JsonSlurper().parseText(jsonData) + log.debug("Creating repository object for [${inputJson}]") + Repository repo = new Repository() + inputJson.each { + repo.properties.put(it.key, it.value) + } + + log.debug("Created repository object [${repo}]") + return repo +} + +//def repositoryManager = container.lookup(RepositoryManager.class.getName()) + +def createConfiguration(Repository repo) { + repositoryManager = container.lookup(RepositoryManager.class.getName()) + Configuration conf = repositoryManager.newConfiguration() + + conf.with { + repositoryName = getName(repo) + recipeName = getRecipeName(repo) + online = getOnline(repo) + attributes = repo.properties.get("attributes") as Map + } + + // https://github.com/thiagofigueiro/nexus3-cli/issues/77 + try { + policy_name = conf.attributes.cleanup.policyName + log.info("policy name is ${policy_name.getClass()}") + if (policy_name.getClass() == java.util.ArrayList) { + Set set = new HashSet(policy_name) + conf.attributes.cleanup.policyName = set + log.info("Converted to ${set.getClass()}") + } + } + catch (java.lang.NullPointerException e) { + log.info("No cleanup policy provided; that's ok.") + } + + return conf +} + +def getName(Repository repo){ + String name = repo.getProperties().get("name") + return name +} + +def getRecipeName(Repository repo){ + String recipeName = repo.getProperties().get("recipeName") + return recipeName +} + +def getOnline(Repository repo){ + String online = repo.getProperties().get("online") + return online +} diff --git a/tests/conftest.py b/tests/conftest.py index 9c454df..d39187c 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,6 +1,7 @@ import os import pathlib import pytest +import semver import shutil import tempfile import time @@ -157,6 +158,7 @@ def json(self): return_value=ResponseMock()) client = NexusClient() + client._server_version = semver.VersionInfo(3, 19, 0) client.repositories.refresh() return client