Azure SDK for .NET を使用したリソース管理

Azure SDK for .NET 管理プレーン ライブラリは、.NET アプリケーション内から Azure リソースを作成、プロビジョニング、管理するのに役立ちます。 すべての Azure サービスには、対応する管理ライブラリがあります。

管理ライブラリ (Azure.ResourceManager で始まる名前空間、たとえば Azure.ResourceManager.Compute) を使用すると、Azure portal、Azure CLI、またはその他のリソース管理ツールから実行できるものと同じタスクを実行する構成およびデプロイ プログラムを記述できます。

これらのパッケージは、新しい Azure SDK ガイドラインに従います。これは、すべての Azure SDK 間で共有される以下のようなコア機能を提供します。

  • 直観的な Azure ID ライブラリ。
  • カスタム ポリシーを持つ HTTP パイプライン。
  • エラー処理。
  • 分散トレース。

注意

一部のパッケージはまだプレリリース バージョンであり、追加の Azure サービスの管理プレーン ライブラリについては段階的なリリースが進行中であることに注意してください。 特定の Azure リソースの安定バージョンのパッケージを探しているにも関わらず、現在プレリリース バージョンしか利用できない場合は、Azure SDK for .NET Github リポジトリで issue を提起してください

作業の開始

前提条件

パッケージをインストールする

Azure Identity と .NET 用の Azure リソース管理 NuGet パッケージをインストールします。 次に例を示します。

Install-Package Azure.Identity
Install-Package Azure.ResourceManager
Install-Package Azure.ResourceManager.Resources
Install-Package Azure.ResourceManager.Compute
Install-Package Azure.ResourceManager.Network

クライアントを認証する

認証されたクライアントを作成するための既定のオプションは、DefaultAzureCredential を使用することです。 すべての管理 API は同じエンドポイントを通過するため、リソースを操作するには、1 つの最上位レベル ArmClient のみを作成する必要があります。

Azure で認証し、ArmClient を作成して、特定の資格情報 ArmClient のインスタンスを作成するには、次のようにします。

using Azure.Identity;
using Azure.ResourceManager;
using System;
using System.Threading.Tasks;

// Code omitted for brevity

ArmClient client = new ArmClient(new DefaultAzureCredential());

Azure.Identity.DefaultAzureCredential クラスの詳細については、「DefaultAzureCredential クラス」を参照してください。

管理 SDK チート シート

一般的な Azure Service Bus 名前空間の作成、一覧表示、更新、削除を行うタスクがあるとして、.NET 用の Azure 管理 SDK の使用を開始するには、次の手順に従います。

  1. 作業するサブスクリプションとリソース グループに対して認証を行います。
using Azure.Identity;
using Azure.ResourceManager;
using Azure.ResourceManager.ServiceBus;

ArmClient client = new ArmClient(new DefaultAzureCredential());
SubscriptionResource subscription = client.GetDefaultSubscription();
ResourceGroupResource resourceGroup =
    client.GetDefaultSubscription().GetResourceGroup(resourceGroupName);
  1. Azure リソースを管理するための対応する方法を見つけます。
操作 メソッド
リソース識別子を使用してリソースを取得する client.GetServiceBusQueueResource(ResourceIdentifier resourceIdentifier)
List resourceGroup.GetServiceBusNamespaces()
インデックス resourceGroup.GetServiceBusNamespace(string servicebusNamespaceName)
追加または更新 resourceGroup.GetServiceBusNamespaces().CreateOrUpdate(Azure.WaitUntil waitUntil, string name, ServiceBusNamespaceData data)
Contains resourceGroup.GetServiceBusNamespaces().Exists(string servicebusNamespaceName)
削除 client.GetServiceBusQueueResource(ResourceIdentifior resourceIdentifior).Delete() または resourceGroup.GetServiceBusNamespace(string servicebusNamespaceName).Delete()

リソース グループ自体を含むすべての Azure リソースは、上記の例のようなコードを使用して、対応する管理 SDK によって管理できることに注意してください。 適切な Azure 管理 SDK パッケージを見つけるには、名前のパターンが Azure.ResourceManager.{ResourceProviderName} であるパッケージを探します。

ResourceIdentifier の詳細については、「構造化リソース識別子」を参照してください。

主要な概念

Azure リソースの階層について

一般的なタスクを実行するために必要なクライアントの数と、各クライアントで使用される冗長なパラメーターの数を減らすために、SDK には Azure のオブジェクト階層を模倣するオブジェクト階層が導入されています。 SDK の各リソース クライアントには、スコープが既に適切なサブスクリプションとリソース グループに設定されている、その子のリソース クライアントにアクセスするためのメソッドが含まれています。

これを実現するために、Azure のすべてのリソースには次の 3 つの標準型が導入されています。

{ResourceName}Resource クラス

この型は、詳細を {ResourceName}Data 型として公開する Data プロパティを含む完全なリソース クライアント オブジェクトを表します。 また、サブスクリプション ID やリソース名などのスコープ パラメーターを渡すことなく、そのリソースのすべての操作にアクセスすることもできます。 これにより、すべてが完全なリソース クライアントとして返されるようになったため、リスト呼び出しの結果に対して操作を直接実行でき、非常に便利です。

ArmClient client = new ArmClient(new DefaultAzureCredential());
string resourceGroupName = "myResourceGroup";
SubscriptionResource subscription = await client.GetDefaultSubscriptionAsync();
ResourceGroupResource resourceGroup = await subscription.GetResourceGroupAsync(resourceGroupName);
await foreach (VirtualMachineResource virtualMachine in resourceGroup.GetVirtualMachinesAsync())
{
    //previously we would have to take the resourceGroupName and the vmName from the vm object
    //and pass those into the powerOff method as well as we would need to execute that on a separate compute client
    await virtualMachine.PowerOffAsync(WaitUntil.Completed);
}

{ResourceName}Data クラス

この型は、特定のリソースを構成するモデルを表します。 通常、これは HTTP GET などのサービス呼び出しからの応答データであり、基になるリソースに関する詳細情報を提供します。 以前、これは Model クラスによって表されていました。

{ResourceName}Collection クラス

この型は、特定の親リソースに属するリソースのコレクションに対して実行できる操作を表します。 このオブジェクトにより、ほとんどの論理コレクション操作が提供されます。

コレクションの動作 コレクション メソッド
反復/リスト GetAll()
インデックス Get(文字列名)
追加 CreateOrUpdate(Azure.WaitUntil waitUntil, 文字列名, {ResourceName}Data データ)
Contains Exists(文字列名)

ほとんどの場合、リソースの親は ResourceGroup ですが、場合によっては、リソース自体にサブリソースが含まれることがあります。たとえば、SubnetVirtualNetwork の子です。 ResourceGroup 自体は Subscription の子です。

まとめ

会社で、すべての仮想マシンに所有者のタグを付ける必要があるとしましょう。 私たちは、特定のリソース グループ内で不足しているすべての仮想マシンにタグを追加するプログラムの作成を任せられました。

// First we construct our armClient
ArmClient client = new ArmClient(new DefaultAzureCredential());

// Next we get a resource group object
// ResourceGroup is a {ResourceName}Resource object from above
SubscriptionResource subscription = await client.GetDefaultSubscriptionAsync();
ResourceGroupResource resourceGroup =
   await subscription.GetResourceGroupAsync("myRgName");

// Next we get the collection for the virtual machines
// vmCollection is a {ResourceName}Collection object from above
VirtualMachineCollection virtualMachineCollection = await resourceGroup.GetVirtualMachines();

// Next we loop over all vms in the collection
// Each vm is a {ResourceName}Resource object from above
await foreach(VirtualMachineResource virtualMachine in virtualMachineCollection)
{
   // We access the {ResourceName}Data properties from vm.Data
   if(!virtualMachine.Data.Tags.ContainsKey("owner"))
   {
       // We can also access all operations from vm since it is already scoped for us
       await virtualMachine.AddTagAsync("owner", GetOwner());
   }
}

構造化リソース識別子

リソース ID にはリソース自体に関する有用な情報が含まれていますが、プレーンな文字列であり、解析が必要です。 独自の解析ロジックを実装する代わりに、解析を実行する ResourceIdentifier オブジェクトを使用できます。

例: ResourceIdentifier オブジェクトを使用した ID の解析

string resourceId = "/subscriptions/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/resourceGroups/workshop2021-rg/providers/Microsoft.Network/virtualNetworks/myVnet/subnets/mySubnet";
ResourceIdentifier id = new ResourceIdentifier(resourceId);
Console.WriteLine($"Subscription: {id.SubscriptionId}");
Console.WriteLine($"ResourceGroup: {id.ResourceGroupName}");
Console.WriteLine($"Vnet: {id.Parent.Name}");
Console.WriteLine($"Subnet: {id.Name}");

ただし、これらのプロパティの一部が null 値になる可能性があることに注意してください。 通常、ID 文字列自体によって、リソース ID がどの型であるかがわかります。 ただし、不明な場合は、プロパティが null 値かどうかを確認します。

例: リソース識別子ジェネレーター

純粋な string から resourceId を手動で作成したくない場合があります。 各 {ResourceName}Resource クラスには、リソース識別子文字列を作成するのに役立つ静的メソッドがあります。

ResourceIdentifier resourceId =
    AvailabilitySetResource.CreateResourceIdentifier(
        "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
        "resourceGroupName",
        "resourceName");

既存のリソースを管理する

管理クライアント ライブラリを使用する場合、既に存在するリソースで操作を実行することは一般的なユース ケースです。 このシナリオでは、通常、文字列として使用するリソースの識別子を指定します。 新しいオブジェクト階層は、特定の親のスコープ内でのプロビジョニングと操作には適していますが、このシナリオに関していえば、最も効率的とはなりません。

AvailabilitySetResource オブジェクトにアクセスし、そのリソース識別子で直接管理する方法の例を次に示します

using Azure.Identity;
using Azure.ResourceManager;
using Azure.ResourceManager.Resources;
using Azure.ResourceManager.Compute;
using System;
using System.Threading.Tasks;

// Code omitted for brevity

ResourceIdentifier subscriptionId =
    SubscriptionResource.CreateResourceIdentifier("aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee");

ResourceIdentifier resourceId =
    AvailabilitySetResource.CreateResourceIdentifier(
        subscriptionId.SubscriptionId,
        "resourceGroupName",
        "resourceName");

// We construct a new armClient to work with
ArmClient client = new ArmClient(new DefaultAzureCredential());
// Next we get the specific subscription this resource belongs to
SubscriptionResource subscription = client.GetSubscriptionResource(subscriptionId);
// Next we get the specific resource group this resource belongs to
ResourceGroupResource resourceGroup = await subscription.GetResourceGroupAsync(resourceId.ResourceGroupName);
// Finally we get the resource itself
// Note: for this last step in this example, Azure.ResourceManager.Compute is needed
AvailabilitySetResource availabilitySet = await resourceGroup.GetAvailabilitySetAsync(resourceId.Name);

この方法では、多数のコードと、Azure に対して 3 回の API 呼び出しが必要でした。 提供されている拡張メソッドをクライアント自体で使用すると、同じことを少ないコードで、API 呼び出しを必要とせずに行うことができます。 これらの拡張メソッドを使用すると、リソース識別子を渡し、スコープが設定されているリソース クライアントを取得できます。 返されるオブジェクトは、{ResourceName}Resource です。 データを取得するためにまだ Azure にアクセスしていないため、Data プロパティを呼び出すと例外がスローされます。HasData プロパティを使用して、リソース インスタンスにデータが含まれているかどうかを確認するか、リソースで Get または GetAsync メソッドを呼び出してリソース データを取得することができます。

そのため、上の例は、最終的に次のようになります。

ResourceIdentifier resourceId =
    AvailabilitySetResource.CreateResourceIdentifier(
        "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
        "resourceGroupName",
        "resourceName");
// We construct a new armClient to work with
ArmClient client = new ArmClient(new DefaultAzureCredential());
// Next we get the AvailabilitySet resource client from the armClient
// The method takes in a ResourceIdentifier but we can use the implicit cast from string
AvailabilitySetResource availabilitySet = client.GetAvailabilitySetResource(resourceId);
// At this point availabilitySet.Data will be null and trying to access it will throw exception
// If we want to retrieve the objects data we can simply call get
availabilitySet = await availabilitySet.GetAsync();
// we now have the data representing the availabilitySet
Console.WriteLine(availabilitySet.Data.Name);

リソースが存在するかどうかを確認する

取得するリソースが存在するかどうかが不明な場合、または単にそのリソースが存在するかどうかを確認したい場合、Exists() または ExistsAsync() メソッドを使用できます。これらは、任意の {ResourceName}Collection クラスから呼び出すことができます。

Exists() では Response<bool> が返されますが、その非同期バージョンとしての ExistsAsync() では、Task<Response<bool>> が返されます。 Response<bool> オブジェクトでは、その Value プロパティにアクセスしてリソースが存在するかどうかを確認できます。 リソースが存在しない場合、Valuefalse であり、その逆も同様です。

以前のバージョンのパッケージでは、RequestFailedException をキャッチし、状態コードが 404 かどうかを検査する必要がありました。 この新しい API により、開発者の生産性が向上し、リソース アクセスが最適化されることを期待しています。

ArmClient client = new ArmClient(new DefaultAzureCredential());
SubscriptionResource subscription = await client.GetDefaultSubscriptionAsync();
string resourceGroupName = "myRgName";

try
{
    ResourceGroupResource resourceGroup = await subscription.GetResourceGroupAsync(resourceGroupName);
    // At this point, we are sure that myRG is a not null Resource Group, so we can use this object to perform any operations we want.
}
catch (RequestFailedException ex) when (ex.Status == 404)
{
    Console.WriteLine($"Resource Group {resourceGroupName} does not exist.");
}

次に、これらの便利なメソッドを使用すると、以下を簡単に行うことができます。

ArmClient client = new ArmClient(new DefaultAzureCredential());
SubscriptionResource subscription = await client.GetDefaultSubscriptionAsync();
string resourceGroupName = "myRgName";

bool exists = await subscription.GetResourceGroups().ExistsAsync(resourceGroupName).Value;

if (exists)
{
    Console.WriteLine($"Resource Group {resourceGroupName} exists.");

    // We can get the resource group now that we know it exists.
    // This does introduce a small race condition where resource group could have been deleted between the check and the get.
    ResourceGroupResource resourceGroup = await subscription.GetResourceGroupAsync(resourceGroupName);
}
else
{
    Console.WriteLine($"Resource Group {rgName} does not exist.");
}

リソース グループを作成する

// First, initialize the ArmClient and get the default subscription
ArmClient client = new ArmClient(new DefaultAzureCredential());
// Now we get a ResourceGroup collection for that subscription
SubscriptionResource subscription = await client.GetDefaultSubscriptionAsync();
ResourceGroupCollection resourceGroupCollection = subscription.GetResourceGroups();

// With the collection, we can create a new resource group with an specific name
string resourceGroupName = "myRgName";
AzureLocation location = AzureLocation.WestUS2;
ResourceGroupData resourceGroupData = new ResourceGroupData(location);
ResourceGroupResource resourceGroup = (await resourceGroupCollection.CreateOrUpdateAsync(resourceGroupName, resourceGroupData)).Value;

すべてのリソース グループの一覧表示

// First, initialize the ArmClient and get the default subscription
ArmClient client = new ArmClient(new DefaultAzureCredential());
SubscriptionResource subscription = await client.GetDefaultSubscriptionAsync();
// Now we get a ResourceGroup collection for that subscription
ResourceGroupCollection resourceGroupCollection = subscription.GetResourceGroups();
// With GetAllAsync(), we can get a list of the resources in the collection
await foreach (ResourceGroupResource resourceGroup in resourceGroupCollection)
{
    Console.WriteLine(resourceGroup.Data.Name);
}

リソース グループの更新

// Note: Resource group named 'myRgName' should exist for this example to work.
ArmClient client = new ArmClient(new DefaultAzureCredential());
SubscriptionResource subscription = await client.GetDefaultSubscriptionAsync();
string resourceGroupName = "myRgName";
ResourceGroupResource resourceGroup = await subscription.GetResourceGroupAsync(resourceGroupName);
resourceGroup = await resourceGroup.AddTagAsync("key", "value");

リソース グループの削除

ArmClient client = new ArmClient(new DefaultAzureCredential());
SubscriptionResource subscription = await client.GetDefaultSubscriptionAsync();
string resourceGroupName = "myRgName";
ResourceGroupResource resourceGroup = await subscription.GetResourceGroupAsync(resourceGroupName);
await resourceGroup.DeleteAsync();

より詳細な例については、サンプルを用意していますので、ご覧ください。

トラブルシューティング

  • 報告するバグがある場合、または提案がある場合は、GitHub の issue から issue を報告し、issue に "Preview" ラベルを追加してください。
  • ヘルプが必要な場合は、過去の質問を確認するか、StackOverflow で Azure および .NET タグを使用して新たに質問してください。
  • 認証に問題がある場合は、DefaultAzureCredential のドキュメントを参照してください。

次のステップ

その他のサンプル コード

その他のドキュメント

以前の SDK からこのプレビューに移行する場合は、こちらの移行ガイドを確認してください。

Azure SDK の詳細については、「Azure SDK のリリース」を参照してください。