Skip to content

Commit

Permalink
Initial support for Azure Blobs & Queues (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
Philippe Birbaum authored Oct 1, 2019
1 parent 524a6ef commit b6b35e1
Show file tree
Hide file tree
Showing 20 changed files with 567 additions and 139 deletions.
5 changes: 5 additions & 0 deletions global.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"sdk": {
"version": "2.2.401"
}
}
28 changes: 28 additions & 0 deletions src/AzureStorage.Tests/AzureStorage.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<IsPackable>false</IsPackable>
<RootNamespace>Squadron.AzureStorage.Tests</RootNamespace>
<AssemblyName>Squadron.AzureStorage.Tests</AssemblyName>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
<PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
<PackageReference Include="FluentAssertions" Version="5.4.2" />
<PackageReference Include="coverlet.collector" Version="1.0.1" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\AzureStorage\AzureStorage.csproj" />
</ItemGroup>

<ItemGroup>
<None Update="xunit.runner.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
37 changes: 37 additions & 0 deletions src/AzureStorage.Tests/AzureStorageBlobResourceTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System.Text;
using System.Threading.Tasks;
using FluentAssertions;
using Microsoft.Azure.Storage.Blob;
using Xunit;

namespace Squadron.AzureStorage.Tests
{
public class AzureStorageBlobResourceTests : IClassFixture<AzureStorageBlobResource>
{
private readonly AzureStorageBlobResource _azureStorageResource;

public AzureStorageBlobResourceTests(AzureStorageBlobResource azureStorageResource)
{
_azureStorageResource = azureStorageResource;
}

[Fact]
public async Task CreateBlobClient_UploadFile_ContentMatch()
{
//Arrange
CloudBlobClient blobClient = _azureStorageResource.CreateBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference("foo");
await container.CreateIfNotExistsAsync();
string inputText = "Hello_AzureStorage";
var data = Encoding.UTF8.GetBytes(inputText);

//Act
CloudBlockBlob textFile = container.GetBlockBlobReference("test.txt");
await textFile.UploadFromByteArrayAsync(data, 0, data.Length);

//Assert
string downloaded = await textFile.DownloadTextAsync();
downloaded.Should().Be(inputText);
}
}
}
37 changes: 37 additions & 0 deletions src/AzureStorage.Tests/AzureStorageQueueResourceTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System.Threading.Tasks;
using FluentAssertions;
using Microsoft.Azure.Storage.Queue;
using Xunit;

namespace Squadron.AzureStorage.Tests
{
public class AzureStorageQueueResourceTests : IClassFixture<AzureStorageQueueResource>
{
private readonly AzureStorageQueueResource _azureStorageResource;

public AzureStorageQueueResourceTests(AzureStorageQueueResource azureStorageResource)
{
_azureStorageResource = azureStorageResource;
}

[Fact]
public async Task CreateQueueClient_AddMessage_Peeked()
{
//Arrange
CloudQueueClient queueClient = _azureStorageResource.CreateQueueClient();
CloudQueue queue = queueClient.GetQueueReference("foo");
string messageText = "Hello_AzureStorage";

await queue.CreateIfNotExistsAsync();
var message = new CloudQueueMessage(messageText);

//Act
queue.AddMessage(message);

//Assert
CloudQueueMessage peekedMessage = await queue.PeekMessageAsync();
peekedMessage.AsString.Should().Be(messageText);
}

}
}
4 changes: 4 additions & 0 deletions src/AzureStorage.Tests/xunit.runner.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"appDomain": "denied",
"parallelizeAssembly": true
}
36 changes: 36 additions & 0 deletions src/AzureStorage/AzureStorage.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<RootNamespace>Squadron</RootNamespace>
<AssemblyName>Squadron.AzureStorage</AssemblyName>
<IsPackable>true</IsPackable>
</PropertyGroup>

<PropertyGroup>
<DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>Full</DebugType>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DebugType>pdbonly</DebugType>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Azure.Storage.Blob" Version="11.1.0" />
<PackageReference Include="Microsoft.Azure.Storage.Queue" Version="11.1.0" />
<PackageReference Include="System.Collections.Immutable" Version="1.4.0" />
<PackageReference Include="xunit.core" Version="2.3.1" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Core\Core.csproj" />
</ItemGroup>


</Project>
24 changes: 24 additions & 0 deletions src/AzureStorage/Blob/AzureStorageBlobImageSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System.Collections.Generic;

namespace Squadron
{
public class AzureStorageBlobImageSettings : IImageSettings
{
public AzureStorageBlobImageSettings()
{
EnvironmentVariable =
new List<string>();
}

public string Name { get; } = ContainerName.Create();
public string Image { get; } = "mcr.microsoft.com/azure-storage/azurite";
public long ContainerPort { get; } = 10000;
public long HostPort { get; set; }
public string ContainerId { get; set; }
public string ContainerAddress { get; set; }
public string Username { get; } = string.Empty;
public string Password { get; } = string.Empty;
public List<string> EnvironmentVariable { get; }
public string Logs { get; set; }
}
}
44 changes: 44 additions & 0 deletions src/AzureStorage/Blob/AzureStorageBlobResource.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using System;
using System.Threading.Tasks;
using Microsoft.Azure.Storage;
using Microsoft.Azure.Storage.Blob;
using Xunit;

namespace Squadron
{
/// <summary>
/// Represents a AzureStorage blob resource that can be used by unit tests.
/// Currenty Blob and Queues are supported by this resource
/// </summary>
/// <seealso cref="IDisposable"/>
public class AzureStorageBlobResource
: ResourceBase<AzureStorageBlobImageSettings>, IAsyncLifetime
{
CloudStorageAccount _storageAccount = null;

public async Task InitializeAsync()
{
await StartContainerAsync();

_storageAccount = CloudStorageAccountBuilder.GetForBlob(Settings);

await Initializer.WaitAsync(
new AzureStorageBlobStatus(_storageAccount), Settings);
}

/// <summary>
/// Creates a Blob client
/// </summary>
/// <returns></returns>
public CloudBlobClient CreateBlobClient()
{
return _storageAccount.CreateCloudBlobClient();
}

/// <inheritdoc cref="IAsyncLifetime"/>
public async Task DisposeAsync()
{
await StopContainerAsync();
}
}
}
41 changes: 41 additions & 0 deletions src/AzureStorage/Blob/AzureStorageBlobStatus.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System.Threading.Tasks;
using Microsoft.Azure.Storage;
using Microsoft.Azure.Storage.Blob;
using Microsoft.Azure.Storage.Shared.Protocol;

namespace Squadron
{
/// <summary>
/// Status checker for AzureStorage Blob
/// </summary>
/// <seealso cref="IResourceStatusProvider" />
public class AzureStorageBlobStatus : IResourceStatusProvider
{
private readonly CloudStorageAccount _account;

/// <summary>
/// Initializes a new instance of the <see cref="AzureStorageBlobStatus"/> class.
/// </summary>
public AzureStorageBlobStatus(CloudStorageAccount account)
{
_account = account;
}

/// <summary>
/// Determines whether Azure Blob is ready
/// </summary>
public async Task<Status> IsReadyAsync()
{
CloudBlobClient blobClient = _account.CreateCloudBlobClient();
ServiceProperties serviceProperties =
await blobClient.GetServicePropertiesAsync(
new BlobRequestOptions(),
default);
return new Status
{
IsReady = serviceProperties != null,
Message = _account.BlobStorageUri.ToString()
};
}
}
}
29 changes: 29 additions & 0 deletions src/AzureStorage/CloudStorageAccountBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Microsoft.Azure.Storage;

namespace Squadron
{
internal static class CloudStorageAccountBuilder
{
internal static CloudStorageAccount GetForBlob(IImageSettings settings)
{
return GetAccountByEndpoint("BlobEndpoint", settings);
}

internal static CloudStorageAccount GetForQueue(IImageSettings settings)
{
return GetAccountByEndpoint("QueueEndpoint", settings);
}

private static CloudStorageAccount GetAccountByEndpoint(
string endpoint,
IImageSettings settings)
{
CloudStorageAccount dev = CloudStorageAccount.DevelopmentStorageAccount;
return CloudStorageAccount.Parse(
$"DefaultEndpointsProtocol=http;AccountName={dev.Credentials.AccountName};" +
$"AccountKey={dev.Credentials.ExportBase64EncodedKey()};" +
$"{endpoint}=http://{settings.ContainerAddress}:{settings.HostPort}/" +
$"{dev.Credentials.AccountName};");
}
}
}
24 changes: 24 additions & 0 deletions src/AzureStorage/Queue/AzureStorageQueueImageSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System.Collections.Generic;

namespace Squadron
{
public class AzureStorageQueueImageSettings : IImageSettings
{
public AzureStorageQueueImageSettings()
{
EnvironmentVariable =
new List<string>();
}

public string Name { get; } = ContainerName.Create();
public string Image { get; } = "mcr.microsoft.com/azure-storage/azurite";
public long ContainerPort { get; } = 10001;
public long HostPort { get; set; }
public string ContainerId { get; set; }
public string ContainerAddress { get; set; }
public string Username { get; } = string.Empty;
public string Password { get; } = string.Empty;
public List<string> EnvironmentVariable { get; }
public string Logs { get; set; }
}
}
46 changes: 46 additions & 0 deletions src/AzureStorage/Queue/AzureStorageQueueResource.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System;
using System.Threading.Tasks;
using Microsoft.Azure.Storage;
using Microsoft.Azure.Storage.Blob;
using Microsoft.Azure.Storage.Queue;
using Xunit;

namespace Squadron
{
/// <summary>
/// Represents a AzureStorage queue resource that can be used by unit tests.
/// Currenty Blob and Queues are supported by this resource
/// </summary>
/// <seealso cref="IDisposable"/>
public class AzureStorageQueueResource
: ResourceBase<AzureStorageQueueImageSettings>, IAsyncLifetime
{
CloudStorageAccount _storageAccount = null;

public async Task InitializeAsync()
{
await StartContainerAsync();

_storageAccount = CloudStorageAccountBuilder.GetForQueue(Settings);

await Initializer.WaitAsync(
new AzureStorageQueueStatus(_storageAccount), Settings);
}


/// <summary>
/// Creates a Queue client
/// </summary>
/// <returns></returns>
public CloudQueueClient CreateQueueClient()
{
return _storageAccount.CreateCloudQueueClient();
}

/// <inheritdoc cref="IAsyncLifetime"/>
public async Task DisposeAsync()
{
await StopContainerAsync();
}
}
}
Loading

0 comments on commit b6b35e1

Please sign in to comment.