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

Implement decompilation for the 'scope' property #1190

Merged
merged 1 commit into from
Dec 18, 2020
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.
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
@@ -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