Beispiel #1
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);
        }
Beispiel #2
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);
        }
Beispiel #3
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);
        }
Beispiel #4
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);
        }
Beispiel #5
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);
        }
Beispiel #6
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));
        }
Beispiel #7
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);
        }
        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 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;
            }
        }