Beispiel #1
0
Datei: tag.py Projekt: ynnt/quay
def create_temporary_hidden_tag(repo, image_obj, expiration_s):
    """
    Create a tag with a defined timeline, that will not appear in the UI or CLI.

    Returns the name of the temporary tag or None on error.
    """
    now_ts = get_epoch_timestamp()
    expire_ts = now_ts + expiration_s
    tag_name = str(uuid4())

    # Ensure the repository is not marked for deletion.
    with db_transaction():
        current = Repository.get(id=repo)
        if current.state == RepositoryState.MARKED_FOR_DELETION:
            return None

        RepositoryTag.create(
            repository=repo,
            image=image_obj,
            name=tag_name,
            lifetime_start_ts=now_ts,
            lifetime_end_ts=expire_ts,
            hidden=True,
        )
        return tag_name
Beispiel #2
0
Datei: tag.py Projekt: zhill/quay
def create_temporary_hidden_tag(repo, image_obj, expiration_s):
    """ Create a tag with a defined timeline, that will not appear in the UI or CLI. Returns the name
      of the temporary tag. """
    now_ts = get_epoch_timestamp()
    expire_ts = now_ts + expiration_s
    tag_name = str(uuid4())
    RepositoryTag.create(
        repository=repo,
        image=image_obj,
        name=tag_name,
        lifetime_start_ts=now_ts,
        lifetime_end_ts=expire_ts,
        hidden=True,
    )
    return tag_name
Beispiel #3
0
def test_manifest_backfill_broken_tag(clear_rows, initialized_db):
    """
    Tests backfilling a broken tag.
    """
    # Delete existing tag manifest so we can reuse the tag.
    TagManifestLabel.delete().execute()
    TagManifest.delete().execute()

    # Create a tag with an image referenced missing parent images.
    repo = model.repository.get_repository("devtable", "gargantuan")
    broken_image = Image.create(
        docker_image_id="foo",
        repository=repo,
        ancestors="/348723847234/",
        storage=ImageStorage.get(),
    )
    broken_image_tag = RepositoryTag.create(repository=repo,
                                            image=broken_image,
                                            name="broken")

    # Backfill the tag.
    assert backfill_tag(broken_image_tag)

    # Ensure we backfilled, even though we reference a broken manifest.
    tag_manifest = TagManifest.get(tag=broken_image_tag)

    map_row = TagManifestToManifest.get(tag_manifest=tag_manifest)
    manifest = map_row.manifest
    assert manifest.manifest_bytes == tag_manifest.json_data

    tag = TagToRepositoryTag.get(repository_tag=broken_image_tag).tag
    assert tag.name == "broken"
    assert tag.manifest == manifest
Beispiel #4
0
Datei: tag.py Projekt: zhill/quay
def create_or_update_tag_for_repo(repository_id,
                                  tag_name,
                                  tag_docker_image_id,
                                  reversion=False,
                                  oci_manifest=None,
                                  now_ms=None):
    now_ms = now_ms or get_epoch_timestamp_ms()
    now_ts = int(now_ms / 1000)

    with db_transaction():
        try:
            tag = db_for_update(
                _tag_alive(
                    RepositoryTag.select().where(
                        RepositoryTag.repository == repository_id,
                        RepositoryTag.name == tag_name),
                    now_ts,
                )).get()
            tag.lifetime_end_ts = now_ts
            tag.save()

            # Check for an OCI tag.
            try:
                oci_tag = db_for_update(
                    Tag.select().join(TagToRepositoryTag).where(
                        TagToRepositoryTag.repository_tag == tag)).get()
                oci_tag.lifetime_end_ms = now_ms
                oci_tag.save()
            except Tag.DoesNotExist:
                pass
        except RepositoryTag.DoesNotExist:
            pass
        except IntegrityError:
            msg = "Tag with name %s was stale when we tried to update it; Please retry the push"
            raise StaleTagException(msg % tag_name)

        try:
            image_obj = Image.get(Image.docker_image_id == tag_docker_image_id,
                                  Image.repository == repository_id)
        except Image.DoesNotExist:
            raise DataModelException("Invalid image with id: %s" %
                                     tag_docker_image_id)

        try:
            created = RepositoryTag.create(
                repository=repository_id,
                image=image_obj,
                name=tag_name,
                lifetime_start_ts=now_ts,
                reversion=reversion,
            )
            if oci_manifest:
                # Create the OCI tag as well.
                oci_tag = Tag.create(
                    repository=repository_id,
                    manifest=oci_manifest,
                    name=tag_name,
                    lifetime_start_ms=now_ms,
                    reversion=reversion,
                    tag_kind=Tag.tag_kind.get_id("tag"),
                )
                TagToRepositoryTag.create(tag=oci_tag,
                                          repository_tag=created,
                                          repository=repository_id)

            return created
        except IntegrityError:
            msg = "Tag with name %s and lifetime start %s already exists"
            raise TagAlreadyCreatedException(msg % (tag_name, now_ts))
Beispiel #5
0
def retarget_tag(tag_name,
                 manifest_id,
                 is_reversion=False,
                 now_ms=None,
                 adjust_old_model=True):
    """
    Creates or updates a tag with the specified name to point to the given manifest under its
    repository.

    If this action is a reversion to a previous manifest, is_reversion should be set to True.
    Returns the newly created tag row or None on error.
    """
    try:
        manifest = (Manifest.select(
            Manifest,
            MediaType).join(MediaType).where(Manifest.id == manifest_id).get())
    except Manifest.DoesNotExist:
        return None

    # CHECK: Make sure that we are not mistargeting a schema 1 manifest to a tag with a different
    # name.
    if manifest.media_type.name in DOCKER_SCHEMA1_CONTENT_TYPES:
        try:
            parsed = DockerSchema1Manifest(Bytes.for_string_or_unicode(
                manifest.manifest_bytes),
                                           validate=False)
            if parsed.tag != tag_name:
                logger.error(
                    "Tried to re-target schema1 manifest with tag `%s` to tag `%s",
                    parsed.tag,
                    tag_name,
                )
                return None
        except MalformedSchema1Manifest:
            logger.exception("Could not parse schema1 manifest")
            return None

    legacy_image = get_legacy_image_for_manifest(manifest)
    now_ms = now_ms or get_epoch_timestamp_ms()
    now_ts = int(now_ms / 1000)

    with db_transaction():
        # Lookup an existing tag in the repository with the same name and, if present, mark it
        # as expired.
        existing_tag = get_tag(manifest.repository_id, tag_name)
        if existing_tag is not None:
            _, okay = set_tag_end_ms(existing_tag, now_ms)

            # TODO: should we retry here and/or use a for-update?
            if not okay:
                return None

        # Create a new tag pointing to the manifest with a lifetime start of now.
        created = Tag.create(
            name=tag_name,
            repository=manifest.repository_id,
            lifetime_start_ms=now_ms,
            reversion=is_reversion,
            manifest=manifest,
            tag_kind=Tag.tag_kind.get_id("tag"),
        )

        # TODO: Remove the linkage code once RepositoryTag is gone.
        # If this is a schema 1 manifest, then add a TagManifest linkage to it. Otherwise, it will only
        # be pullable via the new OCI model.
        if adjust_old_model:
            if (manifest.media_type.name in DOCKER_SCHEMA1_CONTENT_TYPES
                    and legacy_image is not None):
                old_style_tag = RepositoryTag.create(
                    repository=manifest.repository_id,
                    image=legacy_image,
                    name=tag_name,
                    lifetime_start_ts=now_ts,
                    reversion=is_reversion,
                )
                TagToRepositoryTag.create(tag=created,
                                          repository_tag=old_style_tag,
                                          repository=manifest.repository_id)

                tag_manifest = TagManifest.create(
                    tag=old_style_tag,
                    digest=manifest.digest,
                    json_data=manifest.manifest_bytes)
                TagManifestToManifest.create(tag_manifest=tag_manifest,
                                             manifest=manifest,
                                             repository=manifest.repository_id)

        return created