Exemple #1
0
def test_search_pagination(query, authed_username, initialized_db):
    # Create some public repos.
    repo1 = create_repository('devtable',
                              'somenewrepo',
                              None,
                              repo_kind='image',
                              visibility='public')
    repo2 = create_repository('devtable',
                              'somenewrepo2',
                              None,
                              repo_kind='image',
                              visibility='public')
    repo3 = create_repository('devtable',
                              'somenewrepo3',
                              None,
                              repo_kind='image',
                              visibility='public')

    repositories = get_filtered_matching_repositories(
        query, filter_username=authed_username)
    assert len(repositories) > 3

    next_repos = get_filtered_matching_repositories(
        query, filter_username=authed_username, offset=1)
    assert repositories[0].id != next_repos[0].id
    assert repositories[1].id == next_repos[0].id
Exemple #2
0
def test_delete_namespace_via_marker(initialized_db):
    def create_transaction(db):
        return db.transaction()

    # Create a user and then mark it for deletion.
    user = create_user_noverify("foobar",
                                "*****@*****.**",
                                email_required=False)

    # Add some repositories.
    create_repository("foobar", "somerepo", user)
    create_repository("foobar", "anotherrepo", user)

    # Mark the user for deletion.
    queue = WorkQueue("testgcnamespace", create_transaction)
    marker_id = mark_namespace_for_deletion(user, [], queue)

    # Delete the user.
    with check_transitive_modifications():
        delete_namespace_via_marker(marker_id, [])

    # Ensure the user was actually deleted.
    with pytest.raises(User.DoesNotExist):
        User.get(id=user.id)

    with pytest.raises(DeletedNamespace.DoesNotExist):
        DeletedNamespace.get(id=marker_id)
Exemple #3
0
def test_duplicate_repository_different_kinds(initialized_db):
    # Create an image repo.
    assert create_repository("devtable",
                             "somenewrepo",
                             None,
                             repo_kind="image")

    # Try to create an app repo with the same name, which should fail.
    assert not create_repository(
        "devtable", "somenewrepo", None, repo_kind="application")
Exemple #4
0
def test_duplicate_repository_different_kinds(initialized_db):
    # Create an image repo.
    create_repository('devtable', 'somenewrepo', None, repo_kind='image')

    # Try to create an app repo with the same name, which should fail.
    with pytest.raises(IntegrityError):
        create_repository('devtable',
                          'somenewrepo',
                          None,
                          repo_kind='application')
Exemple #5
0
def test_lookup_manifest_child_tag(initialized_db):
    repository = create_repository("devtable", "newrepo", None)
    manifest, manifest_impl = create_manifest_for_testing(repository)

    # Mark the hidden tag as dead.
    hidden_tag = Tag.get(manifest=manifest, hidden=True)
    hidden_tag.lifetime_end_ms = hidden_tag.lifetime_start_ms
    hidden_tag.save()

    # Ensure the manifest cannot currently be looked up, as it is not pointed to by an alive tag.
    assert lookup_manifest(repository, manifest.digest) is None
    assert lookup_manifest(repository, manifest.digest,
                           allow_dead=True) is not None

    # Populate a manifest list.
    list_builder = DockerSchema2ManifestListBuilder()
    list_builder.add_manifest(manifest_impl, "amd64", "linux")
    manifest_list = list_builder.build()

    # Write the manifest list, which should also write the manifests themselves.
    created_tuple = get_or_create_manifest(repository, manifest_list, storage)
    assert created_tuple is not None

    # Since the manifests are not yet referenced by a tag, they cannot be found.
    assert lookup_manifest(repository, manifest.digest) is None
    assert lookup_manifest(repository, manifest_list.digest) is None

    # Unless we ask for "dead" manifests.
    assert lookup_manifest(repository, manifest.digest,
                           allow_dead=True) is not None
    assert lookup_manifest(repository, manifest_list.digest,
                           allow_dead=True) is not None
Exemple #6
0
def test_change_tag_expiration(expiration_offset, expected_offset, initialized_db):
  repository = create_repository('devtable', 'somenewrepo', None)
  image1 = find_create_or_link_image('foobarimage1', repository, None, {}, 'local_us')

  manifest = Manifest.get()
  footag = create_or_update_tag_for_repo(repository, 'foo', image1.docker_image_id,
                                         oci_manifest=manifest)

  expiration_date = None
  if expiration_offset is not None:
    expiration_date = datetime.utcnow() + convert_to_timedelta(expiration_offset)

  assert change_tag_expiration(footag, expiration_date)

  # Lookup the tag again.
  footag_updated = get_active_tag('devtable', 'somenewrepo', 'foo')
  oci_tag = _get_oci_tag(footag_updated)

  if expected_offset is None:
    assert footag_updated.lifetime_end_ts is None
    assert oci_tag.lifetime_end_ms is None
  else:
    start_date = datetime.utcfromtimestamp(footag_updated.lifetime_start_ts)
    end_date = datetime.utcfromtimestamp(footag_updated.lifetime_end_ts)
    expected_end_date = start_date + convert_to_timedelta(expected_offset)
    assert (expected_end_date - end_date).total_seconds() < 5 # variance in test

    assert oci_tag.lifetime_end_ms == (footag_updated.lifetime_end_ts * 1000)
Exemple #7
0
def test_create_reversion_tag(initialized_db):
  repository = create_repository('devtable', 'somenewrepo', None)
  manifest = Manifest.get()
  image1 = find_create_or_link_image('foobarimage1', repository, None, {}, 'local_us')

  footag = create_or_update_tag_for_repo(repository, 'foo', image1.docker_image_id,
                                         oci_manifest=manifest, reversion=True)
  assert footag.reversion

  oci_tag = _get_oci_tag(footag)
  assert oci_tag.name == footag.name
  assert not oci_tag.hidden
  assert oci_tag.reversion == footag.reversion
    def lookup_repository(self,
                          namespace_name,
                          repo_name,
                          kind_filter=None,
                          raise_on_error=False,
                          manifest_ref=None):
        """
        Looks up and returns a reference to the repository with the given namespace and name, or
        None if none.

        If the repository does not exist and the given manifest_ref exists upstream,
        creates the repository.
        """
        repo = get_repository(namespace_name, repo_name)
        exists = repo is not None
        if exists:
            return RepositoryReference.for_repo_obj(
                repo,
                namespace_name,
                repo_name,
                repo.namespace_user.stripe_id is None if repo else None,
                state=repo.state if repo is not None else None,
            )

        # we only create a repository for images that exist upstream, and if
        # we're not given a manifest reference then we can't check whether the
        # image exists upstream or not, so we refuse to create the repo.
        if manifest_ref is None:
            return None

        try:
            self._proxy.manifest_exists(manifest_ref, ACCEPTED_MEDIA_TYPES)
        except UpstreamRegistryError as e:
            if raise_on_error:
                raise RepositoryDoesNotExist(str(e))
            return None

        repo = create_repository(namespace_name, repo_name, self._user)
        return RepositoryReference.for_repo_obj(
            repo,
            namespace_name,
            repo_name,
            repo.namespace_user.stripe_id is None if repo else None,
            state=repo.state if repo is not None else None,
        )
def test_update_repository_score(bucket_sums, expected_score, initialized_db):
    # Create a new repository.
    repo = create_repository('devtable',
                             'somenewrepo',
                             None,
                             repo_kind='image')

    # Delete the RAC created in create_repository.
    RepositoryActionCount.delete().where(
        RepositoryActionCount.repository == repo).execute()

    # Add RAC rows for each of the buckets.
    for index, bucket in enumerate(SEARCH_BUCKETS):
        for day in range(0, bucket.days):
            RepositoryActionCount.create(
                repository=repo,
                count=(bucket_sums[index] / bucket.days * 1.0),
                date=date.today() - bucket.delta + timedelta(days=day))

    assert update_repository_score(repo)
    assert RepositorySearchScore.get(repository=repo).score == expected_score
Exemple #10
0
def test_create_manifest_cannot_load_config_blob(initialized_db):
    repository = create_repository("devtable", "newrepo", None)

    layer_json = json.dumps({
        "config": {},
        "rootfs": {
            "type": "layers",
            "diff_ids": []
        },
        "history": [
            {
                "created": "2018-04-03T18:37:09.284840891Z",
                "created_by": "do something",
            },
        ],
    })

    # Add a blob containing the config.
    _, config_digest = _populate_blob(layer_json)

    # Add a blob of random data.
    random_data = "hello world"
    _, random_digest = _populate_blob(random_data)

    remote_digest = sha256_digest(b"something")

    builder = DockerSchema2ManifestBuilder()
    builder.set_config_digest(config_digest, len(layer_json.encode("utf-8")))
    builder.add_layer(random_digest, len(random_data.encode("utf-8")))
    manifest = builder.build()

    broken_retriever = BrokenRetriever()

    # Write the manifest.
    with pytest.raises(CreateManifestException):
        get_or_create_manifest(repository,
                               manifest,
                               storage,
                               retriever=broken_retriever,
                               raise_on_error=True)
Exemple #11
0
def test_is_empty(initialized_db):
    create_repository("devtable", "somenewrepo", None, repo_kind="image")

    assert is_empty("devtable", "somenewrepo")
    assert not is_empty("devtable", "simple")
Exemple #12
0
def test_get_or_create_manifest_with_remote_layers(initialized_db):
    repository = create_repository("devtable", "newrepo", None)

    layer_json = json.dumps({
        "config": {},
        "rootfs": {
            "type": "layers",
            "diff_ids": []
        },
        "history": [
            {
                "created": "2018-04-03T18:37:09.284840891Z",
                "created_by": "do something",
            },
            {
                "created": "2018-04-03T18:37:09.284840891Z",
                "created_by": "do something",
            },
        ],
    })

    # Add a blob containing the config.
    _, config_digest = _populate_blob(layer_json)

    # Add a blob of random data.
    random_data = "hello world"
    _, random_digest = _populate_blob(random_data)

    remote_digest = sha256_digest(b"something")

    builder = DockerSchema2ManifestBuilder()
    builder.set_config_digest(config_digest, len(layer_json.encode("utf-8")))
    builder.add_layer(remote_digest, 1234, urls=["http://hello/world"])
    builder.add_layer(random_digest, len(random_data.encode("utf-8")))
    manifest = builder.build()

    assert remote_digest in manifest.blob_digests
    assert remote_digest not in manifest.local_blob_digests

    assert manifest.has_remote_layer
    assert not manifest.has_legacy_image
    assert manifest.get_schema1_manifest("foo", "bar", "baz", None) is None

    # Write the manifest.
    created_tuple = get_or_create_manifest(repository, manifest, storage)
    assert created_tuple is not None

    created_manifest = created_tuple.manifest
    assert created_manifest
    assert created_manifest.media_type.name == manifest.media_type
    assert created_manifest.digest == manifest.digest
    assert created_manifest.config_media_type == manifest.config_media_type
    assert created_manifest.layers_compressed_size == manifest.layers_compressed_size

    # Verify the legacy image.
    legacy_image = get_legacy_image_for_manifest(created_manifest)
    assert legacy_image is None

    # Verify the linked blobs.
    blob_digests = {
        mb.blob.content_checksum
        for mb in ManifestBlob.select().where(
            ManifestBlob.manifest == created_manifest)
    }

    assert random_digest in blob_digests
    assert config_digest in blob_digests
    assert remote_digest not in blob_digests
Exemple #13
0
def test_is_empty(initialized_db):
    create_repository('devtable', 'somenewrepo', None, repo_kind='image')

    assert is_empty('devtable', 'somenewrepo')
    assert not is_empty('devtable', 'simple')
 def _create_repo(orgname, reponame, user):
     r = create_repository(orgname, reponame, user)
     assert r is not None
     repo_ref = registry_model.lookup_repository(orgname, reponame)
     assert repo_ref is not None
     return repo_ref
Exemple #15
0
def test_get_or_create_manifest(schema_version, initialized_db):
    repository = create_repository("devtable", "newrepo", None)

    expected_labels = {
        "Foo": "Bar",
        "Baz": "Meh",
    }

    layer_json = json.dumps({
        "id":
        "somelegacyid",
        "config": {
            "Labels": expected_labels,
        },
        "rootfs": {
            "type": "layers",
            "diff_ids": []
        },
        "history": [
            {
                "created": "2018-04-03T18:37:09.284840891Z",
                "created_by": "do something",
            },
        ],
    })

    # Create a legacy image.
    find_create_or_link_image("somelegacyid", repository, "devtable", {},
                              "local_us")

    # Add a blob containing the config.
    _, config_digest = _populate_blob(layer_json)

    # Add a blob of random data.
    random_data = "hello world"
    _, random_digest = _populate_blob(random_data)

    # Build the manifest.
    if schema_version == 1:
        builder = DockerSchema1ManifestBuilder("devtable", "simple",
                                               "anothertag")
        builder.add_layer(random_digest, layer_json)
        sample_manifest_instance = builder.build(docker_v2_signing_key)
    elif schema_version == 2:
        builder = DockerSchema2ManifestBuilder()
        builder.set_config_digest(config_digest,
                                  len(layer_json.encode("utf-8")))
        builder.add_layer(random_digest, len(random_data.encode("utf-8")))
        sample_manifest_instance = builder.build()

    assert sample_manifest_instance.layers_compressed_size is not None

    # Create a new manifest.
    created_manifest = get_or_create_manifest(repository,
                                              sample_manifest_instance,
                                              storage)
    created = created_manifest.manifest
    newly_created = created_manifest.newly_created

    assert newly_created
    assert created is not None
    assert created.media_type.name == sample_manifest_instance.media_type
    assert created.digest == sample_manifest_instance.digest
    assert created.manifest_bytes == sample_manifest_instance.bytes.as_encoded_str(
    )
    assert created_manifest.labels_to_apply == expected_labels
    assert created.config_media_type == sample_manifest_instance.config_media_type
    assert created.layers_compressed_size == sample_manifest_instance.layers_compressed_size

    # Lookup the manifest and verify.
    found = lookup_manifest(repository, created.digest, allow_dead=True)
    assert found.digest == created.digest
    assert found.config_media_type == created.config_media_type
    assert found.layers_compressed_size == created.layers_compressed_size

    # Verify it has a temporary tag pointing to it.
    assert Tag.get(manifest=created, hidden=True).lifetime_end_ms

    # Verify the linked blobs.
    blob_digests = [
        mb.blob.content_checksum
        for mb in ManifestBlob.select().where(ManifestBlob.manifest == created)
    ]

    assert random_digest in blob_digests
    if schema_version == 2:
        assert config_digest in blob_digests

    # Retrieve it again and ensure it is the same manifest.
    created_manifest2 = get_or_create_manifest(repository,
                                               sample_manifest_instance,
                                               storage)
    created2 = created_manifest2.manifest
    newly_created2 = created_manifest2.newly_created

    assert not newly_created2
    assert created2 == created

    # Ensure it again has a temporary tag.
    assert Tag.get(manifest=created2, hidden=True).lifetime_end_ms

    # Ensure the labels were added.
    labels = list(list_manifest_labels(created))
    assert len(labels) == 2

    labels_dict = {label.key: label.value for label in labels}
    assert labels_dict == expected_labels
Exemple #16
0
def test_get_or_create_manifest_list_duplicate_child_manifest(initialized_db):
    repository = create_repository("devtable", "newrepo", None)

    expected_labels = {
        "Foo": "Bar",
        "Baz": "Meh",
    }

    layer_json = json.dumps({
        "id":
        "somelegacyid",
        "config": {
            "Labels": expected_labels,
        },
        "rootfs": {
            "type": "layers",
            "diff_ids": []
        },
        "history": [
            {
                "created": "2018-04-03T18:37:09.284840891Z",
                "created_by": "do something",
            },
        ],
    })

    # Create a legacy image.
    find_create_or_link_image("somelegacyid", repository, "devtable", {},
                              "local_us")

    # Add a blob containing the config.
    _, config_digest = _populate_blob(layer_json)

    # Add a blob of random data.
    random_data = "hello world"
    _, random_digest = _populate_blob(random_data)

    # Build the manifest.
    v2_builder = DockerSchema2ManifestBuilder()
    v2_builder.set_config_digest(config_digest,
                                 len(layer_json.encode("utf-8")))
    v2_builder.add_layer(random_digest, len(random_data.encode("utf-8")))
    v2_manifest = v2_builder.build()

    # Write the manifest.
    v2_created = get_or_create_manifest(repository, v2_manifest, storage)
    assert v2_created
    assert v2_created.manifest.digest == v2_manifest.digest

    # Build the manifest list, with the child manifest repeated.
    list_builder = DockerSchema2ManifestListBuilder()
    list_builder.add_manifest(v2_manifest, "amd64", "linux")
    list_builder.add_manifest(v2_manifest, "amd32", "linux")
    manifest_list = list_builder.build()

    # Write the manifest list, which should also write the manifests themselves.
    created_tuple = get_or_create_manifest(repository, manifest_list, storage)
    assert created_tuple is not None

    created_list = created_tuple.manifest
    assert created_list
    assert created_list.media_type.name == manifest_list.media_type
    assert created_list.digest == manifest_list.digest

    # Ensure the child manifest links exist.
    child_manifests = {
        cm.child_manifest.digest: cm.child_manifest
        for cm in ManifestChild.select().where(
            ManifestChild.manifest == created_list)
    }
    assert len(child_manifests) == 1
    assert v2_manifest.digest in child_manifests
    assert child_manifests[
        v2_manifest.digest].media_type.name == v2_manifest.media_type

    # Try to create again and ensure we get back the same manifest list.
    created2_tuple = get_or_create_manifest(repository, manifest_list, storage)
    assert created2_tuple is not None
    assert created2_tuple.manifest == created_list
Exemple #17
0
def test_get_or_create_manifest_list(initialized_db):
    repository = create_repository('devtable', 'newrepo', None)

    expected_labels = {
        'Foo': 'Bar',
        'Baz': 'Meh',
    }

    layer_json = json.dumps({
        'id':
        'somelegacyid',
        'config': {
            'Labels': expected_labels,
        },
        "rootfs": {
            "type": "layers",
            "diff_ids": []
        },
        "history": [
            {
                "created": "2018-04-03T18:37:09.284840891Z",
                "created_by": "do something",
            },
        ],
    })

    # Create a legacy image.
    find_create_or_link_image('somelegacyid', repository, 'devtable', {},
                              'local_us')

    # Add a blob containing the config.
    _, config_digest = _populate_blob(layer_json)

    # Add a blob of random data.
    random_data = 'hello world'
    _, random_digest = _populate_blob(random_data)

    # Build the manifests.
    v1_builder = DockerSchema1ManifestBuilder('devtable', 'simple',
                                              'anothertag')
    v1_builder.add_layer(random_digest, layer_json)
    v1_manifest = v1_builder.build(docker_v2_signing_key).unsigned()

    v2_builder = DockerSchema2ManifestBuilder()
    v2_builder.set_config_digest(config_digest, len(layer_json))
    v2_builder.add_layer(random_digest, len(random_data))
    v2_manifest = v2_builder.build()

    # Write the manifests.
    v1_created = get_or_create_manifest(repository, v1_manifest, storage)
    assert v1_created
    assert v1_created.manifest.digest == v1_manifest.digest

    v2_created = get_or_create_manifest(repository, v2_manifest, storage)
    assert v2_created
    assert v2_created.manifest.digest == v2_manifest.digest

    # Build the manifest list.
    list_builder = DockerSchema2ManifestListBuilder()
    list_builder.add_manifest(v1_manifest, 'amd64', 'linux')
    list_builder.add_manifest(v2_manifest, 'amd32', 'linux')
    manifest_list = list_builder.build()

    # Write the manifest list, which should also write the manifests themselves.
    created_tuple = get_or_create_manifest(repository, manifest_list, storage)
    assert created_tuple is not None

    created_list = created_tuple.manifest
    assert created_list
    assert created_list.media_type.name == manifest_list.media_type
    assert created_list.digest == manifest_list.digest

    # Ensure the child manifest links exist.
    child_manifests = {
        cm.child_manifest.digest: cm.child_manifest
        for cm in ManifestChild.select().where(
            ManifestChild.manifest == created_list)
    }
    assert len(child_manifests) == 2
    assert v1_manifest.digest in child_manifests
    assert v2_manifest.digest in child_manifests

    assert child_manifests[
        v1_manifest.digest].media_type.name == v1_manifest.media_type
    assert child_manifests[
        v2_manifest.digest].media_type.name == v2_manifest.media_type
Exemple #18
0
def test_list_active_tags(initialized_db):
  # Create a new repository.
  repository = create_repository('devtable', 'somenewrepo', None)
  manifest = Manifest.get()

  # Create some images.
  image1 = find_create_or_link_image('foobarimage1', repository, None, {}, 'local_us')
  image2 = find_create_or_link_image('foobarimage2', repository, None, {}, 'local_us')

  # Make sure its tags list is empty.
  assert_tags(repository)

  # Add some new tags.
  footag = create_or_update_tag_for_repo(repository, 'foo', image1.docker_image_id,
                                         oci_manifest=manifest)
  bartag = create_or_update_tag_for_repo(repository, 'bar', image1.docker_image_id,
                                         oci_manifest=manifest)

  # Since timestamps are stored on a second-granularity, we need to make the tags "start"
  # before "now", so when we recreate them below, they don't conflict.
  footag.lifetime_start_ts -= 5
  footag.save()

  bartag.lifetime_start_ts -= 5
  bartag.save()

  footag_oci = _get_oci_tag(footag)
  footag_oci.lifetime_start_ms -= 5000
  footag_oci.save()

  bartag_oci = _get_oci_tag(bartag)
  bartag_oci.lifetime_start_ms -= 5000
  bartag_oci.save()

  # Make sure they are returned.
  assert_tags(repository, 'foo', 'bar')

  # Set the expirations to be explicitly empty.
  set_tag_end_ts(footag, None)
  set_tag_end_ts(bartag, None)

  # Make sure they are returned.
  assert_tags(repository, 'foo', 'bar')

  # Mark as a tag as expiring in the far future, and make sure it is still returned.
  set_tag_end_ts(footag, footag.lifetime_start_ts + 10000000)

  # Make sure they are returned.
  assert_tags(repository, 'foo', 'bar')

  # Delete a tag and make sure it isn't returned.
  footag = delete_tag('devtable', 'somenewrepo', 'foo')
  set_tag_end_ts(footag, footag.lifetime_end_ts - 4)

  assert_tags(repository, 'bar')

  # Add a new foo again.
  footag = create_or_update_tag_for_repo(repository, 'foo', image1.docker_image_id,
                                         oci_manifest=manifest)
  footag.lifetime_start_ts -= 3
  footag.save()

  footag_oci = _get_oci_tag(footag)
  footag_oci.lifetime_start_ms -= 3000
  footag_oci.save()

  assert_tags(repository, 'foo', 'bar')

  # Mark as a tag as expiring in the far future, and make sure it is still returned.
  set_tag_end_ts(footag, footag.lifetime_start_ts + 10000000)

  # Make sure they are returned.
  assert_tags(repository, 'foo', 'bar')

  # "Move" foo by updating it and make sure we don't get duplicates.
  create_or_update_tag_for_repo(repository, 'foo', image2.docker_image_id, oci_manifest=manifest)
  assert_tags(repository, 'foo', 'bar')
Exemple #19
0
def test_retriever(initialized_db):
    repository = create_repository("devtable", "newrepo", None)

    layer_json = json.dumps({
        "config": {},
        "rootfs": {
            "type": "layers",
            "diff_ids": []
        },
        "history": [
            {
                "created": "2018-04-03T18:37:09.284840891Z",
                "created_by": "do something",
            },
            {
                "created": "2018-04-03T18:37:09.284840891Z",
                "created_by": "do something",
            },
        ],
    })

    # Add a blob containing the config.
    _, config_digest = _populate_blob(layer_json)

    # Add a blob of random data.
    random_data = "hello world"
    _, random_digest = _populate_blob(random_data)

    # Add another blob of random data.
    other_random_data = "hi place"
    _, other_random_digest = _populate_blob(other_random_data)

    remote_digest = sha256_digest(b"something")

    builder = DockerSchema2ManifestBuilder()
    builder.set_config_digest(config_digest, len(layer_json.encode("utf-8")))
    builder.add_layer(other_random_digest,
                      len(other_random_data.encode("utf-8")))
    builder.add_layer(random_digest, len(random_data.encode("utf-8")))
    manifest = builder.build()

    assert config_digest in manifest.blob_digests
    assert random_digest in manifest.blob_digests
    assert other_random_digest in manifest.blob_digests

    assert config_digest in manifest.local_blob_digests
    assert random_digest in manifest.local_blob_digests
    assert other_random_digest in manifest.local_blob_digests

    # Write the manifest.
    created_tuple = get_or_create_manifest(repository, manifest, storage)
    assert created_tuple is not None

    created_manifest = created_tuple.manifest
    assert created_manifest
    assert created_manifest.media_type.name == manifest.media_type
    assert created_manifest.digest == manifest.digest

    # Verify the linked blobs.
    blob_digests = {
        mb.blob.content_checksum
        for mb in ManifestBlob.select().where(
            ManifestBlob.manifest == created_manifest)
    }

    assert random_digest in blob_digests
    assert other_random_digest in blob_digests
    assert config_digest in blob_digests

    # Delete any Image rows linking to the blobs from temp tags.
    for blob_digest in blob_digests:
        storage_row = ImageStorage.get(content_checksum=blob_digest)
        for image in list(Image.select().where(Image.storage == storage_row)):
            all_temp = all([
                rt.hidden for rt in RepositoryTag.select().where(
                    RepositoryTag.image == image)
            ])
            if all_temp:
                RepositoryTag.delete().where(
                    RepositoryTag.image == image).execute()
                image.delete_instance(recursive=True)

    # Verify the blobs in the retriever.
    retriever = RepositoryContentRetriever(repository, storage)
    assert (retriever.get_manifest_bytes_with_digest(
        created_manifest.digest) == manifest.bytes.as_encoded_str())

    for blob_digest in blob_digests:
        assert retriever.get_blob_bytes_with_digest(blob_digest) is not None
Exemple #20
0
def test_get_most_recent_tag_empty_repo(initialized_db):
    empty_repo = create_repository("devtable", "empty", None)

    with assert_query_count(1):
        assert get_most_recent_tag(empty_repo) is None
Exemple #21
0
def test_get_or_create_manifest(schema_version, initialized_db):
    repository = create_repository('devtable', 'newrepo', None)

    expected_labels = {
        'Foo': 'Bar',
        'Baz': 'Meh',
    }

    layer_json = json.dumps({
        'id':
        'somelegacyid',
        'config': {
            'Labels': expected_labels,
        },
        "rootfs": {
            "type": "layers",
            "diff_ids": []
        },
        "history": [
            {
                "created": "2018-04-03T18:37:09.284840891Z",
                "created_by": "do something",
            },
        ],
    })

    # Create a legacy image.
    find_create_or_link_image('somelegacyid', repository, 'devtable', {},
                              'local_us')

    # Add a blob containing the config.
    _, config_digest = _populate_blob(layer_json)

    # Add a blob of random data.
    random_data = 'hello world'
    _, random_digest = _populate_blob(random_data)

    # Build the manifest.
    if schema_version == 1:
        builder = DockerSchema1ManifestBuilder('devtable', 'simple',
                                               'anothertag')
        builder.add_layer(random_digest, layer_json)
        sample_manifest_instance = builder.build(docker_v2_signing_key)
    elif schema_version == 2:
        builder = DockerSchema2ManifestBuilder()
        builder.set_config_digest(config_digest, len(layer_json))
        builder.add_layer(random_digest, len(random_data))
        sample_manifest_instance = builder.build()

    # Create a new manifest.
    created_manifest = get_or_create_manifest(repository,
                                              sample_manifest_instance,
                                              storage)
    created = created_manifest.manifest
    newly_created = created_manifest.newly_created

    assert newly_created
    assert created is not None
    assert created.media_type.name == sample_manifest_instance.media_type
    assert created.digest == sample_manifest_instance.digest
    assert created.manifest_bytes == sample_manifest_instance.bytes.as_encoded_str(
    )
    assert created_manifest.labels_to_apply == expected_labels

    # Verify it has a temporary tag pointing to it.
    assert Tag.get(manifest=created, hidden=True).lifetime_end_ms

    # Verify the legacy image.
    legacy_image = get_legacy_image_for_manifest(created)
    assert legacy_image is not None
    assert legacy_image.storage.content_checksum == random_digest

    # Verify the linked blobs.
    blob_digests = [
        mb.blob.content_checksum
        for mb in ManifestBlob.select().where(ManifestBlob.manifest == created)
    ]

    assert random_digest in blob_digests
    if schema_version == 2:
        assert config_digest in blob_digests

    # Retrieve it again and ensure it is the same manifest.
    created_manifest2 = get_or_create_manifest(repository,
                                               sample_manifest_instance,
                                               storage)
    created2 = created_manifest2.manifest
    newly_created2 = created_manifest2.newly_created

    assert not newly_created2
    assert created2 == created

    # Ensure it again has a temporary tag.
    assert Tag.get(manifest=created2, hidden=True).lifetime_end_ms

    # Ensure the labels were added.
    labels = list(list_manifest_labels(created))
    assert len(labels) == 2

    labels_dict = {label.key: label.value for label in labels}
    assert labels_dict == expected_labels