Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make AddDependency public and use project ref for ease of testing #43257

Merged
merged 2 commits into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ public abstract partial class Resource : System.ClientModel.Primitives.IPersista
protected object ResourceData { get { throw null; } }
public Azure.Provisioning.IConstruct Scope { get { throw null; } }
public string Version { get { throw null; } }
public void AddDependency(Azure.Provisioning.Resource resource) { }
public Azure.Provisioning.RoleAssignment AssignRole(Azure.Provisioning.RoleDefinition roleDefinition, System.Guid? principalId = default(System.Guid?), Azure.ResourceManager.Authorization.Models.RoleManagementPrincipalType? principalType = default(Azure.ResourceManager.Authorization.Models.RoleManagementPrincipalType?)) { throw null; }
protected virtual Azure.Provisioning.Resource? FindParentInScope(Azure.Provisioning.IConstruct scope) { throw null; }
protected virtual string GetAzureName(Azure.Provisioning.IConstruct scope, string resourceName) { throw null; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ public abstract partial class Resource : System.ClientModel.Primitives.IPersista
protected object ResourceData { get { throw null; } }
public Azure.Provisioning.IConstruct Scope { get { throw null; } }
public string Version { get { throw null; } }
public void AddDependency(Azure.Provisioning.Resource resource) { }
public Azure.Provisioning.RoleAssignment AssignRole(Azure.Provisioning.RoleDefinition roleDefinition, System.Guid? principalId = default(System.Guid?), Azure.ResourceManager.Authorization.Models.RoleManagementPrincipalType? principalType = default(Azure.ResourceManager.Authorization.Models.RoleManagementPrincipalType?)) { throw null; }
protected virtual Azure.Provisioning.Resource? FindParentInScope(Azure.Provisioning.IConstruct scope) { throw null; }
protected virtual string GetAzureName(Azure.Provisioning.IConstruct scope, string resourceName) { throw null; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ public abstract partial class Resource : System.ClientModel.Primitives.IPersista
protected object ResourceData { get { throw null; } }
public Azure.Provisioning.IConstruct Scope { get { throw null; } }
public string Version { get { throw null; } }
public void AddDependency(Azure.Provisioning.Resource resource) { }
public Azure.Provisioning.RoleAssignment AssignRole(Azure.Provisioning.RoleDefinition roleDefinition, System.Guid? principalId = default(System.Guid?), Azure.ResourceManager.Authorization.Models.RoleManagementPrincipalType? principalType = default(Azure.ResourceManager.Authorization.Models.RoleManagementPrincipalType?)) { throw null; }
protected virtual Azure.Provisioning.Resource? FindParentInScope(Azure.Provisioning.IConstruct scope) { throw null; }
protected virtual string GetAzureName(Azure.Provisioning.IConstruct scope, string resourceName) { throw null; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ public abstract partial class Resource : System.ClientModel.Primitives.IPersista
protected object ResourceData { get { throw null; } }
public Azure.Provisioning.IConstruct Scope { get { throw null; } }
public string Version { get { throw null; } }
public void AddDependency(Azure.Provisioning.Resource resource) { }
public Azure.Provisioning.RoleAssignment AssignRole(Azure.Provisioning.RoleDefinition roleDefinition, System.Guid? principalId = default(System.Guid?), Azure.ResourceManager.Authorization.Models.RoleManagementPrincipalType? principalType = default(Azure.ResourceManager.Authorization.Models.RoleManagementPrincipalType?)) { throw null; }
protected virtual Azure.Provisioning.Resource? FindParentInScope(Azure.Provisioning.IConstruct scope) { throw null; }
protected virtual string GetAzureName(Azure.Provisioning.IConstruct scope, string resourceName) { throw null; }
Expand Down
2 changes: 1 addition & 1 deletion sdk/provisioning/Azure.Provisioning/assets.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "net",
"TagPrefix": "net/provisioning/Azure.Provisioning",
"Tag": "net/provisioning/Azure.Provisioning_6da137c164"
"Tag": "net/provisioning/Azure.Provisioning_3336ebb5fd"
}
17 changes: 13 additions & 4 deletions sdk/provisioning/Azure.Provisioning/src/ModuleInfrastructure.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ public void Write(string? outputPath = null)
outputPath ??= $".\\{GetType().Name}";
outputPath = Path.GetFullPath(outputPath);

WriteBicepFile(_rootConstruct!, outputPath);
WriteBicepFile(_rootConstruct, outputPath);
if (_rootConstruct == null)
{
return;
}

var queue = new Queue<ModuleConstruct>();
queue.Enqueue(_rootConstruct!);
Expand Down Expand Up @@ -190,16 +194,21 @@ private void WriteConstructsByLevel(Queue<ModuleConstruct> constructs, string ou
}
}

private string GetFilePath(ModuleConstruct construct, string outputPath)
private string GetFilePath(ModuleConstruct? construct, string outputPath)
{
string fileName = construct.IsRoot ? Path.Combine(outputPath, "main.bicep") : Path.Combine(outputPath, "resources", construct.Name, $"{construct.Name}.bicep");
string fileName = construct == null || construct.IsRoot ? Path.Combine(outputPath, "main.bicep") : Path.Combine(outputPath, "resources", construct.Name, $"{construct.Name}.bicep");
Directory.CreateDirectory(Path.GetDirectoryName(fileName)!);
return fileName;
}

private void WriteBicepFile(ModuleConstruct construct, string outputPath)
private void WriteBicepFile(ModuleConstruct? construct, string outputPath)
{
using var stream = new FileStream(GetFilePath(construct, outputPath), FileMode.Create);
// just create an empty file if there is no construct
if (construct == null)
JoshLove-msft marked this conversation as resolved.
Show resolved Hide resolved
{
return;
}
#if NET6_0_OR_GREATER
stream.Write(construct.SerializeModule());
#else
Expand Down
6 changes: 5 additions & 1 deletion sdk/provisioning/Azure.Provisioning/src/Resource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ public abstract class Resource : IPersistableModel<Resource>

private IList<Resource> Dependencies { get; }

internal void AddDependency(Resource resource)
/// <summary>
/// Adds a dependency to the resource.
/// </summary>
/// <param name="resource">The dependency for this resource.</param>
public void AddDependency(Resource resource)
{
Dependencies.Add(resource);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
targetScope = 'resourceGroup'

@description('')
param location string = resourceGroup().location


resource storageAccount_7EH24TZOS 'Microsoft.Storage/storageAccounts@2022-09-01' = {
name: toLower(take('photoAcct${uniqueString(resourceGroup().id)}', 24))
location: location
sku: {
name: 'Premium_LRS'
}
kind: 'BlockBlobStorage'
properties: {
networkAcls: {
defaultAction: 'Deny'
}
}
}

resource storageAccount_GoC2YPRJs 'Microsoft.Storage/storageAccounts@2022-09-01' = {
dependsOn: [
storageAccount_7EH24TZOS
]
name: toLower(take('photoAcct2${uniqueString(resourceGroup().id)}', 24))
location: location
sku: {
name: 'Premium_LRS'
}
kind: 'BlockBlobStorage'
properties: {
networkAcls: {
defaultAction: 'Deny'
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
targetScope = 'subscription'


resource resourceGroup_I6QNkoPsb 'Microsoft.Resources/resourceGroups@2023-07-01' = {
name: 'rg-TEST'
location: 'westus'
tags: {
'azd-env-name': 'TEST'
}
}

module rg_TEST_module './resources/rg_TEST_module/rg_TEST_module.bicep' = {
name: 'rg_TEST_module'
scope: resourceGroup_I6QNkoPsb
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

resource userAssignedIdentity_AHWXCnFeG 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = {
name: 'existingUserAssignedIdentity'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
targetScope = 'resourceGroup'
JoshLove-msft marked this conversation as resolved.
Show resolved Hide resolved

@description('')
param location string = resourceGroup().location

@description('')
param principalId string


resource storageAccount_7EH24TZOS 'Microsoft.Storage/storageAccounts@2022-09-01' = {
name: toLower(take('photoAcct${uniqueString(resourceGroup().id)}', 24))
location: location
sku: {
name: 'Premium_LRS'
}
kind: 'BlockBlobStorage'
properties: {
networkAcls: {
defaultAction: 'Deny'
}
}
}

resource blobService_7QL3qUuBS 'Microsoft.Storage/storageAccounts/blobServices@2022-09-01' = {
parent: storageAccount_7EH24TZOS
name: 'default'
properties: {
}
}

resource roleAssignment_NfInNFBlY 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
scope: storageAccount_7EH24TZOS
name: guid(storageAccount_7EH24TZOS.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe'))
properties: {
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')
principalId: principalId
principalType: 'ServicePrincipal'
}
}

resource roleAssignment_cmAstwnTk 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
scope: storageAccount_7EH24TZOS
name: guid(storageAccount_7EH24TZOS.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88'))
properties: {
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88')
principalId: principalId
principalType: 'ServicePrincipal'
}
}

resource roleAssignment_4GhzPkC6K 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
scope: storageAccount_7EH24TZOS
name: guid(storageAccount_7EH24TZOS.id, '00000000-0000-0000-0000-000000000000', subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3'))
properties: {
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3')
principalId: '00000000-0000-0000-0000-000000000000'
principalType: 'User'
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
targetScope = 'subscription'


resource resourceGroup_I6QNkoPsb 'Microsoft.Resources/resourceGroups@2023-07-01' = {
name: 'rg-TEST'
location: 'westus'
tags: {
'azd-env-name': 'TEST'
}
}

module rg_TEST_module './resources/rg_TEST_module/rg_TEST_module.bicep' = {
name: 'rg_TEST_module'
scope: resourceGroup_I6QNkoPsb
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@

resource storageAccount_ZnnWSenAP 'Microsoft.Storage/storageAccounts@2022-09-01' = {
name: toLower(take('photoAcct${uniqueString(resourceGroup().id)}', 24))
location: 'westus'
sku: {
name: 'Premium_LRS'
}
kind: 'BlockBlobStorage'
properties: {
networkAcls: {
defaultAction: 'Deny'
}
}
}

resource blobService_wAcYakiP0 'Microsoft.Storage/storageAccounts/blobServices@2022-09-01' = {
parent: storageAccount_ZnnWSenAP
name: 'default'
properties: {
}
}

resource roleAssignment_q3YvdxEC7 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
scope: storageAccount_ZnnWSenAP
name: guid(storageAccount_ZnnWSenAP.id, '00000000-0000-0000-0000-000000000000', subscriptionResourceId('00000000-0000-0000-0000-000000000000', 'Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe'))
properties: {
roleDefinitionId: subscriptionResourceId('00000000-0000-0000-0000-000000000000', 'Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')
principalId: '00000000-0000-0000-0000-000000000000'
principalType: 'ServicePrincipal'
}
}

resource roleAssignment_c4BGrZguw 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
scope: storageAccount_ZnnWSenAP
name: guid(storageAccount_ZnnWSenAP.id, '00000000-0000-0000-0000-000000000000', subscriptionResourceId('00000000-0000-0000-0000-000000000000', 'Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88'))
properties: {
roleDefinitionId: subscriptionResourceId('00000000-0000-0000-0000-000000000000', 'Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88')
principalId: '00000000-0000-0000-0000-000000000000'
principalType: 'ServicePrincipal'
}
}

resource roleAssignment_YUoGSZS0y 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
scope: storageAccount_ZnnWSenAP
name: guid(storageAccount_ZnnWSenAP.id, '00000000-0000-0000-0000-000000000000', subscriptionResourceId('00000000-0000-0000-0000-000000000000', 'Microsoft.Authorization/roleDefinitions', '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3'))
properties: {
roleDefinitionId: subscriptionResourceId('00000000-0000-0000-0000-000000000000', 'Microsoft.Authorization/roleDefinitions', '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3')
principalId: '00000000-0000-0000-0000-000000000000'
principalType: 'User'
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
targetScope = 'resourceGroup'

@description('')
param location string = resourceGroup().location


resource storageAccount_7EH24TZOS 'Microsoft.Storage/storageAccounts@2022-09-01' = {
name: toLower(take('photoAcct${uniqueString(resourceGroup().id)}', 24))
location: location
sku: {
name: 'Premium_LRS'
}
kind: 'BlockBlobStorage'
properties: {
networkAcls: {
defaultAction: 'Deny'
}
}
}

resource blobService_7QL3qUuBS 'Microsoft.Storage/storageAccounts/blobServices@2022-09-01' = {
parent: storageAccount_7EH24TZOS
name: 'default'
properties: {
}
}

resource roleAssignment_Xx3s4qhkk 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
scope: storageAccount_7EH24TZOS
name: guid(storageAccount_7EH24TZOS.id, '00000000-0000-0000-0000-000000000000', subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe'))
properties: {
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')
principalId: '00000000-0000-0000-0000-000000000000'
principalType: 'ServicePrincipal'
}
}

resource roleAssignment_LfCpykUe9 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
scope: storageAccount_7EH24TZOS
name: guid(storageAccount_7EH24TZOS.id, '00000000-0000-0000-0000-000000000000', subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88'))
properties: {
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88')
principalId: '00000000-0000-0000-0000-000000000000'
principalType: 'ServicePrincipal'
}
}

resource roleAssignment_4GhzPkC6K 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
scope: storageAccount_7EH24TZOS
name: guid(storageAccount_7EH24TZOS.id, '00000000-0000-0000-0000-000000000000', subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3'))
properties: {
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3')
principalId: '00000000-0000-0000-0000-000000000000'
principalType: 'User'
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
targetScope = 'resourceGroup'

@description('')
param location string = resourceGroup().location


resource userAssignedIdentity_gswVmGJeD 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
name: toLower(take('useridentity${uniqueString(resourceGroup().id)}', 24))
location: location
properties: {
}
}
21 changes: 21 additions & 0 deletions sdk/provisioning/Azure.Provisioning/tests/ProvisioningTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,27 @@ public async Task UserAssignedIdentities()
await ValidateBicepAsync(interactiveMode: true);
}

[RecordedTest]
public async Task DependentResources()
{
TestInfrastructure infra = new TestInfrastructure(configuration: new Configuration { UseInteractiveMode = true });
var sa1 = infra.AddStorageAccount(name: "photoAcct", sku: StorageSkuName.PremiumLrs, kind: StorageKind.BlockBlobStorage);
var sa2 = infra.AddStorageAccount(name: "photoAcct2", sku: StorageSkuName.PremiumLrs, kind: StorageKind.BlockBlobStorage);
sa2.AddDependency(sa1);

infra.Build(GetOutputPath());

await ValidateBicepAsync(interactiveMode: true);
}

[RecordedTest]
public async Task EmptyConstructDoesNotThrow()
{
TestInfrastructure infra = new TestInfrastructure();
infra.Build(GetOutputPath());
await ValidateBicepAsync();
}

[RecordedTest]
public async Task ExistingUserAssignedIdentityResource()
{
Expand Down
2 changes: 1 addition & 1 deletion sdk/provisioning/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
</PropertyGroup>

<ItemGroup Condition="'$(AssemblyName)' != 'Azure.Provisioning'">
<PackageReference Include="Azure.Provisioning" />
<ProjectReference Include="../../Azure.Provisioning/src/Azure.Provisioning.csproj" />
</ItemGroup>

<ItemGroup>
Expand Down