Commit 0985a3e5 authored by Brian Moore's avatar Brian Moore
Browse files

updates for bp doc to include new staging practices

parent 8eb5edba
......@@ -16,20 +16,22 @@ To make sure your template is added to Azure.com index, please follow these guid
## Files, folders and naming conventions
1. Every deployment template and its associated files must be contained in its own **folder**. Name this folder something that describes what your template does. Usually this naming pattern looks like **appName-osName** or **level-platformCapability** (e.g. 101-vm-user-image)
+ **Required** Numbering should start at 101. 100 is reserved for things that need to be at the top.
+ **Required** - Numbering should start at 101. 100 is reserved for things that need to be at the top.
+ **Protip** - Try to keep the name of your template folder short so that it fits inside the Github folder name column width.
2. Github uses ASCII for ordering files and folder. For consistent ordering **create all files and folders in lowercase**. The only **exception** to this guideline is the **README.md**, that should be in the format **UPPERCASE.lowercase**.
3. Include a **README.md** file that explains how the template works.
1. Github uses ASCII for ordering files and folder. For consistent ordering **create all files and folders in lowercase**. The only **exception** to this guideline is the **README.md**, that should be in the format **UPPERCASE.lowercase**.
1. Include a **README.md** file that explains how the template works.
+ Guidelines on the README.md file below.
4. The deployment template file must be named **azuredeploy.json**.
5. There should be a parameters file named **azuredeploy.parameters.json**.
1. The deployment template file must be named **azuredeploy.json**.
1. There should be a parameters file named **azuredeploy.parameters.json**.
+ Please fill out the values for the parameters according to rules defined in the template (allowed values etc.), For parameters without rules, a simple "changeme" will do as the acomghbot only checks for syntactic correctness using the ARM Validate Template [API](https://msdn.microsoft.com/en-us/library/azure/dn790547.aspx).
6. The template folder must contain a **metadata.json** file to allow the template to be indexed on [Azure.com](http://azure.microsoft.com/).
1. The template folder must contain a **metadata.json** file to allow the template to be indexed on [Azure.com](http://azure.microsoft.com/).
+ Guidelines on the metadata.json file below.
7. The custom scripts that are needed for successful template execution must be placed in a folder called **scripts**.
8. Linked templates must be placed in a folder called **nested**.
9. Images used in the README.md must be placed in a folder called **images**.
10. Any resources that need to be setup outside the template should be named prefixed with existing (e.g. existingVNET, existingDiagnosticsStorageAccount).
1. The custom scripts that are needed for successful template execution must be placed in a folder called **scripts**.
1. Linked templates must be placed in a folder called **nestedtemplates**.
1. DSC configuration scripts and packages must be placed in a folder called **dsc**.
1. Images used in the README.md must be placed in a folder called **images**.
1. Any resources that need to be setup outside the template should be named prefixed with existing (e.g. existingVNET, existingDiagnosticsStorageAccount) and remain in the same folder as **azuredeploy.json**.
1. The template can be deployed using both the **Deploy-AzureResourceGroup.ps1** script and the **azure-group-deploy.sh**. This includes staging any artifacts required for the deployment into Azure storage as an alternative to the raw github location (the scripts will perform this staging).
![alt text](/1-CONTRIBUTION-GUIDE/images/namingConvention.png "Files, folders and naming conventions")
......
......@@ -18,13 +18,12 @@ You are currently reading the best practices.
The following guidelines are relevant to the main deployment template and nested templates (if used).
1. Template parameters should follow **camelCasing**.
2. Minimize parameters whenever possible, this allows for a good "hello world" experience where the user doesn't have to answer a number of questions to complete a deployment. If you can use a variable or a literal, do so. Users who want to parameterize something will likely have the skills to do so. Only provide parameters for:
+ Things that are globally unique (e.g. website name). These are usually endpoints that the user may need to be aware of, however in many cases a unique name can be generated automatically.
1. Minimize parameters whenever possible, this allows for a good "hello world" experience where the user doesn't have to answer a number of questions to complete a deployment. If you can use a variable or a literal, do so. Users who want to parameterize something will likely have the skills to do so. Only provide parameters for:
+ Things that are globally unique (e.g. website name). These are usually endpoints that the user may need to be aware of, however in many cases a unique name can be generated automatically by using the [uniqueString()](https://azure.microsoft.com/en-us/documentation/articles/resource-group-template-functions/#uniquestring) template language function.
+ Other things a user must know to complete a workflow (e.g. admin user name on a vm)
+ Secrets (e.g. admin password on a vm)
+ Share parameters whenever possible - e.g. the location parameter should be shared among resources that must or are likely to be in the same location
+ If you must include a parameter, define a defaultValue, unless the parameter is used for a password.
3. Every parameter in the template should have the **lower-case description** tag specified using the metadata property. This looks like below
1. Every parameter in the template should have the **lower-case description** tag specified using the metadata property. This looks like below
```
"parameters": {
......@@ -37,7 +36,7 @@ The following guidelines are relevant to the main deployment template and nested
}
```
4. Do not use a parameter to specify the **location**. Use the location property of the resourceGroup instead. By using the **resourceGroup().location** expression for all your resources, the resources in the template will automatically be deployed in the same location as the resource group.
1. Do not use a parameter to specify the **location**. Use the location property of the resourceGroup instead. By using the **resourceGroup().location** expression for all your resources, the resources in the template will automatically be deployed in the same location as the resource group.
```
"resources": [
......@@ -53,27 +52,38 @@ The following guidelines are relevant to the main deployment template and nested
}
]
```
+ If you must use a location parameter, share parameters whenever possible - e.g. the location parameter should be shared among resources that must or are likely to be in the same location.
5. Name **variables** using this scheme **templateScenarioResourceName** (e.g. simpleLinuxVMVNET, userRoutesNSG, elasticsearchPublicIP etc.) that describe the scenario rather. This ensures when a user browses all the resources in the Portal there aren't a bunch of resources with the same name (e.g. myVNET, myPublicIP, myNSG)
6. For many resources with a resource group, a name is not often relevant and using something like "storageAccount" may be acceptable. You can also use variables for the name of a resource. Use **displayName** tags for a "friendly" name in the JSON outline view. This should ideally match the name property value or property name.
1. Name **variables** using this scheme **templateScenarioResourceName** (e.g. simpleLinuxVMVNET, userRoutesNSG, elasticsearchPublicIP etc.) that describe the scenario rather. This ensures when a user browses all the resources in the Portal there aren't a bunch of resources with the same name (e.g. myVNET, myPublicIP, myNSG)
1. Do not create a parameter for a **storage account name**. Storage account names need to be lower case and can't contain hyphens (-) in addition to other domain name restrictions. A storage account has a limit of 24 characters. They also need to be globally unique. To prevent any validation issue configure a variables (using the expression **uniqueString** and a static value **storage**). Storage accounts with a common prefix (uniquestring) will not get clustered on the same racks.
```
"variables": {
"storageAccountName": "[concat(uniquestring(resourceGroup().id),'storage')]"
}
```
Note: Templates should consider storage accounts throughput constraints and deploy across multiple storage accounts where necessary. Templates should distribute virtual machine disks across multiple storage accounts to avoid platform throttling.
1. For many resources with a resource group, a name is not often relevant and using something a hard coded string "availabilitySet" may be acceptable. You can also use variables for the name of a resource and generate names for resources with globally unique names. Use **displayName** tags for a "friendly" name in the JSON outline view. This should ideally match the name property value or property name.
```
"resources": [
{
"name": "[variables('storageAccountName')]",
"type": "Microsoft.Storage/storageAccounts",
"name": "availabilitySet",
"type": "Microsoft.Compute/availabilitySets",
"apiVersion": "2015-06-15",
"location": "[resourceGroup().location]",
"comments": "This storage account is used to store the VM disks",
"tags": { "displayName": "storageAccount" },
"tags": { "displayName": "appTierAS" },
"properties": {
"accountType": "Standard_GRS"
...
}
}
]
```
7. Specifying a lower-case **comments** property for each resource in the template, helps other contributors to understand the purpose of the resource.
1. Specifying a lower-case **comments** property for each resource in the template, helps other contributors to understand the purpose of the resource.
```
"resources": [
......@@ -90,17 +100,7 @@ The following guidelines are relevant to the main deployment template and nested
]
```
8. Do not create a parameter for a **storage account name**. Storage account names need to be lower case and can't contain hyphens (-) in addition to other domain name restrictions. A storage account has a limit of 24 characters. They also need to be globally unique. To prevent any validation issue configure a variables (using the expression **uniqueString** and a static value **storage**). Storage accounts with a common prefix (uniquestring) will not get clustered on the same racks.
```
"variables": {
"storageAccountName": "[concat(uniquestring(resourceGroup().id),'storage')]"
}
```
Note: Templates should consider storage accounts throughput constraints and deploy across multiple storage accounts where necessary. Templates should distribute virtual machine disks across multiple storage accounts to avoid platform throttling.
9. If you use a **public endpoint** in your template (e.g. blob storage public endpoint), **do not hardcode** the namespace. Use the **reference** function to retrieve the namespace dynamically. This allows you to deploy the template to different public namespace environments, without the requirement to change the endpoint in the template manually. Use the following reference to specify the osDisk. Define a variable for the storageAccountName (as specified in the previous example), a variable for the vmStorageAccountContainerName and a variable for the OSDiskName. Set the apiVersion to the same version you are using for the storageAccount in your template.
1. If you use a **public endpoint** in your template (e.g. blob storage public endpoint), **do not hardcode** the namespace. Use the **reference** function to retrieve the namespace dynamically. This allows you to deploy the template to different public namespace environments, without the requirement to change the endpoint in the template manually. Use the following reference to specify the osDisk. Define a variable for the storageAccountName (as specified in the previous example), a variable for the vmStorageAccountContainerName and a variable for the OSDiskName. Set the apiVersion to the same version you are using for the storageAccount in your template.
```
"osDisk": {"name": "osdisk","vhd": {"uri": "[concat(reference(concat('Microsoft.Storage/storageAccounts/',
......@@ -214,15 +214,80 @@ It is obvious to create a single deployment template for deploying a single reso
* Create a nested templates deployment for a multitier application
* Use nested templates for conditional deployment
### Samples that contain extra artifacts (Custom Scripts, nested templates, etc)
When samples contain scripts, templates or other artifacts that need to be made available during deployment, using the standard parameters for staging those artifacts will enable command line deployment with the scripts provided at the root of the repo. This allows the template to be used in a variety of workflows without changing the templates or default parameters and the artifacts will be staged to a private location, rather than the public github uri.
First, define two standard parameters:
* _artifactsLocation - this is the base uri where all artifacts for the deployment will be staged. The default value should be the samples folder so that the sample can be easily deployed in scenarios where a private location is not required.
* _artifactsocationSasToken - this is the sasToken required to access _artifactsLocation. The default value should be "?" for scenarios where the _artifactsLocation is not secured, for example, the raw github URI.
```
"parameters": {
"_artifactsLocation": {
"type": "string",
"metadata": {
"description": "The base URI where artifacts required by this template are located. When the template is deployed using the accompanying scripts, a private location in the subscription will be used and this value will be automatically generated."
},
"defaultValue": "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/201-vm-custom-script-windows/"
},
"_artifactsLocationSasToken": {
"type": "securestring",
"metadata": {
"description": "The sasToken required to access _artifactsLocation. When the template is deployed using the accompanying scripts, a sasToken will be automatically generated."
},
"defaultValue": "?"
}
},
```
In this example, the custom script extension can be authored using a common pattern that can be applied to all resources that need staged artifacts as well as applied to all samples.
```
"properties": {
"publisher": "Microsoft.Compute",
"type": "CustomScriptExtension",
"typeHandlerVersion": "1.8",
"autoUpgradeMinorVersion": true,
"settings": {
"fileUris": [
"[concat(parameters('_artifactsLocation'), '/', variables('ScriptFolder'), '/', variables('ScriptFileName'), parameters('_artifactsLocationSasToken'))]"
],
"commandToExecute": "[concat('powershell -ExecutionPolicy Unrestricted -File ', variables('ScriptFolder'), '/', variables('ScriptFileName'))]"
}
}
```
### Nested templates
Define a complex object variable in the azuredeploy.json that contains the absolute Uri of the repository folder. Add an relative path entry in that variable for each nested template you are using in your deployment. This gives quick overview of the nested templates referenced in your resources. Store all nested templates in the nested folder. The templatelink in the resource combines the absolute Uri with the relative path. When you fork a repository you only need to update the absolute Uri in the azuredeploy.json file.
Nested templates that link to templates within the same sample can be authoried using the same pattern described above for scripts.
```
"resources": [
{
"name": "shared",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2015-01-01",
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[concat(parameters('_artifactsLocation'), '/', variables('nestedTemplateFolder'), '/', variables('nestedTemplateFileName'), parameters('_artifactsLocationSasToken'))]",
"contentVersion": "1.0.0.0"
}
}
}
]
```
When authoring a template that references another sample, define a complex object variable in the azuredeploy.json that contains the absolute Uri of the repository folder. Add an relative path entry in that variable for each nested template you are using in your deployment. This gives quick overview of the nested templates referenced in your resources. Store all nested templates in the **nestedtemplates** folder. The templatelink in the resource combines the absolute Uri with the relative path. When you fork a repository you only need to update the absolute Uri in the azuredeploy.json file.
```
"variables": {
"template": {
"base": "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/101-create-availability-set",
"shared": "nested/sharedresources.json"
"shared": "nestedtemplates/sharedresources.json"
}
},
"resources": [
......@@ -241,6 +306,10 @@ Define a complex object variable in the azuredeploy.json that contains the absol
]
```
_**Note:** Using this approach will still require pulling the dependent artifact from the raw github location. The sample scripts do not privately stage artifacts from adjacent solutions. In practice, it is expected that this technique would be rarely used because the main template being deployed has a dependency on a shared template that may have a different lifecycle, resulting in unexpected changes in the configuration. In a real-world scenario, all the templates that make up the deployment should be under the same span of control and could be staged together. Simply put share the same parent. This will work for a shared environment of the repo, but a best practice would be to refactor these samples to ensure a proper configuration is maintained._
It is possible to deploy a nested template based on parameter input. The parameter input is used to concatenate the relative path to a nested template. Based on the user input a different template is deployed. This enabled a conditional nested template deployment. The paramater is used to define the name of the template. Ensure the allowedValues of the input paramater match the names of the nested templates.
### Nested templates design for more advanced scenarios
......@@ -256,4 +325,4 @@ For this guidance a deployment of a SharePoint farm is used as an example. The S
![alt text](images/nestedTemplateDesign.png "Nested templates design")
The **main template** is stored in the **root** of the folder, the **other templates** are stored in the **nested** folder. The scripts are stored in the **scripts** folder.
\ No newline at end of file
The **main template** is stored in the **root** of the folder, the **other templates** are stored in the **nestedtemplates** folder. The scripts are stored in the **scripts** folder.
\ No newline at end of file
......@@ -7,6 +7,24 @@
<img src="http://armviz.io/visualizebutton.png"/>
</a>
To deploy this template using the scripts from the root of this repo: (change the folder name below to match the folder name for this sample)
```PowerShell
.\Deploy-AzureResourceGroup.ps1 -ResourceGroupLocation 'eastus' -ArtifactsStagingDirectory '[foldername]'
```
```bash
azure-group-deploy.sh -a [foldername] -l eastus -u
```
If your sample has artifacts that need to be "staged" for deployment (Configuration Scripts, Nested Templates, DSC Packages) then set the upload switch on the command.
You can optionally specify a storage account to use, if so the storage account must already exist within the subscription. If you don't want to specify a storage account
one will be created by the script (think of this as "temp" storage for AzureRM) and reused by subsequent deployments.
```PowerShell
.\Deploy-AzureResourceGroup.ps1 -ResourceGroupLocation 'eastus' -ArtifactsStagingDirectory '100-STARTER-TEMPLATE-with-VALIDATION' -UploadArtifacts
```
```bash
azure-group-deploy.sh -a 100-STARTER-TEMPLATE-with-VALIDATION -l eastus -u
```
This template deploys a **solution name**. The **solution name** is a **description**
......@@ -45,7 +63,7 @@ Decscription of the prerequistes for the deployment
## Deployment steps
You can click the "deploy to Azure" button at the beginning of this document.
You can click the "deploy to Azure" button at the beginning of this document or follow the instructions for command line deployment using the scripts in the root of this repo.
## Usage
......
......@@ -16,20 +16,22 @@ To make sure your template is added to Azure.com index, please follow these guid
## Files, folders and naming conventions
1. Every deployment template and its associated files must be contained in its own **folder**. Name this folder something that describes what your template does. Usually this naming pattern looks like **appName-osName** or **level-platformCapability** (e.g. 101-vm-user-image)
+ **Required** Numbering should start at 101. 100 is reserved for things that need to be at the top.
+ **Required** - Numbering should start at 101. 100 is reserved for things that need to be at the top.
+ **Protip** - Try to keep the name of your template folder short so that it fits inside the Github folder name column width.
2. Github uses ASCII for ordering files and folder. For consistent ordering **create all files and folders in lowercase**. The only **exception** to this guideline is the **README.md**, that should be in the format **UPPERCASE.lowercase**.
3. Include a **README.md** file that explains how the template works.
1. Github uses ASCII for ordering files and folder. For consistent ordering **create all files and folders in lowercase**. The only **exception** to this guideline is the **README.md**, that should be in the format **UPPERCASE.lowercase**.
1. Include a **README.md** file that explains how the template works.
+ Guidelines on the README.md file below.
4. The deployment template file must be named **azuredeploy.json**.
5. There should be a parameters file named **azuredeploy.parameters.json**.
1. The deployment template file must be named **azuredeploy.json**.
1. There should be a parameters file named **azuredeploy.parameters.json**.
+ Please fill out the values for the parameters according to rules defined in the template (allowed values etc.), For parameters without rules, a simple "changeme" will do as the acomghbot only checks for syntactic correctness using the ARM Validate Template [API](https://msdn.microsoft.com/en-us/library/azure/dn790547.aspx).
6. The template folder must contain a **metadata.json** file to allow the template to be indexed on [Azure.com](http://azure.microsoft.com/).
1. The template folder must contain a **metadata.json** file to allow the template to be indexed on [Azure.com](http://azure.microsoft.com/).
+ Guidelines on the metadata.json file below.
7. The custom scripts that are needed for successful template execution must be placed in a folder called **scripts**.
8. Linked templates must be placed in a folder called **nested**.
9. Images used in the README.md must be placed in a folder called **images**.
10. Any resources that need to be setup outside the template should be named prefixed with existing (e.g. existingVNET, existingDiagnosticsStorageAccount).
1. The custom scripts that are needed for successful template execution must be placed in a folder called **scripts**.
1. Linked templates must be placed in a folder called **nestedtemplates**.
1. DSC configuration scripts and packages must be placed in a folder called **dsc**.
1. Images used in the README.md must be placed in a folder called **images**.
1. Any resources that need to be setup outside the template should be named prefixed with existing (e.g. existingVNET, existingDiagnosticsStorageAccount) and remain in the same folder as **azuredeploy.json**.
1. The template can be deployed using both the **Deploy-AzureResourceGroup.ps1** script and the **azure-group-deploy.sh**. This includes staging any artifacts required for the deployment into Azure storage as an alternative to the raw github location (the scripts will perform this staging).
![alt text](/1-CONTRIBUTION-GUIDE/images/namingConvention.png "Files, folders and naming conventions")
......@@ -51,7 +53,7 @@ You can download a [**sample README.md**](/1-CONTRIBUTION-GUIDE/sample-README.md
## metadata.json
A valid metedata.json must adhere to the following structure
A valid metadata.json must adhere to the following structure
```
{
......@@ -107,7 +109,7 @@ acomghbot is a bot designed to enforce the above rules and check the syntactic c
## Travis CI
We are in the process of activating automated template validation through Travis CI. These builds can be accessed by clicking the 'Details' link at the bottom of the pull-request dialog. This process will ensure that your template conforms to all the rules mentioned above and will also deploy your template to our test azure subscription.
We have automated template validation through Travis CI. These builds can be accessed by clicking the 'Details' link at the bottom of the pull-request dialog. This process will ensure that your template conforms to all the rules mentioned above and will also deploy your template to our test azure subscription.
### Parameters File Placeholders
......@@ -232,4 +234,4 @@ Server Error:{
}
}
}
```
\ No newline at end of file
```
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment