Ejemplo n.º 1
0
    def start_layer(self, layer_id, v1_metadata_string, location_name,
                    calling_user, temp_tag_expiration):
        """ Starts a new layer with the given ID to be placed into a manifest. Returns the layer
        started or None if an error occurred.
    """
        # Ensure the repository still exists.
        repository = model.repository.lookup_repository(
            self._repository_ref._db_id)
        if repository is None:
            return None

        namespace_name = repository.namespace_user.username
        repo_name = repository.name

        try:
            v1_metadata = json.loads(v1_metadata_string)
        except ValueError:
            logger.exception(
                "Exception when trying to parse V1 metadata JSON for layer %s",
                layer_id)
            return None
        except TypeError:
            logger.exception(
                "Exception when trying to parse V1 metadata JSON for layer %s",
                layer_id)
            return None

        # Sanity check that the ID matches the v1 metadata.
        if layer_id != v1_metadata["id"]:
            return None

        # Ensure the parent already exists in the repository.
        parent_id = v1_metadata.get("parent", None)
        parent_image = None

        if parent_id is not None:
            parent_image = model.image.get_repo_image(namespace_name,
                                                      repo_name, parent_id)
            if parent_image is None:
                return None

        # Check to see if this layer already exists in the repository. If so, we can skip the creation.
        existing_image = registry_model.get_legacy_image(
            self._repository_ref, layer_id)
        if existing_image is not None:
            self._builder_state.images[layer_id] = existing_image.id
            self._save_to_session()
            return ManifestLayer(layer_id, v1_metadata_string,
                                 existing_image.id)

        with db_transaction():
            # Otherwise, create a new legacy image and point a temporary tag at it.
            created = model.image.find_create_or_link_image(
                layer_id, repository, calling_user, {}, location_name)
            model.tag.create_temporary_hidden_tag(repository, created,
                                                  temp_tag_expiration)

            # Save its V1 metadata.
            command_list = v1_metadata.get("container_config",
                                           {}).get("Cmd", None)
            command = json.dumps(command_list) if command_list else None

            model.image.set_image_metadata(
                layer_id,
                namespace_name,
                repo_name,
                v1_metadata.get("created"),
                v1_metadata.get("comment"),
                command,
                v1_metadata_string,
                parent=parent_image,
            )

        # Save the changes to the builder.
        self._builder_state.images[layer_id] = created.id
        self._save_to_session()

        return ManifestLayer(layer_id, v1_metadata_string, created.id)
Ejemplo n.º 2
0
Archivo: tag.py Proyecto: xzwupeng/quay
    def put(self, namespace, repository, tag):
        """ Change which image a tag points to or create a new tag."""
        if not TAG_REGEX.match(tag):
            abort(400, TAG_ERROR)

        repo_ref = registry_model.lookup_repository(namespace, repository)
        if repo_ref is None:
            raise NotFound()

        if 'expiration' in request.get_json():
            tag_ref = registry_model.get_repo_tag(repo_ref, tag)
            if tag_ref is None:
                raise NotFound()

            expiration = request.get_json().get('expiration')
            expiration_date = None
            if expiration is not None:
                try:
                    expiration_date = datetime.utcfromtimestamp(
                        float(expiration))
                except ValueError:
                    abort(400)

                if expiration_date <= datetime.now():
                    abort(400)

            existing_end_ts, ok = registry_model.change_repository_tag_expiration(
                tag_ref, expiration_date)
            if ok:
                if not (existing_end_ts is None and expiration_date is None):
                    log_action(
                        'change_tag_expiration',
                        namespace, {
                            'username': get_authenticated_user().username,
                            'repo': repository,
                            'tag': tag,
                            'namespace': namespace,
                            'expiration_date': expiration_date,
                            'old_expiration_date': existing_end_ts
                        },
                        repo_name=repository)
            else:
                raise InvalidRequest(
                    'Could not update tag expiration; Tag has probably changed'
                )

        if 'image' in request.get_json(
        ) or 'manifest_digest' in request.get_json():
            existing_tag = registry_model.get_repo_tag(
                repo_ref, tag, include_legacy_image=True)

            manifest_or_image = None
            image_id = None
            manifest_digest = None

            if 'image' in request.get_json():
                image_id = request.get_json()['image']
                manifest_or_image = registry_model.get_legacy_image(
                    repo_ref, image_id)
            else:
                manifest_digest = request.get_json()['manifest_digest']
                manifest_or_image = registry_model.lookup_manifest_by_digest(
                    repo_ref, manifest_digest, require_available=True)

            if manifest_or_image is None:
                raise NotFound()

            # TODO: Remove this check once fully on V22
            existing_manifest_digest = None
            if existing_tag:
                existing_manifest = registry_model.get_manifest_for_tag(
                    existing_tag)
                existing_manifest_digest = existing_manifest.digest if existing_manifest else None

            if not registry_model.retarget_tag(repo_ref, tag,
                                               manifest_or_image, storage,
                                               docker_v2_signing_key):
                raise InvalidRequest('Could not move tag')

            username = get_authenticated_user().username

            log_action(
                'move_tag' if existing_tag else 'create_tag',
                namespace, {
                    'username':
                    username,
                    'repo':
                    repository,
                    'tag':
                    tag,
                    'namespace':
                    namespace,
                    'image':
                    image_id,
                    'manifest_digest':
                    manifest_digest,
                    'original_image':
                    (existing_tag.legacy_image.docker_image_id if existing_tag
                     and existing_tag.legacy_image_if_present else None),
                    'original_manifest_digest':
                    existing_manifest_digest,
                },
                repo_name=repository)

        return 'Updated', 201
Ejemplo n.º 3
0
    def put(self, namespace, repository, tag):
        """
        Change which image a tag points to or create a new tag.
        """
        if not TAG_REGEX.match(tag):
            abort(400, TAG_ERROR)

        repo_ref = registry_model.lookup_repository(namespace, repository)
        if repo_ref is None:
            raise NotFound()

        if "expiration" in request.get_json():
            tag_ref = registry_model.get_repo_tag(repo_ref, tag)
            if tag_ref is None:
                raise NotFound()

            expiration = request.get_json().get("expiration")
            expiration_date = None
            if expiration is not None:
                try:
                    expiration_date = datetime.utcfromtimestamp(
                        float(expiration))
                except ValueError:
                    abort(400)

                if expiration_date <= datetime.now():
                    abort(400)

            existing_end_ts, ok = registry_model.change_repository_tag_expiration(
                tag_ref, expiration_date)
            if ok:
                if not (existing_end_ts is None and expiration_date is None):
                    log_action(
                        "change_tag_expiration",
                        namespace,
                        {
                            "username": get_authenticated_user().username,
                            "repo": repository,
                            "tag": tag,
                            "namespace": namespace,
                            "expiration_date": expiration_date,
                            "old_expiration_date": existing_end_ts,
                        },
                        repo_name=repository,
                    )
            else:
                raise InvalidRequest(
                    "Could not update tag expiration; Tag has probably changed"
                )

        if "image" in request.get_json(
        ) or "manifest_digest" in request.get_json():
            existing_tag = registry_model.get_repo_tag(
                repo_ref, tag, include_legacy_image=True)

            manifest_or_image = None
            image_id = None
            manifest_digest = None

            if "image" in request.get_json():
                image_id = request.get_json()["image"]
                manifest_or_image = registry_model.get_legacy_image(
                    repo_ref, image_id)
            else:
                manifest_digest = request.get_json()["manifest_digest"]
                manifest_or_image = registry_model.lookup_manifest_by_digest(
                    repo_ref, manifest_digest, require_available=True)

            if manifest_or_image is None:
                raise NotFound()

            # TODO: Remove this check once fully on V22
            existing_manifest_digest = None
            if existing_tag:
                existing_manifest = registry_model.get_manifest_for_tag(
                    existing_tag)
                existing_manifest_digest = existing_manifest.digest if existing_manifest else None

            if not registry_model.retarget_tag(repo_ref, tag,
                                               manifest_or_image, storage,
                                               docker_v2_signing_key):
                raise InvalidRequest("Could not move tag")

            username = get_authenticated_user().username

            log_action(
                "move_tag" if existing_tag else "create_tag",
                namespace,
                {
                    "username":
                    username,
                    "repo":
                    repository,
                    "tag":
                    tag,
                    "namespace":
                    namespace,
                    "image":
                    image_id,
                    "manifest_digest":
                    manifest_digest,
                    "original_image":
                    (existing_tag.legacy_image.docker_image_id if existing_tag
                     and existing_tag.legacy_image_if_present else None),
                    "original_manifest_digest":
                    existing_manifest_digest,
                },
                repo_name=repository,
            )

        return "Updated", 201