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 set_tag_end_ts(tag, end_ts): """ Sets the end timestamp for a tag. Should only be called by change_tag_expiration or tests. """ end_ms = end_ts * 1000 if end_ts is not None else None with db_transaction(): # Note: We check not just the ID of the tag but also its lifetime_end_ts, to ensure that it has # not changed while we were updating it expiration. result = (RepositoryTag.update(lifetime_end_ts=end_ts).where( RepositoryTag.id == tag.id, RepositoryTag.lifetime_end_ts == tag.lifetime_end_ts).execute()) # Check for a mapping to an OCI tag. try: oci_tag = (Tag.select().join(TagToRepositoryTag).where( TagToRepositoryTag.repository_tag == tag).get()) (Tag.update(lifetime_end_ms=end_ms).where( Tag.id == oci_tag.id, Tag.lifetime_end_ms == oci_tag.lifetime_end_ms).execute()) except Tag.DoesNotExist: pass return (tag.lifetime_end_ts, result > 0)
def set_tag_end_ms(tag, end_ms): """ Sets the end timestamp for a tag. Should only be called by change_tag_expiration or tests. """ with db_transaction(): updated = (Tag.update(lifetime_end_ms=end_ms).where( Tag.id == tag).where( Tag.lifetime_end_ms == tag.lifetime_end_ms).execute()) if updated != 1: return (None, False) # TODO: Remove the linkage code once RepositoryTag is gone. try: old_style_tag = (TagToRepositoryTag.select( TagToRepositoryTag, RepositoryTag).join(RepositoryTag).where( TagToRepositoryTag.tag == tag).get()).repository_tag old_style_tag.lifetime_end_ts = end_ms // 1000 if end_ms is not None else None old_style_tag.save() except TagToRepositoryTag.DoesNotExist: pass return (tag.lifetime_end_ms, True)
def _delete_tag(tag, now_ms): """ Deletes the given tag by marking it as expired. """ now_ts = int(now_ms // 1000) with db_transaction(): updated = (Tag.update(lifetime_end_ms=now_ms).where( Tag.id == tag.id, Tag.lifetime_end_ms == tag.lifetime_end_ms).execute()) if updated != 1: return None # TODO: Remove the linkage code once RepositoryTag is gone. try: old_style_tag = (TagToRepositoryTag.select( TagToRepositoryTag, RepositoryTag).join(RepositoryTag).where( TagToRepositoryTag.tag == tag).get()).repository_tag old_style_tag.lifetime_end_ts = now_ts old_style_tag.save() except TagToRepositoryTag.DoesNotExist: pass return tag
def test_get_current_tag_with_multiple_expired_tags(initialized_db): repo = model.repository.create_repository("devtable", "newrepo", None) manifest, _ = create_manifest_for_testing(repo, "1") nowms = get_epoch_timestamp_ms() count = (Tag.update( lifetime_start_ms=nowms - timedelta(hours=24).total_seconds() * 1000, lifetime_end_ms=nowms - timedelta(hours=12).total_seconds() * 1000, ).where(Tag.manifest == manifest.id).execute()) expired_tag = create_temporary_tag_if_necessary(manifest, 3600) expired_tag = Tag.create( name="v6.6.6", repository=repo.id, lifetime_start_ms=nowms - timedelta(hours=10).total_seconds() * 1000, lifetime_end_ms=nowms - timedelta(hours=8).total_seconds() * 1000, reversion=False, hidden=False, manifest=manifest, tag_kind=Tag.tag_kind.get_id("tag"), ) tag = Tag.create( name="v6.6.6", repository=repo.id, lifetime_start_ms=nowms - timedelta(hours=5).total_seconds() * 1000, lifetime_end_ms=nowms + timedelta(hours=5).total_seconds() * 1000, reversion=False, hidden=False, manifest=manifest, tag_kind=Tag.tag_kind.get_id("tag"), ) current_tag = get_current_tag(repo.id, tag.name) assert current_tag.id == tag.id
def test_get_current_tag_with_expired_tag(initialized_db): repo = model.repository.create_repository("devtable", "newrepo", None) manifest, _ = create_manifest_for_testing(repo, "1") before_ms = get_epoch_timestamp_ms() - timedelta( hours=24).total_seconds() * 1000 count = (Tag.update( lifetime_start_ms=before_ms, lifetime_end_ms=before_ms + 5, ).where(Tag.manifest == manifest.id).execute()) assert count == 1
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
def test_get_tag_by_manifest_id_multiple_tags_returns_latest(initialized_db): repo = model.repository.create_repository("devtable", "newrepo", None) manifest, _ = create_manifest_for_testing(repo, "1") before_ms = get_epoch_timestamp_ms() - timedelta( hours=24).total_seconds() * 1000 count = (Tag.update( lifetime_start_ms=before_ms, lifetime_end_ms=before_ms + 5, ).where(Tag.manifest == manifest.id).execute()) assert count == 1 expired_tag = get_tag_by_manifest_id(repo.id, manifest.id) new_tag = create_temporary_tag_if_necessary( manifest, get_epoch_timestamp_ms() + 3600 * 1000) tag = get_tag_by_manifest_id(repo.id, manifest.id) assert tag is not None assert tag.id == new_tag.id assert tag.lifetime_end_ms > expired_tag.lifetime_end_ms