Scale up AppServicePlan from Azure Function App

In this blog post we are going to demo how to programmatically change AppServicePlan properties. For example, we are going to change the pricing tier (Scale Up) from a console app and also from a Azure Function App.

Here are main steps :

Create a Service Principal account

Use Resource Explorer to get details on your existing AppServicePlan

Create a console app or Azure Function App

Step 1 : Service Principal Account

As our console app or function app is going to access Azure resources, we need to set up an account for them. This account is called Service Principal account.  Please click here for more details on Service Principal.  We can create a Service Principal account using these PowerShell cmdlet

 

Login-AzureRmAccount
 $sp = New-AzureRmADServicePrincipal -DisplayName wabacuser -Password "yourpassword"
 Sleep 30
 New-AzureRmRoleAssignment -RoleDefinitionName Contributor -ServicePrincipalName $sp.ApplicationId
 Get-AzureRMADServicePrincipal -SearchString "wabacuser" |fl


From these cmdlet output, copy TenantID.

Step 2 : Resource Explorer

Best way to learn Azure ARM APIs is using Resource Explorer : https://resources.azure.com/. In Resource Explorer you can list existing Azure resources and their properties. In this blog post, we are going to work on the existing AppServicePlan, so log into Resource Explorer and follow these steps:

Expand your subscription

Expand resourceGroup node

Expand your resource group

Expand providers node

Expand Microsoft.Web node

Expand serverfarms node

Expand your AppServicePlan

Click GET button

Note the SKU property (name is set to S2)

ARM_2

And also copy the URL next to the GET button

ARM_3

Step 3a : Console App

Open Visual Studio, and create a empty .NET Console App. Add Active Directory Authentication Library from NuGet : https://www.nuget.org/packages/Microsoft.IdentityModel.Clients.ActiveDirectory/

Next, add following code to program.cs file

 
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

namespace FAppARM
{
    class Program
    {
        static string tenantId = "tenand id from above PowerShell cmdlets";
        static string username = "https://wabacuser";
        static string password = "yourpassword";
        static string token = string.Empty;
        static string subscription = "your subscription id";
        static string resourceGroup = "your resource group name";
        static string appServicePlan = "your app service plan name";

        static HttpClient httpClient = new HttpClient();
        static void Main(string[] args)
        {
            var t = GetToken();
            t.Wait();
            var url = $"https://management.azure.com/subscriptions/{subscription}/resourceGroups/{resourceGroup}/providers/Microsoft.Web/serverfarms/{appServicePlan}?api-version=2016-09-01";
            var t2 = Get(url);
            t2.Wait();
            var t3 = Put(url, "{ \"location\":\"South Central US\",\"Sku\":{\"Name\":\"S1\"}}");
            t3.Wait();
        }

        public static async Task GetToken()
        {
            string url = "https://login.windows.net/" + tenantId;
            var authContext = new AuthenticationContext(url);
            var credential = new ClientCredential(username, password);
            var t = await authContext.AcquireTokenAsync("https://management.azure.com/", credential);
            token = t.AccessToken;
            return token;
        }

        static async Task Get(string url)
        {
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
            return await httpClient.GetStringAsync(url);
        }

        static async Task Put(string url, string jsonData)
        {
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
            StringContent postData = new StringContent(jsonData, System.Text.Encoding.UTF8, "application/json");
            var t = await httpClient.PutAsync(url, postData);
            return await t.Content.ReadAsStringAsync();
        }

        static async Task Post(string url, string jsonData)
        {
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
            StringContent postData = new StringContent(jsonData, System.Text.Encoding.UTF8, "application/json");
            var t = await httpClient.PostAsync(url, postData);
            return await t.Content.ReadAsStringAsync();
        }
    }
}

In the line # 30, we are going to set the scale out to S1.

Now run this console app and then go back to Resource Explorer, check the Sku property.

Step 3b: Function App

Log into Azure portal at https://portal.Azure.com and create a new C# HTTP trigger Function App.

Click on the View files menu from the blade at right. Next click on Add and set file name to project.json. Add these lines in this file. This will tell Function Runtime to download the ADAL NuGet package

 
{
    "frameworks":{
        "net46":{
            "dependencies":{
                "Microsoft.IdentityModel.Clients.ActiveDirectory":"3.17.2"
            }
        }
    }
}

ARM_4

Next, add this below code in the run.csx:

 


using System.Net;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System;
using System.Net.Http;
using System.Net.Http.Headers;

static string tenantId = "your tenant id";
static string username = "https://wabacuser";
static string password = "your password";
static string token = string.Empty;
static string subscription = "your subscription";
static string resourceGroup = "your resource group name";
static string appServicePlan = "your service plan";

static HttpClient httpClient = new HttpClient();

public static async Task Run(HttpRequestMessage req, TraceWriter log)
{
    log.Info("C# HTTP trigger function processed a request.");

    token = await GetToken();

    var url = $"https://management.azure.com/subscriptions/{subscription}/resourceGroups/{resourceGroup}/providers/Microsoft.Web/serverfarms/{appServicePlan}?api-version=2016-09-01";
    var str = await Get(url);
    var str1 = await Put(url, "{ \"location\":\"South Central US\",\"Sku\":{\"Name\":\"S2\"}}");

    return req.CreateResponse(HttpStatusCode.OK, "DONE");
}

public static async Task GetToken()
{
    string url = "https://login.windows.net/" + tenantId;
    var authContext = new AuthenticationContext(url);
    var credential = new ClientCredential(username, password);
    var t = await authContext.AcquireTokenAsync("https://management.azure.com/", credential);
    token = t.AccessToken;
    return token;
}

static async Task Get(string url)
{
    httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
    return await httpClient.GetStringAsync(url);
}

static async Task Put(string url, string jsonData)
{
    httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
    StringContent postData = new StringContent(jsonData, System.Text.Encoding.UTF8, "application/json");
    var t = await httpClient.PutAsync(url, postData);
    return await t.Content.ReadAsStringAsync();
}

static async Task Post(string url, string jsonData)
{
    httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
    StringContent postData = new StringContent(jsonData, System.Text.Encoding.UTF8, "application/json");
    var t = await httpClient.PostAsync(url, postData);
    return await t.Content.ReadAsStringAsync();
}

In the line#25, we are now changing it to back to S2. Execute this function and check the Sku property in the Resource Explorer