2
votes

I am attempting to set up an Azure Function that will scale our App Service Plan to be larger during business hours, and smaller outside of them. I drew from the answer to this question.

public static class ScaleUpWeekdayMornings
{
    [FunctionName(nameof(ScaleUpWeekdayMornings))]
    public static async Task Run([TimerTrigger("0 0 13 * * 1-5")]TimerInfo myTimer, ILogger log) // Uses GMT timezone
    {
        var resourceGroup = "DesignServiceResourceGroup";
        var appServicePlanName = "DesignService";
        var webSiteManagementClient = await Utilities.GetWebSiteManagementClient();
        var appServicePlanRequest = await webSiteManagementClient.AppServicePlans.ListByResourceGroupWithHttpMessagesAsync(resourceGroup);
        appServicePlanRequest.Body.ToList().ForEach(x => log.LogInformation($">>>{x.Name}"));
        var appServicePlan = appServicePlanRequest.Body.Where(x => x.Name.Equals(appServicePlanName)).FirstOrDefault();
        if (appServicePlan == null)
        {
            log.LogError("Could not find app service plan.");
            return;
        }
        appServicePlan.Sku.Family = "P";
        appServicePlan.Sku.Name = "P2V2";
        appServicePlan.Sku.Size = "P2V2";
        appServicePlan.Sku.Tier = "Premium";
        appServicePlan.Sku.Capacity = 1;
        var updateResult = await webSiteManagementClient.AppServicePlans.CreateOrUpdateWithHttpMessagesAsync(resourceGroup, appServicePlanName, appServicePlan);
    }
}

public static class Utilities
{
    public static async Task<WebSiteManagementClient> GetWebSiteManagementClient()
    {
        var azureServiceTokenProvider = new AzureServiceTokenProvider();
        var accessToken = await azureServiceTokenProvider.GetAccessTokenAsync("https://management.azure.com/");
        var tokenCredentials = new TokenCredentials(accessToken);
        return new WebSiteManagementClient(tokenCredentials)
        {
            SubscriptionId = "<realSubscriptionIdHere>",                
        };
    }
}

When I run this locally, it works, and actually performs the scale up on our Azure App Service Plan (I believe via Azure CLI). However, when this Azure Function is deployed to Azure, it does not find any App Service Plans. It hits the appservicePlan == null block and returns. I have turned on the Managed Service Identity for the deployed Azure Function, and granted it contributor permissions in the App Service I want to scale for.

Azure App Service permission

Am I missing something? Why does

await webSiteManagementClient.AppServicePlans.ListByResourceGroupWithHttpMessagesAsync(resourceGroup);

not return anything when run as part of a published Azure Function?

1

1 Answers

0
votes

The problem was the permission was set on the App Service (which was an app on the App Service Plan). It needed to be set on the Resource Group to be able to read the App Service Plans.