Azure Function gives "InvokeMethodOnNull" error when calling Start-AzContainerGroup

188 Views Asked by At

I have a basic Azure Function running Powershell. I have followed instructions from the Microsoft Learn Tutorial to create an HTTP trigger to start a Container Instance. I have modified the tutorial after various attempts, so that the code now just starts an existing Container Instance on my Azure tenant, as follows:

using namespace System.Net

# Input bindings are passed in via param block.
param($Request, $TriggerMetadata)

# Write to the Azure Functions log stream.
Write-Host "PowerShell HTTP trigger function processed a request."

# Interact with query parameters or the body of the request.
$command = $Request.Query.Command
if (-not $command) {
    $command = $Request.Body.Command
}

$body = "This HTTP triggered function executed successfully. Either pass 'start' or 'stop' as the 'command' parameter for the appropriate action to be executed on the acme-dns container."

if ($command) {
    $body = "Command received: $command"         
    if ($command = "start") {
        Start-AzContainerGroup -ResourceGroupName test -Name dev
    }
    elseif ($command = "stop") {
        Stop-AzContainerGroup -ResourceGroupName test -Name dev
    }

    if ($?) {
        $body = "This HTTP triggered function executed successfully. Started container group $name"
    }
    else  {
        $body = "There was a problem starting the container group."
    }
}

# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
    StatusCode = [HttpStatusCode]::OK
    Body = $body
})

requirements.psd1:

@{
    # For latest supported version, go to 'https://www.powershellgallery.com/packages/Az'.
    # To use the Az module in your function app, please uncomment the line below.
    'Az' = '9.*'
}

Error text when I try to debug locally:

Azure Functions Core Tools
Core Tools Version:       4.0.4915 Commit hash: N/A  (64-bit)
Function Runtime Version: 4.14.0.19631


Functions:

        HttpExample: [GET,POST] http://localhost:7071/api/HttpExample

For detailed output, run func with --verbose flag.
[2022-12-13T14:27:14.456Z] Worker process started and initialized.
[2022-12-13T14:27:18.512Z] Host lock lease acquired by instance ID '0000000000000000000000000713F6BA'.
[2022-12-13T14:27:38.039Z] Executing 'Functions.HttpExample' (Reason='This function was programmatically called via the host APIs.', Id=5b3c9e21-290f-4ff4-ac49-21f362414926)
[2022-12-13T14:27:38.238Z] INFORMATION: PowerShell HTTP trigger function processed a request.
[2022-12-13T14:27:56.862Z] EXCEPTION: You cannot call a method on a null-valued expression.
[2022-12-13T14:27:56.863Z]
[2022-12-13T14:27:56.863Z] Exception             :
[2022-12-13T14:27:56.864Z]     Type    : System.Management.Automation.ParentContainsErrorRecordException
[2022-12-13T14:27:56.865Z]     Message : You cannot call a method on a null-valued expression.
[2022-12-13T14:27:56.866Z]     HResult : -2146233087
[2022-12-13T14:27:56.867Z] CategoryInfo          : InvalidOperation: (:) [], ParentContainsErrorRecordException
[2022-12-13T14:27:56.868Z] FullyQualifiedErrorId : InvokeMethodOnNull
[2022-12-13T14:27:56.869Z] InvocationInfo        :
[2022-12-13T14:27:56.870Z]     ScriptLineNumber : 1777
[2022-12-13T14:27:56.871Z]     OffsetInLine     : 13
[2022-12-13T14:27:56.872Z]     HistoryId        : -1
[2022-12-13T14:27:56.873Z]     ScriptName       : C:\Users\{USER}\Documents\PowerShell\Modules\Az.ContainerInstance\3.1.0\exports\ProxyCmdletDefinitions.ps1
[2022-12-13T14:27:56.874Z]     Line             : [Microsoft.WindowsAzure.Commands.Utilities.Common.AzurePSCmdlet]::PowerShellVersion = $Host.Runspace.Version.ToString()
[2022-12-13T14:27:56.875Z]
[2022-12-13T14:27:56.876Z]     PositionMessage  : At C:\Users\{USER}\Documents\PowerShell\Modules\Az.ContainerInstance\3.1.0\exports\ProxyCmdletDefinitions.ps1:1777 char:13
[2022-12-13T14:27:56.877Z]                        +             [Microsoft.WindowsAzure.Commands.Utilities.Common.AzurePS .
[2022-12-13T14:27:56.878Z]                        +             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[2022-12-13T14:27:56.879Z]     PSScriptRoot     : C:\Users\{USER}\Documents\PowerShell\Modules\Az.ContainerInstance\3.1.0\exports
[2022-12-13T14:27:56.880Z]     PSCommandPath    : C:\Users\{USER}\Documents\PowerShell\Modules\Az.ContainerInstance\3.1.0\exports\ProxyCmdletDefinitions.ps1
[2022-12-13T14:27:56.881Z]     CommandOrigin    : Internal
[2022-12-13T14:27:56.882Z] ScriptStackTrace      : at Start-AzContainerGroup<Begin>, C:\Users\{USER}\Documents\PowerShell\Modules\Az.ContainerInstance\3.1.0\exports\ProxyCmdletDefinitions.ps1: line 1777
[2022-12-13T14:27:56.883Z]                         at <ScriptBlock>, C:\Coding\AzFunctions\PsHttpTrigger\HttpExample\run.ps1: line 20
[2022-12-13T14:27:56.884Z]
[2022-12-13T14:27:56.884Z]
[2022-12-13T14:27:56.913Z] Executed 'Functions.HttpExample' (Failed, Id=5b3c9e21-290f-4ff4-ac49-21f362414926, Duration=18894ms)
[2022-12-13T14:27:56.914Z] System.Private.CoreLib: Exception while executing function: Functions.HttpExample. System.Private.CoreLib: Result: Failure
Exception: You cannot call a method on a null-valued expression.
Stack:    at System.Management.Automation.Runspaces.PipelineBase.Invoke(IEnumerable input)
[2022-12-13T14:27:56.914Z]    at System.Management.Automation.Runspaces.Pipeline.Invoke()
[2022-12-13T14:27:56.915Z]    at System.Management.Automation.PowerShell.Worker.ConstructPipelineAndDoWork(Runspace rs, Boolean performSyncInvoke)
[2022-12-13T14:27:56.916Z]    at System.Management.Automation.PowerShell.Worker.CreateRunspaceIfNeededAndDoWork(Runspace rsToUse, Boolean isSync)
[2022-12-13T14:27:56.917Z]    at System.Management.Automation.PowerShell.CoreInvokeHelper[TInput,TOutput](PSDataCollection`1 input, PSDataCollection`1 output, PSInvocationSettings settings)       
[2022-12-13T14:27:56.917Z]    at System.Management.Automation.PowerShell.CoreInvoke[TInput,TOutput](PSDataCollection`1 input, PSDataCollection`1 output, PSInvocationSettings settings)
[2022-12-13T14:27:56.918Z]    at System.Management.Automation.PowerShell.Invoke[T](IEnumerable input, IList`1 output, PSInvocationSettings settings)
[2022-12-13T14:27:56.919Z]    at System.Management.Automation.PowerShell.Invoke[T]()
[2022-12-13T14:27:56.919Z]    at Microsoft.Azure.Functions.PowerShellWorker.PowerShell.PowerShellExtensions.InvokeAndClearCommands[T](PowerShell pwsh) in /mnt/vss/_work/1/s/src/PowerShell/PowerShellExtensions.cs:line 45
[2022-12-13T14:27:56.920Z]    at Microsoft.Azure.Functions.PowerShellWorker.PowerShell.PowerShellManager.InvokeNonOrchestrationFunction(DurableController durableController, IDictionary outputBindings) in /mnt/vss/_work/1/s/src/PowerShell/PowerShellManager.cs:line 301
[2022-12-13T14:27:56.921Z]    at Microsoft.Azure.Functions.PowerShellWorker.PowerShell.PowerShellManager.InvokeFunction(AzFunctionInfo functionInfo, Hashtable triggerMetadata, TraceContext traceContext, RetryContext retryContext, IList`1 inputData, FunctionInvocationPerformanceStopwatch stopwatch) in /mnt/vss/_work/1/s/src/PowerShell/PowerShellManager.cs:line 230
[2022-12-13T14:27:56.922Z]    at Microsoft.Azure.Functions.PowerShellWorker.RequestProcessor.InvokeFunction(AzFunctionInfo functionInfo, PowerShellManager psManager, FunctionInvocationPerformanceStopwatch stopwatch, InvocationRequest invocationRequest) in /mnt/vss/_work/1/s/src/RequestProcessor.cs:line 336
[2022-12-13T14:27:56.923Z]    at Microsoft.Azure.Functions.PowerShellWorker.RequestProcessor.ProcessInvocationRequestImpl(StreamingMessage request, AzFunctionInfo functionInfo, PowerShellManager psManager, FunctionInvocationPerformanceStopwatch stopwatch) in /mnt/vss/_work/1/s/src/RequestProcessor.cs:line 308.

It seems to me that the $Host variable within the AzurePS module is null, but I have no idea how to go about fixing this.

When I run the function from Azure cloud, it times out (Error: 500 - The request timed out. The web server failed to respond within the specified time.)

Running Start-AzContainerGroup from Powershell on my local PC works just fine.

1

There are 1 best solutions below

0
On

I have modified your code accordingly for the requirement of Starting and stopping the Azure Container groups using PowerShell Azure Functions and it's working as expected:

using  namespace  System.Net

# Input bindings are passed in via param block.
param($Request, $TriggerMetadata)

# Write to the Azure Functions log stream.
Write-Host  "PowerShell HTTP trigger function processed a request."

Connect-AzAccount -Tenant 'TeantId' -SubscriptionId 'SubscriptionId'
Set-AzContext -Subscription 'SubscriptionId'
  
$command = $Request.Query.Command
if (-not $command) {
$command = $Request.Body.Command
}

$body = "This HTTP triggered function executed successfully. Either pass 'start' or 'stop' as the 'command' parameter for the appropriate action to be executed on the acme-dns container."


if ($command) {
Write-Host  "Command received: $command"

if ($command = "start") {

Start-AzContainerGroup -ResourceGroupName HariTestRG -Name test-cg
$body = "This HTTP triggered function executed successfully. Started container group."
}

elseif ($command = "stop") {

Stop-AzContainerGroup -ResourceGroupName HariTestRG -Name test-cg
$body = "This HTTP triggered function executed successfully. Stopped container group."
    }
}

Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
StatusCode = [HttpStatusCode]::OK
Body = $body
})

Function API Response: enter image description here

Result of Input Parameter to the Function API as Command = Start: enter image description here

Before running this function, I have created the Container Group in Azure using these PowerShell Cmdlets:

$port1 = New-AzContainerInstancePortObject -Port 8000 -Protocol TCP
$port2 = New-AzContainerInstancePortObject -Port 8001 -Protocol TCP
$container = New-AzContainerInstanceObject -Name test-container -Image nginx -RequestCpu 1 -RequestMemoryInGb 1.5 -Port @($port1, $port2)
$containerGroup = New-AzContainerGroup -ResourceGroupName HariTestRG -Name test-cg -Location eastus -Container $container -OsType Linux -RestartPolicy "Never" -IpAddressType Public

Note: Few Parts of the above code taken from the MS Doc Reference 1 & 2.