Skip to content

Disallow tag deletion when container repository is importing

Steve Abrams requested to merge 349747-skip-delete-importing into master

🦋 Context

We are preparing for Phase 2 of the Container Registry migration which involves importing all existing container repositories to the new platform (Phase 1 involved routing all new container repositories to the new platform). See &7316 (closed) for full details of how the import will work.

When a container repository is importing, it becomes read only and is locked for pushing and deletion. If a user tries to delete a repository tag while it is locked, the registry will throw an error. Currently, we have a guard in place when users make requests to push or delete a new tag using their docker client, but we also allow tag deletion using the API and through cleanup policies. We need to guard those deletions, which is what this MR is all about.

🔎 What does this MR do and why?

Container registry tag deletion is handled by Projects::ContainerRepository::DeleteTagsService. We add a guard here to reject the deletion if the repository is currently importing.

Screenshots or screen recordings

See below.

🖥 How to set up and validate locally

  1. Push an image with a few tags to one of your projects (this example is using a project asdf in the root user namespace):

    # this retags alpine:latest and push it multiple times
    docker pull alpine:latest
    docker tag alpine:latest gdk.test:5000/root/asdf:latest
    docker tag alpine:latest gdk.test:5000/root/asdf:foo
    docker tag alpine:latest gdk.test:5000/root/asdf:bar
    
    docker push gdk.test:5000/root/asdf:latest
    docker push gdk.test:5000/root/asdf:foo
    docker push gdk.test:5000/root/asdf:bar
  2. In the rails console, get the container repository id and project id:

    c = ContainerRepository.last
    c.id
    c.project.id
  3. Delete a tag with the API

    $ curl --request DELETE --header "PRIVATE-TOKEN: <personal_access_token>" \
      "http://gdk.test:3001/api/v4/projects/<project_id>/registry/repositories/<container_repository_id>/tags/foo"
    200

    The request should succeed and you can verify the tag is gone in the UI or rails console.

  4. In the rails console, change the container repository migraiton_state to importing:

    c.update_columns(migration_state: 'importing', migration_import_started_at: Time.zone.now)
  5. Try to delete another tag

    $ curl --request DELETE --header "PRIVATE-TOKEN: <personal_access_token>" \
      "http://gdk.test:3001/api/v4/projects/<project_id>/registry/repositories/<container_repository_id>/tags/bar"
    400

    The request should fail and you can verify the tag remains in the UI or rails console.

🛂 MR acceptance checklist

This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.

Related to #349747 (closed)

Edited by Steve Abrams

Merge request reports