title | description | ms.date | author | ms.author | ms.topic |
---|---|---|---|---|---|
Azure management libraries for .NET usage concepts and patterns |
10/19/2017 |
CamSoper |
casoper |
conceptual |
This article will help you understand how to effectively use the fluent interface in the Azure management libraries for .NET.
A fluent interface is a specific form of the builder pattern that creates objects through a method chain that enforces correct configuration of a resource. For example, the entry-point Azure object is created using a fluent interface:
var azure = Azure
.Configure()
.Authenticate(credentials)
.WithDefaultSubscription();
The Microsoft.Azure.Management.Fluent.Azure
object shown above is the entry point for all resource creation in the fluent management libraries. Select which type of resources to work with using the resource collections in the Azure
object. For example, for SQL Database:
var sql = azure.SqlServers.Define(sqlServerName)
.WithRegion(Region.USEast)
.WithNewResourceGroup(rgName)
.WithAdministratorLogin(administratorLogin)
.WithAdministratorPassword(administratorPassword)
.Create();
As seen above, most fluent "conversations" you have with the API start with selecting the appropriate resource collection for the Azure resources you need to work with. Intellisense in Visual Studio then guides you through the conversation.
Every resource collection has a List()
method to return every instance of that resource in your current subscription. For example, Azure.SqlServers.List()
returns all SQL servers in the subscription.
Use the ListByResourceGroup()
method to scope the returned List to a specific Azure resource group.
Iterate over the returned collection just as you would a normal List<T>
:
var vmList = azure.VirtualMachines.List();
foreach(var vm in vmList)
{
Console.WriteLine("VM Name: {0}", vm.Name);
}
Resource collection methods with verbs in their names take immediate action in Azure. These methods work synchronously and block execution in the current thread until they complete.
Verb | Sample usage |
---|---|
Create | azure.VirtualMachines.Create(listOfVMCreatables) |
Apply | virtualMachineScaleSet.Update().WithCapacity(6).Apply() |
Delete | azure.Disks.DeleteById(id) |
List | azure.SqlServers.List() |
Get | var vm = azure.VirtualMachines.GetByResourceGroup(group, vmName) |
Note
Define()
and Update()
are verbs but do not block unless followed by a Create()
or Apply()
.
Specific resource objects have verbs that change the state of the resource in Azure. For example:
var vmToRestart = azure.VirtualMachines.GetById(id);
vmToRestart.Restart();
Most of the methods described in this section have an asynchronous version as well, denoted by the suffix Async
.
Task restartTask = azure.VirtualMachines.GetById(id).RestartAsync();
A challenge when creating Azure resources arises when a new resource depends on another resource that doesn't yet exist. An example is reserving a public IP address and setting up a disk when creating a new virtual machine. You don't want to verify reserving the address or the creating the disk, you just want to configure the virtual machine with those resources.
Use creatable objects to define Azure resources for use in your code but only create them when needed in Azure. Code written with creatable objects offloads resource creation in the Azure environment to the management API, boosting performance.
Generate creatable objects through the resource collections' Define()
verb without a Create()
verb:
// Init a creatable Public IP Address
var publicIpAddressCreatable = azure.PublicIPAddresses.Define("publicIPAddressName")
.WithRegion(Region.USEast)
.WithNewResourceGroup(rgName);
The Azure resource defined by the creatable object does not yet exist in your subscription. A creatable object is a local representation of a resource that the management API will create when it's needed (when .Create()
is called). Use this creatable object in the definition of other Azure resources that need this resource.
// Init a creatable VM using the creatable Public IP Address
var vmCreatable = azure.VirtualMachines.Define("creatableVM")
// ...
.withNewPrimaryPublicIPAddress(publicIPAddressCreatable)
// ...
Create the resources in your Azure subscription using the Create()
method for the resource collection.
// Create the VM and its Public IP Address
var virtualMachine = azure.VirtualMachines.Create(vmCreatable);
Passing creatable objects to Create()
returns a ICreatedResources
object instead of a single resource object. The CreatedRelatedResource
object lets you access all resources created by the Create()
call, not just the type from the resource collection. To access the public IP address created in Azure for the virtual machine created in the above example:
var pip = virtualMachine.CreatedRelatedResource(publicIPAddressCreatable.Key()) as PublicIPAddress;;
The management API defines exception classes that extend Microsoft.Rest.RestException
. Catch exceptions generated by management API, with a catch (RestException exception)
block after the relevant try
statement.
Logging in the fluent Azure management libraries for .NET leverages the underlying AutoRest service client tracing.
Create a class that implements Microsoft.Rest.IServiceClientTracingInterceptor
. This class will be responsible for intercepting log messages and passing them to whatever logging mechanism you're using. In this example, we're just writing messages to the console, but you could also pass them to Log4Net, Microsoft.Extensions.Logging
, or any other logging framework.
class ConsoleTracer : IServiceClientTracingInterceptor
{
public void Information(string message)
{
Console.WriteLine(message);
}
public void TraceError(string invocationId, Exception exception)
{
Console.WriteLine("Exception in {0}: {1}", invocationId, exception);
}
public void ReceiveResponse(string invocationId, HttpResponseMessage response) { }
public void SendRequest(string invocationId, HttpRequestMessage request) { }
public void Configuration(string source, string name, string value) { }
public void EnterMethod(string invocationId, object instance, string method, IDictionary<string, object> parameters) { }
public void ExitMethod(string invocationId, object returnValue) { }
}
Before creating the Microsoft.Azure.Management.Fluent.Azure
object, initialize the IServiceClientTracingInterceptor
you created above by calling ServiceClientTracing.AddTracingInterceptor()
and set ServiceClientTracing.IsEnabled
to true. When you create the Azure
object, include the .WithDelegatingHandler()
and .WithLogLevel()
methods to wire up the client to AutoRest's service client tracing.
ServiceClientTracing.AddTracingInterceptor(new ConsoleTracer());
ServiceClientTracing.IsEnabled = true;
var azure = Azure
.Configure()
.WithDelegatingHandler(new HttpLoggingDelegatingHandler())
.WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic)
.Authenticate(credentials)
.WithDefaultSubscription();
The HttpLoggingDelegatingHandler
log levels are defined as follows:
Trace level | Logging enabled |
---|---|
HttpLoggingDelegatingHandler.Level.None | No output |
HttpLoggingDelegatingHandler.Level.Basic | Logs the URLs to underlying REST calls, response codes and times |
HttpLoggingDelegatingHandler.Level.Body | Everything in Basic plus request and response bodies for the REST calls |
HttpLoggingDelegatingHandler.Level.Headers | Everything in Basic plus the request and response headers REST calls |
HttpLoggingDelegatingHandler.Level.BodyAndHeaders | Everything in both Body and Headers log level |