Search in sources :

Example 26 with Container

use of com.github.ambry.account.Container in project ambry by linkedin.

the class PostBlobHandlerTest method stitchedUploadTest.

/**
 * Test flows related to the {@link Operations#STITCH} operation.
 * @throws Exception
 */
@Test
public void stitchedUploadTest() throws Exception {
    idConverterFactory.translation = CONVERTED_ID;
    String uploadSession = UUID.randomUUID().toString();
    long creationTimeMs = System.currentTimeMillis();
    time.setCurrentMilliseconds(creationTimeMs);
    String[] prefixToTest = new String[] { "/" + CLUSTER_NAME, "" };
    for (String prefix : prefixToTest) {
        // success cases
        // multiple chunks
        List<ChunkInfo> chunksToStitch = uploadChunksViaRouter(creationTimeMs, REF_CONTAINER, 45, 10, 200, 19, 0, 50);
        List<String> signedChunkIds = chunksToStitch.stream().map(chunkInfo -> prefix + getSignedId(chunkInfo, uploadSession)).collect(Collectors.toList());
        stitchBlobAndVerify(getStitchRequestBody(signedChunkIds), chunksToStitch, null);
        // one chunk
        chunksToStitch = uploadChunksViaRouter(creationTimeMs, REF_CONTAINER, 45);
        signedChunkIds = chunksToStitch.stream().map(chunkInfo -> prefix + getSignedId(chunkInfo, uploadSession)).collect(Collectors.toList());
        stitchBlobAndVerify(getStitchRequestBody(signedChunkIds), chunksToStitch, null);
        // failure cases
        // invalid json input
        stitchBlobAndVerify("badjsonbadjson".getBytes(StandardCharsets.UTF_8), null, restServiceExceptionChecker(RestServiceErrorCode.BadRequest));
        // no chunk ids in request
        stitchBlobAndVerify(getStitchRequestBody(Collections.emptyList()), null, restServiceExceptionChecker(RestServiceErrorCode.MissingArgs));
        stitchBlobAndVerify(new JSONObject().toString().getBytes(StandardCharsets.UTF_8), null, restServiceExceptionChecker(RestServiceErrorCode.MissingArgs));
        // differing session IDs
        signedChunkIds = uploadChunksViaRouter(creationTimeMs, REF_CONTAINER, 45, 22).stream().map(chunkInfo -> prefix + getSignedId(chunkInfo, UUID.randomUUID().toString())).collect(Collectors.toList());
        stitchBlobAndVerify(getStitchRequestBody(signedChunkIds), null, restServiceExceptionChecker(RestServiceErrorCode.BadRequest));
        // differing containers
        signedChunkIds = Stream.concat(uploadChunksViaRouter(creationTimeMs, REF_CONTAINER, 50, 50).stream(), uploadChunksViaRouter(creationTimeMs, REF_CONTAINER_WITH_TTL_REQUIRED, 50).stream()).map(chunkInfo -> prefix + getSignedId(chunkInfo, uploadSession)).collect(Collectors.toList());
        stitchBlobAndVerify(getStitchRequestBody(signedChunkIds), null, restServiceExceptionChecker(RestServiceErrorCode.BadRequest));
        // differing accounts
        Container altAccountContainer = ACCOUNT_SERVICE.createAndAddRandomAccount().getContainerById(Container.DEFAULT_PRIVATE_CONTAINER_ID);
        signedChunkIds = Stream.concat(uploadChunksViaRouter(creationTimeMs, REF_CONTAINER, 50, 50).stream(), uploadChunksViaRouter(creationTimeMs, altAccountContainer, 50).stream()).map(chunkInfo -> prefix + getSignedId(chunkInfo, uploadSession)).collect(Collectors.toList());
        stitchBlobAndVerify(getStitchRequestBody(signedChunkIds), null, restServiceExceptionChecker(RestServiceErrorCode.BadRequest));
        // invalid blob ID
        stitchBlobAndVerify(getStitchRequestBody(Collections.singletonList(getSignedId(new ChunkInfo("abcd", 200, -1), uploadSession))), null, restServiceExceptionChecker(RestServiceErrorCode.BadRequest));
        // unsigned ID
        stitchBlobAndVerify(getStitchRequestBody(Collections.singletonList("/notASignedId")), null, restServiceExceptionChecker(RestServiceErrorCode.BadRequest));
    }
}
Also used : Arrays(java.util.Arrays) FrontendConfig(com.github.ambry.config.FrontendConfig) BlobProperties(com.github.ambry.messageformat.BlobProperties) URISyntaxException(java.net.URISyntaxException) FutureResult(com.github.ambry.router.FutureResult) ByteBufferReadableStreamChannel(com.github.ambry.commons.ByteBufferReadableStreamChannel) ContainerBuilder(com.github.ambry.account.ContainerBuilder) ByteBuffer(java.nio.ByteBuffer) ThrowingConsumer(com.github.ambry.utils.ThrowingConsumer) JSONObject(org.json.JSONObject) TestUtils(com.github.ambry.utils.TestUtils) Map(java.util.Map) ChunkInfo(com.github.ambry.router.ChunkInfo) RouterErrorCode(com.github.ambry.router.RouterErrorCode) Container(com.github.ambry.account.Container) RestResponseChannel(com.github.ambry.rest.RestResponseChannel) RestServiceErrorCode(com.github.ambry.rest.RestServiceErrorCode) Utils(com.github.ambry.utils.Utils) UUID(java.util.UUID) AccountBuilder(com.github.ambry.account.AccountBuilder) Collectors(java.util.stream.Collectors) StandardCharsets(java.nio.charset.StandardCharsets) List(java.util.List) RestServiceException(com.github.ambry.rest.RestServiceException) Stream(java.util.stream.Stream) MockRestResponseChannel(com.github.ambry.rest.MockRestResponseChannel) MockTime(com.github.ambry.utils.MockTime) QuotaTestUtils(com.github.ambry.quota.QuotaTestUtils) Account(com.github.ambry.account.Account) RestUtils(com.github.ambry.rest.RestUtils) UnsupportedEncodingException(java.io.UnsupportedEncodingException) InMemAccountService(com.github.ambry.account.InMemAccountService) InMemoryRouter(com.github.ambry.router.InMemoryRouter) ByteArrayOutputStream(java.io.ByteArrayOutputStream) AccountService(com.github.ambry.account.AccountService) HashMap(java.util.HashMap) QuotaManager(com.github.ambry.quota.QuotaManager) ArrayList(java.util.ArrayList) QuotaConfig(com.github.ambry.config.QuotaConfig) RequestPath(com.github.ambry.rest.RequestPath) QuotaMode(com.github.ambry.quota.QuotaMode) LinkedList(java.util.LinkedList) MetricRegistry(com.codahale.metrics.MetricRegistry) Properties(java.util.Properties) RestMethod(com.github.ambry.rest.RestMethod) VerifiableProperties(com.github.ambry.config.VerifiableProperties) ClusterMap(com.github.ambry.clustermap.ClusterMap) Test(org.junit.Test) RouterException(com.github.ambry.router.RouterException) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) AmbryQuotaManager(com.github.ambry.quota.AmbryQuotaManager) Mockito(org.mockito.Mockito) QuotaMetrics(com.github.ambry.quota.QuotaMetrics) PutBlobOptionsBuilder(com.github.ambry.router.PutBlobOptionsBuilder) SimpleQuotaRecommendationMergePolicy(com.github.ambry.quota.SimpleQuotaRecommendationMergePolicy) Assert(org.junit.Assert) RestRequest(com.github.ambry.rest.RestRequest) Collections(java.util.Collections) MockClusterMap(com.github.ambry.clustermap.MockClusterMap) Container(com.github.ambry.account.Container) ChunkInfo(com.github.ambry.router.ChunkInfo) JSONObject(org.json.JSONObject) Test(org.junit.Test)

Example 27 with Container

use of com.github.ambry.account.Container in project ambry by linkedin.

the class FrontendTestUrlSigningServiceFactory method containerMetricsExclusionTest.

/**
 * Tests that container metrics are not generated when the target account is in the excluded list.
 * @throws Exception
 */
@Test
public void containerMetricsExclusionTest() throws Exception {
    short excludedAccountId = Utils.getRandomShort(TestUtils.RANDOM);
    short containerId = 2;
    String containerName = "tenant1";
    Container container = new ContainerBuilder(containerId, containerName, Container.ContainerStatus.ACTIVE, "test", excludedAccountId).build();
    Account excludedAccount = new AccountBuilder(excludedAccountId, excludedAccountName, Account.AccountStatus.ACTIVE).addOrUpdateContainer(container).build();
    accountService.updateAccounts(Collections.singletonList(excludedAccount));
    postBlobAndVerifyWithAccountAndContainer(excludedAccountName, containerName, "serviceId", !container.isCacheable(), excludedAccount, container, null);
}
Also used : Account(com.github.ambry.account.Account) Container(com.github.ambry.account.Container) ContainerBuilder(com.github.ambry.account.ContainerBuilder) AccountBuilder(com.github.ambry.account.AccountBuilder) Test(org.junit.Test) RestUtilsTest(com.github.ambry.rest.RestUtilsTest) StorageStatsUtilTest(com.github.ambry.server.StorageStatsUtilTest)

Example 28 with Container

use of com.github.ambry.account.Container in project ambry by linkedin.

the class FrontendTestUrlSigningServiceFactory method validateSecurePathTest.

/**
 * Test that the secure path is validated if required by {@link Container}.
 * @throws Exception
 */
@Test
public void validateSecurePathTest() throws Exception {
    short refAccountId = Utils.getRandomShort(TestUtils.RANDOM);
    String refAccountName = TestUtils.getRandomString(10);
    short[] refContainerIds = new short[] { 2, 3 };
    String[] refContainerNames = new String[] { "SecurePathValidation", "NoValidation" };
    Container signedPathRequiredContainer = new ContainerBuilder(refContainerIds[0], refContainerNames[0], Container.ContainerStatus.ACTIVE, "validate secure path", refAccountId).setSecurePathRequired(true).build();
    Container noValidationContainer = new ContainerBuilder(refContainerIds[1], refContainerNames[1], Container.ContainerStatus.ACTIVE, "no validation on secure path", refAccountId).setSecurePathRequired(false).build();
    Account account = new AccountBuilder(refAccountId, refAccountName, Account.AccountStatus.ACTIVE).addOrUpdateContainer(signedPathRequiredContainer).addOrUpdateContainer(noValidationContainer).build();
    accountService.updateAccounts(Collections.singletonList(account));
    ByteBuffer content = ByteBuffer.wrap(TestUtils.getRandomBytes(CONTENT_LENGTH));
    String contentType = "application/octet-stream";
    String ownerId = "SecurePathValidationTest";
    JSONObject headers = new JSONObject();
    setAmbryHeadersForPut(headers, TTL_SECS, false, refAccountName, contentType, ownerId, refAccountName, refContainerNames[0], null);
    Map<String, String> userMetadata = new HashMap<>();
    userMetadata.put(RestUtils.Headers.USER_META_DATA_HEADER_PREFIX + "key1", "value1");
    RestUtilsTest.setUserMetadataHeaders(headers, userMetadata);
    String blobId = postBlobAndVerify(headers, content, account, signedPathRequiredContainer);
    headers.put(RestUtils.Headers.BLOB_SIZE, (long) CONTENT_LENGTH);
    // test that secure path validation succeeded
    String testUri = "/" + frontendConfig.securePathPrefix + blobId;
    getBlobAndVerify(testUri, null, null, headers, content, account, signedPathRequiredContainer);
    // test that no secure path should fail (return AccessDenied)
    try {
        getBlobAndVerify(blobId, null, null, headers, content, account, signedPathRequiredContainer);
        fail("get blob should fail because secure path is missing");
    } catch (RestServiceException e) {
        assertEquals("Mismatch in error code", RestServiceErrorCode.AccessDenied, e.getErrorCode());
    }
    // test that secure path equals other prefix should fail (return AccessDenied)
    try {
        getBlobAndVerify("/media" + blobId, null, null, headers, content, account, signedPathRequiredContainer);
        fail("get blob should fail because secure path equals other prefix and doesn't match expected one");
    } catch (RestServiceException e) {
        assertEquals("Mismatch in error code", RestServiceErrorCode.AccessDenied, e.getErrorCode());
    }
    // test that incorrect path should fail (return BadRequest)
    try {
        getBlobAndVerify("/incorrect-path" + blobId, null, null, headers, content, account, signedPathRequiredContainer);
        fail("get blob should fail because secure path is incorrect");
    } catch (RestServiceException e) {
        assertEquals("Mismatch in error code", RestServiceErrorCode.BadRequest, e.getErrorCode());
    }
    // test container with no validation
    setAmbryHeadersForPut(headers, TTL_SECS, false, refAccountName, contentType, ownerId, refAccountName, refContainerNames[1], null);
    content = ByteBuffer.wrap(TestUtils.getRandomBytes(CONTENT_LENGTH));
    blobId = postBlobAndVerify(headers, content, account, noValidationContainer);
    // test container with no validation should fail if there is invalid path in URI
    try {
        getBlobAndVerify("/incorrect-path" + blobId, null, null, headers, content, account, noValidationContainer);
        fail("get blob should fail because there is invalid path in uri");
    } catch (RestServiceException e) {
        assertEquals("Mismatch in error code", RestServiceErrorCode.BadRequest, e.getErrorCode());
    }
    // test container with no validation should succeed if URI is correct
    getBlobAndVerify(blobId, null, null, headers, content, account, noValidationContainer);
}
Also used : Account(com.github.ambry.account.Account) HashMap(java.util.HashMap) ByteBuffer(java.nio.ByteBuffer) RestServiceException(com.github.ambry.rest.RestServiceException) Container(com.github.ambry.account.Container) ContainerBuilder(com.github.ambry.account.ContainerBuilder) JSONObject(org.json.JSONObject) AccountBuilder(com.github.ambry.account.AccountBuilder) Test(org.junit.Test) RestUtilsTest(com.github.ambry.rest.RestUtilsTest) StorageStatsUtilTest(com.github.ambry.server.StorageStatsUtilTest)

Example 29 with Container

use of com.github.ambry.account.Container in project ambry by linkedin.

the class GetAccountsHandlerTest method getSingleContainerSuccessTest.

/**
 * Test success case of getting single container.
 * @throws Exception
 */
@Test
public void getSingleContainerSuccessTest() throws Exception {
    Account existingAccount = accountService.createAndAddRandomAccount();
    Container existingContainer = existingAccount.getAllContainers().iterator().next();
    ThrowingBiConsumer<RestRequest, Container> testAction = (request, expectedContainer) -> {
        RestResponseChannel restResponseChannel = new MockRestResponseChannel();
        ReadableStreamChannel channel = sendRequestGetResponse(request, restResponseChannel);
        assertNotNull("There should be a response", channel);
        Assert.assertNotNull("Date has not been set", restResponseChannel.getHeader(RestUtils.Headers.DATE));
        assertEquals("Content-type is not as expected", RestUtils.JSON_CONTENT_TYPE, restResponseChannel.getHeader(RestUtils.Headers.CONTENT_TYPE));
        assertEquals("Content-length is not as expected", channel.getSize(), Integer.parseInt((String) restResponseChannel.getHeader(RestUtils.Headers.CONTENT_LENGTH)));
        RetainingAsyncWritableChannel asyncWritableChannel = new RetainingAsyncWritableChannel((int) channel.getSize());
        channel.readInto(asyncWritableChannel, null).get();
        assertEquals("Container does not match", Collections.singletonList(expectedContainer), AccountCollectionSerde.containersFromInputStreamInJson(asyncWritableChannel.consumeContentAsInputStream(), existingAccount.getId()));
    };
    testAction.accept(createRestRequest(existingAccount.getName(), null, existingContainer.getName(), Operations.ACCOUNTS_CONTAINERS), existingContainer);
}
Also used : MockRestRequest(com.github.ambry.rest.MockRestRequest) FutureResult(com.github.ambry.router.FutureResult) ThrowingConsumer(com.github.ambry.utils.ThrowingConsumer) AccountCollectionSerde(com.github.ambry.account.AccountCollectionSerde) RequestPath(com.github.ambry.rest.RequestPath) HashSet(java.util.HashSet) JSONObject(org.json.JSONObject) TestUtils(com.github.ambry.utils.TestUtils) RetainingAsyncWritableChannel(com.github.ambry.commons.RetainingAsyncWritableChannel) Container(com.github.ambry.account.Container) ReadableStreamChannel(com.github.ambry.router.ReadableStreamChannel) MetricRegistry(com.codahale.metrics.MetricRegistry) RestMethod(com.github.ambry.rest.RestMethod) Collection(java.util.Collection) RestResponseChannel(com.github.ambry.rest.RestResponseChannel) RestServiceErrorCode(com.github.ambry.rest.RestServiceErrorCode) Test(org.junit.Test) ThrowingBiConsumer(com.github.ambry.utils.ThrowingBiConsumer) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) RestServiceException(com.github.ambry.rest.RestServiceException) MockRestResponseChannel(com.github.ambry.rest.MockRestResponseChannel) Account(com.github.ambry.account.Account) RestUtils(com.github.ambry.rest.RestUtils) Assert(org.junit.Assert) RestRequest(com.github.ambry.rest.RestRequest) Collections(java.util.Collections) InMemAccountService(com.github.ambry.account.InMemAccountService) Account(com.github.ambry.account.Account) Container(com.github.ambry.account.Container) MockRestRequest(com.github.ambry.rest.MockRestRequest) RestRequest(com.github.ambry.rest.RestRequest) ReadableStreamChannel(com.github.ambry.router.ReadableStreamChannel) RetainingAsyncWritableChannel(com.github.ambry.commons.RetainingAsyncWritableChannel) RestResponseChannel(com.github.ambry.rest.RestResponseChannel) MockRestResponseChannel(com.github.ambry.rest.MockRestResponseChannel) MockRestResponseChannel(com.github.ambry.rest.MockRestResponseChannel) Test(org.junit.Test)

Example 30 with Container

use of com.github.ambry.account.Container in project ambry by linkedin.

the class MySqlNamedBlobDbIntegrationTest method testPutGetListDeleteSequence.

/**
 * Tests sequences of puts, gets, lists, and deletes across multiple containers.
 * @throws Exception
 */
@Test
public void testPutGetListDeleteSequence() throws Exception {
    int blobsPerContainer = 5;
    List<NamedBlobRecord> records = new ArrayList<>();
    for (Account account : accountService.getAllAccounts()) {
        for (Container container : account.getAllContainers()) {
            for (int i = 0; i < blobsPerContainer; i++) {
                String blobId = getBlobId(account, container);
                String blobName = "name/" + i + "/more path segments--";
                long expirationTime = i % 2 == 0 ? Utils.Infinite_Time : System.currentTimeMillis() + TimeUnit.HOURS.toMillis(1);
                NamedBlobRecord record = new NamedBlobRecord(account.getName(), container.getName(), blobName, blobId, expirationTime);
                namedBlobDb.put(record).get();
                records.add(record);
            }
        }
    }
    // get records just inserted
    for (NamedBlobRecord record : records) {
        NamedBlobRecord recordFromStore = namedBlobDb.get(record.getAccountName(), record.getContainerName(), record.getBlobName()).get();
        assertEquals("Record does not match expectations.", record, recordFromStore);
    }
    // list records in each container
    for (Account account : accountService.getAllAccounts()) {
        for (Container container : account.getAllContainers()) {
            Page<NamedBlobRecord> page = namedBlobDb.list(account.getName(), container.getName(), "name", null).get();
            assertNull("No continuation token expected", page.getNextPageToken());
            assertEquals("Unexpected number of blobs in container", blobsPerContainer, page.getEntries().size());
        }
    }
    // check that puts to the same keys fail.
    for (Account account : accountService.getAllAccounts()) {
        for (Container container : account.getAllContainers()) {
            for (int i = 0; i < blobsPerContainer; i++) {
                String blobId = getBlobId(account, container);
                String blobName = "name/" + i + "/more path segments--";
                NamedBlobRecord record = new NamedBlobRecord(account.getName(), container.getName(), blobName, blobId, Utils.Infinite_Time);
                checkErrorCode(() -> namedBlobDb.put(record), RestServiceErrorCode.Conflict);
            }
        }
    }
    // delete the records and check that they cannot be fetched with a get call.
    for (NamedBlobRecord record : records) {
        DeleteResult deleteResult = namedBlobDb.delete(record.getAccountName(), record.getContainerName(), record.getBlobName()).get();
        assertEquals("Unexpected deleted ID", record.getBlobId(), deleteResult.getBlobId());
        assertFalse("Unexpected alreadyDeleted value", deleteResult.isAlreadyDeleted());
        checkErrorCode(() -> namedBlobDb.get(record.getAccountName(), record.getContainerName(), record.getBlobName()), RestServiceErrorCode.Deleted);
    }
    // deletes should be idempotent and additional delete calls should succeed
    for (NamedBlobRecord record : records) {
        DeleteResult deleteResult = namedBlobDb.delete(record.getAccountName(), record.getContainerName(), record.getBlobName()).get();
        assertEquals("Unexpected deleted ID", record.getBlobId(), deleteResult.getBlobId());
        assertTrue("Unexpected alreadyDeleted value", deleteResult.isAlreadyDeleted());
    }
    // delete and get for non existent blobs should return not found.
    for (NamedBlobRecord record : records) {
        String nonExistentName = record.getBlobName() + "-other";
        checkErrorCode(() -> namedBlobDb.get(record.getAccountName(), record.getContainerName(), nonExistentName), RestServiceErrorCode.NotFound);
        checkErrorCode(() -> namedBlobDb.delete(record.getAccountName(), record.getContainerName(), nonExistentName), RestServiceErrorCode.NotFound);
    }
    records.clear();
    // should be able to put new records again after deletion
    for (Account account : accountService.getAllAccounts()) {
        for (Container container : account.getAllContainers()) {
            for (int i = 0; i < blobsPerContainer; i++) {
                String blobId = getBlobId(account, container);
                String blobName = "name/" + i + "/more path segments--";
                long expirationTime = i % 2 == 1 ? Utils.Infinite_Time : System.currentTimeMillis() + TimeUnit.HOURS.toMillis(1);
                NamedBlobRecord record = new NamedBlobRecord(account.getName(), container.getName(), blobName, blobId, expirationTime);
                namedBlobDb.put(record).get();
                records.add(record);
            }
        }
    }
}
Also used : Account(com.github.ambry.account.Account) Container(com.github.ambry.account.Container) ArrayList(java.util.ArrayList) Test(org.junit.Test)

Aggregations

Container (com.github.ambry.account.Container)119 Account (com.github.ambry.account.Account)88 Test (org.junit.Test)61 ArrayList (java.util.ArrayList)30 RestServiceException (com.github.ambry.rest.RestServiceException)20 ContainerBuilder (com.github.ambry.account.ContainerBuilder)17 JSONObject (org.json.JSONObject)17 VerifiableProperties (com.github.ambry.config.VerifiableProperties)16 HashSet (java.util.HashSet)15 HashMap (java.util.HashMap)14 Properties (java.util.Properties)14 AccountBuilder (com.github.ambry.account.AccountBuilder)13 RestRequest (com.github.ambry.rest.RestRequest)13 ByteBuffer (java.nio.ByteBuffer)13 Map (java.util.Map)13 MetricRegistry (com.codahale.metrics.MetricRegistry)12 TestUtils (com.github.ambry.utils.TestUtils)12 Collections (java.util.Collections)12 List (java.util.List)12 Assert (org.junit.Assert)12