Skip to content

Instantly share code, notes, and snippets.

@benhysell
Created July 23, 2018 12:55
Show Gist options
  • Save benhysell/a7cb2b95b83a50b89382b5cbdf6c3e23 to your computer and use it in GitHub Desktop.
Save benhysell/a7cb2b95b83a50b89382b5cbdf6c3e23 to your computer and use it in GitHub Desktop.
Azure Storage Simulator using Azurite and Docker
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Docker.DotNet;
using Docker.DotNet.Models;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
namespace Web.Utilities
{
/// <summary>
/// Azure Storage Simulator using Azurite, https://github.com/Azure/Azurite
/// </summary>
public class AzureStorageSimulator
{
private static string _containerPortBlob = "10000";
private static string _containerPortQueue = "10001";
private static string _containerPortTable = "10002";
private static string _dockerImageName = "arafato/azurite";
private static Uri _localHost = new Uri("http://localhost:2375");
/// <summary>
/// Start a container
/// </summary>
/// <param name="dockerContainerName"></param>
/// <param name="storagePathLocalFileSystem"></param>
/// <param name="hostPortBlob"></param>
/// <param name="hostPortQueue"></param>
/// <param name="hostPortTable"></param>
/// <param name="storageAccountConnectionString"></param>
/// <param name="storageBlobContainerName"></param>
/// <returns></returns>
public static async Task<string> StartContainerAsync(string dockerContainerName, string storagePathLocalFileSystem, string hostPortBlob, string hostPortQueue, string hostPortTable, string storageAccountConnectionString, string storageBlobContainerName)
{
//create directory for local storage
if (!Directory.Exists(storagePathLocalFileSystem))
{
Directory.CreateDirectory(storagePathLocalFileSystem);
}
var _dockerClient = new DockerClientConfiguration(_localHost).CreateClient();
var containerId = string.Empty;
var containers = await FindContainerAsync(dockerContainerName, _dockerClient);
if (!containers.Any())
{
//create the container
var container = await _dockerClient.Containers.CreateContainerAsync(
new CreateContainerParameters
{
Name = dockerContainerName,
Image = _dockerImageName,
Volumes = new Dictionary<string, EmptyStruct>
{
{
storagePathLocalFileSystem, new EmptyStruct()
}
},
ExposedPorts = new Dictionary<string, EmptyStruct>
{
{
_containerPortBlob, new EmptyStruct()
},
{
_containerPortTable, new EmptyStruct()
},
{
_containerPortQueue, new EmptyStruct()
}
},
HostConfig = new HostConfig
{
//bind local storage to internal storage
Binds = new List<string>() { $"{storagePathLocalFileSystem}:/opt/azurite/folder" },
PortBindings = new Dictionary<string, IList<PortBinding>>
{
{
_containerPortBlob, new List<PortBinding>
{
new PortBinding
{
HostPort = hostPortBlob
}
}
},
{
_containerPortTable, new List<PortBinding>
{
new PortBinding
{
HostPort = hostPortTable
}
}
},
{
_containerPortQueue, new List<PortBinding>
{
new PortBinding
{
HostPort = hostPortQueue
}
}
}
}
}
});
await _dockerClient.Containers.StartContainerAsync(container.ID, new ContainerStartParameters());
containerId = container.ID;
//add storage container
CloudBlobContainer cloudBlobContainer = null;
if (CloudStorageAccount.TryParse(storageAccountConnectionString, out var storageAccount))
{
// Create the CloudBlobClient that represents the Blob storage endpoint for the storage account.
var cloudBlobClient = storageAccount.CreateCloudBlobClient();
cloudBlobContainer = cloudBlobClient.GetContainerReference(storageBlobContainerName);
if (!await cloudBlobContainer.CreateIfNotExistsAsync())
{
throw new Exception($"Could not create blob container {storageBlobContainerName}");
}
}
else
{
throw new Exception($"Could not create blob container, could not parse connection string {storageBlobContainerName}");
}
}
else
{
if ("running" != containers[0].State)
{
await _dockerClient.Containers.StartContainerAsync(containers[0].ID, new ContainerStartParameters());
}
containerId = containers[0].ID;
}
return containerId;
}
/// <summary>
/// Stop container
/// </summary>
/// <param name="dockerContainerName"></param>
/// <returns></returns>
public static async Task StopContainerAsync(string dockerContainerName)
{
var _dockerClient = new DockerClientConfiguration(_localHost).CreateClient();
var containers = await FindContainerAsync(dockerContainerName, _dockerClient);
if (containers.Any())
{
if ("running" == containers[0].State)
{
await _dockerClient.Containers.StopContainerAsync(containers[0].ID, new ContainerStopParameters());
}
}
}
/// <summary>
/// Deletes a container and local resources
/// </summary>
/// <param name="dockerContainerName"></param>
/// <param name="storagePathLocalFileSystem"></param>
/// <returns></returns>
public static async Task<string> DeleteContainerAsync(string dockerContainerName, string storagePathLocalFileSystem)
{
var _dockerClient = new DockerClientConfiguration(_localHost).CreateClient();
var containerId = string.Empty;
var containers = await FindContainerAsync(dockerContainerName, _dockerClient);
if (containers.Any())
{
await _dockerClient.Containers.RemoveContainerAsync(containers[0].ID, new ContainerRemoveParameters() { Force = true });
//create directory for local storage
if (Directory.Exists(storagePathLocalFileSystem))
{
Directory.Delete(storagePathLocalFileSystem, true);
}
}
return containerId;
}
/// <summary>
/// Find container based on name
/// </summary>
/// <param name="dockerContainerName"></param>
/// <param name="_dockerClient"></param>
/// <returns></returns>
private static async Task<IList<ContainerListResponse>> FindContainerAsync(string dockerContainerName, DockerClient _dockerClient)
{
return await _dockerClient.Containers.ListContainersAsync(
new ContainersListParameters()
{
All = true,
Filters = new Dictionary<string, IDictionary<string, bool>>
{
{
"name", new Dictionary<string, bool>
{
{ dockerContainerName, true }
}
}
} as IDictionary<string, IDictionary<string, bool>>
});
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment