├── .gitignore
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── cleanup.js
├── index.js
├── package.json
└── templates
└── template.json
/.gitignore:
--------------------------------------------------------------------------------
1 | .vs/
2 | obj/
3 | .ntvs_analysis.*
4 | node_modules
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to Azure samples
2 |
3 | Thank you for your interest in contributing to Azure samples!
4 |
5 | ## Ways to contribute
6 |
7 | You can contribute to [Azure samples](https://azure.microsoft.com/documentation/samples/) in a few different ways:
8 |
9 | - Submit feedback on [this sample page](https://azure.microsoft.com/documentation/samples/resource-manager-node-template-deployment/) whether it was helpful or not.
10 | - Submit issues through [issue tracker](https://github.com/Azure-Samples/resource-manager-node-template-deployment/issues) on GitHub. We are actively monitoring the issues and improving our samples.
11 | - If you wish to make code changes to samples, or contribute something new, please follow the [GitHub Forks / Pull requests model](https://help.github.com/articles/fork-a-repo/): Fork the sample repo, make the change and propose it back by submitting a pull request.
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Microsoft Corporation
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | page_type: sample
3 | languages:
4 | - javascript
5 | products:
6 | - azure
7 | description: "This sample explains how to use Azure Resource Manager templates to deploy your resources to Azure
8 | using the Azure SDK for Node.js."
9 | urlFragment: resource-manager-node-template-deployment
10 | ---
11 |
12 | # Deploy an SSH Enabled VM with a Template in Node.js
13 |
14 | This sample explains how to use Azure Resource Manager templates to deploy your resources to Azure
15 | using the Azure SDK for Node.js.
16 |
17 | When deploying an application definition with a template, you can provide parameter values to customize how the
18 | resources are created. You specify values for these parameters either inline or in a parameter file.
19 |
20 | ** On this page**
21 |
22 | - [Running this sample](#run)
23 | - [What is index.js doing?](#example)
24 | - [Deploy the template](#deploy)
25 |
26 |
27 | ## Running this sample
28 |
29 | 1. If you don't already have it, [get node.js](https://nodejs.org).
30 |
31 | 2. Clone the repository.
32 |
33 | ```
34 | git clone git@github.com:Azure-Samples/resource-manager-node-template-deployment.git
35 | ```
36 |
37 | 3. Install the dependencies.
38 |
39 | ```
40 | cd resource-manager-node-template-deployment
41 | npm install
42 | ```
43 |
44 | 4. Create an Azure service principal either through
45 | [Azure CLI](https://azure.microsoft.com/documentation/articles/resource-group-authenticate-service-principal-cli/),
46 | [PowerShell](https://azure.microsoft.com/documentation/articles/resource-group-authenticate-service-principal/)
47 | or [the portal](https://azure.microsoft.com/documentation/articles/resource-group-create-service-principal-portal/).
48 |
49 | 5. Set the following environment variables using the information from the service principle that you created.
50 |
51 | ```
52 | export AZURE_SUBSCRIPTION_ID={your subscription id}
53 | export CLIENT_ID={your client id}
54 | export APPLICATION_SECRET={your client secret}
55 | export DOMAIN={your tenant id as a guid OR the domain name of your org }
56 | ```
57 |
58 | > [AZURE.NOTE] On Windows, use `set` instead of `export`.
59 |
60 | 6. Run the sample.
61 |
62 | ```
63 | // By default the script will use the ssh public key from your default ssh location
64 | node index.js [path/to/ssh_public_key]
65 | ```
66 |
67 | 7. To clean up after index.js, run the cleanup script.
68 |
69 | ```
70 | node cleanup.js
71 | ```
72 |
73 |
74 | ## What is index.js doing?
75 |
76 | The sample starts by logging in using your service principal.
77 |
78 | ```
79 | _validateEnvironmentVariables();
80 | var clientId = process.env['CLIENT_ID'];
81 | var domain = process.env['DOMAIN'];
82 | var secret = process.env['APPLICATION_SECRET'];
83 | var subscriptionId = process.env['AZURE_SUBSCRIPTION_ID'];
84 | var publicSSHKeyPath = process.argv[2] || "~/.ssh/id_rsa.pub";
85 | var resourceClient;
86 | //Sample Config
87 | var randomIds = {};
88 | var location = 'eastus';
89 | var resourceGroupName = _generateRandomId('testrg', randomIds);
90 | var deploymentName = _generateRandomId('testdeployment', randomIds);
91 | var dnsLabelPrefix = _generateRandomId('testdnslable', randomIds);
92 |
93 | ///////////////////////////////////////
94 | //Entrypoint for the sample script //
95 | ///////////////////////////////////////
96 |
97 | msRestAzure.loginWithServicePrincipalSecret(clientId, secret, domain, function (err, credentials) {
98 | if (err) return console.log(err);
99 | resourceClient = new ResourceManagementClient(credentials, subscriptionId);
100 | ```
101 |
102 | Then it creates a resource group into which the VM will be deployed.
103 |
104 | ```
105 | var groupParameters = { location: location, tags: { sampletag: 'sampleValue' } };
106 | resourceClient.resourceGroups.createOrUpdate(resourceGroupName, groupParameters, callback);
107 | ```
108 |
109 |
110 | ### Deploy the template
111 |
112 | Now, the sample loads the template and deploys it into the resource group that it just created.
113 |
114 | ```
115 | try {
116 | var templateFilePath = path.join(__dirname, "templates/template.json");
117 | var template = JSON.parse(fs.readFileSync(templateFilePath, 'utf8'));
118 | var publicSSHKey = fs.readFileSync(expandTilde(publicSSHKeyPath), 'utf8');
119 | } catch (ex) {
120 | return callback(ex);
121 | }
122 |
123 | var parameters = {
124 | "sshKeyData": {
125 | "value": publicSSHKey
126 | },
127 | "vmName": {
128 | "value": "azure-deployment-sample-vm"
129 | },
130 | "dnsLabelPrefix": {
131 | "value": dnsLabelPrefix
132 | }
133 | };
134 | var deploymentParameters = {
135 | "properties": {
136 | "parameters": parameters,
137 | "template": template,
138 | "mode": "Incremental"
139 | }
140 | };
141 |
142 | resourceClient.deployments.createOrUpdate(resourceGroupName,
143 | deploymentName,
144 | deploymentParameters,
145 | callback);
146 | ```
147 |
148 | ## More information
149 |
150 | Please refer to [Azure SDK for Node](https://github.com/Azure/azure-sdk-for-node) for more information.
151 |
--------------------------------------------------------------------------------
/cleanup.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Microsoft Corporation. All rights reserved.
3 | * Licensed under the MIT License. See License.txt in the project root for
4 | * license information.
5 | */
6 | 'use strict';
7 |
8 | var util = require('util');
9 | var msRestAzure = require('ms-rest-azure');
10 | var ResourceManagementClient = require('azure-arm-resource').ResourceManagementClient;
11 |
12 | _validateEnvironmentVariables();
13 | _validateParameters();
14 | var clientId = process.env['CLIENT_ID'];
15 | var domain = process.env['DOMAIN'];
16 | var secret = process.env['APPLICATION_SECRET'];
17 | var subscriptionId = process.env['AZURE_SUBSCRIPTION_ID'];
18 | var resourceGroupName = process.argv[2];
19 | var deploymentName = process.argv[3];
20 | var resourceClient;
21 |
22 | function deleteDeployment(callback) {
23 | console.log(util.format('\nDeleting deployment: %s'), deploymentName);
24 | return resourceClient.deployments.deleteMethod(resourceGroupName, deploymentName, callback);
25 | }
26 |
27 | function deleteResourceGroup(callback) {
28 | console.log('\nDeleting resource group: ' + resourceGroupName);
29 | return resourceClient.resourceGroups.deleteMethod(resourceGroupName, callback);
30 | }
31 |
32 | function _validateEnvironmentVariables() {
33 | var envs = [];
34 | if (!process.env['CLIENT_ID']) envs.push('CLIENT_ID');
35 | if (!process.env['DOMAIN']) envs.push('DOMAIN');
36 | if (!process.env['APPLICATION_SECRET']) envs.push('APPLICATION_SECRET');
37 | if (!process.env['AZURE_SUBSCRIPTION_ID']) envs.push('AZURE_SUBSCRIPTION_ID');
38 | if (envs.length > 0) {
39 | throw new Error(util.format('please set/export the following environment variables: %s', envs.toString()));
40 | }
41 | }
42 |
43 | function _validateParameters() {
44 | if (!process.argv[2] || !process.argv[3]) {
45 | throw new Error('Please provide the resource group and the resource name by executing the script as follows: "node cleanup.js ".');
46 | }
47 | }
48 |
49 | //Entrypoint of the cleanup script
50 | msRestAzure.loginWithServicePrincipalSecret(clientId, secret, domain, function (err, credentials) {
51 | if (err) return console.log(err);
52 | resourceClient = new ResourceManagementClient(credentials, subscriptionId);
53 | deleteDeployment(function (err, result) {
54 | if (err) return console.log('Error occured in deleting the deployment: ' + deploymentName + '\n' + util.inspect(err, { depth: null }));
55 | console.log('Successfully deleted the deployment: ' + deploymentName);
56 | console.log('\nDeleting the resource group can take few minutes, so please be patient :).');
57 | deleteResourceGroup(function (err, result) {
58 | if (err) return console.log('Error occured in deleting the resource group: ' + resourceGroupName + '\n' + util.inspect(err, { depth: null }));
59 | console.log('Successfully deleted the resourcegroup: ' + resourceGroupName);
60 | });
61 | });
62 | });
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Microsoft Corporation. All rights reserved.
3 | * Licensed under the MIT License. See License.txt in the project root for
4 | * license information.
5 | */
6 | 'use strict';
7 |
8 | var fs = require('fs');
9 | var path = require('path');
10 | var util = require('util');
11 | var async = require('async');
12 | var expandTilde = require('expand-tilde');
13 | var msRestAzure = require('ms-rest-azure');
14 | var ResourceManagementClient = require('azure-arm-resource').ResourceManagementClient;
15 |
16 | _validateEnvironmentVariables();
17 | var clientId = process.env['CLIENT_ID'];
18 | var domain = process.env['DOMAIN'];
19 | var secret = process.env['APPLICATION_SECRET'];
20 | var subscriptionId = process.env['AZURE_SUBSCRIPTION_ID'];
21 | var publicSSHKeyPath = process.argv[2] || "~/.ssh/id_rsa.pub";
22 | var resourceClient;
23 | //Sample Config
24 | var randomIds = {};
25 | var location = 'eastus';
26 | var resourceGroupName = _generateRandomId('testrg', randomIds);
27 | var deploymentName = _generateRandomId('testdeployment', randomIds);
28 | var dnsLabelPrefix = _generateRandomId('testdnslable', randomIds);
29 |
30 | ///////////////////////////////////////
31 | //Entrypoint for the sample script //
32 | ///////////////////////////////////////
33 |
34 | msRestAzure.loginWithServicePrincipalSecret(clientId, secret, domain, function (err, credentials) {
35 | if (err) return console.log(err);
36 | resourceClient = new ResourceManagementClient(credentials, subscriptionId);
37 | // Work flow of this sample:
38 | // 1. create a resource group
39 | // 2. load a VM template and deploy it.
40 | // 3. delete deployed resource(optional)
41 | // 4. delete a resource group(optional)
42 |
43 | async.series([
44 | function (callback) {
45 | //Task 1
46 | createResourceGroup(function (err, result, request, response) {
47 | if (err) {
48 | return callback(err);
49 | }
50 | callback(null, result);
51 | });
52 | },
53 | function (callback) {
54 | //Task 2
55 | loadTemplateAndDeploy(function (err, result, request, response) {
56 | if (err) {
57 | return callback(err);
58 | }
59 | console.log(util.format('\nDeployed template %s : \n%s', deploymentName, util.inspect(result, { depth: null })));
60 | callback(null, result);
61 | });
62 | }
63 | ],
64 | // Once above operations finish, cleanup and exit.
65 | function (err, results) {
66 | if (err) {
67 | console.log(util.format('\n??????Error occurred in one of the operations.\n%s',
68 | util.inspect(err, { depth: null })));
69 | } else {
70 | //console.log(util.format('\n######You can browse the website at: https://%s.', results[4].enabledHostNames[0]));
71 | }
72 | console.log('\n###### Exit ######');
73 | console.log(util.format('Please execute the following script for cleanup:\nnode cleanup.js %s', resourceGroupName, deploymentName));
74 | process.exit();
75 | });
76 | });
77 |
78 |
79 | // Helper functions
80 | function createResourceGroup(callback) {
81 | var groupParameters = { location: location, tags: { sampletag: 'sampleValue' } };
82 | console.log('\nCreating resource group: ' + resourceGroupName);
83 | return resourceClient.resourceGroups.createOrUpdate(resourceGroupName, groupParameters, callback);
84 | }
85 |
86 | function loadTemplateAndDeploy(callback) {
87 | try {
88 | var templateFilePath = path.join(__dirname, "templates/template.json");
89 | var template = JSON.parse(fs.readFileSync(templateFilePath, 'utf8'));
90 | var publicSSHKey = fs.readFileSync(expandTilde(publicSSHKeyPath), 'utf8');
91 | } catch (ex) {
92 | return callback(ex);
93 | }
94 |
95 | console.log('\nLoaded template from template.json');
96 | var parameters = {
97 | "sshKeyData": {
98 | "value": publicSSHKey
99 | },
100 | "vmName": {
101 | "value": "azure-deployment-sample-vm"
102 | },
103 | "dnsLabelPrefix": {
104 | "value": dnsLabelPrefix
105 | }
106 | };
107 | var deploymentParameters = {
108 | "properties": {
109 | "parameters": parameters,
110 | "template": template,
111 | "mode": "Incremental"
112 | }
113 | };
114 |
115 | console.log(util.format('\nDeploying template %s : \n%s', deploymentName, util.inspect(template, { depth: null })));
116 | return resourceClient.deployments.createOrUpdate(resourceGroupName,
117 | deploymentName,
118 | deploymentParameters,
119 | callback);
120 | }
121 |
122 | function deleteDeployment(callback) {
123 | console.log(util.format('\nDeleting deployment %s in resource group %s'),
124 | deploymentName, resourceGroupName);
125 | return resourceClient.deployments.deleteMethod(resourceGroupName, deploymentName, callback);
126 | }
127 |
128 | function deleteResourceGroup(callback) {
129 | console.log('\nDeleting resource group: ' + resourceGroupName);
130 | return resourceClient.resourceGroups.deleteMethod(resourceGroupName, callback);
131 | }
132 |
133 | function _validateEnvironmentVariables() {
134 | var envs = [];
135 | if (!process.env['CLIENT_ID']) envs.push('CLIENT_ID');
136 | if (!process.env['DOMAIN']) envs.push('DOMAIN');
137 | if (!process.env['APPLICATION_SECRET']) envs.push('APPLICATION_SECRET');
138 | if (!process.env['AZURE_SUBSCRIPTION_ID']) envs.push('AZURE_SUBSCRIPTION_ID');
139 | if (envs.length > 0) {
140 | throw new Error(util.format('please set/export the following environment variables: %s', envs.toString()));
141 | }
142 | }
143 |
144 | function _generateRandomId(prefix, exsitIds) {
145 | var newNumber;
146 | while (true) {
147 | newNumber = prefix + Math.floor(Math.random() * 10000);
148 | if (!exsitIds || !(newNumber in exsitIds)) {
149 | break;
150 | }
151 | }
152 | return newNumber;
153 | }
154 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "resource-manager-node-template-deployment",
3 | "author": "Microsoft Corporation",
4 | "contributors": [
5 | "Chen, Hao ",
6 | "Zavery, Amar "
7 | ],
8 | "version": "0.1.0",
9 | "description": "An example illustrating how to use node.js to deploy an Azure Resource Manager Template.",
10 | "tags": [
11 | "azure",
12 | "sdk"
13 | ],
14 | "keywords": [
15 | "node",
16 | "azure"
17 | ],
18 | "main": "./index.js",
19 | "license": "MIT",
20 | "dependencies": {
21 | "async": "0.2.7",
22 | "azure-arm-resource": "^1.4.4-preview",
23 | "expand-tilde": "^1.2.2",
24 | "ms-rest-azure": "^1.14.3"
25 | },
26 | "homepage": "https://github.com/Azure-Samples/resource-manager-node-template-deployment",
27 | "repository": {
28 | "type": "git",
29 | "url": "https://github.com/Azure-Samples/resource-manager-node-template-deployment"
30 | },
31 | "bugs": {
32 | "url": "https://github.com/azure/azures-sdk-for-node/issues"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/templates/template.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://schema.management.azure.com/schemas/2014-04-01-preview/deploymentTemplate.json",
3 | "contentVersion": "1.0.0.0",
4 | "parameters": {
5 | "adminUserName": {
6 | "type": "string",
7 | "defaultValue": "azureSample",
8 | "metadata": {
9 | "description": "User name for the Virtual Machine."
10 | }
11 | },
12 | "sshKeyData": {
13 | "type": "string",
14 | "metadata": {
15 | "description": "SSH rsa public key file as a string."
16 | }
17 | },
18 | "dnsLabelPrefix": {
19 | "type": "string",
20 | "metadata": {
21 | "description": "Unique DNS Name for the Public IP used to access the Virtual Machine."
22 | }
23 | },
24 | "vmSize": {
25 | "type": "string",
26 | "defaultValue": "Standard_D1",
27 | "metadata": {
28 | "description": "Size of the VM"
29 | }
30 | },
31 | "vmName": {
32 | "type": "string",
33 | "metadata": {
34 | "description": "Name of the VM"
35 | }
36 | },
37 | "imagePublisher": {
38 | "type": "string",
39 | "defaultValue": "canonical",
40 | "metadata": {
41 | "description": "Name of the image publisher"
42 | }
43 | },
44 | "imageOffer": {
45 | "type": "string",
46 | "defaultValue": "ubuntuserver",
47 | "metadata": {
48 | "description": "Name of the image offer"
49 | }
50 | },
51 | "imageSku": {
52 | "type": "string",
53 | "defaultValue": "16.04-DAILY-LTS",
54 | "metadata": {
55 | "description": "Name of the image sku"
56 | }
57 | },
58 | "imageVersion": {
59 | "type": "string",
60 | "defaultValue": "latest",
61 | "metadata": {
62 | "description": "Name of the image sku"
63 | }
64 | },
65 | "subnetName": {
66 | "type": "string",
67 | "defaultValue": "azsample-subnet",
68 | "metadata": {
69 | "description": "Name of the subnet"
70 | }
71 | },
72 | "virtualNetworkName": {
73 | "type": "string",
74 | "defaultValue": "azsampleVNET",
75 | "metadata": {
76 | "description": "Name of the virtual network"
77 | }
78 | }
79 | },
80 | "variables": {
81 | "storageAccountName": "[concat(uniquestring(resourceGroup().id), 'azsample')]",
82 | "location": "[resourceGroup().location]",
83 | "osDiskName": "osDisk1",
84 | "addressPrefix": "10.0.0.0/16",
85 | "subnetPrefix": "10.0.0.0/24",
86 | "vmStorageAccountContainerName": "azsample-vhds",
87 | "nicName": "[concat(parameters('vmName'), '-azsampleNIC')]",
88 | "publicIPAddressName": "[concat(parameters('vmName'), '-azsamplePublicIP')]",
89 | "publicIPAddressType": "Dynamic",
90 | "storageAccountType": "Standard_LRS",
91 | "networkSecurityGroupName": "[concat(parameters('vmName'), '-azsampleNSG')]",
92 | "sshKeyPath": "[concat('/home/',parameters('adminUsername'),'/.ssh/authorized_keys')]",
93 | "vnetID": "[resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworkName'))]",
94 | "subnetRef": "[concat(variables('vnetID'),'/subnets/',parameters('subnetName'))]",
95 | "apiVersion": "2015-06-15"
96 | },
97 | "resources": [
98 | {
99 | "type": "Microsoft.Storage/storageAccounts",
100 | "name": "[variables('storageAccountName')]",
101 | "apiVersion": "[variables('apiVersion')]",
102 | "location": "[variables('location')]",
103 | "properties": {
104 | "accountType": "[variables('storageAccountType')]"
105 | }
106 | },
107 | {
108 | "apiVersion": "[variables('apiVersion')]",
109 | "type": "Microsoft.Network/networkSecurityGroups",
110 | "name": "[variables('networkSecurityGroupName')]",
111 | "location": "[variables('location')]",
112 | "properties": {
113 | "securityRules": [
114 | {
115 | "name": "ssh_rule",
116 | "properties": {
117 | "description": "Locks inbound down to ssh default port 22.",
118 | "protocol": "Tcp",
119 | "sourcePortRange": "*",
120 | "destinationPortRange": "22",
121 | "sourceAddressPrefix": "*",
122 | "destinationAddressPrefix": "*",
123 | "access": "Allow",
124 | "priority": 123,
125 | "direction": "Inbound"
126 | }
127 | }
128 | ]
129 | }
130 | },
131 | {
132 | "apiVersion": "[variables('apiVersion')]",
133 | "type": "Microsoft.Network/publicIPAddresses",
134 | "name": "[variables('publicIPAddressName')]",
135 | "location": "[variables('location')]",
136 | "properties": {
137 | "publicIPAllocationMethod": "[variables('publicIPAddressType')]",
138 | "dnsSettings": {
139 | "domainNameLabel": "[parameters('dnsLabelPrefix')]"
140 | }
141 | }
142 | },
143 | {
144 | "apiVersion": "[variables('apiVersion')]",
145 | "type": "Microsoft.Network/virtualNetworks",
146 | "name": "[parameters('virtualNetworkName')]",
147 | "location": "[variables('location')]",
148 | "dependsOn": [
149 | "[concat('Microsoft.Network/networkSecurityGroups/', variables('networkSecurityGroupName'))]"
150 | ],
151 | "properties": {
152 | "addressSpace": {
153 | "addressPrefixes": [
154 | "[variables('addressPrefix')]"
155 | ]
156 | },
157 | "subnets": [
158 | {
159 | "name": "[parameters('subnetName')]",
160 | "properties": {
161 | "addressPrefix": "[variables('subnetPrefix')]",
162 | "networkSecurityGroup": {
163 | "id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]"
164 | }
165 | }
166 | }
167 | ]
168 | }
169 | },
170 | {
171 | "apiVersion": "[variables('apiVersion')]",
172 | "type": "Microsoft.Network/networkInterfaces",
173 | "name": "[variables('nicName')]",
174 | "location": "[variables('location')]",
175 | "dependsOn": [
176 | "[concat('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]",
177 | "[concat('Microsoft.Network/virtualNetworks/', parameters('virtualNetworkName'))]"
178 | ],
179 | "properties": {
180 | "ipConfigurations": [
181 | {
182 | "name": "ipconfig1",
183 | "properties": {
184 | "privateIPAllocationMethod": "Dynamic",
185 | "publicIPAddress": {
186 | "id": "[resourceId('Microsoft.Network/publicIPAddresses', variables('publicIPAddressName'))]"
187 | },
188 | "subnet": {
189 | "id": "[variables('subnetRef')]"
190 | }
191 | }
192 | }
193 | ]
194 | }
195 | },
196 | {
197 | "apiVersion": "[variables('apiVersion')]",
198 | "type": "Microsoft.Compute/virtualMachines",
199 | "name": "[parameters('vmName')]",
200 | "location": "[variables('location')]",
201 | "dependsOn": [
202 | "[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName'))]",
203 | "[concat('Microsoft.Network/networkInterfaces/', variables('nicName'))]"
204 | ],
205 | "properties": {
206 | "hardwareProfile": {
207 | "vmSize": "[parameters('vmSize')]"
208 | },
209 | "osProfile": {
210 | "computerName": "[parameters('vmName')]",
211 | "adminUsername": "[parameters('adminUsername')]",
212 | "linuxConfiguration": {
213 | "disablePasswordAuthentication": "true",
214 | "ssh": {
215 | "publicKeys": [
216 | {
217 | "path": "[variables('sshKeyPath')]",
218 | "keyData": "[parameters('sshKeyData')]"
219 | }
220 | ]
221 | }
222 | }
223 | },
224 | "storageProfile": {
225 | "imageReference": {
226 | "publisher": "[parameters('imagePublisher')]",
227 | "offer": "[parameters('imageOffer')]",
228 | "sku": "[parameters('imageSku')]",
229 | "version": "latest"
230 | },
231 | "osDisk": {
232 | "name": "osdisk",
233 | "vhd": {
234 | "uri": "[concat('http://',variables('storageAccountName'),'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/', variables('osDiskName'),'.vhd')]"
235 | },
236 | "caching": "ReadWrite",
237 | "createOption": "FromImage"
238 | }
239 | },
240 | "networkProfile": {
241 | "networkInterfaces": [
242 | {
243 | "id": "[resourceId('Microsoft.Network/networkInterfaces', variables('nicName'))]"
244 | }
245 | ]
246 | },
247 | "diagnosticsProfile": {
248 | "bootDiagnostics": {
249 | "enabled": "true",
250 | "storageUri": "[concat('http://',variables('storageAccountName'),'.blob.core.windows.net')]"
251 | }
252 | }
253 | }
254 | }
255 | ]
256 | }
257 |
--------------------------------------------------------------------------------