Udostępnij za pośrednictwem


Zarządzanie grupami zasobów platformy Azure przy użyciu interfejsu API funkcji TypeScript

W tym samouczku utworzysz lokalną aplikację funkcji platformy Azure TypeScript z interfejsami API, aby zarządzać grupami zasobów platformy Azure i wdrażać aplikację na platformie Azure.

Funkcje i funkcje:

  • Tworzenie lokalnego projektu aplikacji funkcji platformy Azure TypeScript w programie Visual Studio Code
  • Tworzenie kodu standardowego interfejsu API funkcji w programie Visual Studio Code
  • Wdrażanie w usłudze Azure Functions z poziomu programu Visual Studio Code
  • Tworzenie jednostki usługi przy użyciu interfejsu wiersza polecenia platformy Azure
  • Konfigurowanie ustawień aplikacji lokalnej i zdalnej przy użyciu programu Visual Studio Code
  • Użyj opcji DefaultAzureCredential w środowiskach lokalnych i zdalnych dla połączeń bez hasła
  • Zarządzanie zasobami platformy Azure przy użyciu zestawów SDK usługi Azure Identity i Azure Resource Management
  • Używanie lokalnych i chmurowych interfejsów API do tworzenia, usuwania i wyświetlania listy grup zasobów w ramach subskrypcji

Ostrzeżenie

Ten samouczek jest przeznaczony do szybkiego wdrażania i w związku z tym nie spełnia wymagań dotyczących bezpieczeństwa domyślnie. Aby dowiedzieć się więcej na temat tego scenariusza z celem bezpiecznym domyślnie, przejdź do sekcji Zagadnienia dotyczące zabezpieczeń.

Kod źródłowy jest napisany przy użyciu języka TypeScript, ale kod źródłowy jest prosty. Jeśli wiesz, jak korzystać z nowoczesnego języka JavaScript przy użyciu async/await, kod będzie Ci znany.

Wymagania wstępne

Architektura aplikacji

Aplikacja udostępnia następujące punkty końcowe interfejsu API.

Method URL opis
POST, DELETE http://localhost:7071/api/resourcegroup Dodawanie lub usuwanie grupy zasobów. Dodając, dołącz tagi (pary klucz/wartość), aby później zidentyfikować cel grupy.
GET http://localhost:7071/api/resourcegroups Wyświetl listę wszystkich grup zasobów w subskrypcji.
GET http://localhost:7071/api/resources Wyświetl listę wszystkich zasobów w subskrypcji lub grupie zasobów.

Chociaż te punkty końcowe są publiczne, należy zabezpieczyć punkty końcowe interfejsu API za pomocą uwierzytelniania i autoryzacji przed wdrożeniem w środowisku na żywo.

Ta aplikacja jest ograniczona do subskrypcji, ponieważ jest to zakres określony podczas tworzenia jednostki usługi.

1. Przygotowywanie środowiska

Musisz przygotować środowiska lokalne i chmurowe do korzystania z zestawu Azure Identity SDK.

Logowanie do interfejsu wiersza polecenia platformy Azure

W terminalu powłoki bash zaloguj się do interfejsu wiersza polecenia platformy Azure przy użyciu następującego polecenia:

az login

Uzyskiwanie identyfikatora subskrypcji platformy Azure

  1. W terminalu powłoki bash pobierz subskrypcje i znajdź identyfikator subskrypcji, której chcesz użyć. Poniższe zapytanie zwraca identyfikator subskrypcji, nazwę subskrypcji i identyfikator dzierżawy posortowane według nazwy subskrypcji.

    az account list --query "sort_by([].{Name:name, SubscriptionId:id, TenantId:tenantId}, &Name)" --output table
    
  2. Skopiuj identyfikator subskrypcji do poprzedniego pliku tymczasowego. To ustawienie będzie potrzebne później.

Tworzenie jednostki usługi platformy Azure

Jednostka usługi platformy Azure zapewnia dostęp do platformy Azure bez konieczności używania poświadczeń użytkownika osobistego. Na potrzeby tego samouczka jednostka usługi może być używana zarówno w środowiskach lokalnych, jak i w chmurze. W środowisku przedsiębiorstwa powinny być potrzebne oddzielne jednostki usługi dla każdego środowiska.

  1. Określ format nazwy głównej usługi, aby później można było łatwo znaleźć jednostkę usługi. Na przykład kilka pojęć dotyczących formatu to:

    • Twój projekt i właściciel: resource-management-john-smith.
    • Dział i data: IT-2021-September
  2. W terminalu powłoki bash utwórz jednostkę usługi za pomocą polecenia az ad sp create-for-rbac. Zastąp <SUBSCRIPTION-ID> ciąg identyfikatorem subskrypcji.

    az ad sp create-for-rbac --name YOUR-SERVICE-PRINCIPAL-NAME --role Contributor --scopes /subscriptions/<SUBSCRIPTION-ID>
    
  3. Skopiuj wszystkie wyniki wyjściowe do pliku tymczasowego. Te ustawienia będą potrzebne później.

    {
      "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. Tworzenie lokalnej aplikacji funkcji platformy Azure w programie Visual Studio Code

Utwórz aplikację funkcji platformy Azure w programie Visual Studio Code, aby zarządzać grupami zasobów platformy Azure.

Tworzenie aplikacji funkcji

Użyj programu Visual Studio Code, aby utworzyć lokalną aplikację funkcji.

  1. W terminalu powłoki bash utwórz i przejdź do nowego katalogu:

    mkdir my-function-app && cd my-function-app
    
  2. W terminalu powłoki bash otwórz program Visual Studio Code:

    code .
    
  3. Otwórz paletę poleceń programu Visual Studio Code: Ctrl + Shift + p.

  4. Wprowadź Azure Functions: create new project. Aby zakończyć monity, użyj poniższej tabeli:

    Monit Wartość
    Wybierz folder, który będzie zawierać projekt funkcji Wybierz domyślny katalog (bieżący)
    Wybierz język Wybierz pozycję TypeScript.
    Wybieranie modelu programowania TypeScript Wybieranie modelu w wersji 4 (wersja zapoznawcza)
    Wybieranie szablonu dla pierwszej funkcji projektu Wybierz pozycję Wyzwalacz HTTP.
    Tworzenie nowego wyzwalacza HTTP Wprowadź nazwę interfejsu API .resourcegroups
    Poziom autoryzacji Wybierz pozycję Anonimowe. Jeśli ten projekt będzie kontynuowany po tym artykule, zmień poziom autoryzacji na funkcję. Dowiedz się więcej o autoryzacji na poziomie funkcji.

    Projekt standardowy jest tworzony i instalowane są zależności.

Dodawanie ustawień jednostki usługi do pliku local.settings.json

  1. Otwórz plik w katalogu głównym projektu i dodaj sekcję ./local.settings.json VALUES z pięcioma następującymi zmiennymi środowiskowymi.

    {
      "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. Zapoznaj się z ustawieniami z poprzedniej sekcji, aby dodać wartości. Te zmienne środowiskowe są wymagane, aby kontekst używał wartości DefaultAzureCredential.

    • AZURE_TENANT_ID: tenant z danych wyjściowych jednostki usługi powyżej.
    • AZURE_CLIENT_ID: appId z danych wyjściowych jednostki usługi powyżej.
    • AZURE_CLIENT_SECRET: password z danych wyjściowych jednostki usługi powyżej.
  3. Należy również ustawić identyfikator subskrypcji. Do zarządzania zasobami jest wymagany zestaw Azure SDK.

    • AZURE_SUBSCRIPTION_ID: Domyślna subskrypcja zawierająca grupy zasobów.

Ten local.settings.json plik jest ignorowany przez lokalną usługę Git celowo, więc nie możesz przypadkowo zatwierdzić go w kodzie źródłowym.

Instalowanie zależności npm na potrzeby zarządzania tożsamościami i zasobami platformy Azure

W zintegrowanym terminalu powłoki bash programu Visual Studio Code zainstaluj zależności zestawu Azure SDK na potrzeby zarządzania tożsamościami i zasobami platformy Azure.

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

Wyświetlanie listy wszystkich grup zasobów w subskrypcji przy użyciu języka JavaScript

  1. ./src/functions/resourcegroups.ts Otwórz plik i zastąp zawartość następującym kodem:

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

    Ten plik odpowiada na żądania interfejsu API do /api/resourcegroups i zwraca listę wszystkich grup zasobów w subskrypcji.

  2. Utwórz podkatalog o src nazwie lib i utwórz nowy plik w tym katalogu o nazwie azure-resource-groups.ts.

  3. Skopiuj następujący kod do ./src/lib/azure-resource-groups.ts pliku:

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

    Ten plik kończy się następującą czynnością:

    • Pobiera identyfikator subskrypcji
    • Tworzy kontekst DefaultAzureCredential
    • Tworzy element ResourceManagementClient wymagany do korzystania z zestawu RESOURCE Management SDK.
    • Pobiera wszystkie grupy zasobów w subskrypcji.
  4. Utwórz nowy plik w ./src/lib katalogu o nazwie environment-vars.ts i skopiuj następujący kod do tego pliku.

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

    Ten plik sprawdza zmienne środowiskowe przed zwróceniem identyfikatora subskrypcji.

  5. Utwórz nowy plik w ./src/lib katalogu o nazwie error.ts i skopiuj następujący kod do tego pliku.

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

    Ten plik zwraca błąd 500 z komunikatem o błędzie. Stos jest zwracany, jeśli zmienna NODE_ENV nie jest ustawiona na productionwartość .

Testowanie funkcji lokalnych

  1. W zintegrowanym terminalu programu Visual Studio Code uruchom projekt lokalny:

    npm start
    
  2. Poczekaj, aż zintegrowany terminal powłoki bash wyświetli adres URL uruchomionej funkcji.

    Częściowy zrzut ekranu przedstawiający zintegrowany terminal powłoki bash programu Visual Studio Code, gdy funkcja platformy Azure działa lokalnie i wyświetla lokalny adres URL interfejsów API w aplikacji funkcji.

  3. Otwórz drugi zintegrowany terminal powłoki bash w programie Visual Studio Code, Ctrl + Shift + 5 i użyj następującego polecenia GET cURL, aby użyć interfejsu API:

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

    Jeśli masz wiele grup zasobów w ramach subskrypcji, możesz chcieć przesłać dane wyjściowe do pliku w celu łatwiejszego przeglądu.

    curl http://localhost:7071/api/resourcegroups > resourcegroups.json
    
  4. Odpowiedź obejmuje subscriptionId wszystkie list grupy zasobów w tej subskrypcji.

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

Rozwiązywanie problemów

Jeśli nie można ukończyć tego artykułu, zapoznaj się z poniższą tabelą pod kątem problemów. Jeśli problem nie znajduje się na liście w tabeli, otwórz problem na tej stronie dokumentacji.

Problem Wprowadzanie poprawek
Aplikacja nie rozpoczęła się. Przejrzyj błędy. Upewnij się, że zainstalowano wymagane zależności.
Aplikacja została uruchomiona, ale nie można uzyskać odpowiedzi 200. Upewnij się, że polecenie curl żąda z prawidłowej trasy lokalnej.
Interfejs API zwrócił odpowiedź 200, ale nie zwrócił żadnych wyników. Użyj rozszerzenia programu Visual Studio Code dla zasobów platformy Azure, aby sprawdzić, czy subskrypcja ma jakiekolwiek grupy zasobów. Jeśli nie widzisz żadnych grup zasobów, nie martw się. Ten samouczek dodaje interfejs API do tworzenia i usuwania grup zasobów w ramach subskrypcji. Ten interfejs API jest dodawany po pierwszym wdrożeniu kodu źródłowego na platformie Azure, aby dowiedzieć się, jak ponownie wdrożyć kod.

3. Tworzenie aplikacji funkcji platformy Azure opartej na chmurze

  1. W programie Visual Studio Code wybierz ikonę platformy Azure, aby otworzyć eksploratora platformy Azure.

  2. Wybierz ikonę, + aby utworzyć nową aplikację funkcji platformy Azure w chmurze platformy Azure.

    Zrzut ekranu przedstawiający Eksplorator platformy Azure programu Visual Studio Code z wyróżnioną ikoną aplikacji funkcji platformy Azure.

  3. Wybierz pozycję Utwórz aplikację funkcji na platformie Azure.

  4. Wprowadź globalnie unikatową nazwę nowej aplikacji funkcji. Nazwa musi być unikatowa we wszystkich funkcjach platformy Azure. Na przykład jsmith-rg-management.

  5. Wybierz to samo środowisko uruchomieniowe Node.js 18+ LTS wybrane podczas tworzenia lokalnej aplikacji funkcji.

  6. Wybierz lokalizację geograficzną w pobliżu, taką jak Zachodnie stany USA 3.

  7. Poczekaj na utworzenie zasobu. Aby uzyskać szczegółowe informacje, możesz obejrzeć dziennik aktywności platformy Azure.

    Zrzut ekranu przedstawiający dziennik aktywności platformy Azure programu Visual Studio Code przedstawiający stan tworzenia zasobów.

4. Konfigurowanie aplikacji funkcji platformy Azure opartej na chmurze

Musisz skonfigurować ustawienia aplikacji platformy Azure, aby nawiązać połączenie z aplikacją funkcji platformy Azure. Lokalnie te ustawienia znajdują się w pliku local.settings.json . Ten proces dodaje te wartości do aplikacji w chmurze.

  1. W programie Visual Studio Code w eksploratorze platformy Azure w sekcji Zasoby rozwiń węzeł Aplikacja funkcji, a następnie wybierz aplikację funkcji.

  2. Kliknij prawym przyciskiem myszy pozycję Ustawienia aplikacji i wybierz pozycję Dodaj nowe ustawienie.

  3. Dodaj cztery wartości ze swojej local.settings.json nazwy i wartości.

    • AZURE_TENANT_ID: tenant z danych wyjściowych jednostki usługi powyżej.
    • AZURE_CLIENT_ID: appId z danych wyjściowych jednostki usługi powyżej.
    • AZURE_CLIENT_SECRET: password z danych wyjściowych jednostki usługi powyżej.
    • AZURE_SUBSCRIPTION_ID: Domyślna subskrypcja zawierająca grupy zasobów.
    • AzureWebJobsFeatureFlags:EnableWorkerIndexing

Częściowy zrzut ekranu eksploratora platformy Azure programu Visual Studio Code przedstawiający ustawienia aplikacji funkcji zdalnej/chmury.

5. Wdrażanie aplikacji funkcji usługi Resource Manager

Wdrażanie aplikacji funkcji platformy Azure w programie Visual Studio Code w celu zarządzania grupami zasobów platformy Azure.

Wdrażanie w środowisku hostingu przy użyciu rozszerzenia programu Visual Studio Code

  1. W programie VS Code otwórz local.settings.json plik, aby był widoczny. Ułatwi to skopiowanie tych nazw i wartości.

  2. Wybierz logo platformy Azure, aby otworzyć Eksplorator platformy Azure, a następnie w obszarze Funkcje wybierz ikonę chmury, aby wdrożyć aplikację.

    Zrzut ekranu przedstawiający lokalny obszar roboczy programu Visual Studio Code z wyróżnioną ikoną wdrożenia w chmurze.

    Alternatywnie możesz wdrożyć, otwierając paletę poleceń za pomocą Ctrl + Shift + p, wprowadzając deploy to function apppolecenie i uruchamiając polecenie Azure Functions: Deploy to Function App ( Wdrażanie w aplikacji funkcji).

  3. Wybierz pozycję Wdróż w aplikacji funkcji.

  4. Wybierz nazwę aplikacji funkcji utworzoną w poprzedniej sekcji.

  5. Po wyświetleniu monitu o to, czy na pewno chcesz wdrożyć, wybierz pozycję Wdróż.

  6. Panel Dane wyjściowe programu VS Code dla usługi Azure Functions pokazuje postęp. Podczas wdrażania cała aplikacja usługi Functions jest wdrażana, więc zmiany we wszystkich funkcjach są wdrażane jednocześnie.

Sprawdzanie, czy aplikacja usługi Functions jest dostępna w przeglądarce

  1. Nadal w programie Visual Studio Code użyj eksploratora usługi Azure Functions, rozwiń węzeł subskrypcji platformy Azure, rozwiń węzeł aplikacji usługi Functions, a następnie rozwiń węzeł Funkcje (tylko do odczytu). Kliknij prawym przyciskiem myszy nazwę funkcji i wybierz pozycję Kopiuj adres URL funkcji:

    Częściowy zrzut ekranu przedstawiający eksploratora platformy Azure programu Visual Studio Code pokazujący, gdzie skopiować adres URL funkcji.

  2. Wklej adres URL w przeglądarce i naciśnij Enter , aby zażądać listy grup zasobów z interfejsu API chmury.

6. Dodawanie interfejsów API do aplikacji funkcji i ponowne wdrażanie na platformie Azure

Dodaj następujące interfejsy API, a następnie ponownie wdróż aplikację funkcji platformy Azure w programie Visual Studio Code:

  • Dodawanie i usuwanie grup zasobów
  • Wyświetlanie listy zasobów w grupie zasobów lub subskrypcji.

W tym momencie w samouczku utworzono lokalną aplikację funkcji z jednym interfejsem API, aby wyświetlić listę grup zasobów subskrypcji i wdrożono tę aplikację na platformie Azure. Jako deweloper platformy Azure możesz utworzyć lub usunąć grupy zasobów w ramach potoku automatyzacji procesów.

Tworzenie interfejsu API grupy zasobów dla aplikacji funkcji

Użyj rozszerzenia programu Visual Studio Code dla usługi Azure Functions, aby dodać pliki TypeScript do aplikacji funkcji w celu utworzenia i usunięcia grup zasobów.

  1. Otwórz paletę poleceń programu Visual Studio Code: Ctrl + Shift + p.

  2. Wprowadź, a następnie naciśnij Enter Azure Functions: Create Function , aby rozpocząć proces.

  3. Użyj poniższej tabeli, aby utworzyć interfejs API /api/resourcegroup :

    Monit Wartość
    Wybieranie szablonu dla funkcji Wyzwalacz HTTP
    Podaj nazwę funkcji resourcegroup
    Poziom autoryzacji Wybierz pozycję Anonimowe. Jeśli będziesz kontynuować pracę z tym projektem, zmień poziom autoryzacji na funkcję. Dowiedz się więcej o autoryzacji na poziomie funkcji.
  4. Otwórz plik ./src/functions/resourcegroup.ts i zastąp cały plik następującym kodem źródłowym.

    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. Plik ./src/lib/azure-resource-groups.ts zawiera już kod umożliwiający dodawanie i usuwanie grup zasobów.

Tworzenie interfejsu API zasobów dla aplikacji funkcji

Użyj rozszerzenia programu Visual Studio Code dla usługi Azure Functions, aby dodać pliki TypeScript do aplikacji funkcji, aby wyświetlić listę zasobów w grupie zasobów.

  1. Otwórz paletę poleceń programu Visual Studio Code: Ctrl + Shift + p.

  2. Wprowadź, a następnie naciśnij Enter Azure Functions: Create Function , aby rozpocząć proces.

  3. Użyj poniższej tabeli, aby utworzyć interfejs API /api/resources :

    Monit Wartość
    Wybieranie szablonu dla funkcji Wyzwalacz HTTP
    Podaj nazwę funkcji resources
    Poziom autoryzacji Wybierz pozycję Anonimowe. Jeśli będziesz kontynuować pracę z tym projektem, zmień poziom autoryzacji na funkcję. Dowiedz się więcej o autoryzacji na poziomie funkcji.
  4. Otwórz plik ./src/functions/resources.ts i zastąp cały plik następującym kodem źródłowym.

    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 Utwórz plik i skopiuj do niego następujący kod, aby wyświetlić listę zasobów w grupie zasobów.

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

Uruchamianie lokalnej aplikacji funkcji i testowanie nowego interfejsu API

  1. W zintegrowanym terminalu programu Visual Studio Code uruchom projekt lokalny:

    npm start
    
  2. Poczekaj, aż zintegrowany terminal powłoki bash wyświetli adres URL uruchomionej funkcji.

    Częściowy zrzut ekranu przedstawiający zintegrowany terminal powłoki bash programu Visual Studio Code, gdy funkcja platformy Azure działa lokalnie i wyświetla lokalne adresy URL interfejsów API w aplikacji funkcji.

  3. Użyj następujących poleceń curl w innym zintegrowanym terminalu powłoki bash, aby wywołać interfejs API, aby dodać grupę zasobów do subskrypcji. Zmień nazwę grupy zasobów, aby używać własnych konwencji nazewnictwa.

    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. Użyj następującego polecenia curl, aby wyświetlić nową grupę zasobów wymienioną w subskrypcji.

    curl http://localhost:7071/api/resource-groups
    
  5. Użyj następującego polecenia curl, aby usunąć właśnie dodaną grupę zasobów.

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

Ponowne wdrażanie aplikacji funkcji przy użyciu nowych interfejsów API na platformie Azure

  1. W programie VS Code wdróż, otwierając paletę poleceń za pomocą Ctrl + Shift + p, wprowadzając deploy to function apppolecenie i uruchamiając polecenie Azure Functions: Deploy to Function App ( Wdrażanie w aplikacji funkcji).

  2. Wybierz aplikację funkcji z listy aplikacji.

  3. Wybierz pozycję Wdróż w oknie podręcznym.

  4. Poczekaj na zakończenie wdrażania.

Weryfikowanie interfejsów API funkcji za pomocą przeglądarki

Użyj poprzednich poleceń cURL, zastępując adres localhost nazwą zasobu funkcji platformy Azure, http://localhost:7071 taką jak https://myfunction.azurewebsites.net.

7. Wyświetlanie i wykonywanie zapytań dotyczących dzienników aplikacji funkcji

Wyświetlanie i wykonywanie zapytań dotyczących dzienników aplikacji funkcji platformy Azure w witrynie Azure Portal.

Wykonywanie zapytań względem dzienników funkcji platformy Azure

Użyj witryny Azure Portal, aby wyświetlić dzienniki funkcji i wykonywać względem nich zapytania.

  1. W programie VS Code wybierz logo platformy Azure, aby otworzyć Eksplorator platformy Azure, a następnie w obszarze Funkcje kliknij prawym przyciskiem myszy aplikację funkcji, a następnie wybierz polecenie Otwórz w portalu.

    Spowoduje to otwarcie witryny Azure Portal dla funkcji platformy Azure.

  2. Wybierz pozycję Application Insights w obszarze Ustawienia, a następnie wybierz pozycję Wyświetl dane usługi Application Insights.

    Zrzut ekranu przeglądarki przedstawiający opcje menu. Wybierz pozycję Application Insights w obszarze Ustawienia, a następnie wybierz pozycję Wyświetl dane usługi Application Insights.

    Ten link umożliwia przejście do oddzielnego zasobu metryk utworzonego podczas tworzenia funkcji platformy Azure za pomocą programu VS Code.

  3. Wybierz pozycję Dzienniki w sekcji Monitorowanie. Jeśli zostanie wyświetlone okno podręczne Zapytania, wybierz ikonę X w prawym górnym rogu wyskakującego okienka, aby go zamknąć.

  4. W okienku Schemat i filtr na karcie Tabele kliknij dwukrotnie tabelę śladów .

    Spowoduje to wprowadzenie zapytaniatraces Kusto w oknie zapytania.

  5. Edytuj zapytanie, aby wyszukać wywołania interfejsu API:

    traces 
    | where message startswith "Executing "
    
  6. Wybierz Uruchom.

    Jeśli dziennik nie wyświetli żadnych wyników, może to być spowodowane kilkuminutowym opóźnieniem między żądaniem HTTP a dostępnością dziennika w usłudze Kusto. Zaczekaj kilka minut i ponownie uruchom zapytanie.

    Zrzut ekranu przeglądarki przedstawiający wynik zapytania kusto witryny Azure Portal dla tabeli Trace.

    Ponieważ zasób usługi Application Insights został dodany do Ciebie podczas tworzenia aplikacji funkcji platformy Azure, nie trzeba wykonywać żadnych dodatkowych czynności, aby uzyskać te informacje rejestrowania:

    • Aplikacja funkcji dodała usługę Application Insights.
    • Narzędzie Zapytanie znajduje się w witrynie Azure Portal.
    • Możesz wybrać traces zamiast nauczyć się pisać zapytanie Kusto, aby uzyskać nawet minimalne informacje z dzienników.

8. Czyszczenie zasobów platformy Azure

Usuwanie grupy zasobów

  1. W programie VS Code wybierz logo platformy Azure, aby otworzyć Eksplorator platformy Azure, a następnie w obszarze Funkcje kliknij prawym przyciskiem myszy aplikację funkcji, a następnie wybierz polecenie Otwórz w portalu. Spowoduje to otwarcie witryny Azure Portal dla funkcji platformy Azure.

  2. W sekcji Przegląd znajdź i wybierz nazwę grupy zasobów. Ta akcja powoduje przejście do grupy zasobów w witrynie Azure Portal.

  3. Strona grupy zasobów zawiera listę wszystkich zasobów skojarzonych z tym samouczkiem.

  4. Wybierz pozycję Usuń grupę zasobów w górnym menu.

  5. W menu bocznym wprowadź nazwę grupy zasobów, a następnie wybierz pozycję Usuń.

Usuwanie jednostki usługi

Aby usunąć jednostkę usługi, uruchom następujące polecenie. Zastąp <YOUR-SERVICE-PRINCIPAL-NAME> ciąg nazwą jednostki usługi.

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

Przykładowy kod

Zagadnienia dotyczące zabezpieczeń

To rozwiązanie, jako samouczek dla początkujących, nie demonstruje praktyk bezpiecznych domyślnie. Jest to zamierzone, aby umożliwić pomyślne wdrożenie rozwiązania. Następnym krokiem po pomyślnym wdrożeniu jest zabezpieczenie zasobów. To rozwiązanie korzysta z trzech usług platformy Azure, z których każdy ma własne funkcje zabezpieczeń i zagadnienia dotyczące konfiguracji zabezpieczeń domyślnie:

Następne kroki