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

Use tenant function and resourceGroup().location #42257

Merged
merged 3 commits into from
Feb 28, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,15 @@ public static partial class CdkExtensions
public static T? GetSingleResourceInScope<T>(this Azure.Provisioning.IConstruct construct) where T : Azure.Provisioning.Resource { throw null; }
public static T? GetSingleResource<T>(this Azure.Provisioning.IConstruct construct) where T : Azure.Provisioning.Resource { throw null; }
}
public partial class Configuration
{
public Configuration() { }
public bool UsePromptMode { get { throw null; } set { } }
}
public abstract partial class Construct : Azure.Provisioning.IConstruct
{
protected Construct(Azure.Provisioning.IConstruct? scope, string name, Azure.Provisioning.ConstructScope constructScope = Azure.Provisioning.ConstructScope.ResourceGroup, System.Guid? tenantId = default(System.Guid?), System.Guid? subscriptionId = default(System.Guid?), string? envName = null, Azure.Provisioning.ResourceManager.ResourceGroup? resourceGroup = null) { }
public Azure.Provisioning.Configuration? Configuration { get { throw null; } }
public Azure.Provisioning.ConstructScope ConstructScope { get { throw null; } }
public string EnvironmentName { get { throw null; } }
public string Name { get { throw null; } }
Expand All @@ -34,6 +40,7 @@ public enum ConstructScope
}
public partial interface IConstruct
{
Azure.Provisioning.Configuration? Configuration { get; }
Azure.Provisioning.ConstructScope ConstructScope { get; }
string EnvironmentName { get; }
string Name { get; }
Expand All @@ -52,7 +59,7 @@ public partial interface IConstruct
}
public abstract partial class Infrastructure : Azure.Provisioning.Construct
{
public Infrastructure(Azure.Provisioning.ConstructScope constructScope = Azure.Provisioning.ConstructScope.Subscription, System.Guid? tenantId = default(System.Guid?), System.Guid? subscriptionId = default(System.Guid?), string? envName = null, bool useAnonymousResourceGroup = false) : base (default(Azure.Provisioning.IConstruct), default(string), default(Azure.Provisioning.ConstructScope), default(System.Guid?), default(System.Guid?), default(string), default(Azure.Provisioning.ResourceManager.ResourceGroup)) { }
public Infrastructure(Azure.Provisioning.ConstructScope constructScope = Azure.Provisioning.ConstructScope.Subscription, System.Guid? tenantId = default(System.Guid?), System.Guid? subscriptionId = default(System.Guid?), string? envName = null, Azure.Provisioning.Configuration? configuration = null) : base (default(Azure.Provisioning.IConstruct), default(string), default(Azure.Provisioning.ConstructScope), default(System.Guid?), default(System.Guid?), default(string), default(Azure.Provisioning.ResourceManager.ResourceGroup)) { }
public void Build(string? outputPath = null) { }
}
public partial class Output
Expand Down Expand Up @@ -95,6 +102,7 @@ public abstract partial class Resource<T> : Azure.Provisioning.Resource where T
public T Properties { get { throw null; } }
public Azure.Provisioning.Output AddOutput(System.Linq.Expressions.Expression<System.Func<T, object?>> propertySelector, string outputName, bool isLiteral = false, bool isSecure = false) { throw null; }
public void AssignParameter(System.Linq.Expressions.Expression<System.Func<T, object?>> propertySelector, Azure.Provisioning.Parameter parameter) { }
public void AssignProperty(System.Linq.Expressions.Expression<System.Func<T, object?>> propertySelector, string propertyValue) { }
}
}
namespace Azure.Provisioning.AppConfiguration
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,15 @@ public static partial class CdkExtensions
public static T? GetSingleResourceInScope<T>(this Azure.Provisioning.IConstruct construct) where T : Azure.Provisioning.Resource { throw null; }
public static T? GetSingleResource<T>(this Azure.Provisioning.IConstruct construct) where T : Azure.Provisioning.Resource { throw null; }
}
public partial class Configuration
{
public Configuration() { }
public bool UsePromptMode { get { throw null; } set { } }
}
public abstract partial class Construct : Azure.Provisioning.IConstruct
{
protected Construct(Azure.Provisioning.IConstruct? scope, string name, Azure.Provisioning.ConstructScope constructScope = Azure.Provisioning.ConstructScope.ResourceGroup, System.Guid? tenantId = default(System.Guid?), System.Guid? subscriptionId = default(System.Guid?), string? envName = null, Azure.Provisioning.ResourceManager.ResourceGroup? resourceGroup = null) { }
public Azure.Provisioning.Configuration? Configuration { get { throw null; } }
public Azure.Provisioning.ConstructScope ConstructScope { get { throw null; } }
public string EnvironmentName { get { throw null; } }
public string Name { get { throw null; } }
Expand All @@ -34,6 +40,7 @@ public enum ConstructScope
}
public partial interface IConstruct
{
Azure.Provisioning.Configuration? Configuration { get; }
Azure.Provisioning.ConstructScope ConstructScope { get; }
string EnvironmentName { get; }
string Name { get; }
Expand All @@ -52,7 +59,7 @@ public partial interface IConstruct
}
public abstract partial class Infrastructure : Azure.Provisioning.Construct
{
public Infrastructure(Azure.Provisioning.ConstructScope constructScope = Azure.Provisioning.ConstructScope.Subscription, System.Guid? tenantId = default(System.Guid?), System.Guid? subscriptionId = default(System.Guid?), string? envName = null, bool useAnonymousResourceGroup = false) : base (default(Azure.Provisioning.IConstruct), default(string), default(Azure.Provisioning.ConstructScope), default(System.Guid?), default(System.Guid?), default(string), default(Azure.Provisioning.ResourceManager.ResourceGroup)) { }
public Infrastructure(Azure.Provisioning.ConstructScope constructScope = Azure.Provisioning.ConstructScope.Subscription, System.Guid? tenantId = default(System.Guid?), System.Guid? subscriptionId = default(System.Guid?), string? envName = null, Azure.Provisioning.Configuration? configuration = null) : base (default(Azure.Provisioning.IConstruct), default(string), default(Azure.Provisioning.ConstructScope), default(System.Guid?), default(System.Guid?), default(string), default(Azure.Provisioning.ResourceManager.ResourceGroup)) { }
public void Build(string? outputPath = null) { }
}
public partial class Output
Expand Down Expand Up @@ -95,6 +102,7 @@ public abstract partial class Resource<T> : Azure.Provisioning.Resource where T
public T Properties { get { throw null; } }
public Azure.Provisioning.Output AddOutput(System.Linq.Expressions.Expression<System.Func<T, object?>> propertySelector, string outputName, bool isLiteral = false, bool isSecure = false) { throw null; }
public void AssignParameter(System.Linq.Expressions.Expression<System.Func<T, object?>> propertySelector, Azure.Provisioning.Parameter parameter) { }
public void AssignProperty(System.Linq.Expressions.Expression<System.Func<T, object?>> propertySelector, string propertyValue) { }
}
}
namespace Azure.Provisioning.AppConfiguration
Expand Down
18 changes: 18 additions & 0 deletions sdk/provisioning/Azure.Provisioning/src/Configuration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

namespace Azure.Provisioning
{
/// <summary>
/// Configuration for the provisioning.
/// </summary>
#pragma warning disable AZC0012 // Avoid single word type names
public class Configuration
#pragma warning restore AZC0012 // Avoid single word type names
{
/// <summary>
/// Whether to use prompt mode.
/// </summary>
public bool UsePromptMode { get; set; }
}
}
26 changes: 26 additions & 0 deletions sdk/provisioning/Azure.Provisioning/src/Construct.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,19 @@ public abstract class Construct : IConstruct
public Tenant Root { get; }
/// <inheritdoc/>
public ConstructScope ConstructScope { get; }
/// <inheritdoc/>
public Configuration? Configuration
{
get
{
return Scope == null ? _configuration : Scope.Configuration;
}
internal set
{
_configuration = value;
}
}
private Configuration? _configuration;

/// <summary>
/// Initializes a new instance of the <see cref="Construct"/> class.
Expand Down Expand Up @@ -91,6 +104,19 @@ private string GetEnvironmentName()
return _environmentName is null ? Scope!.EnvironmentName : _environmentName;
}

/// <summary>
///
/// </summary>
/// <returns></returns>
internal Infrastructure? FindInfrastructure()
{
if (this is Infrastructure infrastructure)
{
return infrastructure;
}
return ((Construct?)Scope)?.FindInfrastructure();
}

/// <summary>
/// Registers an existing resource with this construct that will be used by other resources in the construct.
/// </summary>
Expand Down
5 changes: 5 additions & 0 deletions sdk/provisioning/Azure.Provisioning/src/IConstruct.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ public interface IConstruct
/// </summary>
public Subscription? Subscription { get; }

/// <summary>
/// Gets the configuration for the construct.
/// </summary>
public Configuration? Configuration { get; }

/// <summary>
/// Gets the parent of the construct.
/// </summary>
Expand Down
8 changes: 3 additions & 5 deletions sdk/provisioning/Azure.Provisioning/src/Infrastructure.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,13 @@ public abstract class Infrastructure : Construct
/// <param name="tenantId">The tenant id to use. If not passed in will try to load from AZURE_TENANT_ID environment variable.</param>
/// <param name="subscriptionId">The subscription id to use. If not passed, the subscription will be loaded from the deployment context.</param>
/// <param name="envName">The environment name to use. If not passed in will try to load from AZURE_ENV_NAME environment variable.</param>
/// <param name="useAnonymousResourceGroup">Whether to use a single anonymous resource group. When deploying the resource group will need to be provided.</param>
public Infrastructure(ConstructScope constructScope = ConstructScope.Subscription, Guid? tenantId = null, Guid? subscriptionId = null, string? envName = null, bool useAnonymousResourceGroup = false)
/// <param name="configuration">The configuration for the infrastructure.</param>
public Infrastructure(ConstructScope constructScope = ConstructScope.Subscription, Guid? tenantId = null, Guid? subscriptionId = null, string? envName = null, Configuration? configuration = null)
: base(null, "default", constructScope, tenantId, subscriptionId, envName ?? Environment.GetEnvironmentVariable("AZURE_ENV_NAME") ?? throw new Exception("No environment variable found named 'AZURE_ENV_NAME'"), resourceGroup: null)
{
UseAnonymousResourceGroup = useAnonymousResourceGroup;
Configuration = configuration;
}

internal bool UseAnonymousResourceGroup { get; }

/// <summary>
/// Converts the infrastructure to Bicep files.
/// </summary>
Expand Down
12 changes: 0 additions & 12 deletions sdk/provisioning/Azure.Provisioning/src/ModuleConstruct.cs
Original file line number Diff line number Diff line change
Expand Up @@ -254,18 +254,6 @@ private static void WriteLines(int depth, BinaryData data, MemoryStream stream,
{
start++;
}
line = line.Slice(start);
int end = line.IndexOf(':');
if (end > 0)
{
// foo: 1
// foo: 'something.url'
string name = line.Slice(0, end).ToString();
if (resource.ParameterOverrides.TryGetValue(name, out var value))
{
lineToWrite = $"{new string(' ', start)}{name}: {value}";
}
}
stream.WriteLine($"{indent}{lineToWrite}");
}
}
Expand Down
28 changes: 28 additions & 0 deletions sdk/provisioning/Azure.Provisioning/src/Resource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using Azure.Provisioning.ResourceManager;
using Azure.Provisioning.Resources;
using Azure.ResourceManager;
using Azure.ResourceManager.Models;

namespace Azure.Provisioning
{
Expand All @@ -25,6 +26,8 @@ public abstract class Resource : IPersistableModel<Resource>
{
internal Dictionary<object, Dictionary<string, Parameter>> ParameterOverrides { get; }

private Dictionary<object, Dictionary<string, string>> PropertyOverrides { get; }

private IList<Resource> Dependencies { get; }

internal void AddDependency(Resource resource)
Expand Down Expand Up @@ -85,6 +88,7 @@ protected Resource(IConstruct scope, Resource? parent, string resourceName, Reso
ResourceData = createProperties(azureName);
Version = version;
ParameterOverrides = new Dictionary<object, Dictionary<string, Parameter>>();
PropertyOverrides = new Dictionary<object, Dictionary<string, string>>();
Dependencies = new List<Resource>();
ResourceType = resourceType;
Id = Parent is null
Expand Down Expand Up @@ -161,6 +165,18 @@ private protected void AssignParameter(object instance, string propertyName, Par
Parameters.Add(parameter);
}

private protected void AssignProperty(object instance, string propertyName, string propertyValue)
{
if (PropertyOverrides.TryGetValue(instance, out var overrides))
{
overrides[propertyName] = propertyValue;
}
else
{
PropertyOverrides.Add(instance, new Dictionary<string, string> { { propertyName, propertyValue } });
}
}

/// <summary>
/// Adds an output to the resource.
/// </summary>
Expand Down Expand Up @@ -245,6 +261,18 @@ private BinaryData SerializeModule(ModelReaderWriterOptions options)
}
bicepOptions.ParameterOverrides.Add(parameter.Key, dict);
}
foreach (var propertyOverride in PropertyOverrides)
{
if (!bicepOptions.ParameterOverrides.TryGetValue(propertyOverride.Key, out var dict))
{
dict = new Dictionary<string, string>();
bicepOptions.ParameterOverrides.Add(propertyOverride.Key, dict);
}
foreach (var kvp in propertyOverride.Value)
{
dict.Add(kvp.Key, kvp.Value);
}
}
var data = ModelReaderWriter.Write(ResourceData, bicepOptions).ToMemory();

#if NET6_0_OR_GREATER
Expand Down
34 changes: 32 additions & 2 deletions sdk/provisioning/Azure.Provisioning/src/ResourceOfT.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
using System.Linq;
using System.Linq.Expressions;
using Azure.Core;
using Azure.Provisioning.ResourceManager;
using Azure.ResourceManager.Models;

namespace Azure.Provisioning
{
Expand Down Expand Up @@ -33,10 +35,24 @@ public abstract class Resource<T> : Resource
/// <param name="resourceType">The resourceType.</param>
/// <param name="version">The version.</param>
/// <param name="createProperties">Lambda to create the ARM properties.</param>
protected Resource(IConstruct scope, Resource? parent, string resourceName, ResourceType resourceType, string version, Func<string, T> createProperties)
: base(scope, parent, resourceName, resourceType, version, (name) => createProperties(name))
protected Resource(
IConstruct scope,
Resource? parent,
string resourceName,
ResourceType resourceType,
string version,
Func<string, T> createProperties)
: base(scope, parent, resourceName, resourceType, version, name => createProperties(name))
{
Properties = (T)ResourceData;

// Resources that have a non-RG parent do not require a location value
if (scope.Configuration?.UsePromptMode == true && Parent is ResourceGroup)
{
// We can't use the lambda overload because not all of the T's will inherit from TrackedResourceData
// TODO we may need to add a protected LocationSelector property in the future if there are exceptions to the rule
AssignProperty(Properties, "Location", $"{ResourceGroup.AnonymousResourceGroupName}.location");
}
}

/// <summary>
Expand All @@ -51,6 +67,18 @@ public void AssignParameter(Expression<Func<T, object?>> propertySelector, Param
AssignParameter(instance, name, parameter);
}

/// <summary>
///
/// </summary>
/// <param name="propertySelector"></param>
/// <param name="propertyValue"></param>
/// <exception cref="NotSupportedException"></exception>
public void AssignProperty(Expression<Func<T, object?>> propertySelector, string propertyValue)
{
(object instance, string name, string expression) = EvaluateLambda(propertySelector);
AssignProperty(instance, name, propertyValue);
}

/// <summary>
/// Adds an output to the resource.
/// </summary>
Expand Down Expand Up @@ -113,6 +141,8 @@ private void GetBicepExpression(Expression expression, ref string result)
GetBicepExpression(memberExpression.Expression, ref result);
}
break;
case UnaryExpression unaryExpression:
break;
case MethodCallExpression methodCallExpression:
break; // skip
case ParameterExpression parameterExpression:
Expand Down
5 changes: 4 additions & 1 deletion sdk/provisioning/Azure.Provisioning/src/keyvault/KeyVault.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ public KeyVault(IConstruct scope, ResourceGroup? parent = default, string name =
resourceType: ResourceTypeName,
location: location ?? Environment.GetEnvironmentVariable("AZURE_LOCATION") ?? AzureLocation.WestUS,
properties: ArmKeyVaultModelFactory.KeyVaultProperties(
tenantId: scope.Root.Properties.TenantId!.Value,
sku: new KeyVaultSku(KeyVaultSkuFamily.A, KeyVaultSkuName.Standard),
accessPolicies: Environment.GetEnvironmentVariable("AZURE_PRINCIPAL_ID") is not null ? new List<KeyVaultAccessPolicy>()
{
Expand All @@ -47,6 +46,10 @@ public KeyVault(IConstruct scope, ResourceGroup? parent = default, string name =
enableRbacAuthorization: true)))
{
AddOutput(kv => kv.Properties.VaultUri, "vaultUri");
if (scope.Root.Properties.TenantId == Guid.Empty)
{
AssignProperty(kv => kv.Properties.TenantId, "tenant()");
}
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public static ResourceGroup AddResourceGroup(this IConstruct construct)
throw new InvalidOperationException("ResourceGroup already exists on the construct");
}

return new ResourceGroup(construct, name: construct is Infrastructure { UseAnonymousResourceGroup: true } ? ResourceGroup.AnonymousResourceGroupName : "rg");
return new ResourceGroup(construct, name: construct.Configuration?.UsePromptMode == true ? ResourceGroup.AnonymousResourceGroupName : "rg");
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ public class SqlDatabase : Resource<SqlDatabaseData>
public SqlDatabase(IConstruct scope, SqlServer? parent = null, string name = "db", string version = "2022-08-01-preview", AzureLocation? location = default)
: base(scope, parent, name, ResourceTypeName, version, (name) => ArmSqlModelFactory.SqlDatabaseData(
name: name,
resourceType: ResourceTypeName,
location: location ?? Environment.GetEnvironmentVariable("AZURE_LOCATION") ?? AzureLocation.WestUS))
resourceType: ResourceTypeName))
{
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ resource keyVault_j1ww9730M 'Microsoft.KeyVault/vaults@2023-02-01' = {
name: 'kv-TEST'
location: 'westus'
properties: {
tenantId: '00000000-0000-0000-0000-000000000000'
tenantId: tenant()
sku: {
name: 'standard'
family: 'A'
Expand Down
Loading
Loading