diff --git a/src/stargripcorp.dataplatform.infra.azure/Exceptions/ApiResponseExceptions.cs b/src/stargripcorp.dataplatform.infra.azure/Exceptions/ApiResponseExceptions.cs new file mode 100644 index 0000000..41e196c --- /dev/null +++ b/src/stargripcorp.dataplatform.infra.azure/Exceptions/ApiResponseExceptions.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace stargripcorp.dataplatform.infra.azure.Exceptions +{ + internal class ApiResponseExceptions(string message) : Exception(message) + { + } +} diff --git a/src/stargripcorp.dataplatform.infra.azure/Helpers/Utils.cs b/src/stargripcorp.dataplatform.infra.azure/Helpers/Utils.cs index 5e28556..adece06 100644 --- a/src/stargripcorp.dataplatform.infra.azure/Helpers/Utils.cs +++ b/src/stargripcorp.dataplatform.infra.azure/Helpers/Utils.cs @@ -1,32 +1,33 @@ using Pulumi.AzureNative.Authorization; +using stargripcorp.dataplatform.infra.azure.Exceptions; using System.Net.Http.Headers; using System.Text.Json; -namespace stargripcorp.dataplatform.infra.azure.Helpers +namespace stargripcorp.dataplatform.infra.azure.Helpers; + +internal static class Utils { - internal class Utils + public static async Task GetRoleIdByNameAsync(string roleName) { - public static async Task GetRoleIdByNameAsync(string roleName) - { - var config = await GetClientConfig.InvokeAsync(); - var token = await GetClientToken.InvokeAsync(); + var config = await GetClientConfig.InvokeAsync(); + var token = await GetClientToken.InvokeAsync(); - // Unfortunately, Microsoft hasn't shipped an .NET5-compatible SDK at the time of writing this. - // So, we have to hand-craft an HTTP request to retrieve a role definition. - var httpClient = new HttpClient(); - httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token.Token); - var response = await httpClient.GetAsync($"https://management.azure.com/subscriptions/{config.SubscriptionId}/providers/Microsoft.Authorization/roleDefinitions?api-version=2018-01-01-preview&$filter=roleName%20eq%20'{roleName}'"); - if (!response.IsSuccessStatusCode) - { - throw new Exception($"Request failed with {response.StatusCode}"); - } - var body = await response.Content.ReadAsStringAsync(); - var definition = JsonSerializer.Deserialize(body); - return definition!.value[0].id; + // Unfortunately, Microsoft hasn't shipped an .NET5-compatible SDK at the time of writing this. + // So, we have to hand-craft an HTTP request to retrieve a role definition. + var httpClient = new HttpClient(); + httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token.Token); + var response = await httpClient.GetAsync($"https://management.azure.com/subscriptions/{config.SubscriptionId}/providers/Microsoft.Authorization/roleDefinitions?api-version=2018-01-01-preview&$filter=roleName%20eq%20'{roleName}'"); + if (!response.IsSuccessStatusCode) + { + throw new ApiResponseExceptions($"Request failed with {response.StatusCode}"); } + var body = await response.Content.ReadAsStringAsync(); + var definition = JsonSerializer.Deserialize(body); + return definition!.value[0].id; } +} #pragma warning disable IDE1006 // Naming Styles - public record RoleDefinition(List value); - public record RoleDefinitionValue(string id, string type, string name); +public record RoleDefinition(List value); +public record RoleDefinitionValue(string id, string type, string name); #pragma warning restore IDE1006 // Naming Styles -} + diff --git a/src/stargripcorp.dataplatform.infra.azure/Infrastructure/CoreComponents.cs b/src/stargripcorp.dataplatform.infra.azure/Infrastructure/CoreComponents.cs index e474430..687f5e2 100644 --- a/src/stargripcorp.dataplatform.infra.azure/Infrastructure/CoreComponents.cs +++ b/src/stargripcorp.dataplatform.infra.azure/Infrastructure/CoreComponents.cs @@ -6,10 +6,10 @@ namespace stargripcorp.dataplatform.infra.azure.Infrastructure; internal class CoreComponents(NamingConvention naming, Dictionary tags) { - private readonly string shortName = "core"; - public void Run() { + var shortName = "core"; + var rg = new AzResourceGroup($"{shortName}-rg", naming, tags).WithBudget(20, ["merca@cetera.desunt.com"]); var admins = new Dictionary diff --git a/src/stargripcorp.dataplatform.infra.azure/Infrastructure/DataPlatform.cs b/src/stargripcorp.dataplatform.infra.azure/Infrastructure/DataPlatform.cs index 48827ee..ee6d3e3 100644 --- a/src/stargripcorp.dataplatform.infra.azure/Infrastructure/DataPlatform.cs +++ b/src/stargripcorp.dataplatform.infra.azure/Infrastructure/DataPlatform.cs @@ -5,10 +5,9 @@ namespace stargripcorp.dataplatform.infra.azure.Infrastructure; internal class DataPlatform(NamingConvention naming, Dictionary tags) { - private readonly string shortName = "data"; - public void Run() { + var shortName = "data"; var rg = new AzResourceGroup($"{shortName}-rg", naming, tags).WithBudget(20, ["merca.ovnerud@pulumi.me"]); _ = new AzStorage($"{shortName}-sa", naming, rg.ResourceGroupName).AsDataLake(); } diff --git a/src/stargripcorp.dataplatform.infra.azure/Resources/AzKeyVault.cs b/src/stargripcorp.dataplatform.infra.azure/Resources/AzKeyVault.cs index cee1154..9edc141 100644 --- a/src/stargripcorp.dataplatform.infra.azure/Resources/AzKeyVault.cs +++ b/src/stargripcorp.dataplatform.infra.azure/Resources/AzKeyVault.cs @@ -64,16 +64,16 @@ public AzKeyVault WithSecretsReader(string[] readerIds) } public AzKeyVault WithKeyVaultSecretsAdmins(Output> contributors) { - object value = contributors.Apply(x => + _ = contributors.Apply(x => { List roleAssignments = []; foreach (var key in x.Keys) { x.TryGetValue(key, out bool user); - if (user) - roleAssignments.Add(ForUser(key, $"{_naming.GenerateResourceId("azure-native:authorization:RoleAssignment")}-{key}")); - else - roleAssignments.Add(ForSp(key, $"{_naming.GenerateResourceId("azure-native:authorization:RoleAssignment")}-{key}")); + if (user) { roleAssignments.Add(ForUser(key, $"{_naming.GenerateResourceId("azure-native:authorization:RoleAssignment")}-{key}")); } + + else { roleAssignments.Add(ForSp(key, $"{_naming.GenerateResourceId("azure-native:authorization:RoleAssignment")}-{key}")); } + } return roleAssignments; }); diff --git a/src/stargripcorp.dataplatform.infra.azure/Resources/AzResourceGroup.cs b/src/stargripcorp.dataplatform.infra.azure/Resources/AzResourceGroup.cs index 65a4b88..dd5aee7 100644 --- a/src/stargripcorp.dataplatform.infra.azure/Resources/AzResourceGroup.cs +++ b/src/stargripcorp.dataplatform.infra.azure/Resources/AzResourceGroup.cs @@ -34,8 +34,8 @@ public AzResourceGroup WithBudget(double budgetAmount, string[] notificationEmai Scope = Output.Format($"/subscriptions/{subscriptionId}"), TimePeriod = new Azure.Consumption.Inputs.BudgetTimePeriodArgs { - StartDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1, 0, 0, 0, DateTimeKind.Utc).ToString("yyyy-MM-ddTHH:mm:ssZ"), - EndDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1, 0, 0, 0, DateTimeKind.Utc).AddYears(1).ToString("yyyy-MM-ddTHH:mm:ssZ") + StartDate = new DateTime(DateTime.UtcNow.Year, DateTime.UtcNow.Month, 1, 0, 0, 0, DateTimeKind.Utc).ToString("yyyy-MM-ddTHH:mm:ssZ"), + EndDate = new DateTime(DateTime.UtcNow.Year, DateTime.UtcNow.Month, 1, 0, 0, 0, DateTimeKind.Utc).AddYears(1).ToString("yyyy-MM-ddTHH:mm:ssZ") }, BudgetName = _naming.GetResourceName("azure-native:resources:Budget"), Filter = new Azure.Consumption.Inputs.BudgetFilterArgs @@ -45,11 +45,10 @@ public AzResourceGroup WithBudget(double budgetAmount, string[] notificationEmai Name = "ResourceGroupName", Operator = "In", Values = new() - { - $"/subscriptions/{ClientConfig.Apply(o=>o.SubscriptionId)}/resourceGroups/{ResourceGroup!.Name}" - } + { + $"/subscriptions/{ClientConfig.Apply(o=>o.SubscriptionId)}/resourceGroups/{ResourceGroup!.Name}" + } }, - }, Notifications = { diff --git a/src/stargripcorp.dataplatform.infra.azure/Resources/AzStorage.cs b/src/stargripcorp.dataplatform.infra.azure/Resources/AzStorage.cs index 47696af..52a8a0b 100644 --- a/src/stargripcorp.dataplatform.infra.azure/Resources/AzStorage.cs +++ b/src/stargripcorp.dataplatform.infra.azure/Resources/AzStorage.cs @@ -6,13 +6,12 @@ namespace stargripcorp.dataplatform.infra.azure.Resources; internal class AzStorage(string id, NamingConvention naming, Output resourceGroupName) : ComponentResource("pkg:azure:storage", id) { - private readonly NamingConvention _naming = naming; public void GenerateStorageAccount(bool isHnsEnabled) { - _ = new Azure.Storage.StorageAccount(_naming.GenerateResourceId("azure-native:storage:StorageAccount"), new() + _ = new Azure.Storage.StorageAccount(naming.GenerateResourceId("azure-native:storage:StorageAccount"), new() { - AccountName = _naming.GetResourceName("azure-native:storage:StorageAccount"), + AccountName = naming.GetResourceName("azure-native:storage:StorageAccount"), ResourceGroupName = resourceGroupName, Sku = new Azure.Storage.Inputs.SkuArgs { diff --git a/src/stargripcorp.dataplatform.infra.utils/Naming/NamingConvention.cs b/src/stargripcorp.dataplatform.infra.utils/Naming/NamingConvention.cs index f4734f4..273222b 100644 --- a/src/stargripcorp.dataplatform.infra.utils/Naming/NamingConvention.cs +++ b/src/stargripcorp.dataplatform.infra.utils/Naming/NamingConvention.cs @@ -40,14 +40,7 @@ public string GetResourceName(string resourceType) public string GenerateResourceId(string resourceType) { - if (!resourceTypeGenerators.ContainsKey(resourceType)) - { - throw new ArgumentException($"Unknown resource type: {resourceType}"); - } - - var resourceTypeAbbreviation = resourceTypeAbbreviations.GetAbbreviation(resourceType); - var resourceName = $"{owner}-{shortName}-{environment}-{resourceTypeAbbreviation}"; - return $"{resourceName}"; + return GenerateResourceName(resourceType); } public string GenerateResourceName(string resourceType) {