繁体   English   中英

从ARM模板部署新的Azure VM时,无法格式化有效的JObject for.WithParameters()

[英]Trouble formatting valid JObject for .WithParameters() when deploying new Azure VM from ARM Template

目前,我在使用使用C#编写的Azure函数从ARM模板部署Azure VM时遇到麻烦,同时使用Newjonsoft.Json,Linq库中的JObject为新VM提供参数时,无法部署Azure VM。

JObject.FromObject()方法以"{"paramName": "paramValue"}"的格式制定参数,但是我认为它需要表述为"{"paramName": { "value": "paramValue"} 。我不确定是否还需要指定'contentVersion'和'$ schema'ARM模板参数才能使其正常工作。

到目前为止,我已经尝试使用动态变量来表述对象,然后将其转换为字符串并使用JObject.Parse()方法进行解析,但是这只能产生与前面所述相同的结果。

Azure Function代码示例(并非所有代码):

using Microsoft.Azure.Management.Fluent;
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Logging;
using Microsoft.WindowsAzure.Storage.Table;
using System.Threading.Tasks;
using System;
using Microsoft.Rest.Azure;
using Newtonsoft.Json.Linq;

// Authenticate with Azure

IAzure azure = await 
    Authentication.AuthenticateWithAzure(azureVmDeploymentRequest.SubscriptionId);

// Get current datetime
string Datetime = DateTime.Now.ToString("yyyy-MM-ddHHmmss");

log.LogInformation("Initiating VM ARM Template Deployment");
var parameters = azureVmDeploymentRequest.ToArmParameters(
        subscriptionId: azureVmDeploymentRequest.SubscriptionId,
        imageReferencePublisher: azureVmDeploymentRequest.ImageReferencePublisher
    );

// AzNewVmRequestArmParametersMain is a custom object containing the 
// parameters needed for the ARM template, constructed with GET SET

var parametersMain = new AzNewVmRequestArmParametersMain
{
    parameters = parameters
};

var jParameters = JObject.FromObject(parameters);

// Deploy VM from ARM template if request is valid
var vmArmTemplateParams = new ARMTemplateDeploymentRequest
{
    DeploymentName = "vmDeployTfLCP-" + Datetime,
    ParametersObject = jParameters,
    ResourceGroupName = azureVmDeploymentRequest.ResourceGroupName,
    TemplateUri = Environment.GetEnvironmentVariable("VM_ARMTEMPLATE_URI"),
    SasToken = Environment.GetEnvironmentVariable("STORAGE_ACCOUNT_SASTOKEN")
};

ARM模板部署类代码示例(并非所有代码):

using Microsoft.Azure.Management.Fluent;
using System.Threading.Tasks;
using Microsoft.Azure.Management.ResourceManager.Fluent;
using System;
using Microsoft.Extensions.Logging;
using Microsoft.Rest.Azure;


// Formulate ARM template URI
var ArmTemplatePath = ARMTemplateDeploymentRequest.TemplateUri + ARMTemplateDeploymentRequest.SasToken;

deployment = azure.Deployments.Define(ARMTemplateDeploymentRequest.DeploymentName)
    .WithExistingResourceGroup(ARMTemplateDeploymentRequest.ResourceGroupName)
    .WithTemplateLink(ArmTemplatePath, "1.0.0.0")
    .WithParameters(ARMTemplateDeploymentRequest.ParametersObject)
    .WithMode(Microsoft.Azure.Management.ResourceManager.Fluent.Models.DeploymentMode.Incremental)
    .Create();

预期的结果是,我期望代码仅将ARM模板部署启动到Azure资源组,但是当前它失败,并显示以下消息:

'请求内容无效,无法反序列化:'将值“ parameterValue”转换为'Microsoft.WindowsAzure.ResourceStack.Frontdoor.Data.Definitions.DeploymentParameterDefinition'时出错。 路径'properties.parameters.vNetResourceGroup',第8行,位置48。'。”

根据我的测试,如果要使用动态变量来制定对象,则需要创建一个新的JObject。 例如我的template.json

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
      "adminUsername": { "type": "string" },
      "adminPassword": { "type": "securestring" }
    },
    "variables": {
      "vnetID": "[resourceId('Microsoft.Network/virtualNetworks','myVNet123456')]", 
      "subnetRef": "[concat(variables('vnetID'),'/subnets/mySubnet')]"
    },
    "resources": [
      {
        "apiVersion": "2016-03-30",
        "type": "Microsoft.Network/publicIPAddresses",
        "name": "myPublicIPAddress123456",
        "location": "[resourceGroup().location]",
        "properties": {
          "publicIPAllocationMethod": "Dynamic",
          "dnsSettings": {
            "domainNameLabel": "myresourcegroupdns15896"
          }
        }
      },
      {
        "apiVersion": "2016-03-30",
        "type": "Microsoft.Network/virtualNetworks",
        "name": "myVNet123456",
        "location": "[resourceGroup().location]",
        "properties": {
          "addressSpace": { "addressPrefixes": [ "10.0.0.0/16" ] },
          "subnets": [
            {
              "name": "mySubnet",
              "properties": { "addressPrefix": "10.0.0.0/24" }
            }
          ]
        }
      },
      {
        "apiVersion": "2016-03-30",
        "type": "Microsoft.Network/networkInterfaces",
        "name": "myNic562354",
        "location": "[resourceGroup().location]",
        "dependsOn": [
          "[resourceId('Microsoft.Network/publicIPAddresses/', 'myPublicIPAddress123456')]",
          "[resourceId('Microsoft.Network/virtualNetworks/', 'myVNet')]"
        ],
        "properties": {
          "ipConfigurations": [
            {
              "name": "ipconfig1",
              "properties": {
                "privateIPAllocationMethod": "Dynamic",
                "publicIPAddress": { "id": "[resourceId('Microsoft.Network/publicIPAddresses','myPublicIPAddress123456')]" },
                "subnet": { "id": "[variables('subnetRef')]" }
              }
            }
          ]
        }
      },
      {
        "apiVersion": "2016-04-30-preview",
        "type": "Microsoft.Compute/virtualMachines",
        "name": "myVM",
        "location": "[resourceGroup().location]",
        "dependsOn": [
          "[resourceId('Microsoft.Network/networkInterfaces/', 'myNic562354')]"
        ],
        "properties": {
          "hardwareProfile": { "vmSize": "Standard_DS1" },
          "osProfile": {
            "computerName": "myVM",
            "adminUsername": "[parameters('adminUsername')]",
            "adminPassword": "[parameters('adminPassword')]"
          },
          "storageProfile": {
            "imageReference": {
              "publisher": "MicrosoftWindowsServer",
              "offer": "WindowsServer",
              "sku": "2012-R2-Datacenter",
              "version": "latest"
            },
            "osDisk": {
              "name": "myManagedOSDisk",
              "caching": "ReadWrite",
              "createOption": "FromImage"
            }
          },
          "networkProfile": {
            "networkInterfaces": [
              {
                "id": "[resourceId('Microsoft.Network/networkInterfaces','myNic562354')]"
              }
            ]
          }
        }
      }
    ]
  }

我的密码

JObject parametesObjectv1 = new JObject(
                    new JProperty("adminUsername",
                        new JObject(
                            new JProperty("value", "azureuser")
                        )
                    ),
                    new JProperty("adminPassword",
                        new JObject(
                            new JProperty("value", "Azure12345678")
                        )
                    )
                );



       var credentials = SdkContext.AzureCredentialsFactory.FromServicePrincipal(clientId, clientSecret, tenantId, AzureEnvironment.AzureGlobalCloud);
        var azure = Azure
                    .Configure()
                    .WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic)
                    .Authenticate(credentials)
                    .WithSubscription(subscriptionId);
        if (azure.ResourceGroups.Contain(resourceGroupName) == false)
        {
            var resourceGroup = azure.ResourceGroups.Define(resourceGroupName)
                            .WithRegion(resourceGroupLocation)
                            .Create();
        }
        Console.WriteLine("start");
        var deployment = azure.Deployments.Define(deploymentName)
                    .WithExistingResourceGroup(resourceGroupName)
                    .WithTemplateLink(pathToTemplateFile, "1.0.0.0")
                    .WithParameters(parametesObjectv1)
                    .WithMode(Microsoft.Azure.Management.ResourceManager.Fluent.Models.DeploymentMode.Incremental)
                    .Create();

Besdes,如果您不想使用动态变量,则可以直接提供parameter.json和template.json的网址来创建资源

var deployment = azure.Deployments.Define(deploymentName)
                    .WithExistingResourceGroup(resourceGroupName)
                    .WithTemplateLink(pathToTemplateFile, "1.0.0.0")
                    .WithParametersLink(pathToJsonFile, "1.0.0.0")
                    .WithMode(Microsoft.Azure.Management.ResourceManager.Fluent.Models.DeploymentMode.Incremental)
                    .Create();

我能够通过构造基于参数类型的类来解决该问题,并制定了一种将参数值映射到ARM参数类型的方法。

ARM模板参数类提取:

namespace FuncApp.MSAzure.ARMTemplates.ARMParaneterTypes
{
    public class ParameterValueString
    {
        public string Value { get; set; }
    }

    public class ParameterValueArray
    {
        public string[] Value { get; set; }
    }

    public class ParameterBoolValue
    {
        public bool Value { get; set; }
    }
}

映射类方法摘录:

   public static AzNewVmRequestArmParameters ToArmParameters(
            this AzNewVmRequest requestContent,
            string adminUsername,
            string adminPassword
        )
    {

            return new AzNewVmRequestArmParameters
            {
                location = new ParameterValueString {
                    Value = requestContent.Location
                },
                adminUsername = new ParameterValueString
                {
                    Value = adminUsername
                },
                adminPassword = new ParameterValueString
                {
                    Value = adminPassword
                },
            };
        }

'AzNewVmRequestArmParameters'模型类摘录:

namespace FuncApp.MSAzure.VirtualMachines
{
    public class AzNewVmRequestArmParameters
    {

        public ParameterValueString location { get; set; }

        public ParameterValueString adminUsername { get; set; }

        public ParameterValueString adminPassword { get; set; }

    }
}

有了这些,我就可以在下面(简化的)运行以下代码,用API可以准备好的参数来公式化有效的jObject变量:

var parameters = azureVmDeploymentRequest.ToArmParameters(
   adminUsername: "azurevmadmin",
   adminPassword: "P@ssword123!"
);
var jParameters = JObject.FromObject(parameters);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM