Home > Back-end >  Output Azure Function powershell value to azure storage account
Output Azure Function powershell value to azure storage account

Time:03-22

I have a powershell script running in an azure function app that grabs a json list of IPs, parses it and just returns a list of IPs with 1 per line. I need to take this output and save it to a specific azure storage account. I'm attempting to use the static website in the storage account to create an HTTP endpoint for others to retrieve the list of IPs.

Here's the script

# Input bindings are passed in via param block.
param($Timer)

# Get the current universal time in the default string format.
$currentUTCtime = (Get-Date).ToUniversalTime()

# The 'IsPastDue' property is 'true' when the current function invocation is later than scheduled.
if ($Timer.IsPastDue) {
    Write-Host "PowerShell timer is running late!"
}

# Write an information log with the current time.
Write-Host "PowerShell timer trigger function ran! TIME: $currentUTCtime"

#-------------------------------------------------------------------------------------------

$url = "https://ip-ranges.atlassian.com/"

Invoke-RestMethod $url

$iplist = Invoke-RestMethod $url

$iplist.items | select-object -ExpandProperty cidr

out-file $outputBlob

I've tested the function in azure and it runs there just fine. I can't seem to get the integration outputs section of the function app to work. The settings for the outputs is

Binding type - azure blob storage
blob paramter name - outputBlob
Path - test/list.txt
storage account connection - searched and selected the storage account

I am not finding much documentation on how to make my powershell script output to this storage account. The out-file clearly doesn't work.

----------- updated code ----------

Here is the code that now successfully saves the file to a container, but I still cant save to the $web container for the static website. The $ is not something I can use in the output binding

# Input bindings are passed in via param block.
param($Timer)

# Get the current universal time in the default string format.
$currentUTCtime = (Get-Date).ToUniversalTime()

# The 'IsPastDue' property is 'true' when the current function invocation is later than scheduled.
if ($Timer.IsPastDue) {
    Write-Host "PowerShell timer is running late!"
}

# Write an information log with the current time.
Write-Host "PowerShell timer trigger function ran! TIME: $currentUTCtime"


#------------------------

$url = "https://ip-ranges.atlassian.com/" 

Invoke-RestMethod $url

$call = Invoke-RestMethod $url

$iplist = $call.items | select-object -ExpandProperty cidr

$output = out-string -InputObject $iplist

Push-OutputBinding -Name outputBlob -Value $output

the outputBlob binding is configured under integration > outputs > and the Path which is in the format of container/file. I cannot specify $web/file.txt...but if I do web/file.txt it will create a web container and put the output as file.txt within it. I need to do this, but it must go in the $web container.

CodePudding user response:

This is something that I've been meaning to try for a little while but not actually got around to. Decided to give it a shot today when I seen your question.

So it is possible to push content using the blob output binding but the functionality is limited.

run.ps1

using namespace System.Net

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

# Call the atlassian API to get the address ranges
$atlassianUri = "https://ip-ranges.atlassian.com/"
$iplist = Invoke-RestMethod $atlassianUri -ErrorAction Stop
$cidrList = $iplist.items | select-object -ExpandProperty cidr

# Push the contents to blob storage using the outputBinding
Push-OutputBinding -Name myOutputBlob -Value $cidrList

# Return a simple response so I know it worked
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
    StatusCode = [HttpStatusCode]::OK
    Body = 'Successfully Updated Blob Storage'
})

function.json

You would have to include an timer Input Binding in your function but I used HTTP so that I could trigger it on-demand to test that it would work.

I have provided a static path to the blob output binding. The Path property can not be dynamically assigned from within the function yet according to this open GitHub issue.

{
  "bindings": [
    {
      "authLevel": "function",
      "type": "httpTrigger",
      "direction": "in",
      "name": "Request",
      "methods": [
        "get",
        "post"
      ]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "Response"
    },
    {
      "name": "myOutputBlob",
      "type": "blob",
      "path": "functioncopy/ipRanges.txt",
      "connection": "MyStorageConnectionAppSetting",
      "direction": "out"
    }
  ]
}

The above code works however when sending the data to the blob file in the storage account Push-OutputBinding serialises the content to a JSON array e.g.

Storage Account Screenshot

This may or may not work for you in it's current guise but I don't think there is a way using the output binding to just have a raw list.

You could however use the Az.Storage module within your function, create the file within your function execution and upload it that way instead

run.ps1

# Variables required - Fill these out
$storageAccountName = '<Insert Storage Account Here'
$containerName = '<Insert StorageContainer Name Here>'
$resourceGroupName = '<Insert resourceGroup Name Here>'
$subscriptionId = '<Insert subscriptionId Here>'

# Call the atlassian API to get the address ranges
$atlassianUri   = "https://ip-ranges.atlassian.com/"
$iplist         = Invoke-RestMethod $atlassianUri -ErrorAction Stop
$cidrList       = $iplist.items | select-object -ExpandProperty cidr

# New-TemporaryFile uses [System.IO.Path]::GetTempPath() location
$tempFile = New-TemporaryFile

# Set the context to the subscription you want to use
# If your functionApp has access to more than one subscription it will load the first subscription by default.
# Possibly a good habit to be explicit about context.
Set-AzContext -Subscription $subscriptionId

# Get the Storage Account Key to authenticate
$storAccKeys = Get-AzStorageAccountKey -ResourceGroupName $resourceGroupName -Name $storageAccountName
$primaryKey = $storAccKeys | Where-Object keyname -eq 'key1' | Select-Object -ExpandProperty value

# Write the CIDR list to the temp file created earlier
$cidrList | Out-File $tempFile

# Create a Storage Context which will be used in the subsequent commands
$storageContext = New-AzStorageContext -StorageAccountName $storageAccountName -StorageAccountKey $primaryKey

# Upload the temp file to blob storage
$setAzStorageBlobContentSplat = @{
    Container  = $containerName
    File       = $tempFile.FullName
    Blob       = 'ipranges.txt'
    Context    = $storageContext
    Properties = @{
        ContentType = 'text/plain'
    }
}

Set-AzStorageBlobContent @setAzStorageBlobContentSplat

# Return a simple response so I know it worked
Push-OutputBinding -Name Response -Value (
    [HttpResponseContext]@{
        StatusCode = [HttpStatusCode]::OK
        Body       = 'Successfully Updated Blob Storage'
    }
)

You can see the documentation on Set-AzStorageBlobContent for examples on that here: https://docs.microsoft.com/en-us/powershell/module/az.storage/set-azstorageblobcontent?view=azps-6.2.1#examples

  • Related