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_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_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_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_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_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_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_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_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_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
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_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_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_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