Bibliothèque de client Microsoft Azure Resource Manager pour .NET

Microsoft Azure Resource Manager est le service de déploiement et de gestion pour Azure. Il fournit une couche de gestion qui vous permet de créer, de mettre à jour et de supprimer des ressources dans votre compte Azure.

Cette bibliothèque fournit des fonctionnalités de gestion des groupes de ressources et des ressources pour Microsoft Azure.

Cette bibliothèque suit les nouvelles recommandations du Kit de développement logiciel (SDK) Azure et fournit de nombreuses fonctionnalités de base :

- Support MSAL.NET, Azure.Identity is out of box for supporting MSAL.NET.
- Support [OpenTelemetry](https://opentelemetry.io/) for distributed tracing.
- HTTP pipeline with custom policies.
- Better error-handling.
- Support uniform telemetry across all languages.

Prise en main

Installer le package

Installez la bibliothèque principale de gestion des ressources Microsoft Azure pour .NET avec NuGet :

dotnet add package Azure.ResourceManager

Prérequis

Authentifier le client

L'option par défaut pour créer un client authentifié consiste à utiliser DefaultAzureCredential. Comme toutes les API de gestion passent par le même point de terminaison, pour interagir avec les ressources, un seul niveau supérieur ArmClient doit être créé.

Pour vous authentifier auprès d’Azure et créer un ArmClient, effectuez le code suivant :

using System;
using System.Threading.Tasks;
using Azure.Core;
using Azure.Identity;
using Azure.ResourceManager;
using Azure.ResourceManager.Compute;
using Azure.ResourceManager.Resources;
ArmClient client = new ArmClient(new DefaultAzureCredential());

Vous trouverez plus de documentation pour la Azure.Identity.DefaultAzureCredential classe dans ce document.

Concepts clés

Présentation de la hiérarchie des ressources Azure

Pour réduire à la fois le nombre de clients nécessaires pour effectuer des tâches courantes et le nombre de paramètres redondants que chacun de ces clients accepte, nous avons introduit une hiérarchie d’objets dans le KIT de développement logiciel (SDK) qui imite la hiérarchie d’objets dans Azure. Chaque client de ressources du kit SDK propose des méthodes permettant d'accéder aux clients de ressources de ses enfants qui sont déjà associés à l'abonnement et au groupe de ressources appropriés.

Pour atteindre cet objectif, nous introduisons trois types standard pour toutes les ressources dans Azure :

[Ressource] Resource.cs

Cette classe représente un objet client de ressource complet qui contient une propriété Data qui expose les détails sous la forme d’un type [Ressource]Données . Il a également accès à toutes les opérations sur cette ressource sans avoir à passer des paramètres de portée tels que l'ID de l'abonnement ou le nom de la ressource. Cette classe de ressources facilite l’exécution directe d’opérations sur le résultat des appels de liste, car tout est retourné en tant que client de ressources complet.

ArmClient client = new ArmClient(new DefaultAzureCredential());
string resourceGroupName = "myResourceGroup";
SubscriptionResource subscription = await client.GetDefaultSubscriptionAsync();
ResourceGroupCollection resourceGroups = subscription.GetResourceGroups();
ResourceGroupResource resourceGroup = await resourceGroups.GetAsync(resourceGroupName);
await foreach (VirtualMachineResource virtualMachine in resourceGroup.GetVirtualMachines())
{
    //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);
}

[Ressource] Data.cs

Cette classe représente le modèle qui compose une ressource donnée. En règle générale, cette classe est les données de réponse d’un appel de service tel que HTTP GET et fournit des détails sur la ressource sous-jacente. Auparavant, cette classe était représentée par une classe Model .

[Ressource] Collection.cs

Cette classe représente les opérations que vous pouvez effectuer sur une collection de ressources appartenant à une ressource parente spécifique. Cette classe fournit la plupart des opérations de collection logique.

Comportement de collection Méthode de collection
Itérer/Répertorier GetAll()
Index Get(nom de chaîne)
Ajouter CreateOrUpdate(string name, [Resource]Data data)
Contient Exists(nom de chaîne)

Pour la plupart des choses, le parent est un ResourceGroup. Par exemple, un sous-réseau est un enfant d’un virtualNetwork et un groupe de ressources est un enfant d’un abonnement.

Exemple complet

Imaginez que notre entreprise exige que toutes les machines virtuelles soient étiquetées pour indiquer leur propriétaire. Nous sommes chargés d’écrire un programme pour ajouter l’étiquette à toutes les machines virtuelles manquantes dans un groupe de ressources donné.

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

// Next we get a resource group object
// ResourceGroupResource is a [Resource] object from above
SubscriptionResource subscription = await client.GetDefaultSubscriptionAsync();
ResourceGroupCollection resourceGroups = subscription.GetResourceGroups();
ResourceGroupResource resourceGroup = await resourceGroups.GetAsync("myRgName");

// Next we get the collection for the virtual machines
// vmCollection is a [Resource]Collection object from above
VirtualMachineCollection virtualMachines = resourceGroup.GetVirtualMachines();

// Next we loop over all vms in the collection
// Each vm is a [Resource] object from above
await foreach (VirtualMachineResource virtualMachine in virtualMachines)
{
   // We access the [Resource]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", "tagValue");
   }
}

Structured Resource Identifier

Les ID de ressource contiennent des informations utiles sur la ressource elle-même, mais ils représentent des chaînes simples qui doivent être analysées. Au lieu d’implémenter votre propre logique d’analyse, vous pouvez utiliser un ResourceIdentifier objet qui effectuera l’analyse à votre place : new ResourceIdentifier("myid");.

Exemple : analyse d’un ID à l’aide d’un objet ResourceIdentifier

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

Gestion des ressources existantes par identificateur de ressource

Effectuer des opérations sur des ressources qui existent déjà est un cas d'utilisation courant lors de l'utilisation des bibliothèques clientes de gestion. Dans ce scénario, vous disposez généralement de l'identifiant de la ressource sur laquelle vous souhaitez travailler sous forme d’une chaîne. Bien que la nouvelle hiérarchie d’objets soit idéale pour l’approvisionnement et fonctionne dans l’étendue d’un parent donné, elle n’est pas la plus efficace quand il s’agit de ce scénario spécifique.

Voici un exemple de façon d’accéder à un AvailabilitySet objet et de le gérer directement avec son ID :

ResourceIdentifier id = new ResourceIdentifier("/subscriptions/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/resourceGroups/workshop2021-rg/providers/Microsoft.Compute/availabilitySets/ws2021availSet");
// We construct a new client to work with
ArmClient client = new ArmClient(new DefaultAzureCredential());
// Next we get the collection of subscriptions
SubscriptionCollection subscriptions = client.GetSubscriptions();
// Next we get the specific subscription this resource belongs to
SubscriptionResource subscription = await subscriptions.GetAsync(id.SubscriptionId);
// Next we get the collection of resource groups that belong to that subscription
ResourceGroupCollection resourceGroups = subscription.GetResourceGroups();
// Next we get the specific resource group this resource belongs to
ResourceGroupResource resourceGroup = await resourceGroups.GetAsync(id.ResourceGroupName);
// Next we get the collection of availability sets that belong to that resource group
AvailabilitySetCollection availabilitySets = resourceGroup.GetAvailabilitySets();
// Finally we get the resource itself
// Note: for this last step in this example, Azure.ResourceManager.Compute is needed
AvailabilitySetResource availabilitySet = await availabilitySets.GetAsync(id.Name);

Cette approche nécessitait beaucoup de code et trois appels d’API à Azure. La même opération peut être effectuée avec moins de code et sans aucun appel à l'API en utilisant les méthodes d'extension que nous avons fournies au client lui-même. Ces méthodes d'extension vous permettent de transmettre un identifiant de ressource et de récupérer un client de ressource délimité. L’objet retourné est une [Ressource] mentionnée ci-dessus, car elle n’a pas atteint Azure pour récupérer les données, mais la propriété Data sera null.

Ainsi, l'exemple précédent ressemblerait à ceci :

ResourceIdentifier resourceId = new ResourceIdentifier("/subscriptions/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/resourceGroups/workshop2021-rg/providers/Microsoft.Compute/availabilitySets/ws2021availSet");
// We construct a new client to work with
ArmClient client = new ArmClient(new DefaultAzureCredential());
// Next we get the AvailabilitySetResource resource client from the client
// 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
// 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);

Nous fournissons également une option qui, si vous connaissez uniquement les éléments qui composent chaque ResourceIdentifier ressource, fournit une méthode statique pour construire la chaîne complète à partir de ces éléments. L’exemple ci-dessus ressemblerait alors à ceci.

string subscriptionId = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee";
string resourceGroupName = "workshop2021-rg";
string availabilitySetName = "ws2021availSet";
ResourceIdentifier resourceId = AvailabilitySetResource.CreateResourceIdentifier(subscriptionId, resourceGroupName, availabilitySetName);
// We construct a new client to work with
ArmClient client = new ArmClient(new DefaultAzureCredential());
// Next we get the AvailabilitySetResource resource client from the client
// 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
// 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);

Vérifier si une [ressource] existe

Si vous ne savez pas si une ressource que vous souhaitez obtenir existe ou si vous souhaitez simplement case activée si elle existe, vous pouvez utiliser Exists() la méthode , qui peut être appelée à partir de n’importe quelle classe [Resource]Collection.

Exists() et ExistsAsync() retournent Response<bool> où le bool sera false si la ressource spécifiée n’existe pas. Ces deux méthodes vous donnent toujours accès à la réponse brute sous-jacente.

Avant l’introduction de ces méthodes, vous devez intercepter et RequestFailedException inspecter le code status pour 404.

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

try
{
    ResourceGroupResource resourceGroup = await resourceGroups.GetAsync(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.");
}

Maintenant, avec ces méthodes pratiques, nous pouvons effectuer le code suivant.

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

bool exists = await resourceGroups.ExistsAsync(resourceGroupName);

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 resourceGroups.GetAsync(resourceGroupName);
}
else
{
    Console.WriteLine($"Resource Group {resourceGroupName} does not exist.");
}

Exemples

Créer un groupe de ressources

// First, initialize the ArmClient and get the default subscription
ArmClient client = new ArmClient(new DefaultAzureCredential());
// Now we get a ResourceGroupResource collection for that subscription
SubscriptionResource subscription = await client.GetDefaultSubscriptionAsync();
ResourceGroupCollection resourceGroups = 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);
ArmOperation<ResourceGroupResource> operation = await resourceGroups.CreateOrUpdateAsync(WaitUntil.Completed, resourceGroupName, resourceGroupData);
ResourceGroupResource resourceGroup = operation.Value;

Liste de tous les groupes de ressources

// First, initialize the ArmClient and get the default subscription
ArmClient client = new ArmClient(new DefaultAzureCredential());
SubscriptionResource subscription = await client.GetDefaultSubscriptionAsync();
// Now we get a ResourceGroupResource collection for that subscription
ResourceGroupCollection resourceGroups = subscription.GetResourceGroups();
// We can then iterate over this collection to get the resources in the collection
await foreach (ResourceGroupResource resourceGroup in resourceGroups)
{
    Console.WriteLine(resourceGroup.Data.Name);
}

Mise à jour d'un groupe de ressources

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

Supprimer un groupe de ressources

ArmClient client = new ArmClient(new DefaultAzureCredential());
SubscriptionResource subscription = await client.GetDefaultSubscriptionAsync();
ResourceGroupCollection resourceGroups = subscription.GetResourceGroups();
string resourceGroupName = "myRgName";
ResourceGroupResource resourceGroup = await resourceGroups.GetAsync(resourceGroupName);
await resourceGroup.DeleteAsync(WaitUntil.Completed);

Obtenir la liste GenericResource

ArmClient client = new ArmClient(new DefaultAzureCredential());
SubscriptionResource sub = client.GetDefaultSubscription();
AsyncPageable<GenericResource> networkAndVmWithTestInName = sub.GetGenericResourcesAsync(
    // Set filter to only return virtual network and virtual machine resource with 'test' in the name
    filter: "(resourceType eq 'Microsoft.Network/virtualNetworks' or resourceType eq 'Microsoft.Compute/virtualMachines') and substringof('test', name)",
    // Include 'createdTime' and 'changeTime' properties in the returned data
    expand: "createdTime,changedTime"
    );

int count = 0;
await foreach (var res in networkAndVmWithTestInName)
{
    Console.WriteLine($"{res.Id.Name} in resource group {res.Id.ResourceGroupName} created at {res.Data.CreatedOn} and changed at {res.Data.ChangedOn}");
    count++;
}
Console.WriteLine($"{count} resources found");

Create GenericResource

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

var subnetName = "samplesubnet";
var addressSpaces = new Dictionary<string, object>()
{
    { "addressPrefixes", new List<string>() { "10.0.0.0/16" } }
};
var subnet = new Dictionary<string, object>()
{
    { "name", subnetName },
    { "properties", new Dictionary<string, object>()
        {
            { "addressPrefix", "10.0.1.0/24" }
        }
    }
};
var subnets = new List<object>() { subnet };
var data = new GenericResourceData(AzureLocation.EastUS)
{
    Properties = BinaryData.FromObjectAsJson(new Dictionary<string, object>()
    {
        { "addressSpace", addressSpaces },
        { "subnets", subnets }
    })
};
ResourceIdentifier id = new ResourceIdentifier("/subscriptions/{subscription_id}/resourceGroups/{resourcegroup_name}/providers/Microsoft.Network/virtualNetworks/{vnet_name}");

var createResult = await client.GetGenericResources().CreateOrUpdateAsync(WaitUntil.Completed, id, data);
Console.WriteLine($"Resource {createResult.Value.Id.Name} in resource group {createResult.Value.Id.ResourceGroupName} created");

Mettre à jour GenericResource

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

var subnetName = "samplesubnet";
var addressSpaces = new Dictionary<string, object>()
{
    { "addressPrefixes", new List<string>() { "10.0.0.0/16" } }
};
var subnet = new Dictionary<string, object>()
{
    { "name", subnetName },
    { "properties", new Dictionary<string, object>()
        {
            { "addressPrefix", "10.0.1.0/24" }
        }
    }
};
var subnets = new List<object>() { subnet };
var data = new GenericResourceData(AzureLocation.EastUS)
{
    Properties = BinaryData.FromObjectAsJson(new Dictionary<string, object>()
    {
        { "addressSpace", addressSpaces },
        { "subnets", subnets }
    })
};
ResourceIdentifier id = new ResourceIdentifier("/subscriptions/{subscription_id}/resourceGroups/{resourcegroup_name}/providers/Microsoft.Network/virtualNetworks/{vnet_name}");

var createResult = await client.GetGenericResources().CreateOrUpdateAsync(WaitUntil.Completed, id, data);
Console.WriteLine($"Resource {createResult.Value.Id.Name} in resource group {createResult.Value.Id.ResourceGroupName} updated");

Mettre à jour les balises GenericResourc

ArmClient client = new ArmClient(new DefaultAzureCredential());
ResourceIdentifier id = new ResourceIdentifier("/subscriptions/{subscription_id}/resourceGroups/{resourcegroup_name}/providers/Microsoft.Network/virtualNetworks/{vnet_name}");
GenericResource resource = client.GetGenericResources().Get(id).Value;

GenericResourceData updateTag = new GenericResourceData(AzureLocation.EastUS);
updateTag.Tags.Add("tag1", "sample-for-genericresource");
ArmOperation<GenericResource> updateTagResult = await resource.UpdateAsync(WaitUntil.Completed, updateTag);

Console.WriteLine($"Resource {updateTagResult.Value.Id.Name} in resource group {updateTagResult.Value.Id.ResourceGroupName} updated");

Obtenir GenericResource

ArmClient client = new ArmClient(new DefaultAzureCredential());
ResourceIdentifier id = new ResourceIdentifier("/subscriptions/{subscription_id}/resourceGroups/{resourcegroup_name}/providers/Microsoft.Network/virtualNetworks/{vnet_name}");

Response<GenericResource> getResultFromGenericResourceCollection = await client.GetGenericResources().GetAsync(id);
Console.WriteLine($"Resource {getResultFromGenericResourceCollection.Value.Id.Name} in resource group {getResultFromGenericResourceCollection.Value.Id.ResourceGroupName} got");

GenericResource resource = getResultFromGenericResourceCollection.Value;
Response<GenericResource> getResultFromGenericResource = await resource.GetAsync();
Console.WriteLine($"Resource {getResultFromGenericResource.Value.Id.Name} in resource group {getResultFromGenericResource.Value.Id.ResourceGroupName} got");

Vérifier si GenericResource existe

ArmClient client = new ArmClient(new DefaultAzureCredential());
ResourceIdentifier id = new ResourceIdentifier("/subscriptions/{subscription_id}/resourceGroups/{resourcegroup_name}/providers/Microsoft.Network/virtualNetworks/{vnet_name}");

bool existResult = await client.GetGenericResources().ExistsAsync(id);
Console.WriteLine($"Resource exists: {existResult}");

Delete GenericResource

ArmClient client = new ArmClient(new DefaultAzureCredential());
ResourceIdentifier id = new ResourceIdentifier("/subscriptions/{subscription_id}/resourceGroups/{resourcegroup_name}/providers/Microsoft.Network/virtualNetworks/{vnet_name}");
GenericResource resource = client.GetGenericResources().Get(id).Value;

var deleteResult = await resource.DeleteAsync(WaitUntil.Completed);
Console.WriteLine($"Resource deletion response status code: {deleteResult.WaitForCompletionResponse().Status}");

Pour obtenir des exemples plus détaillés, consultez les exemples que nous proposons.

Tests Azure Resource Manager

Pour exécuter le test : dotnet test

Pour exécuter un test avec la couverture du code et générer automatiquement un rapport html : dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura

Le rapport de couverture sera placé dans votre chemin d’accès par rapport à azure-proto-core-test au/coverage format html pour l’affichage

Les rapports peuvent également être consultés dans VS ou VsCode avec le plug-in de visionneuse approprié

Un rapport terse s’affiche également sur la ligne de commande lors de l’exécution.

exécuter le test avec un seul fichier ou test

Pour exécuter un test avec la couverture du code et générer automatiquement un rapport html avec un seul test : dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura --filter <test-to-run>

Dépannage

Étapes suivantes

Autres exemples de code

Autre documentation

Si vous effectuez une migration à partir de l’ancien SDK, case activée ce guide de migration.

Pour plus d’informations sur le Kit de développement logiciel (SDK) Microsoft Azure, consultez ce site web.

Contribution

Pour plus d’informations sur la contribution à ce dépôt, consultez le guide de contribution.

Ce projet accepte les contributions et les suggestions. La plupart des contributions vous demandent d’accepter un contrat de licence de contribution (CLA) déclarant que vous avez le droit de nous accorder, et que vous nous accordez réellement, les droits d’utilisation de votre contribution. Pour plus d’informations, visitez https://cla.microsoft.com.

Lorsque vous envoyez une demande de tirage, un bot CLA détermine automatiquement si vous devez fournir un cla cla et décorer la demande de tirage de manière appropriée (par exemple, étiquette, commentaire). Suivez les instructions fournies par le bot. Vous n’aurez besoin d’effectuer cette action qu’une seule fois sur tous les dépôts à l’aide de notre cla cla.

Ce projet a adopté le Code de conduite Open Source de Microsoft. Pour plus d’informations, consultez les Questions fréquentes (FAQ) sur le code de conduite ou envoyez vos questions ou vos commentaires à opencode@microsoft.com.