Wednesday, October 10, 2018

Nexus Groovy scripting

Huge issue in Nexus is that you can't export/import your Users/Groups/Privileges and Repository configuration. All you can do is to take a "backup", which ends of in a folder as a completely unreadable/unversionable format.

So I was looking for

when you run a Groovy script in Nexus, you have available a predefined variable "repository", which is of type org.sonatype.nexus.script.plugin.internal.provisioning.RepositoryApiImpl

This in turn contains a reference to a blobStoreManager org.sonatype.nexus.blobstore.api.BlobStoreManager and to a repositoryManager org.sonatype.nexus.repository.manager.RepositoryManager , plus a series of convenience methods to create commonly used repository formats (you are not expected to create anything fancy, most properties are assigned by default) and groups.

Key element is a org.sonatype.nexus.repository.config.Configuration object, again very disappointing since the configuration is represented by a "attribute" map (String, Map(String, Object)) which is really a stupid idea, too generic interface.

RepositoryManager has a Iterable<Repository> browse(); which returns a collection of org.sonatype.nexus.repository.Repository

Sample script:

import org.sonatype.nexus.repository.Repository

repository.repositoryManager.browse().each { Repository repo ->
    log.info("Repository: $repo")
    log.info("Repository Configuration: $repo.configuration")
}


this dumps in nexus.log the following content:

Repository: RepositoryImpl$$EnhancerByGuice$$c5f0822b{type=proxy, format=nuget, name='nuget.org-proxy'}
Repository Configuration: Configuration{repositoryName='nuget.org-proxy', recipeName='nuget-proxy', attributes={proxy={strictContentTypeValidation=true, contentMaxAge=1440, remoteUrl=https://www.nuget.org/api/v2/, metadataMaxAge=1440}, negativeCache={}, storage={blobStoreName=default}, nugetProxy={}, httpclient={connection={blocked=false, autoBlock=true}}}}

Repository: RepositoryImpl$$EnhancerByGuice$$c5f0822b{type=hosted, format=maven2, name='maven-releases'}
Repository Configuration: Configuration{repositoryName='maven-releases', recipeName='maven2-hosted', attributes={maven={versionPolicy=RELEASE, layoutPolicy=STRICT}, storage={writePolicy=ALLOW_ONCE, strictContentTypeValidation=false, blobStoreName=default}}}

Repository: RepositoryImpl$$EnhancerByGuice$$c5f0822b{type=hosted, format=maven2, name='maven-snapshots'}
Repository Configuration: Configuration{repositoryName='maven-snapshots', recipeName='maven2-hosted', attributes={maven={versionPolicy=SNAPSHOT, layoutPolicy=STRICT}, storage={writePolicy=ALLOW, strictContentTypeValidation=false, blobStoreName=default}}}

Repository: RepositoryImpl$$EnhancerByGuice$$c5f0822b{type=proxy, format=maven2, name='maven-central'}
Repository Configuration: Configuration{repositoryName='maven-central', recipeName='maven2-proxy', attributes={proxy={contentMaxAge=-1, remoteUrl=https://repo1.maven.org/maven2/, metadataMaxAge=1440}, negativeCache={timeToLive=1440, enabled=true}, storage={strictContentTypeValidation=false, blobStoreName=default}, maven-indexer={}, httpclient={connection={blocked=false, autoBlock=true}}, maven={versionPolicy=RELEASE, layoutPolicy=PERMISSIVE}}}

Repository: RepositoryImpl$$EnhancerByGuice$$c5f0822b{type=group, format=nuget, name='nuget-group'}
Repository Configuration: Configuration{repositoryName='nuget-group', recipeName='nuget-group', attributes={storage={blobStoreName=default}, nugetProxy={}, httpclient={}, group={memberNames=[nuget-hosted, nuget.org-proxy]}}}

Repository: RepositoryImpl$$EnhancerByGuice$$c5f0822b{type=hosted, format=nuget, name='nuget-hosted'}
Repository Configuration: Configuration{repositoryName='nuget-hosted', recipeName='nuget-hosted', attributes={storage={writePolicy=ALLOW, blobStoreName=default}}}

Repository: RepositoryImpl$$EnhancerByGuice$$c5f0822b{type=group, format=maven2, name='maven-public'}
Repository Configuration: Configuration{repositoryName='maven-public', recipeName='maven2-group', attributes={maven={versionPolicy=MIXED}, group={memberNames=[maven-releases, maven-snapshots, maven-central]}, storage={blobStoreName=default}}}





which is pretty good result, at least you can capture in one go all the configuration of all your repositories.



This task will delete all your repos:

import org.sonatype.nexus.repository.Repository

repository.repositoryManager.browse().each { Repository repo ->
    log.info("DELETE Repository: $repo")
    repository.repositoryManager.delete("$repo.name")
}


All the predefined variables are

core which is a org.sonatype.nexus.internal.provisioning.CoreApiImpl

repository which is a org.sonatype.nexus.script.plugin.internal.provisioning.RepositoryApiImpl

blobStore which is a org.sonatype.nexus.internal.provisioning.BlobStoreApiImpl
createFileBlobStore(final String name, final String path)
org.sonatype.nexus.blobstore.api.BlobStoreManager blobStoreManager 

security which is a org.sonatype.nexus.security.internal.SecurityApiImpl
User addUser(final String id, final String firstName, final String lastName, final String email, final boolean active,
final String password, final List roleIds)
Role addRole(final String id, final String name, final String description, final List privileges,
final List roles)
User setUserRoles(final String userId, final List roleIds)

If you do security.getSecuritySystem() you get an instance of this:
https://github.com/sonatype/nexus-public/blob/master/components/nexus-security/src/main/java/org/sonatype/nexus/security/SecuritySystem.java


Good is that if you clone the github repo nexus-book-examples you can directly open the APIs in file:///home/centos/gitclones/nexus-book-examples/scripting/apidocs/index.html


List all users with their roles

import groovy.json.JsonOutput
users = security.getSecuritySystem().listUsers()
userjson = JsonOutput.toJson(users)
log.info("USERS $userjson")





No comments: