Esempio n. 1
0
        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);
        }
Esempio n. 2
0
        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);
        }
Esempio n. 3
0
        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;
 }
Esempio n. 6
0
 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));
 }
Esempio n. 7
0
 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));
 }
Esempio n. 8
0
        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);
        }
Esempio n. 9
0
        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);
        }
Esempio n. 10
0
        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);
        }
Esempio n. 11
0
 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()));
 }
Esempio n. 13
0
 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>();
 }
Esempio n. 15
0
 public ExpandResourcePropertiesActivity(ARMFunctions functions, IInfrastructure infrastructure, ARMTemplateHelper helper)
 {
     this.functions      = functions;
     this.infrastructure = infrastructure;
     this.helper         = helper;
 }
Esempio n. 16
0
        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);
        }
Esempio n. 17
0
        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);
        }
Esempio n. 18
0
 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);
        }
Esempio n. 20
0
        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);
        }
Esempio n. 21
0
        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);
        }
Esempio n. 22
0
        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);
 }
Esempio n. 25
0
 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));
 }