示例#1
0
def test_ociregistry_upload_blob_bad_response_middle(tmp_path, responses,
                                                     monkeypatch):
    """Bad response from the server when pumping bytes."""
    ocireg = OCIRegistry("https://fakereg.com", "test-image")
    base_url = "https://fakereg.com/v2/test-image/"

    # fake the first initial response
    pump_url_1 = base_url + "fakeurl-1"
    responses.add(
        responses.POST,
        base_url + "blobs/uploads/",
        status=202,
        headers={
            "Location": pump_url_1,
            "Range": "0-0"
        },
    )

    # and the intermediate ones, chained, with a crash
    pump_url_2 = base_url + "fakeurl-2"
    responses.add(responses.PATCH,
                  pump_url_1,
                  status=202,
                  headers={"Location": pump_url_2})
    responses.add(responses.PATCH, pump_url_2, status=504)

    # prepare a fake content that will be pushed in 3 parts
    monkeypatch.setattr(registry, "CHUNK_SIZE", 3)
    bytes_source = tmp_path / "testfile"
    bytes_source.write_text("abcdefgh")

    # call!
    msg = r"Wrong status code from server \(expected=202, got=504\).*"
    with pytest.raises(CommandError, match=msg):
        ocireg.upload_blob(bytes_source, 8, "test-digest")
示例#2
0
def test_ociregistry_upload_blob_bad_initial_response(responses):
    """Bad initial response when starting to upload."""
    ocireg = OCIRegistry("https://fakereg.com", "test-image")
    base_url = "https://fakereg.com/v2/test-image/"

    # fake the first initial response with problems
    responses.add(responses.POST, base_url + "blobs/uploads/", status=500)

    # call!
    msg = r"Wrong status code from server \(expected=202, got=500\).*"
    with pytest.raises(CommandError, match=msg):
        ocireg.upload_blob("test-filepath", 8, "test-digest")
示例#3
0
def test_ociregistry_upload_blob_bad_upload_range(responses):
    """Received a broken range info."""
    ocireg = OCIRegistry("https://fakereg.com", "test-image")
    base_url = "https://fakereg.com/v2/test-image/"

    # fake the first initial response with problems
    responses.add(
        responses.POST,
        base_url + "blobs/uploads/",
        status=202,
        headers={
            "Location": "test-next-url",
            "Range": "9-9"
        },
    )

    # call!
    msg = "Server error: bad range received"
    with pytest.raises(CommandError, match=msg):
        ocireg.upload_blob("test-filepath", 8, "test-digest")
示例#4
0
def test_ociregistry_upload_blob_bad_final_digest(tmp_path, responses):
    """Bad digest from server after closing the upload."""
    ocireg = OCIRegistry("https://fakereg.com", "test-image")
    base_url = "https://fakereg.com/v2/test-image/"

    # fake the first initial response
    pump_url_1 = base_url + "fakeurl-1"
    responses.add(
        responses.POST,
        base_url + "blobs/uploads/",
        status=202,
        headers={
            "Location": pump_url_1,
            "Range": "0-0"
        },
    )

    # and the intermediate one
    pump_url_2 = base_url + "fakeurl-2"
    responses.add(responses.PATCH,
                  pump_url_1,
                  status=202,
                  headers={"Location": pump_url_2})

    # finally, the closing url, bad digest
    responses.add(
        responses.PUT,
        base_url + "fakeurl-2&digest=test-digest",
        status=201,
        headers={"Docker-Content-Digest": "somethingelse"},
    )

    # prepare a fake content
    bytes_source = tmp_path / "testfile"
    bytes_source.write_text("abcdefgh")

    # call!
    msg = "Server error: the upload is corrupted"
    with pytest.raises(CommandError, match=msg):
        ocireg.upload_blob(bytes_source, 8, "test-digest")
示例#5
0
def test_ociregistry_upload_blob_bad_upload_range(responses):
    """Received a broken range info."""
    ocireg = OCIRegistry("https://fakereg.com", "test-image")
    base_url = "https://fakereg.com/v2/test-image/"

    # fake the first initial response with problems
    responses.add(
        responses.POST,
        base_url + "blobs/uploads/",
        status=202,
        headers={
            "Location": "test-next-url",
            "Range": "9-9"
        },
    )

    # call!
    with pytest.raises(CraftError) as cm:
        ocireg.upload_blob("test-filepath", 8, "test-digest")
    error = cm.value
    assert str(error) == "Server error: bad range received"
    assert error.details == "Range='9-9'"
示例#6
0
def test_ociregistry_upload_blob_bad_response_closing(tmp_path, responses):
    """Bad response from the server when closing the upload."""
    ocireg = OCIRegistry("https://fakereg.com", "test-image")
    base_url = "https://fakereg.com/v2/test-image/"

    # fake the first initial response
    pump_url_1 = base_url + "fakeurl-1"
    responses.add(
        responses.POST,
        base_url + "blobs/uploads/",
        status=202,
        headers={
            "Location": pump_url_1,
            "Range": "0-0"
        },
    )

    # and the intermediate one
    pump_url_2 = base_url + "fakeurl-2"
    responses.add(responses.PATCH,
                  pump_url_1,
                  status=202,
                  headers={"Location": pump_url_2})

    # finally, the closing url, crashing
    responses.add(responses.PUT,
                  base_url + "fakeurl-2&digest=test-digest",
                  status=502)

    # prepare a fake content
    bytes_source = tmp_path / "testfile"
    bytes_source.write_text("abcdefgh")

    # call!
    msg = r"Wrong status code from server \(expected=201, got=502\).*"
    with pytest.raises(CommandError, match=msg):
        ocireg.upload_blob(bytes_source, 8, "test-digest")
示例#7
0
def test_ociregistry_upload_blob_resumed(tmp_path, caplog, responses):
    """The upload is resumed after server indication to do so."""
    caplog.set_level(logging.DEBUG, logger="charmcraft")
    ocireg = OCIRegistry("https://fakereg.com", "test-image")
    base_url = "https://fakereg.com/v2/test-image/"

    # fake the first initial response, indicating that the store has already the first 5 bytes
    pump_url_1 = base_url + "fakeurl-1"
    responses.add(
        responses.POST,
        base_url + "blobs/uploads/",
        status=202,
        headers={
            "Location": pump_url_1,
            "Range": "0-4"
        },
    )  # has bytes in position 0, 1, 2, 3 & 4

    # and the intermediate one
    pump_url_2 = base_url + "fakeurl-2"
    responses.add(responses.PATCH,
                  pump_url_1,
                  status=202,
                  headers={"Location": pump_url_2})

    # finally, the closing url
    responses.add(
        responses.PUT,
        base_url + "fakeurl-2&digest=test-digest",
        status=201,
        headers={"Docker-Content-Digest": "test-digest"},
    )

    # prepare a fake content
    bytes_source = tmp_path / "testfile"
    bytes_source.write_text("abcdefgh")

    # call!
    ocireg.upload_blob(bytes_source, 8, "test-digest")

    # check all the sent headers
    expected_headers_per_request = [
        {},  # nothing special in the initial one
        {
            "Content-Length": "3",
            "Content-Range": "5-8",
            "Content-Type": OCTET_STREAM_MIMETYPE,
        },
        {
            "Content-Length": "0",
            "Connection": "close"
        },  # closing
    ]
    for idx, expected_headers in enumerate(expected_headers_per_request):
        sent_headers = responses.calls[idx].request.headers
        for key, value in expected_headers.items():
            assert sent_headers.get(key) == value

    expected = [
        "Getting URL to push the blob",
        "Hitting the registry: POST https://fakereg.com/v2/test-image/blobs/uploads/",
        "Got upload URL ok with range 0-4",
        "Closing the upload",
        "Hitting the registry: PUT https://fakereg.com/v2/test-image/fakeurl-2&digest=test-digest",
        "Upload finished OK",
    ]
    assert expected == [rec.message for rec in caplog.records]
示例#8
0
def test_ociregistry_upload_blob_complete(tmp_path, caplog, responses,
                                          monkeypatch):
    """Complete upload of a binary to the registry."""
    caplog.set_level(logging.DEBUG, logger="charmcraft")
    ocireg = OCIRegistry("https://fakereg.com", "test-image")
    base_url = "https://fakereg.com/v2/test-image/"

    # fake the first initial response
    pump_url_1 = base_url + "fakeurl-1"
    responses.add(
        responses.POST,
        base_url + "blobs/uploads/",
        status=202,
        headers={
            "Location": pump_url_1,
            "Range": "0-0"
        },
    )

    # and the intermediate ones, chained
    pump_url_2 = base_url + "fakeurl-2"
    pump_url_3 = base_url + "fakeurl-3"
    pump_url_4 = base_url + "fakeurl-4"
    responses.add(responses.PATCH,
                  pump_url_1,
                  status=202,
                  headers={"Location": pump_url_2})
    responses.add(responses.PATCH,
                  pump_url_2,
                  status=202,
                  headers={"Location": pump_url_3})
    responses.add(responses.PATCH,
                  pump_url_3,
                  status=202,
                  headers={"Location": pump_url_4})

    # finally, the closing url
    responses.add(
        responses.PUT,
        base_url + "fakeurl-4&digest=test-digest",
        status=201,
        headers={"Docker-Content-Digest": "test-digest"},
    )

    # prepare a fake content that will be pushed in 3 parts
    monkeypatch.setattr(registry, "CHUNK_SIZE", 3)
    bytes_source = tmp_path / "testfile"
    bytes_source.write_text("abcdefgh")

    # call!
    ocireg.upload_blob(bytes_source, 8, "test-digest")

    # check all the sent headers
    expected_headers_per_request = [
        {},  # nothing special in the initial one
        {
            "Content-Length": "3",
            "Content-Range": "0-3",
            "Content-Type": OCTET_STREAM_MIMETYPE,
        },
        {
            "Content-Length": "3",
            "Content-Range": "3-6",
            "Content-Type": OCTET_STREAM_MIMETYPE,
        },
        {
            "Content-Length": "2",
            "Content-Range": "6-8",
            "Content-Type": OCTET_STREAM_MIMETYPE,
        },
        {
            "Content-Length": "0",
            "Connection": "close"
        },  # closing
    ]
    for idx, expected_headers in enumerate(expected_headers_per_request):
        sent_headers = responses.calls[idx].request.headers
        for key, value in expected_headers.items():
            assert sent_headers.get(key) == value

    expected = [
        "Getting URL to push the blob",
        "Hitting the registry: POST https://fakereg.com/v2/test-image/blobs/uploads/",
        "Got upload URL ok with range 0-0",
        "Closing the upload",
        "Hitting the registry: PUT https://fakereg.com/v2/test-image/fakeurl-4&digest=test-digest",
        "Upload finished OK",
    ]
    assert expected == [rec.message for rec in caplog.records]