Créer ses propres outils Azure en C# avec .net core, Azure Resource Manager et WAML (Part 2)
Dans le précédent article nous avons mis en place un service permettant de s’authentifier pour utiliser les librairies WAML avec .net core.
Dans ce post, nous verrons comment intégrer ce service dans une application ASP NET Core puis nous allons mettre en place l’architecture d’une application qui permet de transférer des ressources Azure d’un groupe de ressources vers un autre. L’objectif n’est pas de mettre en place une application complète, mais simplement de montrer comment manipuler les librairies WAML depuis un controller ASP NET core.
L’architecture du projet « AzureManager » :
L’architecture de ce projet se veut très simpliste :
- un projet de type « Class Library (Package) » (couche « Domain »)
- un projet ASP NET core. (Application « Web »)
La librairie .net core (« Domain ») est de même organisée assez simplement :
- Un dossier « Contracts » qui contient les interfaces qui “définissent” les services
- Un dossier « Services » dans lequel on retrouve les services implémentant les interfaces
Le projet Web et un projet ASP NET Core classique, on y retrouve deux controllers : « HomeController » et « ResourceGroupController ».
Configuration du projet Web :
1. Référencement de la librairie « Domain »
Premièrement, il faut ajouter une référence vers la librairie « Domain » dans le fichier « Project.json » du projet « AzureManager.Web » :
"dependencies": { "AzureManager.Domain": "1.0.0-*"
2. Fichier de configuration
Dans le fichier « appsettings.json », il est nécessaire de rajouter les informations utiles au service d’authentification :
"AzureADApp": { "ClientId": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "TenantId": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "RedirectUri": "http://localhost/wamlrgsample" }, "AzureAccount": { "Email": "tranise@infinitesquare.com", "Password": "xxxxxxxxxxxx", "SubscriptionId": "xxxxxxxxxxxxxxxxxxxxxxxxxxxx" }
Ces informations sont identiques à celles utilisées dans le précédent article
3. Injection des services
Ensuite nous allons utiliser le système d’injection de dépendances d’ASP net core pour utiliser nos services à l’intérieur de nos controllers. Pour cela, on utilise le fichier « Startup.cs », c’est à l’intérieur de la méthode « ConfigureServices » que nous ajoutons les services :
public void ConfigureServices(IServiceCollection services) { // Create a class to map AppSettings values services.Configure<AppSettings>(Configuration.GetSection("AppSettings")); // Add AuthenticationService with params from appsettings.json services.AddScoped<IAuthenticationService>(_ => new AuthenticationService ( clientId : Configuration["AzureADApp:ClientId"], tenantId : Configuration["AzureADApp:TenantId"], redirectUri : Configuration["AzureADApp:RedirectUri"], email: Configuration["AzureAccount:Email"], password : Configuration["AzureAccount:Password"], subscriptionId: Configuration["AzureAccount:SubscriptionId"] )); // Add ResourceGroupService services.AddScoped<IResourceGroupService, ResourceGroupService>(); services.AddMvc(); }
Le service WAML :
Lors de l’injection des services dans le fichier « Startup.cs », nous avons injecté un service nommé : « ResourceGroupService » :
// Add ResourceGroupService services.AddScoped<IResourceGroupService, ResourceGroupService>();
Ce dernier implémente une interface qui définit une méthode « MoveResources » permettant de déplacer une liste de ressources d’un groupe de ressource « Parent » vers un groupe de ressources cible.
Ce service est dépendant du service d’authentification implémenté dans le précédent article et utilise ce dernier pour deux raisons :
- Pour récupérer le token d’authentification nécessaire pour manipuler les ressources Azure
- Pour récupérer l’identifiant de la souscription Azure cible
IResourceGroupeService.cs :
public interface IResourceGroupService { Task<AzureOperationResponse> MoveResources(string resourceGroupSource, IEnumerable<string> resources, string resourceGroupTarget); }
ResourceGroupeService.cs :
public class ResourceGroupService : IResourceGroupService { // Authentication service IAuthenticationService authenticateService; public ResourceGroupService(IAuthenticationService authenticateService) { this.authenticateService = authenticateService; } /// <summary> /// Move azure resources from a parent resource group to another one /// </summary> public async Task<AzureOperationResponse> MoveResources(string resourceGroupSource, IEnumerable<string> resources, string resourceGroupTarget) { // Get the credentials from the authentication service var crendentials = await this.authenticateService.Auth(); using (var rgClient = new ResourceManagementClient(crendentials)) { // Get the subscription id from the authentication service rgClient.SubscriptionId = this.authenticateService.GetSubscriptionId(); ResourcesMoveInfo moveInfos = new ResourcesMoveInfo() { Resources = resources.ToList(), TargetResourceGroup = resourceGroupTarget }; return await rgClient.Resources.BeginMoveResourcesWithHttpMessagesAsync(resourceGroupSource, moveInfos); } } }
L’utilisation de WAML reste relativement simple puisque un seul appel à la méthode « BeginMoveReousesWithHttpMessageAsync » est nécessaire. Cette méthode renvoie un « statut » qui peut être utilisé pour connaitre l’avancement de la tâche en cours.
Le controller « ResourceGroupController » :
La dernière étape de ce « mini » projet consiste à utiliser notre service WAML au sein du controller « ResourceGroupController ». Dans un premier temps il faut récupérer les services dans notre controller via le constructeur de dernier, puis dans notre cas, une seule action de type POST est nécessaire pour donner un exemple d’utilisation du « ResourceGroupService » :
public class ResourceGroupController : Controller { private IResourceGroupService resourceGroupService; private IOptions<AppSettings> appSettings; public ResourceGroupController(IResourceGroupService resourceGroupService, IOptions<AppSettings> appSettings) { this.appSettings = appSettings; this.resourceGroupService = resourceGroupService; } [HttpPost] public async Task<IActionResult> Move(MoveResourceViewModel moveViewModel) { var rgTarget = await this.resourceGroupService.GetResourceGroup(moveViewModel.ResourceGroupTarget); var response = await this.resourceGroupService.MoveResources( moveViewModel.ResourceGroupSource, new List<string>() { moveViewModel.ResourceToMoveId }, rgTarget.Id) .ConfigureAwait(false); return View(); } }
Pour aller plus loin…
Bien sûr ce petit projet est minimaliste, c’est cependant une base intéressante pour découvrir l’utilité des librairies de management Azure couplées à .net core. Dans notre cas on pourrait enrichir notre service « ResourceGroupService » avec plusieurs méthodes permettant par exemple de récupérer les groupes de ressources de la souscription ainsi que leurs ressources, ce qui permettrait de mettre en place une interface web permettant le worflow suivant :
- sélection du groupe de ressources parent
- sélection des ressources que l’on désire déplacer
- sélection du groupe de ressources cible
- Appel vers l’action “Move” du controller “ResourceGroupController”
Le code source est disponible sur Github !
Happy coding
Commentaires