Skip to content
113 changes: 5 additions & 108 deletions sdk/resourcemanager/Azure.ResourceManager.Core/src/ContainerBase.cs
Original file line number Diff line number Diff line change
@@ -1,30 +1,24 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;

namespace Azure.ResourceManager.Core
{
/// <summary>
/// Base class representing collection of resources.
/// </summary>
/// <typeparam name="TOperations"> The type of the class containing operations for the underlying resource. </typeparam>
/// <typeparam name="TIdentifier"> The type of the resource identifier. </typeparam>
public abstract class ContainerBase<TIdentifier, TOperations> : OperationsBase
where TOperations : ResourceOperationsBase<TIdentifier, TOperations> where TIdentifier : ResourceIdentifier
public abstract class ContainerBase<TIdentifier> : OperationsBase
where TIdentifier : ResourceIdentifier
{
/// <summary>
/// Initializes a new instance of the <see cref="ContainerBase{TIdentifier, TOperations}"/> class for mocking.
/// Initializes a new instance of the <see cref="ContainerBase{TIdentifier}"/> class for mocking.
/// </summary>
protected ContainerBase()
{
}

/// <summary>
/// Initializes a new instance of the <see cref="ContainerBase{TIdentifier, TOperations}"/> class.
/// Initializes a new instance of the <see cref="ContainerBase{TIdentifier}"/> class.
/// </summary>
/// <param name="clientContext"></param>
/// <param name="id"> The identifier of the resource that is the target of operations. </param>
Expand All @@ -34,7 +28,7 @@ internal ContainerBase(ClientContext clientContext, TIdentifier id)
}

/// <summary>
/// Initializes a new instance of the <see cref="ContainerBase{TOperations, TIdentifier}"/> class.
/// Initializes a new instance of the <see cref="ContainerBase{TOperations}"/> class.
/// </summary>
/// <param name="parent"> The resource representing the parent resource. </param>
protected ContainerBase(ResourceOperationsBase parent)
Expand All @@ -47,102 +41,5 @@ protected ContainerBase(ResourceOperationsBase parent)
/// Gets the parent resource of this resource.
/// </summary>
protected ResourceOperationsBase Parent { get; }

/// <summary>
/// Returns the resource from Azure if it exists.
/// </summary>
/// <param name="resourceName"> The name of the resource you want to get. </param>
/// <param name="cancellationToken"> A token to allow the caller to cancel the call to the service.
/// The default value is <see cref="CancellationToken.None" />. </param>
/// <returns> Whether or not the resource existed. </returns>
public virtual TOperations TryGet(string resourceName, CancellationToken cancellationToken = default)
{
using var scope = Diagnostics.CreateScope("ContainerBase`2.TryGet");
scope.Start();

var op = GetOperation(resourceName);

try
{
return op.Get(cancellationToken).Value;
}
catch (RequestFailedException e) when (e.Status == 404)
{
return null;
}
catch (Exception e)
{
scope.Failed(e);
throw;
}
}

/// <summary>
/// Returns the resource from Azure if it exists.
/// </summary>
/// <param name="resourceName"> The name of the resource you want to get. </param>
/// <param name="cancellationToken"> A token to allow the caller to cancel the call to the service.
/// The default value is <see cref="CancellationToken.None" />. </param>
/// <returns> Whether or not the resource existed. </returns>
public async virtual Task<TOperations> TryGetAsync(string resourceName, CancellationToken cancellationToken = default)
{
using var scope = Diagnostics.CreateScope("ContainerBase`2.TryGet");
scope.Start();

var op = GetOperation(resourceName);

try
{
return (await op.GetAsync(cancellationToken).ConfigureAwait(false)).Value;
}
catch (RequestFailedException e) when (e.Status == 404)
{
return null;
}
catch (Exception e)
{
scope.Failed(e);
throw;
}
}

/// <summary>
/// Determines whether or not the azure resource exists in this container
/// </summary>
/// <param name="resourceName"> The name of the resource you want to check. </param>
/// <param name="cancellationToken"> A token to allow the caller to cancel the call to the service.
/// The default value is <see cref="CancellationToken.None" />. </param>
/// <returns> Whether or not the resource existed. </returns>
public virtual bool DoesExist(string resourceName, CancellationToken cancellationToken = default)
{
return TryGet(resourceName, cancellationToken) == null ? false : true;
}

/// <summary>
/// Determines whether or not the azure resource exists in this container
/// </summary>
/// <param name="resourceName"> The name of the resource you want to check. </param>
/// <param name="cancellationToken"> A token to allow the caller to cancel the call to the service.
/// The default value is <see cref="CancellationToken.None" />. </param>
/// <returns> Whether or not the resource existed. </returns>
public virtual async Task<bool> DoesExistAsync(string resourceName, CancellationToken cancellationToken = default)
{
return await TryGetAsync(resourceName, cancellationToken).ConfigureAwait(false) == null ? false : true;
}

/// <summary>
/// Get an instance of the operations this container holds.
/// </summary>
/// <param name="resourceName"> The name of the resource to scope the operations to. </param>
/// <returns> An instance of <see cref="ResourceContainerBase{TIdentifier, TOperations, TResource}"/>. </returns>
protected virtual ResourceOperationsBase<TIdentifier, TOperations> GetOperation(string resourceName)
{
return Activator.CreateInstance(
typeof(TOperations).BaseType,
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance,
null,
new object[] { Parent, resourceName },
CultureInfo.InvariantCulture) as ResourceOperationsBase<TIdentifier, TOperations>;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the MIT License.

using System;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;

Expand All @@ -13,12 +14,12 @@ namespace Azure.ResourceManager.Core
/// <typeparam name="TIdentifier"> The type of the resource identifier. </typeparam>
/// <typeparam name="TOperations"> The type of the class containing operations for the underlying resource. </typeparam>
/// <typeparam name="TResource"> The type of the class containing properties for the underlying resource. </typeparam>
public abstract class ResourceContainerBase<TIdentifier, TOperations, TResource> : ContainerBase<TIdentifier, TOperations>
public abstract class ResourceContainerBase<TIdentifier, TOperations, TResource> : ContainerBase<TIdentifier>
where TIdentifier : ResourceIdentifier
where TOperations : ResourceOperationsBase<TIdentifier, TOperations>
where TResource : class
{
private static readonly object _parentLock = new object();
private readonly object _parentLock = new object();
private object _parentResource;

/// <summary>
Expand Down Expand Up @@ -105,5 +106,102 @@ protected TParent GetParentResource<TParent, TParentId, TParentOperations>()
/// <returns> A <see cref="Task"/> that on completion returns a response with the <see cref="Response{TOperations}"/> operation for this resource. </returns>
/// <exception cref="ArgumentException"> resourceName cannot be null or a whitespace. </exception>
public abstract Task<Response<TOperations>> GetAsync(string resourceName, CancellationToken cancellationToken = default);

/// <summary>
/// Returns the resource from Azure if it exists.
/// </summary>
/// <param name="resourceName"> The name of the resource you want to get. </param>
/// <param name="cancellationToken"> A token to allow the caller to cancel the call to the service.
/// The default value is <see cref="CancellationToken.None" />. </param>
/// <returns> Whether or not the resource existed. </returns>
public virtual TOperations TryGet(string resourceName, CancellationToken cancellationToken = default)
{
using var scope = Diagnostics.CreateScope("ResourceContainerBase`3.TryGet");
scope.Start();

var op = GetOperation(resourceName);

try
{
return op.Get(cancellationToken).Value;
}
catch (RequestFailedException e) when (e.Status == 404)
{
return null;
}
catch (Exception e)
{
scope.Failed(e);
throw;
}
}

/// <summary>
/// Returns the resource from Azure if it exists.
/// </summary>
/// <param name="resourceName"> The name of the resource you want to get. </param>
/// <param name="cancellationToken"> A token to allow the caller to cancel the call to the service.
/// The default value is <see cref="CancellationToken.None" />. </param>
/// <returns> Whether or not the resource existed. </returns>
public virtual async Task<TOperations> TryGetAsync(string resourceName, CancellationToken cancellationToken = default)
{
using var scope = Diagnostics.CreateScope("ResourceContainerBase`3.TryGet");
scope.Start();

var op = GetOperation(resourceName);

try
{
return (await op.GetAsync(cancellationToken).ConfigureAwait(false)).Value;
}
catch (RequestFailedException e) when (e.Status == 404)
{
return null;
}
catch (Exception e)
{
scope.Failed(e);
throw;
}
}

/// <summary>
/// Determines whether or not the azure resource exists in this container
/// </summary>
/// <param name="resourceName"> The name of the resource you want to check. </param>
/// <param name="cancellationToken"> A token to allow the caller to cancel the call to the service.
/// The default value is <see cref="CancellationToken.None" />. </param>
/// <returns> Whether or not the resource existed. </returns>
public virtual bool DoesExist(string resourceName, CancellationToken cancellationToken = default)
{
return TryGet(resourceName, cancellationToken) != null;
}

/// <summary>
/// Determines whether or not the azure resource exists in this container
/// </summary>
/// <param name="resourceName"> The name of the resource you want to check. </param>
/// <param name="cancellationToken"> A token to allow the caller to cancel the call to the service.
/// The default value is <see cref="CancellationToken.None" />. </param>
/// <returns> Whether or not the resource existed. </returns>
public virtual async Task<bool> DoesExistAsync(string resourceName, CancellationToken cancellationToken = default)
{
return await TryGetAsync(resourceName, cancellationToken).ConfigureAwait(false) != null;
}

/// <summary>
/// Get an instance of the operations this container holds.
/// </summary>
/// <param name="resourceName"> The name of the resource to scope the operations to. </param>
/// <returns> An instance of <see cref="ResourceContainerBase{TIdentifier, TOperations, TResource}"/>. </returns>
protected virtual ResourceOperationsBase<TIdentifier, TOperations> GetOperation(string resourceName)
{
return Activator.CreateInstance(
typeof(TOperations).BaseType,
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance,
null,
new object[] { Parent, resourceName },
CultureInfo.InvariantCulture) as ResourceOperationsBase<TIdentifier, TOperations>;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ protected SingletonOperationsBase()
}

/// <summary>
/// Initializes a new instance of the <see cref="ContainerBase{TOperations, TIdentifier}"/> class.
/// Initializes a new instance of the <see cref="ContainerBase{TOperations}"/> class.
/// </summary>
/// <param name="parent"> The resource representing the parent resource. </param>
protected SingletonOperationsBase(OperationsBase parent)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System;
using System.Threading;
using System.Threading.Tasks;
using Azure.Core;
using Azure.ResourceManager.Resources;

Expand All @@ -11,7 +12,7 @@ namespace Azure.ResourceManager.Core
/// <summary>
/// A class representing collection of Subscription and their operations
/// </summary>
public class SubscriptionContainer : ContainerBase<SubscriptionResourceIdentifier, Subscription>
public class SubscriptionContainer : ResourceContainerBase<SubscriptionResourceIdentifier, Subscription, SubscriptionData>
{
/// <summary>
/// Initializes a new instance of the <see cref="SubscriptionContainer"/> class for mocking.
Expand Down Expand Up @@ -103,6 +104,22 @@ protected override void Validate(ResourceIdentifier identifier)
throw new ArgumentException("Invalid parent for subscription container", nameof(identifier));
}

/// <inheritdoc />
public override Response<Subscription> Get(string subscriptionGuid, CancellationToken cancellationToken = default)
{
return new SubscriptionOperations(
new ClientContext(ClientOptions, Credential, BaseUri, Pipeline),
subscriptionGuid).Get(cancellationToken);
}

/// <inheritdoc />
public override Task<Response<Subscription>> GetAsync(string subscriptionGuid, CancellationToken cancellationToken = default)
{
return new SubscriptionOperations(
new ClientContext(ClientOptions, Credential, BaseUri, Pipeline),
subscriptionGuid).GetAsync(cancellationToken);
}

/// <summary>
/// Get an instance of the operations this container holds.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,5 +136,28 @@ public static AsyncPageable<AvailabilitySet> ListAvailabilitySetsAsync(this Subs
);
}
#endregion

#region VMImage Operations
/// <summary>
/// Lists the Virtual Machine Extension Images Container for this SubscriptionOperations.
/// </summary>
/// <param name="subscription"> The <see cref="SubscriptionOperations" /> instance the method will execute against. </param>
/// <returns> A collection of resource operations that may take multiple service requests to iterate over. </returns>
public static VirtualMachineExtensionImageContainer GetVmExtensionImages(this SubscriptionOperations subscription)
{
return new VirtualMachineExtensionImageContainer(subscription);
}

/// <summary>
/// Lists the Virtual Machine Images Container for this SubscriptionOperations.
/// </summary>
/// <param name="subscription"> The <see cref="SubscriptionOperations" /> instance the method will execute against. </param>
/// <returns> A collection of resource operations that may take multiple service requests to iterate over. </returns>
public static VirtualMachineImageContainer GetVmImages(this SubscriptionOperations subscription)
{
return new VirtualMachineImageContainer(subscription);
}

#endregion
}
}
Loading