Manage Azure resource groups with TypeScript Function API

In this tutorial, you'll create a local TypeScript Azure Function app with APIs to manage Azure resource groups and deploy the app to Azure.

Features and functionality:

  • Create local TypeScript Azure Function app project in Visual Studio Code
  • Create function API boilerplate code in Visual Studio Code
  • Deploy to Azure Functions from Visual Studio Code
  • Create service principal with Azure CLI
  • Configure local and remote application settings with Visual Studio Code
  • Use DefaultAzureCredential in both local and remote environments for passwordless connections
  • Use Azure Identity and Azure Resource Management SDKs to manage Azure resources
  • Use your local and cloud APIs to create, delete, and list resource groups in your subscription

While the source code is written with TypeScript, the source code is simple. If you're comfortable with modern JavaScript using async/await, the code will be familiar to you.

Create or use an existing Azure subscription

You'll need an Azure user account with an active subscription. Create one for free.

Prerequisites

Application architecture

The app provides the following API endpoints.

Method URL Description
POST,DELETE http://localhost:7071/api/resourcegroup Add or delete a resource group. While adding, include tags (key/value pairs) to identify the purpose of the group later.
GET http://localhost:7071/api/resourcegroups List all resource groups in subscription.
GET http://localhost:7071/api/resources List all resources in a subscription or resource group.

While these endpoints are public, you should secure your API endpoints with authentication and authorization before deploying to your live environment.

This app is limited to a subscription because that is the scope specified when creating the service principal.

1. Preparing your environment

You must prepare your local and cloud environments to use the Azure Identity SDK.

Sign in to Azure CLI

In a bash terminal, sign in to the Azure CLI with the following command:

az login

Get your Azure subscription ID

  1. In a bash terminal, get your subscriptions and find the subscription ID you want to use. The following query returns the subscription ID, subscription name, and tenant ID sorted by subscription name.

    az account list --query "sort_by([].{Name:name, SubscriptionId:id, TenantId:tenantId}, &Name)" --output table
    
  2. Copy the subscription ID to the previous temporary file. You'll need this setting later.

Create an Azure service principal

An Azure service principal provides access to Azure without having to use your personal user credentials. For this tutorial, the service principal can be used both in your local and cloud environments. In an enterprise environment, you would want separate service principals for each environment.

  1. Determine a service principal name format so you can easily find your service principal later. For example, several format ideas are:

    • Your project and owner: resource-management-john-smith.
    • Your department and date: IT-2021-September
    • A unique identifier: 1e8966d7-ba85-424b-9db4-c39e1ae9d0ca
  2. In a bash terminal, create your service principal with az ad sp create-for-rbac. Replace <SUBSCRIPTION-ID> with your subscription ID.

    az ad sp create-for-rbac --name YOUR-SERVICE-PRINCIPAL-NAME --role Contributor --scopes /subscriptions/<SUBSCRIPTION-ID>
    
  3. Copy the entire output results to a temporary file. You'll need these settings later.

    {
      "appId": "YOUR-SERVICE-PRINCIPAL-ID",
      "displayName": "YOUR-SERVICE-PRINCIPAL-NAME",
      "name": "http://YOUR-SERVICE-PRINCIPAL-NAME",
      "password": "YOUR-SERVICE-PRINCIPAL-PASSWORD",
      "tenant": "YOUR-TENANT-ID"
    }
    

2. Create local Azure Function app in Visual Studio Code

Create an Azure Function app in Visual Studio Code to manage Azure resource groups.

Create function app

Use Visual Studio Code to create a local Function app.

  1. In a bash terminal, create and change into a new directory:

    mkdir my-function-app && cd my-function-app
    
  2. In a bash terminal, open Visual Studio Code:

    code .
    
  3. Open the Visual Studio Code command palette: Ctrl + Shift + p.

  4. Enter Azure Functions: create new project. Use the following table to finish the prompts:

    Prompt Value
    Select the folder that will contain your function project Select the default (current) directory
    Select a language Select TypeScript.
    Select a TypeScript programming model Select Model V4 (Preview)
    Select a template for your project's first function Select HTTP trigger.
    Create new HTTP trigger Enter the API name of resourcegroups.
    Authorization level Select anonymous. If you continue with this project after this article, change the authorization level to the function. Learn more about Function-level authorization.

    The project boilerplate is created and the dependencies are installed.

Add service principal settings to local.settings.json file

  1. Open the ./local.settings.json file in the project root directory and add your VALUES section with the five following environment variables.

    {
      "IsEncrypted": false,
      "Values": {
        "AzureWebJobsStorage": "",
        "FUNCTIONS_WORKER_RUNTIME": "node",
        "AzureWebJobsFeatureFlags": "EnableWorkerIndexing",
        "AZURE_CLIENT_ID": "REPLACE-WITH-SERVICE-PRINCIPAL-APPID",
        "AZURE_CLIENT_SECRET": "REPLACE-WITH-SERVICE-PRINCIPAL-PASSWORD",
        "AZURE_SUBSCRIPTION_ID":"REPLACE-WITH-SUBSCRIPTION-ID",
        "AZURE_TENANT_ID":"REPLACE-WITH-SERVICE-PRINCIPAL-TENANT",
        "NODE_ENV":"development"
      }
    }
    
  2. Refer to your settings from the previous section to add the values. These environment variables are REQUIRED for the context to use DefaultAzureCredential.

    • AZURE_TENANT_ID: tenant from the service principal output above.
    • AZURE_CLIENT_ID: appId from the service principal output above.
    • AZURE_CLIENT_SECRET: password from the service principal output above.
  3. You also need to set the subscription ID. It's required to use the Azure SDK for resource management.

    • AZURE_SUBSCRIPTION_ID: Your default subscription containing your resource groups.

This local.settings.json file is ignored by your local git on purpose so you don't accidentally commit it to your source code.

Install npm dependencies for Azure Identity and Resource management

In a Visual Studio Code integrated bash terminal, install the Azure SDK dependencies for Azure Identity and Resource management.

npm install @azure/identity @azure/arm-resources

List all resource groups in subscription with JavaScript

  1. Open the ./src/functions/resourcegroups.ts file and replace the contents with the following:

    import { ResourceGroup } from '@azure/arm-resources';
    import {
      app,
      HttpRequest,
      HttpResponseInit,
      InvocationContext
    } from '@azure/functions';
    import {
      createResourceGroup,
      deleteResourceGroup
    } from '../lib/azure-resource-groups';
    import { processError } from '../lib/error';
    
    export async function resourcegroup(
      request: HttpRequest,
      context: InvocationContext
    ): Promise<HttpResponseInit> {
      try {
        console.log(JSON.stringify(request.query));
        console.log(JSON.stringify(request.params));
    
        const name: string = request.query.get('name');
        const location: string = request.query.get('location');
        console.log(`name: ${name}`);
        console.log(`location: ${location}`);
    
        switch (request.method) {
          case 'POST': // wait for create to complete before returning
            if (!name || !location) {
              return { body: 'Missing required parameters.', status: 400 };
            }
    
            if (request.headers.get('content-type') === 'application/json') {
              // create with tags
    
              const body: Record<string, unknown> =
                (await request.json()) as Record<string, string>;
              const tags: Record<string, string> = body?.tags
                ? (body?.tags as Record<string, string>)
                : null;
              const resourceGroup: ResourceGroup = await createResourceGroup(
                name,
                location,
                tags
              );
              return { jsonBody: resourceGroup, status: 200 };
            } else {
              // create without tags
    
              const resourceGroup: ResourceGroup = await createResourceGroup(
                name,
                location,
                null
              );
              return { jsonBody: resourceGroup, status: 200 };
            }
    
          case 'DELETE': // wait for delete to complete before returning
            if (!name) {
              return { body: 'Missing required parameters.', status: 400 };
            }
            await deleteResourceGroup(name);
            return { status: 204 };
        }
      } catch (err: unknown) {
        return processError(err);
      }
    }
    
    app.http('resourcegroup', {
      methods: ['DELETE', 'POST'],
      authLevel: 'anonymous',
      handler: resourcegroup
    });
    

    This file responds to API requests to /api/resourcegroups and returns a list of all resource groups in the subscription.

  2. Create a subdirectory in src named lib and create a new file in that directory named azure-resource-groups.ts.

  3. Copy the following code into the ./src/lib/azure-resource-groups.ts file:

    // Include npm dependencies
    import {
      ResourceGroup, ResourceManagementClient
    } from '@azure/arm-resources';
    import { DefaultAzureCredential } from '@azure/identity';
    import { getSubscriptionId } from './environment-vars';
    
    const subscriptionId = getSubscriptionId();
    
    // Create Azure authentication credentials
    const credentials = new DefaultAzureCredential();
    
    // Create Azure SDK client for Resource Management such as resource groups
    const resourceManagement = new ResourceManagementClient(
      credentials,
      subscriptionId
    );
    
    // all resources groups in subscription
    export const listResourceGroups = async (): Promise<{
      list: ResourceGroup[];
      subscriptionId: string;
    }> => {
      const list: ResourceGroup[] = [];
      for await (const resourceGroup of resourceManagement.resourceGroups.list()) {
        list.push(resourceGroup);
      }
      return {
        subscriptionId,
        list
      };
    };
    export const createResourceGroup = async (
      resourceGroupName: string,
      location: string,
      tags: { [propertyName: string]: string }
    ): Promise<ResourceGroup> => {
      const resourceGroupParameters = {
        location: location,
        tags
      };
    
      return await resourceManagement.resourceGroups.createOrUpdate(
        resourceGroupName,
        resourceGroupParameters
      );
    };
    export const deleteResourceGroup = async (
      resourceGroupName: string
    ): Promise<void> => {
      return await resourceManagement.resourceGroups.beginDeleteAndWait(
        resourceGroupName
      );
    };
    

    This file completes the following:

    • Gets the subscription ID
    • Creates the DefaultAzureCredential context
    • Creates the ResourceManagementClient required to use the Resource management SDK.
    • Gets all the resource groups in the subscription.
  4. Create a new file in the ./src/lib directory named environment-vars.ts and copy the following code into that file.

    export const checkAzureAuth = () => {
      // The following code is only used to check you have environment
      // variables configured. The DefaultAzureCredential reads your
      // environment - it doesn't read these variables.
      const tenantId = process.env['AZURE_TENANT_ID'];
      if (!tenantId)
        throw Error('AZURE_TENANT_ID is missing from environment variables.');
      const clientId = process.env['AZURE_CLIENT_ID'];
      if (!clientId)
        throw Error('AZURE_CLIENT_ID is missing from environment variables.');
      const secret = process.env['AZURE_CLIENT_SECRET'];
      if (!secret)
        throw Error('AZURE_CLIENT_SECRET is missing from environment variables.');
    };
    
    export const getSubscriptionId = (): string => {
      checkAzureAuth();
    
      // Get subscription from environment variables
      const subscriptionId = process.env['AZURE_SUBSCRIPTION_ID'];
      if (!subscriptionId)
        throw Error('Azure Subscription is missing from environment variables.');
      return subscriptionId;
    };
    

    This file checks the environment variables before returning the subscription ID.

  5. Create a new file in the ./src/lib directory named error.ts and copy the following code into that file.

    export function processError(err: unknown): any {
      if (typeof err === 'string') {
        return { body: err.toUpperCase(), status: 500 };
      } else if (
        err['stack'] &&
        process.env.NODE_ENV.toLowerCase() !== 'production'
      ) {
        return { jsonBody: { stack: err['stack'], message: err['message'] } };
      } else if (err instanceof Error) {
        return { body: err.message, status: 500 };
      } else {
        return { body: JSON.stringify(err) };
      }
    }
    

    This file returns a 500 error with the error message. The stack is returned if the NODE_ENV variable isn't set to production.

Test local functions

  1. In the Visual Studio Code integrated terminal, run the local project:

    npm start
    
  2. Wait until the integrated bash terminal displays the running function's URL.

    Partial screenshot of Visual Studio Code's integrated bash terminal when the Azure Function is running locally and displaying the local URL for the APIs in the Function app.

  3. Open a second integrated bash terminal in Visual Studio Code, Ctrl + Shift + 5, and use the following GET cURL command to use the API:

    curl http://localhost:7071/api/resourcegroups
    

    If you have many resource groups in your subscription, you may want to pipe the output to a file for easier review.

    curl http://localhost:7071/api/resourcegroups > resourcegroups.json
    
  4. The response includes subscriptionId and a list of all resource groups in that subscription.

    {
      "subscriptionId": "ABC123",
      "list": [
            {
              "id": "/subscriptions/ABC123/resourceGroups/vmagelo-cloudshell",
              "name": "jsmith-cloudshell",
              "type": "Microsoft.Resources/resourceGroups",
              "properties": {
                "provisioningState": "Succeeded"
              },
              "location": "westeurope"
            },
            ... REMOVED FOR BREVITY ...
        ]
    }
    

Troubleshooting

If you couldn't complete this article, check the following table for issues. If your issue isn't listed in the table, open an issue on this documentation page.

Issue Fix
The app didn't start. Review the errors. Make sure you installed the required dependencies.
The app started but you can't get a 200 response. Make sure your curl command is requesting from the correct local route.
The API returned a 200 response but returned no results. Use the Visual Studio Code extension for Azure Resources to verify that your subscription has any resource groups. If you don't see any resource groups, don't worry. This tutorial adds an API to create and delete resource groups in your subscription. This API is added after the first deployment of the source code to Azure, so that you learn how to redeploy your code.

3. Create cloud-based Azure Function app

  1. In Visual Studio Code, select the Azure icon to open the Azure Explorer.

  2. Select the + icon to create a new Azure Function app in the Azure cloud.

    Screenshot of Visual Studio Code's Azure Explorer with the Azure Function app icon highlighted.

  3. Select Create Function App in Azure.

  4. Enter a globally unique name for the new function app. The name must be unique across all Azure functions. For example, jsmith-rg-management.

  5. Select the same Node.js 18+ LTS runtime you selected when you created your local function app.

  6. Select a geographical location close to you such as West US 3.

  7. Wait until the resource is created. You can watch the Azure: Activity Log for details.

    Screenshot of Visual Studio Code's Azure activity log showing the resource creation status.

4. Configure cloud-based Azure Function app

You need to configure your Azure app settings to connect to the Azure Function app. Locally, these settings are in your local.settings.json file. This process adds those values to your cloud app.

  1. In Visual Studio Code, in the Azure explorer, in the Resources section, expand Function App then select your function app.

  2. Right-click on Application Settings and select Add New Setting.

  3. Add the four values from your local.settings.json with the exact same name and values.

    • AZURE_TENANT_ID: tenant from the service principal output above.
    • AZURE_CLIENT_ID: appId from the service principal output above.
    • AZURE_CLIENT_SECRET: password from the service principal output above.
    • AZURE_SUBSCRIPTION_ID: Your default subscription containing your resource groups.
    • AzureWebJobsFeatureFlags:EnableWorkerIndexing

Partial screenshot of Visual Studio Code's Azure explorer showing the remote/cloud function's app settings.

5. Deploy Resource Manager function app

Deploy an Azure Function app in Visual Studio Code to manage Azure resource groups.

Use Visual Studio Code extension to deploy to hosting environment

  1. In VS Code, open the local.settings.json file so it is visible. This will make the next steps of copying those names and values easier.

  2. Select the Azure logo to open the Azure Explorer, then under Functions, select the cloud icon to deploy your app.

    Screenshot of Visual Studio Code's local Workspace area with the cloud deployment icon highlighted.

    Alternately, you can deploy by opening the Command Palette with Ctrl + Shift + p, entering deploy to function app, and running the Azure Functions: Deploy to Function App command.

  3. Select Deploy to Function app.

  4. Select the Function App name your created in the previous section.

  5. When asked if you're sure you want to deploy, select Deploy.

  6. The VS Code Output panel for Azure Functions shows progress. When deploying, the entire Functions application is deployed, so changes to all individual functions are deployed at once.

Verify Functions app is available with browser

  1. While still in Visual Studio Code, use the Azure Functions explorer, expand the node for your Azure subscription, expand the node for your Functions app, then expand Functions (read only). Right-click the function name and select Copy Function Url:

    Partial screenshot of Visual Studio Code's Azure explorer showing where to copy the Function's URL.

  2. Paste the URL into a browser and press Enter to request the resource group list from the cloud API.

6. Add APIs to function app and redeploy to Azure

Add the following APIs then redeploy your Azure Function app in Visual Studio Code:

  • Add and delete resource groups
  • List resources in resource group or subscription.

At this point in the tutorial, you created a local function app with one API to list your subscription's resource groups and you deployed that app to Azure. As an Azure developer, you may want to create or delete resource groups as part of your process automation pipeline.

Create resourcegroup API for your function app

Use the Visual Studio Code extension for Azure Functions to add the TypeScript files to your function app to create and delete resource groups.

  1. Open the Visual Studio Code command palette: Ctrl + Shift + p.

  2. Enter Azure Functions: Create Function then press enter to begin the process.

  3. Use the following table to create the /api/resourcegroup API:

    Prompt Value
    Select a template for your function HTTP trigger
    Provide a function name resourcegroup
    Authorization level Select anonymous. If you continue with this project, change the authorization level to the function. Learn more about Function-level authorization.
  4. Open the ./src/functions/resourcegroup.ts and replace the entire file with the following source code.

    import { ResourceGroup } from '@azure/arm-resources';
    import {
      app,
      HttpRequest,
      HttpResponseInit,
      InvocationContext
    } from '@azure/functions';
    import {
      createResourceGroup,
      deleteResourceGroup
    } from '../lib/azure-resource-groups';
    import { processError } from '../lib/error';
    
    export async function resourcegroup(
      request: HttpRequest,
      context: InvocationContext
    ): Promise<HttpResponseInit> {
      try {
        console.log(JSON.stringify(request.query));
        console.log(JSON.stringify(request.params));
    
        const name: string = request.query.get('name');
        const location: string = request.query.get('location');
        console.log(`name: ${name}`);
        console.log(`location: ${location}`);
    
        switch (request.method) {
          case 'POST': // wait for create to complete before returning
            if (!name || !location) {
              return { body: 'Missing required parameters.', status: 400 };
            }
    
            if (request.headers.get('content-type') === 'application/json') {
              // create with tags
    
              const body: Record<string, unknown> =
                (await request.json()) as Record<string, string>;
              const tags: Record<string, string> = body?.tags
                ? (body?.tags as Record<string, string>)
                : null;
              const resourceGroup: ResourceGroup = await createResourceGroup(
                name,
                location,
                tags
              );
              return { jsonBody: resourceGroup, status: 200 };
            } else {
              // create without tags
    
              const resourceGroup: ResourceGroup = await createResourceGroup(
                name,
                location,
                null
              );
              return { jsonBody: resourceGroup, status: 200 };
            }
    
          case 'DELETE': // wait for delete to complete before returning
            if (!name) {
              return { body: 'Missing required parameters.', status: 400 };
            }
            await deleteResourceGroup(name);
            return { status: 204 };
        }
      } catch (err: unknown) {
        return processError(err);
      }
    }
    
    app.http('resourcegroup', {
      methods: ['DELETE', 'POST'],
      authLevel: 'anonymous',
      handler: resourcegroup
    });
    
  5. The ./src/lib/azure-resource-groups.ts file already contains the code to add and delete resource groups.

Create resources API for your function app

Use the Visual Studio Code extension for Azure Functions to add the TypeScript files to your function app to list resources in a resource group.

  1. Open the Visual Studio Code command palette: Ctrl + Shift + p.

  2. Enter Azure Functions: Create Function then press enter to begin the process.

  3. Use the following table to create the /api/resources API:

    Prompt Value
    Select a template for your function HTTP trigger
    Provide a function name resources
    Authorization level Select anonymous. If you continue with this project, change the authorization level to the function. Learn more about Function-level authorization.
  4. Open the ./src/functions/resources.ts and replace the entire file with the following source code.

    import {
      app,
      HttpRequest,
      HttpResponseInit,
      InvocationContext
    } from '@azure/functions';
    import {
      listResourceByResourceGroup, listResourceBySubscription
    } from '../lib/azure-resource';
    import { processError } from '../lib/error';
    
    export async function resources(
      request: HttpRequest,
      context: InvocationContext
    ): Promise<HttpResponseInit> {
      try {
        const resourceGroupName: string = request.query.get('resourceGroupName');
        context.log(`resourceGroupName: '${resourceGroupName}'`);
    
        if (resourceGroupName) {
          const resourcesByName = await listResourceByResourceGroup(
            resourceGroupName
          );
          return { jsonBody: resourcesByName };
        } else {
          const resourcesBySubscription = await listResourceBySubscription();
          return { jsonBody: resourcesBySubscription };
        }
      } catch (err: unknown) {
        return processError(err);
      }
    }
    app.http('resources', {
      methods: ['GET'],
      authLevel: 'anonymous',
      handler: resources
    });
    
  5. Create the ./src/lib/azure-resource.ts file and copy the following code into it to list the resources in a resource group.

    // Include npm dependencies
    import { Resource, ResourceManagementClient } from '@azure/arm-resources';
    import { DefaultAzureCredential } from '@azure/identity';
    import { getSubscriptionId } from './environment-vars';
    
    const subscriptionId = getSubscriptionId();
    
    // Create Azure authentication credentials
    const credentials = new DefaultAzureCredential();
    
    // Create Azure SDK client for Resource Management such as resource groups
    const resourceManagement = new ResourceManagementClient(
      credentials,
      subscriptionId
    );
    
    // all resources groups in subscription
    export const listResourceBySubscription = async (): Promise<{
      list: Resource[];
      subscriptionId: string;
    }> => {
      const list: Resource[] = [];
    
      for await (const resource of resourceManagement.resources.list()) {
        list.push(resource);
      }
    
      return {
        subscriptionId,
        list
      };
    };
    // all resources groups in resource group
    export const listResourceByResourceGroup = async (
      resourceGroupName: string
    ): Promise<{
      list: Resource[];
      subscriptionId: string;
      resourceGroupName: string;
    }> => {
      const list: Resource[] = [];
    
      for await (const resource of resourceManagement.resources.listByResourceGroup(
        resourceGroupName
      )) {
        list.push(resource);
      }
    
      return {
        subscriptionId,
        resourceGroupName,
        list
      };
    };
    

Start your local function app and test the new API

  1. In the Visual Studio Code integrated terminal, run the local project:

    npm start
    
  2. Wait until the integrated bash terminal displays the running function's URL.

    Partial screenshot of Visual Studio Code's integrated bash terminal when the Azure Function is running locally and displaying the local URLs for the APIs in the Function app.

  3. Use the following curl commands in a different integrated bash terminal, to call your API, to add a resource group to your subscription. Change the name of the resource group to use your own naming conventions.

    curl -X POST 'http://localhost:7071/api/resourcegroup?name=my-test-1&location=westus'
    
    curl -X POST 'http://localhost:7071/api/resourcegroup?name=my-test-1&location=westus' \
      -H 'content-type: application/json' \
      -d '{"tags": {"a":"b"}}'
    
  4. Use the following curl command to see the new resource group listed in your subscription.

    curl http://localhost:7071/api/resource-groups
    
  5. Use the following curl command to delete the resource group you just added.

    curl -X DELETE 'http://localhost:7071/api/resourcegroup?name=my-test-1' \
      -H 'Content-Type: application/json'
    

Redeploy your function app with new APIs to Azure

  1. In VS Code, deploy by opening the Command Palette with Ctrl + Shift + p, entering deploy to function app, and running the Azure Functions: Deploy to Function App command.

  2. Select your function app from the list of apps.

  3. Select Deploy from the pop-up window.

  4. Wait until the deployment completes.

Verify Function APIs with browser

Use the previous cURL commands, replacing the localhost address, http://localhost:7071 with your Azure Function resource name such as https://myfunction.azurewebsites.net.

7. View and query your Function app logs

View and query Azure Function app logs in the Azure portal.

Query your Azure Function logs

Use the Azure portal to view and query your function logs.

  1. In VS Code, select the Azure logo to open the Azure Explorer, then under Functions, right-click on your function app, then select Open in Portal.

    This opens the Azure portal to your Azure Function.

  2. Select Application Insights from the Settings, then select View Application Insights data.

    Browser screenshot showing menu choices. Select Application Insights from the Settings, then select View Application Insights data.

    This link takes you to your separate metrics resource created for you when you created your Azure Function with VS Code.

  3. Select Logs in the Monitoring section. If a Queries pop-up window appears, select the X in the top-right corner of the pop-up to close it.

  4. In the Schema and Filter pane, on the Tables tab, double-click the traces table.

    This enters the Kusto query, traces into the query window.

  5. Edit the query to search for API calls:

    traces 
    | where message startswith "Executing "
    
  6. Select Run.

    If the log doesn't display any results, it may be because there's a few minutes delay between the HTTP request to the Azure Function and the log availability in Kusto. Wait a few minutes and run the query again.

    Browser screenshot showing Azure portal Kusto query result for Trace table.

    Because an Application Insights resource was added for you when you created the Azure Function app, you didn't need to do anything extra to get this logging information:

    • The Function app added Application Insights for you.
    • The Query tool is included in the Azure portal.
    • You can select traces instead of having to learn to write a Kusto query to get even the minimum information from your logs.

8. Clean up Azure resources

Delete the resource group

  1. In VS Code, select the Azure logo to open the Azure Explorer, then under Functions, right-click on your function app, then select Open in Portal.This opens the Azure portal to your Azure Function.

  2. In the Overview section, find and select the resource group name. This action takes you to the resource group in the Azure portal.

  3. The resource group page lists all resources associated with this tutorial.

  4. In the top menu, select Delete resource group.

  5. In the side menu, enter the name of the resource group then select Delete.

Delete the service principal

To delete the service principal, run the following command. Replace <YOUR-SERVICE-PRINCIPAL-NAME> with the name of your service principal.

az ad sp delete --id <YOUR-SERVICE-PRINCIPAL-NAME>

Sample code

Next steps