public void copyindex() { Dictionary <string, object> cxt = new Dictionary <string, object>() { { "currentloopname", "loop1" }, { "copyindex", new Dictionary <string, int>() { { "loop1", 2 }, { "loop2", 7 } } } }; ARMFunctions functions = new ARMFunctions( Options.Create(new ARMOrchestrationOptions()), null, new MockInfrastructure(null)); object rtv = functions.Evaluate("[copyindex()]", cxt); Assert.Equal(2, (int)rtv); rtv = functions.Evaluate("[copyindex(1)]", cxt); Assert.Equal(3, (int)rtv); rtv = functions.Evaluate("[copyindex('loop2')]", cxt); Assert.Equal(7, (int)rtv); rtv = functions.Evaluate("[copyindex('loop2',2)]", cxt); Assert.Equal(9, (int)rtv); }
public static SKU Parse(JsonElement root, ARMFunctions functions, Dictionary <string, object> context) { SKU sku = new SKU(); if (root.TryGetProperty("name", out JsonElement nameE)) { sku.Name = functions.Evaluate(nameE.GetString(), context).ToString(); } else { throw new Exception("cannot find name property in SKU node"); } if (root.TryGetProperty("tier", out JsonElement tierE)) { sku.Name = functions.Evaluate(tierE.GetString(), context).ToString(); } if (root.TryGetProperty("size", out JsonElement sizeE)) { sku.Size = functions.Evaluate(sizeE.GetString(), context).ToString(); } if (root.TryGetProperty("family", out JsonElement familyE)) { sku.Family = functions.Evaluate(familyE.GetString(), context).ToString(); } if (root.TryGetProperty("capacity", out JsonElement capacityE)) { sku.Capacity = capacityE.GetRawText(); } return(sku); }
private static List <Resource> ExpandCopyResource( JsonElement resource , JsonElement copyElement , Dictionary <string, object> context , ARMFunctions functions , IInfrastructure infrastructure , string parentName , string parentType) { Copy copy = Copy.Parse(copyElement, context, functions, infrastructure); DeploymentContext deploymentContext = context[ContextKeys.ARM_CONTEXT] as DeploymentContext; var CopyResource = new CopyResource() { Name = copy.Name, Type = Copy.ServiceType, FullName = $"{deploymentContext.DeploymentName}/{copy.Name}", FullType = $"{infrastructure.BuiltinServiceTypes.Deployments}/{Copy.ServiceType}", ResourceId = copy.Id, Mode = copy.Mode, BatchSize = copy.BatchSize, }; List <Resource> resources = new List <Resource> { CopyResource }; var copyindex = new Dictionary <string, int>() { { copy.Name, 0 } }; Dictionary <string, object> copyContext = new Dictionary <string, object> { { ContextKeys.ARM_CONTEXT, deploymentContext }, { ContextKeys.COPY_INDEX, copyindex }, { ContextKeys.CURRENT_LOOP_NAME, copy.Name }, { ContextKeys.IS_PREPARE, true } }; for (int i = 0; i < copy.Count; i++) { copyindex[copy.Name] = i; var rs = ParseInternal(resource, copyContext, functions, infrastructure, parentName, parentType); rs[0].CopyIndex = i; rs[0].CopyId = copy.Id; rs[0].CopyName = copy.Name; CopyResource.Resources.Add(rs[0].Name); resources.AddRange(rs); } CopyResource.SubscriptionId = resources[1].SubscriptionId; CopyResource.ManagementGroupId = resources[1].ManagementGroupId; CopyResource.SKU = resources[1].SKU; CopyResource.Plan = resources[1].Plan; CopyResource.Kind = resources[1].Kind; CopyResource.Zones = resources[1].Zones; CopyResource.Location = resources[1].Location; return(resources); }
public void resourcegroup() { ARMFunctions functions = new ARMFunctions( Options.Create(new ARMOrchestrationOptions() { //ListFunction = (sp, cxr, resourceId, apiVersion, functionValues, value) => //{ // return new TaskResult() { Content = value }; //} }), null, new MockInfrastructure(null)); functions.SetFunction("resourcegroup", (args, cxt) => { if (!cxt.TryGetValue("armcontext", out object armcxt)) { return; } var input = armcxt as DeploymentOrchestrationInput; JObject obj = new JObject(); obj.Add("id", $"/subscription/{input.SubscriptionId}/resourceGroups/{input.ResourceGroup}"); obj.Add("name", input.ResourceGroup); obj.Add("type", "xxxx.Resources/resourceGroups"); obj.Add("location", ""); args.Result = new JsonValue(obj.ToString(Newtonsoft.Json.Formatting.None)); }); }
public DeploymentOrchestration( ARMTemplateHelper helper, IInfrastructure infrastructure, ARMFunctions aRMFunctions) { this._ARMFunctions = aRMFunctions; this.helper = helper; this.infrastructure = infrastructure; }
public static List <Resource> Parse( string rawString , Dictionary <string, object> context , ARMFunctions functions , IInfrastructure infrastructure , string parentName, string parentType) { using var doc = JsonDocument.Parse(rawString); return(Parse(doc.RootElement, context, functions, infrastructure, parentName, parentType)); }
public static List <Resource> Parse( JsonElement resourceElement , Dictionary <string, object> context , ARMFunctions functions , IInfrastructure infrastructure , string parentName, string parentType) { if (resourceElement.TryGetProperty("copy", out JsonElement copy)) { return(ExpandCopyResource(resourceElement, copy, context, functions, infrastructure, parentName, parentType)); } return(ParseInternal(resourceElement, context, functions, infrastructure, parentName, parentType)); }
public void ListResource() { ARMFunctions functions = new ARMFunctions( Options.Create(new ARMOrchestrationOptions()), null, new MockInfrastructure(null)); object rtv = functions.Evaluate( "[listId('resourceId','2019-01-02')]", new Dictionary <string, object>() { { "armcontext", new DeploymentContext() { Template = new Template() } } }); Assert.NotNull(rtv); }
public void ListResourceInPrepareTime() { Dictionary <string, object> cxt = new Dictionary <string, object>() { { "armcontext", new DeploymentContext() { Template = new Template() } }, { ContextKeys.IS_PREPARE, true } }; ARMFunctions functions = new ARMFunctions( Options.Create(new ARMOrchestrationOptions()), null, new MockInfrastructure(null)); object rtv = functions.Evaluate("[listId('resourceId','2019-01-02')]", cxt); Assert.NotNull(rtv); Assert.True(cxt.TryGetValue(ContextKeys.DEPENDSON, out object depend)); var dList = depend as List <string>; Assert.Contains("resourceId", dList); }
public ARMTemplateHelper( IOptions <ARMOrchestrationOptions> options, ARMFunctions functions, IInfrastructure infrastructure) { this.options = options?.Value; this.ARMfunctions = functions; this.infrastructure = infrastructure; this._saveDeploymentOperationCommandString = string.Format(@" MERGE {0} with (serializable) [Target] USING (VALUES (@InstanceId,@ExecutionId)) as [Source](InstanceId,ExecutionId) ON [Target].InstanceId = [Source].InstanceId AND [Target].ExecutionId = [Source].ExecutionId WHEN NOT MATCHED THEN INSERT ([InstanceId],[ExecutionId],[GroupId],[GroupType],[HierarchyId],[RootId],[DeploymentId],[CorrelationId],[ParentResourceId],[ResourceId],[Name],[Type],[Stage],[CreateTimeUtc],[UpdateTimeUtc],[SubscriptionId],[ManagementGroupId],[Input],[Result],[Comments],[CreateByUserId],[LastRunUserId]) VALUES (@InstanceId,@ExecutionId,@GroupId,@GroupType,@HierarchyId,@RootId,@DeploymentId,@CorrelationId,@ParentResourceId,@ResourceId,@Name,@Type,@Stage,GETUTCDATE(),GETUTCDATE(),@SubscriptionId,@ManagementGroupId,@Input,@Result,@Comments,@CreateByUserId,@LastRunUserId) WHEN MATCHED THEN UPDATE SET [Stage]=@Stage,[UpdateTimeUtc]=GETUTCDATE(),[Result]=isnull(cast(@Result AS NVARCHAR(MAX)),[Result]),[Comments]=isnull(@Comments,Comments),[LastRunUserId]=isnull(@LastRunUserId,LastRunUserId),[Input]=isnull(cast(@Input AS NVARCHAR(MAX)),[Input]); ", this.options.Database.DeploymentOperationsTableName); }
public string ExpandProperties(DeploymentContext deploymentContext, ARMFunctions functions, IInfrastructure infrastructure) { if (string.IsNullOrEmpty(this.Properties)) { return(string.Empty); } { var doc = JsonDocument.Parse(this.Properties); Dictionary <string, object> cxt = new Dictionary <string, object>() { { ContextKeys.ARM_CONTEXT, deploymentContext } }; if (!string.IsNullOrEmpty(this.CopyName)) { cxt.Add(ContextKeys.CURRENT_LOOP_NAME, this.CopyName); cxt.Add(ContextKeys.COPY_INDEX, new Dictionary <string, int>() { { this.CopyName, this.CopyIndex } }); } return(doc.RootElement.ExpandObject(cxt, functions, infrastructure)); } }
public static string ExpandObject(this JsonElement self, Dictionary <string, object> context, ARMFunctions functions, IInfrastructure infrastructure) { using MemoryStream ms = new MemoryStream(); using Utf8JsonWriter writer = new Utf8JsonWriter(ms); writer.WriteStartObject(); foreach (var item in self.EnumerateObject()) { writer.WriteProperty(item, context, functions, infrastructure); } writer.WriteEndObject(); writer.Flush(); return(Encoding.UTF8.GetString(ms.ToArray())); }
public static SKU Parse(string rawString, ARMFunctions functions, Dictionary <string, object> context) { using var doc = JsonDocument.Parse(rawString); return(Parse(doc.RootElement, functions, context)); }
public ValidateTemplateTest(ARMOrchestartionFixture fixture) { this.functions = fixture.ARMFunctions; this.infrastructure = fixture.ServiceProvider.GetService <IInfrastructure>(); }
public ExpandResourcePropertiesActivity(ARMFunctions functions, IInfrastructure infrastructure, ARMTemplateHelper helper) { this.functions = functions; this.infrastructure = infrastructure; this.helper = helper; }
private static List <Resource> ParseInternal( JsonElement resourceElement , Dictionary <string, object> context , ARMFunctions functions , IInfrastructure infrastructure , string parentName, string parentType) { DeploymentContext deploymentContext = context[ContextKeys.ARM_CONTEXT] as DeploymentContext; List <Resource> resources = new List <Resource>(); Resource r = new Resource(); resources.Add(r); if (resourceElement.TryGetProperty("condition", out JsonElement condition)) { if (condition.ValueKind == JsonValueKind.False) { r.Condition = false; } else if (condition.ValueKind == JsonValueKind.String) { r.Condition = (bool)functions.Evaluate(condition.GetString(), context); } } if (resourceElement.TryGetProperty("apiVersion", out JsonElement apiVersion)) { r.ApiVersion = apiVersion.GetString(); } else { throw new Exception("not find apiVersion in resource node"); } if (resourceElement.TryGetProperty("type", out JsonElement type)) { r.Type = type.GetString(); } else { throw new Exception("not find type in resource node"); } if (!string.IsNullOrEmpty(parentType)) { r.FullType = $"{parentType}/{r.Type}"; } else { r.FullType = r.Type; } if (resourceElement.TryGetProperty("name", out JsonElement name)) { r.Name = functions.Evaluate(name.GetString(), context).ToString(); } else { throw new Exception("not find name in resource node"); } if (!string.IsNullOrEmpty(parentName)) { r.FullName = $"{parentName}/{r.Name}"; } else { r.FullName = r.Name; } if (resourceElement.TryGetProperty("resourceGroup", out JsonElement resourceGroup)) { r.ResourceGroup = functions.Evaluate(resourceGroup.GetString(), context).ToString(); } else { r.ResourceGroup = deploymentContext.ResourceGroup; } if (resourceElement.TryGetProperty("subscriptionId", out JsonElement subscriptionId)) { r.SubscriptionId = functions.Evaluate(subscriptionId.GetString(), context).ToString(); } else { r.SubscriptionId = deploymentContext.SubscriptionId; } if (resourceElement.TryGetProperty("managementGroupId", out JsonElement managementGroupId)) { r.ManagementGroupId = functions.Evaluate(managementGroupId.GetString(), context).ToString(); } else { r.ManagementGroupId = deploymentContext.ManagementGroupId; } if (resourceElement.TryGetProperty("location", out JsonElement location)) { r.Location = functions.Evaluate(location.GetString(), context).ToString(); } if (resourceElement.TryGetProperty("comments", out JsonElement comments)) { r.Comments = comments.GetString(); } if (resourceElement.TryGetProperty("dependsOn", out JsonElement dependsOn)) { using var dd = JsonDocument.Parse(dependsOn.GetRawText()); foreach (var item in dd.RootElement.EnumerateArray()) { r.DependsOn.Add(functions.Evaluate(item.GetString(), context).ToString()); } } #region ResouceId if (deploymentContext.Template.DeployLevel == DeployLevel.ResourceGroup) { List <object> pars = new List <object> { r.SubscriptionId, r.ResourceGroup, r.FullType }; pars.AddRange(r.FullName.Split('/')); r.ResourceId = functions.ResourceId( deploymentContext, pars.ToArray()); } else if (deploymentContext.Template.DeployLevel == DeployLevel.Subscription) { List <object> pars = new List <object> { r.SubscriptionId, r.FullType }; pars.AddRange(r.FullName.Split('/')); r.ResourceId = functions.SubscriptionResourceId(deploymentContext, pars.ToArray()); } else { List <object> pars = new List <object> { r.FullType }; pars.AddRange(r.FullName.Split('/')); r.ResourceId = functions.TenantResourceId(pars.ToArray()); } #endregion ResouceId if (resourceElement.TryGetProperty("sku", out JsonElement sku)) { r.SKU = SKU.Parse(sku, functions, context); } else { r.SKU = new SKU() { Name = SKU.Default } }; if (resourceElement.TryGetProperty("kind", out JsonElement kind)) { r.Kind = kind.GetString(); } if (resourceElement.TryGetProperty("plan", out JsonElement plan)) { r.Plan = plan.GetRawText(); } if (resourceElement.TryGetProperty("zones", out JsonElement zones)) { foreach (var z in zones.EnumerateArray()) { r.Zones.Add(functions.Evaluate(z.GetString(), context).ToString()); } } if (context.ContainsKey(ContextKeys.DEPENDSON)) { //https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/template-functions-resource#valid-uses-1 throw new Exception("The reference function can only be used in the properties of a resource definition and the outputs section of a template or deployment."); } if (!r.Condition) { return(resources); } if (resourceElement.TryGetProperty("properties", out JsonElement properties)) { if (r.FullType == infrastructure.BuiltinServiceTypes.Deployments) { r.Properties = properties.GetRawText(); } else { r.Properties = properties.ExpandObject(context, functions, infrastructure); // if there has Implicit dependency by reference function in properties // the reference function should be evaluate at provisioning time // so keep the original text if (HandleDependsOn(r, context)) { r.Properties = properties.GetRawText(); } } } if (resourceElement.TryGetProperty("resources", out JsonElement _resources)) { foreach (var childres in _resources.EnumerateArray()) { //https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/child-resource-name-type var childResult = Resource.Parse(childres.GetRawText(), context, functions, infrastructure, r.Name, r.Type); r.Resources.Add(childResult[0].Name); resources.AddRange(childResult); } } return(resources); }
public static Template Parse(JsonElement root, DeploymentContext input, ARMFunctions functions, IInfrastructure infrastructure) { Template template = new Template(); input.Template = template; Dictionary <string, object> context = new Dictionary <string, object>() { { ContextKeys.ARM_CONTEXT, input }, { ContextKeys.IS_PREPARE, true } }; if (!root.TryGetProperty("$schema", out JsonElement schema)) { throw new Exception("not find $schema in template"); } template.Schema = schema.GetString(); if (!root.TryGetProperty("contentVersion", out JsonElement contentVersion)) { throw new Exception("not find contentVersion in template"); } template.ContentVersion = contentVersion.GetString(); if (template.Schema.EndsWith("deploymentTemplate.json#", StringComparison.InvariantCultureIgnoreCase)) { template.DeployLevel = DeployLevel.ResourceGroup; } else if (template.Schema.EndsWith("subscriptionDeploymentTemplate.json#", StringComparison.InvariantCultureIgnoreCase)) { template.DeployLevel = DeployLevel.Subscription; } else if (template.Schema.EndsWith("managementGroupDeploymentTemplate.json#", StringComparison.InvariantCultureIgnoreCase)) { template.DeployLevel = DeployLevel.ManagemnetGroup; } else { throw new Exception("wrong $shema setting"); } if (!root.TryGetProperty("resources", out JsonElement resources)) { throw new Exception("not find resources in template"); } if (root.TryGetProperty("apiProfile", out JsonElement apiProfile)) { template.ApiProfile = apiProfile.GetString(); } if (root.TryGetProperty("parameters", out JsonElement parameters)) { template.Parameters = parameters.GetRawText(); } if (root.TryGetProperty("outputs", out JsonElement outputs)) { template.Outputs = outputs.GetRawText(); } if (root.TryGetProperty("variables", out JsonElement variables)) { // cos var can reference var template.Variables = variables.GetRawText(); template.Variables = variables.ExpandObject(context, functions, infrastructure); } if (root.TryGetProperty("functions", out JsonElement funcs)) { template.Functions = Functions.Parse(funcs); } foreach (var resource in resources.EnumerateArray()) { foreach (var r in Resource.Parse(resource, context, functions, infrastructure, string.Empty, string.Empty)) { if (r.Condition) { template.Resources.Add(r); } else { template.ConditionFalseResources.Add(r.Name); } } } return(template); }
public static Template Parse(string content, DeploymentContext input, ARMFunctions functions, IInfrastructure infrastructure) { using JsonDocument doc = JsonDocument.Parse(content); return(Parse(doc.RootElement, input, functions, infrastructure)); }
public static (bool Result, string Message) WriteProperty(this Utf8JsonWriter writer, JsonProperty property, Dictionary <string, object> context, ARMFunctions functions, IInfrastructure infrastructure) { // https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/template-functions-numeric#copyindex if ("copy".Equals(property.Name, StringComparison.OrdinalIgnoreCase)) { var copyProperty = property.Value; // this is for Variable and Property iteration if (copyProperty.ValueKind == JsonValueKind.Array) { foreach (var item in property.Value.EnumerateArray()) { Copy copy = null; try { copy = Copy.Parse(item, context, functions, infrastructure); } catch (Exception ex) { return(false, ex.Message); } using JsonDocument doc = JsonDocument.Parse(copy.Input); var copyindex = new Dictionary <string, int>() { { copy.Name, 0 } }; Dictionary <string, object> copyContext = new Dictionary <string, object> { { "copyindex", copyindex }, { "currentloopname", copy.Name } }; foreach (var k in context.Keys) { copyContext.Add(k, context[k]); } writer.WritePropertyName(copy.Name); writer.WriteStartArray(); for (int i = 0; i < copy.Count; i++) { copyindex[copy.Name] = i; writer.WriteElement(doc.RootElement, copyContext, functions, infrastructure); } writer.WriteEndArray(); if (copyContext.TryGetValue(ContextKeys.DEPENDSON, out object copyDependsOn)) { List <string> dependsOn; if (context.TryGetValue(ContextKeys.DEPENDSON, out object d)) { dependsOn = d as List <string>; } else { dependsOn = new List <string>(); context.Add(ContextKeys.DEPENDSON, dependsOn); } dependsOn.AddRange(copyDependsOn as List <string>); } if (copyContext.ContainsKey(ContextKeys.NEED_REEVALUATE)) { context.TryAdd(ContextKeys.NEED_REEVALUATE, true); } } } // this is for output else if (copyProperty.ValueKind == JsonValueKind.Object) { var input = copyProperty.GetProperty("input"); var countProperty = copyProperty.GetProperty("count"); int count; if (countProperty.ValueKind == JsonValueKind.Number) { count = countProperty.GetInt32(); } else if (countProperty.ValueKind == JsonValueKind.String) { count = (int)functions.Evaluate(countProperty.GetString(), context); } else { throw new Exception("the property of count has wrong error. It should be number or an function return a number"); } var name = Guid.NewGuid().ToString("N"); var copyindex = new Dictionary <string, int>() { { name, 0 } }; Dictionary <string, object> copyContext = new Dictionary <string, object> { { "copyindex", copyindex }, { "currentloopname", name } }; foreach (var k in context.Keys) { copyContext.Add(k, context[k]); } writer.WritePropertyName("value"); writer.WriteStartArray(); for (int i = 0; i < count; i++) { copyindex[name] = i; writer.WriteElement(input, copyContext, functions, infrastructure); } writer.WriteEndArray(); } else { throw new Exception("the structer of copy property is wrong"); } } else { writer.WritePropertyName(property.Name); writer.WriteElement(property.Value, context, functions, infrastructure); } return(true, string.Empty); }
public static Copy Parse(JsonElement root, Dictionary <string, object> context, ARMFunctions functions, IInfrastructure infrastructure) { var copy = new Copy(); var deployContext = context[ContextKeys.ARM_CONTEXT] as DeploymentContext; if (root.TryGetProperty("name", out JsonElement name)) { copy.Name = name.GetString(); } if (root.TryGetProperty("count", out JsonElement count)) { if (count.ValueKind == JsonValueKind.Number) { copy.Count = count.GetInt32(); } else if (count.ValueKind == JsonValueKind.String) { copy.Count = (int)functions.Evaluate(count.GetString(), context); } else { throw new Exception("the value of count property should be Number in copy node"); } // https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/template-functions-resource#valid-uses-1 if (context.ContainsKey(ContextKeys.DEPENDSON)) { throw new Exception("You can't use the reference function to set the value of the count property in a copy loop."); } } else { throw new Exception("not find count in copy node"); } if (root.TryGetProperty("mode", out JsonElement mode)) { copy.Mode = mode.GetString().ToLower(); } if (root.TryGetProperty("batchSize", out JsonElement batchSize)) { if (batchSize.ValueKind == JsonValueKind.Number) { copy.BatchSize = batchSize.GetInt32(); } else if (batchSize.ValueKind == JsonValueKind.String) { copy.BatchSize = (int)functions.Evaluate(batchSize.GetString(), context); } } if (root.TryGetProperty("input", out JsonElement input)) { copy.Input = input.GetRawText(); } copy.Id = functions.ResourceId(deployContext, new object[] { $"{infrastructure.BuiltinServiceTypes.Deployments}/{Copy.ServiceType}", deployContext.DeploymentName, copy.Name }); return(copy); }
public static DeploymentOrchestrationInput Validate(DeploymentOrchestrationInput input, ARMFunctions functions, IInfrastructure infrastructure) { if (input.Template != null) { return(input); } input.Template = Template.Parse(input.TemplateContent, input, functions, infrastructure); foreach (var res in input.Template.Resources) { #region Deployment if (res.FullType == infrastructure.BuiltinServiceTypes.Deployments) { var deploy = Parse(res, input, functions, infrastructure); input.Deployments.Add(deploy.DeploymentName, deploy); foreach (var item in deploy.Deployments.Values) { input.Deployments.Add(item.DeploymentName, item); } deploy.Deployments.Clear(); } #endregion #region dependsOn for (int i = res.DependsOn.Count - 1; i >= 0; i--) { string dependsOnName = res.DependsOn[i]; // https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/define-resource-dependency#dependson // When a conditional resource isn't deployed, Azure Resource Manager automatically removes it from the required dependencies. if (!input.Template.Resources.ContainsKey(dependsOnName)) { if (input.Template.ConditionFalseResources.Contains(dependsOnName)) { res.DependsOn.RemoveAt(i); } else { throw new Exception($"cannot find dependson resource named '{dependsOnName}'"); } } // check duplicated dependsOn if (HasSameName(res.DependsOn, i - 1, dependsOnName)) { res.DependsOn.RemoveAt(i); } } // TODO: check circular dependencies #endregion } return(input); }
public static DeploymentOrchestrationInput Parse(Resource resource, DeploymentContext deploymentContext, ARMFunctions functions, IInfrastructure infrastructure) { var armContext = new Dictionary <string, object>() { { ContextKeys.ARM_CONTEXT, deploymentContext }, { ContextKeys.IS_PREPARE, true } }; using var doc = JsonDocument.Parse(resource.Properties); var rootElement = doc.RootElement; var mode = DeploymentMode.Incremental; if (rootElement.TryGetProperty("mode", out JsonElement _mode)) { if (_mode.GetString().Equals(DeploymentMode.Complete.ToString(), StringComparison.OrdinalIgnoreCase)) { mode = DeploymentMode.Complete; } if (_mode.GetString().Equals(DeploymentMode.OnlyCreation.ToString(), StringComparison.OrdinalIgnoreCase)) { mode = DeploymentMode.OnlyCreation; } } string template = string.Empty; if (rootElement.TryGetProperty("template", out JsonElement _template)) { template = _template.GetRawText(); } TemplateLink templateLink = null; if (rootElement.TryGetProperty("templateLink", out JsonElement _templateLink)) { templateLink = new TemplateLink() { ContentVersion = _templateLink.GetProperty("contentVersion").GetString(), Uri = functions.Evaluate(_templateLink.GetProperty("uri").GetString(), armContext).ToString() }; } // https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/linked-templates#scope-for-expressions-in-nested-templates string parameters = string.Empty; ParametersLink parametersLink = null; if (rootElement.TryGetProperty("expressionEvaluationOptions", out JsonElement _expressionEvaluationOptions) && _expressionEvaluationOptions.GetProperty("scope").GetString().Equals("inner", StringComparison.OrdinalIgnoreCase)) { if (rootElement.TryGetProperty("parameters", out JsonElement _parameters)) { parameters = _parameters.GetRawText(); } if (rootElement.TryGetProperty("parametersLink", out JsonElement _parametersLink)) { parametersLink = new ParametersLink() { ContentVersion = _parametersLink.GetProperty("contentVersion").GetString(), Uri = functions.Evaluate(_parametersLink.GetProperty("uri").GetString(), armContext).ToString() }; } } else { parameters = deploymentContext.Parameters; using MemoryStream ms = new MemoryStream(); using Utf8JsonWriter writer = new Utf8JsonWriter(ms); writer.WriteStartObject(); using var doc1 = JsonDocument.Parse(template); var root1 = doc1.RootElement; foreach (var node in root1.EnumerateObject()) { if (node.Name.Equals("parameters", StringComparison.OrdinalIgnoreCase) || node.Name.Equals("variables", StringComparison.OrdinalIgnoreCase)) { continue; } writer.WritePropertyName(node.Name); node.Value.WriteTo(writer); } if (!string.IsNullOrWhiteSpace(deploymentContext.Template.Parameters)) { using var p = JsonDocument.Parse(deploymentContext.Template.Parameters); writer.WritePropertyName("parameters"); p.RootElement.WriteTo(writer); } if (!string.IsNullOrWhiteSpace(deploymentContext.Template.Variables)) { using var v = JsonDocument.Parse(deploymentContext.Template.Variables); writer.WritePropertyName("variables"); v.RootElement.WriteTo(writer); } writer.WriteEndObject(); writer.Flush(); template = Encoding.UTF8.GetString(ms.ToArray()); } var(groupId, groupType, hierarchyId) = infrastructure.GetGroupInfo(resource.ManagementGroupId, resource.SubscriptionId, resource.ResourceGroup); var deployInput = new DeploymentOrchestrationInput() { RootId = deploymentContext.RootId, DeploymentId = Guid.NewGuid().ToString("N"), ParentId = deploymentContext.GetResourceId(infrastructure), GroupId = groupId, GroupType = groupType, HierarchyId = hierarchyId, CorrelationId = deploymentContext.CorrelationId, SubscriptionId = resource.SubscriptionId, ManagementGroupId = resource.ManagementGroupId, ResourceGroup = resource.ResourceGroup, DeploymentName = resource.Name, Mode = mode, TemplateContent = template, TemplateLink = templateLink, Parameters = parameters, ParametersLink = parametersLink, ApiVersion = resource.ApiVersion, CreateByUserId = deploymentContext.CreateByUserId, LastRunUserId = deploymentContext.LastRunUserId, DependsOn = resource.DependsOn, Extensions = deploymentContext.Extensions, TenantId = deploymentContext.TenantId }; return(Validate(deployInput, functions, infrastructure)); }
public static void WriteElement(this Utf8JsonWriter writer, JsonElement element, Dictionary <string, object> context, ARMFunctions functions, IInfrastructure infrastructure) { switch (element.ValueKind) { case JsonValueKind.Undefined: case JsonValueKind.Number: case JsonValueKind.True: case JsonValueKind.False: case JsonValueKind.Null: element.WriteTo(writer); break; case JsonValueKind.Object: writer.WriteStartObject(); foreach (var p in element.EnumerateObject()) { writer.WriteProperty(p, context, functions, infrastructure); } writer.WriteEndObject(); break; case JsonValueKind.Array: writer.WriteStartArray(); foreach (var a in element.EnumerateArray()) { writer.WriteElement(a, context, functions, infrastructure); } writer.WriteEndArray(); break; case JsonValueKind.String: var r = functions.Evaluate(element.GetString(), context); if (r is JsonValue j) { j.RootElement.WriteTo(writer); } else if (r is bool b) { writer.WriteBooleanValue(b); } else if (r is string s) { writer.WriteStringValue(s); } else if (r is Int32 i) { writer.WriteNumberValue(i); } else if (r is FakeJsonValue) { writer.WriteStringValue("fakeString"); } else { writer.WriteNullValue(); } break; default: break; } }
public static IServiceCollection UsingARMOrchestration(this IServiceCollection services, Func <IServiceProvider, ARMOrchestrationSqlServerConfig> configOption) { services.AddSingleton((sp) => { return(configOption(sp)); }); services.UsingOrchestration((sp) => { var config = sp.GetService <ARMOrchestrationSqlServerConfig>(); SqlServerConfiguration sqlServerConfiguration = new SqlServerConfiguration() { AutoCreate = config.Database.AutoCreate, ConnectionString = config.Database.ConnectionString, HubName = config.Database.HubName, SchemaName = config.Database.SchemaName, CommunicationWorkerOptions = config.CommunicationWorkerOptions, OrchestrationServiceSettings = config.OrchestrationServiceSettings }; sqlServerConfiguration.OrchestrationWorkerOptions.FetchJobCount = config.OrchestrationWorkerOptions.FetchJobCount; sqlServerConfiguration.OrchestrationWorkerOptions.GetBuildInTaskActivitiesFromInterface = config.OrchestrationWorkerOptions.GetBuildInTaskActivitiesFromInterface; sqlServerConfiguration.OrchestrationWorkerOptions.GetBuildInOrchestrators = (sp) => { IList <(string, string, Type)> orchList; if (config.OrchestrationWorkerOptions.GetBuildInOrchestrators == null) { orchList = new List <(string, string, Type)>(); } else { orchList = config.OrchestrationWorkerOptions.GetBuildInOrchestrators(sp); } orchList.Add((ResourceOrchestration.Name, "1.0", typeof(ResourceOrchestration))); orchList.Add((DeploymentOrchestration.Name, "1.0", typeof(DeploymentOrchestration))); orchList.Add((RequestOrchestration.Name, "1.0", typeof(RequestOrchestration))); orchList.Add((CopyOrchestration.Name, "1.0", typeof(CopyOrchestration))); return(orchList); }; sqlServerConfiguration.OrchestrationWorkerOptions.GetBuildInTaskActivities = (sp) => { IList <(string, string, Type)> activityTypes; if (config.OrchestrationWorkerOptions.GetBuildInTaskActivities == null) { activityTypes = new List <(string, string, Type)>(); } else { activityTypes = config.OrchestrationWorkerOptions.GetBuildInTaskActivities(sp); } activityTypes.Add((DeploymentOperationActivity.Name, "1.0", typeof(DeploymentOperationActivity))); activityTypes.Add((WaitDependsOnActivity.Name, "1.0", typeof(WaitDependsOnActivity))); activityTypes.Add((ValidateTemplateActivity.Name, "1.0", typeof(ValidateTemplateActivity))); activityTypes.Add((AsyncRequestActivity.Name, "1.0", typeof(AsyncRequestActivity))); activityTypes.Add((ExpandResourcePropertiesActivity.Name, "1.0", typeof(ExpandResourcePropertiesActivity))); return(activityTypes); }; return(sqlServerConfiguration); }); services.AddSingleton <ARMOrchestrationClient>(); services.AddSingleton <ARMTemplateHelper>(); services.AddSingleton <ARMFunctions>((sp) => { var options = sp.GetService <IOptions <ARMOrchestrationOptions> >(); var infra = sp.GetService <IInfrastructure>(); var config = sp.GetService <ARMOrchestrationSqlServerConfig>(); var func = new ARMFunctions(options, sp, infra); config.ConfigARMFunctions?.Invoke(func); return(func); }); services.AddSingleton <WaitDependsOnWorker>(); services.AddSingleton <IHostedService>(p => p.GetService <WaitDependsOnWorker>()); services.AddSingleton((sp) => { var config = sp.GetService <ARMOrchestrationSqlServerConfig>(); var option = new ARMOrchestrationOptions { Database = config.Database }; return(Options.Create(option)); }); return(services); }
public static Copy Parse(string rawString, Dictionary <string, object> context, ARMFunctions functions, IInfrastructure infrastructure) { using var doc = JsonDocument.Parse(rawString); return(Parse(doc.RootElement, context, functions, infrastructure)); }