Skip to content

Commit

Permalink
Merge pull request Azure#6152 from bmoore-msft/functionapps
Browse files Browse the repository at this point in the history
added sample
  • Loading branch information
bmoore-msft authored May 4, 2019
2 parents 32af920 + ecd93c7 commit 6920874
Show file tree
Hide file tree
Showing 17 changed files with 576 additions and 0 deletions.
96 changes: 96 additions & 0 deletions 101-custom-rp-with-function/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Creating a Custom Provider with Resources

<a href="https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-quickstart-templates%2Fmaster%2F101-custom-rp-with-function%2Fazuredeploy.json" target="_blank">
<img src="http://azuredeploy.net/deploybutton.png"/>
</a>
<a href="http://armviz.io/#/?load=https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-quickstart-templates%2Fmaster%2F101-custom-rp-function%2Fazuredeploy.json" target="_blank">
<img src="http://armviz.io/visualizebutton.png"/>
</a>

This sample template deploys a custom resource provider to Azure and creates a user using an ARM template. You may optionally deploy the function app and custom provider definition - this only needs to be done once and then the custom resource can be deployed many times.

The customproviders resource is a hidden Azure resource so to confirm that the resource provider has been deployed you will have to check the box that says *Show hidden types* in the Azure portal Overview page for the resource group.

![](images/showhidden.png)

## Details on the custom resource provider created

This sample deployment creates the following two apis on the resource.

1) An ARM extended resource called "users"
2) An API called "ping"

### Users

The users resource is defined in the following part of the ARM template :

```json
"resourceTypes": [
{
"name":"users",
"routingType":"Proxy,Cache",
"endpoint": "[concat('https://', parameters('funcname'), '.azurewebsites.net/api/{requestPath}')]"
}
]
```

In the above template we can see that the resource "users" has been defined as a Proxy resource which means that it is backed by a REST api endpoint. The details of the endpoint come next. The endpoint uri in the section refers to the endpoint that implements this resource. When the resource is defined as above , the resource will support all CRUD calls like "GET", "PUT", "DELETE" etc and it is expected that the endpoint has implemented them. In the above case this means that we will be able to make the following calls on ARM:

```
PUT/GET/DELETE /subscriptions/{subscriptionid}/resourceGroups/{resourcegroup}/providers/Microsoft.CustomProviders/resourceProviders/{customrpname}/users/name?<api-version>
```

You can see this in action in the last part of the template where we create this new user type :

```json
{
"type": "Microsoft.CustomProviders/resourceProviders/users",
"name": "[concat(parameters('funcname'), '/santa')]",
"apiVersion": "2018-09-01-preview",
"location": "eastus",
"properties": {
"FullName": "Santa Claus",
"Location": "NorthPole"
},
"dependsOn": [
"[concat('Microsoft.Web/sites/',parameters('funcname'))]"
]
}
```

Navigating to the deployment details on the templatedeployment will show a new resource type called resourceproviders/users created on the custom resource provider with the name santa
![](images/createduser.png)

To confirm that the user has been created , you can use a rest api client such as postman and run the following query and see the results:

```
GET
https://management.azure.com/subscriptions/{subscriptionid}/resourceGroups/{resourcegroup}/providers/Microsoft.CustomProviders/resourceProviders/{customrpname}/users/santa?api-version=2018-09-01-preview
```

You can also create\delete additional users.

### Ping action

In addition to users you can also define actions on your resourceprovider. An example action called ping is provided here defined as follows:

```json
"actions": [
{
"name": "ping",
"routingType":"Proxy",
"endpoint": "[concat('https://', parameters('funcname'), '.azurewebsites.net/api/{requestPath}')]"
}
]
```

The format for this action is similar to the resource type defined above , but since this is an action this call will only support POST methods as follows:

```
POST
https://management.azure.com/subscriptions/{subscriptionid}/resourceGroups/{resourcegroup}/providers/Microsoft.CustomProviders/resourceProviders/{customrpname}/ping?api-version=2018-09-01-preview
```

The code that enables this process is all implemented as part of the azure function that is deployed along with the template. To further understand how the function has been configured please look here:

+ [**Creating an azure function**](SampleFunctions/CSharpSimpleProvider/README.md)
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
162 changes: 162 additions & 0 deletions 101-custom-rp-with-function/azuredeploy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"location": {
"type": "string",
"allowedValues": [ "australiaeast", "eastus", "westeurope" ],
"metadata": {
"description": "Location for the resources."
}
},
"deployFunction": {
"type": "bool",
"defaultValue": true,
"metadata": {
"description": "Determines whether to deploy the function app and create the custom RP."
}
},
"funcName": {
"type": "string",
"defaultValue": "[uniqueString(resourceGroup().id)]",
"metadata": {
"description": "Name of the function app to be created."
}
},
"storageAccountName": {
"type": "string",
"defaultValue": "[uniqueString(resourceGroup().id)]",
"metadata": {
"description": "Name of the storage account for storing users in the function app"
}
},
"userName": {
"type": "string",
"metadata": {
"description": "Name of the user to be added."
}
},
"userLocation": {
"type": "string",
"metadata": {
"description": "location of the user, not related to the resource location."
}
},
"_artifactsLocation": {
"type": "string",
"metadata": {
"description": "The base URI where artifacts required by this template are located. When the template is deployed using the accompanying scripts, a private location in the subscription will be used and this value will be automatically generated."
},
"defaultValue": "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/101-custom-rp-with-function/"
},
"_artifactsLocationSasToken": {
"type": "securestring",
"metadata": {
"description": "The sasToken required to access _artifactsLocation. When the template is deployed using the accompanying scripts, a sasToken will be automatically generated."
},
"defaultValue": ""
}
},
"variables": {},
"resources": [
{
"condition": "[parameters('deployFunction')]",
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2018-02-01",
"name": "[parameters('storageAccountName')]",
"location": "[parameters('location')]",
"kind": "StorageV2",
"sku": {
"name": "Standard_LRS"
}
},
{
"condition": "[parameters('deployFunction')]",
"type": "Microsoft.Web/sites",
"apiVersion": "2018-02-01",
"name": "[parameters('funcName')]",
"location": "[parameters('location')]",
"kind": "functionapp",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]"
],
"properties": {
"name": "[parameters('funcName')]",
"siteConfig": {
"appSettings": [
{
"name": "AzureWebJobsDashboard",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=',parameters('storageAccountName'),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2018-02-01').keys[0].value)]"
},
{
"name": "AzureWebJobsStorage",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=',parameters('storageAccountName'),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2018-02-01').keys[0].value)]"
},
{
"name": "FUNCTIONS_EXTENSION_VERSION",
"value": "~2"
},
{
"name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=',parameters('storageAccountName'),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2018-02-01').keys[0].value)]"
},
{
"name": "WEBSITE_CONTENTSHARE",
"value": "[concat(toLower(parameters('funcName')), 'b86e')]"
},
{
"name": "WEBSITE_NODE_DEFAULT_VERSION",
"value": "6.5.0"
},
{
"name": "WEBSITE_RUN_FROM_PACKAGE",
"value": "[uri(parameters('_artifactsLocation'), concat('artifacts/functionzip/functionpackage.zip', parameters('_artifactsLocationSasToken')))]"
}
]
},
"clientAffinityEnabled": false,
"reserved": false
}
},
{
"condition": "[parameters('deployFunction')]",
"type": "Microsoft.CustomProviders/resourceProviders",
"apiVersion": "2018-09-01-preview",
"name": "[parameters('funcName')]",
"location": "[parameters('location')]",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', parameters('funcName'))]"
],
"properties": {
"actions": [
{
"name": "ping",
"routingType": "Proxy",
"endpoint": "[concat('https://', reference(resourceId('Microsoft.Web/sites', parameters('funcName')), '2018-02-01').defaultHostName, '/api/{requestPath}')]"
}
],
"resourceTypes": [
{
"name": "users",
"routingType": "Proxy,Cache",
"endpoint": "[concat('https://', reference(resourceId('Microsoft.Web/sites', parameters('funcName')), '2018-02-01').defaultHostName, '/api/{requestPath}')]"
}
]
}
},
{
"type": "Microsoft.CustomProviders/resourceProviders/users",
"name": "[concat(parameters('funcName'), '/addUser')]",
"apiVersion": "2018-09-01-preview",
"location": "[parameters('location')]",
"dependsOn": [
"[resourceId('Microsoft.CustomProviders/resourceProviders', parameters('funcName'))]"
],
"properties": {
"FullName": "[parameters('userName')]",
"Location": "[parameters('userLocation')]"
}
}

]
}
15 changes: 15 additions & 0 deletions 101-custom-rp-with-function/azuredeploy.parameters.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"location": {
"value": "eastus"
},
"username": {
"value": "Santa Claus"
},
"userLocation": {
"value": "NorthPole"
}
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added 101-custom-rp-with-function/images/showhidden.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions 101-custom-rp-with-function/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"$schema": "https://aka.ms/azure-quickstart-templates-metadata-schema#",
"type": "QuickStart",
"itemDisplayName": "Create a function app and call it using a Custom Resource",
"description": "This template creates function app used as the workload for a custom resource provider in a template deployment.",
"summary": "This template creates function app used as the workload for a custom resource provider in a template deployment.",
"githubUsername": "raosuhas",
"dateUpdated": "2019-05-03"
}


36 changes: 36 additions & 0 deletions 101-custom-rp-with-function/src/HttpTrigger1/function.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"bindings": [
{
"authLevel": "anonymous",
"name": "req",
"type": "httpTrigger",
"direction": "in",
"methods": [
"post",
"get",
"delete",
"put"
],
"route": "subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.CustomProviders/resourceproviders/{minirpname}/{action}/{name}"
},
{
"name": "$return",
"type": "http",
"direction": "out"
},
{
"type": "blob",
"name": "outstorageBlob",
"path": "storecontainer/datastore",
"connection": "AzureWebJobsStorage",
"direction": "out"
},
{
"type": "blob",
"name": "instorageBlob",
"path": "storecontainer/datastore",
"connection": "AzureWebJobsStorage",
"direction": "in"
}
]
}
11 changes: 11 additions & 0 deletions 101-custom-rp-with-function/src/HttpTrigger1/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# HttpTrigger - C<span>#</span>

The `HttpTrigger` makes it incredibly easy to have your functions executed via an HTTP call to your function.

## How it works

When you call the function, be sure you checkout which security rules you apply. If you're using an apikey, you'll need to include that in your request.

## Learn more

<TODO> Documentation
Loading

0 comments on commit 6920874

Please sign in to comment.