0

We are using AzureCLI to be able to call an Azure Function endpoint upon a successful deployment. The call to get token works and the call to our azure function makes it into MyFunction.

The problem is the format of the body when it arrives.

If we include the -Compress for ConvertTo-Json, the body arrives like {ResourceId:3,BuildPipelineName:ResourceName} and System.Text.Json.JsonSerializer.Deserialize throws 'R' is an invalid start of a property name. Expected a '"'. LineNumber: 0 | BytePositionInLine: 1.

If we don't include the -Compress for ConvertTo-Json, the body arrives like { and throws Expected depth to be zero at the end of the JSON payload. There is an open JSON object or array that should be closed. LineNumber: 0 | BytePositionInLine: 1.

      runOnce:
        deploy:
          steps:
            - template: ./deployment.yml    

        on:  # On success or failure hook for runOnce deployment strategy
          success:  # Runs on success of all of the steps
            steps:
              - task: AzureCLI@2
                inputs:
                  azureSubscription: 'MyServiceConnectionName'
                  scriptType: ps
                  scriptLocation: inlineScript
                  inlineScript: |
                    $functionKeys = az functionapp function keys list -g my-resource-group -n my-azure-function-name --function-name MyFunction | ConvertFrom-Json
                    $defaultKey = $functionKeys.default
                    
                    $body = @{ 
                        ResourceId="$(Environment.ResourceId)";
                        ResourceName="$(Environment.ResourceName)";
                        } | ConvertTo-Json -Compress 
                    echo body: $body

                    $url2 = "https://my-azure-function-name.azurewebsites.net/api/MyFunction?code=$defaultKey"

                    $response = az rest --method post --uri $url2 --skip-authorization-header --verbose --body $body
                    echo response: $response

We've tried adding the following json options to JsonSerializer.Deserialize but with no change in behavior

        var jsonOptions = new JsonSerializerOptions
        {
            PropertyNameCaseInsensitive = true,
            ReadCommentHandling = JsonCommentHandling.Skip,
            AllowTrailingCommas = true,
            NumberHandling = JsonNumberHandling.AllowReadingFromString
        };

We've also tried changing the body creation to be a single line like:

  $body = @{ResourceId="$(Environment.ResourceId)";ResourceName="$(Environment.ResourceName)" } | ConvertTo-Json -Compress

We are new to both PowerShell and .NET6. We will gladly attempt changes on either side. Anything that may make this request succeed will be much appreciated.

Thank you for sharing your hard earned knowledge.

cResults
  • 733
  • 1
  • 5
  • 17
  • `{ResourceId:3,BuildPipelineName:ResourceName}` should be `{"ResourceId:"3,"BuildPipelineName":"ResourceName"}` as you can see executing `$body = @{ResourceId=$env:COMPUTERNAME;ResourceName=$Env:NUMBER_OF_PROCESSORS;} | ConvertTo-Json -Compress` – JPBlanc May 12 '22 at 03:23

1 Answers1

0

Az rest is very sensitive about the format of JSON input. For example, it requires double quotes to be escaped, even on Windows. It also doesn't like newlines, as you already noticed.

Try this way:

$body = (@{
  ResourceId="$(Environment.ResourceId)";
  ResourceName="$(Environment.ResourceName)";
} | ConvertTo-Json -Compress).Replace('"', '\"')

This will escape double quotes (bash style).

I would also recommend changing scriptType to pscore in your pipeline (it's supported on both Windows and Linux agents).

qbik
  • 5,502
  • 2
  • 27
  • 33
  • Thank you adding the Replace after the ConvertTo_Json -Compress worked; Thank you. I started off using pscore, but the machines that we are deploying to are all windows and unfortunately don't yet have pscore installed on them. – cResults May 17 '22 at 00:10
  • Now that I better understand, a better question would have been "How to create a JSON object with PowerShell" and there are likely a number of posts that answer that. I suspect that I had too many ancillary works in my questions such that Google couldn't find an answer. Thank you. – cResults May 17 '22 at 00:13
  • 1
    Actually, the way you did it was correct from PowerShell perspective. If you dumped that to a file, that would be a perfectly valid JSON. It's rather a matter of `az rest` quirk. So a good title would be "How to pass JSON to az rest CLI from Powershell" – qbik May 17 '22 at 10:24