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)
And also copy the URL next to the GET button
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"
}
}
}
}
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