Beispiel #1
0
        public static LanguageExpression FormatLocallyScopedResourceId(SemanticModel.SemanticModel semanticModel, string fullyQualifiedType, IEnumerable <LanguageExpression> nameSegments)
        {
            var initialArgs = new JTokenExpression(fullyQualifiedType).AsEnumerable();

            switch (semanticModel.TargetScope)
            {
            case ResourceScopeType.TenantScope:
                var tenantArgs = initialArgs.Concat(nameSegments);
                return(new FunctionExpression("tenantResourceId", tenantArgs.ToArray(), new LanguageExpression[0]));

            case ResourceScopeType.SubscriptionScope:
                var subscriptionArgs = initialArgs.Concat(nameSegments);
                return(new FunctionExpression("subscriptionResourceId", subscriptionArgs.ToArray(), new LanguageExpression[0]));

            case ResourceScopeType.ResourceGroupScope:
                var resourceGroupArgs = initialArgs.Concat(nameSegments);
                return(new FunctionExpression("resourceId", resourceGroupArgs.ToArray(), new LanguageExpression[0]));

            case ResourceScopeType.ManagementGroupScope:
                // We need to do things slightly differently for Management Groups, because there is no IL to output for "Give me a fully-qualified resource id at the current scope",
                // and we don't even have a mechanism for reliably getting the current scope (e.g. something like 'deployment().scope'). There are plans to add a managementGroupResourceId function,
                // but until we have it, we should generate unqualified resource Ids. There should not be a risk of collision, because we do not allow mixing of resource scopes in a single bicep file.
                return(ExpressionConverter.GenerateUnqualifiedResourceId(fullyQualifiedType, nameSegments));

            default:
                // this should have already been caught during compilation
                throw new InvalidOperationException($"Invalid target scope {semanticModel.TargetScope} for module");
            }
        }
Beispiel #2
0
        public static LanguageExpression FormatCrossScopeResourceId(ExpressionConverter expressionConverter, ScopeData scopeData, string fullyQualifiedType, IEnumerable <LanguageExpression> nameSegments)
        {
            var arguments = new List <LanguageExpression>();

            switch (scopeData.RequestedScope)
            {
            case ResourceScopeType.TenantScope:
                arguments.Add(new JTokenExpression(fullyQualifiedType));
                arguments.AddRange(nameSegments);

                return(new FunctionExpression("tenantResourceId", arguments.ToArray(), new LanguageExpression[0]));

            case ResourceScopeType.SubscriptionScope:
                if (scopeData.SubscriptionIdProperty != null)
                {
                    arguments.Add(expressionConverter.ConvertExpression(scopeData.SubscriptionIdProperty));
                }
                arguments.Add(new JTokenExpression(fullyQualifiedType));
                arguments.AddRange(nameSegments);

                return(new FunctionExpression("subscriptionResourceId", arguments.ToArray(), new LanguageExpression[0]));

            case ResourceScopeType.ResourceGroupScope:
                // We avoid using the 'resourceId' function at all here, because its behavior differs depending on the scope that it is called FROM.
                LanguageExpression scope;
                if (scopeData.SubscriptionIdProperty == null)
                {
                    if (scopeData.ResourceGroupProperty == null)
                    {
                        scope = new FunctionExpression("resourceGroup", new LanguageExpression[0], new LanguageExpression[] { new JTokenExpression("id") });
                    }
                    else
                    {
                        var subscriptionId = new FunctionExpression("subscription", new LanguageExpression[0], new LanguageExpression[] { new JTokenExpression("subscriptionId") });
                        var resourceGroup  = expressionConverter.ConvertExpression(scopeData.ResourceGroupProperty);
                        scope = ExpressionConverter.GenerateResourceGroupScope(subscriptionId, resourceGroup);
                    }
                }
                else
                {
                    if (scopeData.ResourceGroupProperty == null)
                    {
                        throw new NotImplementedException($"Cannot format resourceId with non-null subscription and null resourceGroup");
                    }

                    var subscriptionId = expressionConverter.ConvertExpression(scopeData.SubscriptionIdProperty);
                    var resourceGroup  = expressionConverter.ConvertExpression(scopeData.ResourceGroupProperty);
                    scope = ExpressionConverter.GenerateResourceGroupScope(subscriptionId, resourceGroup);
                }

                // We've got to DIY it, unfortunately. The resourceId() function behaves differently when used at different scopes, so is unsuitable here.
                return(ExpressionConverter.GenerateScopedResourceId(scope, fullyQualifiedType, nameSegments));

            case ResourceScopeType.ManagementGroupScope:
                if (scopeData.ManagementGroupNameProperty != null)
                {
                    var managementGroupName  = expressionConverter.ConvertExpression(scopeData.ManagementGroupNameProperty);
                    var managementGroupScope = ExpressionConverter.GetManagementGroupScopeExpression(managementGroupName);

                    return(ExpressionConverter.GenerateScopedResourceId(managementGroupScope, fullyQualifiedType, nameSegments));
                }

                // We need to do things slightly differently for Management Groups, because there is no IL to output for "Give me a fully-qualified resource id at the current scope",
                // and we don't even have a mechanism for reliably getting the current scope (e.g. something like 'deployment().scope'). There are plans to add a managementGroupResourceId function,
                // but until we have it, we should generate unqualified resource Ids. There should not be a risk of collision, because we do not allow mixing of resource scopes in a single bicep file.
                return(ExpressionConverter.GenerateUnqualifiedResourceId(fullyQualifiedType, nameSegments));

            default:
                throw new NotImplementedException($"Cannot format resourceId for scope {scopeData.RequestedScope}");
            }
        }