使用 TypeScript 函数 API 管理 Azure 资源组

在本教程中,你将创建一个本地 TypeScript Azure 函数应用,其中包含用于管理 Azure 资源组并将应用部署到 Azure 的 API。

特性和功能:

  • 在 Visual Studio Code 中创建本地 TypeScript Azure 函数应用项目
  • 在 Visual Studio Code 中创建函数 API 样本代码
  • 从 Visual Studio Code 部署到 Azure Functions
  • 使用 Azure CLI 创建服务主体
  • 使用 Visual Studio Code 配置本地和远程应用程序设置
  • 在本地和远程环境中使用 DefaultAzureCredential 进行无密码连接
  • 使用 Azure 标识和 Azure 资源管理 SDK 管理 Azure 资源
  • 使用本地和云 API 创建、删除和列出订阅中的资源组

虽然源代码是用 TypeScript 编写的,但源代码非常简单。 如果你熟悉新式 JavaScript 使用 async/await,则代码将熟悉你。

创建 Azure 订阅或使用现有 Azure 订阅

你将需要具有活动订阅的 Azure 用户帐户。 免费创建一个

先决条件

应用程序体系结构

应用提供以下 API 终结点。

方法 URL 说明
POST、DELETE http://localhost:7071/api/resourcegroup 添加或删除资源组。 添加时,请包含标记(键/值对),以标识组的用途。
GET http://localhost:7071/api/resourcegroups 列出订阅中的所有资源组。
GET http://localhost:7071/api/resources 列出订阅或资源组中的所有资源。

虽然这些终结点是公共的,但 先使用身份验证和授权来保护 API 终结点,然后再部署到实时环境。

此应用仅限于订阅,因为这是创建服务主体时指定的范围。

1.准备环境

必须准备本地和云环境,才能使用 Azure 标识 SDK。

登录 Azure CLI

在 bash 终端中,使用以下命令登录到 Azure CLI:

az login

获取 Azure 订阅 ID

  1. 在 bash 终端中,获取订阅并查找要使用的订阅 ID。 以下查询返回按订阅名称排序的订阅 ID、订阅名称和租户 ID。

    az account list --query "sort_by([].{Name:name, SubscriptionId:id, TenantId:tenantId}, &Name)" --output table
    
  2. 将订阅 ID 复制到上一个临时文件中。 稍后需要此设置。

创建 Azure 服务主体

Azure 服务主体提供对 Azure 的访问权限,而无需使用你的个人用户凭据。 在本教程中,可以在本地和云环境中使用服务主体。 在企业环境中,需要为每个环境单独服务主体。

  1. 确定服务主体名称格式,以便以后可以轻松地查找服务主体。 例如,有几种格式建议:

    • 你的项目和所有者:resource-management-john-smith
    • 你的部门和日期:IT-2021-September
    • 一个唯一标识符:00000000-0000-0000-0000-000000000000
  2. 在 bash 终端中,使用 az ad sp create-for-rbac 创建服务主体。 将 <SUBSCRIPTION-ID> 替换为订阅 ID。

    az ad sp create-for-rbac --name YOUR-SERVICE-PRINCIPAL-NAME --role Contributor --scopes /subscriptions/<SUBSCRIPTION-ID>
    
  3. 将整个输出结果复制到一个临时文件中。 稍后需要这些设置。

    {
      "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. 在 Visual Studio Code 中创建本地 Azure 函数应用

在 Visual Studio Code 中创建 Azure 函数应用以管理 Azure 资源组。

创建 Function App

使用 Visual Studio Code 创建本地 Azure 函数。

  1. 在 bash 终端中,创建并更改到新目录:

    mkdir my-function-app && cd my-function-app
    
  2. 在 bash 终端中,打开 Visual Studio Code:

    code .
    
  3. 打开 Visual Studio Code 命令面板:Ctrl + Shift + p

  4. 输入 Azure Functions: create new project。 使用下表根据提示完成操作:

    Prompt
    选择将包含函数项目的文件夹 选择默认目录(当前) 目录
    选择一种语言 选择 TypeScript。
    选择 TypeScript 编程模型 选择 模型 V4 (预览版)
    为项目的第一个函数选择模板 选择“HTTP 触发器”。
    创建新的 HTTP 触发器 输入 API 名称 resourcegroups
    授权级别 选择“匿名”。 如果在本文之后继续执行此项目,请将授权级别更改为函数。 详细了解函数级别授权

    创建项目样板并安装依赖项。

将服务主体设置添加到 local.settings.json 文件

  1. 打开 ./local.settings.json 项目根目录中的文件,并使用以下五个环境变量添加 VALUES 节。

    {
      "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. 请参阅上一部分中的设置以添加值。 上下文需要这些环境变量才能使用 DefaultAzureCredential。

    • AZURE_TENANT_ID:上述服务主体输出中的 tenant
    • AZURE_CLIENT_ID:上述服务主体输出中的 appId
    • AZURE_CLIENT_SECRET:上述服务主体输出中的 password
  3. 还需要设置订阅 ID。 需要使用 Azure SDK 进行资源管理。

    • AZURE_SUBSCRIPTION_ID:包含资源组的默认订阅。

本地 git 将有意忽略此 local.settings.json 文件,以免你不小心将其提交到你的源代码

安装 Azure 标识和资源管理的 npm 依赖项

在 Visual Studio Code 集成 bash 终端中,安装适用于 Azure 标识和资源管理的 Azure SDK 依赖项

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

使用 JavaScript 列出订阅中的所有资源组

  1. 打开 ./src/functions/resourcegroups.ts 文件并将其内容替换为以下内容:

    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
    });
    

    此文件响应 API 请求 /api/resourcegroups ,并返回订阅中所有资源组的列表。

  2. 在命名lib目录中src创建一个子目录,并在该目录中创建一个名为的新azure-resource-groups.ts文件。

  3. 将以下代码复制到 ./src/lib/azure-resource-groups.ts 文件中:

    // 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
      );
    };
    

    此文件将完成以下操作:

    • 获取订阅 ID
    • 创建 DefaultAzureCredential 上下文
    • 创建使用资源管理 SDK 所需的 ResourceManagementClient。
    • 获取订阅中的所有资源组。
  4. 在命名environment-vars.ts./src/lib目录中创建新文件,并将以下代码复制到该文件中。

    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;
    };
    

    此文件在返回订阅 ID 之前检查环境变量。

  5. 在命名error.ts./src/lib目录中创建新文件,并将以下代码复制到该文件中。

    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) };
      }
    }
    

    此文件返回一个包含错误消息的 500 错误。 如果未将变量设置为 production,则NODE_ENV返回堆栈。

测试本地函数

  1. 在 Visual Studio Code 集成终端中,运行本地项目:

    npm start
    
  2. 等到集成 bash 终端显示正在运行的函数的 URL。

    Visual Studio Code 集成 bash 终端的部分屏幕截图,其中 Azure 函数正在本地运行,并在函数应用中显示了 API 的本地 URL。

  3. 在 Visual Studio Code 中打开第二个集成 bash 终端,Ctrl + Shift + 5,并使用以下 GET cURL 命令来使用 API:

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

    如果订阅中有很多资源组,建议通过管道将输出传递给文件以方便查看。

    curl http://localhost:7071/api/resourcegroups > resourcegroups.json
    
  4. 响应包括 subscriptionIdlist 订阅中的所有资源组。

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

故障排除

如果无法完成本文操作,请查看下表中的问题。 如果你的问题未在表中列出,请在此文档页上创建问题。

问题 修补程序
应用未启动。 查看错误。 请确保已安装所需的依赖项。
应用已启动,但无法获取 200 响应。 请确保你的 curl 命令从正确的本地路由发出请求。
API 返回了 200 响应,但未返回任何结果。 请使用 Azure 资源的 Visual Studio Code 扩展来验证你的订阅是否有任何资源组。 如果看不到任何资源组,请不要担心。 本教程添加了一个 API,用于在订阅中创建和删除资源组。 此 API 的添加操作在第一次将源代码部署到 Azure 后进行,以便你了解如何重新部署代码。

3.创建基于云的 Azure 函数应用

  1. 在 Visual Studio Code 中,选择 Azure 图标以打开 Azure 资源管理器

  2. 选择图标 + 以在 Azure 云中创建新的 Azure 函数应用。

    Visual Studio Code 的 Azure 资源管理器的屏幕截图,其中突出显示了 Azure 函数应用图标。

  3. 选择“在 Azure 中创建函数应用”。

  4. 输入新函数应用的全局唯一 名称 。 该名称在所有 Azure 函数中必须是唯一的。 例如 jsmith-rg-management

  5. 选择创建本地函数应用时选择的同 一Node.js 18+ LTS 运行时

  6. 选择靠近你的地理位置,例如美国西部 3

  7. 等待资源创建完成。 可以查看 Azure:活动日志 以了解详细信息。

    Visual Studio Code 的 Azure 活动日志的屏幕截图,其中显示了资源创建状态。

4.配置基于云的 Azure 函数应用

你需要配置 Azure 应用设置以连接到 Azure 函数应用。 在本地,这些设置位于 local.settings.json 文件中。 此过程会将这些值添加到云应用。

  1. 在 Visual Studio Code 的 Azure 资源管理器 的“资源 ”部分中,展开 Function App ,然后选择函数应用。

  2. 右键单击“应用程序设置”,然后选择“添加新设置”

  3. 用完全相同的名称和值添加 local.settings.json 中的四个值。

    • AZURE_TENANT_ID:上述服务主体输出中的 tenant
    • AZURE_CLIENT_ID:上述服务主体输出中的 appId
    • AZURE_CLIENT_SECRET:上述服务主体输出中的 password
    • AZURE_SUBSCRIPTION_ID:包含资源组的默认订阅。
    • AzureWebJobsFeatureFlags:EnableWorkerIndexing

Visual Studio Code 的 Azure 资源管理器的部分屏幕截图,其中显示远程/云函数的应用设置。

5.部署资源管理器函数应用

在 Visual Studio Code 中部署 Azure 函数应用以管理 Azure 资源组。

使用 Visual Studio Code 扩展来部署到托管环境

  1. 在 VS Code 中 local.settings.json ,打开文件,使其可见。 这将简化复制这些名称和值的后续步骤。

  2. 选择 Azure 徽标以打开 Azure 资源管理器,然后在 Functions,选择要部署应用的云图标。

    Visual Studio Code 的本地工作区区域的屏幕截图,其中突出显示了云部署图标。

    或者,可以通过打开“命令面板”(使用 Ctrl + Shift + p),输入 deploy to function app 并运行“Azure Functions: Deploy to Function App”命令来进行部署

  3. 选择“ 部署到函数应用”。

  4. 选择在上一部分中创建的 Function App 名称。

  5. 当系统询问是否确定要部署时,请选择“ 部署”。

  6. Azure Functions 的 VS Code“输出”面板显示进度。 在部署时,整个 Functions 应用程序将进行部署,因此对所有单个函数的更改将立即部署。

验证通过浏览器提供的 Functions 应用

  1. 在 Visual Studio Code 中,使用“Azure Functions”资源管理器,展开 Azure 订阅的节点,展开 Functions 应用的节点,然后展开“Functions (只读)”。 右键单击函数名称并选择“复制函数 URL”

    Visual Studio Code 的 Azure 资源管理器的部分屏幕截图,其中显示复制函数的 URL 的位置。

  2. 将 URL 粘贴到浏览器中,然后按 Enter 从云 API 请求资源组列表。

6.将 API 添加到函数应用并重新部署到 Azure

添加以下 API,然后在 Visual Studio Code 中重新部署 Azure 函数应用:

  • 添加和删除资源组
  • 列出资源组或订阅中的资源。

在本教程中,你创建了一个具有一个 API 的本地函数应用,用于列出订阅的资源组,并将该应用部署到 Azure。 作为 Azure 开发人员,你可能希望创建或删除资源组,作为流程自动化管道的一部分。

为函数应用创建资源组 API

使用适用于 Azure Functions 的 Visual Studio Code 扩展将 TypeScript 文件添加到函数应用以创建和删除资源组。

  1. 打开 Visual Studio Code 命令面板:Ctrl + Shift + p

  2. 输入 Azure Functions: Create Function,然后按 Enter 开始进程。

  3. 使用下表创建 /api/resourcegroup API:

    Prompt
    选择函数的模板 HTTP 触发器
    提供函数名称 resourcegroup
    授权级别 选择“匿名”。 如果继续执行此项目,请将授权级别更改为函数。 详细了解函数级别授权
  4. ./src/functions/resourcegroup.ts打开并用以下源代码替换整个文件。

    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. 该文件 ./src/lib/azure-resource-groups.ts 已包含用于添加和删除资源组的代码。

为函数应用创建资源 API

使用适用于 Azure Functions 的 Visual Studio Code 扩展将 TypeScript 文件添加到函数应用,以列出资源组中的资源。

  1. 打开 Visual Studio Code 命令面板:Ctrl + Shift + p

  2. 输入 Azure Functions: Create Function,然后按 Enter 开始进程。

  3. 使用下表创建 /api/resources API:

    Prompt
    选择函数的模板 HTTP 触发器
    提供函数名称 resources
    授权级别 选择“匿名”。 如果继续执行此项目,请将授权级别更改为函数。 详细了解函数级别授权
  4. ./src/functions/resources.ts打开并用以下源代码替换整个文件。

    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. ./src/lib/azure-resource.ts创建文件并将以下代码复制到其中以列出资源组中的资源。

    // 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
      };
    };
    

启动本地函数应用并测试新 API

  1. 在 Visual Studio Code 集成终端中,运行本地项目:

    npm start
    
  2. 等到集成 bash 终端显示正在运行的函数的 URL。

    Visual Studio Code 集成 bash 终端的部分屏幕截图,其中 Azure 函数正在本地运行,并在函数应用中显示了 API 的本地 URL。

  3. 使用不同的集成 bash 终端中的以下 curl 命令调用 API,将资源组添加到订阅。 更改资源组的名称以使用自己的命名约定。

    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. 使用以下 curl 命令查看订阅中列出的新资源组。

    curl http://localhost:7071/api/resource-groups
    
  5. 使用以下 curl 命令删除刚添加的资源组。

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

将包含新 API 的函数应用重新部署到 Azure

  1. 在 VS Code 中,使用 Ctrl + Shift + p 打开命令面板,输入deploy to function app并运行 Azure Functions:部署到 Function App 命令进行部署。

  2. 从应用列表中选择你的函数应用。

  3. 从弹出窗口中选择“部署”

  4. 等待部署完成。

使用浏览器验证函数 API

使用前面的 cURL 命令,将 localhost 地址 http://localhost:7071 替换为 Azure 函数资源名称,例如 https://myfunction.azurewebsites.net

7. 查看和查询函数应用日志

在Azure 门户中查看和查询 Azure 函数应用日志。

查询 Azure 函数日志

使用 Azure 门户查看和查询函数日志。

  1. 在 VS Code 中,选择 Azure 徽标来打开 Azure 资源管理器,然后在“函数”下右键单击你的函数应用,再选择“在门户中打开”

    这将打开 Azure 门户指向你的 Azure 函数。

  2. 从“设置”中选择 Application Insights,然后选择“查看 Application Insights 数据”

    显示菜单选项的浏览器屏幕截图。从设置中选择 Application Insights,然后选择“查看 Application Insights 数据”。

    此链接将转到在使用 VS Code 创建 Azure 函数时为你创建的单独指标资源。

  3. 在“监视”部分,选择“日志”。 如果出现“查询”弹出窗口,请选择弹出窗口右上角的 X 将其关闭

  4. 在“架构和筛选器”窗格中,在“表”选项卡上双击“跟踪”表

    这会在查询窗口中输入 Kusto 查询traces

  5. 编辑查询以搜索 API 调用:

    traces 
    | where message startswith "Executing "
    
  6. 选择运行

    如果日志未显示任何结果,可能是因为 HTTP 请求与 Kusto 中的日志可用性之间存在几分钟延迟。 等待几分钟,然后再次运行查询。

    显示对“跟踪”表的 Azure 门户 Kusto 查询结果的浏览器屏幕截图。

    由于创建 Azure 函数应用时已为你添加了 Application Insights 资源,因此无需执行任何额外操作即可获取此日志记录信息:

    • 函数应用为你添加了 Application Insights
    • 查询工具包含在 Azure 门户中。
    • 可以选择 traces ,而无需了解如何编写 Kusto 查询 ,以便从日志中获取最小信息。

8. 清理 Azure 资源

删除资源组

  1. 在 VS Code 中,选择 Azure 徽标以打开 Azure 资源管理器,然后在 Functions右键单击函数应用,然后在门户中选择“打开”。这会打开 Azure 函数的Azure 门户。

  2. 在“ 概述 ”部分中,找到并选择资源组名称。 此操作会将你转到Azure 门户中的资源组。

  3. 资源组页列出与本教程关联的所有资源。

  4. 在顶部菜单中选择“删除资源组”。

  5. 在侧菜单中,输入资源组的名称,然后选择“ 删除”。

删除服务主体

若要删除服务主体,请运行以下命令。 替换为 <YOUR-SERVICE-PRINCIPAL-NAME> 服务主体的名称。

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

示例代码

后续步骤