Skip to content

Commit

Permalink
Implement decompilation for the 'scope' property (#1190)
Browse files Browse the repository at this point in the history
  • Loading branch information
anthony-c-martin authored Dec 18, 2020
1 parent 0b7427f commit a19d66c
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 27 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
param hostingPlanName string
param location string = resourceGroup().location

var siteName_var = 'ExampleSite${uniqueString(resourceGroup().id)}'

resource hostingPlanName_resource 'Microsoft.Web/serverfarms@2020-06-01' = {
name: hostingPlanName
location: location
sku: {
tier: 'Free'
name: 'f1'
capacity: 0
}
properties: {
targetWorkerCount: 1
}
}

resource siteName 'Microsoft.Web/sites@2020-06-01' = {
name: siteName_var
location: location
properties: {
serverFarmId: hostingPlanName
}
dependsOn: [
hostingPlanName_resource
]
}

resource siteLock 'Microsoft.Authorization/locks@2016-09-01' = {
name: 'siteLock'
properties: {
level: 'CanNotDelete'
notes: 'Site should not be deleted.'
}
scope: siteName
dependsOn: [
siteName
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"hostingPlanName": {
"type": "string"
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]"
}
},
"variables": {
"siteName": "[concat('ExampleSite', uniqueString(resourceGroup().id))]"
},
"resources": [
{
"type": "Microsoft.Web/serverfarms",
"apiVersion": "2020-06-01",
"name": "[parameters('hostingPlanName')]",
"location": "[parameters('location')]",
"sku": {
"tier": "Free",
"name": "f1",
"capacity": 0
},
"properties": {
"targetWorkerCount": 1
}
},
{
"type": "Microsoft.Web/sites",
"apiVersion": "2020-06-01",
"name": "[variables('siteName')]",
"location": "[parameters('location')]",
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms', parameters('hostingPlanName'))]"
],
"properties": {
"serverFarmId": "[parameters('hostingPlanName')]"
}
},
{
"type": "Microsoft.Authorization/locks",
"apiVersion": "2016-09-01",
"name": "siteLock",
"scope": "[concat('Microsoft.Web/sites/', variables('siteName'))]",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', variables('siteName'))]"
],
"properties": {
"level": "CanNotDelete",
"notes": "Site should not be deleted."
}
}
]
}
82 changes: 55 additions & 27 deletions src/Bicep.Decompiler/TemplateConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -639,28 +639,28 @@ StringSyntax createFakeModulePath(string templateLinkExpression)
return SyntaxHelpers.CreateStringLiteral(filePath);
}

private SyntaxBase? ProcessCondition(JObject resource)
{
JProperty? conditionProperty = TemplateHelpers.GetProperty(resource, "condition");

if (conditionProperty == null)
{
return null;
}

SyntaxBase conditionExpression = ParseJToken(conditionProperty.Value);

if (conditionExpression is not ParenthesizedExpressionSyntax)
{
conditionExpression = new ParenthesizedExpressionSyntax(
SyntaxHelpers.CreateToken(TokenType.LeftParen, "("),
conditionExpression,
SyntaxHelpers.CreateToken(TokenType.RightParen, ")"));
}

return new IfConditionSyntax(
SyntaxHelpers.CreateToken(TokenType.Identifier, "if"),
conditionExpression);
private SyntaxBase? ProcessCondition(JObject resource)
{
JProperty? conditionProperty = TemplateHelpers.GetProperty(resource, "condition");

if (conditionProperty == null)
{
return null;
}

SyntaxBase conditionExpression = ParseJToken(conditionProperty.Value);

if (conditionExpression is not ParenthesizedExpressionSyntax)
{
conditionExpression = new ParenthesizedExpressionSyntax(
SyntaxHelpers.CreateToken(TokenType.LeftParen, "("),
conditionExpression,
SyntaxHelpers.CreateToken(TokenType.RightParen, ")"));
}

return new IfConditionSyntax(
SyntaxHelpers.CreateToken(TokenType.Identifier, "if"),
conditionExpression);
}

private SyntaxBase? ProcessDependsOn(JObject resource)
Expand Down Expand Up @@ -707,7 +707,7 @@ StringSyntax createFakeModulePath(string templateLinkExpression)
return SyntaxHelpers.CreateArray(syntaxItems);
}

private SyntaxBase? TryGetScopeProperty(JObject resource)
private SyntaxBase? TryModuleGetScopeProperty(JObject resource)
{
var subscriptionId = TemplateHelpers.GetProperty(resource, "subscriptionId");
var resourceGroup = TemplateHelpers.GetProperty(resource, "resourceGroup");
Expand Down Expand Up @@ -789,7 +789,7 @@ private SyntaxBase ParseModule(JObject resource, string typeString, string nameS
var properties = new List<ObjectPropertySyntax>();
properties.Add(SyntaxHelpers.CreateObjectProperty("name", ParseJToken(nameString)));

var scope = TryGetScopeProperty(resource);
var scope = TryModuleGetScopeProperty(resource);
if (scope is not null)
{
properties.Add(SyntaxHelpers.CreateObjectProperty("scope", scope));
Expand Down Expand Up @@ -854,7 +854,28 @@ private SyntaxBase ParseModule(JObject resource, string typeString, string nameS
SyntaxHelpers.CreateObject(properties));
}

public SyntaxBase ParseResource(JObject template, JToken value)
private SyntaxBase? TryGetResourceScopeProperty(JObject resource)
{
if (TemplateHelpers.GetProperty(resource, "scope") is not JProperty scopeProperty)
{
return null;
}

var scopeExpression = ExpressionHelpers.ParseExpression(scopeProperty.Value.Value<string>());
if (TryLookupResource(scopeExpression) is string resourceName)
{
return SyntaxHelpers.CreateIdentifier(resourceName);
}

if (TryParseStringExpression(scopeExpression) is SyntaxBase parsedSyntax)
{
return parsedSyntax;
}

throw new ConversionFailedException($"Parsing failed for property value {scopeProperty}", scopeProperty);
}

public SyntaxBase ParseResource(JToken value)
{
var resource = (value as JObject) ?? throw new ConversionFailedException($"Incorrect resource format", value);

Expand Down Expand Up @@ -886,6 +907,7 @@ public SyntaxBase ParseResource(JObject template, JToken value)
"properties",
"dependsOn",
"comments",
"scope",
}, StringComparer.OrdinalIgnoreCase);

var resourcePropsToOmit = new HashSet<string>(new [] {
Expand All @@ -894,10 +916,10 @@ public SyntaxBase ParseResource(JObject template, JToken value)
"apiVersion",
"dependsOn",
"comments",
"scope",
}, StringComparer.OrdinalIgnoreCase);

TemplateHelpers.AssertUnsupportedProperty(resource, "copy", "The 'copy' property is not supported");
TemplateHelpers.AssertUnsupportedProperty(resource, "scope", "The 'scope' property is not supported");

var topLevelProperties = new List<ObjectPropertySyntax>();
foreach (var prop in resource.Properties())
Expand All @@ -921,6 +943,12 @@ public SyntaxBase ParseResource(JObject template, JToken value)
topLevelProperties.Add(SyntaxHelpers.CreateObjectProperty(prop.Name, valueSyntax));
}

var scope = TryGetResourceScopeProperty(resource);
if (scope is not null)
{
topLevelProperties.Add(SyntaxHelpers.CreateObjectProperty("scope", scope));
}

var dependsOn = ProcessDependsOn(resource);
if (dependsOn != null)
{
Expand Down Expand Up @@ -1025,7 +1053,7 @@ private ProgramSyntax Parse()

AddSyntaxBlock(statements, parameters.Select(ParseParam), false);
AddSyntaxBlock(statements, variables.Select(ParseVariable), false);
AddSyntaxBlock(statements, flattenedResources.Select(r => ParseResource(template, r)), true);
AddSyntaxBlock(statements, flattenedResources.Select(ParseResource), true);
AddSyntaxBlock(statements, outputs.Select(ParseOutput), false);

return new ProgramSyntax(
Expand Down

0 comments on commit a19d66c

Please sign in to comment.