Uploaded image for project: 'Dev - Nexus Repo'
  1. Dev - Nexus Repo
  2. NEXUS-35497

Staging move fails if some image layers are contained in a proxy repository.

    Details

    • Type: Bug
    • Status: New
    • Priority: Major
    • Resolution: Unresolved
    • Affects Version/s: 3.41.1
    • Fix Version/s: None
    • Component/s: Docker, Staging
    • Labels:
    • Notability:
      3
    • InvestmentLayer:
      support-escalated
    • Aha Concept:
      non-concept

      Description

      Staging move fails if some layers are contained in a proxy repository.

      To reproduce, set up Nexus Repo with these repositories:

      ├ ⧈ docker-group (docker-group)
      │   ├ • docker-hosted (docker-hosted)
      │   └ ▶ docker-proxy (docker-proxy) ≻ https://registry-1.docker.io
      ├ • docker-releases (docker-hosted)
      

      Configure "docker-group" with "docker-hosted" as its writable repository.

      Pull an image through the group, tag it, and push it back through the group:

      docker pull localhost:8445/hello-world
      docker images
      docker tag feb5d9fea6a5 localhost:8445/hello-world:1.2.3
      docker push localhost:8445/hello-world:1.2.3
      

      You'll end up with the tag and manifest in "docker-hosted", and the image's layer in "docker-proxy".

      Now tag it with Nexus Repo tagging, and attempt to move it to "docker-releases".

      curl -u admin:admin123 -X POST 'http://localhost:8081/service/rest/v1/tags/associate/hello-123?repository=docker-hosted&format=docker&docker.imageName=hello-world&docker.imageTag=1.2.3'
      
      curl -u admin:admin123 -X POST 'http://localhost:8081/service/rest/v1/staging/move/docker-releases?tag=hello-123'
      

      The staging move will fail with an HTTP 500 response.

      The log will show:

      2022-09-27 11:57:02,662-0500 WARN [qtp590587555-842] admin org.sonatype.nexus.siesta.internal.UnexpectedExceptionMapper - (ID c73e46ce-540f-4689-bebd-d6272697a302) Unexpected exception: java.lang.NullPointerException
      java.lang.NullPointerException: null
      at org.sonatype.nexus.repository.docker.internal.orient.DockerComponentDirector.maybeCopyAssets(DockerComponentDirector.java:154)
      at org.sonatype.nexus.repository.docker.internal.orient.DockerComponentDirector.beforeMove(DockerComponentDirector.java:109)
      at org.sonatype.nexus.transaction.TransactionalWrapper.proceedWithTransaction(TransactionalWrapper.java:58)
      at org.sonatype.nexus.transaction.TransactionInterceptor.proceedWithTransaction(TransactionInterceptor.java:66)
      at org.sonatype.nexus.transaction.TransactionInterceptor.invoke(TransactionInterceptor.java:55)
      at com.sonatype.nexus.staging.internal.orient.OrientStagingComponentManager.move(OrientStagingComponentManager.java:87)
      at com.sonatype.nexus.staging.internal.orient.OrientStagingService.doMove(OrientStagingService.java:399)
      at com.sonatype.nexus.staging.internal.orient.OrientStagingService.move(OrientStagingService.java:185)
      at org.sonatype.nexus.common.stateguard.MethodInvocationAction.run(MethodInvocationAction.java:39)
      at org.sonatype.nexus.common.stateguard.StateGuard$GuardImpl.run(StateGuard.java:272)
      at org.sonatype.nexus.common.stateguard.GuardedInterceptor.invoke(GuardedInterceptor.java:54)
      at com.sonatype.nexus.staging.internal.StagingResource.move(StagingResource.java:89)
      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 org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:138)
      at org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:546)
      at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:435)
      at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$0(ResourceMethodInvoker.java:396)
      at org.jboss.resteasy.core.interception.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:358)
      at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:398)
      at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:365)
      at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:338)
      at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:440)
      at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:229)
      at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:135)
      at org.jboss.resteasy.core.interception.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:358)
      at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:138)
      at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:215)
      at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:245)
      at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:61)
      at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56)
      at org.sonatype.nexus.siesta.internal.resteasy.ComponentContainerImpl.service(ComponentContainerImpl.java:111)
      at org.sonatype.nexus.siesta.SiestaServlet.service(SiestaServlet.java:137)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)

      Expected: When deploying an image to a docker group that contains a proxy repository it is not uncommon for some of the layers in the image to already exist in the proxy repository. It should be possible to perform a staging move on these images. Likely this means copying the layers from the proxy rather than moving them.

      Workaround: If staging is needed deploy directly to hosted docker repositories, don't deploy through group repositories.

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              Unassigned Unassigned
              Reporter:
              rseddon Rich Seddon
              Last Updated By:
              Rich Seddon Rich Seddon
              Votes:
              2 Vote for this issue
              Watchers:
              5 Start watching this issue

                Dates

                Created:
                Updated:

                  tigCommentSecurity.panel-title