Skip to content

Commit

Permalink
Add IStorageService.
Browse files Browse the repository at this point in the history
Configure DependencyInjection for DataLake.
  • Loading branch information
eminencegrs committed Jan 28, 2024
1 parent f543e69 commit f7e5619
Show file tree
Hide file tree
Showing 11 changed files with 170 additions and 89 deletions.
22 changes: 19 additions & 3 deletions src/Seneca.Azure.Integration.Api/DirectoriesController.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,31 @@
using Microsoft.AspNetCore.Mvc;
using Seneca.Azure.Integration.DataLake;
using Swashbuckle.AspNetCore.Annotations;

namespace Seneca.Azure.Integration.Api;

[Route("api/[controller]")]
[ApiController]
[Route("api/[controller]/{name}")]
public class DirectoriesController : ControllerBase
{
[HttpPost]
public async Task<IActionResult> CreateFolder()
private readonly IStorageService storageService;

public DirectoriesController(IStorageService storageService)
{
this.storageService = storageService;
}

[HttpPut]
public async Task<IActionResult> CreateDirectory(string name)
{
// TODO: add implementation.
return await Task.FromResult(new OkObjectResult("Not implemented yet"));
}

[HttpPut("link")]
public async Task<IActionResult> GenerateToken(string name)
{
// TODO: add implementation.
return await Task.FromResult(new OkObjectResult("Not implemented yet"));
}
}
16 changes: 2 additions & 14 deletions src/Seneca.Azure.Integration.Api/Program.cs
Original file line number Diff line number Diff line change
@@ -1,21 +1,11 @@
using Microsoft.Extensions.Azure;
using Seneca.Azure.Integration.DataLake;
using Seneca.Azure.Integration.DataLake.DependencyInjection;

var builder = WebApplication.CreateBuilder(args);

builder.Services.Configure<DataLakeSettings>(builder.Configuration.GetSection(DataLakeSettings.SectionName));

// TODO: register all dependencies.
builder.Services.AddScoped<DataLakeServiceV1>();

builder.Services.AddAzureClients(clientBuilder =>
{
clientBuilder.AddDataLakeServiceClient(builder.Configuration.GetSection(DataLakeSettings.SectionName));
});
builder.Services.AddDataLake(builder.Configuration);

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

builder.Services.AddControllers();

var app = builder.Build();
Expand All @@ -27,7 +17,5 @@
}

app.UseHttpsRedirection();

app.MapControllers();

app.Run();
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Azure" Version="1.7.1" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.5.0" />
</ItemGroup>

<ItemGroup>
Expand Down
124 changes: 62 additions & 62 deletions src/Seneca.Azure.Integration.DataLake/DataLakeServiceV1.cs
Original file line number Diff line number Diff line change
@@ -1,62 +1,62 @@
using System;
using System.Threading.Tasks;
using Azure.Storage;
using Azure.Storage.Files.DataLake;
using Azure.Storage.Files.DataLake.Models;
using Azure.Storage.Sas;
using Microsoft.Extensions.Options;

namespace Seneca.Azure.Integration.DataLake;

[Obsolete("Will be removed. Use StorageService instead.")]
public class DataLakeServiceV1
{
private const string FileSystemDefaultName = "default-file-system";

private readonly DataLakeServiceClient serviceClient;
private readonly DataLakeSettings settings;

public DataLakeServiceV1(IOptions<DataLakeSettings> options)
{
this.settings = options.Value;
var credential = new StorageSharedKeyCredential(this.settings.AccountName, this.settings.AccountKey);
var serviceUri = new Uri($"https://{this.settings.AccountName}.dfs.core.windows.net");
this.serviceClient = new DataLakeServiceClient(serviceUri, credential);
}

public async Task<(DataLakeDirectoryClient directoryClient, Uri sasUri)> CreateDirectoryWithSas(
string directoryName,
string policyName = "mySasPolicy")
{
var fileSystemClient = this.serviceClient.GetFileSystemClient(FileSystemDefaultName);
await fileSystemClient.CreateIfNotExistsAsync();

var directoryClientResponse = await fileSystemClient.CreateDirectoryAsync(directoryName);
var directoryClient = directoryClientResponse.HasValue
? directoryClientResponse.Value
: throw new InvalidOperationException();

var sasBuilder = new DataLakeSasBuilder
{
FileSystemName = fileSystemClient.Name,
Path = directoryClient.Path,
// TODO: move to the settings.
ExpiresOn = DateTimeOffset.UtcNow.AddDays(1),
Protocol = SasProtocol.Https,
// TODO: move to the settings?
Resource = "d", // 'd' for directory
StartsOn = DateTimeOffset.UtcNow,
};

// TODO: manage permissions properly.
sasBuilder.SetPermissions(DataLakeSasPermissions.Read | DataLakeSasPermissions.Write);

var sasToken = sasBuilder
.ToSasQueryParameters(new StorageSharedKeyCredential(this.settings.AccountName, this.settings.AccountKey))
.ToString();

var sasUri = new Uri($"{directoryClient.Uri}?{sasToken}");

return (directoryClient, sasUri);
}
}
// using System;
// using System.Threading.Tasks;
// using Azure.Storage;
// using Azure.Storage.Files.DataLake;
// using Azure.Storage.Files.DataLake.Models;
// using Azure.Storage.Sas;
// using Microsoft.Extensions.Options;
//
// namespace Seneca.Azure.Integration.DataLake;
//
// [Obsolete("Will be removed. Use StorageService instead.")]
// public class DataLakeServiceV1
// {
// private const string FileSystemDefaultName = "default-file-system";
//
// private readonly DataLakeServiceClient serviceClient;
// private readonly DataLakeSettings settings;
//
// public DataLakeServiceV1(IOptions<DataLakeSettings> options)
// {
// this.settings = options.Value;
// var credential = new StorageSharedKeyCredential(this.settings.AccountName, this.settings.AccountKey);
// var serviceUri = new Uri($"https://{this.settings.AccountName}.dfs.core.windows.net");
// this.serviceClient = new DataLakeServiceClient(serviceUri, credential);
// }
//
// public async Task<(DataLakeDirectoryClient directoryClient, Uri sasUri)> CreateDirectoryWithSas(
// string directoryName,
// string policyName = "mySasPolicy")
// {
// var fileSystemClient = this.serviceClient.GetFileSystemClient(FileSystemDefaultName);
// await fileSystemClient.CreateIfNotExistsAsync();
//
// var directoryClientResponse = await fileSystemClient.CreateDirectoryAsync(directoryName);
// var directoryClient = directoryClientResponse.HasValue
// ? directoryClientResponse.Value
// : throw new InvalidOperationException();
//
// var sasBuilder = new DataLakeSasBuilder
// {
// FileSystemName = fileSystemClient.Name,
// Path = directoryClient.Path,
// // TODO: move to the settings.
// ExpiresOn = DateTimeOffset.UtcNow.AddDays(1),
// Protocol = SasProtocol.Https,
// // TODO: move to the settings?
// Resource = "d", // 'd' for directory
// StartsOn = DateTimeOffset.UtcNow,
// };
//
// // TODO: manage permissions properly.
// sasBuilder.SetPermissions(DataLakeSasPermissions.Read | DataLakeSasPermissions.Write);
//
// var sasToken = sasBuilder
// .ToSasQueryParameters(new StorageSharedKeyCredential(this.settings.AccountName, this.settings.AccountKey))
// .ToString();
//
// var sasUri = new Uri($"{directoryClient.Uri}?{sasToken}");
//
// return (directoryClient, sasUri);
// }
// }
1 change: 0 additions & 1 deletion src/Seneca.Azure.Integration.DataLake/DataLakeSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,5 @@ public record class DataLakeSettings
{
public static readonly string SectionName = "Azure:DataLake";
public string AccountName { get; init; } = null!;
public string AccountKey { get; init; } = null!;
public string ServiceUri { get; init; } = null!;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using Microsoft.Extensions.Azure;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace Seneca.Azure.Integration.DataLake.DependencyInjection;

public static class ServiceCollectionExtensions
{
public static IServiceCollection AddDataLake(this IServiceCollection services, IConfiguration configuration)
{
ArgumentNullException.ThrowIfNull(services);

services.AddSettings(configuration);
services.AddAzureClients(clientBuilder =>
{
clientBuilder.AddDataLakeServiceClient(configuration.GetSection(DataLakeSettings.SectionName));
});

services.AddScoped<IStorageService, StorageService>();

return services;
}

private static IServiceCollection AddSettings(this IServiceCollection services, IConfiguration configuration)
{
services.Configure<DataLakeSettings>(configuration.GetSection(DataLakeSettings.SectionName));

return services;
}
}
7 changes: 7 additions & 0 deletions src/Seneca.Azure.Integration.DataLake/IStorageService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Seneca.Azure.Integration.DataLake;

public interface IStorageService
{
Task CreateDirectory(string name);
Task GenerateToken(string name);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,16 @@
<ItemGroup>
<PackageReference Include="Azure.Identity" Version="1.10.4" />
<PackageReference Include="Azure.Storage.Files.DataLake" Version="12.17.1" />
<PackageReference Include="Microsoft.Extensions.Azure" Version="1.7.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="8.0.0" />
</ItemGroup>

<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
<_Parameter1>Seneca.Azure.Integration.DataLake.UnitTests</_Parameter1>
</AssemblyAttribute>
</ItemGroup>

</Project>
7 changes: 1 addition & 6 deletions src/Seneca.Azure.Integration.DataLake/StorageService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Seneca.Azure.Integration.DataLake;

internal class StorageService
internal class StorageService : IStorageService
{
private readonly ILogger<StorageService> logger;
private readonly DataLakeSettings settings;
Expand All @@ -29,9 +29,4 @@ public Task GenerateToken(string name)
{
throw new NotImplementedException();
}

public async Task UploadFile(string directoryName, string fileName, Stream stream)
{
throw new NotImplementedException();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="Moq" Version="4.20.70" />
<PackageReference Include="Shouldly" Version="4.2.1" />
<PackageReference Include="xunit" Version="2.6.5" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.6">
Expand All @@ -23,4 +24,8 @@
</PackageReference>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Seneca.Azure.Integration.DataLake\Seneca.Azure.Integration.DataLake.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using Azure.Storage.Files.DataLake;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Moq;
using Shouldly;
using Xunit;

namespace Seneca.Azure.Integration.DataLake.UnitTests;

public class StorageServiceTests
{
[Fact]
public void GivenNull_WhenCallCreateDirectory_ThenNotImplementedExceptionThrown()
{
var logger = new NullLogger<StorageService>();
var settingsMock = new Mock<IOptions<DataLakeSettings>>();
var clientMock = new Mock<DataLakeServiceClient>();
var sut = new StorageService(logger, settingsMock.Object, clientMock.Object);
var action = () => sut.CreateDirectory(default!);
action.ShouldThrow<NotImplementedException>();
}

[Fact]
public void GivenNull_WhenCallGenerateToken_ThenNotImplementedExceptionThrown()
{
var logger = new NullLogger<StorageService>();
var settingsMock = new Mock<IOptions<DataLakeSettings>>();
var clientMock = new Mock<DataLakeServiceClient>();
var sut = new StorageService(logger, settingsMock.Object, clientMock.Object);
var action = () => sut.GenerateToken(default!);
action.ShouldThrow<NotImplementedException>();
}
}

0 comments on commit f7e5619

Please sign in to comment.