public async Task CloudBlobContainerSetMetadataAsync() { CloudBlobContainer container = GetRandomContainerReference(); try { await container.CreateAsync(); CloudBlobContainer container2 = container.ServiceClient.GetContainerReference(container.Name); await container2.FetchAttributesAsync(); Assert.AreEqual(0, container2.Metadata.Count); container.Metadata.Add("key1", "value1"); await container.SetMetadataAsync(); await container2.FetchAttributesAsync(); Assert.AreEqual(1, container2.Metadata.Count); Assert.AreEqual("value1", container2.Metadata["key1"]); ContainerResultSegment results = await container.ServiceClient.ListContainersSegmentedAsync(container.Name, ContainerListingDetails.Metadata, null, null, null, null); CloudBlobContainer container3 = results.Results.First(); Assert.AreEqual(1, container3.Metadata.Count); Assert.AreEqual("value1", container3.Metadata["key1"]); container.Metadata.Clear(); await container.SetMetadataAsync(); await container2.FetchAttributesAsync(); Assert.AreEqual(0, container2.Metadata.Count); } finally { container.DeleteIfExistsAsync().Wait(); } }
public async Task CloudBlobContainerConditionalAccessAsync() { OperationContext operationContext = new OperationContext(); CloudBlobContainer container = GetRandomContainerReference(); try { await container.CreateAsync(); await container.FetchAttributesAsync(); string currentETag = container.Properties.ETag; DateTimeOffset currentModifiedTime = container.Properties.LastModified.Value; // ETag conditional tests container.Metadata["ETagConditionalName"] = "ETagConditionalValue"; await container.SetMetadataAsync(); await container.FetchAttributesAsync(); string newETag = container.Properties.ETag; Assert.AreNotEqual(newETag, currentETag, "ETage should be modified on write metadata"); // LastModifiedTime tests currentModifiedTime = container.Properties.LastModified.Value; container.Metadata["DateConditionalName"] = "DateConditionalValue"; await TestHelper.ExpectedExceptionAsync( async() => await container.SetMetadataAsync(AccessCondition.GenerateIfModifiedSinceCondition(currentModifiedTime), null, operationContext), operationContext, "IfModifiedSince conditional on current modified time should throw", HttpStatusCode.PreconditionFailed, "ConditionNotMet"); container.Metadata["DateConditionalName"] = "DateConditionalValue2"; currentETag = container.Properties.ETag; DateTimeOffset pastTime = currentModifiedTime.Subtract(TimeSpan.FromMinutes(5)); await container.SetMetadataAsync(AccessCondition.GenerateIfModifiedSinceCondition(pastTime), null, null); pastTime = currentModifiedTime.Subtract(TimeSpan.FromHours(5)); await container.SetMetadataAsync(AccessCondition.GenerateIfModifiedSinceCondition(pastTime), null, null); pastTime = currentModifiedTime.Subtract(TimeSpan.FromDays(5)); await container.SetMetadataAsync(AccessCondition.GenerateIfModifiedSinceCondition(pastTime), null, null); await container.FetchAttributesAsync(); newETag = container.Properties.ETag; Assert.AreNotEqual(newETag, currentETag, "ETage should be modified on write metadata"); } finally { container.DeleteIfExistsAsync().AsTask().Wait(); } }
private static async Task TestAccessAsync(BlobContainerPublicAccessType accessType, CloudBlobContainer container, CloudBlob inputBlob) { StorageCredentials credentials = new StorageCredentials(); container = new CloudBlobContainer(container.Uri, credentials); CloudPageBlob blob = new CloudPageBlob(inputBlob.Uri, credentials); OperationContext context = new OperationContext(); BlobRequestOptions options = new BlobRequestOptions(); if (accessType.Equals(BlobContainerPublicAccessType.Container)) { await blob.FetchAttributesAsync(); await container.ListBlobsSegmentedAsync(null, true, BlobListingDetails.All, null, null, options, context); await container.FetchAttributesAsync(); } else if (accessType.Equals(BlobContainerPublicAccessType.Blob)) { await blob.FetchAttributesAsync(); await TestHelper.ExpectedExceptionAsync( async() => await container.ListBlobsSegmentedAsync(null, true, BlobListingDetails.All, null, null, options, context), context, "List blobs while public access does not allow for listing", HttpStatusCode.NotFound); await TestHelper.ExpectedExceptionAsync( async() => await container.FetchAttributesAsync(null, options, context), context, "Fetch container attributes while public access does not allow", HttpStatusCode.NotFound); } else { await TestHelper.ExpectedExceptionAsync( async() => await blob.FetchAttributesAsync(null, options, context), context, "Fetch blob attributes while public access does not allow", HttpStatusCode.NotFound); await TestHelper.ExpectedExceptionAsync( async() => await container.ListBlobsSegmentedAsync(null, true, BlobListingDetails.All, null, null, options, context), context, "List blobs while public access does not allow for listing", HttpStatusCode.NotFound); await TestHelper.ExpectedExceptionAsync( async() => await container.FetchAttributesAsync(null, options, context), context, "Fetch container attributes while public access does not allow", HttpStatusCode.NotFound); } }
private static async Task TestAccessAsync(BlobContainerPublicAccessType accessType, CloudBlobContainer container, CloudBlob inputBlob) { StorageCredentials credentials = new StorageCredentials(); container = new CloudBlobContainer(container.Uri, credentials); CloudPageBlob blob = new CloudPageBlob(inputBlob.Uri, credentials); OperationContext context = new OperationContext(); BlobRequestOptions options = new BlobRequestOptions(); if (accessType.Equals(BlobContainerPublicAccessType.Container)) { await blob.FetchAttributesAsync(); await container.ListBlobsSegmentedAsync(null, true, BlobListingDetails.All, null, null, options, context); await container.FetchAttributesAsync(); } else if (accessType.Equals(BlobContainerPublicAccessType.Blob)) { await blob.FetchAttributesAsync(); await TestHelper.ExpectedExceptionAsync( async () => await container.ListBlobsSegmentedAsync(null, true, BlobListingDetails.All, null, null, options, context), context, "List blobs while public access does not allow for listing", HttpStatusCode.NotFound); await TestHelper.ExpectedExceptionAsync( async () => await container.FetchAttributesAsync(null, options, context), context, "Fetch container attributes while public access does not allow", HttpStatusCode.NotFound); } else { await TestHelper.ExpectedExceptionAsync( async () => await blob.FetchAttributesAsync(null, options, context), context, "Fetch blob attributes while public access does not allow", HttpStatusCode.NotFound); await TestHelper.ExpectedExceptionAsync( async () => await container.ListBlobsSegmentedAsync(null, true, BlobListingDetails.All, null, null, options, context), context, "List blobs while public access does not allow for listing", HttpStatusCode.NotFound); await TestHelper.ExpectedExceptionAsync( async () => await container.FetchAttributesAsync(null, options, context), context, "Fetch container attributes while public access does not allow", HttpStatusCode.NotFound); } }
public async Task CloudBlobClientListContainersWithPublicAccessAsync() { string name = GetRandomContainerName(); CloudBlobClient blobClient = GenerateCloudBlobClient(); CloudBlobContainer container = blobClient.GetContainerReference(name); try { await container.CreateAsync(); BlobContainerPublicAccessType[] accessValues = { BlobContainerPublicAccessType.Container, BlobContainerPublicAccessType.Off, BlobContainerPublicAccessType.Blob }; BlobContainerPermissions permissions = new BlobContainerPermissions(); foreach (BlobContainerPublicAccessType access in accessValues) { permissions.PublicAccess = access; await container.SetPermissionsAsync(permissions); Assert.AreEqual(access, container.Properties.PublicAccess); CloudBlobContainer container2 = blobClient.GetContainerReference(name); Assert.IsFalse(container2.Properties.PublicAccess.HasValue); await container2.FetchAttributesAsync(); Assert.AreEqual(access, container2.Properties.PublicAccess); CloudBlobContainer container3 = blobClient.GetContainerReference(name); BlobContainerPermissions containerAccess = await container3.GetPermissionsAsync(); Assert.AreEqual(access, containerAccess.PublicAccess); Assert.AreEqual(access, container3.Properties.PublicAccess); List <CloudBlobContainer> listedContainers = new List <CloudBlobContainer>(); BlobContinuationToken token = null; do { ContainerResultSegment resultSegment = await blobClient.ListContainersSegmentedAsync(name, token); foreach (CloudBlobContainer returnedContainer in resultSegment.Results) { listedContainers.Add(returnedContainer); } token = resultSegment.ContinuationToken; }while (token != null); Assert.AreEqual(1, listedContainers.Count()); Assert.AreEqual(access, listedContainers.First().Properties.PublicAccess); } } finally { container.DeleteAsync().GetAwaiter().GetResult(); } }
public async Task CloudBlobContainerCreateWithMetadataAsync() { CloudBlobContainer container = GetRandomContainerReference(); try { container.Metadata.Add("key1", "value1"); await container.CreateAsync(); CloudBlobContainer container2 = container.ServiceClient.GetContainerReference(container.Name); await container2.FetchAttributesAsync(); Assert.AreEqual(1, container2.Metadata.Count); Assert.AreEqual("value1", container2.Metadata["key1"]); Assert.IsTrue(container2.Properties.LastModified.Value.AddHours(1) > DateTimeOffset.Now); Assert.IsNotNull(container2.Properties.ETag); } finally { container.DeleteIfExistsAsync().Wait(); } }
/// <summary> /// Calls samples that demonstrate how to work with a blob container. /// </summary> /// <param name="container">A CloudBlobContainer object.</param> /// <returns>A Task object.</returns> private static async Task CallContainerSamples(CloudBlobContainer container) { // Fetch container attributes in order to populate the container's properties and metadata. await container.FetchAttributesAsync(); // Read container metadata and properties. PrintContainerPropertiesAndMetadata(container); // Add container metadata. await AddContainerMetadataAsync(container); // Fetch the container's attributes again, and read container metadata to see the new additions. await container.FetchAttributesAsync(); PrintContainerPropertiesAndMetadata(container); // Make the container available for public access. // With Container-level permissions, container and blob data can be read via anonymous request. // Clients can enumerate blobs within the container via anonymous request, but cannot enumerate containers. await SetAnonymousAccessLevelAsync(container, BlobContainerPublicAccessType.Container); // Try an anonymous operation to read container properties and metadata. Uri containerUri = container.Uri; // Note that we obtain the container reference using only the URI. No account credentials are used. CloudBlobContainer publicContainer = new CloudBlobContainer(containerUri); Console.WriteLine("Read container metadata anonymously"); await container.FetchAttributesAsync(); PrintContainerPropertiesAndMetadata(container); // Make the container private again. await SetAnonymousAccessLevelAsync(container, BlobContainerPublicAccessType.Off); // Test container lease conditions. // This code creates and deletes additional containers. await ManageContainerLeasesAsync(container.ServiceClient); }
/// <summary> /// Checks the lease status of a container, both from its attributes and from a container listing. /// </summary> /// <param name="container">The container to test.</param> /// <param name="expectedStatus">The expected lease status.</param> /// <param name="expectedState">The expected lease state.</param> /// <param name="expectedDuration">The expected lease duration.</param> /// <param name="description">A description of the circumstances that lead to the expected status.</param> private async Task CheckLeaseStatusAsync( CloudBlobContainer container, LeaseStatus expectedStatus, LeaseState expectedState, LeaseDuration expectedDuration, string description) { await container.FetchAttributesAsync(); Assert.AreEqual(expectedStatus, container.Properties.LeaseStatus, "LeaseStatus mismatch: " + description + " (from FetchAttributes)"); Assert.AreEqual(expectedState, container.Properties.LeaseState, "LeaseState mismatch: " + description + " (from FetchAttributes)"); Assert.AreEqual(expectedDuration, container.Properties.LeaseDuration, "LeaseDuration mismatch: " + description + " (from FetchAttributes)"); ContainerResultSegment containers = await this.blobClient.ListContainersSegmentedAsync(container.Name, ContainerListingDetails.None, null, null, null, null); BlobContainerProperties propertiesInListing = (from CloudBlobContainer c in containers.Results where c.Name == container.Name select c.Properties).Single(); Assert.AreEqual(expectedStatus, propertiesInListing.LeaseStatus, "LeaseStatus mismatch: " + description + " (from ListContainers)"); Assert.AreEqual(expectedState, propertiesInListing.LeaseState, "LeaseState mismatch: " + description + " (from ListContainers)"); Assert.AreEqual(expectedDuration, propertiesInListing.LeaseDuration, "LeaseDuration mismatch: " + description + " (from ListContainers)"); }
/// <summary> /// Test container reads and writes, expecting success. /// </summary> /// <param name="testContainer">The container.</param> /// <param name="testAccessCondition">The access condition to use.</param> private async Task ContainerReadWriteExpectLeaseSuccessAsync(CloudBlobContainer testContainer, AccessCondition testAccessCondition) { await testContainer.FetchAttributesAsync(testAccessCondition, null /* options */, null); await testContainer.GetPermissionsAsync(testAccessCondition, null /* options */, null); await testContainer.SetMetadataAsync(testAccessCondition, null /* options */, null); await testContainer.SetPermissionsAsync(new BlobContainerPermissions(), testAccessCondition, null /* options */, null); }
/// <summary> /// Test container reads and writes, expecting lease failure. /// </summary> /// <param name="testContainer">The container.</param> /// <param name="testAccessCondition">The failing access condition to use.</param> /// <param name="expectedErrorCode">The expected error code.</param> /// <param name="description">The reason why these calls should fail.</param> private async Task ContainerReadWriteExpectLeaseFailureAsync(CloudBlobContainer testContainer, AccessCondition testAccessCondition, HttpStatusCode expectedStatusCode, string expectedErrorCode, string description) { OperationContext operationContext = new OperationContext(); // FetchAttributes is a HEAD request with no extended error info, so it returns with the generic ConditionFailed error code. await TestHelper.ExpectedExceptionAsync( async () => await testContainer.FetchAttributesAsync(testAccessCondition, null /* options */, operationContext), operationContext, description + "(Fetch Attributes)", HttpStatusCode.PreconditionFailed); await TestHelper.ExpectedExceptionAsync( async () => await testContainer.GetPermissionsAsync(testAccessCondition, null /* options */, operationContext), operationContext, description + " (Get Permissions)", expectedStatusCode, expectedErrorCode); await TestHelper.ExpectedExceptionAsync( async () => await testContainer.SetMetadataAsync(testAccessCondition, null /* options */, operationContext), operationContext, description + " (Set Metadata)", expectedStatusCode, expectedErrorCode); await TestHelper.ExpectedExceptionAsync( async () => await testContainer.SetPermissionsAsync(new BlobContainerPermissions(), testAccessCondition, null /* options */, operationContext), operationContext, description + " (Set Permissions)", expectedStatusCode, expectedErrorCode); }
/// <summary> /// Verifies the behavior of a lease while the lease holds. Once the lease expires, this method confirms that write operations succeed. /// The test is cut short once the <c>testLength</c> time has elapsed. /// </summary> /// <param name="leasedContainer">The container.</param> /// <param name="duration">The duration of the lease.</param> /// <param name="testLength">The maximum length of time to run the test.</param> /// <param name="tolerance">The allowed lease time error.</param> internal async Task ContainerAcquireRenewLeaseTestAsync(CloudBlobContainer leasedContainer, TimeSpan? duration, TimeSpan testLength, TimeSpan tolerance) { OperationContext operationContext = new OperationContext(); DateTime beginTime = DateTime.UtcNow; while (true) { try { // Attempt to delete the container with no lease ID. await leasedContainer.DeleteAsync(null, null, operationContext); // The delete succeeded, which means that the lease must have expired. // If the lease was infinite then there is an error because it should not have expired. Assert.IsNotNull(duration, "An infinite lease should not expire."); // The lease should be past its expiration time. Assert.IsTrue(DateTime.UtcNow - beginTime > duration - tolerance, "Deletes should not succeed while lease is present."); // Since the lease has expired (and the container was deleted), the test is over. return; } catch (Exception) { if (operationContext.LastResult.ExtendedErrorInformation.ErrorCode == BlobErrorCodeStrings.LeaseIdMissing) { // We got this error because the lease has not expired yet. // Make sure the lease is not past its expiration time yet. DateTime currentTime = DateTime.UtcNow; if (duration.HasValue) { Assert.IsTrue(currentTime - beginTime < duration + tolerance, "Deletes should succeed after a lease expires."); } // End the test early if necessary if (currentTime - beginTime > testLength) { // The lease has not expired, but we're not waiting any longer. return; } } else { throw; } } // Attempt to write to and read from the container. This should always succeed. await leasedContainer.SetMetadataAsync(); await leasedContainer.FetchAttributesAsync(); // Wait 1 second before trying again. await Task.Delay(TimeSpan.FromSeconds(1)); } }
/// <summary> /// Test container reads and writes, expecting success. /// </summary> /// <param name="testContainer">The container.</param> /// <param name="testAccessCondition">The access condition to use.</param> private void ContainerReadWriteExpectLeaseSuccessTask(CloudBlobContainer testContainer, AccessCondition testAccessCondition) { testContainer.FetchAttributesAsync(testAccessCondition, null /* options */, null /* operationContext */).Wait(); testContainer.GetPermissionsAsync(testAccessCondition, null /* options */, null /* operationContext */).Wait(); testContainer.SetMetadataAsync(testAccessCondition, null /* options */, null /* operationContext */).Wait(); testContainer.SetPermissionsAsync(new BlobContainerPermissions(), testAccessCondition, null /* options */, null /* operationContext */).Wait(); }
private static void TestAccessTask(BlobContainerPublicAccessType accessType, CloudBlobContainer container, CloudBlob inputBlob) { StorageCredentials credentials = new StorageCredentials(); container = new CloudBlobContainer(container.Uri, credentials); CloudPageBlob blob = new CloudPageBlob(inputBlob.Uri, credentials); if (accessType.Equals(BlobContainerPublicAccessType.Container)) { blob.FetchAttributesAsync().Wait(); BlobContinuationToken token = null; do { BlobResultSegment results = container.ListBlobsSegmented(token); results.Results.ToArray(); token = results.ContinuationToken; } while (token != null); container.FetchAttributesAsync().Wait(); } else if (accessType.Equals(BlobContainerPublicAccessType.Blob)) { blob.FetchAttributesAsync().Wait(); TestHelper.ExpectedExceptionTask( container.ListBlobsSegmentedAsync(null), "List blobs while public access does not allow for listing", HttpStatusCode.NotFound); TestHelper.ExpectedExceptionTask( container.FetchAttributesAsync(), "Fetch container attributes while public access does not allow", HttpStatusCode.NotFound); } else { TestHelper.ExpectedExceptionTask( blob.FetchAttributesAsync(), "Fetch blob attributes while public access does not allow", HttpStatusCode.NotFound); TestHelper.ExpectedExceptionTask( container.ListBlobsSegmentedAsync(null), "List blobs while public access does not allow for listing", HttpStatusCode.NotFound); TestHelper.ExpectedExceptionTask( container.FetchAttributesAsync(), "Fetch container attributes while public access does not allow", HttpStatusCode.NotFound); } }
private async Task AddBasicContainerHeaders(HttpResponseMessage response, CloudBlobContainer container) { await container.FetchAttributesAsync(); response.Headers.ETag = new EntityTagHeaderValue(container.Properties.ETag); if (container.Properties.LastModified.HasValue) { if (response.Content == null) { response.Content = new StringContent(""); } response.Content.Headers.LastModified = container.Properties.LastModified.Value.UtcDateTime; } //Right now we are just parroting back the values sent by the client. Might need to generate our //own values for these if none are provided. IEnumerable<string> headerValues; if (Request.Headers.TryGetValues("x-ms-client-request-id", out headerValues)) { response.Headers.Add("x-ms-request-id", headerValues); } response.Headers.Add("x-ms-version", TryGetHeader(Request.Headers, "x-ms-version")); response.Headers.Date = DateTimeOffset.UtcNow; }
private async Task<HttpResponseMessage> ValidatePreconditions(CloudBlobContainer container) { // TODO: Ensure that all preconditions are validated if (!await container.ExistsAsync()) { return new HttpResponseMessage(HttpStatusCode.NotFound); } IEnumerable<string> leaseID; if (Request.Headers.TryGetValues("x-ms-lease-id", out leaseID)) { AccessCondition condition = new AccessCondition() { LeaseId = leaseID.First() }; //Try fetching the attributes to force validation of the leaseID await container.FetchAttributesAsync(condition, null, null); } // If we don't find any errors, just return null to indicate that everything is A-OK. return null; }
static async Task CopyContainer(CloudBlobContainer sourceContainer, CloudBlobContainer destContainer) { await sourceContainer.FetchAttributesAsync(); var access = await sourceContainer.GetPermissionsAsync(); await destContainer.CreateIfNotExistsAsync(access.PublicAccess, null, null); await destContainer.SetPermissionsAsync(access); destContainer.Metadata.Clear(); foreach (var metadatum in sourceContainer.Metadata) { destContainer.Metadata.Add(metadatum); } await destContainer.SetMetadataAsync(); }