Repository: serverless/serverless-azure-functions
Pull request #348 (2019-09-27 15:42:47)

feat: Refactor runtime configuration to allow for non-node runtimes
<!--
1. Please check out and follow our Contributing Guidelines: https://github.com/serverless/serverless-azure-functions/CONTRIBUTING.md
2. Do not remove any section of the template. If something is not applicable leave it empty but leave it in the PR
3. Please follow the template, otherwise we'll have to ask you to update it and it will take longer until your PR is merged
-->

## What did you implement:

- Refactored runtime to allow for non-node runtimes

<!--
Briefly describe the feature if no issue exists for this PR
-->

## How did you implement it:

- Added `FunctionRuntime` configuration to provider
- Extracting `FunctionRuntime` from `runtime` property of configuration within `ConfigService`
- Refactored node-specific code in ARM template generation

<!--
If this is a nontrivial change please briefly describe your implementation so its easy for us to understand and review your code.
-->

## How can we verify it:

- Run a full deployment, check the ARM template

<!--
Add any applicable config, commands, screenshots or other resources
to make it easy for us to verify this works. The easier you make it for us
to review a PR, the faster we can review and merge it.

Examples:
* serverless.yml - Fully functioning to easily deploy changes
* Screenshots - Showing the difference between your output and the master
* Cloud Configuration - List cloud resources and show that the correct configuration is in place (e.g. AWS CLI commands)
* Other - Anything else that comes to mind to help us evaluate
-->

## Todos:

_**Note: Run `npm run test:ci` to run all validation checks on proposed changes**_

- [x] Write tests and confirm existing functionality is not broken.  
       **Validate via `npm test`**
- [x] Write documentation
- [x] Ensure there are no lint errors.  
       **Validate via `npm run lint`**  
       _Note: Some reported issues can be automatically fixed by running `npm run lint:fix`_
- [x] Make sure code coverage hasn't dropped
- [x] Provide verification config / commands / resources
- [x] Enable "Allow edits from maintainers" for this PR
- [x] Update the messages below

**_Is this ready for review?:_** YES  
**_Is it a breaking change?:_** NO



Patch:
diff --git a/.gitignore b/.gitignore
index c93070f..f707dcf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,5 @@ node_modules/
 /coverage/
 .env*
 .idea/
+
+.vscode/launch.json
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index e3c724b..33af377 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
 {
   "name": "serverless-azure-functions",
-  "version": "1.0.2-4",
+  "version": "1.0.2-5",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
diff --git a/package.json b/package.json
index 130a4ad..1ab3364 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "serverless-azure-functions",
-  "version": "1.0.2-4",
+  "version": "1.0.2-5",
   "description": "Provider plugin for the Serverless Framework v1.x which adds support for Azure Functions.",
   "license": "MIT",
   "main": "./lib/index.js",
diff --git a/src/armTemplates/resources/functionApp.ts b/src/armTemplates/resources/functionApp.ts
index aceaa92..5d597c5 100644
--- a/src/armTemplates/resources/functionApp.ts
+++ b/src/armTemplates/resources/functionApp.ts
@@ -1,11 +1,7 @@
-import { ArmResourceTemplate, ArmResourceTemplateGenerator, ArmParamType, ArmParameters, DefaultArmParams, ArmParameter } from "../../models/armTemplates";
-import { FunctionAppConfig, ServerlessAzureConfig } from "../../models/serverless";
+import { ArmParameter, ArmParameters, ArmParamType, ArmResourceTemplate, ArmResourceTemplateGenerator, DefaultArmParams } from "../../models/armTemplates";
+import { FunctionAppConfig, ServerlessAzureConfig, SupportedRuntimeLanguage } from "../../models/serverless";
 import { AzureNamingService, AzureNamingServiceOptions } from "../../services/namingService";
 
-//Runtime versions found at " https://<sitename>.scm.azurewebsites.net/api/diagnostics/runtime".
-import runtimeVersionsJson from "../../services/runtimeVersions.json";
-import semver from "semver";
-
 interface FunctionAppParams extends DefaultArmParams {
   functionAppName: ArmParameter;
   functionAppNodeVersion: ArmParameter;
@@ -132,18 +128,23 @@ export class FunctionAppResource implements ArmResourceTemplateGenerator {
   public getParameters(config: ServerlessAzureConfig): ArmParameters {
     const resourceConfig: FunctionAppConfig = {
       ...config.provider.functionApp,
-      nodeVersion: this.getRuntimeVersion(config.provider.runtime)
     };
+    const { functionRuntime } = config.provider;
+
 
     const params: FunctionAppParams = {
       functionAppName: {
         value: FunctionAppResource.getResourceName(config),
       },
       functionAppNodeVersion: {
-        value: resourceConfig.nodeVersion,
+        value: (functionRuntime.language === SupportedRuntimeLanguage.NODE)
+          ?
+          functionRuntime.version
+          :
+          undefined
       },
       functionAppWorkerRuntime: {
-        value: resourceConfig.workerRuntime,
+        value: functionRuntime.language,
       },
       functionAppExtensionVersion: {
         value: resourceConfig.extensionVersion,
@@ -152,37 +153,4 @@ export class FunctionAppResource implements ArmResourceTemplateGenerator {
 
     return params as unknown as ArmParameters;
   }
-
-  private getRuntimeVersion(runtime: string): string {
-    if (!runtime) {
-      throw new Error("Runtime version not specified in serverless.yml");
-    }
-    const extractedVersion = runtime.split("nodejs")[1];
-    const runtimeVersionsList = runtimeVersionsJson["nodejs"];
-
-    //Searches for a specific version. For example nodejs10.6.0.
-    if (!extractedVersion.endsWith(".x")) {
-      let retrivedVersion: string;
-      for (const version of runtimeVersionsList) {
-        retrivedVersion = version["version"];
-        if (extractedVersion === retrivedVersion && semver.valid(retrivedVersion)) {
-          return retrivedVersion;
-        }
-      }
-    }
-    else {
-      // User specified something like nodejs10.14.x
-      const extractedVersionNumber = extractedVersion.replace(/[^0-9\.]/g, "");
-
-      const selectedVersions = runtimeVersionsList.filter(({ version }) => {
-        return version.startsWith(extractedVersionNumber) && semver.valid(version)
-      }).map((item) => item.version);
-
-      if (!selectedVersions.length) {
-        throw new Error(`Could not find runtime version matching ${runtime}`)
-      }
-      return selectedVersions.sort(semver.rcompare)[0]
-    }
-    throw new Error(`Could not find runtime version matching ${runtime}`)
-  }
 }
diff --git a/src/models/serverless.ts b/src/models/serverless.ts
index 78be3ea..16dfbe6 100644
--- a/src/models/serverless.ts
+++ b/src/models/serverless.ts
@@ -53,6 +53,22 @@ export interface ServerlessAzureProvider {
   armTemplate?: ArmTemplateConfig;
   keyVaultConfig?: AzureKeyVaultConfig;
   runtime: string;
+  functionRuntime?: FunctionRuntime;
+}
+
+export enum FunctionAppOS {
+  WINDOWS = "windows",
+  LINUX = "linux"
+}
+
+export interface FunctionRuntime {
+  language: SupportedRuntimeLanguage;
+  version: string;
+}
+
+export enum SupportedRuntimeLanguage {
+  PYTHON = "python",
+  NODE = "node"
 }
 
 /**
diff --git a/src/services/armService.ts b/src/services/armService.ts
index a574c01..f64f7e4 100644
--- a/src/services/armService.ts
+++ b/src/services/armService.ts
@@ -1,16 +1,16 @@
 import { ResourceManagementClient } from "@azure/arm-resources";
 import { Deployment, DeploymentExtended } from "@azure/arm-resources/esm/models";
+import deepEqual from "deep-equal";
 import fs from "fs";
 import jsonpath from "jsonpath";
 import path from "path";
 import Serverless from "serverless";
-import { ArmDeployment, ArmResourceTemplateGenerator, ArmTemplateType, ArmResourceTemplate, ArmParameters } from "../models/armTemplates";
-import { ArmTemplateConfig, ServerlessAzureConfig, ServerlessAzureOptions } from "../models/serverless";
+import { ArmDeployment, ArmParameters, ArmResourceTemplate, ArmResourceTemplateGenerator, ArmTemplateType } from "../models/armTemplates";
+import { DeploymentExtendedError } from "../models/azureProvider";
+import { ArmTemplateConfig, ServerlessAzureOptions } from "../models/serverless";
 import { Guard } from "../shared/guard";
 import { BaseService } from "./baseService";
-import { ResourceService } from "./resourceService"
-import { DeploymentExtendedError } from "../models/azureProvider";
-import deepEqual from "deep-equal";
+import { ResourceService } from "./resourceService";
 
 export class ArmService extends BaseService {
   private resourceClient: ResourceManagementClient;
@@ -39,13 +39,12 @@ export class ArmService extends BaseService {
       throw new Error(`Unable to find template with name ${type} `);
     }
 
-    const azureConfig: ServerlessAzureConfig = this.serverless.service as any;
     const mergedTemplate = template.getTemplate();
-    let parameters = template.getParameters(azureConfig);
+    let parameters = template.getParameters(this.config);
 
     if (this.config.provider.apim) {
       const apimTemplate = apimResource.getTemplate();
-      const apimParameters = apimResource.getParameters(azureConfig);
+      const apimParameters = apimResource.getParameters(this.config);
 
       mergedTemplate.parameters = {
         ...mergedTemplate.parameters,
diff --git a/src/services/baseService.ts b/src/services/baseService.ts
index 13caf56..71ace8c 100644
--- a/src/services/baseService.ts
+++ b/src/services/baseService.ts
@@ -4,11 +4,7 @@ import fs from "fs";
 import request from "request";
 import Serverless from "serverless";
 import { StorageAccountResource } from "../armTemplates/resources/storageAccount";
-import { 
-  ServerlessAzureConfig,
-  ServerlessAzureOptions,
-  ServerlessLogOptions 
-} from "../models/serverless";
+import { ServerlessAzureConfig, ServerlessAzureOptions, ServerlessLogOptions } from "../models/serverless";
 import { constants } from "../shared/constants";
 import { Guard } from "../shared/guard";
 import { Utils } from "../shared/utils";
diff --git a/src/services/configService.ts b/src/services/configService.ts
index 3af065f..a1c549a 100644
--- a/src/services/configService.ts
+++ b/src/services/configService.ts
@@ -1,10 +1,14 @@
+import semver from "semver";
 import Serverless from "serverless";
 import Service from "serverless/classes/Service";
 import configConstants from "../config";
-import { ServerlessAzureConfig, ServerlessAzureFunctionConfig, DeploymentConfig } from "../models/serverless";
+import { DeploymentConfig, FunctionRuntime, ServerlessAzureConfig, 
+  ServerlessAzureFunctionConfig, SupportedRuntimeLanguage } from "../models/serverless";
 import { constants } from "../shared/constants";
+import { Guard } from "../shared/guard";
 import { Utils } from "../shared/utils";
 import { AzureNamingService, AzureNamingServiceOptions } from "./namingService";
+import runtimeVersionsJson from "./runtimeVersions.json";
 
 /**
  * Handles all Service Configuration
@@ -107,6 +111,13 @@ export class ConfigService {
     return this.config.service;
   }
 
+  /**
+   * Function runtime configuration
+   */
+  public getFunctionRuntime(): FunctionRuntime {
+    return this.config.provider.functionRuntime;
+  }
+
   /**
    * Set any default values required for service
    * @param config Current Serverless configuration
@@ -143,7 +154,8 @@ export class ConfigService {
       subscriptionId,
       tenantId,
       appId,
-      deployment
+      deployment,
+      runtime
     } = config.provider;
 
     const options: AzureNamingServiceOptions = {
@@ -182,9 +194,65 @@ export class ConfigService {
       ...deployment
     }
 
+    config.provider.functionRuntime = this.getRuntime(runtime)
+
     return config;
   }
 
+  private getRuntime(runtime: string): FunctionRuntime {
+    Guard.null(runtime, "runtime", "Runtime version not specified in serverless.yml");
+
+    const versionMatch = runtime.match(/([0-9]+\.)+[0-9]*x?/);
+    const languageMatch = runtime.match(/nodejs|python/);
+
+    let versionInput: string;
+    let languageInput: string;
+
+    // Extract version and language input
+    if (versionMatch && languageMatch) {
+      versionInput = versionMatch[0];
+      languageInput = languageMatch[0];
+    } else {
+      throw new Error(`Invalid runtime: ${runtime}. ${this.getRuntimeErrorMessage(null)}`);
+    }
+
+    const targetedVersionRegex = new RegExp(
+      `^${versionInput}`
+        .replace(".", "\.")
+        .replace("x", "[0-9]+"),
+    );
+
+    const matchingVersions: string[] = runtimeVersionsJson[languageInput]
+      .filter((item) => item.version.match(targetedVersionRegex))
+      .map((item) => item.version);
+
+    if (!matchingVersions.length) {
+      throw new Error(`Runtime ${runtime} is not supported. ${this.getRuntimeErrorMessage(null)}`);
+    }
+
+    const version = matchingVersions.sort(semver.rcompare)[0];
+
+    const language: SupportedRuntimeLanguage = {
+      "nodejs": SupportedRuntimeLanguage.NODE,
+      "python": SupportedRuntimeLanguage.PYTHON
+    }[languageInput];
+    
+    return {
+      language,
+      version
+    }
+  }
+
+  private getRuntimeErrorMessage(language: SupportedRuntimeLanguage) {
+    if (language) {
+      return `Supported versions for ${language} are: ${
+        runtimeVersionsJson[language]
+          .map((item) => item.version)
+          .join(",")}`
+    }
+    return `Supported versions: ${JSON.stringify(runtimeVersionsJson, null, 2)}`
+  }
+
   /**
    * Get timestamp from `packageTimestamp` serverless variable
    * If not set, create timestamp, set variable and return timestamp
diff --git a/src/services/offlineService.ts b/src/services/offlineService.ts
index 2664e82..656ea2a 100644
--- a/src/services/offlineService.ts
+++ b/src/services/offlineService.ts
@@ -15,7 +15,7 @@ export class OfflineService extends BaseService {
       IsEncrypted: false,
       Values: {
         AzureWebJobsStorage: "UseDevelopmentStorage=true",
-        FUNCTIONS_WORKER_RUNTIME: "node"
+        FUNCTIONS_WORKER_RUNTIME: this.config.provider.functionRuntime.language
       }
     }),
   }
diff --git a/src/services/runtimeVersions.json b/src/services/runtimeVersions.json
index 7e81b70..af11e33 100644
--- a/src/services/runtimeVersions.json
+++ b/src/services/runtimeVersions.json
@@ -1,63 +1,69 @@
 {
-    "nodejs": [{
-        "version": "0.10.40",
-        "npm": "1.4.28"
-    }, {
-        "version": "0.10.5",
-        "npm": "1.2.18"
-    }, {
-        "version": "0.12.6",
-        "npm": "2.11.2"
-    }, {
-        "version": "0.6.20",
-        "npm": "1.1.37"
-    }, {
-        "version": "0.8.28",
-        "npm": "1.2.30"
-    }, {
-        "version": "10.14.1",
-        "npm": "6.4.1"
-    }, {
-        "version": "10.15.2",
-        "npm": "6.4.1"
-    }, {
-        "version": "10.6.0",
-        "npm": "6.1.0"
-    }, {
-        "version": "4.8.4",
-        "npm": "2.15.11"
-    }, {
-        "version": "6.12.3",
-        "npm": "3.10.10"
-    }, {
-        "version": "6.5.0",
-        "npm": "3.10.3"
-    }, {
-        "version": "6.9.1",
-        "npm": "3.10.8"
-    }, {
-        "version": "6.9.5",
-        "npm": "3.10.10"
-    }, {
-        "version": "7.10.1",
-        "npm": "4.2.0"
-    }, {
-        "version": "8.1.4",
-        "npm": "5.0.3"
-    }, {
-        "version": "8.10.0",
-        "npm": "5.6.0"
-    }, {
-        "version": "8.11.1",
-        "npm": "5.6.0"
-    }, {
-        "version": "8.4.0",
-        "npm": "5.3.0"
-    }, {
-        "version": "8.5.0",
-        "npm": "5.3.0"
-    }, {
-        "version": "8.9.4",
-        "npm": "5.6.0"
-    }]
+    "nodejs": [
+        {
+            "version": "0.10.40"
+        },
+        {
+            "version": "0.10.5"
+        },
+        {
+            "version": "0.12.6"
+        },
+        {
+            "version": "0.6.20"
+        },
+        {
+            "version": "0.8.28"
+        },
+        {
+            "version": "10.14.1"
+        },
+        {
+            "version": "10.15.2"
+        },
+        {
+            "version": "10.6.0"
+        },
+        {
+            "version": "4.8.4"
+        },
+        {
+            "version": "6.12.3"
+        },
+        {
+            "version": "6.5.0"
+        },
+        {
+            "version": "6.9.1"
+        },
+        {
+            "version": "6.9.5"
+        },
+        {
+            "version": "7.10.1"
+        },
+        {
+            "version": "8.1.4"
+        },
+        {
+            "version": "8.10.0"
+        },
+        {
+            "version": "8.11.1"
+        },
+        {
+            "version": "8.4.0"
+        },
+        {
+            "version": "8.5.0"
+        },
+        {
+            "version": "8.9.4"
+        }
+    ],
+    "python": [
+        {
+            "version": "3.6"
+        }
+    ]
 }
\ No newline at end of file
diff --git a/src/shared/bindings.json b/src/shared/bindings.json
index b9d17ce..359f25f 100644
--- a/src/shared/bindings.json
+++ b/src/shared/bindings.json
@@ -1,1741 +1,1749 @@
 {
-    "$schema": "<TBD>",
-    "contentVersion": "2016-03-04-alpha",
-    "variables": {
-        "storageConnStringLabel": "$variables_storageConnStringLabel",
-        "appSettingsHelp": "$variables_appSettingsHelp",
-        "selectConnection": "$variables_selectConnection",
-        "parameterName": "$variables_parameterName",
-        "paramNameLabel": "$variables_paramNameLabel",
-        "paramNameInputHelp": "$variables_paramNameInputHelp",
-        "paramNameOutputHelp": "$variables_paramNameOutputHelp",
-        "apiHubTableDataSetLabel": "$variables_apiHubTableDataSetLabel",
-        "apiHubTableDataSetHelp": "$variables_apiHubTableDataSetHelp",
-        "apiHubTableNameLabel": "$variables_apiHubTableNameLabel",
-        "apiHubTableHelp": "$variables_apiHubTableHelp",
-        "apiHubTableEntityLabel": "$variables_apiHubTableEntityLabel",
-        "apiHubTableEntityHelp": "$variables_apiHubTableEntityHelp",
-        "apiHubTableConnectionLabel": "$variables_apiHubTableConnectionLabel",
-        "apiHubTableConnectionHelp": "$variables_apiHubTableConnectionHelp"
+  "$schema": "<TBD>",
+  "contentVersion": "2016-03-04-alpha",
+  "variables": {
+    "storageConnStringLabel": "$variables_storageConnStringLabel",
+    "appSettingsHelp": "$variables_appSettingsHelp",
+    "selectConnection": "$variables_selectConnection",
+    "parameterName": "$variables_parameterName",
+    "paramNameLabel": "$variables_paramNameLabel",
+    "paramNameInputHelp": "$variables_paramNameInputHelp",
+    "paramNameOutputHelp": "$variables_paramNameOutputHelp",
+    "apiHubTableDataSetLabel": "$variables_apiHubTableDataSetLabel",
+    "apiHubTableDataSetHelp": "$variables_apiHubTableDataSetHelp",
+    "apiHubTableNameLabel": "$variables_apiHubTableNameLabel",
+    "apiHubTableHelp": "$variables_apiHubTableHelp",
+    "apiHubTableEntityLabel": "$variables_apiHubTableEntityLabel",
+    "apiHubTableEntityHelp": "$variables_apiHubTableEntityHelp",
+    "apiHubTableConnectionLabel": "$variables_apiHubTableConnectionLabel",
+    "apiHubTableConnectionHelp": "$variables_apiHubTableConnectionHelp"
+  },
+  "bindings": [
+    {
+      "type": "timerTrigger",
+      "displayName": "$timerTrigger_displayName",
+      "direction": "trigger",
+      "enabledInTryMode": true,
+      "documentation": "$content=Documentation\\timerTrigger.md",
+      "settings": [
+        {
+          "name": "name",
+          "value": "string",
+          "defaultValue": "myTimer",
+          "required": true,
+          "label": "$timerTrigger_name_label",
+          "help": "$timerTrigger_name_help",
+          "validators": [
+            {
+              "expression": "^[a-zA-Z][a-zA-Z0-9]{0,127}$",
+              "errorText": "[variables('parameterName')]"
+            }
+          ]
+        },
+        {
+          "name": "schedule",
+          "value": "string",
+          "defaultValue": "0 * * * * *",
+          "required": true,
+          "label": "$timerTrigger_schedule_label",
+          "help": "$timerTrigger_schedule_help",
+          "validators": [
+            {
+              "expression": "^(\\*|((([1-5]\\d)|\\d)(\\-(([1-5]\\d)|\\d)(\\/\\d+)?)?)(,((([1-5]\\d)|\\d)(\\-(([1-5]\\d)|\\d)(\\/\\d+)?)?))*)(\\/\\d+)? (\\*|((([1-5]\\d)|\\d)(\\-(([1-5]\\d)|\\d)(\\/\\d+)?)?)(,((([1-5]\\d)|\\d)(\\-(([1-5]\\d)|\\d)(\\/\\d+)?)?))*)(\\/\\d+)? (\\*|(((1\\d)|(2[0-3])|\\d)(\\-((1\\d)|(2[0-3])|\\d)(\\/\\d+)?)?)(,(((1\\d)|(2[0-3])|\\d)(\\-((1\\d)|(2[0-3])|\\d)(\\/\\d+)?)?))*)(\\/\\d+)? (\\*|((([1-2]\\d)|(3[0-1])|[1-9])(\\-(([1-2]\\d)|(3[0-1])|[1-9])(\\/\\d+)?)?)(,((([1-2]\\d)|(3[0-1])|[1-9])(\\-(([1-2]\\d)|(3[0-1])|[1-9])(\\/\\d+)?)?))*)(\\/\\d+)? (\\*|(([A-Za-z]+|(1[0-2])|[1-9])(\\-([A-Za-z]+|(1[0-2])|[1-9])(\\/\\d+)?)?)(,(([A-Za-z]+|(1[0-2])|[1-9])(\\-([A-Za-z]+|(1[0-2])|[1-9])(\\/\\d+)?)?))*)(\\/\\d+)? (\\*|(([A-Za-z]+|[0-6])(\\-([A-Za-z]+|[0-6])(\\/\\d+)?)?)(,(([A-Za-z]+|[0-6])(\\-([A-Za-z]+|[0-6])(\\/\\d+)?)?))*)(\\/\\d+)?$",
+              "errorText": "$timerTrigger_schedule_errorText"
+            }
+          ]
+        }
+      ]
     },
-    "bindings": [
-        {
-            "type": "timerTrigger",
-            "displayName": "$timerTrigger_displayName",
-            "direction": "trigger",
-            "enabledInTryMode": true,
-            "documentation": "$content=Documentation\\timerTrigger.md",
-            "settings": [
-                {
-                    "name": "name",
-                    "value": "string",
-                    "defaultValue": "myTimer",
-                    "required": true,
-                    "label": "$timerTrigger_name_label",
-                    "help": "$timerTrigger_name_help",
-                    "validators": [
-                        {
-                            "expression": "^[a-zA-Z][a-zA-Z0-9]{0,127}$",
-                            "errorText": "[variables('parameterName')]"
-                        }
-                    ]
-                },
-                {
-                    "name": "schedule",
-                    "value": "string",
-                    "defaultValue": "0 * * * * *",
-                    "required": true,
-                    "label": "$timerTrigger_schedule_label",
-                    "help": "$timerTrigger_schedule_help",
-                    "validators": [
-                        {
-                            "expression": "^(\\*|((([1-5]\\d)|\\d)(\\-(([1-5]\\d)|\\d)(\\/\\d+)?)?)(,((([1-5]\\d)|\\d)(\\-(([1-5]\\d)|\\d)(\\/\\d+)?)?))*)(\\/\\d+)? (\\*|((([1-5]\\d)|\\d)(\\-(([1-5]\\d)|\\d)(\\/\\d+)?)?)(,((([1-5]\\d)|\\d)(\\-(([1-5]\\d)|\\d)(\\/\\d+)?)?))*)(\\/\\d+)? (\\*|(((1\\d)|(2[0-3])|\\d)(\\-((1\\d)|(2[0-3])|\\d)(\\/\\d+)?)?)(,(((1\\d)|(2[0-3])|\\d)(\\-((1\\d)|(2[0-3])|\\d)(\\/\\d+)?)?))*)(\\/\\d+)? (\\*|((([1-2]\\d)|(3[0-1])|[1-9])(\\-(([1-2]\\d)|(3[0-1])|[1-9])(\\/\\d+)?)?)(,((([1-2]\\d)|(3[0-1])|[1-9])(\\-(([1-2]\\d)|(3[0-1])|[1-9])(\\/\\d+)?)?))*)(\\/\\d+)? (\\*|(([A-Za-z]+|(1[0-2])|[1-9])(\\-([A-Za-z]+|(1[0-2])|[1-9])(\\/\\d+)?)?)(,(([A-Za-z]+|(1[0-2])|[1-9])(\\-([A-Za-z]+|(1[0-2])|[1-9])(\\/\\d+)?)?))*)(\\/\\d+)? (\\*|(([A-Za-z]+|[0-6])(\\-([A-Za-z]+|[0-6])(\\/\\d+)?)?)(,(([A-Za-z]+|[0-6])(\\-([A-Za-z]+|[0-6])(\\/\\d+)?)?))*)(\\/\\d+)?$",
-                            "errorText": "$timerTrigger_schedule_errorText"
-                        }
-                    ]
-                }
-            ]
+    {
+      "type": "eventHubTrigger",
+      "displayName": "$eventHubTrigger_displayName",
+      "direction": "trigger",
+      "enabledInTryMode": false,
+      "documentation": "$content=Documentation\\eventHubTrigger.md",
+      "settings": [
+        {
+          "name": "name",
+          "value": "string",
+          "defaultValue": "myEventHubMessage",
+          "required": true,
+          "label": "$eventHubTrigger_name_label",
+          "help": "$eventHubTrigger_name_help",
+          "validators": [
+            {
+              "expression": "^[a-zA-Z][a-zA-Z0-9]{0,127}$",
+              "errorText": "[variables('parameterName')]"
+            }
+          ]
         },
         {
-            "type": "eventHubTrigger",
-            "displayName": "$eventHubTrigger_displayName",
-            "direction": "trigger",
-            "enabledInTryMode": false,
-            "documentation": "$content=Documentation\\eventHubTrigger.md",
-            "settings": [
-                {
-                    "name": "name",
-                    "value": "string",
-                    "defaultValue": "myEventHubMessage",
-                    "required": true,
-                    "label": "$eventHubTrigger_name_label",
-                    "help": "$eventHubTrigger_name_help",
-                    "validators": [
-                        {
-                            "expression": "^[a-zA-Z][a-zA-Z0-9]{0,127}$",
-                            "errorText": "[variables('parameterName')]"
-                        }
-                    ]
-                },
-                {
-                    "name": "eventHubName",
-                    "value": "string",
-                    "defaultValue": "myeventhub",
-                    "required": true,
-                    "label": "$eventHubOut_path_label",
-                    "help": "$eventHubTrigger_path_help",
-                    "validators": [
-                        {
-                            "expression": "^[a-z0-9]$|^[a-z0-9][a-z0-9-_.]{0,48}[a-z0-9]$|^[{][a-zA-Z0-9]{1,126}[}]$|^[%][a-zA-Z0-9]{1,126}[%]$",
-                            "errorText": "$eventHubTrigger_path_errorText"
-                        }
-                    ]
-                },
-                {
-                    "name": "consumerGroup",
-                    "value": "string",
-                    "defaultValue": "$Default",
-                    "required": false,
-                    "label": "$eventHubTrigger_consumerGroup_label",
-                    "help": "$eventHubTrigger_consumerGroup_help",
-                    "validators": [
-                        {
-                            "expression": "(^[a-z0-9]$|^[a-z0-9][a-z0-9-_.]{0,48}[a-z0-9]$)|^\\$Default$|^[{][a-zA-Z0-9]{1,126}[}]$|^[%][a-zA-Z0-9]{1,126}[%]$",
-                            "errorText": "$eventHubTrigger_consumerGroup_errorText"
-                        }
-                    ]
-                },
-                {
-                    "name": "connection",
-                    "value": "string",
-                    "resource": "EventHub",
-                    "required": true,
-                    "label": "$eventHubTrigger_connection_label",
-                    "help": "$eventHubTrigger_connection_help",
-                    "placeholder": "[variables('selectConnection')]"
-                }
-            ]
+          "name": "eventHubName",
+          "value": "string",
+          "defaultValue": "myeventhub",
+          "required": true,
+          "label": "$eventHubOut_path_label",
+          "help": "$eventHubTrigger_path_help",
+          "validators": [
+            {
+              "expression": "^[a-z0-9]$|^[a-z0-9][a-z0-9-_.]{0,48}[a-z0-9]$|^[{][a-zA-Z0-9]{1,126}[}]$|^[%][a-zA-Z0-9]{1,126}[%]$",
+              "errorText": "$eventHubTrigger_path_errorText"
+            }
+          ]
         },
         {
-            "type": "eventHub",
-            "displayName": "$eventHubOut_displayName",
-            "direction": "out",
-            "enabledInTryMode": false,
-            "actions": [
-                {
-                    "template": "EventHubTrigger",
-                    "binding": "eventHubTrigger",
-                    "settings": [
-                        "path",
-                        "connection"
-                    ]
-                }
-            ],
-            "documentation": "$content=Documentation\\eventHubOut.md",
-            "settings": [
-                {
-                    "name": "name",
-                    "value": "string",
-                    "defaultValue": "outputEventHubMessage",
-                    "required": true,
-                    "label": "$eventHubOut_name_label",
-                    "help": "$eventHubOut_name_help",
-                    "validators": [
-                        {
-                            "expression": "(^[a-zA-Z][a-zA-Z0-9]{0,127}$)|^\\$return$",
-                            "errorText": "[variables('parameterName')]"
-                        }
-                    ]
-                },
-                {
-                    "name": "path",
-                    "value": "string",
-                    "defaultValue": "outeventhub",
-                    "required": true,
-                    "label": "$eventHubOut_path_label",
-                    "help": "$eventHubOut_path_help",
-                    "validators": [
-                        {
-                            "expression": "^[a-z0-9]$|^[a-z0-9][a-z0-9-_.]{0,48}[a-z0-9]$|^[{][a-zA-Z0-9]{1,126}[}]$|^[%][a-zA-Z0-9]{1,126}[%]$",
-                            "errorText": "$eventHubOut_path_errorText"
-                        }
-                    ]
-                },
-                {
-                    "name": "connection",
-                    "value": "string",
-                    "resource": "EventHub",
-                    "required": true,
-                    "label": "$eventHubOut_connection_label",
-                    "help": "$eventHubOut_connection_help",
-                    "placeholder": "[variables('selectConnection')]"
-                }
-            ]
+          "name": "consumerGroup",
+          "value": "string",
+          "defaultValue": "$Default",
+          "required": false,
+          "label": "$eventHubTrigger_consumerGroup_label",
+          "help": "$eventHubTrigger_consumerGroup_help",
+          "validators": [
+            {
+              "expression": "(^[a-z0-9]$|^[a-z0-9][a-z0-9-_.]{0,48}[a-z0-9]$)|^\\$Default$|^[{][a-zA-Z0-9]{1,126}[}]$|^[%][a-zA-Z0-9]{1,126}[%]$",
+              "errorText": "$eventHubTrigger_consumerGroup_errorText"
+            }
+          ]
         },
         {
-            "type": "queue",
-            "displayName": "$queueOut_displayName",
-            "direction": "out",
-            "enabledInTryMode": true,
-            "actions": [
-                {
-                    "template": "QueueTrigger",
-                    "binding": "queueTrigger",
-                    "settings": [
-                        "queueName",
-                        "connection"
-                    ]
-                }
-            ],
-            "documentation": "$content=Documentation\\queueOut.md",
-            "settings": [
-                {
-                    "name": "name",
-                    "value": "string",
-                    "defaultValue": "outputQueueItem",
-                    "required": true,
-                    "label": "$queueOut_name_label",
-                    "help": "$queueOut_name_help",
-                    "validators": [
-                        {
-                            "expression": "(^[a-zA-Z][a-zA-Z0-9]{0,127}$)|^\\$return$",
-                            "errorText": "[variables('parameterName')]"
-                        }
-                    ]
-                },
-                {
-                    "name": "queueName",
-                    "value": "string",
-                    "defaultValue": "outqueue",
-                    "required": true,
-                    "label": "$queueOut_queueName_label",
-                    "help": "$queueOut_queueName_help",
-                    "validators": [
-                        {
-                            "expression": "^[0-9a-z][a-z0-9-]{1,61}[0-9a-z]$|^[{][a-zA-Z0-9]{1,126}[}]$|^[%][a-zA-Z0-9]{1,126}[%]$",
-                            "errorText": "$queueOut_queueName_errorText"
-                        }
-                    ]
-                },
-                {
-                    "name": "connection",
-                    "value": "string",
-                    "resource": "Storage",
-                    "required": true,
-                    "label": "[variables('storageConnStringLabel')]",
-                    "help": "[variables('appSettingsHelp')]",
-                    "placeholder": "[variables('selectConnection')]"
-                }
-            ]
+          "name": "connection",
+          "value": "string",
+          "resource": "EventHub",
+          "required": true,
+          "label": "$eventHubTrigger_connection_label",
+          "help": "$eventHubTrigger_connection_help",
+          "placeholder": "[variables('selectConnection')]"
+        }
+      ]
+    },
+    {
+      "type": "eventHub",
+      "displayName": "$eventHubOut_displayName",
+      "direction": "out",
+      "enabledInTryMode": false,
+      "actions": [
+        {
+          "template": "EventHubTrigger",
+          "binding": "eventHubTrigger",
+          "settings": [
+            "path",
+            "connection"
+          ]
+        }
+      ],
+      "documentation": "$content=Documentation\\eventHubOut.md",
+      "settings": [
+        {
+          "name": "name",
+          "value": "string",
+          "defaultValue": "outputEventHubMessage",
+          "required": true,
+          "label": "$eventHubOut_name_label",
+          "help": "$eventHubOut_name_help",
+          "validators": [
+            {
+              "expression": "(^[a-zA-Z][a-zA-Z0-9]{0,127}$)|^\\$return$",
+              "errorText": "[variables('parameterName')]"
+            }
+          ]
         },
         {
-            "type": "queueTrigger",
-            "displayName": "$queueTrigger_displayName",
-            "direction": "trigger",
-            "enabledInTryMode": true,
-            "documentation": "$content=Documentation\\queueTrigger.md",
-            "settings": [
-                {
-                    "name": "name",
-                    "value": "string",
-                    "defaultValue": "myQueueItem",
-                    "required": true,
-                    "label": "$queueTrigger_name_label",
-                    "help": "$queueTrigger_name_help",
-                    "validators": [
-                        {
-                            "expression": "^[a-zA-Z][a-zA-Z0-9]{0,127}$",
-                            "errorText": "[variables('parameterName')]"
-                        }
-                    ]
-                },
-                {
-                    "name": "queueName",
-                    "value": "string",
-                    "defaultValue": "myqueue",
-                    "required": true,
-                    "label": "$queueTrigger_queueName_label",
-                    "help": "$queueTrigger_queueName_help",
-                    "validators": [
-                        {
-                            "expression": "^[0-9a-z][a-z0-9-]{1,61}[0-9a-z]$|^[{][a-zA-Z0-9]{1,126}[}]$|^[%][a-zA-Z0-9]{1,126}[%]$",
-                            "errorText": "$queueTrigger_queueName_errorText"
-                        }
-                    ]
-                },
-                {
-                    "name": "connection",
-                    "value": "string",
-                    "resource": "Storage",
-                    "required": true,
-                    "label": "[variables('storageConnStringLabel')]",
-                    "help": "[variables('appSettingsHelp')]",
-                    "placeholder": "[variables('selectConnection')]"
-                }
-            ]
+          "name": "path",
+          "value": "string",
+          "defaultValue": "outeventhub",
+          "required": true,
+          "label": "$eventHubOut_path_label",
+          "help": "$eventHubOut_path_help",
+          "validators": [
+            {
+              "expression": "^[a-z0-9]$|^[a-z0-9][a-z0-9-_.]{0,48}[a-z0-9]$|^[{][a-zA-Z0-9]{1,126}[}]$|^[%][a-zA-Z0-9]{1,126}[%]$",
+              "errorText": "$eventHubOut_path_errorText"
+            }
+          ]
         },
         {
-            "type": "blob",
-            "displayName": "$blobOut_displayName",
-            "direction": "out",
-            "enabledInTryMode": true,
-            "actions": [
-                {
-                    "template": "BlobTrigger",
-                    "binding": "blobTrigger",
-                    "settings": [
-                        "path",
-                        "connection"
-                    ]
-                }
-            ],
-            "documentation": "$content=Documentation\\blobOut.md",
-            "settings": [
-                {
-                    "name": "name",
-                    "value": "string",
-                    "defaultValue": "outputBlob",
-                    "required": true,
-                    "label": "$blobOut_name_label",
-                    "help": "$blobOut_name_help",
-                    "validators": [
-                        {
-                            "expression": "(^[a-zA-Z][a-zA-Z0-9]{0,127}$)|^\\$return$",
-                            "errorText": "[variables('parameterName')]"
-                        }
-                    ]
-                },
-                {
-                    "name": "path",
-                    "value": "string",
-                    "defaultValue": "outcontainer/{rand-guid}",
-                    "required": true,
-                    "label": "$blobOut_path_label",
-                    "help": "$blobOut_path_help",
-                    "validators": [
-                        {
-                            "expression": "^[a-z0-9{](?:[a-z0-9{}]|(?:\\-(?!\\-))){1,61}[a-z0-9{}][\\/](\\S){0,1023}[^\\/]$|^[{][a-zA-Z0-9]{1,126}[}]$|^[%][a-zA-Z0-9]{1,126}[%]$",
-                            "errorText": "$blobOut_path_errorText"
-                        }
-                    ]
-                },
-                {
-                    "name": "connection",
-                    "value": "string",
-                    "resource": "Storage",
-                    "required": true,
-                    "label": "[variables('storageConnStringLabel')]",
-                    "help": "[variables('appSettingsHelp')]",
-                    "placeholder": "[variables('selectConnection')]"
-                }
-            ]
+          "name": "connection",
+          "value": "string",
+          "resource": "EventHub",
+          "required": true,
+          "label": "$eventHubOut_connection_label",
+          "help": "$eventHubOut_connection_help",
+          "placeholder": "[variables('selectConnection')]"
+        }
+      ]
+    },
+    {
+      "type": "queue",
+      "displayName": "$queueOut_displayName",
+      "direction": "out",
+      "enabledInTryMode": true,
+      "actions": [
+        {
+          "template": "QueueTrigger",
+          "binding": "queueTrigger",
+          "settings": [
+            "queueName",
+            "connection"
+          ]
+        }
+      ],
+      "documentation": "$content=Documentation\\queueOut.md",
+      "settings": [
+        {
+          "name": "name",
+          "value": "string",
+          "defaultValue": "outputQueueItem",
+          "required": true,
+          "label": "$queueOut_name_label",
+          "help": "$queueOut_name_help",
+          "validators": [
+            {
+              "expression": "(^[a-zA-Z][a-zA-Z0-9]{0,127}$)|^\\$return$",
+              "errorText": "[variables('parameterName')]"
+            }
+          ]
         },
         {
-            "type": "blob",
-            "displayName": "$blobIn_displayName",
-            "direction": "in",
-            "enabledInTryMode": true,
-            "documentation": "$content=Documentation\\blobIn.md",
-            "settings": [
-                {
-                    "name": "name",
-                    "value": "string",
-                    "defaultValue": "inputBlob",
-                    "required": true,
-                    "label": "$blobIn_name_label",
-                    "help": "$blobIn_name_help",
-                    "validators": [
-                        {
-                            "expression": "^[a-zA-Z][a-zA-Z0-9]{0,127}$",
-                            "errorText": "[variables('parameterName')]"
-                        }
-                    ]
-                },
-                {
-                    "name": "path",
-                    "value": "string",
-                    "defaultValue": "incontainer/{name}",
-                    "required": true,
-                    "label": "$blobIn_path_label",
-                    "help": "$blobIn_path_help",
-                    "validators": [
-                        {
-                            "expression": "^[a-z0-9{](?:[a-z0-9{}]|(?:\\-(?!\\-))){1,61}[a-z0-9{}][\\/](\\S){0,1023}[^\\/]$|^[{][a-zA-Z0-9]{1,126}[}]$|^[%][a-zA-Z0-9]{1,126}[%]$",
-                            "errorText": "$blobIn_patherrorText"
-                        }
-                    ]
-                },
-                {
-                    "name": "connection",
-                    "value": "string",
-                    "resource": "Storage",
-                    "required": true,
-                    "label": "[variables('storageConnStringLabel')]",
-                    "help": "[variables('appSettingsHelp')]",
-                    "placeholder": "[variables('selectConnection')]"
-                }
-            ]
+          "name": "queueName",
+          "value": "string",
+          "defaultValue": "outqueue",
+          "required": true,
+          "label": "$queueOut_queueName_label",
+          "help": "$queueOut_queueName_help",
+          "validators": [
+            {
+              "expression": "^[0-9a-z][a-z0-9-]{1,61}[0-9a-z]$|^[{][a-zA-Z0-9]{1,126}[}]$|^[%][a-zA-Z0-9]{1,126}[%]$",
+              "errorText": "$queueOut_queueName_errorText"
+            }
+          ]
         },
         {
-            "type": "blobTrigger",
-            "displayName": "$blobTrigger_displayName",
-            "direction": "trigger",
-            "enabledInTryMode": true,
-            "documentation": "$content=Documentation\\blobTrigger.md",
-            "settings": [
-                {
-                    "name": "name",
-                    "value": "string",
-                    "defaultValue": "myBlob",
-                    "required": true,
-                    "label": "$blobTrigger_name_label",
-                    "help": "$blobTrigger_name_help",
-                    "validators": [
-                        {
-                            "expression": "^[a-zA-Z][a-zA-Z0-9]{0,127}$",
-                            "errorText": "[variables('parameterName')]"
-                        }
-                    ]
-                },
-                {
-                    "name": "path",
-                    "value": "string",
-                    "defaultValue": "mycontainer",
-                    "required": true,
-                    "label": "$blobTrigger_path_label",
-                    "help": "$blobTrigger_path_help",
-                    "validators": [
-                        {
-                            "expression": "(^[a-z0-9{](?:[a-z0-9{}]|(?:\\-(?!\\-))){1,61}[a-z0-9{}]$)|(^[a-z0-9{](?:[a-z0-9{}]|(?:\\-(?!\\-))){1,61}[a-z0-9{}][\\/](\\S){0,1023}[^\\/]$)|^[{][a-zA-Z0-9]{1,126}[}]$|^[%][a-zA-Z0-9]{1,126}[%]$",
-                            "errorText": "$blobTrigger_path_errorText"
-                        }
-                    ]
-                },
-                {
-                    "name": "connection",
-                    "value": "string",
-                    "resource": "Storage",
-                    "required": true,
-                    "label": "[variables('storageConnStringLabel')]",
-                    "help": "[variables('appSettingsHelp')]",
-                    "placeholder": "[variables('selectConnection')]"
-                }
-            ]
+          "name": "connection",
+          "value": "string",
+          "resource": "Storage",
+          "required": true,
+          "label": "[variables('storageConnStringLabel')]",
+          "help": "[variables('appSettingsHelp')]",
+          "placeholder": "[variables('selectConnection')]"
+        }
+      ]
+    },
+    {
+      "type": "queueTrigger",
+      "displayName": "$queueTrigger_displayName",
+      "direction": "trigger",
+      "enabledInTryMode": true,
+      "documentation": "$content=Documentation\\queueTrigger.md",
+      "settings": [
+        {
+          "name": "name",
+          "value": "string",
+          "defaultValue": "myQueueItem",
+          "required": true,
+          "label": "$queueTrigger_name_label",
+          "help": "$queueTrigger_name_help",
+          "validators": [
+            {
+              "expression": "^[a-zA-Z][a-zA-Z0-9]{0,127}$",
+              "errorText": "[variables('parameterName')]"
+            }
+          ]
         },
         {
-            "type": "apiHubFile",
-            "displayName": "$apiHubFileIn_displayName",
-            "direction": "in",
-            "enabledInTryMode": false,
-            "documentation": "$content=Documentation\\apiHubFileIn.md",
-            "settings": [
-                {
-                    "name": "name",
-                    "value": "string",
-                    "defaultValue": "inputFile",
-                    "required": true,
-                    "label": "$apiHubFileIn_name_label",
-                    "help": "$apiHubFileIn_name_help",
-                    "validators": [
-                        {
-                            "expression": "^[a-zA-Z][a-zA-Z0-9]{0,127}$",
-                            "errorText": "[variables('parameterName')]"
-                        }
-                    ]
-                },
-                {
-                    "name": "path",
-                    "value": "string",
-                    "defaultValue": "path/{file}",
-                    "required": true,
-                    "label": "$apiHubFileIn_path_label",
-                    "help": "$apiHubFileIn_path_help",
-                    "validators": []
-                },
-                {
-                    "name": "connection",
-                    "value": "string",
-                    "resource": "ApiHub",
-                    "required": true,
-                    "label": "$apiHubFileIn_connection_label",
-                    "help": "$apiHubFileIn_connection_help",
-                    "metadata": {
-                        "capability": "blob"
-                    }
-                }
-            ]
+          "name": "queueName",
+          "value": "string",
+          "defaultValue": "myqueue",
+          "required": true,
+          "label": "$queueTrigger_queueName_label",
+          "help": "$queueTrigger_queueName_help",
+          "validators": [
+            {
+              "expression": "^[0-9a-z][a-z0-9-]{1,61}[0-9a-z]$|^[{][a-zA-Z0-9]{1,126}[}]$|^[%][a-zA-Z0-9]{1,126}[%]$",
+              "errorText": "$queueTrigger_queueName_errorText"
+            }
+          ]
         },
         {
-            "type": "apiHubFile",
-            "displayName": "$apiHubFileIn_displayName",
-            "direction": "out",
-            "enabledInTryMode": false,
-            "documentation": "$content=Documentation\\apiHubFileOut.md",
-            "settings": [
-                {
-                    "name": "name",
-                    "value": "string",
-                    "defaultValue": "outputFile",
-                    "required": true,
-                    "label": "$apiHubFileIn_name_label",
-                    "help": "$apiHubFileIn_name_help",
-                    "validators": [
-                        {
-                            "expression": "(^[a-zA-Z][a-zA-Z0-9]{0,127}$)|^\\$return$",
-                            "errorText": "[variables('parameterName')]"
-                        }
-                    ]
-                },
-                {
-                    "name": "path",
-                    "value": "string",
-                    "defaultValue": "path/{file}",
-                    "required": true,
-                    "label": "$apiHubFileIn_path_label",
-                    "help": "$apiHubFileIn_path_help",
-                    "validators": []
-                },
-                {
-                    "name": "connection",
-                    "value": "string",
-                    "resource": "ApiHub",
-                    "required": true,
-                    "label": "$apiHubFileIn_connection_label",
-                    "help": "$apiHubFileIn_connection_help",
-                    "metadata": {
-                        "capability": "blob"
-                    }
-                }
-            ]
+          "name": "connection",
+          "value": "string",
+          "resource": "Storage",
+          "required": true,
+          "label": "[variables('storageConnStringLabel')]",
+          "help": "[variables('appSettingsHelp')]",
+          "placeholder": "[variables('selectConnection')]"
+        }
+      ]
+    },
+    {
+      "type": "blob",
+      "displayName": "$blobOut_displayName",
+      "direction": "out",
+      "enabledInTryMode": true,
+      "actions": [
+        {
+          "template": "BlobTrigger",
+          "binding": "blobTrigger",
+          "settings": [
+            "path",
+            "connection"
+          ]
+        }
+      ],
+      "documentation": "$content=Documentation\\blobOut.md",
+      "settings": [
+        {
+          "name": "name",
+          "value": "string",
+          "defaultValue": "outputBlob",
+          "required": true,
+          "label": "$blobOut_name_label",
+          "help": "$blobOut_name_help",
+          "validators": [
+            {
+              "expression": "(^[a-zA-Z][a-zA-Z0-9]{0,127}$)|^\\$return$",
+              "errorText": "[variables('parameterName')]"
+            }
+          ]
         },
         {
-            "type": "apiHubFileTrigger",
-            "displayName": "$apiHubFileTrigger_displayName",
-            "direction": "trigger",
-            "enabledInTryMode": false,
-            "documentation": "$content=Documentation\\apiHubFileTrigger.md",
-            "settings": [
-                {
-                    "name": "name",
-                    "value": "string",
-                    "defaultValue": "inputFile",
-                    "required": true,
-                    "label": "$apiHubFileTrigger_name_label",
-                    "help": "$apiHubFileTrigger_name_help",
-                    "validators": [
-                        {
-                            "expression": "^[a-zA-Z][a-zA-Z0-9]{0,127}$",
-                            "errorText": "[variables('parameterName')]"
-                        }
-                    ]
-                },
-                {
-                    "name": "path",
-                    "value": "string",
-                    "defaultValue": "path/{file}",
-                    "required": true,
-                    "label": "$apiHubFileTrigger_path_label",
-                    "help": "$apiHubFileTrigger_path_help",
-                    "validators": []
-                },
-                {
-                    "name": "connection",
-                    "value": "string",
-                    "resource": "ApiHub",
-                    "required": true,
-                    "label": "$apiHubFileTrigger_connection_label",
-                    "help": "$apiHubFileTrigger_connection_help",
-                    "metadata": {
-                        "capability": "blob",
-                        "excluded": [
-                            "googledrive",
-                            "azureblob"
-                        ]
-                    }
-                }
-            ]
+          "name": "path",
+          "value": "string",
+          "defaultValue": "outcontainer/{rand-guid}",
+          "required": true,
+          "label": "$blobOut_path_label",
+          "help": "$blobOut_path_help",
+          "validators": [
+            {
+              "expression": "^[a-z0-9{](?:[a-z0-9{}]|(?:\\-(?!\\-))){1,61}[a-z0-9{}][\\/](\\S){0,1023}[^\\/]$|^[{][a-zA-Z0-9]{1,126}[}]$|^[%][a-zA-Z0-9]{1,126}[%]$",
+              "errorText": "$blobOut_path_errorText"
+            }
+          ]
         },
         {
-            "type": "apiHubTable",
-            "displayName": "$apiHubTableIn_displayName",
-            "direction": "in",
-            "enabledInTryMode": false,
-            "documentation": "$content=Documentation\\apiHubTable.md",
-            "settings": [
-                {
-                    "name": "name",
-                    "value": "string",
-                    "defaultValue": "inputTable",
-                    "required": true,
-                    "label": "[variables('paramNameLabel')]",
-                    "help": "[variables('paramNameInputHelp')]",
-                    "validators": [
-                        {
-                            "expression": "^[a-zA-Z][a-zA-Z0-9]{0,127}$",
-                            "errorText": "[variables('parameterName')]"
-                        }
-                    ]
-                },
-                {
-                    "name": "dataSetName",
-                    "value": "string",
-                    "defaultValue": "default",
-                    "required": false,
-                    "label": "[variables('apiHubTableDataSetLabel')]",
-                    "help": "[variables('apiHubTableDataSetHelp')]",
-                    "validators": []
-                },
-                {
-                    "name": "tableName",
-                    "value": "string",
-                    "defaultValue": null,
-                    "required": false,
-                    "label": "[variables('apiHubTableNameLabel')]",
-                    "help": "[variables('apiHubTableHelp')]",
-                    "validators": []
-                },
-                {
-                    "name": "entityId",
-                    "value": "string",
-                    "defaultValue": null,
-                    "required": false,
-                    "label": "[variables('apiHubTableEntityLabel')]",
-                    "help": "[variables('apiHubTableEntityHelp')]",
-                    "validators": []
-                },
-                {
-                    "name": "connection",
-                    "value": "string",
-                    "resource": "ApiHub",
-                    "required": true,
-                    "label": "[variables('apiHubTableConnectionLabel')]",
-                    "help": "[variables('apiHubTableConnectionHelp')]",
-                    "metadata": {
-                        "capability": "tabular"
-                    }
-                }
-            ]
+          "name": "connection",
+          "value": "string",
+          "resource": "Storage",
+          "required": true,
+          "label": "[variables('storageConnStringLabel')]",
+          "help": "[variables('appSettingsHelp')]",
+          "placeholder": "[variables('selectConnection')]"
+        }
+      ]
+    },
+    {
+      "type": "blob",
+      "displayName": "$blobIn_displayName",
+      "direction": "in",
+      "enabledInTryMode": true,
+      "documentation": "$content=Documentation\\blobIn.md",
+      "settings": [
+        {
+          "name": "name",
+          "value": "string",
+          "defaultValue": "inputBlob",
+          "required": true,
+          "label": "$blobIn_name_label",
+          "help": "$blobIn_name_help",
+          "validators": [
+            {
+              "expression": "^[a-zA-Z][a-zA-Z0-9]{0,127}$",
+              "errorText": "[variables('parameterName')]"
+            }
+          ]
         },
         {
-            "type": "apiHubTable",
-            "displayName": "$apiHubTableOut_displayName",
-            "direction": "out",
-            "enabledInTryMode": false,
-            "documentation": "$content=Documentation\\apiHubTableOut.md",
-            "settings": [
-                {
-                    "name": "name",
-                    "value": "string",
-                    "defaultValue": "outputTable",
-                    "required": true,
-                    "label": "[variables('paramNameLabel')]",
-                    "help": "[variables('paramNameOutputHelp')]",
-                    "validators": [
-                        {
-                            "expression": "(^[a-zA-Z][a-zA-Z0-9]{0,127}$)|^\\$return$",
-                            "errorText": "[variables('parameterName')]"
-                        }
-                    ]
-                },
-                {
-                    "name": "dataSetName",
-                    "value": "string",
-                    "defaultValue": "default",
-                    "required": false,
-                    "label": "[variables('apiHubTableDataSetLabel')]",
-                    "help": "[variables('apiHubTableDataSetHelp')]",
-                    "validators": []
-                },
-                {
-                    "name": "tableName",
-                    "value": "string",
-                    "defaultValue": null,
-                    "required": false,
-                    "label": "[variables('apiHubTableNameLabel')]",
-                    "help": "[variables('apiHubTableHelp')]",
-                    "validators": []
-                },
-                {
-                    "name": "entityId",
-                    "value": "string",
-                    "defaultValue": null,
-                    "required": false,
-                    "label": "[variables('apiHubTableEntityLabel')]",
-                    "help": "[variables('apiHubTableEntityHelp')]",
-                    "validators": []
-                },
-                {
-                    "name": "connection",
-                    "value": "string",
-                    "resource": "ApiHub",
-                    "required": true,
-                    "label": "[variables('apiHubTableConnectionLabel')]",
-                    "help": "[variables('apiHubTableConnectionHelp')]",
-                    "metadata": {
-                        "capability": "tabular"
-                    }
-                }
-            ]
+          "name": "path",
+          "value": "string",
+          "defaultValue": "incontainer/{name}",
+          "required": true,
+          "label": "$blobIn_path_label",
+          "help": "$blobIn_path_help",
+          "validators": [
+            {
+              "expression": "^[a-z0-9{](?:[a-z0-9{}]|(?:\\-(?!\\-))){1,61}[a-z0-9{}][\\/](\\S){0,1023}[^\\/]$|^[{][a-zA-Z0-9]{1,126}[}]$|^[%][a-zA-Z0-9]{1,126}[%]$",
+              "errorText": "$blobIn_patherrorText"
+            }
+          ]
         },
         {
-            "type": "httpTrigger",
-            "displayName": "$httpTrigger_displayName",
-            "direction": "trigger",
-            "enabledInTryMode": true,
-            "documentation": "$content=Documentation\\httpTrigger.md",
-            "settings": [
-                {
-                    "name": "name",
-                    "value": "string",
-                    "defaultValue": "req",
-                    "required": true,
-                    "label": "$httpTrigger_name_label",
-                    "help": "$httpTrigger_name_help",
-                    "validators": [
-                        {
-                            "expression": "^[a-zA-Z][a-zA-Z0-9]{0,127}$",
-                            "errorText": "[variables('parameterName')]"
-                        }
-                    ]
-                },
-                {
-                    "name": "route",
-                    "value": "string",
-                    "required": false,
-                    "label": "$httpTrigger_route_label",
-                    "help": "$httpTrigger_route_help",
-                    "validators": []
-                },
-                {
-                    "name": "webHookType",
-                    "value": "enum",
-                    "enum": [
-                        {
-                            "value": "github",
-                            "display": "GitHub"
-                        },
-                        {
-                            "value": "genericJson",
-                            "display": "Generic JSON"
-                        },
-                        {
-                            "value":"slack",
-                            "display":"Slack"
-                        }
-                    ],
-                    "label": "$httpTrigger_webHookType_label",
-                    "help": "$httpTrigger_webHookType_help"
-                },
-                {
-                    "name": "authLevel",
-                    "value": "enum",
-                    "enum": [
-                        {
-                            "value": "function",
-                            "display": "Function"
-                        },
-                        {
-                            "value": "anonymous",
-                            "display": "Anonymous"
-                        },
-                        {
-                            "value": "admin",
-                            "display": "Admin"
-                        }
-                    ],
-                    "label": "$httpTrigger_authLevel_label",
-                    "help": "$httpTrigger_authLevel_help"
-                },
-                {
-                    "name": "methods",
-                    "value": "checkBoxList",
-                    "defaultValue": [
-                        "get",
-                        "post",
-                        "delete",
-                        "head",
-                        "patch",
-                        "put",
-                        "options",
-                        "trace"
-                    ],
-                    "enum": [
-                        {
-                            "value": "get",
-                            "display": "GET"
-                        },
-                        {
-                            "value": "post",
-                            "display": "POST"
-                        },
-                        {
-                            "value": "delete",
-                            "display": "DELETE"
-                        },
-                        {
-                            "value": "head",
-                            "display": "HEAD"
-                        },
-                        {
-                            "value": "patch",
-                            "display": "PATCH"
-                        },
-                        {
-                            "value": "put",
-                            "display": "PUT"
-                        },
-                        {
-                            "value": "options",
-                            "display": "OPTIONS"
-                        },
-                        {
-                            "value": "trace",
-                            "display": "TRACE"
-                        }
-                    ],
-                    "label": "$httpTrigger_methods_label",
-                    "help": "$httpTrigger_methods_help"
-                }
-            ],
-            "rules": [
-                {
-                    "name": "mode",
-                    "type": "exclusivity",
-                    "values": [
-                        {
-                            "value": "authLevel",
-                            "display": "Standard",
-                            "hiddenSettings": [
-                                "webHookType"
-                            ],
-                            "shownSettings": [
-                                "authLevel"
-                            ]
-                        },
-                        {
-                            "value": "webHookType",
-                            "display": "Webhook",
-                            "hiddenSettings": [
-                                "authLevel"
-                            ],
-                            "shownSettings": [
-                                "webHookType"
-                            ]
-                        }
-                    ],
-                    "label": "$httpTrigger_mode_label",
-                    "help": "$httpTrigger_mode_help"
-                },
-                {
-                    "name": "methodRule",
-                    "type": "exclusivity",
-                    "values": [
-                        {
-                            "value": "allMethods",
-                            "display": "All methods",
-                            "hiddenSettings": [
-                                "methods"
-                            ],
-                            "shownSettings": []
-                        },
-                        {
-                            "value": "methods",
-                            "display": "Selected methods",
-                            "hiddenSettings": [],
-                            "shownSettings": [
-                                "methods"
-                            ]
-                        }
-                    ],
-                    "label": "$httpTrigger_methodRule_label",
-                    "help": "$httpTrigger_methodRule_help"
-                }
-            ]
+          "name": "connection",
+          "value": "string",
+          "resource": "Storage",
+          "required": true,
+          "label": "[variables('storageConnStringLabel')]",
+          "help": "[variables('appSettingsHelp')]",
+          "placeholder": "[variables('selectConnection')]"
+        }
+      ]
+    },
+    {
+      "type": "blobTrigger",
+      "displayName": "$blobTrigger_displayName",
+      "direction": "trigger",
+      "enabledInTryMode": true,
+      "documentation": "$content=Documentation\\blobTrigger.md",
+      "settings": [
+        {
+          "name": "name",
+          "value": "string",
+          "defaultValue": "myBlob",
+          "required": true,
+          "label": "$blobTrigger_name_label",
+          "help": "$blobTrigger_name_help",
+          "validators": [
+            {
+              "expression": "^[a-zA-Z][a-zA-Z0-9]{0,127}$",
+              "errorText": "[variables('parameterName')]"
+            }
+          ]
         },
         {
-            "type": "http",
-            "displayName": "$httpOut_displayName",
-            "direction": "out",
-            "enabledInTryMode": true,
-            "documentation": "$content=Documentation\\httpOut.md",
-            "settings": [
-                {
-                    "name": "name",
-                    "value": "string",
-                    "defaultValue": "res",
-                    "required": true,
-                    "label": "$httpOut_name_label",
-                    "help": "$httpOut_name_help",
-                    "validators": [
-                        {
-                            "expression": "(^[a-zA-Z][a-zA-Z0-9]{0,127}$)|^\\$return$",
-                            "errorText": "[variables('parameterName')]"
-                        }
-                    ]
-                }
-            ]
+          "name": "path",
+          "value": "string",
+          "defaultValue": "mycontainer",
+          "required": true,
+          "label": "$blobTrigger_path_label",
+          "help": "$blobTrigger_path_help",
+          "validators": [
+            {
+              "expression": "(^[a-z0-9{](?:[a-z0-9{}]|(?:\\-(?!\\-))){1,61}[a-z0-9{}]$)|(^[a-z0-9{](?:[a-z0-9{}]|(?:\\-(?!\\-))){1,61}[a-z0-9{}][\\/](\\S){0,1023}[^\\/]$)|^[{][a-zA-Z0-9]{1,126}[}]$|^[%][a-zA-Z0-9]{1,126}[%]$",
+              "errorText": "$blobTrigger_path_errorText"
+            }
+          ]
         },
         {
-            "type": "serviceBusTrigger",
-            "displayName": "$serviceBusTrigger_displayName",
-            "direction": "trigger",
-            "enabledInTryMode": false,
-            "documentation": "$content=Documentation\\serviceBusTrigger.md",
-            "settings": [
-                {
-                    "name": "name",
-                    "value": "string",
-                    "defaultValue": "mySbMsg",
-                    "required": true,
-                    "label": "$serviceBusTrigger_name_label",
-                    "help": "$serviceBusTrigger_name_help",
-                    "validators": [
-                        {
-                            "expression": "^[a-zA-Z][a-zA-Z0-9]{0,127}$",
-                            "errorText": "[variables('parameterName')]"
-                        }
-                    ]
-                },
-                {
-                    "name": "queueName",
-                    "value": "string",
-                    "defaultValue": "mysbqueue",
-                    "required": false,
-                    "label": "$serviceBusTrigger_queueName_label",
-                    "help": "$serviceBusTrigger_queueName_help",
-                    "validators": [
-                        {
-                            "expression": "^[0-9a-z][a-z0-9_.-]{1,48}[0-9a-z]$|^[{][a-zA-Z0-9]{1,126}[}]$|^[%][a-zA-Z0-9]{1,126}[%]$",
-                            "errorText": "$serviceBusTrigger_queueName_errorText"
-                        }
-                    ]
-                },
-                {
-                    "name": "topicName",
-                    "value": "string",
-                    "defaultValue": "mysbtopic",
-                    "required": false,
-                    "label": "$serviceBusTrigger_topicName_label",
-                    "help": "$serviceBusTrigger_topicName_help",
-                    "validators": [
-                        {
-                            "expression": "^[0-9a-z][a-z0-9_.-]{1,48}[0-9a-z]$|^[{][a-zA-Z0-9]{1,126}[}]$|^[%][a-zA-Z0-9]{1,126}[%]$",
-                            "errorText": "$serviceBusTrigger_topicName_errorText"
-                        }
-                    ]
-                },
-                {
-                    "name": "subscriptionName",
-                    "value": "string",
-                    "defaultValue": "mysubscription",
-                    "required": false,
-                    "label": "$serviceBusTrigger_subscriptionName_label",
-                    "help": "$serviceBusTrigger_subscriptionName_help",
-                    "validators": [
-                        {
-                            "expression": "^[0-9a-zA-Z][a-zA-Z0-9_.-]{1,48}[0-9a-zA-Z]$|^[{][a-zA-Z0-9]{1,126}[}]$|^[%][a-zA-Z0-9]{1,126}[%]$",
-                            "errorText": "$serviceBusTrigger_subscriptionName_errorText"
-                        }
-                    ]
-                },
-                {
-                    "name": "connection",
-                    "value": "string",
-                    "resource": "EventHub",
-                    "required": true,
-                    "label": "$serviceBusTrigger_connection_label",
-                    "help": "$serviceBusTrigger_connection_help",
-                    "placeholder": "[variables('selectConnection')]"
-                },
-                {
-                    "name": "accessRights",
-                    "value": "enum",
-                    "enum": [
-                        {
-                            "value": "Manage",
-                            "display": "Manage"
-                        },
-                        {
-                            "value": "Listen",
-                            "display": "Listen"
-                        }
-                    ],
-                    "label": "$serviceBusTrigger_accessRights_label",
-                    "help": "$serviceBusTrigger_accessRights_help"
-                }
-            ],
-            "rules": [
-                {
-                    "name": "messageType",
-                    "type": "exclusivity",
-                    "values": [
-                        {
-                            "value": "queueName",
-                            "display": "$serviceBusTrigger_messageType_queueName",
-                            "hiddenSettings": [
-                                "topicName",
-                                "subscriptionName"
-                            ],
-                            "shownSettings": [
-                                "queueName"
-                            ]
-                        },
-                        {
-                            "value": "topicName",
-                            "display": "$serviceBusTrigger_messageType_topicName",
-                            "hiddenSettings": [
-                                "queueName"
-                            ],
-                            "shownSettings": [
-                                "topicName",
-                                "subscriptionName"
-                            ]
-                        }
-                    ],
-                    "label": "$serviceBusTrigger_messageType_label",
-                    "help": "$serviceBusTrigger_messageType_help"
-                }
-            ]
+          "name": "connection",
+          "value": "string",
+          "resource": "Storage",
+          "required": true,
+          "label": "[variables('storageConnStringLabel')]",
+          "help": "[variables('appSettingsHelp')]",
+          "placeholder": "[variables('selectConnection')]"
+        }
+      ]
+    },
+    {
+      "type": "apiHubFile",
+      "displayName": "$apiHubFileIn_displayName",
+      "direction": "in",
+      "enabledInTryMode": false,
+      "documentation": "$content=Documentation\\apiHubFileIn.md",
+      "settings": [
+        {
+          "name": "name",
+          "value": "string",
+          "defaultValue": "inputFile",
+          "required": true,
+          "label": "$apiHubFileIn_name_label",
+          "help": "$apiHubFileIn_name_help",
+          "validators": [
+            {
+              "expression": "^[a-zA-Z][a-zA-Z0-9]{0,127}$",
+              "errorText": "[variables('parameterName')]"
+            }
+          ]
         },
         {
-            "type": "serviceBus",
-            "displayName": "$serviceBusOut_displayName",
-            "direction": "out",
-            "enabledInTryMode": false,
-            "documentation": "$content=Documentation\\serviceBusOut.md",
-            "settings": [
-                {
-                    "name": "name",
-                    "value": "string",
-                    "defaultValue": "outputSbMsg",
-                    "required": true,
-                    "label": "$serviceBusOut_name_label",
-                    "help": "$serviceBusOut_name_help",
-                    "validators": [
-                        {
-                            "expression": "(^[a-zA-Z][a-zA-Z0-9]{0,127}$)|^\\$return$",
-                            "errorText": "[variables('parameterName')]"
-                        }
-                    ]
-                },
-                {
-                    "name": "queueName",
-                    "value": "string",
-                    "defaultValue": "outqueue",
-                    "required": true,
-                    "label": "$serviceBusOut_queueName_label",
-                    "help": "$serviceBusOut_queueName_help",
-                    "validators": [
-                        {
-                            "expression": "^[0-9a-z][a-z0-9_.-]{1,48}[0-9a-z]$|^[{][a-zA-Z0-9]{1,126}[}]$|^[%][a-zA-Z0-9]{1,126}[%]$",
-                            "errorText": "$serviceBusOut_queueName_errorText"
-                        }
-                    ]
-                },
-                {
-                    "name": "topicName",
-                    "value": "string",
-                    "defaultValue": "outtopic",
-                    "required": true,
-                    "label": "$serviceBusOut_topicName_label",
-                    "help": "$serviceBusOut_topicName_help",
-                    "validators": [
-                        {
-                            "expression": "^[0-9a-z][a-z0-9_.-]{1,48}[0-9a-z]$|^[{][a-zA-Z0-9]{1,126}[}]$|^[%][a-zA-Z0-9]{1,126}[%]$",
-                            "errorText": "$serviceBusOut_topicName_errorText"
-                        }
-                    ]
-                },
-                {
-                    "name": "connection",
-                    "value": "string",
-                    "resource": "EventHub",
-                    "required": true,
-                    "label": "$serviceBusOut_connection_label",
-                    "help": "$serviceBusOut_connection_help",
-                    "placeholder": "[variables('selectConnection')]"
-                },
-                {
-                    "name": "accessRights_",
-                    "value": "enum",
-                    "enum": [
-                        {
-                            "value": "Manage",
-                            "display": "Manage"
-                        },
-                        {
-                            "value": "Send",
-                            "display": "Send"
-                        }
-                    ],
-                    "label": "$serviceBusOut_accessRights_label",
-                    "help": "$serviceBusOut_accessRights_help"
-                }
-            ],
-            "rules": [
-                {
-                    "name": "messageType",
-                    "type": "exclusivity",
-                    "values": [
-                        {
-                            "value": "queueName",
-                            "display": "$serviceBusOut_messageType_queueName",
-                            "hiddenSettings": [
-                                "topicName"
-                            ],
-                            "shownSettings": [
-                                "queueName"
-                            ]
-                        },
-                        {
-                            "value": "topicName",
-                            "display": "$serviceBusOut_messageType_topicName",
-                            "hiddenSettings": [
-                                "queueName"
-                            ],
-                            "shownSettings": [
-                                "topicName"
-                            ]
-                        }
-                    ],
-                    "label": "$serviceBusOut_messageType_label",
-                    "help": "$serviceBusOut_messageType_help"
-                }
-            ]
+          "name": "path",
+          "value": "string",
+          "defaultValue": "path/{file}",
+          "required": true,
+          "label": "$apiHubFileIn_path_label",
+          "help": "$apiHubFileIn_path_help",
+          "validators": []
         },
         {
-            "type": "manualTrigger",
-            "displayName": "Manual",
-            "direction": "trigger",
-            "enabledInTryMode": true,
-            "documentation": "$content=Documentation\\manualTrigger.md",
-            "settings": [
-                {
-                    "name": "name",
-                    "value": "string",
-                    "defaultValue": "input",
-                    "required": true,
-                    "label": "$manualTrigger_name_label",
-                    "help": "$manualTrigger_name_help",
-                    "validators": [
-                        {
-                            "expression": "^[a-zA-Z][a-zA-Z0-9]{0,127}$",
-                            "errorText": "[variables('parameterName')]"
-                        }
-                    ]
-                }
-            ]
+          "name": "connection",
+          "value": "string",
+          "resource": "ApiHub",
+          "required": true,
+          "label": "$apiHubFileIn_connection_label",
+          "help": "$apiHubFileIn_connection_help",
+          "metadata": {
+            "capability": "blob"
+          }
+        }
+      ]
+    },
+    {
+      "type": "apiHubFile",
+      "displayName": "$apiHubFileIn_displayName",
+      "direction": "out",
+      "enabledInTryMode": false,
+      "documentation": "$content=Documentation\\apiHubFileOut.md",
+      "settings": [
+        {
+          "name": "name",
+          "value": "string",
+          "defaultValue": "outputFile",
+          "required": true,
+          "label": "$apiHubFileIn_name_label",
+          "help": "$apiHubFileIn_name_help",
+          "validators": [
+            {
+              "expression": "(^[a-zA-Z][a-zA-Z0-9]{0,127}$)|^\\$return$",
+              "errorText": "[variables('parameterName')]"
+            }
+          ]
         },
         {
-            "type": "table",
-            "displayName": "$tableout_displayName",
-            "direction": "out",
-            "enabledInTryMode": true,
-            "documentation": "$content=Documentation\\tableOut.md",
-            "settings": [
-                {
-                    "name": "name",
-                    "value": "string",
-                    "defaultValue": "outputTable",
-                    "required": true,
-                    "label": "$tableout_name_label",
-                    "help": "$tableout_name_help",
-                    "validators": [
-                        {
-                            "expression": "(^[a-zA-Z][a-zA-Z0-9]{0,127}$)|^\\$return$",
-                            "errorText": "[variables('parameterName')]"
-                        }
-                    ]
-                },
-                {
-                    "name": "tableName",
-                    "value": "string",
-                    "defaultValue": "outTable",
-                    "required": true,
-                    "label": "$table_tableName_label",
-                    "help": "$table_tableName_help",
-                    "validators": [
-                        {
-                            "expression": "^[A-Za-z][A-Za-z0-9]{2,62}$|^[{][a-zA-Z0-9]{1,126}[}]$|^[%][a-zA-Z0-9]{1,126}[%]$",
-                            "errorText": "$table_tableName_errorText"
-                        }
-                    ]
-                },
-                {
-                    "name": "connection",
-                    "value": "string",
-                    "resource": "Storage",
-                    "required": true,
-                    "label": "[variables('storageConnStringLabel')]",
-                    "help": "[variables('appSettingsHelp')]",
-                    "placeholder": "[variables('selectConnection')]"
-                }
-            ]
+          "name": "path",
+          "value": "string",
+          "defaultValue": "path/{file}",
+          "required": true,
+          "label": "$apiHubFileIn_path_label",
+          "help": "$apiHubFileIn_path_help",
+          "validators": []
         },
         {
-            "type": "table",
-            "displayName": "$tableIn_displayName",
-            "direction": "in",
-            "enabledInTryMode": true,
-            "documentation": "$content=Documentation\\tableIn.md",
-            "settings": [
-                {
-                    "name": "name",
-                    "value": "string",
-                    "defaultValue": "inputTable",
-                    "required": true,
-                    "label": "$tableIn_name_label",
-                    "help": "$tableIn_name_help",
-                    "validators": [
-                        {
-                            "expression": "^[a-zA-Z][a-zA-Z0-9]{0,127}$",
-                            "errorText": "[variables('parameterName')]"
-                        }
-                    ]
-                },
-                {
-                    "name": "tableName",
-                    "value": "string",
-                    "defaultValue": "inTable",
-                    "required": true,
-                    "label": "$tableIn_tableName_label",
-                    "help": "$tableIn_tableName_help",
-                    "validators": [
-                        {
-                            "expression": "^[A-Za-z][A-Za-z0-9]{2,62}$|^[{][a-zA-Z0-9]{1,126}[}]$|^[%][a-zA-Z0-9]{1,126}[%]$",
-                            "errorText": "$tableIn_tableName_errorText"
-                        }
-                    ]
-                },
-                {
-                    "name": "partitionKey",
-                    "value": "string",
-                    "required": false,
-                    "label": "$tableIn_partitionKey_label",
-                    "help": "$tableIn_partitionKey_help"
-                },
-                {
-                    "name": "rowKey",
-                    "value": "string",
-                    "required": false,
-                    "label": "$tableIn_rowKey_label",
-                    "help": "$tableIn_rowKey_help"
-                },
-                {
-                    "name": "take",
-                    "value": "int",
-                    "defaultValue": 50,
-                    "required": false,
-                    "label": "$tableIn_take_label",
-                    "help": "$tableIn_take_help"
-                },
-                {
-                    "name": "filter",
-                    "value": "string",
-                    "required": false,
-                    "label": "$tableIn_filter_label",
-                    "help": "$tableIn_filter_help"
-                },
-                {
-                    "name": "connection",
-                    "value": "string",
-                    "resource": "Storage",
-                    "required": true,
-                    "label": "[variables('storageConnStringLabel')]",
-                    "help": "[variables('appSettingsHelp')]",
-                    "placeholder": "[variables('selectConnection')]"
-                }
-            ]
+          "name": "connection",
+          "value": "string",
+          "resource": "ApiHub",
+          "required": true,
+          "label": "$apiHubFileIn_connection_label",
+          "help": "$apiHubFileIn_connection_help",
+          "metadata": {
+            "capability": "blob"
+          }
+        }
+      ]
+    },
+    {
+      "type": "apiHubFileTrigger",
+      "displayName": "$apiHubFileTrigger_displayName",
+      "direction": "trigger",
+      "enabledInTryMode": false,
+      "documentation": "$content=Documentation\\apiHubFileTrigger.md",
+      "settings": [
+        {
+          "name": "name",
+          "value": "string",
+          "defaultValue": "inputFile",
+          "required": true,
+          "label": "$apiHubFileTrigger_name_label",
+          "help": "$apiHubFileTrigger_name_help",
+          "validators": [
+            {
+              "expression": "^[a-zA-Z][a-zA-Z0-9]{0,127}$",
+              "errorText": "[variables('parameterName')]"
+            }
+          ]
         },
         {
-            "type": "documentDB",
-            "displayName": "$documentDB_displayName",
-            "direction": "out",
-            "enabledInTryMode": false,
-            "documentation": "$content=Documentation\\documentDBOut.md",
-            "settings": [
-                {
-                    "name": "name",
-                    "value": "string",
-                    "defaultValue": "outputDocument",
-                    "required": true,
-                    "label": "$documentDBOut_name_label",
-                    "help": "$documentDBOut_name_help",
-                    "validators": [
-                        {
-                            "expression": "(^[a-zA-Z][a-zA-Z0-9]{0,127}$)|^\\$return$",
-                            "errorText": "[variables('parameterName')]"
-                        }
-                    ]
-                },
-                {
-                    "name": "databaseName",
-                    "value": "string",
-                    "defaultValue": "outDatabase",
-                    "required": true,
-                    "label": "$documentDBOut_databaseName_label",
-                    "help": "$documentDBOut_databaseName_help"
-                },
-                {
-                    "name": "collectionName",
-                    "value": "string",
-                    "defaultValue": "MyCollection",
-                    "required": true,
-                    "label": "$documentDBOut_collectionName_label",
-                    "help": "$documentDBOut_collectionName_help"
-                },
-                {
-                    "name": "createIfNotExists",
-                    "value": "boolean",
-                    "defaultValue": false,
-                    "required": true,
-                    "label": "$documentDBOut_createIfNotExists_label",
-                    "help": "$documentDBOut_createIfNotExists_help"
-                },
-                {
-                    "name": "connection",
-                    "value": "string",
-                    "resource": "DocumentDB",
-                    "required": true,
-                    "label": "$documentDBOut_connection_label",
-                    "help": "$documentDBOut_connection_help",
-                    "placeholder": "[variables('selectConnection')]"
-                }
-            ]
+          "name": "path",
+          "value": "string",
+          "defaultValue": "path/{file}",
+          "required": true,
+          "label": "$apiHubFileTrigger_path_label",
+          "help": "$apiHubFileTrigger_path_help",
+          "validators": []
         },
         {
-            "type": "documentDB",
-            "displayName": "$documentDBIn_displayName",
-            "direction": "in",
-            "enabledInTryMode": false,
-            "documentation": "$content=Documentation\\documentDBIn.md",
-            "settings": [
-                {
-                    "name": "name",
-                    "value": "string",
-                    "defaultValue": "inputDocument",
-                    "required": true,
-                    "label": "$documentDBIn_name_label",
-                    "help": "$documentDBIn_name_help",
-                    "validators": [
-                        {
-                            "expression": "^[a-zA-Z][a-zA-Z0-9]{0,127}$",
-                            "errorText": "[variables('parameterName')]"
-                        }
-                    ]
-                },
-                {
-                    "name": "databaseName",
-                    "value": "string",
-                    "defaultValue": "inDatabase",
-                    "required": true,
-                    "label": "$documentDBIn_databaseName_label",
-                    "help": "$documentDBIn_databaseName_help"
-                },
-                {
-                    "name": "collectionName",
-                    "value": "string",
-                    "defaultValue": "MyCollection",
-                    "required": true,
-                    "label": "$documentDBIn_collectionName_label",
-                    "help": "$documentDBIn_collectionName_help"
-                },
-                {
-                    "name": "id",
-                    "value": "string",
-                    "defaultValue": "{documentId}",
-                    "required": true,
-                    "label": "$documentDBIn_id_label",
-                    "help": "$documentDBIn_id_help"
-                },
-                {
-                    "name": "connection",
-                    "value": "string",
-                    "resource": "DocumentDB",
-                    "required": true,
-                    "label": "$documentDBIn_connection_label",
-                    "help": "$documentDBIn_connection_help",
-                    "placeholder": "[variables('selectConnection')]"
-                }
+          "name": "connection",
+          "value": "string",
+          "resource": "ApiHub",
+          "required": true,
+          "label": "$apiHubFileTrigger_connection_label",
+          "help": "$apiHubFileTrigger_connection_help",
+          "metadata": {
+            "capability": "blob",
+            "excluded": [
+              "googledrive",
+              "azureblob"
             ]
+          }
+        }
+      ]
+    },
+    {
+      "type": "apiHubTable",
+      "displayName": "$apiHubTableIn_displayName",
+      "direction": "in",
+      "enabledInTryMode": false,
+      "documentation": "$content=Documentation\\apiHubTable.md",
+      "settings": [
+        {
+          "name": "name",
+          "value": "string",
+          "defaultValue": "inputTable",
+          "required": true,
+          "label": "[variables('paramNameLabel')]",
+          "help": "[variables('paramNameInputHelp')]",
+          "validators": [
+            {
+              "expression": "^[a-zA-Z][a-zA-Z0-9]{0,127}$",
+              "errorText": "[variables('parameterName')]"
+            }
+          ]
         },
         {
-            "type": "mobileTable",
-            "displayName": "$mobileTableOut_displayName",
-            "direction": "out",
-            "enabledInTryMode": false,
-            "documentation": "$content=Documentation\\mobileTableOut.md",
-            "settings": [
-                {
-                    "name": "name",
-                    "value": "string",
-                    "defaultValue": "outputRecord",
-                    "required": true,
-                    "label": "$mobileTableOut_name_label",
-                    "help": "$mobileTableOut_name_help",
-                    "validators": [
-                        {
-                            "expression": "(^[a-zA-Z][a-zA-Z0-9]{0,127}$)|^\\$return$",
-                            "errorText": "[variables('parameterName')]"
-                        }
-                    ]
-                },
-                {
-                    "name": "tableName",
-                    "value": "string",
-                    "defaultValue": "outTable",
-                    "required": true,
-                    "label": "$mobileTableOut_tableName_label",
-                    "help": "$mobileTableOut_tableName_help"
-                },
-                {
-                    "name": "connection",
-                    "value": "string",
-                    "defaultValue": "My_MobileApp_Uri",
-                    "required": true,
-                    "label": "$mobileTableOut_connection_label",
-                    "help": "$mobileTableOut_connection_help"
-                },
-                {
-                    "name": "apiKey",
-                    "value": "string",
-                    "required": false,
-                    "label": "$mobileTableOut_apiKey_label",
-                    "help": "$mobileTableOut_apiKey_help"
-                }
-            ]
+          "name": "dataSetName",
+          "value": "string",
+          "defaultValue": "default",
+          "required": false,
+          "label": "[variables('apiHubTableDataSetLabel')]",
+          "help": "[variables('apiHubTableDataSetHelp')]",
+          "validators": []
         },
         {
-            "type": "mobileTable",
-            "displayName": "$mobileTableIn_displayName",
-            "direction": "in",
-            "enabledInTryMode": false,
-            "documentation": "$content=Documentation\\mobileTableIn.md",
-            "settings": [
-                {
-                    "name": "name",
-                    "value": "string",
-                    "defaultValue": "inputRecord",
-                    "required": true,
-                    "label": "$mobileTableIn_name_label",
-                    "help": "$mobileTableIn_name_help",
-                    "validators": [
-                        {
-                            "expression": "^[a-zA-Z][a-zA-Z0-9]{0,127}$",
-                            "errorText": "[variables('parameterName')]"
-                        }
-                    ]
-                },
-                {
-                    "name": "tableName",
-                    "value": "string",
-                    "defaultValue": "inTable",
-                    "required": true,
-                    "label": "$mobileTableIn_tableName_label",
-                    "help": "$mobileTableIn_tableName_help"
-                },
-                {
-                    "name": "id",
-                    "value": "string",
-                    "defaultValue": "{itemId}",
-                    "required": true,
-                    "label": "$mobileTableIn_id_label",
-                    "help": "$mobileTableIn_id_help"
-                },
-                {
-                    "name": "connection",
-                    "value": "string",
-                    "defaultValue": "My_MobileApp_Uri",
-                    "required": true,
-                    "label": "$mobileTableIn_connection_label",
-                    "help": "$mobileTableIn_connection_help"
-                },
-                {
-                    "name": "apiKey",
-                    "value": "string",
-                    "required": false,
-                    "label": "$mobileTableIn_apiKey_label",
-                    "help": "$mobileTableIn_apiKey_help"
-                }
-            ]
+          "name": "tableName",
+          "value": "string",
+          "defaultValue": null,
+          "required": false,
+          "label": "[variables('apiHubTableNameLabel')]",
+          "help": "[variables('apiHubTableHelp')]",
+          "validators": []
         },
         {
-            "type": "notificationHub",
-            "displayName": "$notificationHubOut_displayName",
-            "direction": "out",
-            "enabledInTryMode": false,
-            "documentation": "$content=Documentation\\notificationHubOut.md",
-            "settings": [
-                {
-                    "name": "name",
-                    "value": "string",
-                    "defaultValue": "notification",
-                    "required": true,
-                    "label": "$notificationHubOut_name_label",
-                    "help": "$notificationHubOut_name_help",
-                    "validators": [
-                        {
-                            "expression": "(^[a-zA-Z][a-zA-Z0-9]{0,127}$)|^\\$return$",
-                            "errorText": "[variables('parameterName')]"
-                        }
-                    ]
-                },
-                {
-                    "name": "hubName",
-                    "value": "string",
-                    "required": true,
-                    "label": "$notificationHubOut_hubName_label",
-                    "help": "$notificationHubOut_hubName_help"
-                },
-                {
-                    "name": "connection",
-                    "value": "string",
-                    "resource": "ServiceBus",
-                    "required": true,
-                    "label": "$notificationHubOut_connection_label",
-                    "help": "$notificationHubOut_connection_help",
-                    "placeholder": "[variables('selectConnection')]"
-                },
-                {
-                    "name": "tagExpression",
-                    "value": "string",
-                    "required": false,
-                    "label": "$notificationHubOut_tagExpression_label",
-                    "help": "$notificationHubOut_tagExpression_help"
-                },
-                {
-                    "name": "enableTestSend",
-                    "value": "boolean",
-                    "required": false,
-                    "label": "$notificationHubOut_enableTestSend_label",
-                    "help": "$notificationHubOut_enableTestSend_help"
-                },
-                {
-                    "name": "platform",
-                    "value": "enum",
-                    "enum": [
-                        {
-                            "value": "",
-                            "display": "Template"
-                        },
-                        {
-                            "value": "apns",
-                            "display": "Apple (APNS)"
-                        },
-                        {
-                            "value": "adm",
-                            "display": "Amazon (ADM)"
-                        },
-                        {
-                            "value": "gcm",
-                            "display": "Google (GCM)"
-                        },
-                        {
-                            "value": "wns",
-                            "display": "Windows (WNS)"
-                        },
-                        {
-                            "value": "mpns",
-                            "display": "Windows Phone (MPNS)"
-                        }
-                    ],
-                    "label": "$notificationHubOut_platform_label",
-                    "help": "$notificationHubOut_platform_help"
-                }
-            ]
+          "name": "entityId",
+          "value": "string",
+          "defaultValue": null,
+          "required": false,
+          "label": "[variables('apiHubTableEntityLabel')]",
+          "help": "[variables('apiHubTableEntityHelp')]",
+          "validators": []
         },
         {
-            "type": "sendGrid",
-            "displayName": "$sendGrid_displayName",
-            "direction": "out",
-            "enabledInTryMode": false,
-            "documentation": "$content=Documentation\\sendGridOut.md",
-            "settings": [
-                {
-                    "name": "name",
-                    "value": "string",
-                    "defaultValue": "message",
-                    "required": true,
-                    "label": "$sendGrid_name_label",
-                    "help": "$sendGrid_name_help",
-                    "validators": [
-                        {
-                            "expression": "(^[a-zA-Z][a-zA-Z0-9]{0,127}$)|^\\$return$",
-                            "errorText": "[variables('parameterName')]"
-                        }
-                    ]
-                },
-                {
-                    "name": "apiKey",
-                    "value": "string",
-                    "defaultValue": "SendGridApiKey",
-                    "required": true,
-                    "label": "$sendGrid_apiKey_label",
-                    "help": "$sendGrid_apiKey_help"
-                },
-                {
-                    "name": "to",
-                    "value": "string",
-                    "defaultValue": "",
-                    "required": false,
-                    "label": "$sendGrid_to_label",
-                    "help": "$sendGrid_to_help"
-                },
-                {
-                    "name": "from",
-                    "value": "string",
-                    "defaultValue": "",
-                    "required": false,
-                    "label": "$sendGrid_from_label",
-                    "help": "$sendGrid_from_help"
-                },
-                {
-                    "name": "subject",
-                    "value": "string",
-                    "defaultValue": "",
-                    "required": false,
-                    "label": "$sendGrid_subject_label",
-                    "help": "$sendGrid_subject_help"
-                },
-                {
-                    "name": "text",
-                    "value": "string",
-                    "defaultValue": "",
-                    "required": false,
-                    "label": "$sendGrid_text_label",
-                    "help": "$sendGrid_text_help"
-                }
-            ]
+          "name": "connection",
+          "value": "string",
+          "resource": "ApiHub",
+          "required": true,
+          "label": "[variables('apiHubTableConnectionLabel')]",
+          "help": "[variables('apiHubTableConnectionHelp')]",
+          "metadata": {
+            "capability": "tabular"
+          }
+        }
+      ]
+    },
+    {
+      "type": "apiHubTable",
+      "displayName": "$apiHubTableOut_displayName",
+      "direction": "out",
+      "enabledInTryMode": false,
+      "documentation": "$content=Documentation\\apiHubTableOut.md",
+      "settings": [
+        {
+          "name": "name",
+          "value": "string",
+          "defaultValue": "outputTable",
+          "required": true,
+          "label": "[variables('paramNameLabel')]",
+          "help": "[variables('paramNameOutputHelp')]",
+          "validators": [
+            {
+              "expression": "(^[a-zA-Z][a-zA-Z0-9]{0,127}$)|^\\$return$",
+              "errorText": "[variables('parameterName')]"
+            }
+          ]
         },
         {
-            "type": "twilioSms",
-            "displayName": "$twilioSms_displayName",
-            "direction": "out",
-            "enabledInTryMode": false,
-            "documentation": "$content=Documentation\\twilioSmsOut.md",
-            "settings": [
-                {
-                    "name": "name",
-                    "value": "string",
-                    "defaultValue": "message",
-                    "required": true,
-                    "label": "$twilioSms_name_label",
-                    "help": "$twilioSms_name_help",
-                    "validators": [
-                        {
-                            "expression": "(^[a-zA-Z][a-zA-Z0-9]{0,127}$)|^\\$return$",
-                            "errorText": "[variables('parameterName')]"
-                        }
-                    ]
-                },
-                {
-                    "name": "accountSid",
-                    "value": "string",
-                    "defaultValue": "TwilioAccountSid",
-                    "required": true,
-                    "label": "$twilioSms_accountsid_label",
-                    "help": "$twilioSms_accountsid_help"
-                },
-                {
-                    "name": "authToken",
-                    "value": "string",
-                    "defaultValue": "TwilioAuthToken",
-                    "required": true,
-                    "label": "$twilioSms_authtoken_label",
-                    "help": "$twilioSms_authtoken_help"
-                },
-                {
-                    "name": "to",
-                    "value": "string",
-                    "defaultValue": "",
-                    "required": false,
-                    "label": "$twilioSms_to_label",
-                    "help": "$twilioSms_to_help"
-                },
-                {
-                    "name": "from",
-                    "value": "string",
-                    "defaultValue": "",
-                    "required": false,
-                    "label": "$twilioSms_from_label",
-                    "help": "$twilioSms_from_help"
-                },
-                {
-                    "name": "body",
-                    "value": "string",
-                    "defaultValue": "",
-                    "required": false,
-                    "label": "$twilioSms_body_label",
-                    "help": "$twilioSms_body_help"
-                }
-            ]
+          "name": "dataSetName",
+          "value": "string",
+          "defaultValue": "default",
+          "required": false,
+          "label": "[variables('apiHubTableDataSetLabel')]",
+          "help": "[variables('apiHubTableDataSetHelp')]",
+          "validators": []
         },
         {
-            "type": "bot",
-            "displayName": "$bot_out_displayName",
-            "direction": "out",
-            "enabledInTryMode": false,
-            "documentation": "$content=Documentation\\botOut.md",
-            "settings": [
-                {
-                    "name": "name",
-                    "value": "string",
-                    "defaultValue": "$return",
-                    "required": true,
-                    "label": "$bot_out_name_label",
-                    "help": "$bot_out_name_help",
-                    "validators": [
-                        {
-                            "expression": "(^[a-zA-Z][a-zA-Z0-9]{0,127}$)|^\\$return$",
-                            "errorText": "[variables('parameterName')]"
-                        }
-                    ]
-                },
-                {
-                    "name": "botId",
-                    "value": "string",
-                    "required": true,
-                    "label": "$bot_botId_label",
-                    "help": "$bot_botId_help"
-                },
-                {
-                    "name": "secret",
-                    "value": "string",
-                    "required": false,
-                    "label": "$bot_out_secret_label",
-                    "help": "$bot_out_secret_help"
-                }
-            ]
+          "name": "tableName",
+          "value": "string",
+          "defaultValue": null,
+          "required": false,
+          "label": "[variables('apiHubTableNameLabel')]",
+          "help": "[variables('apiHubTableHelp')]",
+          "validators": []
         },
         {
-            "type": "bot",
-            "displayName": "$bot_in_displayName",
-            "direction": "in",
-            "enabledInTryMode": false,
-            "documentation": "$content=Documentation\\botIn.md",
-            "settings": [
-                {
-                    "name": "name",
-                    "value": "string",
-                    "defaultValue": "bot",
-                    "required": true,
-                    "label": "$bot_in_name_label",
-                    "help": "$bot_in_name_help",
-                    "validators": [
-                        {
-                            "expression": "^[a-zA-Z][a-zA-Z0-9]{0,127}$",
-                            "errorText": "[variables('parameterName')]"
-                        }
-                    ]
-                },
-                {
-                    "name": "secret",
-                    "value": "string",
-                    "required": false,
-                    "label": "$bot_in_secret_label",
-                    "help": "$bot_in_secret_help"
-                }
-            ]
+          "name": "entityId",
+          "value": "string",
+          "defaultValue": null,
+          "required": false,
+          "label": "[variables('apiHubTableEntityLabel')]",
+          "help": "[variables('apiHubTableEntityHelp')]",
+          "validators": []
+        },
+        {
+          "name": "connection",
+          "value": "string",
+          "resource": "ApiHub",
+          "required": true,
+          "label": "[variables('apiHubTableConnectionLabel')]",
+          "help": "[variables('apiHubTableConnectionHelp')]",
+          "metadata": {
+            "capability": "tabular"
+          }
+        }
+      ]
+    },
+    {
+      "type": "httpTrigger",
+      "displayName": "$httpTrigger_displayName",
+      "direction": "trigger",
+      "enabledInTryMode": true,
+      "documentation": "$content=Documentation\\httpTrigger.md",
+      "settings": [
+        {
+          "name": "name",
+          "value": "string",
+          "defaultValue": "req",
+          "required": true,
+          "label": "$httpTrigger_name_label",
+          "help": "$httpTrigger_name_help",
+          "validators": [
+            {
+              "expression": "^[a-zA-Z][a-zA-Z0-9]{0,127}$",
+              "errorText": "[variables('parameterName')]"
+            }
+          ]
+        },
+        {
+          "name": "route",
+          "value": "string",
+          "required": false,
+          "label": "$httpTrigger_route_label",
+          "help": "$httpTrigger_route_help",
+          "validators": []
+        },
+        {
+          "name": "webHookType",
+          "value": "enum",
+          "enum": [
+            {
+              "value": "github",
+              "display": "GitHub"
+            },
+            {
+              "value": "genericJson",
+              "display": "Generic JSON"
+            },
+            {
+              "value": "slack",
+              "display": "Slack"
+            }
+          ],
+          "label": "$httpTrigger_webHookType_label",
+          "help": "$httpTrigger_webHookType_help"
+        },
+        {
+          "name": "authLevel",
+          "value": "enum",
+          "enum": [
+            {
+              "value": "function",
+              "display": "Function"
+            },
+            {
+              "value": "anonymous",
+              "display": "Anonymous"
+            },
+            {
+              "value": "admin",
+              "display": "Admin"
+            }
+          ],
+          "label": "$httpTrigger_authLevel_label",
+          "help": "$httpTrigger_authLevel_help"
+        },
+        {
+          "name": "methods",
+          "value": "checkBoxList",
+          "defaultValue": [
+            "get",
+            "post",
+            "delete",
+            "head",
+            "patch",
+            "put",
+            "options",
+            "trace"
+          ],
+          "enum": [
+            {
+              "value": "get",
+              "display": "GET"
+            },
+            {
+              "value": "post",
+              "display": "POST"
+            },
+            {
+              "value": "delete",
+              "display": "DELETE"
+            },
+            {
+              "value": "head",
+              "display": "HEAD"
+            },
+            {
+              "value": "patch",
+              "display": "PATCH"
+            },
+            {
+              "value": "put",
+              "display": "PUT"
+            },
+            {
+              "value": "options",
+              "display": "OPTIONS"
+            },
+            {
+              "value": "trace",
+              "display": "TRACE"
+            }
+          ],
+          "label": "$httpTrigger_methods_label",
+          "help": "$httpTrigger_methods_help"
+        }
+      ],
+      "rules": [
+        {
+          "name": "mode",
+          "type": "exclusivity",
+          "values": [
+            {
+              "value": "authLevel",
+              "display": "Standard",
+              "hiddenSettings": [
+                "webHookType"
+              ],
+              "shownSettings": [
+                "authLevel"
+              ]
+            },
+            {
+              "value": "webHookType",
+              "display": "Webhook",
+              "hiddenSettings": [
+                "authLevel"
+              ],
+              "shownSettings": [
+                "webHookType"
+              ]
+            }
+          ],
+          "label": "$httpTrigger_mode_label",
+          "help": "$httpTrigger_mode_help"
+        },
+        {
+          "name": "methodRule",
+          "type": "exclusivity",
+          "values": [
+            {
+              "value": "allMethods",
+              "display": "All methods",
+              "hiddenSettings": [
+                "methods"
+              ],
+              "shownSettings": []
+            },
+            {
+              "value": "methods",
+              "display": "Selected methods",
+              "hiddenSettings": [],
+              "shownSettings": [
+                "methods"
+              ]
+            }
+          ],
+          "label": "$httpTrigger_methodRule_label",
+          "help": "$httpTrigger_methodRule_help"
+        }
+      ]
+    },
+    {
+      "type": "http",
+      "displayName": "$httpOut_displayName",
+      "direction": "out",
+      "enabledInTryMode": true,
+      "documentation": "$content=Documentation\\httpOut.md",
+      "settings": [
+        {
+          "name": "name",
+          "value": "string",
+          "defaultValue": "res",
+          "required": true,
+          "label": "$httpOut_name_label",
+          "help": "$httpOut_name_help",
+          "validators": [
+            {
+              "expression": "(^[a-zA-Z][a-zA-Z0-9]{0,127}$)|^\\$return$",
+              "errorText": "[variables('parameterName')]"
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "type": "serviceBusTrigger",
+      "displayName": "$serviceBusTrigger_displayName",
+      "direction": "trigger",
+      "enabledInTryMode": false,
+      "documentation": "$content=Documentation\\serviceBusTrigger.md",
+      "settings": [
+        {
+          "name": "name",
+          "value": "string",
+          "defaultValue": "mySbMsg",
+          "required": true,
+          "label": "$serviceBusTrigger_name_label",
+          "help": "$serviceBusTrigger_name_help",
+          "validators": [
+            {
+              "expression": "^[a-zA-Z][a-zA-Z0-9]{0,127}$",
+              "errorText": "[variables('parameterName')]"
+            }
+          ]
+        },
+        {
+          "name": "queueName",
+          "value": "string",
+          "defaultValue": "mysbqueue",
+          "required": false,
+          "label": "$serviceBusTrigger_queueName_label",
+          "help": "$serviceBusTrigger_queueName_help",
+          "validators": [
+            {
+              "expression": "^[0-9a-z][a-z0-9_.-]{1,48}[0-9a-z]$|^[{][a-zA-Z0-9]{1,126}[}]$|^[%][a-zA-Z0-9]{1,126}[%]$",
+              "errorText": "$serviceBusTrigger_queueName_errorText"
+            }
+          ]
+        },
+        {
+          "name": "topicName",
+          "value": "string",
+          "defaultValue": "mysbtopic",
+          "required": false,
+          "label": "$serviceBusTrigger_topicName_label",
+          "help": "$serviceBusTrigger_topicName_help",
+          "validators": [
+            {
+              "expression": "^[0-9a-z][a-z0-9_.-]{1,48}[0-9a-z]$|^[{][a-zA-Z0-9]{1,126}[}]$|^[%][a-zA-Z0-9]{1,126}[%]$",
+              "errorText": "$serviceBusTrigger_topicName_errorText"
+            }
+          ]
+        },
+        {
+          "name": "subscriptionName",
+          "value": "string",
+          "defaultValue": "mysubscription",
+          "required": false,
+          "label": "$serviceBusTrigger_subscriptionName_label",
+          "help": "$serviceBusTrigger_subscriptionName_help",
+          "validators": [
+            {
+              "expression": "^[0-9a-zA-Z][a-zA-Z0-9_.-]{1,48}[0-9a-zA-Z]$|^[{][a-zA-Z0-9]{1,126}[}]$|^[%][a-zA-Z0-9]{1,126}[%]$",
+              "errorText": "$serviceBusTrigger_subscriptionName_errorText"
+            }
+          ]
+        },
+        {
+          "name": "connection",
+          "value": "string",
+          "resource": "EventHub",
+          "required": true,
+          "label": "$serviceBusTrigger_connection_label",
+          "help": "$serviceBusTrigger_connection_help",
+          "placeholder": "[variables('selectConnection')]"
+        },
+        {
+          "name": "accessRights",
+          "value": "enum",
+          "enum": [
+            {
+              "value": "Manage",
+              "display": "Manage"
+            },
+            {
+              "value": "Listen",
+              "display": "Listen"
+            }
+          ],
+          "label": "$serviceBusTrigger_accessRights_label",
+          "help": "$serviceBusTrigger_accessRights_help"
+        }
+      ],
+      "rules": [
+        {
+          "name": "messageType",
+          "type": "exclusivity",
+          "values": [
+            {
+              "value": "queueName",
+              "display": "$serviceBusTrigger_messageType_queueName",
+              "hiddenSettings": [
+                "topicName",
+                "subscriptionName"
+              ],
+              "shownSettings": [
+                "queueName"
+              ]
+            },
+            {
+              "value": "topicName",
+              "display": "$serviceBusTrigger_messageType_topicName",
+              "hiddenSettings": [
+                "queueName"
+              ],
+              "shownSettings": [
+                "topicName",
+                "subscriptionName"
+              ]
+            }
+          ],
+          "label": "$serviceBusTrigger_messageType_label",
+          "help": "$serviceBusTrigger_messageType_help"
+        }
+      ]
+    },
+    {
+      "type": "serviceBus",
+      "displayName": "$serviceBusOut_displayName",
+      "direction": "out",
+      "enabledInTryMode": false,
+      "documentation": "$content=Documentation\\serviceBusOut.md",
+      "settings": [
+        {
+          "name": "name",
+          "value": "string",
+          "defaultValue": "outputSbMsg",
+          "required": true,
+          "label": "$serviceBusOut_name_label",
+          "help": "$serviceBusOut_name_help",
+          "validators": [
+            {
+              "expression": "(^[a-zA-Z][a-zA-Z0-9]{0,127}$)|^\\$return$",
+              "errorText": "[variables('parameterName')]"
+            }
+          ]
+        },
+        {
+          "name": "queueName",
+          "value": "string",
+          "defaultValue": "outqueue",
+          "required": true,
+          "label": "$serviceBusOut_queueName_label",
+          "help": "$serviceBusOut_queueName_help",
+          "validators": [
+            {
+              "expression": "^[0-9a-z][a-z0-9_.-]{1,48}[0-9a-z]$|^[{][a-zA-Z0-9]{1,126}[}]$|^[%][a-zA-Z0-9]{1,126}[%]$",
+              "errorText": "$serviceBusOut_queueName_errorText"
+            }
+          ]
+        },
+        {
+          "name": "topicName",
+          "value": "string",
+          "defaultValue": "outtopic",
+          "required": true,
+          "label": "$serviceBusOut_topicName_label",
+          "help": "$serviceBusOut_topicName_help",
+          "validators": [
+            {
+              "expression": "^[0-9a-z][a-z0-9_.-]{1,48}[0-9a-z]$|^[{][a-zA-Z0-9]{1,126}[}]$|^[%][a-zA-Z0-9]{1,126}[%]$",
+              "errorText": "$serviceBusOut_topicName_errorText"
+            }
+          ]
+        },
+        {
+          "name": "connection",
+          "value": "string",
+          "resource": "EventHub",
+          "required": true,
+          "label": "$serviceBusOut_connection_label",
+          "help": "$serviceBusOut_connection_help",
+          "placeholder": "[variables('selectConnection')]"
+        },
+        {
+          "name": "accessRights_",
+          "value": "enum",
+          "enum": [
+            {
+              "value": "Manage",
+              "display": "Manage"
+            },
+            {
+              "value": "Send",
+              "display": "Send"
+            }
+          ],
+          "label": "$serviceBusOut_accessRights_label",
+          "help": "$serviceBusOut_accessRights_help"
+        }
+      ],
+      "rules": [
+        {
+          "name": "messageType",
+          "type": "exclusivity",
+          "values": [
+            {
+              "value": "queueName",
+              "display": "$serviceBusOut_messageType_queueName",
+              "hiddenSettings": [
+                "topicName"
+              ],
+              "shownSettings": [
+                "queueName"
+              ]
+            },
+            {
+              "value": "topicName",
+              "display": "$serviceBusOut_messageType_topicName",
+              "hiddenSettings": [
+                "queueName"
+              ],
+              "shownSettings": [
+                "topicName"
+              ]
+            }
+          ],
+          "label": "$serviceBusOut_messageType_label",
+          "help": "$serviceBusOut_messageType_help"
+        }
+      ]
+    },
+    {
+      "type": "manualTrigger",
+      "displayName": "Manual",
+      "direction": "trigger",
+      "enabledInTryMode": true,
+      "documentation": "$content=Documentation\\manualTrigger.md",
+      "settings": [
+        {
+          "name": "name",
+          "value": "string",
+          "defaultValue": "input",
+          "required": true,
+          "label": "$manualTrigger_name_label",
+          "help": "$manualTrigger_name_help",
+          "validators": [
+            {
+              "expression": "^[a-zA-Z][a-zA-Z0-9]{0,127}$",
+              "errorText": "[variables('parameterName')]"
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "type": "table",
+      "displayName": "$tableout_displayName",
+      "direction": "out",
+      "enabledInTryMode": true,
+      "documentation": "$content=Documentation\\tableOut.md",
+      "settings": [
+        {
+          "name": "name",
+          "value": "string",
+          "defaultValue": "outputTable",
+          "required": true,
+          "label": "$tableout_name_label",
+          "help": "$tableout_name_help",
+          "validators": [
+            {
+              "expression": "(^[a-zA-Z][a-zA-Z0-9]{0,127}$)|^\\$return$",
+              "errorText": "[variables('parameterName')]"
+            }
+          ]
+        },
+        {
+          "name": "tableName",
+          "value": "string",
+          "defaultValue": "outTable",
+          "required": true,
+          "label": "$table_tableName_label",
+          "help": "$table_tableName_help",
+          "validators": [
+            {
+              "expression": "^[A-Za-z][A-Za-z0-9]{2,62}$|^[{][a-zA-Z0-9]{1,126}[}]$|^[%][a-zA-Z0-9]{1,126}[%]$",
+              "errorText": "$table_tableName_errorText"
+            }
+          ]
+        },
+        {
+          "name": "connection",
+          "value": "string",
+          "resource": "Storage",
+          "required": true,
+          "label": "[variables('storageConnStringLabel')]",
+          "help": "[variables('appSettingsHelp')]",
+          "placeholder": "[variables('selectConnection')]"
+        }
+      ]
+    },
+    {
+      "type": "table",
+      "displayName": "$tableIn_displayName",
+      "direction": "in",
+      "enabledInTryMode": true,
+      "documentation": "$content=Documentation\\tableIn.md",
+      "settings": [
+        {
+          "name": "name",
+          "value": "string",
+          "defaultValue": "inputTable",
+          "required": true,
+          "label": "$tableIn_name_label",
+          "help": "$tableIn_name_help",
+          "validators": [
+            {
+              "expression": "^[a-zA-Z][a-zA-Z0-9]{0,127}$",
+              "errorText": "[variables('parameterName')]"
+            }
+          ]
+        },
+        {
+          "name": "tableName",
+          "value": "string",
+          "defaultValue": "inTable",
+          "required": true,
+          "label": "$tableIn_tableName_label",
+          "help": "$tableIn_tableName_help",
+          "validators": [
+            {
+              "expression": "^[A-Za-z][A-Za-z0-9]{2,62}$|^[{][a-zA-Z0-9]{1,126}[}]$|^[%][a-zA-Z0-9]{1,126}[%]$",
+              "errorText": "$tableIn_tableName_errorText"
+            }
+          ]
+        },
+        {
+          "name": "partitionKey",
+          "value": "string",
+          "required": false,
+          "label": "$tableIn_partitionKey_label",
+          "help": "$tableIn_partitionKey_help"
+        },
+        {
+          "name": "rowKey",
+          "value": "string",
+          "required": false,
+          "label": "$tableIn_rowKey_label",
+          "help": "$tableIn_rowKey_help"
+        },
+        {
+          "name": "take",
+          "value": "int",
+          "defaultValue": 50,
+          "required": false,
+          "label": "$tableIn_take_label",
+          "help": "$tableIn_take_help"
+        },
+        {
+          "name": "filter",
+          "value": "string",
+          "required": false,
+          "label": "$tableIn_filter_label",
+          "help": "$tableIn_filter_help"
+        },
+        {
+          "name": "connection",
+          "value": "string",
+          "resource": "Storage",
+          "required": true,
+          "label": "[variables('storageConnStringLabel')]",
+          "help": "[variables('appSettingsHelp')]",
+          "placeholder": "[variables('selectConnection')]"
+        }
+      ]
+    },
+    {
+      "type": "cosmosDB",
+      "displayName": "$cosmosDBOut_displayName",
+      "direction": "out",
+      "enabledInTryMode": false,
+      "documentation": "$content=Documentation\\cosmosDBOut.md",
+      "settings": [
+        {
+          "name": "name",
+          "value": "string",
+          "defaultValue": "outputDocument",
+          "required": true,
+          "label": "$cosmosDBOut_name_label",
+          "help": "$cosmosDBOut_name_help",
+          "validators": [
+            {
+              "expression": "(^[a-zA-Z][a-zA-Z0-9]{0,127}$)|^\\$return$",
+              "errorText": "[variables('parameterName')]"
+            }
+          ]
+        },
+        {
+          "name": "databaseName",
+          "value": "string",
+          "defaultValue": "outDatabase",
+          "required": true,
+          "label": "$cosmosDBOut_databaseName_label",
+          "help": "$cosmosDBOut_databaseName_help"
+        },
+        {
+          "name": "collectionName",
+          "value": "string",
+          "defaultValue": "MyCollection",
+          "required": true,
+          "label": "$cosmosDBOut_collectionName_label",
+          "help": "$cosmosDBOut_collectionName_help"
+        },
+        {
+          "name": "createIfNotExists",
+          "value": "boolean",
+          "defaultValue": true,
+          "required": false,
+          "label": "$cosmosDBOut_createIfNotExists_label",
+          "help": "$cosmosDBOut_createIfNotExists_help"
+        },
+        {
+          "name": "connectionStringSetting",
+          "value": "string",
+          "resource": "CosmosDB",
+          "required": true,
+          "label": "$cosmosDBOut_connection_label",
+          "help": "$cosmosDBOut_connection_help",
+          "placeholder": "[variables('selectConnection')]"
+        }
+      ]
+    },
+    {
+      "type": "cosmosDBTrigger",
+      "displayName": "$cosmosDBIn_displayName",
+      "direction": "trigger",
+      "enabledInTryMode": false,
+      "documentation": "$content=Documentation\\cosmosDBTrigger.md",
+      "settings": [
+        {
+          "name": "name",
+          "value": "string",
+          "defaultValue": "inputDocument",
+          "required": true,
+          "label": "$cosmosDBIn_name_label",
+          "help": "$cosmosDBIn_name_help",
+          "validators": [
+            {
+              "expression": "^[a-zA-Z][a-zA-Z0-9]{0,127}$",
+              "errorText": "[variables('parameterName')]"
+            }
+          ]
+        },
+        {
+          "name": "databaseName",
+          "value": "string",
+          "defaultValue": "inDatabase",
+          "required": true,
+          "label": "$cosmosDBIn_databaseName_label",
+          "help": "$cosmosDBIn_databaseName_help"
+        },
+        {
+          "name": "collectionName",
+          "value": "string",
+          "defaultValue": "MyCollection",
+          "required": true,
+          "label": "$cosmosDBIn_collectionName_label",
+          "help": "$cosmosDBIn_collectionName_help"
+        },
+        {
+          "name": "leaseCollectionName",
+          "value": "string",
+          "defaultValue": "leases",
+          "required": true,
+          "label": "$cosmosDBIn_leaseCollectionName_label",
+          "help": "$cosmosDBIn_leaseCollectionName_help"
+        },
+        {
+          "name": "createLeaseCollectionIfNotExists",
+          "value": "boolean",
+          "required": false,
+          "defaultValue": true,
+          "label": "$cosmosDBIn_createLeaseCollectionIfNotExists_label",
+          "help": "$cosmosDBIn_createLeaseCollectionIfNotExists_help"
+        },
+        {
+          "name": "connectionStringSetting",
+          "value": "string",
+          "resource": "CosmosDB",
+          "required": true,
+          "label": "$cosmosDBIn_connection_label",
+          "help": "$cosmosDBIn_connection_help",
+          "placeholder": "[variables('selectConnection')]"
+        }
+      ]
+    },
+    {
+      "type": "mobileTable",
+      "displayName": "$mobileTableOut_displayName",
+      "direction": "out",
+      "enabledInTryMode": false,
+      "documentation": "$content=Documentation\\mobileTableOut.md",
+      "settings": [
+        {
+          "name": "name",
+          "value": "string",
+          "defaultValue": "outputRecord",
+          "required": true,
+          "label": "$mobileTableOut_name_label",
+          "help": "$mobileTableOut_name_help",
+          "validators": [
+            {
+              "expression": "(^[a-zA-Z][a-zA-Z0-9]{0,127}$)|^\\$return$",
+              "errorText": "[variables('parameterName')]"
+            }
+          ]
+        },
+        {
+          "name": "tableName",
+          "value": "string",
+          "defaultValue": "outTable",
+          "required": true,
+          "label": "$mobileTableOut_tableName_label",
+          "help": "$mobileTableOut_tableName_help"
+        },
+        {
+          "name": "connection",
+          "value": "string",
+          "defaultValue": "My_MobileApp_Uri",
+          "required": true,
+          "label": "$mobileTableOut_connection_label",
+          "help": "$mobileTableOut_connection_help"
+        },
+        {
+          "name": "apiKey",
+          "value": "string",
+          "required": false,
+          "label": "$mobileTableOut_apiKey_label",
+          "help": "$mobileTableOut_apiKey_help"
+        }
+      ]
+    },
+    {
+      "type": "mobileTable",
+      "displayName": "$mobileTableIn_displayName",
+      "direction": "in",
+      "enabledInTryMode": false,
+      "documentation": "$content=Documentation\\mobileTableIn.md",
+      "settings": [
+        {
+          "name": "name",
+          "value": "string",
+          "defaultValue": "inputRecord",
+          "required": true,
+          "label": "$mobileTableIn_name_label",
+          "help": "$mobileTableIn_name_help",
+          "validators": [
+            {
+              "expression": "^[a-zA-Z][a-zA-Z0-9]{0,127}$",
+              "errorText": "[variables('parameterName')]"
+            }
+          ]
+        },
+        {
+          "name": "tableName",
+          "value": "string",
+          "defaultValue": "inTable",
+          "required": true,
+          "label": "$mobileTableIn_tableName_label",
+          "help": "$mobileTableIn_tableName_help"
+        },
+        {
+          "name": "id",
+          "value": "string",
+          "defaultValue": "{itemId}",
+          "required": true,
+          "label": "$mobileTableIn_id_label",
+          "help": "$mobileTableIn_id_help"
+        },
+        {
+          "name": "connection",
+          "value": "string",
+          "defaultValue": "My_MobileApp_Uri",
+          "required": true,
+          "label": "$mobileTableIn_connection_label",
+          "help": "$mobileTableIn_connection_help"
+        },
+        {
+          "name": "apiKey",
+          "value": "string",
+          "required": false,
+          "label": "$mobileTableIn_apiKey_label",
+          "help": "$mobileTableIn_apiKey_help"
+        }
+      ]
+    },
+    {
+      "type": "notificationHub",
+      "displayName": "$notificationHubOut_displayName",
+      "direction": "out",
+      "enabledInTryMode": false,
+      "documentation": "$content=Documentation\\notificationHubOut.md",
+      "settings": [
+        {
+          "name": "name",
+          "value": "string",
+          "defaultValue": "notification",
+          "required": true,
+          "label": "$notificationHubOut_name_label",
+          "help": "$notificationHubOut_name_help",
+          "validators": [
+            {
+              "expression": "(^[a-zA-Z][a-zA-Z0-9]{0,127}$)|^\\$return$",
+              "errorText": "[variables('parameterName')]"
+            }
+          ]
+        },
+        {
+          "name": "hubName",
+          "value": "string",
+          "required": true,
+          "label": "$notificationHubOut_hubName_label",
+          "help": "$notificationHubOut_hubName_help"
+        },
+        {
+          "name": "connection",
+          "value": "string",
+          "resource": "ServiceBus",
+          "required": true,
+          "label": "$notificationHubOut_connection_label",
+          "help": "$notificationHubOut_connection_help",
+          "placeholder": "[variables('selectConnection')]"
+        },
+        {
+          "name": "tagExpression",
+          "value": "string",
+          "required": false,
+          "label": "$notificationHubOut_tagExpression_label",
+          "help": "$notificationHubOut_tagExpression_help"
+        },
+        {
+          "name": "enableTestSend",
+          "value": "boolean",
+          "required": false,
+          "label": "$notificationHubOut_enableTestSend_label",
+          "help": "$notificationHubOut_enableTestSend_help"
+        },
+        {
+          "name": "platform",
+          "value": "enum",
+          "enum": [
+            {
+              "value": "",
+              "display": "Template"
+            },
+            {
+              "value": "apns",
+              "display": "Apple (APNS)"
+            },
+            {
+              "value": "adm",
+              "display": "Amazon (ADM)"
+            },
+            {
+              "value": "gcm",
+              "display": "Google (GCM)"
+            },
+            {
+              "value": "wns",
+              "display": "Windows (WNS)"
+            },
+            {
+              "value": "mpns",
+              "display": "Windows Phone (MPNS)"
+            }
+          ],
+          "label": "$notificationHubOut_platform_label",
+          "help": "$notificationHubOut_platform_help"
+        }
+      ]
+    },
+    {
+      "type": "sendGrid",
+      "displayName": "$sendGrid_displayName",
+      "direction": "out",
+      "enabledInTryMode": false,
+      "documentation": "$content=Documentation\\sendGridOut.md",
+      "settings": [
+        {
+          "name": "name",
+          "value": "string",
+          "defaultValue": "message",
+          "required": true,
+          "label": "$sendGrid_name_label",
+          "help": "$sendGrid_name_help",
+          "validators": [
+            {
+              "expression": "(^[a-zA-Z][a-zA-Z0-9]{0,127}$)|^\\$return$",
+              "errorText": "[variables('parameterName')]"
+            }
+          ]
+        },
+        {
+          "name": "apiKey",
+          "value": "string",
+          "defaultValue": "SendGridApiKey",
+          "required": true,
+          "label": "$sendGrid_apiKey_label",
+          "help": "$sendGrid_apiKey_help"
+        },
+        {
+          "name": "to",
+          "value": "string",
+          "defaultValue": "",
+          "required": false,
+          "label": "$sendGrid_to_label",
+          "help": "$sendGrid_to_help"
+        },
+        {
+          "name": "from",
+          "value": "string",
+          "defaultValue": "",
+          "required": false,
+          "label": "$sendGrid_from_label",
+          "help": "$sendGrid_from_help"
+        },
+        {
+          "name": "subject",
+          "value": "string",
+          "defaultValue": "",
+          "required": false,
+          "label": "$sendGrid_subject_label",
+          "help": "$sendGrid_subject_help"
+        },
+        {
+          "name": "text",
+          "value": "string",
+          "defaultValue": "",
+          "required": false,
+          "label": "$sendGrid_text_label",
+          "help": "$sendGrid_text_help"
+        }
+      ]
+    },
+    {
+      "type": "twilioSms",
+      "displayName": "$twilioSms_displayName",
+      "direction": "out",
+      "enabledInTryMode": false,
+      "documentation": "$content=Documentation\\twilioSmsOut.md",
+      "settings": [
+        {
+          "name": "name",
+          "value": "string",
+          "defaultValue": "message",
+          "required": true,
+          "label": "$twilioSms_name_label",
+          "help": "$twilioSms_name_help",
+          "validators": [
+            {
+              "expression": "(^[a-zA-Z][a-zA-Z0-9]{0,127}$)|^\\$return$",
+              "errorText": "[variables('parameterName')]"
+            }
+          ]
+        },
+        {
+          "name": "accountSid",
+          "value": "string",
+          "defaultValue": "TwilioAccountSid",
+          "required": true,
+          "label": "$twilioSms_accountsid_label",
+          "help": "$twilioSms_accountsid_help"
+        },
+        {
+          "name": "authToken",
+          "value": "string",
+          "defaultValue": "TwilioAuthToken",
+          "required": true,
+          "label": "$twilioSms_authtoken_label",
+          "help": "$twilioSms_authtoken_help"
+        },
+        {
+          "name": "to",
+          "value": "string",
+          "defaultValue": "",
+          "required": false,
+          "label": "$twilioSms_to_label",
+          "help": "$twilioSms_to_help"
+        },
+        {
+          "name": "from",
+          "value": "string",
+          "defaultValue": "",
+          "required": false,
+          "label": "$twilioSms_from_label",
+          "help": "$twilioSms_from_help"
+        },
+        {
+          "name": "body",
+          "value": "string",
+          "defaultValue": "",
+          "required": false,
+          "label": "$twilioSms_body_label",
+          "help": "$twilioSms_body_help"
+        }
+      ]
+    },
+    {
+      "type": "bot",
+      "displayName": "$bot_out_displayName",
+      "direction": "out",
+      "enabledInTryMode": false,
+      "documentation": "$content=Documentation\\botOut.md",
+      "settings": [
+        {
+          "name": "name",
+          "value": "string",
+          "defaultValue": "$return",
+          "required": true,
+          "label": "$bot_out_name_label",
+          "help": "$bot_out_name_help",
+          "validators": [
+            {
+              "expression": "(^[a-zA-Z][a-zA-Z0-9]{0,127}$)|^\\$return$",
+              "errorText": "[variables('parameterName')]"
+            }
+          ]
+        },
+        {
+          "name": "botId",
+          "value": "string",
+          "required": true,
+          "label": "$bot_botId_label",
+          "help": "$bot_botId_help"
+        },
+        {
+          "name": "secret",
+          "value": "string",
+          "required": false,
+          "label": "$bot_out_secret_label",
+          "help": "$bot_out_secret_help"
+        }
+      ]
+    },
+    {
+      "type": "bot",
+      "displayName": "$bot_in_displayName",
+      "direction": "in",
+      "enabledInTryMode": false,
+      "documentation": "$content=Documentation\\botIn.md",
+      "settings": [
+        {
+          "name": "name",
+          "value": "string",
+          "defaultValue": "bot",
+          "required": true,
+          "label": "$bot_in_name_label",
+          "help": "$bot_in_name_help",
+          "validators": [
+            {
+              "expression": "^[a-zA-Z][a-zA-Z0-9]{0,127}$",
+              "errorText": "[variables('parameterName')]"
+            }
+          ]
+        },
+        {
+          "name": "secret",
+          "value": "string",
+          "required": false,
+          "label": "$bot_in_secret_label",
+          "help": "$bot_in_secret_help"
         }
-    ]
-}
\ No newline at end of file
+      ]
+    }
+  ]
+}
diff --git a/src/shared/constants.ts b/src/shared/constants.ts
index 08b7d4e..4ef4d3f 100644
--- a/src/shared/constants.ts
+++ b/src/shared/constants.ts
@@ -28,5 +28,9 @@ export const constants = {
     appId: "appId",
     packageTimestamp: "packageTimestamp",
     azureCredentials: "azureCredentials",
+  },
+  runtimeExtensions: {
+    node: ".js",
+    python: ".py"
   }
 }
diff --git a/src/shared/utils.ts b/src/shared/utils.ts
index 02cee7f..59804a0 100644
--- a/src/shared/utils.ts
+++ b/src/shared/utils.ts
@@ -1,6 +1,6 @@
 import { relative } from "path";
 import Serverless from "serverless";
-import { ServerlessAzureFunctionConfig } from "../models/serverless";
+import { ServerlessAzureFunctionConfig, ServerlessAzureConfig } from "../models/serverless";
 import { BindingUtils } from "./bindings";
 import { constants } from "./constants";
 
@@ -12,6 +12,7 @@ export interface FunctionMetadata {
 
 export class Utils {
   public static getFunctionMetaData(functionName: string, serverless: Serverless): FunctionMetadata {
+    const config: ServerlessAzureConfig = serverless.service as any;
     const bindings = [];
     let bindingSettingsNames = [];
     let bindingSettings = [];
@@ -84,7 +85,7 @@ export class Utils {
     functionsJson.bindings = bindings;
     params.functionsJson = functionsJson;
 
-    let { handlerPath, entryPoint } = Utils.getEntryPointAndHandlerPath(handler);
+    let { handlerPath, entryPoint } = Utils.getEntryPointAndHandlerPath(handler, config);
     if (functionObject["scriptFile"]) {
       handlerPath = functionObject["scriptFile"];
     }
@@ -96,22 +97,18 @@ export class Utils {
     };
   }
 
-  public static getEntryPointAndHandlerPath(handler: string) {
-    let handlerPath = "handler.js";
-    let entryPoint = handler;
+  public static getEntryPointAndHandlerPath(handler: string, config: ServerlessAzureConfig) {
     const handlerSplit = handler.split(".");
 
-    if (handlerSplit.length > 1) {
-      entryPoint = handlerSplit[handlerSplit.length - 1];
-      handlerPath = `${handler.substring(0, handler.lastIndexOf("."))}.js`;
-    }
+    const entryPoint = (handlerSplit.length > 1) ? handlerSplit[handlerSplit.length - 1] : undefined;
 
-    const metaData = {
-      entryPoint: entryPoint,
-      handlerPath: handlerPath
-    };
+    const handlerPath = ((handlerSplit.length > 1) ? handlerSplit[0] : handler) 
+      + constants.runtimeExtensions[config.provider.functionRuntime.language]
 
-    return metaData;
+    return {
+      entryPoint,
+      handlerPath
+    };
   }
 
   /**


Test patch:
diff --git a/src/services/apimService.test.ts b/src/services/apimService.test.ts
index 0dbb742..6e62453 100644
--- a/src/services/apimService.test.ts
+++ b/src/services/apimService.test.ts
@@ -43,6 +43,7 @@ describe("APIM Service", () => {
         resourceGroup: "test-sls-rg",
         region: "West US",
         apim: apimConfig,
+        runtime: "nodejs10.x"
       },
     };
 
diff --git a/src/services/armService.test.ts b/src/services/armService.test.ts
index 15e1347..d2baa30 100644
--- a/src/services/armService.test.ts
+++ b/src/services/armService.test.ts
@@ -92,41 +92,6 @@ describe("Arm Service", () => {
       await expect(service.createDeploymentFromType("not-found")).rejects.not.toBeNull();
     });
 
-    it("throws error when invalid nodejs version in defined", async () => {
-      sls.service.provider.runtime = "nodejs10.6.1";
-      await expect(service.createDeploymentFromType("premium")).rejects.toThrowError("Could not find runtime version matching nodejs10.6.1");
-    });
-
-    it("throws error when incomplete nodejs version in defined", async () => {
-      sls.service.provider.runtime = "nodejs8";
-      await expect(service.createDeploymentFromType("premium")).rejects.toThrowError("Could not find runtime version matching nodejs8");
-    });
-
-    it("throws error when unsupported nodejs version in defined", async () => {
-      sls.service.provider.runtime = "nodejs5.x";
-      await expect(service.createDeploymentFromType("premium")).rejects.toThrowError("Could not find runtime version matching nodejs5.x");
-    });
-
-    it("Does not throw an error when valid nodejs version is defined", async () => {
-      sls.service.provider.runtime = "nodejs10.x";
-      await expect(service.createDeploymentFromType("premium")).resolves.not.toThrow();
-    });
-
-    it("Does not throw an error when nodejs version with major and minor is defined", async () => {
-      sls.service.provider.runtime = "nodejs6.9.x";
-      await expect(service.createDeploymentFromType("premium")).resolves.not.toThrow();
-    });
-
-    it("Does not throw an error when specific nodejs version is defined", async () => {
-      sls.service.provider.runtime = "nodejs10.6.0";
-      await expect(service.createDeploymentFromType("premium")).resolves.not.toThrow();
-    });
-
-    it("throws an error when no nodejs version is defined", async () => {
-      sls.service.provider.runtime = undefined;
-      await expect(service.createDeploymentFromType("premium")).rejects.toThrowError("Runtime version not specified in serverless.yml");
-    });
-
     it("Premium template includes correct resources", async () => {
       sls.service.provider.runtime = "nodejs10.14.1";
       const deployment = await service.createDeploymentFromType(ArmTemplateType.Premium);
diff --git a/src/services/azureKeyVaultService.test.ts b/src/services/azureKeyVaultService.test.ts
index d06bba3..58ff881 100644
--- a/src/services/azureKeyVaultService.test.ts
+++ b/src/services/azureKeyVaultService.test.ts
@@ -72,7 +72,8 @@ describe("Azure Key Vault Service", () => {
         name: "azure",
         resourceGroup: "test-sls-rg",
         region: "West US",
-        keyVault
+        keyVault,
+        runtime: "nodejs10.x",
       }
     };
 
diff --git a/src/services/baseService.test.ts b/src/services/baseService.test.ts
index a7430e0..90be581 100644
--- a/src/services/baseService.test.ts
+++ b/src/services/baseService.test.ts
@@ -47,6 +47,7 @@ describe("Base Service", () => {
     provider: {
       resourceGroup: "My-Resource-Group",
       deploymentName: "My-Deployment",
+      runtime: "nodejs10.x"
     },
   };
 
diff --git a/src/services/configService.test.ts b/src/services/configService.test.ts
index 6888220..ccd7aa8 100644
--- a/src/services/configService.test.ts
+++ b/src/services/configService.test.ts
@@ -1,8 +1,8 @@
-import { ConfigService } from "./configService";
 import Serverless from "serverless";
-import { MockFactory } from "../test/mockFactory";
-import { ServerlessAzureConfig, DeploymentConfig } from "../models/serverless";
 import configConstants from "../config";
+import { DeploymentConfig, FunctionRuntime, ServerlessAzureConfig, SupportedRuntimeLanguage } from "../models/serverless";
+import { MockFactory } from "../test/mockFactory";
+import { ConfigService } from "./configService";
 import { AzureNamingService } from "./namingService";
 
 describe("Config Service", () => {
@@ -193,4 +193,78 @@ describe("Config Service", () => {
       expect(serverless.service.provider["subscriptionId"]).toEqual(loginResultSubscriptionId);
     });
   });
+
+  describe("Runtime version", () => {
+    it("throws error when invalid nodejs version in defined", () => {
+      const sls = MockFactory.createTestServerless();
+      sls.service.provider.runtime = "nodejs10.6.1";
+      expect(() => new ConfigService(sls, {} as any)).toThrowError("Runtime nodejs10.6.1 is not supported");
+      expect((sls.service as any as ServerlessAzureConfig).provider.functionRuntime).toBeUndefined();
+    });
+  
+    it("throws error when incomplete nodejs version in defined", () => {
+      const sls = MockFactory.createTestServerless();
+      sls.service.provider.runtime = "nodejs8";
+      expect(() => new ConfigService(sls, {} as any)).toThrowError("Invalid runtime: nodejs8");
+      expect((sls.service as any as ServerlessAzureConfig).provider.functionRuntime).toBeUndefined();
+    });
+  
+    it("throws error when unsupported nodejs version in defined", () => {
+      const sls = MockFactory.createTestServerless();
+      sls.service.provider.runtime = "nodejs5.x";
+      expect(() => new ConfigService(sls, {} as any)).toThrowError("Runtime nodejs5.x is not supported");
+      expect((sls.service as any as ServerlessAzureConfig).provider.functionRuntime).toBeUndefined();
+    });
+  
+    it("Does not throw an error when valid nodejs version is defined", () => {
+      const sls = MockFactory.createTestServerless();
+      sls.service.provider.runtime = "nodejs10.x";
+      expect(() => new ConfigService(sls, {} as any)).not.toThrow();
+      const expectedRuntime: FunctionRuntime = {
+        language: SupportedRuntimeLanguage.NODE,
+        version: "10.15.2"
+      }
+      expect((sls.service as any as ServerlessAzureConfig).provider.functionRuntime).toEqual(expectedRuntime);
+    });
+  
+    it("Does not throw an error when nodejs version with major and minor is defined", () => {
+      const sls = MockFactory.createTestServerless();
+      sls.service.provider.runtime = "nodejs6.9.x";
+      expect(() => new ConfigService(sls, {} as any)).not.toThrow();
+      const expectedRuntime: FunctionRuntime = {
+        language: SupportedRuntimeLanguage.NODE,
+        version: "6.9.5"
+      }
+      expect((sls.service as any as ServerlessAzureConfig).provider.functionRuntime).toEqual(expectedRuntime);
+    });
+  
+    it("Does not throw an error when specific nodejs version is defined", () => {
+      const sls = MockFactory.createTestServerless();
+      sls.service.provider.runtime = "nodejs10.6.0";
+      expect(() => new ConfigService(sls, {} as any)).not.toThrow();
+      const expectedRuntime: FunctionRuntime = {
+        language: SupportedRuntimeLanguage.NODE,
+        version: "10.6.0"
+      }
+      expect((sls.service as any as ServerlessAzureConfig).provider.functionRuntime).toEqual(expectedRuntime);
+    });
+  
+    it("throws an error when no nodejs version is defined", () => {
+      const sls = MockFactory.createTestServerless();
+      sls.service.provider.runtime = undefined;
+      expect(() => new ConfigService(sls, {} as any)).toThrowError("Runtime version not specified in serverless.yml");
+      expect((sls.service as any as ServerlessAzureConfig).provider.functionRuntime).toBeUndefined();
+    });
+  
+    it("does not throw an error with python3.6", () => {
+      const sls = MockFactory.createTestServerless();
+      sls.service.provider.runtime = "python3.6";
+      expect(() => new ConfigService(sls, {} as any)).not.toThrow();
+      const expectedRuntime: FunctionRuntime = {
+        language: SupportedRuntimeLanguage.PYTHON,
+        version: "3.6"
+      }
+      expect((sls.service as any as ServerlessAzureConfig).provider.functionRuntime).toEqual(expectedRuntime);
+    });
+  })
 });
diff --git a/src/shared/utils.test.ts b/src/shared/utils.test.ts
index 517c60b..23754cc 100644
--- a/src/shared/utils.test.ts
+++ b/src/shared/utils.test.ts
@@ -2,24 +2,28 @@ import path from "path";
 import Serverless from "serverless";
 import { MockFactory } from "../test/mockFactory";
 import { FunctionMetadata, Utils } from "./utils";
+import { ConfigService } from "../services/configService";
 
 describe("utils", () => {
   let sls: Serverless;
 
   beforeEach(() => {
-    const slsConfig = {
-      service: "my test service",
-      provider: "azure",
-      functions: MockFactory.createTestSlsFunctionConfig(),
-    };
-
     sls = MockFactory.createTestServerless();
-    Object.assign(sls.service, slsConfig);
+    const configService = new ConfigService(sls, {} as any);
+    Object.assign(sls.service, configService.getConfig());
   });
 
   it("resolves handler when handler code is outside function folders", () => {
-    sls.service["functions"].hello.handler = "src/handlers/hello.handler";
-    MockFactory.updateService(sls);
+    const handler = "src/handlers/hello.handler";
+    const slsFunctions = sls.service["functions"];
+    MockFactory.updateService(sls, {
+      ...slsFunctions,
+      hello: {
+        ...slsFunctions.hello,
+        handler
+      }
+    });
+    expect(sls.service["functions"].hello.handler).toEqual(handler);
 
     const functions = sls.service.getAllFunctions();
     const metadata = Utils.getFunctionMetaData(functions[0], sls);
@@ -34,8 +38,15 @@ describe("utils", () => {
   });
 
   it("resolves handler when code is in function folder", () => {
-    sls.service["functions"].hello.handler = "hello/index.handler";
-    MockFactory.updateService(sls);
+    const handler = "hello/index.handler";
+    const slsFunctions = sls.service["functions"];
+    MockFactory.updateService(sls, {
+      ...slsFunctions,
+      hello: {
+        ...slsFunctions.hello,
+        handler
+      }
+    });
 
     const functions = sls.service.getAllFunctions();
     const metadata = Utils.getFunctionMetaData(functions[0], sls);
@@ -50,8 +61,15 @@ describe("utils", () => {
   });
 
   it("resolves handler when code is at the project root", () => {
-    sls.service["functions"].hello.handler = "hello.handler";
-    MockFactory.updateService(sls);
+    const handler = "hello.handler";
+    const slsFunctions = sls.service["functions"];
+    MockFactory.updateService(sls, {
+      ...slsFunctions,
+      hello: {
+        ...slsFunctions.hello,
+        handler
+      }
+    });
 
     const functions = sls.service.getAllFunctions();
     const metadata = Utils.getFunctionMetaData(functions[0], sls);
diff --git a/src/test/mockFactory.ts b/src/test/mockFactory.ts
index 55e3321..298f9a8 100644
--- a/src/test/mockFactory.ts
+++ b/src/test/mockFactory.ts
@@ -67,8 +67,14 @@ export class MockFactory {
     } as any as Service;
   }
 
-  public static updateService(sls: Serverless) {
-    sls.service = MockFactory.createTestService(sls.service["functions"]);
+  public static updateService(serverless: Serverless, functions) {
+    Object.assign(serverless.service, {
+      ...serverless.service,
+      getAllFunctions: jest.fn(() => Object.keys(functions)),
+      getFunction: jest.fn((name: string) => functions[name]),
+      getAllFunctionsNames: jest.fn(() => Object.keys(functions)),
+      functions
+    });
   }
 
   public static createTestServerlessOptions(options?: any): Serverless.Options {