Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get-AzAutomationDscNode #10404

Closed
NolanCui719 opened this issue Oct 28, 2019 · 13 comments
Closed

Get-AzAutomationDscNode #10404

NolanCui719 opened this issue Oct 28, 2019 · 13 comments
Assignees
Labels
Automation bug This issue requires a change to an existing behavior in the product in order to be resolved. customer-reported Service Attention This issue is responsible by Azure service team.

Comments

@NolanCui719
Copy link

Description

These are the commands I run with values hard-coded:

$node = Get-AzAutomationDscNode -ResourceGroupName "xx" -Name "xx" -AutomationAccountName "xx" | ? { $_.Name -eq "xx" }
$node.Id
Get-AzAutomationDscNodeReport -NodeId $node.Id -ResourceGroupName "xx" -AutomationAccountName "xx"

Results:
Get-AzAutomationDscNodeReport -NodeId $node.Id -ResourceGroupName "xx" -AutomationAccountName "xx"
Get-AzAutomationDscNodeReport : Value cannot be null.
Parameter name: stringToEscape
At line:1 char:1

  • Get-AzAutomationDscNodeReport -NodeId $node.Id -ResourceGroupName "WL ...
  •   + CategoryInfo          : CloseError: (:) [Get-AzAutomationDscNodeReport], ArgumentNullException
      + FullyQualifiedErrorId : Microsoft.Azure.Commands.Automation.Cmdlet.GetAzureAutomationDscNodeReport
    
    

Steps to reproduce

Get-AzAutomationDscNodeReport -NodeId $node.Id -ResourceGroupName "xx" -AutomationAccountName "xx"

Environment data


Module versions

Debug output

DEBUG: AzureQoSEvent: CommandName - Get-AzureRmAutomationDscNodeReport; IsSuccess - False; Duration -
00:00:02.5658166; Exception - System.ArgumentNullException: Value cannot be null.
Parameter name: stringToEscape
   at System.Uri.EscapeDataString(String stringToEscape)
   at Microsoft.Azure.Commands.Automation.Common.AutomationPSClient.GetNodeReportListFilterString(String type,
Nullable`1 startTime, Nullable`1 endTime, Nullable`1 lastModifiedTime)
   at Microsoft.Azure.Commands.Automation.Common.AutomationPSClient.ListDscNodeReports(String resourceGroupName,
String automationAccountName, Guid nodeId, Nullable`1 startTime, Nullable`1 endTime, String& nextLink)
   at Microsoft.Azure.Commands.Automation.Cmdlet.GetAzureAutomationDscNodeReport.ExecuteCmdlet()
   at Microsoft.WindowsAzure.Commands.Utilities.Common.AzurePSCmdlet.ProcessRecord();
DEBUG: Finish sending metric.
DEBUG: 14:10:15 - GetAzureAutomationDscNodeReport end processing.

Error output

At line:1 char:1

  • Get-AzAutomationDscNodeReport -NodeId $node.Id -ResourceGroupName "WL ...
  •   + CategoryInfo          : CloseError: (:) [Get-AzAutomationDscNodeReport], ArgumentNullException
      + FullyQualifiedErrorId : Microsoft.Azure.Commands.Automation.Cmdlet.GetAzureAutomationDscNodeReport
    
only we I add -lastest in this vlue, it can work. But as my understanding that is a conditional value. 

Reference:
https://docs.microsoft.com/en-us/powershell/module/az.automation/get-azautomationdscnodereport?view=azps-2.8.0

@wyunchi-ms wyunchi-ms added Automation customer-reported Service Attention This issue is responsible by Azure service team. and removed triage labels Oct 29, 2019
@ghost
Copy link

ghost commented Oct 29, 2019

Thanks for the feedback! We are routing this to the appropriate team for follow-up. cc @zjalexander

1 similar comment
@ghost
Copy link

ghost commented Oct 29, 2019

Thanks for the feedback! We are routing this to the appropriate team for follow-up. cc @zjalexander

@mgreenegit
Copy link
Member

I am able to repro this issue. cc @nitinbps

Output:
Get-AzAutomationDscNodeReport: Value cannot be null. (Parameter 'stringToEscape')

When I use -latest, there is no issue. As reported above.

@zjalexander zjalexander added the bug This issue requires a change to an existing behavior in the product in order to be resolved. label Oct 30, 2019
@VLoub
Copy link

VLoub commented Nov 28, 2019

+1

I am experiencing same issue, only -Latest works here

Also with added start and end time dosen't work

Get-AzAutomationDscNodeReport @GetAzAutomationDscNodeReportParams -StartTime ([DateTimeOffset]::Now.AddDays(-1)) -EndTime ([DateTimeOffset]::Now)

@Elestriel
Copy link

Hello!

I can confirm this issue. The only way this Cmdlet works is with -Latest. Without it, or with -EndTime instead, I get:
Get-AzAutomationDscNodeReport : Value cannot be null. Parameter name: stringToEscape

I tried adding a -stringToEscape parameter, but that, unsurprisingly, led to
Get-AzAutomationDscNodeReport : A parameter cannot be found that matches parameter name 'stringToEscape'.

@andyw248 andyw248 assigned vikram-m and Vikram1988 and unassigned mgreenegit and Vikram1988 Dec 23, 2019
@vikram-m
Copy link

There is dependency on -Latest parameter being mandatory. As there is already a workaround, we will be picking up in Q4CY20.

@vikram-m
Copy link

Currently, team is busy with other high priority items and this would be picked up in CY2021 Q1.

@Bhargava-Chary-Chollaty
Copy link
Member

Bhargava-Chary-Chollaty commented Jul 2, 2021

This issue can be worked around using Invoke-AzRestMethod. Below is a alternative implementation of the command. It will work the way the official commandlet is expected to work.

function Get-AzAutomationDscNodeReport {
   param (
        # SubscriptionId
        [Parameter(Mandatory = $False)]
        [string]
        $SubscriptionId = $null,

        # ResourceGroupName
        [Parameter(Mandatory = $True)]
        [string]
        $ResourceGroupName,

        # Automation Account Name
        [Parameter(Mandatory = $True)]
        [string]
        $AutomationAccountName,

        # Node Id
        [Parameter(Mandatory = $True)]
        [guid]
        $NodeId,

        # Switch Parameter for Latest Report
        [Parameter(Mandatory = $False, ParameterSetName = "Latest")]
        [switch]
        $Latest,

        # StartTime, reports that are received after this time
        [Parameter(Mandatory = $False, ParameterSetName = "StartTime")]
        [DateTime]
        $StartTime,

        # EndTime, reports that are received after this time
        [Parameter(Mandatory = $False, ParameterSetName = "EndTime")]
        [DateTime]
        $EndTime,

        # Api Version
        [Parameter(Mandatory = $False)]
        [string]
        $ApiVersion = "2018-01-15"
    )

    if ([System.String]::IsNullOrEmpty($SubscriptionId)) {
        $SubscriptionId = (Get-AzContext).Subscription.Id
    }

    $Uri = "subscriptions/$SubscriptionId/resourceGroups/$ResourceGroupName/providers/Microsoft.Automation/automationAccounts/$AutomationAccountName/nodes/$NodeId/reports?api-version=$ApiVersion"

    $nodeReports = @()

    try {

        if ($PsCmdlet.ParameterSetName -eq 'Latest') {
            $Uri += '&$top=1' 
        } 
        elseif ($PsCmdlet.ParameterSetName -eq 'StartTime') {
            $Uri += "&`$filter=startTime ge $($StartTime.ToUniversalTime().ToString('yyyy-MM-dd'))" 
        } 
        elseif ($PsCmdlet.ParameterSetName -eq 'EndTime') {
            $Uri += "&`$filter=endTime le $($EndTIme.ToUniversalTime().ToString('yyyy-MM-dd'))" 
        }      

        while ($True) {
            $response = Invoke-AzRestMethod -Path $Uri -Method GET -ErrorAction Ignore

            if ($response.StatusCode -eq 200) {
                $responseObject = $response.Content | ConvertFrom-Json
                if ($null -ne $responseObject -and $null -ne $responseObject.value) {
                    $nodeReports += $responseObject.value

                    if (-not [System.String]::IsNullOrEmpty($responseObject.nextLink)) {
                        $Uri = [System.Uri]::new($responseObject.nextLink).PathAndQuery
                        continue
                    }
                }     
                return $nodeReports
            }
            elseif ($response.StatusCode -eq 404) {
                Write-Warning "Node not found"
                return $nodeReports
            }
            else {
                throw "Server returned unsuccess statuscode. $($response.StatusCode)"
            }   
        }               
    }
    catch {
        Write-Warning "Error occured while getting the node reports. Exception $_"
        throw $_
    }    
}

Examples:

  1. Retrieve all reports for a node.
    Get-AzAutomationDscNodeReport -ResourceGroupName <ResourceGroupName> -AutomationAccountName <AutomationAccountName> -NodeId <NodeId>

  2. Retrieve latest report for a node.
    Get-AzAutomationDscNodeReport -ResourceGroupName <ResourceGroupName> -AutomationAccountName <AutomationAccountName> -NodeId <NodeId> -Latest

  3. Retrieve all reports received by automation after datetime
    Get-AzAutomationDscNodeReport -ResourceGroupName <ResourceGroupName> -AutomationAccountName <AutomationAccountName> -NodeId <NodeId> -StartTime ([DateTime]::Now).AddDays(-3)

  4. Retrieve all reports received by automation before datetime
    Get-AzAutomationDscNodeReport -ResourceGroupName <ResourceGroupName> -AutomationAccountName <AutomationAccountName> -NodeId <NodeId> -EndTime ([DateTime]::Now)

@SatishBoddu-MSFT SatishBoddu-MSFT removed the Service Attention This issue is responsible by Azure service team. label Dec 3, 2021
@ghost ghost added the needs-team-triage label Dec 3, 2021
@SatishBoddu-MSFT SatishBoddu-MSFT added Service Attention This issue is responsible by Azure service team. and removed needs-team-triage labels Dec 3, 2021
@ghost
Copy link

ghost commented Dec 3, 2021

Thanks for the feedback! We are routing this to the appropriate team for follow-up. cc @jaspkaur28.

Issue Details

Description

These are the commands I run with values hard-coded:

$node = Get-AzAutomationDscNode -ResourceGroupName "xx" -Name "xx" -AutomationAccountName "xx" | ? { $_.Name -eq "xx" }
$node.Id
Get-AzAutomationDscNodeReport -NodeId $node.Id -ResourceGroupName "xx" -AutomationAccountName "xx"

Results:
Get-AzAutomationDscNodeReport -NodeId $node.Id -ResourceGroupName "xx" -AutomationAccountName "xx"
Get-AzAutomationDscNodeReport : Value cannot be null.
Parameter name: stringToEscape
At line:1 char:1

  • Get-AzAutomationDscNodeReport -NodeId $node.Id -ResourceGroupName "WL ...
  •   + CategoryInfo          : CloseError: (:) [Get-AzAutomationDscNodeReport], ArgumentNullException
      + FullyQualifiedErrorId : Microsoft.Azure.Commands.Automation.Cmdlet.GetAzureAutomationDscNodeReport
    
    

Steps to reproduce

Get-AzAutomationDscNodeReport -NodeId $node.Id -ResourceGroupName "xx" -AutomationAccountName "xx"

Environment data


Module versions

Debug output

DEBUG: AzureQoSEvent: CommandName - Get-AzureRmAutomationDscNodeReport; IsSuccess - False; Duration -
00:00:02.5658166; Exception - System.ArgumentNullException: Value cannot be null.
Parameter name: stringToEscape
   at System.Uri.EscapeDataString(String stringToEscape)
   at Microsoft.Azure.Commands.Automation.Common.AutomationPSClient.GetNodeReportListFilterString(String type,
Nullable`1 startTime, Nullable`1 endTime, Nullable`1 lastModifiedTime)
   at Microsoft.Azure.Commands.Automation.Common.AutomationPSClient.ListDscNodeReports(String resourceGroupName,
String automationAccountName, Guid nodeId, Nullable`1 startTime, Nullable`1 endTime, String& nextLink)
   at Microsoft.Azure.Commands.Automation.Cmdlet.GetAzureAutomationDscNodeReport.ExecuteCmdlet()
   at Microsoft.WindowsAzure.Commands.Utilities.Common.AzurePSCmdlet.ProcessRecord();
DEBUG: Finish sending metric.
DEBUG: 14:10:15 - GetAzureAutomationDscNodeReport end processing.

Error output

At line:1 char:1

  • Get-AzAutomationDscNodeReport -NodeId $node.Id -ResourceGroupName "WL ...
  •   + CategoryInfo          : CloseError: (:) [Get-AzAutomationDscNodeReport], ArgumentNullException
      + FullyQualifiedErrorId : Microsoft.Azure.Commands.Automation.Cmdlet.GetAzureAutomationDscNodeReport
    
only we I add -lastest in this vlue, it can work. But as my understanding that is a conditional value. 

Reference:
https://docs.microsoft.com/en-us/powershell/module/az.automation/get-azautomationdscnodereport?view=azps-2.8.0

Author: NolanCui719
Assignees: vikram-m
Labels:

Automation, Service Attention, bug, customer-reported

Milestone: -

@jaspkaur28
Copy link

@SatishBoddu-MSFT Automation team has given a workaround for the issue. Please try and confirm.

@navba-MSFT
Copy link
Contributor

@NolanCui719 Apologies for the late reply. Please let us know if you had a chance to follow the workaround suggested here. Also this github thread has been open for quite sometime. Could you please let us know if you still need assistance on this issue ? Awaiting your reply.

@BCOps
Copy link

BCOps commented Jun 7, 2022

@navba-MSFT - Not OP, but I too have the same problem with Get-AzAutomationDscNodeReport, only -Latest works otherwise I receive the same error. I have tried the workaround and I receive the same issue.
There must be something in the way the cmdlet is returning multiple reports, rather than just one using -latest, which causes it to fail.

I've taken a look at the Azure Powershell repo. I confess I am out of my depth here... The below could be completely wrong but it is just a discrepency that I have spotted and am curious if it is the root of the issue due to the error relating to the URI escape string:

Parameter name: stringToEscape
   at System.Uri.EscapeDataString(String stringToEscape)

I note that the majority of the string properties referenced in AutomationPSClientDSC.cs are using escape strings added to their URIs, but all of them check for NOT rather than IS, apart from GetNodeReportListFilterString (which is called from GetAzureAutomationDscNodeReport.cs -> AutomationClient.ListDscNodeReports -> this.GetNodeReportListFilterString)

i.e.
private string GetDscJobFilterString = this checks for NOT null or white space on the string values of certain elements, and applies an escape string to the returned URI

private string GetDscJobFilterString(string configurationName, DateTimeOffset? startTime, DateTimeOffset? endTime, string jobStatus)
        {
            string filter = null;
            List<string> odataFilter = new List<string>();
            if (startTime.HasValue)
            {
                odataFilter.Add("properties/startTime ge " + this.FormatDateTime(startTime.Value));
            }
            if (endTime.HasValue)
            {
                odataFilter.Add("properties/endTime le " + this.FormatDateTime(endTime.Value));
            }
            if (!string.IsNullOrWhiteSpace(jobStatus))
            {
                odataFilter.Add("properties/status eq '" + Uri.EscapeDataString(jobStatus) + "'");
            }
            if (!string.IsNullOrWhiteSpace(configurationName))
            {
                odataFilter.Add("properties/configuration/name eq '" + Uri.EscapeDataString(configurationName) + "'");
            }
            if (odataFilter.Count > 0)
            {
                filter = string.Join(" and ", odataFilter);
            }`

            return filter;
        }

However, GetNodeReportListFilterString does not check for NOT string (note the missing ! and instead checks for IS)

        private string GetNodeReportListFilterString(string type, DateTimeOffset? startTime, DateTimeOffset? endTime, DateTimeOffset? lastModifiedTime)
        {
            string filter = null;
            List<string> odataFilter = new List<string>();
            if (startTime.HasValue)
            {
                odataFilter.Add("properties/startTime ge " + this.FormatDateTime(startTime.Value));
            }
            if (endTime.HasValue)
            {
                odataFilter.Add("properties/endTime le " + this.FormatDateTime(endTime.Value));
            }
            if (string.IsNullOrWhiteSpace(type))
            {
                odataFilter.Add("properties/type eq '" + Uri.EscapeDataString(type) + "'");
            }
            if (lastModifiedTime.HasValue)
            {
                odataFilter.Add("properties/lastModifiedTime ge " + this.FormatDateTime(startTime.Value));
            }
            if (odataFilter.Count > 0)
            {
                filter = string.Join(" and ", odataFilter);
            }

            return filter;
        }

Could this be the cause of the issues? It seems to be only the Get-AzAutomationDscNodeReport cmdlet that refers to this string property, which may explain why only this cmdlet is affected. (If I am right about the cause, which I may not be!)

@Jassingh819
Copy link
Contributor

Thanks @BCOps for looking into this. It was a typo. Fixed in the above PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Automation bug This issue requires a change to an existing behavior in the product in order to be resolved. customer-reported Service Attention This issue is responsible by Azure service team.
Projects
None yet
Development

No branches or pull requests