GoogleCloudPlatform / google-cloud-powershell

PowerShell cmdlets for the Google Cloud Platform
http://googlecloudplatform.github.io/google-cloud-powershell/
Apache License 2.0
135 stars 61 forks source link

Get-GceMetadata does not raise errors #644

Open chilversc opened 4 years ago

chilversc commented 4 years ago

When using the Get-GceMetadata cmdlet it doesn't seem to write errors to the error stream or throw exceptions when the metadata server returns an error such as 404.

Currently there doesn't seem to be a reasonable way to detect that there was an error.

Steps to reproduce

$ErrorActionPreference = "Continue"
Write-Host "Test 1"
$Result = Get-GceMetadata -Path instance/attributes/non-existent
Write-Host "Result: ${Result}"
$ErrorActionPreference = "Stop"
Write-Host "Test 2"
$Result = Get-GceMetadata -Path instance/attributes/non-existent
Write-Host "Result: ${Result}"

Expected result

Test 1 should output a blank result and the console should show the error text (normally in red). Test 2 shouldn't show any output as script should halt

Actual result

The error response is stored in $Result. When writing the result to the console it dumps a large block of HTML that contains a description of the error (e.g. 404).

Workarounds

Invoke-RestMethod

function Get-Metadata {
  [CmdletBinding()]
  param (
    [Parameter($Mandatory = $true)] [string] $Path
  )
  Invoke-RestMethod -Headers @{ "Metadata-Flavor" = "Google" } "http://metadata.google.internal/computeMetadata/v1/$Path"
}

$Result = Get-Metadata -Path instance/attributes/non-existent

Get-GceInstance

Many of the properties you need from the metadata are available directly from the instance object model. However, obtaining a specific metadata attribute by name can be a awkward.


function Get-MetadataAttribute {
  [CmdletBinding()]
  param (
    [Parameter($Mandatory = $true)] [string] $Name
  )
  $Instance = Get-GceInstance
  $Item = ($Instance.Metadata.Items | Where-Object Key -eq $Name)
  if ($Item -eq $null) {
    Write-Error "Metadata does not contain an attribute named '${Name}'"
  }
  return $Item.Value
}
chilversc commented 4 years ago

Looks like https://github.com/GoogleCloudPlatform/google-cloud-powershell/blob/b0549f98b2a150830ff6ddf10c66c3252df7626d/Google.PowerShell/Compute/GceMetadataCmdlet.cs#L161 is missing a call to response.EnsureSuccessCode() before accessing response.Content.