savoirfairelinux / ansible-nexus3-oss

Ansible role to provision Nexus Repository Manager 3.x for RedHat/CentOS
https://galaxy.ansible.com/savoirfairelinux/nexus3-oss/
GNU General Public License v3.0
113 stars 96 forks source link

Multiple runs make repo unconfigurable in GUI #38

Open elconas opened 6 years ago

elconas commented 6 years ago

Hello, when running the create_repo_docker_proxy_each role multiple times, the Nexus GUI returns "Warning Missing entity-metadata" when Itry to make manual changes to the repo created by Nexus. I can see the following:

2017-11-23 05:20:37,828+0000 ERROR [qtp300886853-190]  admin org.sonatype.nexus.extdirect.internal.ExtDirectServlet - Failed to invoke action method: coreui_Repository.update, java-method: org.sonatype.nexus.coreui.RepositoryComponent.update
java.lang.IllegalStateException: Missing entity-metadata
    at com.google.common.base.Preconditions.checkState(Preconditions.java:444)
    at org.sonatype.nexus.common.entity.EntityHelper.metadata(EntityHelper.java:46)
    at org.sonatype.nexus.common.entity.EntityHelper.id(EntityHelper.java:62)
    at org.sonatype.nexus.orient.entity.EntityAdapter.recordIdentity(EntityAdapter.java:363)
    at org.sonatype.nexus.orient.entity.EntityAdapter.editEntity(EntityAdapter.java:286)
    at org.sonatype.nexus.repository.config.internal.ConfigurationStoreImpl.lambda$2(ConfigurationStoreImpl.java:88)
    at org.sonatype.nexus.orient.transaction.OrientOperations.lambda$2(OrientOperations.java:63)
    at org.sonatype.nexus.transaction.OperationPoint.lambda$0(OperationPoint.java:53)
    at org.sonatype.nexus.transaction.OperationPoint.proceed(OperationPoint.java:64)
    at org.sonatype.nexus.transaction.TransactionalWrapper.proceedWithTransaction(TransactionalWrapper.java:56)
    at org.sonatype.nexus.transaction.Operations.transactional(Operations.java:200)
    at org.sonatype.nexus.transaction.Operations.run(Operations.java:155)
    at org.sonatype.nexus.orient.transaction.OrientOperations.run(OrientOperations.java:63)
    at org.sonatype.nexus.repository.config.internal.ConfigurationStoreImpl.update(ConfigurationStoreImpl.java:88)
    at org.sonatype.nexus.common.stateguard.MethodInvocationAction.run(MethodInvocationAction.java:39)
    at org.sonatype.nexus.common.stateguard.StateGuard$GuardImpl.run(StateGuard.java:270)
    at org.sonatype.nexus.common.stateguard.GuardedInterceptor.invoke(GuardedInterceptor.java:53)
    at org.sonatype.nexus.repository.manager.internal.RepositoryManagerImpl.update(RepositoryManagerImpl.java:348)
    at org.sonatype.nexus.common.stateguard.MethodInvocationAction.run(MethodInvocationAction.java:39)
    at org.sonatype.nexus.common.stateguard.StateGuard$GuardImpl.run(StateGuard.java:270)
    at org.sonatype.nexus.common.stateguard.GuardedInterceptor.invoke(GuardedInterceptor.java:53)
    at org.sonatype.nexus.repository.manager.RepositoryManager$update$3.call(Unknown Source)
    at org.sonatype.nexus.coreui.RepositoryComponent.update(RepositoryComponent.groovy:234)
    at com.palominolabs.metrics.guice.ExceptionMeteredInterceptor.invoke(ExceptionMeteredInterceptor.java:49)
    at com.palominolabs.metrics.guice.TimedInterceptor.invoke(TimedInterceptor.java:47)
    at org.sonatype.nexus.validation.internal.ValidationInterceptor.invoke(ValidationInterceptor.java:53)
    at org.apache.shiro.guice.aop.AopAllianceMethodInvocationAdapter.proceed(AopAllianceMethodInvocationAdapter.java:49)
    at org.apache.shiro.authz.aop.AuthorizingAnnotationMethodInterceptor.invoke(AuthorizingAnnotationMethodInterceptor.java:68)
    at org.apache.shiro.guice.aop.AopAllianceMethodInterceptorAdapter.invoke(AopAllianceMethodInterceptorAdapter.java:36)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.softwarementors.extjs.djn.router.dispatcher.DispatcherBase.invokeJavaMethod(DispatcherBase.java:142)
    at com.softwarementors.extjs.djn.router.dispatcher.DispatcherBase.invokeMethod(DispatcherBase.java:133)
    at org.sonatype.nexus.extdirect.internal.ExtDirectServlet$3.invokeMethod(ExtDirectServlet.java:233)
    at com.softwarementors.extjs.djn.router.dispatcher.DispatcherBase.dispatch(DispatcherBase.java:63)
    at com.softwarementors.extjs.djn.router.processor.standard.StandardRequestProcessorBase.dispatchStandardMethod(StandardRequestProcessorBase.java:73)
    at com.softwarementors.extjs.djn.router.processor.standard.json.JsonRequestProcessor.processIndividualRequest(JsonRequestProcessor.java:502)
    at com.softwarementors.extjs.djn.router.processor.standard.json.JsonRequestProcessor.processIndividualRequestsInThisThread(JsonRequestProcessor.java:150)
    at com.softwarementors.extjs.djn.router.processor.standard.json.JsonRequestProcessor.process(JsonRequestProcessor.java:133)
    at com.softwarementors.extjs.djn.router.RequestRouter.processJsonRequest(RequestRouter.java:83)
    at com.softwarementors.extjs.djn.servlet.DirectJNgineServlet.processRequest(DirectJNgineServlet.java:617)
    at com.softwarementors.extjs.djn.servlet.DirectJNgineServlet.doPost(DirectJNgineServlet.java:580)
    at org.sonatype.nexus.extdirect.internal.ExtDirectServlet.doPost(ExtDirectServlet.java:138)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
    at com.google.inject.servlet.ServletDefinition.doServiceImpl(ServletDefinition.java:286)
    at com.google.inject.servlet.ServletDefinition.doService(ServletDefinition.java:276)
    at com.google.inject.servlet.ServletDefinition.service(ServletDefinition.java:181)
    at com.google.inject.servlet.DynamicServletPipeline.service(DynamicServletPipeline.java:71)
    at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:85)
    at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:112)
    at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
    at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:61)
    at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
    at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
    at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
    at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
    at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
    at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
    at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
    at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
    at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449)
    at org.sonatype.nexus.security.SecurityFilter.executeChain(SecurityFilter.java:85)
    at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
    at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
    at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
    at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383)
    at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
    at org.sonatype.nexus.security.SecurityFilter.doFilterInternal(SecurityFilter.java:101)
    at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
    at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
    at com.sonatype.nexus.licensing.internal.LicensingRedirectFilter.doFilter(LicensingRedirectFilter.java:108)
    at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
    at com.codahale.metrics.servlet.AbstractInstrumentedFilter.doFilter(AbstractInstrumentedFilter.java:97)
    at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
    at org.sonatype.nexus.internal.web.ErrorPageFilter.doFilter(ErrorPageFilter.java:68)
    at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
    at org.sonatype.nexus.internal.web.EnvironmentFilter.doFilter(EnvironmentFilter.java:102)
    at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
    at org.sonatype.nexus.internal.web.HeaderPatternFilter.doFilter(HeaderPatternFilter.java:98)
    at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
    at com.google.inject.servlet.DynamicFilterPipeline.dispatch(DynamicFilterPipeline.java:104)
    at com.google.inject.servlet.GuiceFilter.doFilter(GuiceFilter.java:135)
    at org.sonatype.nexus.bootstrap.osgi.DelegatingFilter.doFilter(DelegatingFilter.java:73)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1751)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:582)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1180)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:512)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1112)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134)
    at com.codahale.metrics.jetty9.InstrumentedHandler.handle(InstrumentedHandler.java:175)
    at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:119)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134)
    at org.eclipse.jetty.server.Server.handle(Server.java:534)
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:320)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:251)
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:283)
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:108)
    at org.eclipse.jetty.io.ssl.SslConnection.onFillable(SslConnection.java:251)
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:283)
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:108)
    at org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93)
    at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303)
    at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148)
    at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589)
    at java.lang.Thread.run(Thread.java:748)

Config for the Repo:

    nexus_repos_docker_proxy:
     - name: docker-dockerhub
       http_port: "40010"
       v1_enabled: True
       index_type: "HUB"
       proxy_url: "https://registry-1.docker.io"
       use_nexus_certificates_to_access_index: false
elconas commented 6 years ago

I also tested with a private docker repo. Same issue here. It happens with nexus 3.6.0 and 3.6.1. It also happens with Nexus 3.3.0.

elconas commented 6 years ago

One more not. If I change the "update()" to a noop, everything works. So the problem seems to be in the "update()" call

if (existingRepository != null) {
    existingRepository.stop()
    //configuration.attributes['storage']['blobStoreName'] = existingRepository.configuration.attributes['storage']['blobStoreName']
    //existingRepository.update(configuration)
    existingRepository.start()
} else {
    repository.getRepositoryManager().create(configuration)
}

re-setting the existing configuration does also work

if (existingRepository != null) {
    existingRepository.stop()
    //configuration.attributes['storage']['blobStoreName'] = existingRepository.configuration.attributes['storage']['blobStoreName']
    existingRepository.update(existingRepository.configuration)
    existingRepository.start()
} else {
    repository.getRepositoryManager().create(configuration)
}

modifying the existing config in place and setting it again does also work

if (existingRepository != null) {
    existingRepository.stop()
    //configuration.attributes['storage']['blobStoreName'] = existingRepository.configuration.attributes['storage']['blobStoreName']
    existingRepository.configuration.attributes['docker']['v1Enabled']=false
    existingRepository.update(existingRepository.configuration)
    existingRepository.start()
} else {
    repository.getRepositoryManager().create(configuration)
}
zeitounator commented 6 years ago

+1 Thanks for the tip. I actually tested and the problem is the same with maven repositories (did not test other types but I guess we will have the same problem).

dannyk81 commented 6 years ago

Yes, this seems a comming problem now.

I also reported this in https://github.com/savoirfairelinux/ansible-nexus3-oss/issues/37

There's an ticket NEXUS-14948 for this and a discussion on the users group, here.

dannyk81 commented 6 years ago

Be aware that also any changes you make using the intergation api (groovy scripts) will be reverted when Nexus restarts.

elconas commented 6 years ago

I also see this with Nexus 3.3.0 (using docker version)

elconas commented 6 years ago

@dannyk81 Regarding the statement:

Be aware that also any changes you make using the intergation api (groovy scripts) will be reverted when Nexus restarts.

Is this only to for the writePolicy setting or all settings ?

dannyk81 commented 6 years ago

From my tests with Nexus 3.6.0 and 3.6.1, any parameter change in repository settings gets reverted.

The ticket mentioned the write policy specifically, but I've seen that it affects all settings.

zeitounator commented 6 years ago

I made a first test tonight and was actually able to fix the fact that the repo is not saveable/deleteable from gui after a second playbook run by changing the groovy script (i.e. get the current config and only update values which your are allowed to effectively change). Meanwhile, I did not try to change any values from my vars in playbook. I made the test against docker proxy repo only for now. I'm going to check if the values get reverted. Coming back.

elconas commented 6 years ago

Yes, it seems modifying in place seems to work:

    existingRepository.stop()
    conig = existingRepository.configuration
    .. now modify config ...
    existingRepository.update(config)
    existingRepository.start()
zeitounator commented 6 years ago

working/testing a fix to change only allowed parameters. I'll keep you updated and submit a merge request if successful.

elconas commented 6 years ago

Actually I am (generally) a little concerned that groovy scripts in nexus can make the server unusabe. It should not be possible for users to get Nexus in an inconsistent state.

zeitounator commented 6 years ago

We agree on that point !

Meanwhile, since I'm not a nexus dev and only a late user of this ansible role, I'm trying to find a way to not screw-up my production.

My latest tests:

Looking at the nexus javadoc to see if I can find something interesting there.

zeitounator commented 6 years ago

Hi guys. I did not take the time to start a PR since the issue is not resolved (the settings are still reverted back to previous when nexus restart). But this is how I managed to keep the repos usable in the gui (example for docker hosted):

import groovy.json.JsonSlurper
import org.sonatype.nexus.repository.config.Configuration

parsed_args = new JsonSlurper().parseText(args)

def existingRepository = repository.getRepositoryManager().get(parsed_args.name)

if (existingRepository != null) {
    def newConfig = existingRepository.configuration.copy()
    // We only update values we are allowed to change (cf. greyed out options in gui)
    newConfig.attributes['docker']['forceBasicAuth'] = parsed_args.force_basic_auth
    newConfig.attributes['docker']['v1Enabled'] = parsed_args.v1_enabled
    newConfig.attributes['storage']['writePolicy'] = parsed_args.write_policy.toUpperCase()
    newConfig.attributes['storage']['strictContentTypeValidation'] = Boolean.valueOf(parsed_args.strict_content_validation)
    if (parsed_args.http_port) {
        newConfig.attributes['docker']['httpPort'] = parsed_args.http_port
    } else {
        newConfig.attributes['docker']['httpPort'] = ""
    }
    existingRepository.stop()
    existingRepository.update(newConfig)
    existingRepository.start()
} else {
    configuration = new Configuration(
            repositoryName: parsed_args.name,
            recipeName: 'docker-hosted',
            online: true,
            attributes: [
                    docker: [
                            forceBasicAuth: parsed_args.force_basic_auth,
                            v1Enabled : parsed_args.v1_enabled
                    ],
                    storage: [
                            writePolicy: parsed_args.write_policy.toUpperCase(),
                            blobStoreName: parsed_args.blob_store,
                            strictContentTypeValidation: Boolean.valueOf(parsed_args.strict_content_validation)
                    ]
            ]
    )
    if (parsed_args.http_port) {
        configuration.attributes['docker']['httpPort'] = parsed_args.http_port
    }
    repository.getRepositoryManager().create(configuration)
}
dannyk81 commented 6 years ago

Thanks @zeitounator! this is indeed a way forward.

I suggest we apply these changes to all repo scripts, however please note that @samherve is no longer maintaing this project, so any PR we submit would simply not be merged.

As he suggests, perhaps we should fork this project and start pushing the PRs that are pending here.

In any case, I'm hoping Sonatype will provide root cause for both issues we've been experiencing (vote for the ticket here), as suggested above - it's unresanable that an incorrect usage by a groovy script would render a system inoperable and the reverted settings after restart is still a mistery and in our case a source for a lot of headache...

zeitounator commented 6 years ago

Hi @dannyk81. I missed the information about @samherve stopping maintenance. Thanks for sharing. This is sad. I just added a comment in #36 and I think we should wait some more days (like end of next week ?) for a clear answer from @support-savoirfairelinux before we take a decision. Meanwhile, if we should come to this, I think we should hard fork in an organization somewhere and not keep the new reference repository under a single user name. What's your opinion about it ?

dannyk81 commented 6 years ago

I agree, let's wait for some time for feedback.

Worst case, we'll hard fork this as you suggest.

zeitounator commented 6 years ago

Problem fixed after sonatype response on the ticket. We were making an incorrect use of the groovy available interfaces (even though it should be locked up better and better documented as well.....). Once again, the working solution with docker proxy repo as example

import groovy.json.JsonSlurper
import org.sonatype.nexus.repository.config.Configuration

parsed_args = new JsonSlurper().parseText(args)

repositoryManager = repository.repositoryManager

existingRepository = repositoryManager.get(parsed_args.name)

if (existingRepository != null) {
    newConfig = existingRepository.configuration.copy()
    // We only update values we are allowed to change (cf. greyed out options in gui)
    newConfig.attributes['docker']['forceBasicAuth'] = parsed_args.force_basic_auth
    newConfig.attributes['docker']['v1Enabled'] = parsed_args.v1_enabled
    newConfig.attributes['storage']['writePolicy'] = parsed_args.write_policy.toUpperCase()
    newConfig.attributes['storage']['strictContentTypeValidation'] = Boolean.valueOf(parsed_args.strict_content_validation)
    if (parsed_args.http_port) {
        newConfig.attributes['docker']['httpPort'] = parsed_args.http_port
    } else {
        newConfig.attributes['docker']['httpPort'] = ""
    }

    repositoryManager.update(newConfig)

} else {

    configuration = new Configuration(
            repositoryName: parsed_args.name,
            recipeName: 'docker-hosted',
            online: true,
            attributes: [
                    docker: [
                            forceBasicAuth: parsed_args.force_basic_auth,
                            v1Enabled : parsed_args.v1_enabled
                    ],
                    storage: [
                            writePolicy: parsed_args.write_policy.toUpperCase(),
                            blobStoreName: parsed_args.blob_store,
                            strictContentTypeValidation: Boolean.valueOf(parsed_args.strict_content_validation)
                    ]
            ]
    )
    if (parsed_args.http_port) {
        configuration.attributes['docker']['httpPort'] = parsed_args.http_port
    }

    repositoryManager.create(configuration)

}
dannyk81 commented 6 years ago

Wow! great news 😃 @zeitounator

I'll have to update my scripts per above! shame there's still no response from @support-savoirfairelinux... we need to preserve and maintain this work somehow.

zeitounator commented 6 years ago

Hi guys. Seems like @support-savoirfairelinux is not willing to respond. I would still like to give them a chance to do so until the end of the week.

Meanwhile, as a beginning, I have started to merge the pull requests found in this repo that I already use for production on my own github repo. You can find the result there on the master branch (ongoing work): https://github.com/zeitounator/ansible-nexus3-oss. I have some more additions to share which are not shown there (I use an other gitlab repo for work which is not public)

I am planning to merge all the remaining PRs from here (the ones i did not pick yet on my prod), the necessary changes to groovy scripts for persistence of changes discussed in this issue and the work I have done on my own and not yet shared.

If there is no answer from @support-savoirfairelinux by then, I suggest to hard fork in a central location under a team name. If someone has an existing one to suggest, I'll be happy to join and/or collaborate. If not, I was about to create one under my own self-employed company name (ThoTeam) and invite the good willing people who have some time to spend on maintaining this. Let me know what you think.

Regards

dannyk81 commented 6 years ago

Hi @zeitounator!

+1 on your propsal and thanks for initiative, it seems that if we want to keep this work alive and relevant it should be a good idea.

I would be more than happy to contribute/assist.

zeitounator commented 6 years ago

I went ahead and hard forked the repo since I didn't get a response from the current owners and no proposition for an existing organization to host it. I'm trying to integrate as fast as possible all the leftover pull requests. I will put a comment in each of them once it is done. The new hard forked repository is here: https://github.com/ansible-ThoTeam/nexus3-oss

tycoonm commented 4 years ago

Here is my solution:

import groovy.json.JsonSlurper
import org.sonatype.nexus.repository.config.Configuration

parsed_args = new JsonSlurper().parseText(args)

configuration = new Configuration(
        repositoryName: parsed_args.name,
        recipeName: 'docker-hosted',
        online: true,
        attributes: [
                docker: [
                        httpPort: parsed_args.http_port,
                        v1Enabled : parsed_args.v1_enabled
                ],
                storage: [
                        writePolicy: parsed_args.write_policy.toUpperCase(),
                        blobStoreName: parsed_args.blob_store,
                        strictContentTypeValidation: Boolean.valueOf(parsed_args.strict_content_validation)
                ]
        ]
)

def existingRepository = repository.getRepositoryManager().get(parsed_args.name)

if (existingRepository != null) {
    existingRepository.stop()
    config = existingRepository.configuration;
    blobStoreName = config.attributes['storage']['blobStoreName'];
    config.attributes = configuration.attributes
    config.attributes['storage']['blobStoreName'] = blobStoreName
    existingRepository.update(config)
    existingRepository.start()
} else {
    repository.getRepositoryManager().create(configuration)
}
zeitounator commented 4 years ago

Hi @tycoonm, As you may not have seen, this repo is totally silent since end of maintenance was announced almost 2 years ago. This issue has been fixed very long ago in the following hard fork repo which also contains tons of other new features: https://github.com/ansible-ThoTeam/nexus3-oss. You're welcome to come by and visit if you are interested. Cheers.