From 0424e0fafb3ecc0eec0a797492e30bed61d2f906 Mon Sep 17 00:00:00 2001 From: Allen Zhang Date: Sun, 9 May 2021 21:23:32 -0700 Subject: [PATCH 1/7] initial check in with CustomKeyResourceContainerBase --- .../src/CustomKeyResourceContainerBase.cs | 83 +++++++++++++++++++ .../src/CustomKeyResourceOperationsBase.cs | 81 ++++++++++++++++++ .../Extensions/SubscriptionExtensions.cs | 12 +++ .../VirtualMachineExtensionImageData.cs | 38 +++++++++ .../compute/VirtualMachineExtensionImage.cs | 40 +++++++++ .../VirtualMachineExtensionImageContainer.cs | 75 +++++++++++++++++ .../VirtualMachineExtensionImageOperation.cs | 77 +++++++++++++++++ .../Proto.Client/src/Program.cs | 2 +- .../Proto.Client/src/ScenarioFactory.cs | 1 + .../src/Scenarios/VMImageTests.cs | 32 +++++++ 10 files changed, 440 insertions(+), 1 deletion(-) create mode 100644 sdk/resourcemanager/Azure.ResourceManager.Core/src/CustomKeyResourceContainerBase.cs create mode 100644 sdk/resourcemanager/Azure.ResourceManager.Core/src/CustomKeyResourceOperationsBase.cs create mode 100644 sdk/resourcemanager/Proto.Client/compute/Placeholder/VirtualMachineExtensionImageData.cs create mode 100644 sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImage.cs create mode 100644 sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImageContainer.cs create mode 100644 sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImageOperation.cs create mode 100644 sdk/resourcemanager/Proto.Client/src/Scenarios/VMImageTests.cs diff --git a/sdk/resourcemanager/Azure.ResourceManager.Core/src/CustomKeyResourceContainerBase.cs b/sdk/resourcemanager/Azure.ResourceManager.Core/src/CustomKeyResourceContainerBase.cs new file mode 100644 index 000000000000..9568af903fe2 --- /dev/null +++ b/sdk/resourcemanager/Azure.ResourceManager.Core/src/CustomKeyResourceContainerBase.cs @@ -0,0 +1,83 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; + +namespace Azure.ResourceManager.Core +{ + /// + /// A class representing collection of resources and their operations over their parent. + /// + /// The type of the resource identifier. + /// The type of the class containing operations for the underlying resource. + /// The type of the class containing properties for the underlying resource. + public abstract class CustomKeyResourceContainerBase : OperationsBase + where TOperations : CustomKeyResourceOperationsBase where TIdentifier : ResourceIdentifier + { + private static readonly object _parentLock = new object(); + private object _parentResource; + + /// + /// Gets the parent resource of this resource. + /// + protected ResourceOperationsBase Parent { get; } + + /// + /// Initializes a new instance of the class for mocking. + /// + protected CustomKeyResourceContainerBase() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The resource representing the parent resource. + protected CustomKeyResourceContainerBase(ResourceOperationsBase parent) + : base(new ClientContext(parent.ClientOptions, parent.Credential, parent.BaseUri, parent.Pipeline), parent.Id) + { + Parent = parent; + } + + /// + /// Verify that the input resource Id is a valid container for this type. + /// + /// The input resource Id to check. + /// Resource identifier is not a valid type for this container. + protected override void Validate(ResourceIdentifier identifier) + { + if (identifier.ResourceType != ValidResourceType) + throw new InvalidOperationException($"{identifier.ResourceType} is not a valid container for {Id.ResourceType}"); + } + + /// + /// Gets the location of the parent object. + /// + /// The type of the parents full resource object. + /// The type of the parents resource id. + /// The type of the parents operations object. + /// The associated with the parent object. + protected TParent GetParentResource() + where TParent : TParentOperations + where TParentOperations : ResourceOperationsBase + where TParentId : ResourceIdentifier + { + if (_parentResource is null) + { + lock (_parentLock) + { + if (_parentResource is null) + { + _parentResource = Parent as TParent; + if (_parentResource is null) + { + _parentResource = (Parent as TParentOperations).Get().Value; + } + } + } + } + + return _parentResource as TParent; + } + } +} diff --git a/sdk/resourcemanager/Azure.ResourceManager.Core/src/CustomKeyResourceOperationsBase.cs b/sdk/resourcemanager/Azure.ResourceManager.Core/src/CustomKeyResourceOperationsBase.cs new file mode 100644 index 000000000000..a013694b82da --- /dev/null +++ b/sdk/resourcemanager/Azure.ResourceManager.Core/src/CustomKeyResourceOperationsBase.cs @@ -0,0 +1,81 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Azure.ResourceManager.Core.Extensions; + +namespace Azure.ResourceManager.Core +{ + /// + /// A class representing the operations that can be performed over a specific resource that requires complex key. + /// + public abstract class CustomKeyResourceOperationsBase : OperationsBase + { + /// + /// Initializes a new instance of the class for mocking. + /// + protected CustomKeyResourceOperationsBase() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// + internal CustomKeyResourceOperationsBase(ClientContext clientContext, ResourceIdentifier id) + : base(clientContext, id) + { + } + } + + /// + /// Base class for all operations over a resource + /// + /// The type implementing operations over the resource. + /// The The identifier type for the resource. + [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "Types differ by type argument only")] + public abstract class CustomKeyResourceOperationsBase : CustomKeyResourceOperationsBase + where TOperations : CustomKeyResourceOperationsBase where TIdentifier : ResourceIdentifier + { + /// + /// Initializes a new instance of the class for mocking. + /// + protected CustomKeyResourceOperationsBase() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// Initializes a new instance of the class. + /// The resource representing the parent resource. + /// The identifier of the resource that is the target of operations. + protected CustomKeyResourceOperationsBase(OperationsBase parentOperations, ResourceIdentifier id) + : base(new ClientContext(parentOperations.ClientOptions, parentOperations.Credential, parentOperations.BaseUri, parentOperations.Pipeline), id) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// + internal CustomKeyResourceOperationsBase(ClientContext clientContext, ResourceIdentifier id) + : base(clientContext, id) + { + } + + /// + /// The typed resource identifier for the underlying resource + /// + public virtual new TIdentifier Id + { + get { return base.Id as TIdentifier; } + } + } +} diff --git a/sdk/resourcemanager/Proto.Client/compute/Extensions/SubscriptionExtensions.cs b/sdk/resourcemanager/Proto.Client/compute/Extensions/SubscriptionExtensions.cs index 8503f79e2b14..f76a92b3fdd6 100644 --- a/sdk/resourcemanager/Proto.Client/compute/Extensions/SubscriptionExtensions.cs +++ b/sdk/resourcemanager/Proto.Client/compute/Extensions/SubscriptionExtensions.cs @@ -136,5 +136,17 @@ public static AsyncPageable ListAvailabilitySetsAsync(this Subs ); } #endregion + + #region VMImage Operations + /// + /// Lists the AvailabilitySets for this SubscriptionOperations. + /// + /// The instance the method will execute against. + /// A collection of resource operations that may take multiple service requests to iterate over. + public static VirtualMachineExtensionImageContainer GetVMImagines(this SubscriptionOperations subscription) + { + return new VirtualMachineExtensionImageContainer(subscription); + } + #endregion } } diff --git a/sdk/resourcemanager/Proto.Client/compute/Placeholder/VirtualMachineExtensionImageData.cs b/sdk/resourcemanager/Proto.Client/compute/Placeholder/VirtualMachineExtensionImageData.cs new file mode 100644 index 000000000000..1acff3999f50 --- /dev/null +++ b/sdk/resourcemanager/Proto.Client/compute/Placeholder/VirtualMachineExtensionImageData.cs @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; +using Azure.ResourceManager.Core; +using Azure.ResourceManager.Core.Adapters; + +namespace Proto.Compute +{ + /// Describes a Virtual Machine Extension Image. + public partial class VirtualMachineExtensionImageData : TrackedResource + { + /// + /// Initializes a new instance of the class. + /// + /// The virtual machine to initialize. + public VirtualMachineExtensionImageData(Azure.ResourceManager.Compute.Models.VirtualMachineExtensionImage vmeExtensionImage) + : base(vmeExtensionImage.Id, vmeExtensionImage.Location, vmeExtensionImage) + { + } + + /// The operating system this extension supports. + public string OperatingSystem { get; set; } + /// The type of role (IaaS or PaaS) this extension supports. + public string ComputeRole { get; set; } + /// The schema defined by publisher, where extension consumers should provide settings in a matching schema. + public string HandlerSchema { get; set; } + /// Whether the extension can be used on xRP VMScaleSets. By default existing extensions are usable on scalesets, but there might be cases where a publisher wants to explicitly indicate the extension is only enabled for CRP VMs but not VMSS. + public bool? VmScaleSetEnabled { get; set; } + /// Whether the handler can support multiple extensions. + public bool? SupportsMultipleExtensions { get; set; } + } +} \ No newline at end of file diff --git a/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImage.cs b/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImage.cs new file mode 100644 index 000000000000..316e51ef2362 --- /dev/null +++ b/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImage.cs @@ -0,0 +1,40 @@ +using System.Threading; +using System.Threading.Tasks; +using Azure.ResourceManager.Core; + +namespace Proto.Compute +{ + /// + /// Class representing a VirtualMachine along with the instance operations that can be performed on it. + /// + public class VirtualMachineExtensionImage : VirtualMachineExtensionImageOperation + { + /// + /// Gets the data representing this VirtualMachine. + /// + public VirtualMachineExtensionImageData Data { get; private set; } + + /// + /// Initializes a new instance of the class. + /// + /// The client parameters to use in these operations. + /// The resource that is the target of operations. + internal VirtualMachineExtensionImage(ResourceOperationsBase operations, VirtualMachineExtensionImageData resource) + : base(operations, resource.Id) + { + Data = resource; + } + + ///// + //protected override VirtualMachineExtensionImage GetResource(CancellationToken cancellation = default) + //{ + // return this; + //} + + ///// + //protected override Task GetResourceAsync(CancellationToken cancellationToken = default) + //{ + // return Task.FromResult(this); + //} + } +} diff --git a/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImageContainer.cs b/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImageContainer.cs new file mode 100644 index 000000000000..f8656b815625 --- /dev/null +++ b/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImageContainer.cs @@ -0,0 +1,75 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Azure.ResourceManager.Compute; +using Azure.ResourceManager.Core; + +namespace Proto.Compute +{ + /// + /// A class representing collection of VirtualMachine and their operations over a ResourceGroup. + /// + public class VirtualMachineExtensionImageContainer + : CustomKeyResourceContainerBase + { + /// + /// Initializes a new instance of the class. + /// + /// The ResourceGroup that is the parent of the VirtualMachines. + internal VirtualMachineExtensionImageContainer(SubscriptionOperations resourceGroup) + : base(resourceGroup) + { + } + + private Azure.ResourceManager.Compute.VirtualMachineExtensionImagesOperations Operations => new ComputeManagementClient( + BaseUri, + GetParentResource().Id.SubscriptionId, + Credential, + ClientOptions.Convert()).VirtualMachineExtensionImages; + + /// + /// Gets the valid resource type for this object + /// + protected override ResourceType ValidResourceType => SubscriptionOperations.ResourceType; + + public ArmResponse Get( + string location, + string publisher, + string type, + string version, + CancellationToken cancellationToken = default) + { + return new PhArmResponse( + Operations.Get(location, publisher, type, version, cancellationToken), + v => new VirtualMachineExtensionImage(Parent, new VirtualMachineExtensionImageData(v))); + } + + public IEnumerable ListTypes( + string location, + string publisher, + CancellationToken cancellationToken = default) + { + return Operations + .ListTypes(location, publisher, cancellationToken) + .Value.Select(s => new VirtualMachineExtensionImage(Parent, new VirtualMachineExtensionImageData(s))); + } + + public IEnumerable ListVersions( + string location, + string publisher, + string type, + string filter = null, + int? top = null, + string orderby = null, + CancellationToken cancellationToken = default) + { + return Operations + .ListVersions(location, publisher, type, filter: filter, top: top, orderby: orderby, cancellationToken: cancellationToken) + .Value.Select(s => new VirtualMachineExtensionImage(Parent, new VirtualMachineExtensionImageData(s))); + } + } +} \ No newline at end of file diff --git a/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImageOperation.cs b/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImageOperation.cs new file mode 100644 index 000000000000..78f8808b1707 --- /dev/null +++ b/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImageOperation.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Azure.ResourceManager.Core; + +namespace Proto.Compute +{ + public class VirtualMachineExtensionImageOperation : CustomKeyResourceOperationsBase + { + /// + /// Gets the resource type definition for a virtual machine. + /// + public static readonly IReadOnlyList AllValidResourceTypes = new List + { + "Microsoft.Compute/Locations/Publishers/ArtifactTypes/Types", + "Microsoft.Compute/Locations/Publishers/ArtifactTypes/Types/Versions", + }; + + /// + /// Initializes a new instance of the class. + /// + /// The client parameters to use in these operations. + /// Id of the extension image. + internal VirtualMachineExtensionImageOperation(ResourceOperationsBase parentResourceOperations, SubscriptionResourceIdentifier id) + : base(parentResourceOperations, id) + { + } + + /// + /// Gets the valid resource type. + /// + protected override ResourceType ValidResourceType { get; } + + /// + /// Verify that the input resource Id is a valid container for this type. + /// + /// The input resource Id to check. + /// Resource identifier is not a valid type for this container. + protected override void Validate(ResourceIdentifier identifier) + { + if (!AllValidResourceTypes.Contains(identifier.ResourceType)) + throw new InvalidOperationException($"{identifier.ResourceType} is not a valid container for {Id.ResourceType}"); + } + + public virtual ArmResponse Get(CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public virtual Task> GetAsync(CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + /// + /// Get details for this resource from the service or can be overriden to provide a cached instance. + /// + /// A operation for this resource. + protected virtual VirtualMachineExtensionImageOperation GetResource(CancellationToken cancellationToken = default) + { + return Get(cancellationToken).Value; + } + + /// + /// Get details for this resource from the service or can be overriden to provide a cached instance. + /// + /// A token to allow the caller to cancel the call to the service. The default value is . + /// A that on completion returns a operation for this resource. + protected virtual async Task GetResourceAsync(CancellationToken cancellationToken = default) + { + return (await GetAsync(cancellationToken).ConfigureAwait(false)).Value; + } + } +} diff --git a/sdk/resourcemanager/Proto.Client/src/Program.cs b/sdk/resourcemanager/Proto.Client/src/Program.cs index 02f0cbe08ca2..28bfac1ee964 100644 --- a/sdk/resourcemanager/Proto.Client/src/Program.cs +++ b/sdk/resourcemanager/Proto.Client/src/Program.cs @@ -11,7 +11,7 @@ static void Main(string[] args) Scenario scenario = null; try { - scenario = ScenarioFactory.GetScenario(Scenarios.CreateSingleVmExample); + scenario = ScenarioFactory.GetScenario(Scenarios.VMImageTests); scenario.Execute(); } finally diff --git a/sdk/resourcemanager/Proto.Client/src/ScenarioFactory.cs b/sdk/resourcemanager/Proto.Client/src/ScenarioFactory.cs index 6f094ee6b67d..53df3617d5d3 100644 --- a/sdk/resourcemanager/Proto.Client/src/ScenarioFactory.cs +++ b/sdk/resourcemanager/Proto.Client/src/ScenarioFactory.cs @@ -42,6 +42,7 @@ enum Scenarios CheckResourceGroupContainerAsync, GenericResourceOperationsExample, SingletonVmssUpgrade, + VMImageTests, } class ScenarioFactory diff --git a/sdk/resourcemanager/Proto.Client/src/Scenarios/VMImageTests.cs b/sdk/resourcemanager/Proto.Client/src/Scenarios/VMImageTests.cs new file mode 100644 index 000000000000..65ec6671911d --- /dev/null +++ b/sdk/resourcemanager/Proto.Client/src/Scenarios/VMImageTests.cs @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using Azure.Identity; +using Azure.ResourceManager.Core; +using Proto.Compute; + +namespace Proto.Client +{ + class VMImageTests : Scenario + { + public override void Execute() + { + var client = new ArmClient(new DefaultAzureCredential()); + var subscription = client.DefaultSubscription; + + var defaultLocation = "westus2"; + var publisher = "TrendMicro.DeepSecurity"; + + foreach (var t in subscription.GetVMImagines().ListTypes(defaultLocation, publisher)) + { + Console.WriteLine(t.Data.Name); + + foreach (var v in subscription.GetVMImagines().ListVersions(defaultLocation, publisher, t.Data.Name)) + { + Console.WriteLine(v.Data.Name); + } + } + } + } +} From ec8fa8be2065c9da345cd8401e200130efaf58fa Mon Sep 17 00:00:00 2001 From: Allen Zhang Date: Sun, 9 May 2021 22:59:36 -0700 Subject: [PATCH 2/7] Added VmImage bypassing operation and resource --- .../src/BasicContainerBase.cs | 79 +++++++++++++++ .../Extensions/SubscriptionExtensions.cs | 15 ++- .../compute/VirtualMachineExtensionImage.cs | 12 --- .../VirtualMachineExtensionImageOperation.cs | 53 +++------- .../compute/VirtualMachineImageContainer.cs | 97 +++++++++++++++++++ .../src/Scenarios/VMImageTests.cs | 36 ++++++- 6 files changed, 233 insertions(+), 59 deletions(-) create mode 100644 sdk/resourcemanager/Azure.ResourceManager.Core/src/BasicContainerBase.cs create mode 100644 sdk/resourcemanager/Proto.Client/compute/VirtualMachineImageContainer.cs diff --git a/sdk/resourcemanager/Azure.ResourceManager.Core/src/BasicContainerBase.cs b/sdk/resourcemanager/Azure.ResourceManager.Core/src/BasicContainerBase.cs new file mode 100644 index 000000000000..98188b8d2dab --- /dev/null +++ b/sdk/resourcemanager/Azure.ResourceManager.Core/src/BasicContainerBase.cs @@ -0,0 +1,79 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; + +namespace Azure.ResourceManager.Core +{ + /// + /// A class representing collection of resources and their operations over their parent. + /// + public abstract class BasicContainerBase : OperationsBase + { + private static readonly object _parentLock = new object(); + private object _parentResource; + + /// + /// Gets the parent resource of this resource. + /// + protected ResourceOperationsBase Parent { get; } + + /// + /// Initializes a new instance of the class for mocking. + /// + protected BasicContainerBase() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The resource representing the parent resource. + protected BasicContainerBase(ResourceOperationsBase parent) + : base(new ClientContext(parent.ClientOptions, parent.Credential, parent.BaseUri, parent.Pipeline), parent.Id) + { + Parent = parent; + } + + /// + /// Verify that the input resource Id is a valid container for this type. + /// + /// The input resource Id to check. + /// Resource identifier is not a valid type for this container. + protected override void Validate(ResourceIdentifier identifier) + { + if (identifier.ResourceType != ValidResourceType) + throw new InvalidOperationException($"{identifier.ResourceType} is not a valid container for {Id.ResourceType}"); + } + + /// + /// Gets the location of the parent object. + /// + /// The type of the parents full resource object. + /// The type of the parents resource id. + /// The type of the parents operations object. + /// The associated with the parent object. + protected TParent GetParentResource() + where TParent : TParentOperations + where TParentOperations : ResourceOperationsBase + where TParentId : ResourceIdentifier + { + if (_parentResource is null) + { + lock (_parentLock) + { + if (_parentResource is null) + { + _parentResource = Parent as TParent; + if (_parentResource is null) + { + _parentResource = (Parent as TParentOperations).Get().Value; + } + } + } + } + + return _parentResource as TParent; + } + } +} diff --git a/sdk/resourcemanager/Proto.Client/compute/Extensions/SubscriptionExtensions.cs b/sdk/resourcemanager/Proto.Client/compute/Extensions/SubscriptionExtensions.cs index f76a92b3fdd6..bb085bd408da 100644 --- a/sdk/resourcemanager/Proto.Client/compute/Extensions/SubscriptionExtensions.cs +++ b/sdk/resourcemanager/Proto.Client/compute/Extensions/SubscriptionExtensions.cs @@ -139,14 +139,25 @@ public static AsyncPageable ListAvailabilitySetsAsync(this Subs #region VMImage Operations /// - /// Lists the AvailabilitySets for this SubscriptionOperations. + /// Lists the Virtual Machine Extension Images Container for this SubscriptionOperations. /// /// The instance the method will execute against. /// A collection of resource operations that may take multiple service requests to iterate over. - public static VirtualMachineExtensionImageContainer GetVMImagines(this SubscriptionOperations subscription) + public static VirtualMachineExtensionImageContainer GetVmExtensionImages(this SubscriptionOperations subscription) { return new VirtualMachineExtensionImageContainer(subscription); } + + /// + /// Lists the Virtual Machine Images Container for this SubscriptionOperations. + /// + /// The instance the method will execute against. + /// A collection of resource operations that may take multiple service requests to iterate over. + public static VirtualMachineImageContainer GetVmImages(this SubscriptionOperations subscription) + { + return new VirtualMachineImageContainer(subscription); + } + #endregion } } diff --git a/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImage.cs b/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImage.cs index 316e51ef2362..fcf1ac6d32eb 100644 --- a/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImage.cs +++ b/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImage.cs @@ -24,17 +24,5 @@ internal VirtualMachineExtensionImage(ResourceOperationsBase operations, Virtual { Data = resource; } - - ///// - //protected override VirtualMachineExtensionImage GetResource(CancellationToken cancellation = default) - //{ - // return this; - //} - - ///// - //protected override Task GetResourceAsync(CancellationToken cancellationToken = default) - //{ - // return Task.FromResult(this); - //} } } diff --git a/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImageOperation.cs b/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImageOperation.cs index 78f8808b1707..c58eca32efa4 100644 --- a/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImageOperation.cs +++ b/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImageOperation.cs @@ -13,26 +13,24 @@ public class VirtualMachineExtensionImageOperation : CustomKeyResourceOperations /// /// Gets the resource type definition for a virtual machine. /// - public static readonly IReadOnlyList AllValidResourceTypes = new List + protected static readonly IReadOnlyList AllValidResourceTypes = new List { "Microsoft.Compute/Locations/Publishers/ArtifactTypes/Types", "Microsoft.Compute/Locations/Publishers/ArtifactTypes/Types/Versions", }; - /// - /// Initializes a new instance of the class. - /// - /// The client parameters to use in these operations. - /// Id of the extension image. - internal VirtualMachineExtensionImageOperation(ResourceOperationsBase parentResourceOperations, SubscriptionResourceIdentifier id) - : base(parentResourceOperations, id) + /// + /// Initializes a new instance of the class. + /// + /// The client parameters to use in these operations. + /// Id of the extension image. + internal VirtualMachineExtensionImageOperation(ResourceOperationsBase parentResourceOperations, SubscriptionResourceIdentifier id) + : base(parentResourceOperations, id) { } - /// - /// Gets the valid resource type. - /// - protected override ResourceType ValidResourceType { get; } + // TODO should we update valid types to be list? + protected override ResourceType ValidResourceType => AllValidResourceTypes.First(); /// /// Verify that the input resource Id is a valid container for this type. @@ -42,36 +40,7 @@ internal VirtualMachineExtensionImageOperation(ResourceOperationsBase parentReso protected override void Validate(ResourceIdentifier identifier) { if (!AllValidResourceTypes.Contains(identifier.ResourceType)) - throw new InvalidOperationException($"{identifier.ResourceType} is not a valid container for {Id.ResourceType}"); - } - - public virtual ArmResponse Get(CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public virtual Task> GetAsync(CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - /// - /// Get details for this resource from the service or can be overriden to provide a cached instance. - /// - /// A operation for this resource. - protected virtual VirtualMachineExtensionImageOperation GetResource(CancellationToken cancellationToken = default) - { - return Get(cancellationToken).Value; - } - - /// - /// Get details for this resource from the service or can be overriden to provide a cached instance. - /// - /// A token to allow the caller to cancel the call to the service. The default value is . - /// A that on completion returns a operation for this resource. - protected virtual async Task GetResourceAsync(CancellationToken cancellationToken = default) - { - return (await GetAsync(cancellationToken).ConfigureAwait(false)).Value; + throw new InvalidOperationException($"Invalid resource type {identifier?.ResourceType}."); } } } diff --git a/sdk/resourcemanager/Proto.Client/compute/VirtualMachineImageContainer.cs b/sdk/resourcemanager/Proto.Client/compute/VirtualMachineImageContainer.cs new file mode 100644 index 000000000000..cea422cf08b1 --- /dev/null +++ b/sdk/resourcemanager/Proto.Client/compute/VirtualMachineImageContainer.cs @@ -0,0 +1,97 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Azure.ResourceManager.Compute; +using Azure.ResourceManager.Compute.Models; +using Azure.ResourceManager.Core; + +namespace Proto.Compute +{ + /// + /// A class representing collection of VirtualMachine and their operations over a ResourceGroup. + /// + public class VirtualMachineImageContainer : BasicContainerBase + { + private string _subsriptionId; + + /// + /// Initializes a new instance of the class. + /// + /// The parent subscription. + internal VirtualMachineImageContainer(SubscriptionOperations parent) + : base(parent) + { + _subsriptionId = parent.Id.SubscriptionId; + } + + private Azure.ResourceManager.Compute.VirtualMachineImagesOperations Operations => new ComputeManagementClient( + BaseUri, + _subsriptionId, + Credential, + ClientOptions.Convert()).VirtualMachineImages; + + protected override ResourceType ValidResourceType => SubscriptionOperations.ResourceType; + + public ArmResponse Get( + string location, + string publisher, + string offer, + string sku, + string version, + CancellationToken cancellationToken = default) + { + return new PhArmResponse( + Operations.Get(location, publisher, offer, sku, version, cancellationToken), v => v); + } + + public IEnumerable ListPublishers( + string location, + CancellationToken cancellationToken = default) + { + return Operations.ListPublishers(location, cancellationToken).Value; + } + + public IEnumerable ListOffers( + string location, + string publisher, + CancellationToken cancellationToken = default) + { + return Operations.ListOffers(location, publisher, cancellationToken).Value; + } + + public IEnumerable ListSkus( + string location, + string publisher, + string offer, + CancellationToken cancellationToken = default) + { + return Operations.ListSkus(location, publisher, offer, cancellationToken).Value; + } + + public IEnumerable ListVersions( + string location, + string publisher, + string offer, + string skus, + string expand = null, + int? top = null, + string orderby = null, + CancellationToken cancellationToken = default) + { + return Operations.List( + location, + publisher, + offer, + skus, + expand: expand, + top: top, + orderby: orderby, + cancellationToken: cancellationToken) + .Value; + } + } +} \ No newline at end of file diff --git a/sdk/resourcemanager/Proto.Client/src/Scenarios/VMImageTests.cs b/sdk/resourcemanager/Proto.Client/src/Scenarios/VMImageTests.cs index 65ec6671911d..030c2fb955d4 100644 --- a/sdk/resourcemanager/Proto.Client/src/Scenarios/VMImageTests.cs +++ b/sdk/resourcemanager/Proto.Client/src/Scenarios/VMImageTests.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using System.Linq; using Azure.Identity; using Azure.ResourceManager.Core; using Proto.Compute; @@ -16,13 +17,42 @@ public override void Execute() var subscription = client.DefaultSubscription; var defaultLocation = "westus2"; - var publisher = "TrendMicro.DeepSecurity"; + //var defaultPublisher = "TrendMicro.DeepSecurity"; + var defaultPublisher = "redhat"; - foreach (var t in subscription.GetVMImagines().ListTypes(defaultLocation, publisher)) + foreach (var p in subscription.GetVmImages().ListPublishers(defaultLocation)) + { + Console.WriteLine(p.Name); + } + + foreach (var o in subscription.GetVmImages().ListOffers(defaultLocation, defaultPublisher)) + { + Console.WriteLine($"offer:\t{o.Name}"); + + foreach (var s in subscription.GetVmImages().ListSkus(defaultLocation, defaultPublisher, o.Name)) + { + Console.WriteLine($"sku:\t{s.Name}"); + + foreach (var v in subscription.GetVmImages().ListVersions(defaultLocation, defaultPublisher, o.Name, s.Name).Where(v => v.Name == "7.8.20210222")) + { + Console.WriteLine($"version:\t{v.Name}"); + + var vmImage = subscription.GetVmImages().Get( + defaultLocation, + defaultPublisher, + o.Name, + s.Name, + v.Name); + Console.WriteLine($"vmImage:\t{vmImage.Value.Id}"); + } + } + } + + foreach (var t in subscription.GetVmExtensionImages().ListTypes(defaultLocation, defaultPublisher)) { Console.WriteLine(t.Data.Name); - foreach (var v in subscription.GetVMImagines().ListVersions(defaultLocation, publisher, t.Data.Name)) + foreach (var v in subscription.GetVmExtensionImages().ListVersions(defaultLocation, defaultPublisher, t.Data.Name)) { Console.WriteLine(v.Data.Name); } From 9e6e839046cccdfb4b0c5cf93f435b6680f74757 Mon Sep 17 00:00:00 2001 From: Allen Zhang Date: Tue, 11 May 2021 00:45:28 -0700 Subject: [PATCH 3/7] Updated ExtensionImage to use BasicContainerBase. --- .../src/CustomKeyResourceContainerBase.cs | 83 ------------------- .../src/CustomKeyResourceOperationsBase.cs | 81 ------------------ .../VirtualMachineExtensionImageData.cs | 38 --------- .../compute/VirtualMachineExtensionImage.cs | 28 ------- .../VirtualMachineExtensionImageContainer.cs | 13 +-- .../VirtualMachineExtensionImageOperation.cs | 46 ---------- .../src/Scenarios/VMImageTests.cs | 6 +- 7 files changed, 10 insertions(+), 285 deletions(-) delete mode 100644 sdk/resourcemanager/Azure.ResourceManager.Core/src/CustomKeyResourceContainerBase.cs delete mode 100644 sdk/resourcemanager/Azure.ResourceManager.Core/src/CustomKeyResourceOperationsBase.cs delete mode 100644 sdk/resourcemanager/Proto.Client/compute/Placeholder/VirtualMachineExtensionImageData.cs delete mode 100644 sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImage.cs delete mode 100644 sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImageOperation.cs diff --git a/sdk/resourcemanager/Azure.ResourceManager.Core/src/CustomKeyResourceContainerBase.cs b/sdk/resourcemanager/Azure.ResourceManager.Core/src/CustomKeyResourceContainerBase.cs deleted file mode 100644 index 9568af903fe2..000000000000 --- a/sdk/resourcemanager/Azure.ResourceManager.Core/src/CustomKeyResourceContainerBase.cs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; - -namespace Azure.ResourceManager.Core -{ - /// - /// A class representing collection of resources and their operations over their parent. - /// - /// The type of the resource identifier. - /// The type of the class containing operations for the underlying resource. - /// The type of the class containing properties for the underlying resource. - public abstract class CustomKeyResourceContainerBase : OperationsBase - where TOperations : CustomKeyResourceOperationsBase where TIdentifier : ResourceIdentifier - { - private static readonly object _parentLock = new object(); - private object _parentResource; - - /// - /// Gets the parent resource of this resource. - /// - protected ResourceOperationsBase Parent { get; } - - /// - /// Initializes a new instance of the class for mocking. - /// - protected CustomKeyResourceContainerBase() - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The resource representing the parent resource. - protected CustomKeyResourceContainerBase(ResourceOperationsBase parent) - : base(new ClientContext(parent.ClientOptions, parent.Credential, parent.BaseUri, parent.Pipeline), parent.Id) - { - Parent = parent; - } - - /// - /// Verify that the input resource Id is a valid container for this type. - /// - /// The input resource Id to check. - /// Resource identifier is not a valid type for this container. - protected override void Validate(ResourceIdentifier identifier) - { - if (identifier.ResourceType != ValidResourceType) - throw new InvalidOperationException($"{identifier.ResourceType} is not a valid container for {Id.ResourceType}"); - } - - /// - /// Gets the location of the parent object. - /// - /// The type of the parents full resource object. - /// The type of the parents resource id. - /// The type of the parents operations object. - /// The associated with the parent object. - protected TParent GetParentResource() - where TParent : TParentOperations - where TParentOperations : ResourceOperationsBase - where TParentId : ResourceIdentifier - { - if (_parentResource is null) - { - lock (_parentLock) - { - if (_parentResource is null) - { - _parentResource = Parent as TParent; - if (_parentResource is null) - { - _parentResource = (Parent as TParentOperations).Get().Value; - } - } - } - } - - return _parentResource as TParent; - } - } -} diff --git a/sdk/resourcemanager/Azure.ResourceManager.Core/src/CustomKeyResourceOperationsBase.cs b/sdk/resourcemanager/Azure.ResourceManager.Core/src/CustomKeyResourceOperationsBase.cs deleted file mode 100644 index a013694b82da..000000000000 --- a/sdk/resourcemanager/Azure.ResourceManager.Core/src/CustomKeyResourceOperationsBase.cs +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Azure.ResourceManager.Core.Extensions; - -namespace Azure.ResourceManager.Core -{ - /// - /// A class representing the operations that can be performed over a specific resource that requires complex key. - /// - public abstract class CustomKeyResourceOperationsBase : OperationsBase - { - /// - /// Initializes a new instance of the class for mocking. - /// - protected CustomKeyResourceOperationsBase() - { - } - - /// - /// Initializes a new instance of the class. - /// - /// - /// - internal CustomKeyResourceOperationsBase(ClientContext clientContext, ResourceIdentifier id) - : base(clientContext, id) - { - } - } - - /// - /// Base class for all operations over a resource - /// - /// The type implementing operations over the resource. - /// The The identifier type for the resource. - [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "Types differ by type argument only")] - public abstract class CustomKeyResourceOperationsBase : CustomKeyResourceOperationsBase - where TOperations : CustomKeyResourceOperationsBase where TIdentifier : ResourceIdentifier - { - /// - /// Initializes a new instance of the class for mocking. - /// - protected CustomKeyResourceOperationsBase() - { - } - - /// - /// Initializes a new instance of the class. - /// - /// Initializes a new instance of the class. - /// The resource representing the parent resource. - /// The identifier of the resource that is the target of operations. - protected CustomKeyResourceOperationsBase(OperationsBase parentOperations, ResourceIdentifier id) - : base(new ClientContext(parentOperations.ClientOptions, parentOperations.Credential, parentOperations.BaseUri, parentOperations.Pipeline), id) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// - /// - internal CustomKeyResourceOperationsBase(ClientContext clientContext, ResourceIdentifier id) - : base(clientContext, id) - { - } - - /// - /// The typed resource identifier for the underlying resource - /// - public virtual new TIdentifier Id - { - get { return base.Id as TIdentifier; } - } - } -} diff --git a/sdk/resourcemanager/Proto.Client/compute/Placeholder/VirtualMachineExtensionImageData.cs b/sdk/resourcemanager/Proto.Client/compute/Placeholder/VirtualMachineExtensionImageData.cs deleted file mode 100644 index 1acff3999f50..000000000000 --- a/sdk/resourcemanager/Proto.Client/compute/Placeholder/VirtualMachineExtensionImageData.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -// - -#nullable disable - -using System; -using System.Collections.Generic; -using Azure.ResourceManager.Core; -using Azure.ResourceManager.Core.Adapters; - -namespace Proto.Compute -{ - /// Describes a Virtual Machine Extension Image. - public partial class VirtualMachineExtensionImageData : TrackedResource - { - /// - /// Initializes a new instance of the class. - /// - /// The virtual machine to initialize. - public VirtualMachineExtensionImageData(Azure.ResourceManager.Compute.Models.VirtualMachineExtensionImage vmeExtensionImage) - : base(vmeExtensionImage.Id, vmeExtensionImage.Location, vmeExtensionImage) - { - } - - /// The operating system this extension supports. - public string OperatingSystem { get; set; } - /// The type of role (IaaS or PaaS) this extension supports. - public string ComputeRole { get; set; } - /// The schema defined by publisher, where extension consumers should provide settings in a matching schema. - public string HandlerSchema { get; set; } - /// Whether the extension can be used on xRP VMScaleSets. By default existing extensions are usable on scalesets, but there might be cases where a publisher wants to explicitly indicate the extension is only enabled for CRP VMs but not VMSS. - public bool? VmScaleSetEnabled { get; set; } - /// Whether the handler can support multiple extensions. - public bool? SupportsMultipleExtensions { get; set; } - } -} \ No newline at end of file diff --git a/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImage.cs b/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImage.cs deleted file mode 100644 index fcf1ac6d32eb..000000000000 --- a/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImage.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using Azure.ResourceManager.Core; - -namespace Proto.Compute -{ - /// - /// Class representing a VirtualMachine along with the instance operations that can be performed on it. - /// - public class VirtualMachineExtensionImage : VirtualMachineExtensionImageOperation - { - /// - /// Gets the data representing this VirtualMachine. - /// - public VirtualMachineExtensionImageData Data { get; private set; } - - /// - /// Initializes a new instance of the class. - /// - /// The client parameters to use in these operations. - /// The resource that is the target of operations. - internal VirtualMachineExtensionImage(ResourceOperationsBase operations, VirtualMachineExtensionImageData resource) - : base(operations, resource.Id) - { - Data = resource; - } - } -} diff --git a/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImageContainer.cs b/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImageContainer.cs index f8656b815625..e042a0d10fa0 100644 --- a/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImageContainer.cs +++ b/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImageContainer.cs @@ -6,6 +6,7 @@ using System.Threading; using System.Threading.Tasks; using Azure.ResourceManager.Compute; +using Azure.ResourceManager.Compute.Models; using Azure.ResourceManager.Core; namespace Proto.Compute @@ -13,8 +14,7 @@ namespace Proto.Compute /// /// A class representing collection of VirtualMachine and their operations over a ResourceGroup. /// - public class VirtualMachineExtensionImageContainer - : CustomKeyResourceContainerBase + public class VirtualMachineExtensionImageContainer : BasicContainerBase { /// /// Initializes a new instance of the class. @@ -43,9 +43,10 @@ public ArmResponse Get( string version, CancellationToken cancellationToken = default) { - return new PhArmResponse( + return new PhArmResponse( Operations.Get(location, publisher, type, version, cancellationToken), - v => new VirtualMachineExtensionImage(Parent, new VirtualMachineExtensionImageData(v))); + v => v); } public IEnumerable ListTypes( @@ -55,7 +56,7 @@ public IEnumerable ListTypes( { return Operations .ListTypes(location, publisher, cancellationToken) - .Value.Select(s => new VirtualMachineExtensionImage(Parent, new VirtualMachineExtensionImageData(s))); + .Value; } public IEnumerable ListVersions( @@ -69,7 +70,7 @@ public IEnumerable ListVersions( { return Operations .ListVersions(location, publisher, type, filter: filter, top: top, orderby: orderby, cancellationToken: cancellationToken) - .Value.Select(s => new VirtualMachineExtensionImage(Parent, new VirtualMachineExtensionImageData(s))); + .Value; } } } \ No newline at end of file diff --git a/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImageOperation.cs b/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImageOperation.cs deleted file mode 100644 index c58eca32efa4..000000000000 --- a/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImageOperation.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Azure.ResourceManager.Core; - -namespace Proto.Compute -{ - public class VirtualMachineExtensionImageOperation : CustomKeyResourceOperationsBase - { - /// - /// Gets the resource type definition for a virtual machine. - /// - protected static readonly IReadOnlyList AllValidResourceTypes = new List - { - "Microsoft.Compute/Locations/Publishers/ArtifactTypes/Types", - "Microsoft.Compute/Locations/Publishers/ArtifactTypes/Types/Versions", - }; - - /// - /// Initializes a new instance of the class. - /// - /// The client parameters to use in these operations. - /// Id of the extension image. - internal VirtualMachineExtensionImageOperation(ResourceOperationsBase parentResourceOperations, SubscriptionResourceIdentifier id) - : base(parentResourceOperations, id) - { - } - - // TODO should we update valid types to be list? - protected override ResourceType ValidResourceType => AllValidResourceTypes.First(); - - /// - /// Verify that the input resource Id is a valid container for this type. - /// - /// The input resource Id to check. - /// Resource identifier is not a valid type for this container. - protected override void Validate(ResourceIdentifier identifier) - { - if (!AllValidResourceTypes.Contains(identifier.ResourceType)) - throw new InvalidOperationException($"Invalid resource type {identifier?.ResourceType}."); - } - } -} diff --git a/sdk/resourcemanager/Proto.Client/src/Scenarios/VMImageTests.cs b/sdk/resourcemanager/Proto.Client/src/Scenarios/VMImageTests.cs index 030c2fb955d4..9ecf63da91f6 100644 --- a/sdk/resourcemanager/Proto.Client/src/Scenarios/VMImageTests.cs +++ b/sdk/resourcemanager/Proto.Client/src/Scenarios/VMImageTests.cs @@ -50,11 +50,11 @@ public override void Execute() foreach (var t in subscription.GetVmExtensionImages().ListTypes(defaultLocation, defaultPublisher)) { - Console.WriteLine(t.Data.Name); + Console.WriteLine(t.Name); - foreach (var v in subscription.GetVmExtensionImages().ListVersions(defaultLocation, defaultPublisher, t.Data.Name)) + foreach (var v in subscription.GetVmExtensionImages().ListVersions(defaultLocation, defaultPublisher, t.Name)) { - Console.WriteLine(v.Data.Name); + Console.WriteLine(v.Name); } } } From c6eb44d359c102a57b71e0573a920f0c9c2de6cf Mon Sep 17 00:00:00 2001 From: Allen Zhang Date: Tue, 11 May 2021 13:59:26 -0700 Subject: [PATCH 4/7] Removed BasicContainerBase and making ContainerBase without TryGet --- .../src/BasicContainerBase.cs | 79 --------------- .../src/ContainerBase.cs | 99 +------------------ .../src/ResourceContainerBase.cs | 97 +++++++++++++++++- .../src/SingletonOperationsBase.cs | 2 +- .../src/SubscriptionContainer.cs | 19 +++- .../VirtualMachineExtensionImageContainer.cs | 19 ++-- .../compute/VirtualMachineImageContainer.cs | 24 +++-- .../Proto.Client/src/Program.cs | 2 +- 8 files changed, 142 insertions(+), 199 deletions(-) delete mode 100644 sdk/resourcemanager/Azure.ResourceManager.Core/src/BasicContainerBase.cs diff --git a/sdk/resourcemanager/Azure.ResourceManager.Core/src/BasicContainerBase.cs b/sdk/resourcemanager/Azure.ResourceManager.Core/src/BasicContainerBase.cs deleted file mode 100644 index 98188b8d2dab..000000000000 --- a/sdk/resourcemanager/Azure.ResourceManager.Core/src/BasicContainerBase.cs +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; - -namespace Azure.ResourceManager.Core -{ - /// - /// A class representing collection of resources and their operations over their parent. - /// - public abstract class BasicContainerBase : OperationsBase - { - private static readonly object _parentLock = new object(); - private object _parentResource; - - /// - /// Gets the parent resource of this resource. - /// - protected ResourceOperationsBase Parent { get; } - - /// - /// Initializes a new instance of the class for mocking. - /// - protected BasicContainerBase() - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The resource representing the parent resource. - protected BasicContainerBase(ResourceOperationsBase parent) - : base(new ClientContext(parent.ClientOptions, parent.Credential, parent.BaseUri, parent.Pipeline), parent.Id) - { - Parent = parent; - } - - /// - /// Verify that the input resource Id is a valid container for this type. - /// - /// The input resource Id to check. - /// Resource identifier is not a valid type for this container. - protected override void Validate(ResourceIdentifier identifier) - { - if (identifier.ResourceType != ValidResourceType) - throw new InvalidOperationException($"{identifier.ResourceType} is not a valid container for {Id.ResourceType}"); - } - - /// - /// Gets the location of the parent object. - /// - /// The type of the parents full resource object. - /// The type of the parents resource id. - /// The type of the parents operations object. - /// The associated with the parent object. - protected TParent GetParentResource() - where TParent : TParentOperations - where TParentOperations : ResourceOperationsBase - where TParentId : ResourceIdentifier - { - if (_parentResource is null) - { - lock (_parentLock) - { - if (_parentResource is null) - { - _parentResource = Parent as TParent; - if (_parentResource is null) - { - _parentResource = (Parent as TParentOperations).Get().Value; - } - } - } - } - - return _parentResource as TParent; - } - } -} diff --git a/sdk/resourcemanager/Azure.ResourceManager.Core/src/ContainerBase.cs b/sdk/resourcemanager/Azure.ResourceManager.Core/src/ContainerBase.cs index 019339c0e89f..77576e91cd69 100644 --- a/sdk/resourcemanager/Azure.ResourceManager.Core/src/ContainerBase.cs +++ b/sdk/resourcemanager/Azure.ResourceManager.Core/src/ContainerBase.cs @@ -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 { /// /// Base class representing collection of resources. /// - /// The type of the class containing operations for the underlying resource. /// The type of the resource identifier. - public abstract class ContainerBase : OperationsBase - where TOperations : ResourceOperationsBase where TIdentifier : ResourceIdentifier + public abstract class ContainerBase : OperationsBase + where TIdentifier : ResourceIdentifier { /// - /// Initializes a new instance of the class for mocking. + /// Initializes a new instance of the class for mocking. /// protected ContainerBase() { } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// /// The identifier of the resource that is the target of operations. @@ -34,7 +28,7 @@ internal ContainerBase(ClientContext clientContext, TIdentifier id) } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The resource representing the parent resource. protected ContainerBase(ResourceOperationsBase parent) @@ -47,88 +41,5 @@ protected ContainerBase(ResourceOperationsBase parent) /// Gets the parent resource of this resource. /// protected ResourceOperationsBase Parent { get; } - - /// - /// Returns the resource from Azure if it exists. - /// - /// The name of the resource you want to get. - /// A token to allow the caller to cancel the call to the service. - /// The default value is . - /// Whether or not the resource existed. - 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; - } - } - - /// - /// Returns the resource from Azure if it exists. - /// - /// The name of the resource you want to get. - /// A token to allow the caller to cancel the call to the service. - /// The default value is . - /// Whether or not the resource existed. - public async virtual Task 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; - } - } - - /// - /// Determines whether or not the azure resource exists in this container - /// - /// The name of the resource you want to check. - /// Whether or not the resource existed. - public virtual bool DoesExist(string resourceName) - { - return TryGet(resourceName) == null ? false : true; - } - - /// - /// Get an instance of the operations this container holds. - /// - /// The name of the resource to scope the operations to. - /// An instance of . - protected virtual ResourceOperationsBase 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; - } } } diff --git a/sdk/resourcemanager/Azure.ResourceManager.Core/src/ResourceContainerBase.cs b/sdk/resourcemanager/Azure.ResourceManager.Core/src/ResourceContainerBase.cs index 4752c687452b..85aa75eb108f 100644 --- a/sdk/resourcemanager/Azure.ResourceManager.Core/src/ResourceContainerBase.cs +++ b/sdk/resourcemanager/Azure.ResourceManager.Core/src/ResourceContainerBase.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using System.Globalization; using System.Threading; using System.Threading.Tasks; @@ -13,7 +14,7 @@ namespace Azure.ResourceManager.Core /// The type of the resource identifier. /// The type of the class containing operations for the underlying resource. /// The type of the class containing properties for the underlying resource. - public abstract class ResourceContainerBase : ContainerBase + public abstract class ResourceContainerBase : ContainerBase where TIdentifier : TenantResourceIdentifier where TOperations : ResourceOperationsBase where TResource : class @@ -28,6 +29,17 @@ protected ResourceContainerBase() { } + /// + /// Initializes a new instance of the class. + /// Note: This is only used by SubscriptionContainers. Hence internal only. + /// + /// + /// + internal ResourceContainerBase(ClientContext clientContext, TIdentifier id) + : base(clientContext, id) + { + } + /// /// Initializes a new instance of the class. /// @@ -95,5 +107,88 @@ protected TParent GetParentResource() /// A that on completion returns a response with the operation for this resource. /// resourceName cannot be null or a whitespace. public abstract Task> GetAsync(string resourceName, CancellationToken cancellationToken = default); + + /// + /// Returns the resource from Azure if it exists. + /// + /// The name of the resource you want to get. + /// A token to allow the caller to cancel the call to the service. + /// The default value is . + /// Whether or not the resource existed. + 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; + } + } + + /// + /// Returns the resource from Azure if it exists. + /// + /// The name of the resource you want to get. + /// A token to allow the caller to cancel the call to the service. + /// The default value is . + /// Whether or not the resource existed. + public async virtual Task 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; + } + } + + /// + /// Determines whether or not the azure resource exists in this container + /// + /// The name of the resource you want to check. + /// Whether or not the resource existed. + public virtual bool DoesExist(string resourceName) + { + return TryGet(resourceName) == null ? false : true; + } + + /// + /// Get an instance of the operations this container holds. + /// + /// The name of the resource to scope the operations to. + /// An instance of . + protected virtual ResourceOperationsBase 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; + } } } diff --git a/sdk/resourcemanager/Azure.ResourceManager.Core/src/SingletonOperationsBase.cs b/sdk/resourcemanager/Azure.ResourceManager.Core/src/SingletonOperationsBase.cs index 5a422406ebd3..5e6aae942126 100644 --- a/sdk/resourcemanager/Azure.ResourceManager.Core/src/SingletonOperationsBase.cs +++ b/sdk/resourcemanager/Azure.ResourceManager.Core/src/SingletonOperationsBase.cs @@ -60,7 +60,7 @@ protected SingletonOperationsBase() } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The resource representing the parent resource. protected SingletonOperationsBase(OperationsBase parent) diff --git a/sdk/resourcemanager/Azure.ResourceManager.Core/src/SubscriptionContainer.cs b/sdk/resourcemanager/Azure.ResourceManager.Core/src/SubscriptionContainer.cs index 26cbf02b7264..8274bedad507 100644 --- a/sdk/resourcemanager/Azure.ResourceManager.Core/src/SubscriptionContainer.cs +++ b/sdk/resourcemanager/Azure.ResourceManager.Core/src/SubscriptionContainer.cs @@ -3,6 +3,7 @@ using System; using System.Threading; +using System.Threading.Tasks; using Azure.Core; using Azure.ResourceManager.Resources; @@ -11,7 +12,7 @@ namespace Azure.ResourceManager.Core /// /// A class representing collection of Subscription and their operations /// - public class SubscriptionContainer : ContainerBase + public class SubscriptionContainer : ResourceContainerBase { /// /// Initializes a new instance of the class for mocking. @@ -103,6 +104,22 @@ protected override void Validate(ResourceIdentifier identifier) throw new ArgumentException("Invalid parent for subscription container", nameof(identifier)); } + /// + public override ArmResponse Get(string subscriptionGuid, CancellationToken cancellationToken = default) + { + return new SubscriptionOperations( + new ClientContext(ClientOptions, Credential, BaseUri, Pipeline), + subscriptionGuid).Get(cancellationToken); + } + + /// + public override Task> GetAsync(string subscriptionGuid, CancellationToken cancellationToken = default) + { + return new SubscriptionOperations( + new ClientContext(ClientOptions, Credential, BaseUri, Pipeline), + subscriptionGuid).GetAsync(cancellationToken); + } + /// /// Get an instance of the operations this container holds. /// diff --git a/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImageContainer.cs b/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImageContainer.cs index e042a0d10fa0..11ae3693bf59 100644 --- a/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImageContainer.cs +++ b/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImageContainer.cs @@ -2,9 +2,7 @@ // Licensed under the MIT License. using System.Collections.Generic; -using System.Linq; using System.Threading; -using System.Threading.Tasks; using Azure.ResourceManager.Compute; using Azure.ResourceManager.Compute.Models; using Azure.ResourceManager.Core; @@ -14,20 +12,23 @@ namespace Proto.Compute /// /// A class representing collection of VirtualMachine and their operations over a ResourceGroup. /// - public class VirtualMachineExtensionImageContainer : BasicContainerBase + public class VirtualMachineExtensionImageContainer : ContainerBase { + private string _subsriptionId; + /// /// Initializes a new instance of the class. /// - /// The ResourceGroup that is the parent of the VirtualMachines. - internal VirtualMachineExtensionImageContainer(SubscriptionOperations resourceGroup) - : base(resourceGroup) + /// The subscription that is the parent of the VirtualMachinesExtensionImage. + internal VirtualMachineExtensionImageContainer(SubscriptionOperations subscription) + : base(subscription) { + _subsriptionId = subscription.Id.SubscriptionId; } - private Azure.ResourceManager.Compute.VirtualMachineExtensionImagesOperations Operations => new ComputeManagementClient( + private VirtualMachineExtensionImagesOperations Operations => new ComputeManagementClient( BaseUri, - GetParentResource().Id.SubscriptionId, + _subsriptionId, Credential, ClientOptions.Convert()).VirtualMachineExtensionImages; @@ -44,7 +45,7 @@ public ArmResponse Get( CancellationToken cancellationToken = default) { return new PhArmResponse( + VirtualMachineExtensionImage>( Operations.Get(location, publisher, type, version, cancellationToken), v => v); } diff --git a/sdk/resourcemanager/Proto.Client/compute/VirtualMachineImageContainer.cs b/sdk/resourcemanager/Proto.Client/compute/VirtualMachineImageContainer.cs index cea422cf08b1..81c9284812f9 100644 --- a/sdk/resourcemanager/Proto.Client/compute/VirtualMachineImageContainer.cs +++ b/sdk/resourcemanager/Proto.Client/compute/VirtualMachineImageContainer.cs @@ -2,9 +2,7 @@ // Licensed under the MIT License. using System.Collections.Generic; -using System.Linq; using System.Threading; -using System.Threading.Tasks; using Azure.ResourceManager.Compute; using Azure.ResourceManager.Compute.Models; using Azure.ResourceManager.Core; @@ -14,9 +12,9 @@ namespace Proto.Compute /// /// A class representing collection of VirtualMachine and their operations over a ResourceGroup. /// - public class VirtualMachineImageContainer : BasicContainerBase + public class VirtualMachineImageContainer : ContainerBase { - private string _subsriptionId; + private string _subscriptionId; /// /// Initializes a new instance of the class. @@ -25,12 +23,12 @@ public class VirtualMachineImageContainer : BasicContainerBase internal VirtualMachineImageContainer(SubscriptionOperations parent) : base(parent) { - _subsriptionId = parent.Id.SubscriptionId; + _subscriptionId = parent.Id.SubscriptionId; } - private Azure.ResourceManager.Compute.VirtualMachineImagesOperations Operations => new ComputeManagementClient( + private VirtualMachineImagesOperations Operations => new ComputeManagementClient( BaseUri, - _subsriptionId, + _subscriptionId, Credential, ClientOptions.Convert()).VirtualMachineImages; @@ -44,23 +42,23 @@ public ArmResponse Get( string version, CancellationToken cancellationToken = default) { - return new PhArmResponse( + return new PhArmResponse( Operations.Get(location, publisher, offer, sku, version, cancellationToken), v => v); } - public IEnumerable ListPublishers( + public IEnumerable ListOffers( string location, + string publisher, CancellationToken cancellationToken = default) { - return Operations.ListPublishers(location, cancellationToken).Value; + return Operations.ListOffers(location, publisher, cancellationToken).Value; } - public IEnumerable ListOffers( + public IEnumerable ListPublishers( string location, - string publisher, CancellationToken cancellationToken = default) { - return Operations.ListOffers(location, publisher, cancellationToken).Value; + return Operations.ListPublishers(location, cancellationToken).Value; } public IEnumerable ListSkus( diff --git a/sdk/resourcemanager/Proto.Client/src/Program.cs b/sdk/resourcemanager/Proto.Client/src/Program.cs index 28bfac1ee964..9c94e0e9503c 100644 --- a/sdk/resourcemanager/Proto.Client/src/Program.cs +++ b/sdk/resourcemanager/Proto.Client/src/Program.cs @@ -11,7 +11,7 @@ static void Main(string[] args) Scenario scenario = null; try { - scenario = ScenarioFactory.GetScenario(Scenarios.VMImageTests); + scenario = ScenarioFactory.GetScenario(Scenarios.GetSubscription); scenario.Execute(); } finally From 754e5f008cbe5803d6ab45a50d8f6bd6e8306e65 Mon Sep 17 00:00:00 2001 From: Allen Zhang Date: Tue, 11 May 2021 15:02:38 -0700 Subject: [PATCH 5/7] Fixing test failures. --- .../src/ResourceContainerBase.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sdk/resourcemanager/Azure.ResourceManager.Core/src/ResourceContainerBase.cs b/sdk/resourcemanager/Azure.ResourceManager.Core/src/ResourceContainerBase.cs index 48d61d1f1df1..7fcaaded8fe2 100644 --- a/sdk/resourcemanager/Azure.ResourceManager.Core/src/ResourceContainerBase.cs +++ b/sdk/resourcemanager/Azure.ResourceManager.Core/src/ResourceContainerBase.cs @@ -19,7 +19,7 @@ public abstract class ResourceContainerBase where TOperations : ResourceOperationsBase where TResource : class { - private static readonly object _parentLock = new object(); + private readonly object _parentLock = new object(); private object _parentResource; /// @@ -116,7 +116,7 @@ protected TParent GetParentResource() /// Whether or not the resource existed. public virtual TOperations TryGet(string resourceName, CancellationToken cancellationToken = default) { - using var scope = Diagnostics.CreateScope("ContainerBase`2.TryGet"); + using var scope = Diagnostics.CreateScope("ResourceContainerBase`3.TryGet"); scope.Start(); var op = GetOperation(resourceName); @@ -143,9 +143,9 @@ public virtual TOperations TryGet(string resourceName, CancellationToken cancell /// A token to allow the caller to cancel the call to the service. /// The default value is . /// Whether or not the resource existed. - public async virtual Task TryGetAsync(string resourceName, CancellationToken cancellationToken = default) + public virtual async Task TryGetAsync(string resourceName, CancellationToken cancellationToken = default) { - using var scope = Diagnostics.CreateScope("ContainerBase`2.TryGet"); + using var scope = Diagnostics.CreateScope("ResourceContainerBase`3.TryGet"); scope.Start(); var op = GetOperation(resourceName); From b8e512828bbd450de3e7e38fc01198e35bc2989f Mon Sep 17 00:00:00 2001 From: Allen Zhang Date: Tue, 11 May 2021 23:41:49 -0700 Subject: [PATCH 6/7] Added async methods, TryGet, and DoesExist --- .../VirtualMachineExtensionImageContainer.cs | 150 +++++++++++-- .../compute/VirtualMachineImageContainer.cs | 197 ++++++++++++++++-- .../Proto.Client/src/Program.cs | 2 +- .../src/Scenarios/GetSubscription.cs | 5 +- .../src/Scenarios/VMImageTests.cs | 1 - 5 files changed, 314 insertions(+), 41 deletions(-) diff --git a/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImageContainer.cs b/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImageContainer.cs index f718788e5d43..07ead0dd3fc0 100644 --- a/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImageContainer.cs +++ b/sdk/resourcemanager/Proto.Client/compute/VirtualMachineExtensionImageContainer.cs @@ -1,8 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System; using System.Collections.Generic; using System.Threading; +using System.Threading.Tasks; using Azure; using Azure.ResourceManager.Compute; using Azure.ResourceManager.Compute.Models; @@ -18,7 +20,7 @@ public class VirtualMachineExtensionImageContainer : ContainerBase - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The subscription that is the parent of the VirtualMachinesExtensionImage. internal VirtualMachineExtensionImageContainer(SubscriptionOperations subscription) @@ -40,39 +42,157 @@ internal VirtualMachineExtensionImageContainer(SubscriptionOperations subscripti public Response Get( string location, - string publisher, + string publisherName, string type, string version, CancellationToken cancellationToken = default) { - return new PhArmResponse( - Operations.Get(location, publisher, type, version, cancellationToken), - v => v); + return Operations.Get(location, publisherName, type, version, cancellationToken); + } + + public async Task> GetAsync( + string location, + string publisherName, + string type, + string version, + CancellationToken cancellationToken = default) + { + return await Operations.GetAsync(location, publisherName, type, version, cancellationToken) + .ConfigureAwait(false); } public IEnumerable ListTypes( string location, - string publisher, + string publisherName, CancellationToken cancellationToken = default) { - return Operations - .ListTypes(location, publisher, cancellationToken) - .Value; + return Operations.ListTypes(location, publisherName, cancellationToken).Value; + } + + public async Task> ListTypesAsync( + string location, + string publisherName, + CancellationToken cancellationToken = default) + { + return (await Operations.ListTypesAsync(location, publisherName, cancellationToken).ConfigureAwait(false)).Value; } public IEnumerable ListVersions( string location, - string publisher, + string publisherName, string type, string filter = null, int? top = null, string orderby = null, CancellationToken cancellationToken = default) { - return Operations - .ListVersions(location, publisher, type, filter: filter, top: top, orderby: orderby, cancellationToken: cancellationToken) - .Value; + return Operations.ListVersions(location, publisherName, type, filter: filter, top: top, orderby: orderby, cancellationToken: cancellationToken).Value; + } + + public async Task> ListVersionsAsync( + string location, + string publisherName, + string type, + string filter = null, + int? top = null, + string orderby = null, + CancellationToken cancellationToken = default) + { + return (await Operations.ListVersionsAsync(location, publisherName, type, filter: filter, top: top, orderby: orderby, cancellationToken: cancellationToken).ConfigureAwait(false)).Value; + } + + /// + /// Returns the resource from Azure if it exists. + /// + /// The location of the . + /// The publisherName of the . + /// The type of the . + /// The version of the . + /// A token to allow the caller to cancel the call to the service. + /// The default value is . + /// An instance of resource or null if not found. + public VirtualMachineExtensionImage TryGet( + string location, + string publisherName, + string type, + string version, + CancellationToken cancellationToken = default) + { + try + { + return Get(location:location, publisherName:publisherName, type:type, version:version, cancellationToken:cancellationToken).Value; + } + catch (RequestFailedException e) when (e.Status == 404) + { + return null; + } + } + + /// + /// Returns the resource from Azure if it exists. + /// + /// The location of the . + /// The publisherName of the . + /// The type of the . + /// The version of the . + /// A token to allow the caller to cancel the call to the service. + /// The default value is . + /// An instance of resource or null if not found. + public async Task TryGetAsync( + string location, + string publisherName, + string type, + string version, + CancellationToken cancellationToken = default) + { + try + { + return (await GetAsync(location: location, publisherName: publisherName, type: type, version: version, cancellationToken: cancellationToken).ConfigureAwait(false)).Value; + } + catch (RequestFailedException e) when (e.Status == 404) + { + return null; + } + } + + /// + /// Determines whether or not the azure resource exists in this container + /// + /// The location of the . + /// The publisherName of the . + /// The type of the . + /// The version of the . + /// A token to allow the caller to cancel the call to the service. + /// The default value is . + /// Whether or not the resource existed. + public bool DoesExist( + string location, + string publisherName, + string type, + string version, + CancellationToken cancellationToken = default) + { + return TryGet(location: location, publisherName: publisherName, type: type, version: version, cancellationToken: cancellationToken) != null; + } + + /// + /// Determines whether or not the azure resource exists in this container + /// + /// The location of the . + /// The publisherName of the . + /// The type of the . + /// The version of the . + /// A token to allow the caller to cancel the call to the service. + /// The default value is . + /// Whether or not the resource existed. + public async Task DoesExistAsync( + string location, + string publisherName, + string type, + string version, + CancellationToken cancellationToken = default) + { + return await TryGetAsync(location: location, publisherName: publisherName, type: type, version: version, cancellationToken: cancellationToken).ConfigureAwait(false) != null; } } -} \ No newline at end of file +} diff --git a/sdk/resourcemanager/Proto.Client/compute/VirtualMachineImageContainer.cs b/sdk/resourcemanager/Proto.Client/compute/VirtualMachineImageContainer.cs index dca98f659277..30df61872173 100644 --- a/sdk/resourcemanager/Proto.Client/compute/VirtualMachineImageContainer.cs +++ b/sdk/resourcemanager/Proto.Client/compute/VirtualMachineImageContainer.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Threading; +using System.Threading.Tasks; using Azure; using Azure.ResourceManager.Compute; using Azure.ResourceManager.Compute.Models; @@ -18,7 +19,7 @@ public class VirtualMachineImageContainer : ContainerBase - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The parent subscription. internal VirtualMachineImageContainer(SubscriptionOperations parent) @@ -37,22 +38,40 @@ internal VirtualMachineImageContainer(SubscriptionOperations parent) public Response Get( string location, - string publisher, + string publisherName, string offer, - string sku, + string skus, + string version, + CancellationToken cancellationToken = default) + { + return Operations.Get(location, publisherName, offer, skus, version, cancellationToken); + } + + public async Task> GetAsync( + string location, + string publisherName, + string offer, + string skus, string version, CancellationToken cancellationToken = default) { - return new PhArmResponse( - Operations.Get(location, publisher, offer, sku, version, cancellationToken), v => v); + return await Operations.GetAsync(location, publisherName, offer, skus, version, cancellationToken); } public IEnumerable ListOffers( string location, - string publisher, + string publisherName, CancellationToken cancellationToken = default) { - return Operations.ListOffers(location, publisher, cancellationToken).Value; + return Operations.ListOffers(location, publisherName, cancellationToken).Value; + } + + public async Task> ListOffersAsync( + string location, + string publisherName, + CancellationToken cancellationToken = default) + { + return (await Operations.ListOffersAsync(location, publisherName, cancellationToken).ConfigureAwait(false)).Value; } public IEnumerable ListPublishers( @@ -62,18 +81,34 @@ public IEnumerable ListPublishers( return Operations.ListPublishers(location, cancellationToken).Value; } + public async Task> ListPublishersAsync( + string location, + CancellationToken cancellationToken = default) + { + return (await Operations.ListPublishersAsync(location, cancellationToken).ConfigureAwait(false)).Value; + } + public IEnumerable ListSkus( string location, - string publisher, + string publisherName, string offer, CancellationToken cancellationToken = default) { - return Operations.ListSkus(location, publisher, offer, cancellationToken).Value; + return Operations.ListSkus(location, publisherName, offer, cancellationToken).Value; + } + + public async Task> ListSkusAsync( + string location, + string publisherName, + string offer, + CancellationToken cancellationToken = default) + { + return (await Operations.ListSkusAsync(location, publisherName, offer, cancellationToken).ConfigureAwait(false)).Value; } public IEnumerable ListVersions( string location, - string publisher, + string publisherName, string offer, string skus, string expand = null, @@ -81,16 +116,136 @@ public IEnumerable ListVersions( string orderby = null, CancellationToken cancellationToken = default) { - return Operations.List( - location, - publisher, - offer, - skus, - expand: expand, - top: top, - orderby: orderby, - cancellationToken: cancellationToken) - .Value; + return Operations.List(location, + publisherName: publisherName, + offer: offer, + skus: skus, + expand: expand, + top: top, + orderby: orderby, + cancellationToken: cancellationToken).Value; + } + + public async Task> ListVersionsAsync( + string location, + string publisherName, + string offer, + string skus, + string expand = null, + int? top = null, + string orderby = null, + CancellationToken cancellationToken = default) + { + return (await Operations.ListAsync(location, + publisherName: publisherName, + offer: offer, + skus: skus, + expand: expand, + top: top, + orderby: orderby, + cancellationToken: cancellationToken).ConfigureAwait(false)).Value; + } + + /// + /// Returns the resource from Azure if it exists. + /// + /// The location of the . + /// The publisherName of the . + /// The offer of the . + /// The skus of the . + /// The version of the . + /// A token to allow the caller to cancel the call to the service. + /// The default value is . + /// An instance of resource or null if not found. + public VirtualMachineImage TryGet( + string location, + string publisherName, + string offer, + string skus, + string version, + CancellationToken cancellationToken = default) + { + try + { + return Get(location: location, publisherName: publisherName, offer: offer, skus: skus, version: version, cancellationToken: cancellationToken).Value; + } + catch (RequestFailedException e) when (e.Status == 404) + { + return null; + } + } + + /// + /// Returns the resource from Azure if it exists. + /// + /// The location of the . + /// The publisherName of the . + /// The offer of the . + /// The skus of the . + /// The version of the . + /// A token to allow the caller to cancel the call to the service. + /// The default value is . + /// An instance of resource or null if not found. + public async Task TryGetAsync( + string location, + string publisherName, + string offer, + string skus, + string version, + CancellationToken cancellationToken = default) + { + try + { + return (await GetAsync(location: location, publisherName: publisherName, offer: offer, skus: skus, version: version, cancellationToken: cancellationToken).ConfigureAwait(false)).Value; + } + catch (RequestFailedException e) when (e.Status == 404) + { + return null; + } + } + + /// + /// Determines whether or not the azure resource exists in this container + /// + /// The location of the . + /// The publisherName of the . + /// The offer of the . + /// The skus of the . + /// The version of the . + /// A token to allow the caller to cancel the call to the service. + /// The default value is . + /// Whether or not the resource existed. + public bool DoesExist( + string location, + string publisherName, + string offer, + string skus, + string version, + CancellationToken cancellationToken = default) + { + return TryGet(location: location, publisherName: publisherName, offer: offer, skus: skus, version: version, cancellationToken: cancellationToken) != null; + } + + /// + /// Determines whether or not the azure resource exists in this container + /// + /// The location of the . + /// The publisherName of the . + /// The offer of the . + /// The skus of the . + /// The version of the . + /// A token to allow the caller to cancel the call to the service. + /// The default value is . + /// Whether or not the resource existed. + public async Task DoesExistAsync( + string location, + string publisherName, + string offer, + string skus, + string version, + CancellationToken cancellationToken = default) + { + return await TryGetAsync(location: location, publisherName: publisherName, offer: offer, skus: skus, version: version, cancellationToken: cancellationToken).ConfigureAwait(false) != null; } } -} \ No newline at end of file +} diff --git a/sdk/resourcemanager/Proto.Client/src/Program.cs b/sdk/resourcemanager/Proto.Client/src/Program.cs index fbe8d85a8c7c..99dca879654c 100644 --- a/sdk/resourcemanager/Proto.Client/src/Program.cs +++ b/sdk/resourcemanager/Proto.Client/src/Program.cs @@ -11,7 +11,7 @@ static void Main(string[] args) Scenario scenario = null; try { - scenario = ScenarioFactory.GetScenario(Scenarios.GetSubscription); + scenario = ScenarioFactory.GetScenario(Scenarios.VMImageTests); scenario.Execute(); } finally diff --git a/sdk/resourcemanager/Proto.Client/src/Scenarios/GetSubscription.cs b/sdk/resourcemanager/Proto.Client/src/Scenarios/GetSubscription.cs index a05f1ed9d66f..dca02e127202 100644 --- a/sdk/resourcemanager/Proto.Client/src/Scenarios/GetSubscription.cs +++ b/sdk/resourcemanager/Proto.Client/src/Scenarios/GetSubscription.cs @@ -12,9 +12,8 @@ public override void Execute() var sandboxId = "db1ab6f0-4769-4b27-930e-01e2ef9c123c"; var expectDisplayName = "Azure SDK sandbox"; var subOp = new ArmClient(new DefaultAzureCredential()).GetSubscriptions().TryGet(sandboxId); - var result = subOp.Get(); - Debug.Assert(expectDisplayName == result.Value.Data.DisplayName); - Console.WriteLine("Passed, got " + result.Value.Data.DisplayName); + Debug.Assert(expectDisplayName == subOp.Data.DisplayName); + Console.WriteLine("Passed, got " + subOp.Data.DisplayName); } } diff --git a/sdk/resourcemanager/Proto.Client/src/Scenarios/VMImageTests.cs b/sdk/resourcemanager/Proto.Client/src/Scenarios/VMImageTests.cs index 9ecf63da91f6..bcd3a73ac72e 100644 --- a/sdk/resourcemanager/Proto.Client/src/Scenarios/VMImageTests.cs +++ b/sdk/resourcemanager/Proto.Client/src/Scenarios/VMImageTests.cs @@ -17,7 +17,6 @@ public override void Execute() var subscription = client.DefaultSubscription; var defaultLocation = "westus2"; - //var defaultPublisher = "TrendMicro.DeepSecurity"; var defaultPublisher = "redhat"; foreach (var p in subscription.GetVmImages().ListPublishers(defaultLocation)) From c70021ec6bf29a1f2fe392f7acc0ddb14a733149 Mon Sep 17 00:00:00 2001 From: Allen Zhang Date: Wed, 12 May 2021 00:43:57 -0700 Subject: [PATCH 7/7] Updating test cases --- .../Proto.Client/src/Program.cs | 2 +- .../Proto.Client/src/ScenarioFactory.cs | 2 +- .../src/Scenarios/VMImageTests.cs | 113 ++++++++++++++++-- 3 files changed, 102 insertions(+), 15 deletions(-) diff --git a/sdk/resourcemanager/Proto.Client/src/Program.cs b/sdk/resourcemanager/Proto.Client/src/Program.cs index 99dca879654c..e528a5c9874c 100644 --- a/sdk/resourcemanager/Proto.Client/src/Program.cs +++ b/sdk/resourcemanager/Proto.Client/src/Program.cs @@ -11,7 +11,7 @@ static void Main(string[] args) Scenario scenario = null; try { - scenario = ScenarioFactory.GetScenario(Scenarios.VMImageTests); + scenario = ScenarioFactory.GetScenario(Scenarios.VmImageTests); scenario.Execute(); } finally diff --git a/sdk/resourcemanager/Proto.Client/src/ScenarioFactory.cs b/sdk/resourcemanager/Proto.Client/src/ScenarioFactory.cs index 53df3617d5d3..2d769ee9d9ea 100644 --- a/sdk/resourcemanager/Proto.Client/src/ScenarioFactory.cs +++ b/sdk/resourcemanager/Proto.Client/src/ScenarioFactory.cs @@ -42,7 +42,7 @@ enum Scenarios CheckResourceGroupContainerAsync, GenericResourceOperationsExample, SingletonVmssUpgrade, - VMImageTests, + VmImageTests, } class ScenarioFactory diff --git a/sdk/resourcemanager/Proto.Client/src/Scenarios/VMImageTests.cs b/sdk/resourcemanager/Proto.Client/src/Scenarios/VMImageTests.cs index bcd3a73ac72e..fbf0377e6bba 100644 --- a/sdk/resourcemanager/Proto.Client/src/Scenarios/VMImageTests.cs +++ b/sdk/resourcemanager/Proto.Client/src/Scenarios/VMImageTests.cs @@ -3,38 +3,47 @@ using System; using System.Linq; +using System.Threading.Tasks; using Azure.Identity; using Azure.ResourceManager.Core; using Proto.Compute; namespace Proto.Client { - class VMImageTests : Scenario + class VmImageTests : Scenario { public override void Execute() { var client = new ArmClient(new DefaultAzureCredential()); + Execute(client); + ExecuteAsync(client).ConfigureAwait(false).GetAwaiter().GetResult(); + } + + private void Execute(ArmClient client) + { var subscription = client.DefaultSubscription; - var defaultLocation = "westus2"; + var defaultLocation = ((LocationData)Context.Loc).Name; var defaultPublisher = "redhat"; - foreach (var p in subscription.GetVmImages().ListPublishers(defaultLocation)) + Console.WriteLine($"--------Start listing all VMImage publishers at {defaultLocation}--------"); + foreach (var p in subscription.GetVmImages().ListPublishers(defaultLocation).Take(50)) { Console.WriteLine(p.Name); } - foreach (var o in subscription.GetVmImages().ListOffers(defaultLocation, defaultPublisher)) + Console.WriteLine($"--------Start listing all VMImage offers for Publisher {defaultPublisher}--------"); + foreach (var o in subscription.GetVmImages().ListOffers(defaultLocation, defaultPublisher).Take(3)) { Console.WriteLine($"offer:\t{o.Name}"); - foreach (var s in subscription.GetVmImages().ListSkus(defaultLocation, defaultPublisher, o.Name)) + foreach (var s in subscription.GetVmImages().ListSkus(defaultLocation, defaultPublisher, o.Name).Take(3)) { - Console.WriteLine($"sku:\t{s.Name}"); + Console.WriteLine($"\tsku:\t{s.Name}"); - foreach (var v in subscription.GetVmImages().ListVersions(defaultLocation, defaultPublisher, o.Name, s.Name).Where(v => v.Name == "7.8.20210222")) + foreach (var v in subscription.GetVmImages().ListVersions(defaultLocation, defaultPublisher, o.Name, s.Name).Take(2)) { - Console.WriteLine($"version:\t{v.Name}"); + Console.WriteLine($"\t\tversion:\t{v.Name}"); var vmImage = subscription.GetVmImages().Get( defaultLocation, @@ -42,20 +51,98 @@ public override void Execute() o.Name, s.Name, v.Name); - Console.WriteLine($"vmImage:\t{vmImage.Value.Id}"); + Console.WriteLine($"vmImage:\t\t\tVM Image:\t{vmImage.Value.Id}"); } } } - foreach (var t in subscription.GetVmExtensionImages().ListTypes(defaultLocation, defaultPublisher)) + Console.WriteLine($"--------Start listing all VMExtensionImage offers for Publisher {defaultPublisher}--------"); + foreach (var t in subscription.GetVmExtensionImages().ListTypes(defaultLocation, defaultPublisher).Take(5)) { - Console.WriteLine(t.Name); + Console.WriteLine($"\tType:\t{t.Name}"); - foreach (var v in subscription.GetVmExtensionImages().ListVersions(defaultLocation, defaultPublisher, t.Name)) + foreach (var v in subscription.GetVmExtensionImages().ListVersions(defaultLocation, defaultPublisher, t.Name).Take(5)) { - Console.WriteLine(v.Name); + Console.WriteLine($"\t\tOffer:\t{v.Name}"); } } + + if (!subscription.GetVmExtensionImages().DoesExist(defaultLocation, "Microsoft.Azure.Extensions", "DockerExtension", "1.2.0") + || subscription.GetVmExtensionImages().DoesExist(defaultLocation, "Microsoft.Azure.Extensions", "DockerExtension", "0.0.0")) + { + Console.WriteLine("!!!!!!! DoesExist check failed!"); + } + + if (subscription.GetVmExtensionImages().TryGet(defaultLocation, "Microsoft.Azure.Extensions", "DockerExtension", "1.2.0") == null + || subscription.GetVmExtensionImages().TryGet(defaultLocation, "Microsoft.Azure.Extensions", "DockerExtension", "0.0.0") != null) + { + Console.WriteLine("!!!!!!! DoesExist check failed!"); + } + + Console.WriteLine($"-------- All Sync VM image API test passed.--------"); + } + + private async Task ExecuteAsync (ArmClient client) + { + var subscription = client.DefaultSubscription; + + var defaultLocation = ((LocationData)Context.Loc).Name; + var defaultPublisher = "redhat"; + + Console.WriteLine($"--------Start listing all VMImage publishers at {defaultLocation}--------"); + foreach (var p in (await subscription.GetVmImages().ListPublishersAsync(defaultLocation)).Take(50)) + { + Console.WriteLine(p.Name); + } + + Console.WriteLine($"--------Start listing all VMImage offers for Publisher {defaultPublisher}--------"); + foreach (var o in (await subscription.GetVmImages().ListOffersAsync(defaultLocation, defaultPublisher)).Take(3)) + { + Console.WriteLine($"offer:\t{o.Name}"); + + foreach (var s in (await subscription.GetVmImages().ListSkusAsync(defaultLocation, defaultPublisher, o.Name)).Take(3)) + { + Console.WriteLine($"\tsku:\t{s.Name}"); + + foreach (var v in (await subscription.GetVmImages().ListVersionsAsync(defaultLocation, defaultPublisher, o.Name, s.Name)).Take(2)) + { + Console.WriteLine($"\t\tversion:\t{v.Name}"); + + var vmImage = await subscription.GetVmImages().GetAsync( + defaultLocation, + defaultPublisher, + o.Name, + s.Name, + v.Name); + Console.WriteLine($"vmImage:\t\t\tVM Image:\t{vmImage.Value.Id}"); + } + } + } + + Console.WriteLine($"--------Start listing all VMExtensionImage offers for Publisher {defaultPublisher}--------"); + foreach (var t in (await subscription.GetVmExtensionImages().ListTypesAsync(defaultLocation, defaultPublisher)).Take(5)) + { + Console.WriteLine($"\tType:\t{t.Name}"); + + foreach (var v in (await subscription.GetVmExtensionImages().ListVersionsAsync(defaultLocation, defaultPublisher, t.Name)).Take(5)) + { + Console.WriteLine($"\t\tOffer:\t{v.Name}"); + } + } + + if (!await subscription.GetVmExtensionImages().DoesExistAsync(defaultLocation, "Microsoft.Azure.Extensions", "DockerExtension", "1.2.0") + || await subscription.GetVmExtensionImages().DoesExistAsync(defaultLocation, "Microsoft.Azure.Extensions", "DockerExtension", "0.0.0")) + { + Console.WriteLine("!!!!!!! DoesExist check failed!"); + } + + if (await subscription.GetVmExtensionImages().TryGetAsync(defaultLocation, "Microsoft.Azure.Extensions", "DockerExtension", "1.2.0") == null + || await subscription.GetVmExtensionImages().TryGetAsync(defaultLocation, "Microsoft.Azure.Extensions", "DockerExtension", "0.0.0") != null) + { + Console.WriteLine("!!!!!!! DoesExist check failed!"); + } + + Console.WriteLine($"-------- All Async VM image API test passed.--------"); } } }