0 (Insider Preview) New Programming Model
Francisco Gamino редактировал(а) эту страницу 2023-07-17 14:18:43 -07:00
Этот файл содержит невидимые символы Юникода!

Этот файл содержит невидимые символы Юникода, которые могут быть отображены не так, как показано ниже. Если это намеренно, можете спокойно проигнорировать это предупреждение. Используйте кнопку Экранировать, чтобы показать скрытые символы.

The new v2 programming model is designed to provide an idiomatic development experience for PowerShell developers. Although this new experience is yet be released (timeline TBD), you can use this document to learn more about it and test it out locally.

Why the new programming model?

In accordance with user feedback, we wanted to provide a more frictionless onboarding experience for customers that would simultaneously reduce the complexity of an app's code and file structure.

To that end, the Azure Functions PowerShell team reimagined PowerShell-based Azure Functions development by flattening an app's directory structure, allowing multiple function definitions within the same file, and reducing complexity by streamlining Function definitions and removing the language-agnostic function.json files.

Note that leveraging the v2 programming model will provide an improved and seamless way to create functions, with the underlying deployment, debugging, and monitoring experience remaining the same.

  • General Notes
  • Supported Today
  • Examples
  • Get Started

General Notes

  1. The only files that are scanned for functions are the ones in the function app root folder. Any other files may be used to contain helper functions,but function declarations must be at the root. EXAMPLE: bug-bash-app/functions.psm1 is scanned, but bug-bash-app/src/functions.psm1 will not be

  2. For the binding attributes, only named arguments are supported. Positional arguments will not work.

Comparing the v1 and v2 programming models

v1

run.ps1

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."

$body = "Hello from PowerShell v1 programming model"

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

function.json

{
  "bindings": [
    {
      "authLevel": "function",
      "type": "httpTrigger",
      "direction": "in",
      "name": "Request",
      "methods": [
        "get",
        "post"
      ]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "Response"
    }
  ]
}

v2

[Function()]  
param(  
  [HttpTrigger()]  
   $Request,  
  $TriggerMetadata  
)    
$value = ([HttpResponseContext]@{  
  StatusCode = [HttpStatusCode]::OK  
  Body = 'New Programming Model rules! (Hero executed)'  
})    
$value | Push-OutputBinding -Name Response  

Comparing the folder structure of v1 and v2:

The following is the folder structure for a function application containing three functions.

v1

  • .vscode
  • EventGridTrigger1
    • function.json
    • run.ps1
  • HttpTrigger1
    • function.json
    • run.ps1
  • TimerTrigger1
    • function.json
    • run.ps1
  • .funcignore
  • .gitignore
  • host.json
  • local.settings.json
  • profile.ps1
  • requirements.psd1

v2

  • .vsode
  • .funcignore
  • .gitignore
  • functions.ps1
  • host.json
  • local.settings.json
  • profile.ps1
  • requirements.psd1

As you can see, the folder structure of a function application using the v2 programming model is simpler and flat.

Supported Today

Triggers:

  • HTTP
  • Timer
  • EventGrid
  • EventHub
  • Orchestration
  • Activity

Output Bindings:

  • HTTP
  • EventHub

DurableClient is also supported!

You can also use a combination of InputBinding, OutputBinding, and AdditionalInformation to construct bindings of any other type. InputBinding and OutputBinding should be used to specify the type of binding, and AdditionalInformation allows you to add key-value pairs to that binding.

Examples

HTTP Trigger

using namespace System.Net  
using module AzureFunctions.PowerShell.SDK    
function HttpTriggerMinimal {  
  [Function()]  
  param(  
    [HttpTrigger()]  
    $Request,  
    $TriggerMetadata  
  )   
  $value = ([HttpResponseContext]@{  
    StatusCode = [HttpStatusCode]::OK  
    Body = 'New Programming Model rules! (Hero executed)'  
  })    
  $value | Push-OutputBinding -Name Response  
}  

function HttpTriggerMaximal {  
  [Function(Name='Trig')]  
  [HttpOutput(Name='Resp')]  
  param(  
    [HttpTrigger(AuthLevel='anonymous', Methods=('Get', 'Post'), Route='rerouted')]  
    $Request,  
    $TriggerMetadata  
  )  
  
  $value = ([HttpResponseContext]@{  
    StatusCode = [HttpStatusCode]::OK  
    Body = 'The Http trigger invocation was successful'  
  })  
  
  $value | Push-OutputBinding -Name Resp  
}  

Timer Trigger:

function TimerTriggerMinimal {  
  # Input bindings are passed in via param block.  
  param(  
    [TimerTrigger(Chron='0 */5 * * * *')]  
    $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"  
}  

EventGrid

function EventGridTrigger() {  
  [Function()]  
  param(  
    [EventGridTrigger()]  
    $Request,  
    $TriggerMetadata  
  )    
  $value = ([HttpResponseContext]@{  
    StatusCode = [HttpStatusCode]::OK  
    Body = 'The Http trigger invocation was successful'  
  })  
  
  $value | Push-OutputBinding -Name Response  
}  

EventHub

# NOTE: all 4 arguments are required.   
  
function EventHubTrigger() {  
  [Function()]  
  param(  
    [EventHubTrigger(EventHubName='', ConsumerGroup='', Cardinality='', Connection='')]  
    $Request,  
    $TriggerMetadata  
  ) 
   
  $value = ([HttpResponseContext]@{  
    StatusCode = [HttpStatusCode]::OK    
    Body = 'The Http trigger invocation was successful'    
  })    
    
  $value | Push-OutputBinding -Name Response    
}        

# HttpOutput syntax:   
      
# [HttpOutput(Name='<name>')]  
      
# EventHubOutput syntax:  
 
# [EventHubOutput(Name='<binding name>', EventHubName='<event hub name>', Connection='<event hub connection>')]  

Durable

function DurableFunctionsHttpStart1 {  
  [Function()]  
  param(  
    [DurableClient(Name='starter')]  
    [HttpTrigger(AuthLevel='anonymous', Methods=('get', 'post'), Route='DurableStart')]  
    $Request,   
    $TriggerMetadata  
  )  
 
  $FunctionName = "DurableFunctionsOrchestrator1"  
  $InstanceId = Start-DurableOrchestration -FunctionName $FunctionName  
  Write-Host "Started orchestration with ID = '$InstanceId'"  

  $Response = New-DurableOrchestrationCheckStatusResponse -Request $Request -InstanceId $InstanceId  

  Push-OutputBinding -Name Response -Value $Response  
}  

function DurableFunctionsOrchestrator1 {  
  [Function()]  
  param(  
    [OrchestrationTrigger()]  
    $Context  
  )  

  $output = @()  

  $output += Invoke-DurableActivity -FunctionName 'Hello1' -Input 'Tokyo'  
  $output += Invoke-DurableActivity -FunctionName 'Hello1' -Input 'Seattle'  
  $output += Invoke-DurableActivity -FunctionName 'Hello1' -Input 'London'  

  $output  
}  

function Hello1 {  
  [Function()]  
  param(  
    [ActivityTrigger()]  
    $name  
  )  
  "Hello $name!"  
}  

Generic Binding Syntax Following is an HTTP trigger written in the style of the generic, but use your imagination!

function GenericTrigger() {  
  [Function()]  
  [OutputBinding(Type='http', Name='Response')]  
  [AdditionalInformation(BindingName='', Name='', Value='')]  
  param(  
    [InputBinding(Type='httpTrigger')]  
    [AdditionalInformation(BindingName='Request', Name='authLevel', Value='anonymous')]  
    [AdditionalInformation(BindingName='Request', Name='methods', Value=('GET', 'POST'))]  
    $Request,  
    $TriggerMetadata  
  )  
}