def test_connect_existing_manifest_to_manifest_list(self, create_repo):
        repo_ref = create_repo(self.orgname, self.upstream_repository,
                               self.user)
        input_manifest = parse_manifest_from_bytes(
            Bytes.for_string_or_unicode(UBI8_LATEST_MANIFEST_SCHEMA2),
            DOCKER_SCHEMA2_MANIFEST_CONTENT_TYPE,
        )
        proxy_model = ProxyModel(
            self.orgname,
            self.upstream_repository,
            self.user,
        )
        manifest, _ = proxy_model._create_manifest_with_temp_tag(
            repo_ref, input_manifest)
        assert manifest is not None

        input_list = parse_manifest_from_bytes(
            Bytes.for_string_or_unicode(UBI8_LATEST_MANIFEST_LIST),
            DOCKER_SCHEMA2_MANIFESTLIST_CONTENT_TYPE,
            sparse_manifest_support=True,
        )
        manifest_list, _ = proxy_model._create_manifest_and_retarget_tag(
            repo_ref, input_list, self.tag)
        assert manifest_list is not None
        conn_count = (ManifestChild.select().where(
            ManifestChild.manifest == manifest_list.id,
            ManifestChild.child_manifest == manifest.id,
        ).count())
        assert conn_count == 1
 def test_create_placeholder_blobs_for_new_manifest(self, create_repo):
     repo_ref = create_repo(self.orgname, self.upstream_repository,
                            self.user)
     input_manifest = parse_manifest_from_bytes(
         Bytes.for_string_or_unicode(UBI8_8_4_MANIFEST_SCHEMA2),
         DOCKER_SCHEMA2_MANIFEST_CONTENT_TYPE,
     )
     proxy_model = ProxyModel(
         self.orgname,
         self.upstream_repository,
         self.user,
     )
     manifest, _ = proxy_model._create_manifest_and_retarget_tag(
         repo_ref, input_manifest, self.tag)
     assert manifest is not None
     blob_count = 1  # schema 2 manifests have one extra config blob
     blob_count += len(input_manifest.manifest_dict["layers"])
     mblobs = ManifestBlob.select().where(
         ManifestBlob.manifest == manifest.id)
     assert blob_count == mblobs.count()
     expected_digests = [
         layer["digest"] for layer in input_manifest.manifest_dict["layers"]
     ]
     expected_digests.append(input_manifest.config.digest)
     created_digests = [mblob.blob.content_checksum for mblob in mblobs]
     assert sorted(expected_digests) == sorted(created_digests)
    def test_returns_cached_manifest_when_it_exists_upstream(
            self, create_repo, proxy_manifest_response):
        repo_ref = create_repo(self.orgname, self.upstream_repository,
                               self.user)
        proxy_mock = proxy_manifest_response(
            UBI8_8_4_DIGEST, UBI8_8_4_MANIFEST_SCHEMA2,
            DOCKER_SCHEMA2_MANIFEST_CONTENT_TYPE)
        with patch("data.registry_model.registry_proxy_model.Proxy",
                   MagicMock(return_value=proxy_mock)):
            proxy_model = ProxyModel(
                self.orgname,
                self.upstream_repository,
                self.user,
            )
            manifest = proxy_model.lookup_manifest_by_digest(
                repo_ref, UBI8_8_4_DIGEST)
        assert manifest is not None
        assert manifest.digest == UBI8_8_4_DIGEST
        first_manifest = manifest

        with patch("data.registry_model.registry_proxy_model.Proxy",
                   MagicMock(return_value=proxy_mock)):
            manifest = proxy_model.lookup_manifest_by_digest(
                repo_ref, UBI8_8_4_DIGEST)

        assert manifest is not None
        assert manifest.id == first_manifest.id
        assert manifest.digest == first_manifest.digest

        # one for each lookup_manifest_by_digest call
        assert proxy_mock.manifest_exists.call_count == 2

        # single call from first call to lookup_manifest_by_digest
        assert proxy_mock.get_manifest.call_count == 1
    def test_bumps_tag_expiration_when_upstream_is_alive_and_cache_is_up_to_date(
            self, create_repo, proxy_manifest_response):
        repo_ref = create_repo(self.orgname, self.upstream_repository,
                               self.user)
        proxy_mock = proxy_manifest_response(
            self.tag, UBI8_8_5_MANIFEST_SCHEMA2,
            DOCKER_SCHEMA2_MANIFEST_CONTENT_TYPE)
        with patch("data.registry_model.registry_proxy_model.Proxy",
                   MagicMock(return_value=proxy_mock)):
            proxy_model = ProxyModel(
                self.orgname,
                self.upstream_repository,
                self.user,
            )
            tag = proxy_model.get_repo_tag(repo_ref, self.tag)

        assert tag is not None
        assert tag.name == self.tag

        first_tag = tag
        with patch("data.registry_model.registry_proxy_model.Proxy",
                   MagicMock(return_value=proxy_mock)):
            tag = proxy_model.get_repo_tag(repo_ref, self.tag)

        assert tag is not None
        assert tag.lifetime_end_ms > first_tag.lifetime_end_ms
    def test_renew_tag_when_manifest_is_cached_and_exists_upstream(
            self, create_repo, proxy_manifest_response):
        repo_ref = create_repo(self.orgname, self.upstream_repository,
                               self.user)
        proxy_mock = proxy_manifest_response(
            UBI8_8_4_DIGEST, UBI8_8_4_MANIFEST_SCHEMA2,
            DOCKER_SCHEMA2_MANIFEST_CONTENT_TYPE)
        with patch("data.registry_model.registry_proxy_model.Proxy",
                   MagicMock(return_value=proxy_mock)):
            proxy_model = ProxyModel(
                self.orgname,
                self.upstream_repository,
                self.user,
            )
            manifest = proxy_model.lookup_manifest_by_digest(
                repo_ref, UBI8_8_4_DIGEST)
        assert manifest is not None
        first_tag = oci.tag.get_tag_by_manifest_id(repo_ref.id, manifest.id)

        with patch("data.registry_model.registry_proxy_model.Proxy",
                   MagicMock(return_value=proxy_mock)):
            manifest = proxy_model.lookup_manifest_by_digest(
                repo_ref, UBI8_8_4_DIGEST)
        assert manifest is not None
        tag = oci.tag.get_tag_by_manifest_id(repo_ref.id, manifest.id)
        assert tag.lifetime_end_ms > first_tag.lifetime_end_ms
 def test_create_8_4_tag_for_existing_manifest(self, create_repo):
     repo_ref = create_repo(self.orgname, self.upstream_repository,
                            self.user)
     input_manifest = parse_manifest_from_bytes(
         Bytes.for_string_or_unicode(UBI8_8_4_MANIFEST_SCHEMA2),
         DOCKER_SCHEMA2_MANIFEST_CONTENT_TYPE,
     )
     proxy_model = ProxyModel(
         self.orgname,
         self.upstream_repository,
         self.user,
     )
     # first create the manifest with a temp tag
     first_manifest, _ = proxy_model._create_manifest_with_temp_tag(
         repo_ref, input_manifest)
     # now try to create it again, but using the actual tag
     manifest, tag = proxy_model._create_manifest_and_retarget_tag(
         repo_ref, input_manifest, self.tag)
     assert first_manifest is not None
     assert manifest is not None
     assert tag is not None
     assert manifest.internal_manifest_bytes.as_unicode(
     ) == UBI8_8_4_MANIFEST_SCHEMA2
     assert manifest.digest == UBI8_8_4_DIGEST
     assert manifest.id == first_manifest.id
 def test_create_temp_tags_for_newly_created_sub_manifests_on_manifest_list(
         self, create_repo):
     repo_ref = create_repo(self.orgname, self.upstream_repository,
                            self.user)
     input_manifest = parse_manifest_from_bytes(
         Bytes.for_string_or_unicode(UBI8_LATEST_MANIFEST_LIST),
         DOCKER_SCHEMA2_MANIFESTLIST_CONTENT_TYPE,
         sparse_manifest_support=True,
     )
     proxy_model = ProxyModel(
         self.orgname,
         self.upstream_repository,
         self.user,
     )
     manifest, _ = proxy_model._create_manifest_and_retarget_tag(
         repo_ref, input_manifest, self.tag)
     mchildren = ManifestChild.select(
         ManifestChild.child_manifest_id).where(
             ManifestChild.manifest == manifest.id)
     tags = Tag.select().join(
         ManifestChild,
         on=(Tag.manifest_id == ManifestChild.child_manifest_id))
     assert mchildren.count() == tags.count()
     assert all([t.hidden
                 for t in tags]), "all sub manifest tags must be hidden"
     assert all(
         [t.name != self.tag for t in tags]
     ), "sub manifest tags must have temp tag name, not parent manifest name"
 def test_passes_through_upstream_error_when_image_isnt_cached(
         self, create_repo, proxy_manifest_response):
     repo_ref = create_repo(self.orgname, self.upstream_repository,
                            self.user)
     proxy_mock = proxy_manifest_response("not-existing-ref", "", "")
     with patch("data.registry_model.registry_proxy_model.Proxy",
                MagicMock(return_value=proxy_mock)):
         proxy_model = ProxyModel(
             self.orgname,
             self.upstream_repository,
             self.user,
         )
         with pytest.raises(TagDoesNotExist):
             proxy_model.get_repo_tag(repo_ref, self.tag)
    def test_raises_exception_with_docker_v2_manifest_to_v1(self):
        def get_blob(layer):
            content = Bytes.for_string_or_unicode(layer).as_encoded_str()
            digest = str(sha256_digest(content))
            blob = store_blob_record_and_temp_link(
                self.orgname,
                self.upstream_repository,
                digest,
                ImageStorageLocation.get(name="local_us"),
                len(content),
                120,
            )
            storage.put_content(["local_us"], get_layer_path(blob), content)
            return blob, digest

        layer1 = json.dumps({
            "config": {},
            "rootfs": {
                "type": "layers",
                "diff_ids": []
            },
            "history": [{}],
        })
        _, config_digest = get_blob(layer1)
        layer2 = "hello world"
        _, blob_digest = get_blob(layer2)
        builder = DockerSchema2ManifestBuilder()
        builder.set_config_digest(config_digest, len(layer1.encode("utf-8")))
        builder.add_layer(blob_digest, len(layer2.encode("utf-8")))
        manifest = builder.build()
        created_manifest = get_or_create_manifest(self.repo_ref.id, manifest,
                                                  storage)
        assert created_manifest is not None

        proxy_model = ProxyModel(
            self.orgname,
            self.upstream_repository,
            self.user,
        )
        m = ManifestType.for_manifest(created_manifest.manifest, MagicMock())
        with pytest.raises(ManifestException):
            proxy_model.get_schema1_parsed_manifest(
                m,
                self.orgname,
                self.upstream_repository,
                self.tag,
                storage,
                raise_on_error=True,
            )
Exemple #10
0
    def setup(self, client, app):
        self.client = client

        self.user = model.user.get_user("devtable")
        context, subject = build_context_and_subject(
            ValidatedAuthContext(user=self.user))
        access = [{
            "type": "repository",
            "name": self.repository,
            "actions": ["pull"],
        }]
        token = generate_bearer_token(realapp.config["SERVER_HOSTNAME"],
                                      subject, context, access, 600,
                                      instance_keys)
        self.headers = {
            "Authorization": f"Bearer {token.decode('ascii')}",
        }

        try:
            model.organization.get(self.org)
        except Exception:
            org = model.organization.create_organization(
                self.org, "*****@*****.**", self.user)
            org.save()

        if self.config is None:
            self.config = model.proxy_cache.create_proxy_cache_config(
                org_name=self.org,
                upstream_registry=self.registry,
                expiration_s=3600,
            )

        if self.repo_ref is None:
            r = model.repository.create_repository(self.org, self.image_name,
                                                   self.user)
            assert r is not None
            self.repo_ref = registry_model.lookup_repository(
                self.org, self.image_name)
            assert self.repo_ref is not None

        if self.blob_digest is None:
            proxy_model = ProxyModel(self.org, self.image_name, self.user)
            manifest = proxy_model.lookup_manifest_by_digest(
                self.repo_ref, self.manifest_digest)
            self.blob_digest = manifest.get_parsed_manifest().blob_digests[0]
 def test_raises_exception_with_manifest_list(self):
     manifest = parse_manifest_from_bytes(
         Bytes.for_string_or_unicode(UBI8_LATEST_MANIFEST_LIST),
         DOCKER_SCHEMA2_MANIFESTLIST_CONTENT_TYPE,
     )
     proxy_model = ProxyModel(
         self.orgname,
         self.upstream_repository,
         self.user,
     )
     with pytest.raises(ManifestException):
         proxy_model.get_schema1_parsed_manifest(
             manifest,
             self.orgname,
             self.upstream_repository,
             self.tag,
             storage,
             raise_on_error=True,
         )
    def test_caches_manifest_on_first_pull(self, create_repo,
                                           proxy_manifest_response):
        repo_ref = create_repo(self.orgname, self.upstream_repository,
                               self.user)
        proxy_mock = proxy_manifest_response(
            self.tag, UBI8_8_4_MANIFEST_SCHEMA2,
            DOCKER_SCHEMA2_MANIFEST_CONTENT_TYPE)
        with patch("data.registry_model.registry_proxy_model.Proxy",
                   MagicMock(return_value=proxy_mock)):
            proxy_model = ProxyModel(
                self.orgname,
                self.upstream_repository,
                self.user,
            )
            tag = proxy_model.get_repo_tag(repo_ref, self.tag)

        assert tag is not None
        assert tag.manifest is not None
        assert tag.manifest.internal_manifest_bytes.as_unicode(
        ) == UBI8_8_4_MANIFEST_SCHEMA2
 def test_create_manifest_and_temp_tag_when_they_dont_exist(
         self, create_repo):
     repo_ref = create_repo(self.orgname, self.upstream_repository,
                            self.user)
     input_manifest = parse_manifest_from_bytes(
         Bytes.for_string_or_unicode(UBI8_8_4_MANIFEST_SCHEMA2),
         DOCKER_SCHEMA2_MANIFEST_CONTENT_TYPE,
     )
     proxy_model = ProxyModel(
         self.orgname,
         self.upstream_repository,
         self.user,
     )
     manifest, tag = proxy_model._create_manifest_and_retarget_tag(
         repo_ref, input_manifest, self.tag)
     assert manifest is not None
     assert tag is not None
     assert manifest.internal_manifest_bytes.as_unicode(
     ) == UBI8_8_4_MANIFEST_SCHEMA2
     assert manifest.digest == UBI8_8_4_DIGEST
    def test_renews_expired_tag_when_manifest_is_up_to_date_with_upstream(
            self, create_repo, proxy_manifest_response):
        repo_ref = create_repo(self.orgname, self.upstream_repository,
                               self.user)
        proxy_mock = proxy_manifest_response(
            self.tag, UBI8_8_5_MANIFEST_SCHEMA2,
            DOCKER_SCHEMA2_MANIFEST_CONTENT_TYPE)
        with patch("data.registry_model.registry_proxy_model.Proxy",
                   MagicMock(return_value=proxy_mock)):
            proxy_model = ProxyModel(
                self.orgname,
                self.upstream_repository,
                self.user,
            )
            tag = proxy_model.get_repo_tag(repo_ref, self.tag)

        assert tag is not None
        assert tag.name == self.tag

        # expire the tag by setting start and end time to the past
        before_ms = get_epoch_timestamp_ms() - timedelta(
            hours=24).total_seconds() * 1000
        Tag.update(
            lifetime_start_ms=before_ms,
            lifetime_end_ms=before_ms + 5,
        ).where(Tag.id == tag.id).execute()

        expired_tag = tag

        with patch("data.registry_model.registry_proxy_model.Proxy",
                   MagicMock(return_value=proxy_mock)):
            tag = proxy_model.get_repo_tag(repo_ref, self.tag)

        assert tag is not None
        assert expired_tag.id == tag.id
        assert expired_tag.manifest.id == tag.manifest.id
        assert not tag.expired
        new_expiration_ms = get_epoch_timestamp_ms(
        ) + self.config.expiration_s * 1000
        # subtract a some milliseconds so the test doesn't flake
        assert tag.lifetime_end_ms >= new_expiration_ms - 500
 def test_create_sub_manifests_for_manifest_list(self, create_repo):
     repo_ref = create_repo(self.orgname, self.upstream_repository,
                            self.user)
     input_manifest = parse_manifest_from_bytes(
         Bytes.for_string_or_unicode(UBI8_LATEST_MANIFEST_LIST),
         DOCKER_SCHEMA2_MANIFESTLIST_CONTENT_TYPE,
         sparse_manifest_support=True,
     )
     proxy_model = ProxyModel(
         self.orgname,
         self.upstream_repository,
         self.user,
     )
     manifest, _ = proxy_model._create_manifest_and_retarget_tag(
         repo_ref, input_manifest, self.tag)
     mchildren = ManifestChild.select().where(
         ManifestChild.manifest == manifest.id)
     created_count = mchildren.count()
     expected_count = len(
         list(input_manifest.child_manifests(content_retriever=None)))
     assert expected_count == created_count
    def test_does_not_bump_tag_expiration_when_manifest_is_cached_and_upstream_errors(
            self, create_repo, proxy_manifest_response):
        repo_ref = create_repo(self.orgname, self.upstream_repository,
                               self.user)
        proxy_mock = proxy_manifest_response(
            UBI8_8_4_DIGEST, UBI8_8_4_MANIFEST_SCHEMA2,
            DOCKER_SCHEMA2_MANIFEST_CONTENT_TYPE)
        with patch("data.registry_model.registry_proxy_model.Proxy",
                   MagicMock(return_value=proxy_mock)):
            proxy_model = ProxyModel(
                self.orgname,
                self.upstream_repository,
                self.user,
            )
            manifest = proxy_model.lookup_manifest_by_digest(
                repo_ref, UBI8_8_4_DIGEST)
        assert manifest is not None
        first_tag = Tag.get(manifest_id=manifest.id)

        proxy_mock = proxy_manifest_response("not-existing-ref", "", "")
        with patch("data.registry_model.registry_proxy_model.Proxy",
                   MagicMock(return_value=proxy_mock)):
            proxy_model = ProxyModel(
                self.orgname,
                self.upstream_repository,
                self.user,
            )
            manifest = proxy_model.lookup_manifest_by_digest(
                repo_ref, UBI8_8_4_DIGEST)
        assert manifest is not None
        tag = Tag.get(manifest_id=manifest.id)
        assert tag.id == first_tag.id
        assert tag.lifetime_end_ms == first_tag.lifetime_end_ms
    def test_returns_cached_manifest_when_upstream_errors_and_cache_is_not_expired(
            self, create_repo, proxy_manifest_response):
        repo_ref = create_repo(self.orgname, self.upstream_repository,
                               self.user)
        proxy_mock = proxy_manifest_response(
            UBI8_8_4_DIGEST, UBI8_8_4_MANIFEST_SCHEMA2,
            DOCKER_SCHEMA2_MANIFEST_CONTENT_TYPE)
        with patch("data.registry_model.registry_proxy_model.Proxy",
                   MagicMock(return_value=proxy_mock)):
            proxy_model = ProxyModel(
                self.orgname,
                self.upstream_repository,
                self.user,
            )
            manifest = proxy_model.lookup_manifest_by_digest(
                repo_ref, UBI8_8_4_DIGEST)
        assert manifest is not None
        assert manifest.digest == UBI8_8_4_DIGEST
        first_manifest = manifest

        proxy_mock = proxy_manifest_response("not-existing-ref", "", "")
        with patch("data.registry_model.registry_proxy_model.Proxy",
                   MagicMock(return_value=proxy_mock)):
            proxy_model = ProxyModel(
                self.orgname,
                self.upstream_repository,
                self.user,
            )
            manifest = proxy_model.lookup_manifest_by_digest(
                repo_ref, UBI8_8_4_DIGEST)
        assert manifest is not None
        assert manifest.id == first_manifest.id
        assert manifest.digest == first_manifest.digest
        assert proxy_mock.manifest_exists.call_count == 1
        assert proxy_mock.get_manifest.call_count == 0
    def test_return_None_when_manifest_is_placeholder_and_upstream_is_down(
            self, create_repo, proxy_manifest_response):
        repo_ref = create_repo(self.orgname, self.upstream_repository,
                               self.user)
        proxy_mock = proxy_manifest_response(
            "latest", UBI8_LATEST_MANIFEST_LIST,
            DOCKER_SCHEMA2_MANIFESTLIST_CONTENT_TYPE)
        with patch("data.registry_model.registry_proxy_model.Proxy",
                   MagicMock(return_value=proxy_mock)):
            proxy_model = ProxyModel(
                self.orgname,
                self.upstream_repository,
                self.user,
            )
            tag = proxy_model.get_repo_tag(repo_ref, "latest")
        assert tag is not None
        assert tag.manifest is not None

        proxy_mock = proxy_manifest_response("does-not-exist", "", "")
        with patch("data.registry_model.registry_proxy_model.Proxy",
                   MagicMock(return_value=proxy_mock)):
            proxy_model = ProxyModel(
                self.orgname,
                self.upstream_repository,
                self.user,
            )
            manifest = proxy_model.lookup_manifest_by_digest(
                repo_ref, UBI8_LATEST_DIGEST)
        assert manifest is None
    def test_update_relevant_manifest_fields_when_manifest_is_placeholder(
            self, create_repo, proxy_manifest_response):
        repo_ref = create_repo(self.orgname, self.upstream_repository,
                               self.user)
        proxy_mock = proxy_manifest_response(
            "latest", UBI8_LATEST_MANIFEST_LIST,
            DOCKER_SCHEMA2_MANIFESTLIST_CONTENT_TYPE)
        with patch("data.registry_model.registry_proxy_model.Proxy",
                   MagicMock(return_value=proxy_mock)):
            proxy_model = ProxyModel(
                self.orgname,
                self.upstream_repository,
                self.user,
            )
            tag = proxy_model.get_repo_tag(repo_ref, "latest")
        assert tag is not None
        assert tag.manifest.digest == UBI8_LATEST_MANIFEST_LIST_DIGEST
        assert tag.manifest.is_manifest_list

        proxy_mock = proxy_manifest_response(
            UBI8_LATEST_DIGEST, UBI8_LATEST_MANIFEST_SCHEMA2,
            DOCKER_SCHEMA2_MANIFEST_CONTENT_TYPE)
        with patch("data.registry_model.registry_proxy_model.Proxy",
                   MagicMock(return_value=proxy_mock)):
            proxy_model = ProxyModel(
                self.orgname,
                self.upstream_repository,
                self.user,
            )
            manifest = proxy_model.lookup_manifest_by_digest(
                repo_ref, UBI8_LATEST_DIGEST)
        mbytes = manifest.internal_manifest_bytes.as_unicode()
        assert mbytes != ""
        assert manifest.digest == UBI8_LATEST_DIGEST
        assert manifest.layers_compressed_size == 772795
    def test_returns_None_when_manifest_no_longer_exists_upstream_and_local_cache_is_expired(
            self, create_repo, proxy_manifest_response):
        repo_ref = create_repo(self.orgname, self.upstream_repository,
                               self.user)
        proxy_mock = proxy_manifest_response(
            self.tag, UBI8_8_5_MANIFEST_SCHEMA2,
            DOCKER_SCHEMA2_MANIFEST_CONTENT_TYPE)
        with patch("data.registry_model.registry_proxy_model.Proxy",
                   MagicMock(return_value=proxy_mock)):
            proxy_model = ProxyModel(
                self.orgname,
                self.upstream_repository,
                self.user,
            )
            tag = proxy_model.get_repo_tag(repo_ref, self.tag)
        assert tag is not None

        # expire the tag by setting start and end time to the past
        before_ms = get_epoch_timestamp_ms() - timedelta(
            hours=24).total_seconds() * 1000
        Tag.update(
            lifetime_start_ms=before_ms,
            lifetime_end_ms=before_ms + 5,
        ).where(Tag.id == tag.id).execute()

        proxy_mock = proxy_manifest_response("not-existing-ref", "", "")
        with patch("data.registry_model.registry_proxy_model.Proxy",
                   MagicMock(return_value=proxy_mock)):
            proxy_model = ProxyModel(
                self.orgname,
                self.upstream_repository,
                self.user,
            )
            tag = proxy_model.get_repo_tag(repo_ref, self.tag)
        assert tag is None
    def test_doesnt_bump_tag_expiration_when_upstream_is_dead(
            self, create_repo, proxy_manifest_response):
        repo_ref = create_repo(self.orgname, self.upstream_repository,
                               self.user)
        proxy_mock = proxy_manifest_response(
            self.tag, UBI8_8_5_MANIFEST_SCHEMA2,
            DOCKER_SCHEMA2_MANIFEST_CONTENT_TYPE)
        with patch("data.registry_model.registry_proxy_model.Proxy",
                   MagicMock(return_value=proxy_mock)):
            proxy_model = ProxyModel(
                self.orgname,
                self.upstream_repository,
                self.user,
            )
            tag = proxy_model.get_repo_tag(repo_ref, self.tag)
        assert tag is not None
        first_tag = tag

        proxy_mock = proxy_manifest_response("not-existing-ref", "", "")
        with patch("data.registry_model.registry_proxy_model.Proxy",
                   MagicMock(return_value=proxy_mock)):
            proxy_model = ProxyModel(
                self.orgname,
                self.upstream_repository,
                self.user,
            )
            tag = proxy_model.get_repo_tag(repo_ref, self.tag)
        assert tag is not None
        assert tag.lifetime_end_ms == first_tag.lifetime_end_ms
    def test_connect_existing_blobs_to_new_manifest(self, create_repo):
        repo_ref = create_repo(self.orgname, self.upstream_repository,
                               self.user)
        input_manifest = parse_manifest_from_bytes(
            Bytes.for_string_or_unicode(UBI8_8_4_MANIFEST_SCHEMA2),
            DOCKER_SCHEMA2_MANIFEST_CONTENT_TYPE,
        )
        layer = input_manifest.manifest_dict["layers"][0]
        blob = ImageStorage.create(
            image_size=layer["size"],
            uncompressed_size=layer["size"],
            content_checksum=layer["digest"],
        )

        proxy_model = ProxyModel(
            self.orgname,
            self.upstream_repository,
            self.user,
        )
        proxy_model._create_manifest_and_retarget_tag(repo_ref, input_manifest,
                                                      self.tag)
        blob_count = (ImageStorage.select().where(
            ImageStorage.content_checksum == blob.content_checksum).count())
        assert blob_count == 1
def test_registry_proxy_model_init_only_query_db_once(initialized_db):
    orgname = "testorg"
    user = get_user("devtable")
    org = create_organization(orgname, "{self.orgname}@devtable.com", user)
    org.save()
    create_proxy_cache_config(
        org_name=orgname,
        upstream_registry="quay.io",
        expiration_s=3600,
    )
    with assert_query_count(1):
        ProxyModel(
            orgname,
            "app-sre/ubi8-ubi",
            user,
        )
    def test_renew_manifest_and_parent_tag_when_manifest_is_child_of_manifest_list(
            self, create_repo, proxy_manifest_response):
        repo_ref = create_repo(self.orgname, self.upstream_repository,
                               self.user)
        input_list = parse_manifest_from_bytes(
            Bytes.for_string_or_unicode(UBI8_LATEST_MANIFEST_LIST),
            DOCKER_SCHEMA2_MANIFESTLIST_CONTENT_TYPE,
            sparse_manifest_support=True,
        )
        with patch("data.registry_model.registry_proxy_model.Proxy",
                   MagicMock()):
            proxy_model = ProxyModel(
                self.orgname,
                self.upstream_repository,
                self.user,
            )
            manifest_list, tag = proxy_model._create_manifest_and_retarget_tag(
                repo_ref, input_list, "latest")

        assert manifest_list is not None
        child = (ManifestChild.select(ManifestChild.child_manifest_id).join(
            Manifest,
            on=(ManifestChild.child_manifest_id == Manifest.id
                )).where((ManifestChild.manifest_id == manifest_list.id)
                         & (Manifest.digest == UBI8_LATEST_DIGEST)))
        manifest_tag = Tag.select().where(Tag.manifest == child).get()
        manifest_list_tag = tag

        proxy_mock = proxy_manifest_response(
            UBI8_LATEST_DIGEST, UBI8_LATEST_MANIFEST_SCHEMA2,
            DOCKER_SCHEMA2_MANIFEST_CONTENT_TYPE)
        with patch("data.registry_model.registry_proxy_model.Proxy",
                   MagicMock(return_value=proxy_mock)):
            proxy_model = ProxyModel(
                self.orgname,
                self.upstream_repository,
                self.user,
            )
            manifest = proxy_model.lookup_manifest_by_digest(
                repo_ref, UBI8_LATEST_DIGEST)

        updated_tag = oci.tag.get_tag_by_manifest_id(repo_ref.id, manifest.id)
        updated_list_tag = oci.tag.get_tag_by_manifest_id(
            repo_ref.id, manifest_list.id)

        assert updated_tag.id == manifest_tag.id
        assert updated_list_tag.id == manifest_list_tag.id
        assert updated_tag.lifetime_end_ms > manifest_tag.lifetime_end_ms
        assert updated_list_tag.lifetime_end_ms > manifest_list_tag.lifetime_end_ms
    def test_renew_tag_when_cache_is_expired_and_manifest_is_up_to_date_with_upstream(
            self, create_repo, proxy_manifest_response):
        repo_ref = create_repo(self.orgname, self.upstream_repository,
                               self.user)
        proxy_mock = proxy_manifest_response(
            UBI8_8_4_DIGEST, UBI8_8_4_MANIFEST_SCHEMA2,
            DOCKER_SCHEMA2_MANIFEST_CONTENT_TYPE)
        with patch("data.registry_model.registry_proxy_model.Proxy",
                   MagicMock(return_value=proxy_mock)):
            proxy_model = ProxyModel(
                self.orgname,
                self.upstream_repository,
                self.user,
            )
            manifest = proxy_model.lookup_manifest_by_digest(
                repo_ref, UBI8_8_4_DIGEST)
        assert manifest is not None

        before_ms = get_epoch_timestamp_ms() - timedelta(
            hours=24).total_seconds() * 1000
        Tag.update(
            lifetime_start_ms=before_ms,
            lifetime_end_ms=before_ms + 5,
        ).where(Tag.manifest == manifest.id).execute()

        with patch("data.registry_model.registry_proxy_model.Proxy",
                   MagicMock(return_value=proxy_mock)):
            proxy_model = ProxyModel(
                self.orgname,
                self.upstream_repository,
                self.user,
            )
            manifest = proxy_model.lookup_manifest_by_digest(
                repo_ref, UBI8_8_4_DIGEST)
        assert manifest is not None
        tag = Tag.get(manifest_id=manifest.id)
        now_ms = get_epoch_timestamp_ms()
        assert tag.lifetime_end_ms > now_ms
    def test_updates_manifest_and_bumps_tag_expiration_when_upstream_manifest_changed(
            self, create_repo, proxy_manifest_response):
        repo_ref = create_repo(self.orgname, self.upstream_repository,
                               self.user)
        proxy_mock = proxy_manifest_response(
            self.tag, UBI8_8_4_MANIFEST_SCHEMA2,
            DOCKER_SCHEMA2_MANIFEST_CONTENT_TYPE)
        with patch("data.registry_model.registry_proxy_model.Proxy",
                   MagicMock(return_value=proxy_mock)):
            proxy_model = ProxyModel(
                self.orgname,
                self.upstream_repository,
                self.user,
            )
            tag = proxy_model.get_repo_tag(repo_ref, self.tag)

        assert tag is not None
        assert tag.name == self.tag

        first_manifest = tag.manifest

        proxy_mock = proxy_manifest_response(
            self.tag, UBI8_8_5_MANIFEST_SCHEMA2,
            DOCKER_SCHEMA2_MANIFEST_CONTENT_TYPE)
        with patch("data.registry_model.registry_proxy_model.Proxy",
                   MagicMock(return_value=proxy_mock)):
            proxy_model = ProxyModel(
                self.orgname,
                self.upstream_repository,
                self.user,
            )
            tag = proxy_model.get_repo_tag(repo_ref, self.tag)

        assert tag is not None
        assert tag.name == self.tag
        assert tag.manifest.id != first_manifest.id
        assert tag.manifest.digest == UBI8_8_5_DIGEST