diff --git a/.gitignore b/.gitignore index 0278bab71..259b25be9 100644 --- a/.gitignore +++ b/.gitignore @@ -358,4 +358,7 @@ __queuestorage__ __azurite_db*__.json # Python virtual environment -.venv \ No newline at end of file +.venv + +# Mac OS X +.DS_Store \ No newline at end of file diff --git a/builds/azure-pipelines/template-steps-build-test.yml b/builds/azure-pipelines/template-steps-build-test.yml index c8dd777f0..0473af8b4 100644 --- a/builds/azure-pipelines/template-steps-build-test.yml +++ b/builds/azure-pipelines/template-steps-build-test.yml @@ -12,6 +12,13 @@ steps: inputs: useGlobalJson: true +# Install .Net Core 3.1.0 as PowerShell tests are unable to find 3.1.0 framework to run tests +- task: UseDotNet@2 + displayName: 'Install .NET Core 3.1 sdk' + inputs: + packageType: sdk + version: '3.1.x' + # Run Policheck early to avoid scanning dependency folders - task: securedevelopmentteam.vss-secure-development-tools.build-task-policheck.PoliCheck@2 displayName: 'Run PoliCheck' diff --git a/samples/samples-csharp/Common/Product.cs b/samples/samples-csharp/Common/Product.cs index ec27e77f4..9eeda4ff3 100644 --- a/samples/samples-csharp/Common/Product.cs +++ b/samples/samples-csharp/Common/Product.cs @@ -34,6 +34,16 @@ public class ProductWithOptionalId public class ProductName { public string Name { get; set; } + + public override bool Equals(object obj) + { + if (obj is Product) + { + var that = obj as Product; + return this.Name == that.Name; + } + return false; + } } public class ProductWithDefaultPK diff --git a/samples/samples-powershell/.funcignore b/samples/samples-powershell/.funcignore new file mode 100644 index 000000000..e12aca981 --- /dev/null +++ b/samples/samples-powershell/.funcignore @@ -0,0 +1,3 @@ +.git* +.vscode +local.settings.json \ No newline at end of file diff --git a/samples/samples-powershell/.gitignore b/samples/samples-powershell/.gitignore new file mode 100644 index 000000000..820e1d424 --- /dev/null +++ b/samples/samples-powershell/.gitignore @@ -0,0 +1,10 @@ +# Azure Functions artifacts +bin +obj +appsettings.json +local.settings.json + +# Azurite artifacts +__blobstorage__ +__queuestorage__ +__azurite_db*__.json \ No newline at end of file diff --git a/samples/samples-powershell/.vscode/extensions.json b/samples/samples-powershell/.vscode/extensions.json new file mode 100644 index 000000000..57fa07bd9 --- /dev/null +++ b/samples/samples-powershell/.vscode/extensions.json @@ -0,0 +1,6 @@ +{ + "recommendations": [ + "ms-azuretools.vscode-azurefunctions", + "ms-vscode.powershell" + ] +} \ No newline at end of file diff --git a/samples/samples-powershell/.vscode/launch.json b/samples/samples-powershell/.vscode/launch.json new file mode 100644 index 000000000..1cddecf45 --- /dev/null +++ b/samples/samples-powershell/.vscode/launch.json @@ -0,0 +1,13 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Attach to PowerShell Functions", + "type": "PowerShell", + "request": "attach", + "customPipeName": "AzureFunctionsPSWorker", + "runspaceId": 1, + "preLaunchTask": "func: host start" + } + ] +} \ No newline at end of file diff --git a/samples/samples-powershell/.vscode/settings.json b/samples/samples-powershell/.vscode/settings.json new file mode 100644 index 000000000..49300c80a --- /dev/null +++ b/samples/samples-powershell/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "azureFunctions.templateFilter": "All", + "azureFunctions.deploySubpath": ".", + "azureFunctions.projectLanguage": "PowerShell", + "azureFunctions.projectRuntime": "~4", + "debug.internalConsoleOptions": "neverOpen" +} \ No newline at end of file diff --git a/samples/samples-powershell/.vscode/tasks.json b/samples/samples-powershell/.vscode/tasks.json new file mode 100644 index 000000000..64da1ce15 --- /dev/null +++ b/samples/samples-powershell/.vscode/tasks.json @@ -0,0 +1,11 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "func", + "command": "host start", + "problemMatcher": "$func-powershell-watch", + "isBackground": true + } + ] +} \ No newline at end of file diff --git a/samples/samples-powershell/AddProduct/function.json b/samples/samples-powershell/AddProduct/function.json new file mode 100644 index 000000000..70e0a55cd --- /dev/null +++ b/samples/samples-powershell/AddProduct/function.json @@ -0,0 +1,27 @@ +{ + "bindings": [ + { + "authLevel": "function", + "name": "Request", + "direction": "in", + "type": "httpTrigger", + "methods": [ + "post" + ], + "route": "addproduct" + }, + { + "name": "response", + "type": "http", + "direction": "out" + }, + { + "name": "product", + "type": "sql", + "direction": "out", + "commandText": "[dbo].[Products]", + "connectionStringSetting": "SqlConnectionString" + } + ], + "disabled": false +} \ No newline at end of file diff --git a/samples/samples-powershell/AddProduct/run.ps1 b/samples/samples-powershell/AddProduct/run.ps1 new file mode 100644 index 000000000..dad4b722b --- /dev/null +++ b/samples/samples-powershell/AddProduct/run.ps1 @@ -0,0 +1,23 @@ +using namespace System.Net + +# Trigger binding data passed in via param block +param($Request) + +# Write to the Azure Functions log stream. +Write-Host "PowerShell function with SQL Output Binding processed a request." + +# Update req_body with the body of the request +# Note that this expects the body to be a JSON object or array of objects +# which have a property matching each of the columns in the table to upsert to. +$req_body = $Request.Body + +# Assign the value we want to pass to the SQL Output binding. +# The -Name value corresponds to the name property in the function.json for the binding +Push-OutputBinding -Name product -Value $req_body + +# Assign the value to return as the HTTP response. +# The -Name value matches the name property in the function.json for the binding +Push-OutputBinding -Name response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $req_body +}) \ No newline at end of file diff --git a/samples/samples-powershell/AddProductParams/function.json b/samples/samples-powershell/AddProductParams/function.json new file mode 100644 index 000000000..0623b9df8 --- /dev/null +++ b/samples/samples-powershell/AddProductParams/function.json @@ -0,0 +1,28 @@ +{ + "bindings": [ + { + "authLevel": "function", + "name": "Request", + "direction": "in", + "type": "httpTrigger", + "methods": [ + "get", + "post" + ], + "route": "addproduct-params" + }, + { + "name": "response", + "type": "http", + "direction": "out" + }, + { + "name": "product", + "type": "sql", + "direction": "out", + "commandText": "[dbo].[Products]", + "connectionStringSetting": "SqlConnectionString" + } + ], + "disabled": false +} \ No newline at end of file diff --git a/samples/samples-powershell/AddProductParams/run.ps1 b/samples/samples-powershell/AddProductParams/run.ps1 new file mode 100644 index 000000000..dad483cda --- /dev/null +++ b/samples/samples-powershell/AddProductParams/run.ps1 @@ -0,0 +1,25 @@ +using namespace System.Net + +# Trigger binding data passed in via param block +param($Request) + +# Write to the Azure Functions log stream. +Write-Host "PowerShell function with SQL Output Binding processed a request." + +# Update req_query with the query of the request +$req_query = @{ + "productId"= $Request.QUERY.productId; + "name"= $Request.QUERY.name; + "cost"= $Request.QUERY.cost; +}; + +# Assign the value we want to pass to the SQL Output binding. +# The -Name value corresponds to the name property in the function.json for the binding +Push-OutputBinding -Name product -Value $req_query + +# Assign the value to return as the HTTP response. +# The -Name value matches the name property in the function.json for the binding +Push-OutputBinding -Name response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $req_query +}) \ No newline at end of file diff --git a/samples/samples-powershell/AddProductWithDefaultPK/function.json b/samples/samples-powershell/AddProductWithDefaultPK/function.json new file mode 100644 index 000000000..c7d30f29f --- /dev/null +++ b/samples/samples-powershell/AddProductWithDefaultPK/function.json @@ -0,0 +1,27 @@ +{ + "bindings": [ + { + "authLevel": "function", + "name": "Request", + "direction": "in", + "type": "httpTrigger", + "methods": [ + "post" + ], + "route": "addproductwithdefaultpk" + }, + { + "name": "response", + "type": "http", + "direction": "out" + }, + { + "name": "products", + "type": "sql", + "direction": "out", + "commandText": "[dbo].[ProductsWithDefaultPK]", + "connectionStringSetting": "SqlConnectionString" + } + ], + "disabled": false + } \ No newline at end of file diff --git a/samples/samples-powershell/AddProductWithDefaultPK/run.ps1 b/samples/samples-powershell/AddProductWithDefaultPK/run.ps1 new file mode 100644 index 000000000..a8823cce9 --- /dev/null +++ b/samples/samples-powershell/AddProductWithDefaultPK/run.ps1 @@ -0,0 +1,23 @@ +using namespace System.Net + +# Trigger binding data passed in via param block +param($Request) + +# Write to the Azure Functions log stream. +Write-Host "PowerShell function with SQL Output Binding processed a request." + +# Update req_body with the body of the request +# Note that this expects the body to be a JSON object or array of objects +# which have a property matching each of the columns in the table to upsert to. +$req_body = $Request.Body + +# Assign the value we want to pass to the SQL Output binding. +# The -Name value corresponds to the name property in the function.json for the binding +Push-OutputBinding -Name products -Value $req_body + +# Assign the value to return as the HTTP response. +# The -Name value matches the name property in the function.json for the binding +Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $req_body +}) \ No newline at end of file diff --git a/samples/samples-powershell/AddProductWithIdentityColumn/function.json b/samples/samples-powershell/AddProductWithIdentityColumn/function.json new file mode 100644 index 000000000..95e2598c4 --- /dev/null +++ b/samples/samples-powershell/AddProductWithIdentityColumn/function.json @@ -0,0 +1,28 @@ +{ + "bindings": [ + { + "authLevel": "function", + "name": "Request", + "direction": "in", + "type": "httpTrigger", + "methods": [ + "get", + "post" + ], + "route": "addproductwithidentitycolumn" + }, + { + "name": "response", + "type": "http", + "direction": "out" + }, + { + "name": "product", + "type": "sql", + "direction": "out", + "commandText": "[dbo].[ProductsWithIdentity]", + "connectionStringSetting": "SqlConnectionString" + } + ], + "disabled": false +} \ No newline at end of file diff --git a/samples/samples-powershell/AddProductWithIdentityColumn/run.ps1 b/samples/samples-powershell/AddProductWithIdentityColumn/run.ps1 new file mode 100644 index 000000000..4238efdac --- /dev/null +++ b/samples/samples-powershell/AddProductWithIdentityColumn/run.ps1 @@ -0,0 +1,24 @@ +using namespace System.Net + +# Trigger binding data passed in via param block +param($Request) + +# Write to the Azure Functions log stream. +Write-Host "PowerShell function with SQL Output Binding processed a request." + +# Update req_query with the query of the request +$req_query = @{ + name=$Request.QUERY.name; + cost=$Request.QUERY.cost; +}; + +# Assign the value we want to pass to the SQL Output binding. +# The -Name value corresponds to the name property in the function.json for the binding +Push-OutputBinding -Name product -Value $req_query + +# Assign the value to return as the HTTP response. +# The -Name value matches the name property in the function.json for the binding +Push-OutputBinding -Name response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $req_query +}) \ No newline at end of file diff --git a/samples/samples-powershell/AddProductWithIdentityColumnIncluded/function.json b/samples/samples-powershell/AddProductWithIdentityColumnIncluded/function.json new file mode 100644 index 000000000..bd7137c52 --- /dev/null +++ b/samples/samples-powershell/AddProductWithIdentityColumnIncluded/function.json @@ -0,0 +1,27 @@ +{ + "bindings": [ + { + "authLevel": "function", + "name": "Request", + "direction": "in", + "type": "httpTrigger", + "methods": [ + "get" + ], + "route": "addproductwithidentitycolumnincluded" + }, + { + "name": "response", + "type": "http", + "direction": "out" + }, + { + "name": "product", + "type": "sql", + "direction": "out", + "commandText": "[dbo].[ProductsWithIdentity]", + "connectionStringSetting": "SqlConnectionString" + } + ], + "disabled": false +} \ No newline at end of file diff --git a/samples/samples-powershell/AddProductWithIdentityColumnIncluded/run.ps1 b/samples/samples-powershell/AddProductWithIdentityColumnIncluded/run.ps1 new file mode 100644 index 000000000..421c51dd9 --- /dev/null +++ b/samples/samples-powershell/AddProductWithIdentityColumnIncluded/run.ps1 @@ -0,0 +1,25 @@ +using namespace System.Net + +# Trigger binding data passed in via param block +param($Request) + +# Write to the Azure Functions log stream. +Write-Host "PowerShell function with SQL Output Binding processed a request." + +# Update req_query with the body of the request +$req_query = @{ + productId= if($Request.QUERY.productId) { $Request.QUERY.productId } else { $null }; + name=$Request.QUERY.name; + cost=$Request.QUERY.cost; +}; + +# Assign the value we want to pass to the SQL Output binding. +# The -Name value corresponds to the name property in the function.json for the binding +Push-OutputBinding -Name product -Value $req_query + +# Assign the value to return as the HTTP response. +# The -Name value matches the name property in the function.json for the binding +Push-OutputBinding -Name response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $req_query +}) \ No newline at end of file diff --git a/samples/samples-powershell/AddProductWithMultiplePrimaryColumnsAndIdentity/function.json b/samples/samples-powershell/AddProductWithMultiplePrimaryColumnsAndIdentity/function.json new file mode 100644 index 000000000..983861d99 --- /dev/null +++ b/samples/samples-powershell/AddProductWithMultiplePrimaryColumnsAndIdentity/function.json @@ -0,0 +1,28 @@ +{ + "bindings": [ + { + "authLevel": "function", + "name": "Request", + "direction": "in", + "type": "httpTrigger", + "methods": [ + "get", + "post" + ], + "route": "addproductwithmultipleprimarycolumnsandidentity" + }, + { + "name": "response", + "type": "http", + "direction": "out" + }, + { + "name": "product", + "type": "sql", + "direction": "out", + "commandText": "[dbo].[ProductsWithMultiplePrimaryColumnsAndIdentity]", + "connectionStringSetting": "SqlConnectionString" + } + ], + "disabled": false +} \ No newline at end of file diff --git a/samples/samples-powershell/AddProductWithMultiplePrimaryColumnsAndIdentity/run.ps1 b/samples/samples-powershell/AddProductWithMultiplePrimaryColumnsAndIdentity/run.ps1 new file mode 100644 index 000000000..c5dc81441 --- /dev/null +++ b/samples/samples-powershell/AddProductWithMultiplePrimaryColumnsAndIdentity/run.ps1 @@ -0,0 +1,25 @@ +using namespace System.Net + +# Trigger binding data passed in via param block +param($Request) + +# Write to the Azure Functions log stream. +Write-Host "PowerShell function with SQL Output Binding processed a request." + +# Update req_query with the body of the request +$req_query = @{ + externalId=$Request.QUERY.externalId; + name=$Request.QUERY.name; + cost=$Request.QUERY.cost; +}; + +# Assign the value we want to pass to the SQL Output binding. +# The -Name value corresponds to the name property in the function.json for the binding +Push-OutputBinding -Name product -Value $req_query + +# Assign the value to return as the HTTP response. +# The -Name value matches the name property in the function.json for the binding +Push-OutputBinding -Name response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $req_query +}) \ No newline at end of file diff --git a/samples/samples-powershell/AddProductsArray/function.json b/samples/samples-powershell/AddProductsArray/function.json new file mode 100644 index 000000000..55f5b282d --- /dev/null +++ b/samples/samples-powershell/AddProductsArray/function.json @@ -0,0 +1,27 @@ +{ + "bindings": [ + { + "authLevel": "function", + "name": "Request", + "direction": "in", + "type": "httpTrigger", + "methods": [ + "post" + ], + "route": "addproducts-array" + }, + { + "name": "response", + "type": "http", + "direction": "out" + }, + { + "name": "products", + "type": "sql", + "direction": "out", + "commandText": "[dbo].[Products]", + "connectionStringSetting": "SqlConnectionString" + } + ], + "disabled": false +} \ No newline at end of file diff --git a/samples/samples-powershell/AddProductsArray/run.ps1 b/samples/samples-powershell/AddProductsArray/run.ps1 new file mode 100644 index 000000000..92e89bdbc --- /dev/null +++ b/samples/samples-powershell/AddProductsArray/run.ps1 @@ -0,0 +1,23 @@ +using namespace System.Net + +# Trigger binding data passed in via param block +param($Request) + +# Write to the Azure Functions log stream. +Write-Host "PowerShell function with SQL Output Binding processed a request." + +# Update req_body with the body of the request +# Note that this expects the body to be a JSON object or array of objects +# which have a property matching each of the columns in the table to upsert to. +$req_body = $Request.Body + +# Assign the value we want to pass to the SQL Output binding. +# The -Name value corresponds to the name property in the function.json for the binding +Push-OutputBinding -Name products -Value $req_body + +# Assign the value to return as the HTTP response. +# The -Name value matches the name property in the function.json for the binding +Push-OutputBinding -Name response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $req_body +}) \ No newline at end of file diff --git a/samples/samples-powershell/AddProductsWithIdentityColumnArray/function.json b/samples/samples-powershell/AddProductsWithIdentityColumnArray/function.json new file mode 100644 index 000000000..7bf34fc21 --- /dev/null +++ b/samples/samples-powershell/AddProductsWithIdentityColumnArray/function.json @@ -0,0 +1,28 @@ +{ + "bindings": [ + { + "authLevel": "function", + "name": "Request", + "direction": "in", + "type": "httpTrigger", + "methods": [ + "get", + "post" + ], + "route": "addproductswithidentitycolumnarray" + }, + { + "name": "response", + "type": "http", + "direction": "out" + }, + { + "name": "products", + "type": "sql", + "direction": "out", + "commandText": "[dbo].[ProductsWithIdentity]", + "connectionStringSetting": "SqlConnectionString" + } + ], + "disabled": false +} \ No newline at end of file diff --git a/samples/samples-powershell/AddProductsWithIdentityColumnArray/run.ps1 b/samples/samples-powershell/AddProductsWithIdentityColumnArray/run.ps1 new file mode 100644 index 000000000..bb2e35d52 --- /dev/null +++ b/samples/samples-powershell/AddProductsWithIdentityColumnArray/run.ps1 @@ -0,0 +1,29 @@ +using namespace System.Net + +# Trigger binding data passed in via param block +param($Request) + +# Write to the Azure Functions log stream. +Write-Host "PowerShell function with SQL Output Binding processed a request." + +# Update req_body with the body of the request +# Note that this expects the body to be a JSON object or array of objects +# which have a property matching each of the columns in the table to upsert to. +$req_body = @(@{ + name="Cup"; + cost=2; +}, @{ + name="Glasses"; + cost=12; +}); + +# Assign the value we want to pass to the SQL Output binding. +# The -Name value corresponds to the name property in the function.json for the binding +Push-OutputBinding -Name products -Value $req_body + +# Assign the value to return as the HTTP response. +# The -Name value matches the name property in the function.json for the binding +Push-OutputBinding -Name response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $req_body +}) \ No newline at end of file diff --git a/samples/samples-powershell/GetProductNamesView/function.json b/samples/samples-powershell/GetProductNamesView/function.json new file mode 100644 index 000000000..6fa0b257f --- /dev/null +++ b/samples/samples-powershell/GetProductNamesView/function.json @@ -0,0 +1,28 @@ +{ + "bindings": [ + { + "authLevel": "function", + "name": "Request", + "type": "httpTrigger", + "direction": "in", + "methods": [ + "get" + ], + "route":"getproduct-namesview" + }, + { + "name": "response", + "type": "http", + "direction": "out" + }, + { + "name": "products", + "type": "sql", + "direction": "in", + "commandText": "SELECT * FROM ProductNames", + "commandType": "Text", + "connectionStringSetting": "SqlConnectionString" + } + ], + "disabled": false +} \ No newline at end of file diff --git a/samples/samples-powershell/GetProductNamesView/run.ps1 b/samples/samples-powershell/GetProductNamesView/run.ps1 new file mode 100644 index 000000000..53e94ca3a --- /dev/null +++ b/samples/samples-powershell/GetProductNamesView/run.ps1 @@ -0,0 +1,14 @@ +using namespace System.Net + +# Trigger and input binding data are passed in via the param block. +param($Request, $products) + +# Write to the Azure Functions log stream. +Write-Host "PowerShell function with SQL Input Binding processed a request." + +# Assign the value to return as the HTTP response. +# The -Name value matches the name property in the function.json for the binding +Push-OutputBinding -Name response -Value ([HttpResponseContext]@{ + StatusCode = [System.Net.HttpStatusCode]::OK + Body = $products +}) \ No newline at end of file diff --git a/samples/samples-powershell/GetProducts/function.json b/samples/samples-powershell/GetProducts/function.json new file mode 100644 index 000000000..3de952d09 --- /dev/null +++ b/samples/samples-powershell/GetProducts/function.json @@ -0,0 +1,29 @@ +{ + "bindings": [ + { + "authLevel": "function", + "name": "Request", + "type": "httpTrigger", + "direction": "in", + "methods": [ + "get" + ], + "route": "getproducts/{cost}" + }, + { + "name": "response", + "type": "http", + "direction": "out" + }, + { + "name": "products", + "type": "sql", + "direction": "in", + "commandText": "select * from Products where Cost = @Cost", + "commandType": "Text", + "parameters": "@Cost={cost}", + "connectionStringSetting": "SqlConnectionString" + } + ], + "disabled": false +} \ No newline at end of file diff --git a/samples/samples-powershell/GetProducts/run.ps1 b/samples/samples-powershell/GetProducts/run.ps1 new file mode 100644 index 000000000..53e94ca3a --- /dev/null +++ b/samples/samples-powershell/GetProducts/run.ps1 @@ -0,0 +1,14 @@ +using namespace System.Net + +# Trigger and input binding data are passed in via the param block. +param($Request, $products) + +# Write to the Azure Functions log stream. +Write-Host "PowerShell function with SQL Input Binding processed a request." + +# Assign the value to return as the HTTP response. +# The -Name value matches the name property in the function.json for the binding +Push-OutputBinding -Name response -Value ([HttpResponseContext]@{ + StatusCode = [System.Net.HttpStatusCode]::OK + Body = $products +}) \ No newline at end of file diff --git a/samples/samples-powershell/GetProductsNameEmpty/function.json b/samples/samples-powershell/GetProductsNameEmpty/function.json new file mode 100644 index 000000000..868b2d0e1 --- /dev/null +++ b/samples/samples-powershell/GetProductsNameEmpty/function.json @@ -0,0 +1,29 @@ +{ + "bindings": [ + { + "authLevel": "function", + "name": "Request", + "type": "httpTrigger", + "direction": "in", + "methods": [ + "get" + ], + "route":"getproducts-nameempty/{cost}" + }, + { + "name": "response", + "type": "http", + "direction": "out" + }, + { + "name": "products", + "type": "sql", + "direction": "in", + "commandText": "select * from Products where Cost = @Cost and Name = @Name", + "commandType": "Text", + "parameters": "@Cost={cost},@Name=", + "connectionStringSetting": "SqlConnectionString" + } + ], + "disabled": false +} \ No newline at end of file diff --git a/samples/samples-powershell/GetProductsNameEmpty/run.ps1 b/samples/samples-powershell/GetProductsNameEmpty/run.ps1 new file mode 100644 index 000000000..53e94ca3a --- /dev/null +++ b/samples/samples-powershell/GetProductsNameEmpty/run.ps1 @@ -0,0 +1,14 @@ +using namespace System.Net + +# Trigger and input binding data are passed in via the param block. +param($Request, $products) + +# Write to the Azure Functions log stream. +Write-Host "PowerShell function with SQL Input Binding processed a request." + +# Assign the value to return as the HTTP response. +# The -Name value matches the name property in the function.json for the binding +Push-OutputBinding -Name response -Value ([HttpResponseContext]@{ + StatusCode = [System.Net.HttpStatusCode]::OK + Body = $products +}) \ No newline at end of file diff --git a/samples/samples-powershell/GetProductsStoredProcedure/function.json b/samples/samples-powershell/GetProductsStoredProcedure/function.json new file mode 100644 index 000000000..47837c658 --- /dev/null +++ b/samples/samples-powershell/GetProductsStoredProcedure/function.json @@ -0,0 +1,29 @@ +{ + "bindings": [ + { + "authLevel": "function", + "name": "Request", + "type": "httpTrigger", + "direction": "in", + "methods": [ + "get" + ], + "route": "getproducts-storedprocedure/{cost}" + }, + { + "name": "response", + "type": "http", + "direction": "out" + }, + { + "name": "products", + "type": "sql", + "direction": "in", + "commandText": "SelectProductsCost", + "commandType": "StoredProcedure", + "parameters": "@Cost={cost}", + "connectionStringSetting": "SqlConnectionString" + } + ], + "disabled": false +} \ No newline at end of file diff --git a/samples/samples-powershell/GetProductsStoredProcedure/run.ps1 b/samples/samples-powershell/GetProductsStoredProcedure/run.ps1 new file mode 100644 index 000000000..53e94ca3a --- /dev/null +++ b/samples/samples-powershell/GetProductsStoredProcedure/run.ps1 @@ -0,0 +1,14 @@ +using namespace System.Net + +# Trigger and input binding data are passed in via the param block. +param($Request, $products) + +# Write to the Azure Functions log stream. +Write-Host "PowerShell function with SQL Input Binding processed a request." + +# Assign the value to return as the HTTP response. +# The -Name value matches the name property in the function.json for the binding +Push-OutputBinding -Name response -Value ([HttpResponseContext]@{ + StatusCode = [System.Net.HttpStatusCode]::OK + Body = $products +}) \ No newline at end of file diff --git a/samples/samples-powershell/GetProductsStoredProcedureFromAppSetting/function.json b/samples/samples-powershell/GetProductsStoredProcedureFromAppSetting/function.json new file mode 100644 index 000000000..6c7469789 --- /dev/null +++ b/samples/samples-powershell/GetProductsStoredProcedureFromAppSetting/function.json @@ -0,0 +1,29 @@ +{ + "bindings": [ + { + "authLevel": "function", + "name": "Request", + "type": "httpTrigger", + "direction": "in", + "methods": [ + "get" + ], + "route": "getproductsbycost" + }, + { + "name": "response", + "type": "http", + "direction": "out" + }, + { + "name": "products", + "type": "sql", + "direction": "in", + "commandText": "%Sp_SelectCost%", + "commandType": "StoredProcedure", + "parameters": "@Cost=%ProductCost%", + "connectionStringSetting": "SqlConnectionString" + } + ], + "disabled": false +} \ No newline at end of file diff --git a/samples/samples-powershell/GetProductsStoredProcedureFromAppSetting/run.ps1 b/samples/samples-powershell/GetProductsStoredProcedureFromAppSetting/run.ps1 new file mode 100644 index 000000000..53e94ca3a --- /dev/null +++ b/samples/samples-powershell/GetProductsStoredProcedureFromAppSetting/run.ps1 @@ -0,0 +1,14 @@ +using namespace System.Net + +# Trigger and input binding data are passed in via the param block. +param($Request, $products) + +# Write to the Azure Functions log stream. +Write-Host "PowerShell function with SQL Input Binding processed a request." + +# Assign the value to return as the HTTP response. +# The -Name value matches the name property in the function.json for the binding +Push-OutputBinding -Name response -Value ([HttpResponseContext]@{ + StatusCode = [System.Net.HttpStatusCode]::OK + Body = $products +}) \ No newline at end of file diff --git a/samples/samples-powershell/QueueTriggerProducts/function.json b/samples/samples-powershell/QueueTriggerProducts/function.json new file mode 100644 index 000000000..0e0ecaaa9 --- /dev/null +++ b/samples/samples-powershell/QueueTriggerProducts/function.json @@ -0,0 +1,23 @@ +{ + "bindings": [ + { + "type": "queueTrigger", + "direction": "in", + "name": "queueMessage", + "queueName": "testqueue" + }, + { + "name": "response", + "type": "http", + "direction": "out" + }, + { + "name": "products", + "type": "sql", + "direction": "out", + "commandText": "[dbo].[Products]", + "connectionStringSetting": "SqlConnectionString" + } + ], + "disabled": false +} \ No newline at end of file diff --git a/samples/samples-powershell/QueueTriggerProducts/run.ps1 b/samples/samples-powershell/QueueTriggerProducts/run.ps1 new file mode 100644 index 000000000..edba99505 --- /dev/null +++ b/samples/samples-powershell/QueueTriggerProducts/run.ps1 @@ -0,0 +1,28 @@ +using namespace System.Net + +# Trigger binding data passed in via param block +param($queueMessage) +$totalUpserts = 100; +# Write to the Azure Functions log stream. +Write-Host "[QueueTrigger]: $Get-Date starting execution $queueMessage. Rows to generate=$totalUpserts." + +# Update req_body with the body of the request +# Note that this expects the body to be a JSON object or array of objects +# which have a property matching each of the columns in the table to upsert to. +$start = Get-Date + +$products = @() +for ($i = 0; $i -lt $totalUpserts; $i++) { + $products += [PSCustomObject]@{ + productId = $i; + name = "test"; + cost = 100 * $i; + } +} +# Assign the value we want to pass to the SQL Output binding. +# The -Name value corresponds to the name property in the function.json for the binding +Push-OutputBinding -Name products -Value $products +$end = Get-Date +$duration = New-TimeSpan -Start $start -End $end + +Write-Host "[QueueTrigger]: $Get-Date finished execution $queueMessage. Total time to create $totalUpserts rows=$duration." \ No newline at end of file diff --git a/samples/samples-powershell/TimerTriggerProducts/function.json b/samples/samples-powershell/TimerTriggerProducts/function.json new file mode 100644 index 000000000..009103f51 --- /dev/null +++ b/samples/samples-powershell/TimerTriggerProducts/function.json @@ -0,0 +1,23 @@ +{ + "bindings": [ + { + "schedule": "*/5 * * * * *", + "name": "myTimer", + "type": "timerTrigger", + "direction": "in" + }, + { + "name": "response", + "type": "http", + "direction": "out" + }, + { + "name": "products", + "type": "sql", + "direction": "out", + "commandText": "[dbo].[Products]", + "connectionStringSetting": "SqlConnectionString" + } + ], + "disabled": false +} \ No newline at end of file diff --git a/samples/samples-powershell/TimerTriggerProducts/run.ps1 b/samples/samples-powershell/TimerTriggerProducts/run.ps1 new file mode 100644 index 000000000..94d5b7934 --- /dev/null +++ b/samples/samples-powershell/TimerTriggerProducts/run.ps1 @@ -0,0 +1,27 @@ +using namespace System.Net + +param($myTimer) +$executionNumber = 0; +$totalUpserts = 1000; + +# Write to the Azure Functions log stream. +$start = Get-Date +Write-Host "[QueueTrigger]: $start starting execution $executionNumber. Rows to generate=$totalUpserts." + +$products = @() +for ($i = 0; $i -lt $totalUpserts; $i++) { + $products += [PSCustomObject]@{ + productId = $i; + name = "test"; + cost = 100 * $i; + } +} +$end = Get-Date +$duration = New-TimeSpan -Start $start -End $end + +# Assign the value we want to pass to the SQL Output binding. +# The -Name value corresponds to the name property in the function.json for the binding +Push-OutputBinding -Name products -Value $products + +Write-Host "[QueueTrigger]: $end finished execution $queueMessage. Total time to create $totalUpserts rows=$duration." +$executionNumber += 1; \ No newline at end of file diff --git a/samples/samples-powershell/host.json b/samples/samples-powershell/host.json new file mode 100644 index 000000000..851bea8aa --- /dev/null +++ b/samples/samples-powershell/host.json @@ -0,0 +1,15 @@ +{ + "version": "2.0", + "logging": { + "applicationInsights": { + "samplingSettings": { + "isEnabled": true, + "excludedTypes": "Request" + } + } + }, + "extensionBundle": { + "id": "Microsoft.Azure.Functions.ExtensionBundle.Preview", + "version": "[4.*, 5.0.0)" + } +} diff --git a/samples/samples-powershell/local.settings.json b/samples/samples-powershell/local.settings.json new file mode 100644 index 000000000..fac758659 --- /dev/null +++ b/samples/samples-powershell/local.settings.json @@ -0,0 +1,11 @@ +{ + "IsEncrypted": false, + "Values": { + "AzureWebJobsStorage": "UseDevelopmentStorage=true", + "FUNCTIONS_WORKER_RUNTIME": "powershell", + "FUNCTIONS_WORKER_RUNTIME_VERSION" : "~7", + "SqlConnectionString": "", + "Sp_SelectCost": "SelectProductsCost", + "ProductCost": 100 + } +} diff --git a/samples/samples-powershell/profile.ps1 b/samples/samples-powershell/profile.ps1 new file mode 100644 index 000000000..1670fc99c --- /dev/null +++ b/samples/samples-powershell/profile.ps1 @@ -0,0 +1,22 @@ +# Azure Functions profile.ps1 +# +# This profile.ps1 will get executed every "cold start" of your Function App. +# "cold start" occurs when: +# +# * A Function App starts up for the very first time +# * A Function App starts up after being de-allocated due to inactivity +# +# You can define helper functions, run commands, or specify environment variables +# NOTE: any variables defined that are not environment variables will get reset after the first execution + +# Authenticate with Azure PowerShell using MSI. +# Remove this if you are not planning on using MSI or Azure PowerShell. +if ($env:MSI_SECRET) { + Disable-AzContextAutosave -Scope Process | Out-Null + Connect-AzAccount -Identity +} + +# Uncomment the next line to enable legacy AzureRm alias in Azure PowerShell. +# Enable-AzureRmAlias + +# You can also define functions or aliases that can be referenced in any of your PowerShell functions. diff --git a/samples/samples-powershell/requirements.psd1 b/samples/samples-powershell/requirements.psd1 new file mode 100644 index 000000000..58d3be713 --- /dev/null +++ b/samples/samples-powershell/requirements.psd1 @@ -0,0 +1,8 @@ +# This file enables modules to be automatically managed by the Functions service. +# See https://aka.ms/functionsmanageddependency for additional information. +# +@{ + # 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.*' +} \ No newline at end of file diff --git a/test/Common/SupportedLanguagesTestAttribute.cs b/test/Common/SupportedLanguagesTestAttribute.cs index c2cd73791..a8cec8bd7 100644 --- a/test/Common/SupportedLanguagesTestAttribute.cs +++ b/test/Common/SupportedLanguagesTestAttribute.cs @@ -71,6 +71,7 @@ public UnsupportedLanguagesAttribute(params SupportedLanguages[] argsWithUnsuppo public enum SupportedLanguages { CSharp, - JavaScript + JavaScript, + PowerShell }; } \ No newline at end of file diff --git a/test/Integration/SqlInputBindingIntegrationTests.cs b/test/Integration/SqlInputBindingIntegrationTests.cs index 7f944c370..643337c37 100644 --- a/test/Integration/SqlInputBindingIntegrationTests.cs +++ b/test/Integration/SqlInputBindingIntegrationTests.cs @@ -18,7 +18,6 @@ public class SqlInputBindingIntegrationTests : IntegrationTestBase public SqlInputBindingIntegrationTests(ITestOutputHelper output) : base(output) { } - [Theory] [SqlInlineData(0, 100)] [SqlInlineData(1, -500)] @@ -137,7 +136,7 @@ public async void GetProductNamesViewTest(SupportedLanguages lang) [Theory] [SqlInlineData("en-US")] [SqlInlineData("it-IT")] - [UnsupportedLanguages(SupportedLanguages.JavaScript)] // IAsyncEnumerable is only available in C# + [UnsupportedLanguages(SupportedLanguages.JavaScript, SupportedLanguages.PowerShell)] // IAsyncEnumerable is only available in C# public async void GetProductsColumnTypesSerializationAsyncEnumerableTest(string culture, SupportedLanguages lang) { this.StartFunctionHost(nameof(GetProductsColumnTypesSerializationAsyncEnumerable), lang, true); @@ -174,7 +173,6 @@ public async void GetProductsColumnTypesSerializationTest(SupportedLanguages lan HttpResponseMessage response = await this.SendInputRequest("getproducts-columntypesserialization"); // We expect the datetime and datetime2 fields to be returned in UTC format ProductColumnTypes[] expectedResponse = JsonConvert.DeserializeObject("[{\"ProductId\":999,\"Datetime\":\"2022-10-20T12:39:13.123Z\",\"Datetime2\":\"2022-10-20T12:39:13.123Z\"}]"); - string actualResponse = await response.Content.ReadAsStringAsync(); ProductColumnTypes[] actualProductResponse = JsonConvert.DeserializeObject(actualResponse); diff --git a/test/Integration/SqlOutputBindingIntegrationTests.cs b/test/Integration/SqlOutputBindingIntegrationTests.cs index 179810dac..279e339b8 100644 --- a/test/Integration/SqlOutputBindingIntegrationTests.cs +++ b/test/Integration/SqlOutputBindingIntegrationTests.cs @@ -19,7 +19,6 @@ public class SqlOutputBindingIntegrationTests : IntegrationTestBase public SqlOutputBindingIntegrationTests(ITestOutputHelper output) : base(output) { } - [Theory] [SqlInlineData(1, "Test", 5)] [SqlInlineData(0, "", 0)] @@ -46,6 +45,9 @@ public void AddProductTest(int id, string name, int cost, SupportedLanguages lan [SqlInlineData(1, "Test", 5)] [SqlInlineData(0, "", 0)] [SqlInlineData(-500, "ABCD", 580)] + // Currently PowerShell returns null when the parameter for name is an empty string + // Issue link: https://github.com/Azure/azure-functions-sql-extension/issues/443 + [UnsupportedLanguages(SupportedLanguages.PowerShell)] public void AddProductParamsTest(int id, string name, int cost, SupportedLanguages lang) { this.StartFunctionHost(nameof(AddProductParams), lang); @@ -122,7 +124,7 @@ public void AddProductColumnTypesTest(SupportedLanguages lang) [Theory] [SqlInlineData()] - [UnsupportedLanguages(SupportedLanguages.JavaScript)] // Collectors are only available in C# + [UnsupportedLanguages(SupportedLanguages.JavaScript, SupportedLanguages.PowerShell)] // Collectors are only available in C# public void AddProductsCollectorTest(SupportedLanguages lang) { this.StartFunctionHost(nameof(AddProductsCollector), lang); @@ -215,6 +217,9 @@ public void AddProductNoPartialUpsertTest(SupportedLanguages lang) /// [Theory] [SqlInlineData()] + // Currently PowerShell gives an error due to the deserialization of the object + // Issue link: https://github.com/Azure/azure-functions-sql-extension/issues/448 + [UnsupportedLanguages(SupportedLanguages.PowerShell)] public void AddProductWithIdentity(SupportedLanguages lang) { this.StartFunctionHost(nameof(AddProductWithIdentityColumn), lang); @@ -235,6 +240,9 @@ public void AddProductWithIdentity(SupportedLanguages lang) /// [Theory] [SqlInlineData()] + // Currently PowerShell gives an error due to the deserialization of the object + // Issue link: https://github.com/Azure/azure-functions-sql-extension/issues/448 + [UnsupportedLanguages(SupportedLanguages.PowerShell)] public void AddProductsWithIdentityColumnArray(SupportedLanguages lang) { this.StartFunctionHost(nameof(AddProductsWithIdentityColumnArray), lang); @@ -245,11 +253,14 @@ public void AddProductsWithIdentityColumnArray(SupportedLanguages lang) } /// - /// Tests that for tables with multiple primary columns (including an itemtity column) we are able to + /// Tests that for tables with multiple primary columns (including an identity column) we are able to /// insert items. /// [Theory] [SqlInlineData()] + // Currently PowerShell gives an error due to the deserialization of the object + // Issue link: https://github.com/Azure/azure-functions-sql-extension/issues/448 + [UnsupportedLanguages(SupportedLanguages.PowerShell)] public void AddProductWithIdentity_MultiplePrimaryColumns(SupportedLanguages lang) { this.StartFunctionHost(nameof(AddProductWithMultiplePrimaryColumnsAndIdentity), lang); @@ -329,6 +340,9 @@ public void AddProductWithIdentity_NoIdentityColumn(SupportedLanguages lang) /// [Theory] [SqlInlineData()] + // Currently PowerShell gives an error due to the deserialization of the object + // Issue link: https://github.com/Azure/azure-functions-sql-extension/issues/448 + [UnsupportedLanguages(SupportedLanguages.PowerShell)] public void AddProductWithIdentity_MissingPrimaryColumn(SupportedLanguages lang) { this.StartFunctionHost(nameof(AddProductWithMultiplePrimaryColumnsAndIdentity), lang); @@ -389,6 +403,9 @@ public void AddProductCaseSensitiveTest(SupportedLanguages lang) /// [Theory] [SqlInlineData()] + // Currently PowerShell gives an unknown error (when testing locally we get a missing primary key error) + // Issue link: https://github.com/Azure/azure-functions-sql-extension/issues/448 + [UnsupportedLanguages(SupportedLanguages.PowerShell)] public void AddProductWithDefaultPKTest(SupportedLanguages lang) { this.StartFunctionHost(nameof(AddProductWithDefaultPK), lang); diff --git a/test/Integration/test-powershell/AddProductColumnTypes/function.json b/test/Integration/test-powershell/AddProductColumnTypes/function.json new file mode 100644 index 000000000..3a80fd4bd --- /dev/null +++ b/test/Integration/test-powershell/AddProductColumnTypes/function.json @@ -0,0 +1,28 @@ +{ + "bindings": [ + { + "authLevel": "function", + "name": "Request", + "direction": "in", + "type": "httpTrigger", + "methods": [ + "get" + ], + "route": "addproduct-columntypes" + }, + { + "name": "response", + "type": "http", + "direction": "out" + }, + { + "name": "product", + "type": "sql", + "direction": "out", + "commandText": "[dbo].[ProductsColumnTypes]", + "commandType": "Text", + "connectionStringSetting": "SqlConnectionString" + } + ], + "disabled": false +} \ No newline at end of file diff --git a/test/Integration/test-powershell/AddProductColumnTypes/run.ps1 b/test/Integration/test-powershell/AddProductColumnTypes/run.ps1 new file mode 100644 index 000000000..6647409e4 --- /dev/null +++ b/test/Integration/test-powershell/AddProductColumnTypes/run.ps1 @@ -0,0 +1,27 @@ +using namespace System.Net + +# Trigger binding data passed in via param block +param($Request) + +# Write to the Azure Functions log stream. +Write-Host "PowerShell function with SQL Output Binding processed a request." + +# Update req_body with the body of the request +# Note that this expects the body to be a JSON object or array of objects +# which have a property matching each of the columns in the table to upsert to. +$req_query = @{ + ProductId=$Request.QUERY.productId; + Datetime=Get-Date -AsUTC; + Datetime2=Get-Date -AsUTC; +}; + +# Assign the value we want to pass to the SQL Output binding. +# The -Name value corresponds to the name property in the function.json for the binding +Push-OutputBinding -Name product -Value $req_query + +# Assign the value to return as the HTTP response. +# The -Name value matches the name property in the function.json for the binding +Push-OutputBinding -Name response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $req_query +}) \ No newline at end of file diff --git a/test/Integration/test-powershell/AddProductExtraColumns/function.json b/test/Integration/test-powershell/AddProductExtraColumns/function.json new file mode 100644 index 000000000..3fc82a035 --- /dev/null +++ b/test/Integration/test-powershell/AddProductExtraColumns/function.json @@ -0,0 +1,27 @@ +{ + "bindings": [ + { + "authLevel": "function", + "name": "Request", + "direction": "in", + "type": "httpTrigger", + "methods": [ + "post" + ], + "route": "addproduct-extracolumns" + }, + { + "name": "response", + "type": "http", + "direction": "out" + }, + { + "name": "products", + "type": "sql", + "direction": "out", + "commandText": "[dbo].[Products]", + "connectionStringSetting": "SqlConnectionString" + } + ], + "disabled": false +} \ No newline at end of file diff --git a/test/Integration/test-powershell/AddProductExtraColumns/run.ps1 b/test/Integration/test-powershell/AddProductExtraColumns/run.ps1 new file mode 100644 index 000000000..7fd866193 --- /dev/null +++ b/test/Integration/test-powershell/AddProductExtraColumns/run.ps1 @@ -0,0 +1,26 @@ +using namespace System.Net + +# Trigger binding data passed in via param block +param($Request) + +# Write to the Azure Functions log stream. +Write-Host "PowerShell function with SQL Output Binding processed a request." + +# Update req_body with the body of the request +# Note that this expects the body to be a JSON object or array of objects +# which have a property matching each of the columns in the table to upsert to. +$req_body = @{ + productId=1; + name="MissingCost"; +}; + +# Assign the value we want to pass to the SQL Output binding. +# The -Name value corresponds to the name property in the function.json for the binding +Push-OutputBinding -Name product -Value $req_body + +# Assign the value to return as the HTTP response. +# The -Name value matches the name property in the function.json for the binding +Push-OutputBinding -Name response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $req_body +}) \ No newline at end of file diff --git a/test/Integration/test-powershell/AddProductMissingColumns/function.json b/test/Integration/test-powershell/AddProductMissingColumns/function.json new file mode 100644 index 000000000..4ea683c25 --- /dev/null +++ b/test/Integration/test-powershell/AddProductMissingColumns/function.json @@ -0,0 +1,27 @@ +{ + "bindings": [ + { + "authLevel": "function", + "name": "Request", + "direction": "in", + "type": "httpTrigger", + "methods": [ + "post" + ], + "route": "addproduct-missingcolumns" + }, + { + "name": "response", + "type": "http", + "direction": "out" + }, + { + "name": "product", + "type": "sql", + "direction": "out", + "commandText": "[dbo].[Products]", + "connectionStringSetting": "SqlConnectionString" + } + ], + "disabled": false +} \ No newline at end of file diff --git a/test/Integration/test-powershell/AddProductMissingColumns/run.ps1 b/test/Integration/test-powershell/AddProductMissingColumns/run.ps1 new file mode 100644 index 000000000..e56af3aa0 --- /dev/null +++ b/test/Integration/test-powershell/AddProductMissingColumns/run.ps1 @@ -0,0 +1,27 @@ +using namespace System.Net + +# Trigger binding data passed in via param block +param($Request) + +# Write to the Azure Functions log stream. +Write-Host "PowerShell function with SQL Output Binding processed a request." + +# Update req_body with the body of the request +# Note that this expects the body to be a JSON object or array of objects +# which have a property matching each of the columns in the table to upsert to. +$req_body = @{ + productId=1; + name="MissingCost"; + # Cost is missing +}; + +# Assign the value we want to pass to the SQL Output binding. +# The -Name value corresponds to the name property in the function.json for the binding +Push-OutputBinding -Name product -Value $req_body + +# Assign the value to return as the HTTP response. +# The -Name value matches the name property in the function.json for the binding +Push-OutputBinding -Name response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $req_body +}) \ No newline at end of file diff --git a/test/Integration/test-powershell/AddProductMissingColumnsExceptionFunction/function.json b/test/Integration/test-powershell/AddProductMissingColumnsExceptionFunction/function.json new file mode 100644 index 000000000..f3f49ea8e --- /dev/null +++ b/test/Integration/test-powershell/AddProductMissingColumnsExceptionFunction/function.json @@ -0,0 +1,27 @@ +{ + "bindings": [ + { + "authLevel": "function", + "name": "Request", + "direction": "in", + "type": "httpTrigger", + "methods": [ + "post" + ], + "route": "addproduct-missingcolumnsexception" + }, + { + "name": "response", + "type": "http", + "direction": "out" + }, + { + "name": "products", + "type": "sql", + "direction": "out", + "commandText": "[dbo].[ProductsCostNotNull]", + "connectionStringSetting": "SqlConnectionString" + } + ], + "disabled": false +} \ No newline at end of file diff --git a/test/Integration/test-powershell/AddProductMissingColumnsExceptionFunction/run.ps1 b/test/Integration/test-powershell/AddProductMissingColumnsExceptionFunction/run.ps1 new file mode 100644 index 000000000..87bb12c20 --- /dev/null +++ b/test/Integration/test-powershell/AddProductMissingColumnsExceptionFunction/run.ps1 @@ -0,0 +1,27 @@ +using namespace System.Net + +# Trigger binding data passed in via param block +param($Request) + +# Write to the Azure Functions log stream. +Write-Host "PowerShell function with SQL Output Binding processed a request." + +# Update req_body with the body of the request +# Note that this expects the body to be a JSON object or array of objects +# which have a property matching each of the columns in the table to upsert to. +$req_body = @{ + productId=1; + name="MissingCost"; + # Cost is missing +}; + +# Assign the value we want to pass to the SQL Output binding. +# The -Name value corresponds to the name property in the function.json for the binding +Push-OutputBinding -Name products -Value $req_body + +# Assign the value to return as the HTTP response. +# The -Name value matches the name property in the function.json for the binding +Push-OutputBinding -Name response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $req_body +}) \ No newline at end of file diff --git a/test/Integration/test-powershell/AddProductsNoPartialUpsert/function.json b/test/Integration/test-powershell/AddProductsNoPartialUpsert/function.json new file mode 100644 index 000000000..cbf55b8c1 --- /dev/null +++ b/test/Integration/test-powershell/AddProductsNoPartialUpsert/function.json @@ -0,0 +1,27 @@ +{ + "bindings": [ + { + "authLevel": "function", + "name": "Request", + "direction": "in", + "type": "httpTrigger", + "methods": [ + "post" + ], + "route": "addproducts-nopartialupsert" + }, + { + "name": "response", + "type": "http", + "direction": "out" + }, + { + "name": "products", + "type": "sql", + "direction": "out", + "commandText": "[dbo].[ProductsNameNotNull]", + "connectionStringSetting": "SqlConnectionString" + } + ], + "disabled": false +} \ No newline at end of file diff --git a/test/Integration/test-powershell/AddProductsNoPartialUpsert/run.ps1 b/test/Integration/test-powershell/AddProductsNoPartialUpsert/run.ps1 new file mode 100644 index 000000000..844318d7f --- /dev/null +++ b/test/Integration/test-powershell/AddProductsNoPartialUpsert/run.ps1 @@ -0,0 +1,33 @@ +using namespace System.Net + +# Trigger binding data passed in via param block +param($Request) +$totalUpserts = 1000; + +$products = @() +for($i = 0; $i -lt $totalUpserts; $i++) { + $products += [PSCustomObject]@{ + productId = $i; + name = "test"; + cost = 100 * $i; + } +} + +$invalidProduct = @{ + productId=1000; + name=$null; + cost=1000; +}; + +$products += $invalidProduct + +# Assign the value we want to pass to the SQL Output binding. +# The -Name value corresponds to the name property in the function.json for the binding +Push-OutputBinding -Name products -Value $products + +# Assign the value to return as the HTTP response. +# The -Name value matches the name property in the function.json for the binding +Push-OutputBinding -Name response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $products +}) \ No newline at end of file diff --git a/test/Integration/test-powershell/GetProductsColumnTypesSerialization/function.json b/test/Integration/test-powershell/GetProductsColumnTypesSerialization/function.json new file mode 100644 index 000000000..719e2a3c0 --- /dev/null +++ b/test/Integration/test-powershell/GetProductsColumnTypesSerialization/function.json @@ -0,0 +1,28 @@ +{ + "bindings": [ + { + "authLevel": "function", + "name": "Request", + "type": "httpTrigger", + "direction": "in", + "methods": [ + "get" + ], + "route": "getproducts-columntypesserialization" + }, + { + "name": "response", + "type": "http", + "direction": "out" + }, + { + "name": "products", + "type": "sql", + "direction": "in", + "commandText": "SELECT * FROM [dbo].[ProductsColumnTypes]", + "commandType": "Text", + "connectionStringSetting": "SqlConnectionString" + } + ], + "disabled": false +} \ No newline at end of file diff --git a/test/Integration/test-powershell/GetProductsColumnTypesSerialization/run.ps1 b/test/Integration/test-powershell/GetProductsColumnTypesSerialization/run.ps1 new file mode 100644 index 000000000..53e94ca3a --- /dev/null +++ b/test/Integration/test-powershell/GetProductsColumnTypesSerialization/run.ps1 @@ -0,0 +1,14 @@ +using namespace System.Net + +# Trigger and input binding data are passed in via the param block. +param($Request, $products) + +# Write to the Azure Functions log stream. +Write-Host "PowerShell function with SQL Input Binding processed a request." + +# Assign the value to return as the HTTP response. +# The -Name value matches the name property in the function.json for the binding +Push-OutputBinding -Name response -Value ([HttpResponseContext]@{ + StatusCode = [System.Net.HttpStatusCode]::OK + Body = $products +}) \ No newline at end of file diff --git a/test/Microsoft.Azure.WebJobs.Extensions.Sql.Tests.csproj b/test/Microsoft.Azure.WebJobs.Extensions.Sql.Tests.csproj index 78af40db5..075a7091a 100644 --- a/test/Microsoft.Azure.WebJobs.Extensions.Sql.Tests.csproj +++ b/test/Microsoft.Azure.WebJobs.Extensions.Sql.Tests.csproj @@ -32,5 +32,11 @@ + + <_PSCopyItems Include="..\samples\samples-powershell\**\*.*" /> + <_PSCopyItems Include="Integration\test-powershell\**\*.*" /> + + +