зеркало из https://github.com/Azure/benchpress.git
Parameter and Variable Resolution (#323)
* separate out into method and call for dependson unpacking * Initial code to extract from mulitiple "DependsOn" entries * Rename method and vars and add some descriptive comments * Updating the code to work with other code that will be introduced. * Minor updates to comments and code. * Minor update. * Cleanup a lot and add more descriptive comments * Some renaming cause i can never decide * Remove launchSettings * Remove no longer needed if * Use default value key * set resolvedvalue to null if defaultvalue does not exist * resolve csharpier * Some cleanup * Simplify regex * Potential solution for adding quotes to resolved values that do not contian arm template functions * Typo with name * Reuse square bracket pattern and remove parantheses regex * Typo remove double and --------- Co-authored-by: Marc Lerwick <marclerwick@microsoft.com>
This commit is contained in:
Родитель
815402fb25
Коммит
a1595f9626
|
@ -5,12 +5,21 @@ namespace Generators;
|
|||
|
||||
public class AzureDeploymentImporter
|
||||
{
|
||||
private static Regex s_parametersOrVariablesRegex = new Regex(
|
||||
"(?<paramOrVarType>parameters|variables)\\('(?<paramOrVarName>.*?)'\\)",
|
||||
RegexOptions.Compiled
|
||||
);
|
||||
private static Regex s_resourceIdParametersRegex = new Regex(
|
||||
"\\[resourceId\\((?<resourceIdParameters>.*)\\)\\]",
|
||||
RegexOptions.Compiled
|
||||
);
|
||||
private static string s_resourceIdParametersKey = "resourceIdParameters";
|
||||
private static string s_dependsOnKey = "dependsOn";
|
||||
private static string s_squareBracketPattern = "\\[(.*?)\\]";
|
||||
private static string s_squareBracketSubstituition = "$1";
|
||||
private static string s_paramOrVarNameGroupKey = "paramOrVarName";
|
||||
private static string s_paramOrVarTypeGroupKey = "paramOrVarType";
|
||||
private static string s_defaultValueKey = "defaultValue";
|
||||
|
||||
public static IEnumerable<TestMetadata> Import(FileInfo inputFile, string outputFolderPath)
|
||||
{
|
||||
|
@ -85,48 +94,14 @@ public class AzureDeploymentImporter
|
|||
throw new Exception("Failed to parse json file");
|
||||
}
|
||||
|
||||
if (resourceName.StartsWith("[") && resourceName.EndsWith("]"))
|
||||
{
|
||||
var parts = new[] { "parameters", "variables" };
|
||||
|
||||
foreach (var part in parts)
|
||||
{
|
||||
var temp = resourceName;
|
||||
var parsedValue = temp!
|
||||
.Replace("[", "")
|
||||
.Replace("]", "")
|
||||
.Replace(part, "")
|
||||
.Replace("(", "")
|
||||
.Replace(")", "")
|
||||
.Replace("'", "")
|
||||
.Trim();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(parsedValue))
|
||||
{
|
||||
var defaultValueNode = parsed[part]?[parsedValue];
|
||||
if (defaultValueNode is JsonObject)
|
||||
{
|
||||
temp = defaultValueNode["defaultValue"]!.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
temp = parsed[part]?[parsedValue]?.ToString();
|
||||
}
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(temp))
|
||||
{
|
||||
resourceName = temp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
resourceName = ResolveParamsAndVariables(resourceName, parsed);
|
||||
|
||||
if (resourceName == null)
|
||||
{
|
||||
throw new Exception("Failed to parse json file");
|
||||
}
|
||||
|
||||
var extraProperties = GetExtraProperties(resource);
|
||||
var extraProperties = GetExtraProperties(resource, parsed);
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -172,7 +147,10 @@ public class AzureDeploymentImporter
|
|||
/// }
|
||||
/// </code>
|
||||
/// </summary>
|
||||
private static Dictionary<string, string> GetExtraProperties(JsonNode resource)
|
||||
private static Dictionary<string, string> GetExtraProperties(
|
||||
JsonNode resource,
|
||||
JsonObject armTemplateObject
|
||||
)
|
||||
{
|
||||
var extraProperties = new Dictionary<string, string>();
|
||||
var dependencies = (JsonArray?)resource[s_dependsOnKey];
|
||||
|
@ -214,10 +192,15 @@ public class AzureDeploymentImporter
|
|||
|
||||
for (int index = 0; index < pathParts.Count(); index++)
|
||||
{
|
||||
// If the value is a hard coded value and not a "parameter" or "variable", then the
|
||||
// value will be "'value'" so trim any single quotes (this will not affect "parameter"
|
||||
// or "variable" entries).
|
||||
extraProperties.Add(pathParts[index], values[index].Trim('\''));
|
||||
// If the value is a "parameter" or "variable", then resolve it to the correct value
|
||||
// of the parameter or variable. If the value is a hard coded value, then the
|
||||
// value will be "'value'" so trim any single quotes.
|
||||
var value = ResolveParamsAndVariables(
|
||||
values[index],
|
||||
armTemplateObject
|
||||
)
|
||||
.Trim('\'');
|
||||
extraProperties.Add(pathParts[index], value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -229,4 +212,142 @@ public class AzureDeploymentImporter
|
|||
|
||||
return extraProperties;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Takes a string from an ARM template containing instances of <c>parameters('...')</c> and
|
||||
/// <c>variables('...')</c> and resolves those instances to the correct values, if possible.
|
||||
/// <example>
|
||||
/// For example, if the following ARM template (<paramref name="armTemplateObject"/>) with the parameter block
|
||||
/// below is passed in:
|
||||
/// <code>
|
||||
/// {...
|
||||
/// "parameters": {
|
||||
/// "demoParam": {
|
||||
/// "type": "string",
|
||||
/// "defaultValue": "Contoso"
|
||||
/// }
|
||||
/// }
|
||||
/// ...}
|
||||
/// </code>
|
||||
/// and the following string (<paramref name ="stringToResolve"/>) is passed in:
|
||||
/// <code>
|
||||
/// "[parameters('demoParam')]"
|
||||
/// </code>
|
||||
/// The parameter will be resolved to the default value and result in the following return value:
|
||||
/// <code>
|
||||
/// "Contoso"
|
||||
/// </code>
|
||||
/// This method can also handle resolving ARM template variables. For example if the following ARM template
|
||||
/// (<paramref name="armTemplateObject"/>) with the variable block below is passed in:
|
||||
/// <code>
|
||||
/// {...
|
||||
/// "variables": {
|
||||
/// "demoVar": "Contoso"
|
||||
/// }
|
||||
/// ...}
|
||||
/// </code>
|
||||
/// and the following string (<paramref name ="stringToResolve"/>) is passed in:
|
||||
/// <code>
|
||||
/// "[variables('demoVar')]"
|
||||
/// </code>
|
||||
/// The variable will be resolved to the correct value and result in the following return value:
|
||||
/// <code>
|
||||
/// "Contoso"
|
||||
/// </code>
|
||||
/// Finally, this method can also handle resolving a mixture of ARM template parameters and variables. For example
|
||||
/// if the following ARM template (<paramref name="armTemplateObject"/>) with the parameter and variable block
|
||||
/// below is passed in:
|
||||
/// <code>
|
||||
/// {...
|
||||
/// "parameters": {
|
||||
/// "demoParam": {
|
||||
/// "type": "string",
|
||||
/// "defaultValue": "ContosoParam"
|
||||
/// }
|
||||
/// }
|
||||
/// "variables": {
|
||||
/// "demoVar": "ContosoVar"
|
||||
/// }
|
||||
/// ...}
|
||||
/// </code>
|
||||
/// and the following string (<paramref name ="stringToResolve"/>) is passed in:
|
||||
/// <code>
|
||||
/// "[format('{0}{1}', variables('demoVar'), parameters('demoParam')]"
|
||||
/// </code>
|
||||
/// The variable and parameter will be resolved to the correct values and result in the following return value:
|
||||
/// <code>
|
||||
/// "format('{0}{1}', 'ContosoVar' , 'ContosoParam')"
|
||||
/// </code>
|
||||
/// </summary>
|
||||
private static string ResolveParamsAndVariables(
|
||||
string stringToResolve,
|
||||
JsonObject armTemplateObject
|
||||
)
|
||||
{
|
||||
// Find and remove square brackets from the parameter/variable string. Square brackets are specific to
|
||||
// ARM template syntax and are not needed in generated tests.
|
||||
stringToResolve = Regex.Replace(
|
||||
stringToResolve,
|
||||
s_squareBracketPattern,
|
||||
s_squareBracketSubstituition
|
||||
);
|
||||
|
||||
// Find all matches in the parameter/variable string that follows the pattern of "parameters('...')" or
|
||||
// "variables('...')". The regular expression pattern defines two named subexpressions: paramOrVarType, which
|
||||
// represents the type of parameter/variable (e.g., "parameters" or "variables"), and paramOrVarName, which
|
||||
// represents the name of the parameter/variable.
|
||||
var matches = s_parametersOrVariablesRegex.Matches(stringToResolve);
|
||||
foreach (Match match in matches)
|
||||
{
|
||||
var name = match.Groups[s_paramOrVarNameGroupKey].Value;
|
||||
var type = match.Groups[s_paramOrVarTypeGroupKey].Value;
|
||||
var resolvedValue = System.String.Empty;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
// ARM templates will contain a JSON Object representing parameters and variables for the ARM template.
|
||||
// Get the correct JSON Object using the type from the regex match (e.g., "parameters" or "variables").
|
||||
var parametersOrVariablesObj = armTemplateObject[type];
|
||||
if (parametersOrVariablesObj != null)
|
||||
{
|
||||
// Get the value of the parameter/variable from the JSON Object. If the value is still a JSON
|
||||
// Object, that means it is a parameter that has a default value, so get the default value (if it
|
||||
// exists). Otherwise, the value can be converted to a string and assigned to resolveValue.
|
||||
var resolvedValueNode = parametersOrVariablesObj[name];
|
||||
if (resolvedValueNode != null)
|
||||
{
|
||||
if (resolvedValueNode is JsonObject)
|
||||
{
|
||||
resolvedValue = resolvedValueNode[s_defaultValueKey]?.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
resolvedValue = resolvedValueNode.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(resolvedValue))
|
||||
{
|
||||
// If square brackets are present in the resolved value, remove them from the value. Square brackets
|
||||
// are specific to ARM template syntax to represent expressions and are not needed in generated tests.
|
||||
// If the resolved value does not have square brackets, then the resolved value does not contain ARM
|
||||
// functions and should be wrapped in single quotes.
|
||||
if (Regex.Match(resolvedValue, s_squareBracketPattern).Success)
|
||||
{
|
||||
resolvedValue = Regex.Replace(
|
||||
resolvedValue,
|
||||
s_squareBracketPattern,
|
||||
s_squareBracketSubstituition
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
resolvedValue = "\'" + resolvedValue + "\'";
|
||||
}
|
||||
stringToResolve = stringToResolve.Replace(match.Value, resolvedValue);
|
||||
}
|
||||
}
|
||||
return stringToResolve;
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче