diff --git a/sdk/provisioning/Azure.Provisioning/api/Azure.Provisioning.net6.0.cs b/sdk/provisioning/Azure.Provisioning/api/Azure.Provisioning.net6.0.cs index c88db56682153..0f363d9041689 100644 --- a/sdk/provisioning/Azure.Provisioning/api/Azure.Provisioning.net6.0.cs +++ b/sdk/provisioning/Azure.Provisioning/api/Azure.Provisioning.net6.0.cs @@ -207,3 +207,21 @@ public partial class SqlServer : Azure.Provisioning.Resource + { + public BlobService(Azure.Provisioning.IConstruct scope, string name = "blob") : base (default(Azure.Provisioning.IConstruct), default(Azure.Provisioning.Resource), default(string), default(Azure.Core.ResourceType), default(string), default(Azure.ResourceManager.Storage.BlobServiceData)) { } + protected override Azure.Provisioning.Resource? FindParentInScope(Azure.Provisioning.IConstruct scope) { throw null; } + } + public partial class StorageAccount : Azure.Provisioning.Resource + { + public StorageAccount(Azure.Provisioning.IConstruct scope, Azure.ResourceManager.Storage.Models.StorageKind kind, Azure.ResourceManager.Storage.Models.StorageSkuName sku, Azure.Provisioning.ResourceManager.ResourceGroup? parent = null, string name = "sa") : base (default(Azure.Provisioning.IConstruct), default(Azure.Provisioning.Resource), default(string), default(Azure.Core.ResourceType), default(string), default(Azure.ResourceManager.Storage.StorageAccountData)) { } + protected override Azure.Provisioning.Resource? FindParentInScope(Azure.Provisioning.IConstruct scope) { throw null; } + } + public static partial class StorageExtensions + { + public static Azure.Provisioning.Storage.BlobService AddBlobService(this Azure.Provisioning.IConstruct scope, string name = "blob") { throw null; } + public static Azure.Provisioning.Storage.StorageAccount AddStorageAccount(this Azure.Provisioning.IConstruct scope, Azure.ResourceManager.Storage.Models.StorageKind kind, Azure.ResourceManager.Storage.Models.StorageSkuName sku, Azure.Provisioning.ResourceManager.ResourceGroup? parent = null, string name = "sa") { throw null; } + } +} diff --git a/sdk/provisioning/Azure.Provisioning/api/Azure.Provisioning.netstandard2.0.cs b/sdk/provisioning/Azure.Provisioning/api/Azure.Provisioning.netstandard2.0.cs index c88db56682153..0f363d9041689 100644 --- a/sdk/provisioning/Azure.Provisioning/api/Azure.Provisioning.netstandard2.0.cs +++ b/sdk/provisioning/Azure.Provisioning/api/Azure.Provisioning.netstandard2.0.cs @@ -207,3 +207,21 @@ public partial class SqlServer : Azure.Provisioning.Resource + { + public BlobService(Azure.Provisioning.IConstruct scope, string name = "blob") : base (default(Azure.Provisioning.IConstruct), default(Azure.Provisioning.Resource), default(string), default(Azure.Core.ResourceType), default(string), default(Azure.ResourceManager.Storage.BlobServiceData)) { } + protected override Azure.Provisioning.Resource? FindParentInScope(Azure.Provisioning.IConstruct scope) { throw null; } + } + public partial class StorageAccount : Azure.Provisioning.Resource + { + public StorageAccount(Azure.Provisioning.IConstruct scope, Azure.ResourceManager.Storage.Models.StorageKind kind, Azure.ResourceManager.Storage.Models.StorageSkuName sku, Azure.Provisioning.ResourceManager.ResourceGroup? parent = null, string name = "sa") : base (default(Azure.Provisioning.IConstruct), default(Azure.Provisioning.Resource), default(string), default(Azure.Core.ResourceType), default(string), default(Azure.ResourceManager.Storage.StorageAccountData)) { } + protected override Azure.Provisioning.Resource? FindParentInScope(Azure.Provisioning.IConstruct scope) { throw null; } + } + public static partial class StorageExtensions + { + public static Azure.Provisioning.Storage.BlobService AddBlobService(this Azure.Provisioning.IConstruct scope, string name = "blob") { throw null; } + public static Azure.Provisioning.Storage.StorageAccount AddStorageAccount(this Azure.Provisioning.IConstruct scope, Azure.ResourceManager.Storage.Models.StorageKind kind, Azure.ResourceManager.Storage.Models.StorageSkuName sku, Azure.Provisioning.ResourceManager.ResourceGroup? parent = null, string name = "sa") { throw null; } + } +} diff --git a/sdk/provisioning/Azure.Provisioning/src/Azure.Provisioning.csproj b/sdk/provisioning/Azure.Provisioning/src/Azure.Provisioning.csproj index c45827a3e3542..63f054a28e99a 100644 --- a/sdk/provisioning/Azure.Provisioning/src/Azure.Provisioning.csproj +++ b/sdk/provisioning/Azure.Provisioning/src/Azure.Provisioning.csproj @@ -14,6 +14,7 @@ + diff --git a/sdk/provisioning/Azure.Provisioning/src/storage/BlobService.cs b/sdk/provisioning/Azure.Provisioning/src/storage/BlobService.cs new file mode 100644 index 0000000000000..366e9149f066b --- /dev/null +++ b/sdk/provisioning/Azure.Provisioning/src/storage/BlobService.cs @@ -0,0 +1,44 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Azure.ResourceManager.Storage; +using Azure.ResourceManager.Storage.Models; + +namespace Azure.Provisioning.Storage +{ + /// + /// Represents a blob service. + /// + public class BlobService : Resource + { + private const string ResourceTypeName = "Microsoft.Storage/storageAccounts/blobServices"; + + private static string GetName(IConstruct scope, string? name) + { + return $"{name}-{scope.EnvironmentName}"; + } + + /// + /// Initializes a new instance of the . + /// + /// The scope. + /// The name. + public BlobService(IConstruct scope, string name = "blob") + : base(scope, null, GetName(scope, name), ResourceTypeName, "2022-09-01", ArmStorageModelFactory.BlobServiceData( + name: GetName(scope, name), + resourceType: ResourceTypeName)) + { + } + + /// + protected override Resource? FindParentInScope(IConstruct scope) + { + var result = base.FindParentInScope(scope); + if (result is null) + { + result = scope.GetSingleResource() ?? new StorageAccount(scope, StorageKind.BlockBlobStorage, StorageSkuName.PremiumLrs); + } + return result; + } + } +} diff --git a/sdk/provisioning/Azure.Provisioning/src/storage/StorageAccount.cs b/sdk/provisioning/Azure.Provisioning/src/storage/StorageAccount.cs new file mode 100644 index 0000000000000..ca0ae20f0845f --- /dev/null +++ b/sdk/provisioning/Azure.Provisioning/src/storage/StorageAccount.cs @@ -0,0 +1,54 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using Azure.Core; +using Azure.Provisioning.ResourceManager; +using Azure.ResourceManager.Storage; +using Azure.ResourceManager.Storage.Models; + +namespace Azure.Provisioning.Storage +{ + /// + /// Represents a storage account. + /// + public class StorageAccount : Resource + { + private const string ResourceTypeName = "Microsoft.Storage/storageAccounts"; + + private static string GetName(IConstruct scope, string name) + { + var result = $"{name}-{Guid.NewGuid()}"; + return result.Substring(0, Math.Min(result.Length, 24)); + } + + /// + /// Initializes a new instance of the . + /// + /// The scope. + /// The kind. + /// The sku. + /// The parent. + /// The name. + public StorageAccount(IConstruct scope, StorageKind kind, StorageSkuName sku, ResourceGroup? parent = null, string name = "sa") + : base(scope, parent, GetName(scope, name), ResourceTypeName, "2022-09-01", ArmStorageModelFactory.StorageAccountData( + name: GetName(scope, name), + resourceType: ResourceTypeName, + location: Environment.GetEnvironmentVariable("AZURE_LOCATION") ?? AzureLocation.WestUS, + sku: new StorageSku(sku), + kind: StorageKind.StorageV2)) + { + } + + /// + protected override Resource? FindParentInScope(IConstruct scope) + { + var result = base.FindParentInScope(scope); + if (result is null) + { + result = scope.GetOrAddResourceGroup(); + } + return result; + } + } +} diff --git a/sdk/provisioning/Azure.Provisioning/src/storage/StorageExtensions.cs b/sdk/provisioning/Azure.Provisioning/src/storage/StorageExtensions.cs new file mode 100644 index 0000000000000..8294472b04a76 --- /dev/null +++ b/sdk/provisioning/Azure.Provisioning/src/storage/StorageExtensions.cs @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Azure.Provisioning.ResourceManager; +using Azure.ResourceManager.Storage.Models; + +namespace Azure.Provisioning.Storage +{ + /// + /// Extension methods for . + /// + public static class StorageExtensions + { + /// + /// Adds a to the construct. + /// + /// The scope. + /// The kind. + /// The sku. + /// The parent. + /// The name. + /// + public static StorageAccount AddStorageAccount(this IConstruct scope, StorageKind kind, StorageSkuName sku, ResourceGroup? parent = null, string name = "sa") + { + return new StorageAccount(scope, kind, sku, parent, name); + } + + /// + /// Adds a to the construct. + /// + /// The scope. + /// The name. + /// + public static BlobService AddBlobService(this IConstruct scope, string name = "blob") + { + return new BlobService(scope, name); + } + } +} diff --git a/sdk/provisioning/Azure.Provisioning/tests/Infrastructure/StorageBlobDefaults/main.bicep b/sdk/provisioning/Azure.Provisioning/tests/Infrastructure/StorageBlobDefaults/main.bicep new file mode 100644 index 0000000000000..1ac3d3aacd332 --- /dev/null +++ b/sdk/provisioning/Azure.Provisioning/tests/Infrastructure/StorageBlobDefaults/main.bicep @@ -0,0 +1,31 @@ +targetScope = subscription + + +resource resourceGroup_I6QNkoPsb 'Microsoft.Resources/resourceGroups@2023-07-01' = { + name: 'rg-TEST' + location: 'westus' + tags: { + azd-env-name: 'TEST' + } +} + +resource storageAccount_k7HxHnTvM 'Microsoft.Storage/storageAccounts@2022-09-01' = { + scope: resourceGroup_I6QNkoPsb + name: 'photoAcct-bda380cf-8cdb-' + location: 'westus' + sku: { + name: 'Premium_LRS' + } + kind: 'StorageV2' + properties: { + } +} + +resource blobService_BvgLmmmbK 'Microsoft.Storage/storageAccounts/blobServices@2022-09-01' = { + parent: storageAccount_k7HxHnTvM + name: 'photos-TEST' + properties: { + cors: { + } + } +} diff --git a/sdk/provisioning/Azure.Provisioning/tests/Infrastructure/StorageBlobDropDown/main.bicep b/sdk/provisioning/Azure.Provisioning/tests/Infrastructure/StorageBlobDropDown/main.bicep new file mode 100644 index 0000000000000..7f471daa3d867 --- /dev/null +++ b/sdk/provisioning/Azure.Provisioning/tests/Infrastructure/StorageBlobDropDown/main.bicep @@ -0,0 +1,34 @@ +targetScope = subscription + + +resource resourceGroup_I6QNkoPsb 'Microsoft.Resources/resourceGroups@2023-07-01' = { + name: 'rg-TEST' + location: 'westus' + tags: { + azd-env-name: 'TEST' + } +} + +resource storageAccount_9gvCV8M9t 'Microsoft.Storage/storageAccounts@2022-09-01' = { + scope: resourceGroup_I6QNkoPsb + name: 'photoAcct-464eb449-f1cd-' + location: 'westus' + sku: { + name: 'Premium_LRS' + } + kind: 'StorageV2' + properties: { + } +} + +resource blobService_8xlkwSZNm 'Microsoft.Storage/storageAccounts/blobServices@2022-09-01' = { + parent: storageAccount_9gvCV8M9t + name: 'photos-TEST' + properties: { + cors: { + } + deleteRetentionPolicy: { + enabled: true + } + } +} diff --git a/sdk/provisioning/Azure.Provisioning/tests/ProvisioningTests.cs b/sdk/provisioning/Azure.Provisioning/tests/ProvisioningTests.cs index 3f86d7c686d7a..e319d2b55b44b 100644 --- a/sdk/provisioning/Azure.Provisioning/tests/ProvisioningTests.cs +++ b/sdk/provisioning/Azure.Provisioning/tests/ProvisioningTests.cs @@ -10,6 +10,8 @@ using Azure.Provisioning.KeyVaults; using Azure.Provisioning.Sql; using Azure.Provisioning.Resources; +using Azure.Provisioning.Storage; +using Azure.ResourceManager.Storage.Models; namespace Azure.Provisioning.Tests { @@ -93,6 +95,28 @@ public void WebSiteUsingL3() infra.Build(GetOutputPath()); } + [Test] + public void StorageBlobDefaults() + { + var infra = new TestInfrastructure(); + infra.AddStorageAccount(name: "photoAcct", sku: StorageSkuName.PremiumLrs, kind: StorageKind.BlockBlobStorage); + infra.AddBlobService(name: "photos"); + infra.Build(GetOutputPath()); + } + + [Test] + public void StorageBlobDropDown() + { + var infra = new TestInfrastructure(); + infra.AddStorageAccount(name: "photoAcct", sku: StorageSkuName.PremiumLrs, kind: StorageKind.BlockBlobStorage); + var blob = infra.AddBlobService(name: "photos"); + blob.Properties.DeleteRetentionPolicy = new DeleteRetentionPolicy() + { + IsEnabled = true + }; + infra.Build(GetOutputPath()); + } + private static string GetGitRoot() { ProcessStartInfo startInfo = new ProcessStartInfo