RFP

Blogs

Published on Tuesday, December 22, 2015

Automated provisioning

Automated provisioning

Automated provisioning

According to Enterprise Management Associates’ (EMA) 2014 study on the software-defined data center, 47 percent of enterprise IT teams take from one week to over a month to provide infrastructure resources to developers and testers. There is an upcoming trend of answers to this problem which can auto provision resources in minutes. Check out the two flavors of automated provisioning. First one use Powershell and second uses Chef. Both are simple and straightforward to implement for DevTest and DevOps scenarios.

PowerShell

Azure PowerShell is a scripting module that programmatic way to provision and configure cloud services, virtual machines, virtual networks, and web apps. We developed a PowerShell script to provision simple two tier web application on Azure.

We've developed a PowerShell script to provision Azure resources. To run this script, you need the following:

  • An Azure account
  • The Azure SDK, downloadable from Microsoft
  • A web deploy package of your Visual Studio solution, packaged as a zip file
Before running the script you need to run the command “Add-AzureAccount” from your Azure powershell command line and login using the email address and password for you Azure subscription.
PS C:\Users\iLink\Documents\Azure DevOps> Add-AzureAccount
handheld

 

The script reads inputs from a json file. You pass the path to the input file as a parameter called $Configuration. This is not a formal resource template, merely an object with inputs. The json is given below:

{ 
    location: "West US",
    resourceGroup: {
			name: "ilinkresourcegroup1126"
		   },

    server: {
		name: "ilinkserver1126",
		admin: "peterharnish",
		password: "********"
	     },
    database: {
		name: "ilinksample1126_db",
		edition: "Basic"
	      },
    appServicePlan: {
			name: "ilinkappserviceplan1126",
			Sku: "Standard",
			numberOfWorkers: 1,
			workerSize: "Small"			
		    },
    website: {
		name: "ilinksample1126"
	     },
    appInsights: {
			name: "ilinkappinsights1126",
			location: "Central US"
		 },
    requests: {
		get: "http://ilinksample1126.azurewebsites.net/people",
		create: "http://ilinksample1126.azurewebsites.net/people/Create?Name=Peter Harnish&ZipCode=98054",
		edit: "http://ilinksample1126.azurewebsites.net/people/Edit?ID=1&Name=Peter Harnish&ZipCode=98055",
		delete: "http://ilinksample1126.azurewebsites.net/people/Delete/1"
	      }	
    
}

The script does the following things:

  • Creates a new resource group
  • Creates a SQL Server
  • Creates an App Service plan
  • Creates a web site
  • Creates application insights
  • Creates a database
  • Publishes the web app using the given zip file. The path is passed as a parameter.
  • Opens the SQL Server firewall
  • Runs the following tests to the web app:
    • Get request
    • Create request
    • Edit request
    • Delete request
  • Removes the resource group, which removes all the resources underneath it

The full text of the script is given below:

Param(
  [string] [Parameter(Mandatory=$true)] $Configuration,
  [string] [Parameter(Mandatory=$true)] $Package
)

# read inputs from file
Write-Verbose -message "Reading inputs..."
$inputs = (Get-Content $Configuration) -join "`n" | ConvertFrom-Json

#select the azure subscription
Write-Verbose -message "Selecting the Azure Subscription..."
Select-AzureSubscription -SubscriptionName "Free Trial"

Write-Verbose -message "Switching Azure mode to Azure Resource Manager..."
Switch-AzureMode AzureResourceManager -Verbose:$false 

# create resource group
Write-Verbose -message "Creating Azure Resource Group..."
New-AzureResourceGroup -Location $inputs.location -Name $inputs.resourceGroup.Name 

# create database server
$securePassword1 = ConvertTo-SecureString -String $inputs.server.password -AsPlainText -Force
$cred1 = New-Object System.Management.Automation.PSCredential($inputs.server.admin, $securePassword1)
Write-Verbose -message "Creating Azure SQL Server..."
New-AzureSqlServer -ResourceGroupName $inputs.resourceGroup.Name -Location $inputs.location -ServerName $inputs.server.name -SqlAdministratorCredentials $cred1 


#create app service plan
Write-Verbose -message "Creating Azure App Service Plan..."
$plan = New-AzureAppServicePlan -ResourceGroupName $inputs.resourceGroup.Name -Name $inputs.appServicePlan.name -location $inputs.location -Sku $inputs.appServicePlan.Sku -NumberofWorkers $inputs.appServicePlan.numberOfWorkers -WorkerSize $inputs.appServicePlan.workerSize

#create web site
Write-Verbose -message "Creating web site..."
New-AzureResource -name $inputs.website.name -ResourceGroupName $inputs.resourceGroup.Name -ResourceType "Microsoft.Web/sites" -Location $inputs.location -Force -PropertyObject @{serverFarmId = $plan.ResourceId} -OutputObjectFormat New

#create application insights
Write-Verbose -message "Creating application insights..."
New-AzureResource -ResourceName $inputs.appInsights.name -ResourceGroupName $inputs.resourceGroup.Name -ResourceType "Microsoft.Insights/Components" -Location $inputs.appInsights.location -PropertyObject @{"Type" ="ASP.NET"} -Force -OutputObjectFormat New

#create sql database
Write-Verbose -message "Creating SQL database..."
New-AzureSqlDatabase -ResourceGroupName $inputs.resourceGroup.name -ServerName $inputs.server.name -DatabaseName $inputs.database.name -Edition $inputs.database.edition

Write-Verbose -message "Switching Azure mode to Azure Service management..."
Switch-AzureMode AzureServiceManagement -Verbose:$false

$connectionString = "Server=tcp:{0}.database.windows.net,1433;Database={1};User ID={2}@{0};Password={3};Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;" -f $inputs.server.name,$inputs.database.name,$inputs.server.admin,$inputs.server.password

# publish the web app
Write-Verbose -message "Publishing the web application..."
Publish-AzureWebsiteProject -Name $inputs.website.name -Package $Package -ConnectionString @{ DefaultConnection = $connectionString }

# allow connections to the server
Write-Verbose -message "Creating the server firewall rule..."
New-AzureSqlDatabaseServerFirewallRule -StartIPAddress 0.0.0.0 -EndIPAddress 0.0.0.0 -RuleName "AllowAllWindowsAzureIps" -ServerName $inputs.server.name

# do a get request
Write-Verbose -message "Performing a get request..."
Invoke-WebRequest -Uri $inputs.requests.get -Method GET

# create a record
Write-Verbose -message "Creating a record..."
Invoke-WebRequest -Uri $inputs.requests.create -Method POST

# editing a record
Write-Verbose -message "Editing a record..."
Invoke-WebRequest -Uri $inputs.requests.edit -Method POST

# deleting a record
Write-Verbose -message "Deleting a record..."
Invoke-WebRequest -Uri $inputs.requests.delete -Method POST

Write-Host "Press any key to continue..."
$host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")

Write-Verbose -message "Switching Azure mode to Azure Resource Manager..."
Switch-AzureMode AzureResourceManager -Verbose:$false

# removing the resource group
Write-Verbose -message "Removing the resource group..."
Remove-AzureResourceGroup -Name $inputs.resourceGroup.Name -Force

You run the script using the following command in Azure Powershell:

PS C:\Users\iLink\Documents\Azure DevOps> .\ProvisionWebApp.ps1 -Configuration "ProvisionWebApp.json" -Package "C:\SampleAzureWebApp.zip"

Before deleting the resource group the script pauses for input and you can view the resources created in the portal.

 

handheld

 

So this script creates Azure resources, runs tests, and deprovisions resources all in one. In order to run this script we commented out the “ValidateAntiForgeryToken” attribute from our controller methods in order to be able to do post requests from PowerShell.

Coming soon: How to provision Azure resources using Chef!

CHEF

CHEF is a platform to provision, configure, manage IT infrastructure and applications. We implemented a chef recipe to provision simple two tier application on Azure.

We’ve implemented a chef recipe to provision resources on Azure from a template. This recipe is taken from Stuart Preston’s chef provisioning azurerm driver on GitHub (https://github.com/pendrica/chef-provisioning-azurerm). To run it, you need the fullowing:

  • An Azure subscription
  • The Azure development sdk, downloadable from Microsoft
  • A chef workstation and connection to a chef server
  • The chef-provisioning-azurerm driver, which you can install with chef gem install chef-provisioning-azurerm.

Log into your Azure subscription using Add-AzureAccount before running this recipe.

PS C:\Users\iLink\Documents\Azure DevOps> Add-AzureAccount

 

handheld

 

The recipe does 2 things:

  • Creates an Azure resource group
  • Creates the resources using a json template

Full text of the recipe is below:

require 'chef/provisioning/azurerm'
with_driver 'AzureRM:********-****-****-****-************'

azure_resource_group 'ilinkresourcegroup1120' do
  location 'West US'
end

azure_resource_template 'my-deployment' do
  resource_group 'ilinkresourcegroup1120'
  template_source 'azure_deploy.json'
  parameters location: "West US",
             adminPassword: '********',
	     subscription: '********-****-****-****-************',
	     resourceGroup: 'ilinkresourcegroup1120',
	     serverFarmName: 'ilinkappserviceplan1120',
	     server: 'ilinkserver1120',
	     database: 'ilinksample1120_db',
	     adminLogin: 'peterharnish',
	     websiteName: 'ilinksample1120',
	     appInsights: 'ilinkappinsights1120'
  chef_extension client_type: 'ChefClient',
                 version: '1210.12',
                 runlist: 'role[webserver]'
end

And here is the json template:

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "location": {
      "type": "string"
    },
    "adminPassword": {
      "type": "string"
    },
    "subscription": { "type": "string" },
    "resourceGroup": { "type": "string" },
    "serverFarmName": { "type": "string" },
    "server": { "type": "string" },
    "database": { "type": "string" },
    "adminLogin": { "type": "string" },
    "websiteName": { "type": "string" },
    "appInsights":  {"type": "string"}
  },  
  "resources": [
    {
      "type": "Microsoft.Sql/servers",
      "name": "[parameters('server')]",
      "apiVersion": "2014-04-01-preview",
      "location": "[parameters('location')]",
      "properties": {
        "administratorLogin": "[parameters('adminLogin')]",
        "administratorLoginPassword": "parameters('adminPassword')]"
      },
      "resources": [
        {
          "apiVersion": "2014-04-01-preview",
          "name": "[parameters('database')]",
          "type": "databases",
          "location": "[parameters('location')]",
          "dependsOn": [
            "[concat('Microsoft.Sql/servers/', parameters('server'))]"
          ],
          "properties": {
            "edition": "Basic",
            "maxSizeBytes": "1073741824"
          }
        },
        {
          "apiVersion": "2014-04-01-preview",
          "type": "firewallrules",
          "name": "AllowAllWindowsAzureIps",
          "location": "[parameters('location')]",
          "dependsOn": [
            "[concat('Microsoft.Sql/servers/', parameters('server'))]"
          ],
          "properties": {
            "endIpAddress": "255.255.255.255",
            "startIpAddress": "0.0.0.0"
          }
        }
      ]
    },
    {
      "apiVersion": "2014-06-01",
      "type": "Microsoft.Web/serverfarms",
      "name": "[parameters('serverFarmName')]",
      "location": "[parameters('location')]",
      "properties": {
        "name": "[parameters('serverFarmName')]",
        "sku": "Standard"
      }
    },
    {
      "apiVersion": "2015-08-01",
      "type": "Microsoft.Web/sites",
      "name": "[parameters('websiteName')]",
      "location": "[parameters('location')]",
      "dependsOn": [
        "[concat('Microsoft.Web/serverfarms/', parameters('serverFarmName'))]"
      ],
      "properties": {
        "name": "[parameters('websiteName')]",
        "serverFarmId": "[concat('/subscriptions/', parameters('subscription'), '/resourceGroups/', parameters('resourceGroup'), '/providers/Microsoft.Web/serverfarms/', parameters('serverFarmName'))]"
      },
      "resources": [
        {
          "apiVersion": "2015-08-01",
          "location": "[parameters('location')]",
          "type": "config",
          "name": "web",
          "dependsOn": [
            "[concat('Microsoft.Web/sites/', parameters('websiteName'))]"
          ],
          "properties": {
            "connectionStrings": [
              {
                "ConnectionString": "[concat('Data Source=tcp:', reference(concat('Microsoft.Sql/servers/', parameters('server'))).fullyQualifiedDomainName, ',1433;Initial Catalog=', parameters('database'), ';User Id=admin@', parameters('server'), ';Password=', parameters('adminPassword'), ';')]",
                "Name": "DefaultConnection",
                "Type": 2
              }
            ]
          }
        }
      ]
    },
    {
      "apiVersion": "2014-04-01",
      "type": "Microsoft.Insights/components",
      "name": "[parameters('appInsights')]",
      "location": "Central US",
      "properties": {
        "Type": "ASP.NET"
      }
    }
  ]
}

You provide your subscription GUID, resource group name, template path, and any parameters passed to the template in the recipe. It is very simple and because you are using a resource template it is fully customizable!

 

Comments (0)Number of views (2674)

Author: Mano Venkatesan

Categories: Blogs, Developer

Tags: Automated Provisioning, PowerShell, CHEF

Leave a comment

Name:
Email:
Comment:
CAPTCHA image
Enter the code shown above in the box below
Add comment