From eb64323a4267b1cd077c6fdf8ea382983767ec5d Mon Sep 17 00:00:00 2001 From: Haider Agha Date: Tue, 9 Dec 2025 15:05:07 -0500 Subject: [PATCH 1/2] Add initial implementation of ComputeClientTrack2 and solution files for Compute Management SDK --- .../Compute.Autorest/Az.Compute.csproj | 3 + .../KeyVault.Autorest/Az.KeyVault.csproj | 3 + .../Az.ManagedServiceIdentity.csproj | 3 + .../Compute.AlcWrapper.csproj | 4 + .../Compute.Helpers/Compute.Helpers.csproj | 4 + .../Compute.Management.Sdk.csproj | 4 + .../Compute.Management.Sdk.sln | 24 ++ src/Compute/Compute.Management.Sdk/README.md | 12 +- .../Rest-api-specs/common.json | 89 +++-- .../Rest-api-specs/types.json | 312 ++++++++++++++---- src/Compute/Compute.Test/Compute.Test.csproj | 4 + .../Compute/Common/ComputeClientBaseCmdlet.cs | 18 + .../Compute/Common/ComputeClientTrack2.cs | 310 +++++++++++++++++ src/Compute/Compute/Compute.csproj | 5 + src/Compute/Compute/Compute.sln | 24 ++ .../Operation/GetAzureVMCommand.cs | 29 +- .../Operation/UpdateAzureVMCommand.cs | 70 +++- .../KeyVault.Management.Sdk.csproj | 4 + src/KeyVault/KeyVault/KeyVault.csproj | 4 + .../ManagedServiceIdentity.csproj | 3 + .../Network.Management.Sdk.csproj | 3 + src/Network/Network/Network.csproj | 4 + tools/TestFx/TestFx.csproj | 4 + 23 files changed, 837 insertions(+), 103 deletions(-) create mode 100644 src/Compute/Compute.Management.Sdk/Compute.Management.Sdk.sln create mode 100644 src/Compute/Compute/Common/ComputeClientTrack2.cs create mode 100644 src/Compute/Compute/Compute.sln diff --git a/generated/Compute/Compute.Autorest/Az.Compute.csproj b/generated/Compute/Compute.Autorest/Az.Compute.csproj index 293217b42a73..37fce792d9b7 100644 --- a/generated/Compute/Compute.Autorest/Az.Compute.csproj +++ b/generated/Compute/Compute.Autorest/Az.Compute.csproj @@ -8,4 +8,7 @@ + + + diff --git a/generated/KeyVault/KeyVault.Autorest/Az.KeyVault.csproj b/generated/KeyVault/KeyVault.Autorest/Az.KeyVault.csproj index 26503c830786..366544f97795 100644 --- a/generated/KeyVault/KeyVault.Autorest/Az.KeyVault.csproj +++ b/generated/KeyVault/KeyVault.Autorest/Az.KeyVault.csproj @@ -8,4 +8,7 @@ + + + diff --git a/generated/ManagedServiceIdentity/ManagedServiceIdentity.Autorest/Az.ManagedServiceIdentity.csproj b/generated/ManagedServiceIdentity/ManagedServiceIdentity.Autorest/Az.ManagedServiceIdentity.csproj index b13dd5ffc3f1..ab387c119b0a 100644 --- a/generated/ManagedServiceIdentity/ManagedServiceIdentity.Autorest/Az.ManagedServiceIdentity.csproj +++ b/generated/ManagedServiceIdentity/ManagedServiceIdentity.Autorest/Az.ManagedServiceIdentity.csproj @@ -8,4 +8,7 @@ + + + diff --git a/src/Compute/Compute.AlcWrapper/Compute.AlcWrapper.csproj b/src/Compute/Compute.AlcWrapper/Compute.AlcWrapper.csproj index ed7b8a9bdfcc..038c1d818beb 100644 --- a/src/Compute/Compute.AlcWrapper/Compute.AlcWrapper.csproj +++ b/src/Compute/Compute.AlcWrapper/Compute.AlcWrapper.csproj @@ -17,6 +17,10 @@ + + + + diff --git a/src/Compute/Compute.Helpers/Compute.Helpers.csproj b/src/Compute/Compute.Helpers/Compute.Helpers.csproj index 0733e5aa3d80..1862b0de0b8d 100644 --- a/src/Compute/Compute.Helpers/Compute.Helpers.csproj +++ b/src/Compute/Compute.Helpers/Compute.Helpers.csproj @@ -15,4 +15,8 @@ + + + + diff --git a/src/Compute/Compute.Management.Sdk/Compute.Management.Sdk.csproj b/src/Compute/Compute.Management.Sdk/Compute.Management.Sdk.csproj index 1e6c939e70e1..022c4de917d3 100644 --- a/src/Compute/Compute.Management.Sdk/Compute.Management.Sdk.csproj +++ b/src/Compute/Compute.Management.Sdk/Compute.Management.Sdk.csproj @@ -15,4 +15,8 @@ + + + + diff --git a/src/Compute/Compute.Management.Sdk/Compute.Management.Sdk.sln b/src/Compute/Compute.Management.Sdk/Compute.Management.Sdk.sln new file mode 100644 index 000000000000..3697e52602f6 --- /dev/null +++ b/src/Compute/Compute.Management.Sdk/Compute.Management.Sdk.sln @@ -0,0 +1,24 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.2.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Compute.Management.Sdk", "Compute.Management.Sdk.csproj", "{4D5D485F-DB24-A55D-D626-74B523D84797}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4D5D485F-DB24-A55D-D626-74B523D84797}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4D5D485F-DB24-A55D-D626-74B523D84797}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4D5D485F-DB24-A55D-D626-74B523D84797}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4D5D485F-DB24-A55D-D626-74B523D84797}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {9BD3E99F-41C6-4076-BEEF-CAD959DCC74E} + EndGlobalSection +EndGlobal diff --git a/src/Compute/Compute.Management.Sdk/README.md b/src/Compute/Compute.Management.Sdk/README.md index 157831351d6c..68a0baf4bb57 100644 --- a/src/Compute/Compute.Management.Sdk/README.md +++ b/src/Compute/Compute.Management.Sdk/README.md @@ -25,12 +25,12 @@ title: ComputeManagementClient payload-flattening-threshold: 1 input-file: - - ./Rest-api-specs/types.json - - ./Rest-api-specs/common.json - - ./Rest-api-specs/ComputeRP.json - - ./Rest-api-specs/DiskRP.json - - ./Rest-api-specs/GalleryRP.json - - ./Rest-api-specs/skus.json + - https://github.com/Azure/azure-rest-api-specs/blob/main/specification/common-types/resource-management/v3/types.json + - https://github.com/Azure/azure-rest-api-specs/blob/main/specification/compute/resource-manager/Microsoft.Compute/common-types/v1/common.json + - https://github.com/Azure/azure-rest-api-specs/tree/main/specification/compute/resource-manager/Microsoft.Compute/ComputeRP/stable/2025-04-01/ComputeRP.json + - https://github.com/Azure/azure-rest-api-specs/tree/main/specification/compute/resource-manager/Microsoft.Compute/DiskRP/stable/2025-01-02/DiskRP.json + - https://github.com/Azure/azure-rest-api-specs/tree/main/specification/compute/resource-manager/Microsoft.Compute/GalleryRP/stable/2024-03-03/GalleryRP.json + - https://github.com/Azure/azure-rest-api-specs/tree/main/specification/compute/resource-manager/Microsoft.Compute/Skus/stable/2021-07-01/skus.json output-folder: Generated namespace: Microsoft.Azure.Management.Compute diff --git a/src/Compute/Compute.Management.Sdk/Rest-api-specs/common.json b/src/Compute/Compute.Management.Sdk/Rest-api-specs/common.json index 80b6a26588d8..7ecc3aa7068a 100644 --- a/src/Compute/Compute.Management.Sdk/Rest-api-specs/common.json +++ b/src/Compute/Compute.Management.Sdk/Rest-api-specs/common.json @@ -110,6 +110,42 @@ }, "description": "Api error." }, + "Resource": { + "type": "object", + "description": "The Resource model definition.", + "properties": { + "id": { + "readOnly": true, + "type": "string", + "description": "Resource Id" + }, + "name": { + "readOnly": true, + "type": "string", + "description": "Resource name" + }, + "type": { + "readOnly": true, + "type": "string", + "description": "Resource type" + }, + "location": { + "type": "string", + "description": "Resource location" + }, + "tags": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Resource tags" + } + }, + "required": [ + "location" + ], + "x-ms-azure-resource": true + }, "SubResource": { "type": "object", "properties": { @@ -138,44 +174,39 @@ "description": "Resource location" }, "id": { + "readOnly": true, "type": "string", - "description": "Resource Id", - "readOnly": true + "description": "Resource Id" }, "name": { + "readOnly": true, "type": "string", - "description": "Resource name", - "readOnly": true + "description": "Resource name" }, "type": { + "readOnly": true, "type": "string", - "description": "Resource type", - "readOnly": true + "description": "Resource type" }, "tags": { "type": "object", - "description": "Resource tags", "additionalProperties": { "type": "string" - } + }, + "description": "Resource tags" } - } + }, + "x-ms-azure-resource": true }, "ExtendedLocationType": { "type": "string", - "description": "The type of the extended location.", + "description": "The type of extendedLocation.", "enum": [ "EdgeZone" ], "x-ms-enum": { - "name": "ExtendedLocationType", - "modelAsString": true, - "values": [ - { - "name": "EdgeZone", - "value": "EdgeZone" - } - ] + "name": "ExtendedLocationTypes", + "modelAsString": true } }, "ExtendedLocation": { @@ -192,6 +223,26 @@ } } }, + "UserAssignedIdentities": { + "type": "object", + "additionalProperties": { + "type": "object", + "x-ms-client-name": "userAssignedIdentitiesValue", + "properties": { + "principalId": { + "readOnly": true, + "type": "string", + "description": "The principal id of user assigned identity." + }, + "clientId": { + "readOnly": true, + "type": "string", + "description": "The client id of user assigned identity." + } + } + }, + "description": "The list of user identities associated with the Virtual Machine. The user identity dictionary key references will be ARM resource ids in the form: '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/{identityName}'." + }, "SystemData": { "description": "The system meta data relating to this resource.", "type": "object", @@ -227,4 +278,4 @@ "description": "Client Api Version." } } -} +} \ No newline at end of file diff --git a/src/Compute/Compute.Management.Sdk/Rest-api-specs/types.json b/src/Compute/Compute.Management.Sdk/Rest-api-specs/types.json index 99a57d8f0158..fcbccc115085 100644 --- a/src/Compute/Compute.Management.Sdk/Rest-api-specs/types.json +++ b/src/Compute/Compute.Management.Sdk/Rest-api-specs/types.json @@ -19,7 +19,7 @@ }, "allOf": [ { - "$ref": "#/definitions/ResourceOriginal" + "$ref": "#/definitions/Resource" } ], "x-ms-client-name": "AzureEntityResource" @@ -133,6 +133,33 @@ } } }, + "Identity": { + "type": "object", + "description": "Identity for the resource.", + "properties": { + "principalId": { + "type": "string", + "description": "The principal ID of resource identity.", + "readOnly": true + }, + "tenantId": { + "type": "string", + "description": "The tenant ID of resource.", + "readOnly": true + }, + "type": { + "type": "string", + "description": "The identity type.", + "enum": [ + "SystemAssigned" + ], + "x-ms-enum": { + "name": "ResourceIdentityType", + "modelAsString": false + } + } + } + }, "KeyVaultProperties": { "type": "object", "properties": { @@ -146,42 +173,74 @@ } } }, - "Operation": {}, - "ResourceOriginal": { + "Operation": { "type": "object", - "description": "The Resource model definition.", + "title": "REST API Operation", + "description": "Details of a REST API operation, returned from the Resource Provider Operations API", "properties": { - "id": { - "readOnly": true, - "type": "string", - "description": "Resource Id" - }, "name": { - "readOnly": true, "type": "string", - "description": "Resource name" + "description": "The name of the operation, as per Resource-Based Access Control (RBAC). Examples: \"Microsoft.Compute/virtualMachines/write\", \"Microsoft.Compute/virtualMachines/capture/action\"", + "readOnly": true }, - "type": { - "readOnly": true, - "type": "string", - "description": "Resource type" + "isDataAction": { + "type": "boolean", + "description": "Whether the operation applies to data-plane. This is \"true\" for data-plane operations and \"false\" for ARM/control-plane operations.", + "readOnly": true }, - "location": { + "display": { + "type": "object", + "description": "Localized display information for this particular operation.", + "properties": { + "provider": { + "type": "string", + "description": "The localized friendly form of the resource provider name, e.g. \"Microsoft Monitoring Insights\" or \"Microsoft Compute\".", + "readOnly": true + }, + "resource": { + "type": "string", + "description": "The localized friendly name of the resource type related to this operation. E.g. \"Virtual Machines\" or \"Job Schedule Collections\".", + "readOnly": true + }, + "operation": { + "type": "string", + "description": "The concise, localized friendly name for the operation; suitable for dropdowns. E.g. \"Create or Update Virtual Machine\", \"Restart Virtual Machine\".", + "readOnly": true + }, + "description": { + "type": "string", + "description": "The short, localized friendly description of the operation; suitable for tool tips and detailed views.", + "readOnly": true + } + } + }, + "origin": { "type": "string", - "description": "Resource location" + "description": "The intended executor of the operation; as in Resource Based Access Control (RBAC) and audit logs UX. Default value is \"user,system\"", + "enum": [ + "user", + "system", + "user,system" + ], + "x-ms-enum": { + "name": "Origin", + "modelAsString": true + }, + "readOnly": true }, - "tags": { - "type": "object", - "additionalProperties": { - "type": "string" + "actionType": { + "type": "string", + "description": "Enum. Indicates the action type. \"Internal\" refers to actions that are for internal only APIs.", + "enum": [ + "Internal" + ], + "x-ms-enum": { + "name": "ActionType", + "modelAsString": true }, - "description": "Resource tags." + "readOnly": true } - }, - "required": [ - "location" - ], - "x-ms-azure-resource": true + } }, "OperationListResult": { "type": "object", @@ -253,27 +312,161 @@ "status" ] }, + "Plan": { + "type": "object", + "description": "Plan for the resource.", + "properties": { + "name": { + "type": "string", + "description": "A user defined name of the 3rd Party Artifact that is being procured." + }, + "publisher": { + "type": "string", + "description": "The publisher of the 3rd Party Artifact that is being bought. E.g. NewRelic" + }, + "product": { + "type": "string", + "description": "The 3rd Party artifact that is being procured. E.g. NewRelic. Product maps to the OfferID specified for the artifact at the time of Data Market onboarding. " + }, + "promotionCode": { + "type": "string", + "description": "A publisher provided promotion code as provisioned in Data Market for the said product/artifact." + }, + "version": { + "type": "string", + "description": "The version of the desired product/artifact." + } + }, + "required": [ + "name", + "publisher", + "product" + ] + }, "ProxyResource": { + "type": "object", + "title": "Proxy Resource", + "description": "The resource model definition for a Azure Resource Manager proxy resource. It will not have tags and a location", + "allOf": [ + { + "$ref": "#/definitions/Resource" + } + ] + }, + "Resource": { + "type": "object", + "title": "Resource", + "description": "Common fields that are returned in the response for all Azure Resource Manager resources", "properties": { "id": { - "readOnly": true, "type": "string", - "description": "Resource Id" + "description": "Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}", + "readOnly": true }, "name": { - "readOnly": true, "type": "string", - "description": "Resource name" + "description": "The name of the resource", + "readOnly": true }, "type": { - "readOnly": true, "type": "string", - "description": "Resource type" + "description": "The type of the resource. E.g. \"Microsoft.Compute/virtualMachines\" or \"Microsoft.Storage/storageAccounts\"", + "readOnly": true + }, + "systemData": { + "$ref": "#/definitions/systemData", + "type": "object", + "description": "Azure Resource Manager metadata containing createdBy and modifiedBy information.", + "readOnly": true } }, - "description": "The resource model definition for an Azure Resource Manager proxy resource. It will not have tags and a location", "x-ms-azure-resource": true }, + "ResourceModelWithAllowedPropertySet": { + "type": "object", + "description": "The resource model definition containing the full set of allowed properties for a resource. Except properties bag, there cannot be a top level property outside of this set.", + "properties": { + "managedBy": { + "type": "string", + "description": "The fully qualified resource ID of the resource that manages this resource. Indicates if this resource is managed by another Azure resource. If this is present, complete mode deployment will not delete the resource if it is removed from the template since it is managed by another resource.", + "x-ms-mutability": [ + "read", + "create", + "update" + ] + }, + "kind": { + "type": "string", + "description": "Metadata used by portal/tooling/etc to render different UX experiences for resources of the same type; e.g. ApiApps are a kind of Microsoft.Web/sites type. If supported, the resource provider must validate and persist this value.", + "pattern": "^[-\\w\\._,\\(\\)]+$", + "x-ms-mutability": [ + "read", + "create" + ] + }, + "etag": { + "type": "string", + "description": "The etag field is *not* required. If it is provided in the response body, it must also be provided as a header per the normal etag convention. Entity tags are used for comparing two or more entities from the same requested resource. HTTP/1.1 uses entity tags in the etag (section 14.19), If-Match (section 14.24), If-None-Match (section 14.26), and If-Range (section 14.27) header fields. ", + "readOnly": true + }, + "identity": { + "allOf": [ + { + "$ref": "#/definitions/Identity" + } + ] + }, + "sku": { + "allOf": [ + { + "$ref": "#/definitions/Sku" + } + ] + }, + "plan": { + "allOf": [ + { + "$ref": "#/definitions/Plan" + } + ] + } + }, + "allOf": [ + { + "$ref": "#/definitions/TrackedResource" + } + ], + "x-ms-azure-resource": true + }, + "Sku": { + "type": "object", + "description": "The resource model definition representing SKU", + "properties": { + "name": { + "type": "string", + "description": "The name of the SKU. Ex - P3. It is typically a letter+number code" + }, + "tier": { + "$ref": "#/definitions/SkuTier" + }, + "size": { + "type": "string", + "description": "The SKU size. When the name field is the combination of tier and some other value, this would be the standalone code. " + }, + "family": { + "type": "string", + "description": "If the service has different generations of hardware, for the same SKU, then that can be captured here." + }, + "capacity": { + "type": "integer", + "format": "int32", + "description": "If the SKU supports scale out/in then the capacity integer should be included. If scale out/in is not possible for the resource this may be omitted." + } + }, + "required": [ + "name" + ] + }, "SkuTier": { "type": "string", "description": "This field is required to be implemented by the Resource Provider if the service has more than one tier, but is not required on a PUT.", @@ -290,39 +483,38 @@ }, "TrackedResource": { "type": "object", - "description": "The Resource model definition.", + "title": "Tracked Resource", + "description": "The resource model definition for an Azure Resource Manager tracked top level resource which has 'tags' and a 'location'", "properties": { - "id": { - "readOnly": true, - "type": "string", - "description": "Resource Id" - }, - "name": { - "readOnly": true, - "type": "string", - "description": "Resource name" - }, - "type": { - "readOnly": true, - "type": "string", - "description": "Resource type" - }, - "location": { - "type": "string", - "description": "Resource location" - }, "tags": { "type": "object", + "description": "Resource tags.", "additionalProperties": { "type": "string" }, - "description": "Resource tags" + "x-ms-mutability": [ + "read", + "create", + "update" + ] + }, + "location": { + "type": "string", + "description": "The geo-location where the resource lives", + "x-ms-mutability": [ + "read", + "create" + ] } }, "required": [ "location" ], - "x-ms-azure-resource": true + "allOf": [ + { + "$ref": "#/definitions/Resource" + } + ] }, "encryptionProperties": { "type": "object", @@ -430,9 +622,10 @@ "ApiVersionParameter": { "name": "api-version", "in": "query", + "description": "The API version to use for this operation.", "required": true, "type": "string", - "description": "Client Api Version." + "minLength": 1 }, "LocationParameter": { "name": "location", @@ -465,9 +658,10 @@ "SubscriptionIdParameter": { "name": "subscriptionId", "in": "path", + "description": "The ID of the target subscription.", "required": true, "type": "string", - "description": "Subscription credentials which uniquely identify Microsoft Azure subscription. The subscription ID forms part of the URI for every service call." + "minLength": 1 } } -} +} \ No newline at end of file diff --git a/src/Compute/Compute.Test/Compute.Test.csproj b/src/Compute/Compute.Test/Compute.Test.csproj index 67f8a300fd2f..9986056b9127 100644 --- a/src/Compute/Compute.Test/Compute.Test.csproj +++ b/src/Compute/Compute.Test/Compute.Test.csproj @@ -34,5 +34,9 @@ + + + + diff --git a/src/Compute/Compute/Common/ComputeClientBaseCmdlet.cs b/src/Compute/Compute/Common/ComputeClientBaseCmdlet.cs index db55f9f3a2c2..ef1ae61d0a61 100644 --- a/src/Compute/Compute/Common/ComputeClientBaseCmdlet.cs +++ b/src/Compute/Compute/Common/ComputeClientBaseCmdlet.cs @@ -33,6 +33,7 @@ public abstract class ComputeClientBaseCmdlet : AzureRMCmdlet protected DateTime StartTime; private ComputeClient computeClient; + private ComputeClientTrack2 computeClientTrack2; public ComputeClient ComputeClient { @@ -51,6 +52,23 @@ public ComputeClient ComputeClient set { computeClient = value; } } + public ComputeClientTrack2 ComputeClientTrack2 + { + get + { + if (computeClientTrack2 == null) + { + computeClientTrack2 = new ComputeClientTrack2(DefaultProfile.DefaultContext); + } + + this.computeClientTrack2.VerboseLogger = WriteVerboseWithTimestamp; + this.computeClientTrack2.ErrorLogger = WriteErrorWithTimestamp; + return computeClientTrack2; + } + + set { computeClientTrack2 = value; } + } + public override void ExecuteCmdlet() { StartTime = DateTime.Now; diff --git a/src/Compute/Compute/Common/ComputeClientTrack2.cs b/src/Compute/Compute/Common/ComputeClientTrack2.cs new file mode 100644 index 000000000000..4362759c71fd --- /dev/null +++ b/src/Compute/Compute/Common/ComputeClientTrack2.cs @@ -0,0 +1,310 @@ +// ---------------------------------------------------------------------------------- +// +// Copyright Microsoft Corporation +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ---------------------------------------------------------------------------------- + +using Azure.Core; +using Azure.ResourceManager; +using Azure.ResourceManager.Compute; +using Azure.ResourceManager.Resources; +using Microsoft.Azure.Commands.Common.Authentication; +using Microsoft.Azure.Commands.Common.Authentication.Abstractions; +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.Azure.Commands.Compute +{ + /// + /// ComputeClient for the new Azure.ResourceManager.Compute SDK (Track 2) + /// + public class ComputeClientTrack2 + { + private readonly ArmClient _armClient; + private readonly string _subscriptionId; + + /// + /// Gets the ARM client for accessing Azure Resource Manager resources + /// + public ArmClient ArmClient => _armClient; + + /// + /// Gets the subscription ID + /// + public string SubscriptionId => _subscriptionId; + + /// + /// Gets the subscription resource + /// + public SubscriptionResource SubscriptionResource => _armClient.GetSubscriptionResource( + new ResourceIdentifier($"/subscriptions/{_subscriptionId}")); + + /// + /// Logger for verbose output + /// + public Action VerboseLogger { get; set; } + + /// + /// Logger for error output + /// + public Action ErrorLogger { get; set; } + + /// + /// Initializes a new instance of ComputeClientTrack2 using Azure context + /// + /// Azure context containing authentication and subscription information + public ComputeClientTrack2(IAzureContext context) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (context.Subscription == null) + { + throw new ArgumentException("Context must contain a valid subscription", nameof(context)); + } + + _subscriptionId = context.Subscription.Id; + + // Create credential from the context + TokenCredential credential = CreateCredentialFromContext(context); + + // Initialize the ARM client + var armClientOptions = new ArmClientOptions(); + _armClient = new ArmClient(credential, _subscriptionId, armClientOptions); + } + + /// + /// Initializes a new instance of ComputeClientTrack2 with an existing ArmClient + /// + /// The ARM client to use + /// The subscription ID + public ComputeClientTrack2(ArmClient armClient, string subscriptionId) + { + _armClient = armClient ?? throw new ArgumentNullException(nameof(armClient)); + _subscriptionId = subscriptionId ?? throw new ArgumentNullException(nameof(subscriptionId)); + } + + /// + /// Gets a resource group resource + /// + /// The resource group name + /// Cancellation token + /// The resource group resource + public async Task GetResourceGroupAsync( + string resourceGroupName, + CancellationToken cancellationToken = default) + { + LogVerbose($"Getting resource group: {resourceGroupName}"); + + try + { + var response = await SubscriptionResource.GetResourceGroupAsync( + resourceGroupName, + cancellationToken); + return response.Value; + } + catch (Exception ex) + { + LogError($"Failed to get resource group {resourceGroupName}: {ex.Message}"); + throw; + } + } + + /// + /// Gets a resource group resource synchronously + /// + /// The resource group name + /// The resource group resource + public ResourceGroupResource GetResourceGroup(string resourceGroupName) + { + return GetResourceGroupAsync(resourceGroupName).GetAwaiter().GetResult(); + } + + /// + /// Gets a virtual machine resource + /// + /// The resource group name + /// The virtual machine name + /// Cancellation token + /// The virtual machine resource + public async Task GetVirtualMachineAsync( + string resourceGroupName, + string vmName, + CancellationToken cancellationToken = default) + { + LogVerbose($"Getting virtual machine: {vmName} in resource group: {resourceGroupName}"); + + try + { + var resourceGroup = await GetResourceGroupAsync(resourceGroupName, cancellationToken); + var response = await resourceGroup.GetVirtualMachineAsync(vmName, cancellationToken:cancellationToken); + return response.Value; + } + catch (Exception ex) + { + LogError($"Failed to get virtual machine {vmName}: {ex.Message}"); + throw; + } + } + + /// + /// Gets a virtual machine resource synchronously + /// + /// The resource group name + /// The virtual machine name + /// The virtual machine resource + public VirtualMachineResource GetVirtualMachine(string resourceGroupName, string vmName) + { + return GetVirtualMachineAsync(resourceGroupName, vmName).GetAwaiter().GetResult(); + } + + /// + /// Gets an availability set resource + /// + /// The resource group name + /// The availability set name + /// Cancellation token + /// The availability set resource + public async Task GetAvailabilitySetAsync( + string resourceGroupName, + string availabilitySetName, + CancellationToken cancellationToken = default) + { + LogVerbose($"Getting availability set: {availabilitySetName} in resource group: {resourceGroupName}"); + + try + { + var resourceGroup = await GetResourceGroupAsync(resourceGroupName, cancellationToken); + var response = await resourceGroup.GetAvailabilitySetAsync(availabilitySetName, cancellationToken); + return response.Value; + } + catch (Exception ex) + { + LogError($"Failed to get availability set {availabilitySetName}: {ex.Message}"); + throw; + } + } + + /// + /// Gets an availability set resource synchronously + /// + /// The resource group name + /// The availability set name + /// The availability set resource + public AvailabilitySetResource GetAvailabilitySet(string resourceGroupName, string availabilitySetName) + { + return GetAvailabilitySetAsync(resourceGroupName, availabilitySetName).GetAwaiter().GetResult(); + } + + /// + /// Gets a virtual machine scale set resource + /// + /// The resource group name + /// The virtual machine scale set name + /// Cancellation token + /// The virtual machine scale set resource + public async Task GetVirtualMachineScaleSetAsync( + string resourceGroupName, + string vmssName, + CancellationToken cancellationToken = default) + { + LogVerbose($"Getting virtual machine scale set: {vmssName} in resource group: {resourceGroupName}"); + + try + { + var resourceGroup = await GetResourceGroupAsync(resourceGroupName, cancellationToken); + var response = await resourceGroup.GetVirtualMachineScaleSetAsync(vmssName, cancellationToken:cancellationToken); + return response.Value; + } + catch (Exception ex) + { + LogError($"Failed to get virtual machine scale set {vmssName}: {ex.Message}"); + throw; + } + } + + /// + /// Gets a virtual machine scale set resource synchronously + /// + /// The resource group name + /// The virtual machine scale set name + /// The virtual machine scale set resource + public VirtualMachineScaleSetResource GetVirtualMachineScaleSet(string resourceGroupName, string vmssName) + { + return GetVirtualMachineScaleSetAsync(resourceGroupName, vmssName).GetAwaiter().GetResult(); + } + + /// + /// Creates a credential from the Azure context + /// + /// The Azure context + /// A token credential + private TokenCredential CreateCredentialFromContext(IAzureContext context) + { + // Get the token from the existing authenticated context + // This reuses the authentication that PowerShell already established + return new ComputeTokenCredential(context); + } + + /// + /// Logs a verbose message + /// + /// The message to log + private void LogVerbose(string message) + { + VerboseLogger?.Invoke(message); + } + + /// + /// Logs an error message + /// + /// The message to log + private void LogError(string message) + { + ErrorLogger?.Invoke(message); + } + + /// + /// Token credential that uses the Azure PowerShell context for authentication + /// + private class ComputeTokenCredential : TokenCredential + { + private readonly IAzureContext _context; + + public ComputeTokenCredential(IAzureContext context) + { + _context = context; + } + + public override AccessToken GetToken(TokenRequestContext requestContext, CancellationToken cancellationToken) + { + return GetTokenAsync(requestContext, cancellationToken).GetAwaiter().GetResult(); + } + + public override ValueTask GetTokenAsync(TokenRequestContext requestContext, CancellationToken cancellationToken) + { + // Get the token from the Azure PowerShell session + var accessToken = AzureSession.Instance.AuthenticationFactory.Authenticate( + _context.Account, + _context.Environment, + _context.Tenant.Id, + null, + null, + null); + + return new ValueTask(new AccessToken(accessToken.AccessToken, DateTimeOffset.UtcNow.AddHours(1))); + } + } + } +} \ No newline at end of file diff --git a/src/Compute/Compute/Compute.csproj b/src/Compute/Compute/Compute.csproj index 4b404efdd8dd..cc39b41c9fb2 100644 --- a/src/Compute/Compute/Compute.csproj +++ b/src/Compute/Compute/Compute.csproj @@ -13,6 +13,7 @@ + @@ -58,6 +59,10 @@ + + + + diff --git a/src/Compute/Compute/Compute.sln b/src/Compute/Compute/Compute.sln new file mode 100644 index 000000000000..8c94a2d0c6ea --- /dev/null +++ b/src/Compute/Compute/Compute.sln @@ -0,0 +1,24 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.2.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Compute", "Compute.csproj", "{9647CB21-5F2F-6929-9417-DAF5DB0FD617}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9647CB21-5F2F-6929-9417-DAF5DB0FD617}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9647CB21-5F2F-6929-9417-DAF5DB0FD617}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9647CB21-5F2F-6929-9417-DAF5DB0FD617}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9647CB21-5F2F-6929-9417-DAF5DB0FD617}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E9250FC3-8ECB-4057-AC74-18EA469139E2} + EndGlobalSection +EndGlobal diff --git a/src/Compute/Compute/VirtualMachine/Operation/GetAzureVMCommand.cs b/src/Compute/Compute/VirtualMachine/Operation/GetAzureVMCommand.cs index 1a781453a53b..36aa45f7f606 100644 --- a/src/Compute/Compute/VirtualMachine/Operation/GetAzureVMCommand.cs +++ b/src/Compute/Compute/VirtualMachine/Operation/GetAzureVMCommand.cs @@ -26,6 +26,8 @@ using Microsoft.Rest.Azure; using Microsoft.Azure.Management.Authorization.Version2015_07_01; using Microsoft.WindowsAzure.Commands.Common.CustomAttributes; +using ArmCompute = Azure.ResourceManager.Compute.Models; +using Azure.ResourceManager.Compute; namespace Microsoft.Azure.Commands.Compute { @@ -117,6 +119,17 @@ public class GetAzureVMCommand : VirtualMachineBaseCmdlet ValueFromPipeline = true)] public String ResourceId { get; set; } + // In the parameter section, add: + [Parameter( + Mandatory = false, + HelpMessage = "Specifies the API version for Event Grid and Resource Graph scheduled events in YYYY-MM-DD format.")] + [ValidatePattern(@"^\d{4}-\d{2}-\d{2}$")] + public string ScheduledEventsApiVersion { get; set; } + + [Parameter( + Mandatory = false, + HelpMessage = "Specifies whether Scheduled Events should be auto-approved when all instances are down.")] + public bool EnableAllInstancesDown { get; set; } public override void ExecuteCmdlet() { @@ -168,13 +181,19 @@ public override void ExecuteCmdlet() } else { - var result = this.VirtualMachineClient.GetWithHttpMessagesAsync( - this.ResourceGroupName, this.Name).GetAwaiter().GetResult(); + VirtualMachineResource vmResource = this.ComputeClientTrack2.GetVirtualMachine( + this.ResourceGroupName, + this.Name); - var psResult = ComputeAutoMapperProfile.Mapper.Map(result); - if (result.Body != null) + VirtualMachineData data = vmResource.Data; + + //var result = this.VirtualMachineClient.GetWithHttpMessagesAsync( + // this.ResourceGroupName, this.Name).GetAwaiter().GetResult(); + + var psResult = ComputeAutoMapperProfile.Mapper.Map(vmResource.Data); + if (vmResource.Data != null) { - psResult = ComputeAutoMapperProfile.Mapper.Map(result.Body, psResult); + psResult = ComputeAutoMapperProfile.Mapper.Map(vmResource.Data, psResult); } psResult.DisplayHint = this.DisplayHint; WriteObject(psResult); diff --git a/src/Compute/Compute/VirtualMachine/Operation/UpdateAzureVMCommand.cs b/src/Compute/Compute/VirtualMachine/Operation/UpdateAzureVMCommand.cs index 8731fab6d02c..4f56c153dc4c 100644 --- a/src/Compute/Compute/VirtualMachine/Operation/UpdateAzureVMCommand.cs +++ b/src/Compute/Compute/VirtualMachine/Operation/UpdateAzureVMCommand.cs @@ -21,6 +21,8 @@ using System.Collections; using System.Collections.Generic; using System.Management.Automation; +using ArmCompute = Azure.ResourceManager.Compute.Models; +using Azure; namespace Microsoft.Azure.Commands.Compute { @@ -201,6 +203,17 @@ public class UpdateAzureVMCommand : VirtualMachineBaseCmdlet [ValidateNotNullOrEmpty] public bool? AlignRegionalDisksToVMZone { get; set; } + [Parameter( + Mandatory = false, + HelpMessage = "Specifies the API version for Event Grid and Resource Graph scheduled events in YYYY-MM-DD format.")] + [ValidatePattern(@"^\d{4}-\d{2}-\d{2}$")] + public string ScheduledEventsApiVersion { get; set; } + + [Parameter( + Mandatory = false, + HelpMessage = "Specifies whether Scheduled Events should be auto-approved when all instances are down.")] + public bool EnableAllInstancesDown { get; set; } + public override void ExecuteCmdlet() { if (this.IsParameterBound(c => c.UserData)) @@ -444,28 +457,57 @@ public override void ExecuteCmdlet() parameters.StorageProfile.AlignRegionalDisksToVMZone = this.AlignRegionalDisksToVMZone; } + if (this.IsParameterBound(c => c.ScheduledEventsApiVersion) || this.IsParameterBound(c => c.EnableAllInstancesDown)) + { + // Initialize the policy if it doesn't exist + var scheduledEventsPolicy = new ArmCompute.ScheduledEventsPolicy(); + + // Configure EventGrid and Resource Graph + if (this.IsParameterBound(c => c.ScheduledEventsApiVersion)) + { + scheduledEventsPolicy.ScheduledEventsAdditionalPublishingTargetsEventGridAndResourceGraph = + new ArmCompute.EventGridAndResourceGraph + { + IsEnabled = true, + ScheduledEventsApiVersion = this.ScheduledEventsApiVersion + }; + } + + // Configure AllInstancesDown + if (this.IsParameterBound(c => c.EnableAllInstancesDown)) + { + scheduledEventsPolicy.AllInstancesDown = new ArmCompute.AllInstancesDown + { + AutomaticallyApprove = this.EnableAllInstancesDown + }; + } + } + var vmResource = this.ComputeClientTrack2.GetVirtualMachineAsync( + this.ResourceGroupName, + this.VM.Name).GetAwaiter().GetResult(); + + ArmCompute.VirtualMachinePatch vmPatch = ComputeAutoMapperProfile.Mapper.Map(parameters); + if (NoWait.IsPresent) { - var op = this.VirtualMachineClient.BeginCreateOrUpdateWithHttpMessagesAsync( - this.ResourceGroupName, - this.VM.Name, - parameters, - this.IfMatch, - this.IfNoneMatch).GetAwaiter().GetResult(); - var result = ComputeAutoMapperProfile.Mapper.Map(op); + var updateOperation = vmResource.Update(WaitUntil.Started, vmPatch); + var result = new PSAzureOperationResponse + { + StatusCode = System.Net.HttpStatusCode.Accepted + }; WriteObject(result); } else { - var op = this.VirtualMachineClient.CreateOrUpdateWithHttpMessagesAsync( - this.ResourceGroupName, - this.VM.Name, - parameters, - this.IfMatch, - this.IfNoneMatch).GetAwaiter().GetResult(); - var result = ComputeAutoMapperProfile.Mapper.Map(op); + var updateOperation = vmResource.Update(WaitUntil.Completed, vmPatch); + var result = new PSAzureOperationResponse + { + StatusCode = System.Net.HttpStatusCode.OK + }; WriteObject(result); } + + }); } } diff --git a/src/KeyVault/KeyVault.Management.Sdk/KeyVault.Management.Sdk.csproj b/src/KeyVault/KeyVault.Management.Sdk/KeyVault.Management.Sdk.csproj index ccfbfaf1ae13..2fbc9ba3168f 100644 --- a/src/KeyVault/KeyVault.Management.Sdk/KeyVault.Management.Sdk.csproj +++ b/src/KeyVault/KeyVault.Management.Sdk/KeyVault.Management.Sdk.csproj @@ -15,4 +15,8 @@ + + + + \ No newline at end of file diff --git a/src/KeyVault/KeyVault/KeyVault.csproj b/src/KeyVault/KeyVault/KeyVault.csproj index dd2fa52e82f1..b4fb488aceca 100644 --- a/src/KeyVault/KeyVault/KeyVault.csproj +++ b/src/KeyVault/KeyVault/KeyVault.csproj @@ -44,6 +44,10 @@ True + + + + diff --git a/src/ManagedServiceIdentity/ManagedServiceIdentity/ManagedServiceIdentity.csproj b/src/ManagedServiceIdentity/ManagedServiceIdentity/ManagedServiceIdentity.csproj index be747920ec53..a7f9ae124814 100644 --- a/src/ManagedServiceIdentity/ManagedServiceIdentity/ManagedServiceIdentity.csproj +++ b/src/ManagedServiceIdentity/ManagedServiceIdentity/ManagedServiceIdentity.csproj @@ -22,6 +22,9 @@ + + + diff --git a/src/Network/Network.Management.Sdk/Network.Management.Sdk.csproj b/src/Network/Network.Management.Sdk/Network.Management.Sdk.csproj index c10767bde623..f2a56f23b232 100644 --- a/src/Network/Network.Management.Sdk/Network.Management.Sdk.csproj +++ b/src/Network/Network.Management.Sdk/Network.Management.Sdk.csproj @@ -10,4 +10,7 @@ $(NoWarn);CS0108;CS1573 + + + diff --git a/src/Network/Network/Network.csproj b/src/Network/Network/Network.csproj index db72df064083..ab1a3fb057bb 100644 --- a/src/Network/Network/Network.csproj +++ b/src/Network/Network/Network.csproj @@ -44,6 +44,10 @@ + + + + diff --git a/tools/TestFx/TestFx.csproj b/tools/TestFx/TestFx.csproj index 906a9a1a7331..81108e5a5371 100644 --- a/tools/TestFx/TestFx.csproj +++ b/tools/TestFx/TestFx.csproj @@ -37,4 +37,8 @@ + + + + From 4dbd87cfb29306174ae6e98ef8a4b0f2d1419ee7 Mon Sep 17 00:00:00 2001 From: Haider Agha Date: Fri, 12 Dec 2025 15:26:51 -0500 Subject: [PATCH 2/2] Add Track2 PS model classes and mapping for Azure VMs Introduce new PowerShell model classes under Track2 for Azure Compute resources, including VMs, profiles, diagnostics, and instance views. Add AutoMapper configuration to map Track2 PSVirtualMachine to legacy Track1 PSVirtualMachine, handling property transformations and nested profiles. Update GetAzureVMCommand to use the new mapping for compatibility. Changes are additive and maintain backward compatibility with existing Track1 code. --- .../Common/ComputeAutoMapperProfile.cs | 106 +++++++++++++ .../Compute/Models/PSVirtualMachine.cs | 1 + .../Track2/PSAdditionalPropertiesTrack2.cs | 110 +++++++++++++ .../Track2/PSDiagnosticsProfileTrack2.cs | 12 ++ .../Models/Track2/PSHardwareProfileTrack2.cs | 15 ++ .../Models/Track2/PSNetworkProfileTrack2.cs | 122 +++++++++++++++ .../Models/Track2/PSOSProfileTrack2.cs | 99 ++++++++++++ .../Models/Track2/PSSecurityProfileTrack2.cs | 57 +++++++ .../Models/Track2/PSStorageProfileTrack2.cs | 82 ++++++++++ .../Track2/PSVirtualMachineExtensionTrack2.cs | 27 ++++ .../PSVirtualMachineInstanceViewTrack2.cs | 146 ++++++++++++++++++ .../Models/Track2/PSVirtualMachineTrack2.cs | 107 +++++++++++++ .../Operation/GetAzureVMCommand.cs | 13 +- 13 files changed, 890 insertions(+), 7 deletions(-) create mode 100644 src/Compute/Compute/Models/Track2/PSAdditionalPropertiesTrack2.cs create mode 100644 src/Compute/Compute/Models/Track2/PSDiagnosticsProfileTrack2.cs create mode 100644 src/Compute/Compute/Models/Track2/PSHardwareProfileTrack2.cs create mode 100644 src/Compute/Compute/Models/Track2/PSNetworkProfileTrack2.cs create mode 100644 src/Compute/Compute/Models/Track2/PSOSProfileTrack2.cs create mode 100644 src/Compute/Compute/Models/Track2/PSSecurityProfileTrack2.cs create mode 100644 src/Compute/Compute/Models/Track2/PSStorageProfileTrack2.cs create mode 100644 src/Compute/Compute/Models/Track2/PSVirtualMachineExtensionTrack2.cs create mode 100644 src/Compute/Compute/Models/Track2/PSVirtualMachineInstanceViewTrack2.cs create mode 100644 src/Compute/Compute/Models/Track2/PSVirtualMachineTrack2.cs diff --git a/src/Compute/Compute/Common/ComputeAutoMapperProfile.cs b/src/Compute/Compute/Common/ComputeAutoMapperProfile.cs index dc0bd1568126..d842684c9d86 100644 --- a/src/Compute/Compute/Common/ComputeAutoMapperProfile.cs +++ b/src/Compute/Compute/Common/ComputeAutoMapperProfile.cs @@ -18,8 +18,15 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Linq; using FROM = Microsoft.Azure.Management.Compute.Models; using TO = Microsoft.Azure.Commands.Compute.Models; +using FROMTrack2 = Azure.ResourceManager.Compute.Models; +using Azure.ResourceManager.Models; +using Azure.ResourceManager.Compute; +using Azure.ResourceManager.Resources.Models; +using Track2Models = Microsoft.Azure.Commands.Compute.Models.Track2; +using AutomationModels = Microsoft.Azure.Commands.Compute.Automation.Models; namespace Microsoft.Azure.Commands.Compute { @@ -77,6 +84,105 @@ private static void Initialize() var config = new MapperConfiguration(cfg => { cfg.AddProfile(); + // Track2 PSModels => Track1 PSModels + // PSVirtualMachineTrack2 => PSVirtualMachine + cfg.CreateMap() + // Direct property mappings + .ForMember(d => d.ResourceGroupName, opt => opt.MapFrom(s => s.ResourceGroupName)) + .ForMember(d => d.Id, opt => opt.MapFrom(s => s.Id)) + .ForMember(d => d.VmId, opt => opt.MapFrom(s => s.VmId)) + .ForMember(d => d.Name, opt => opt.MapFrom(s => s.Name)) + .ForMember(d => d.Type, opt => opt.MapFrom(s => s.ResourceType)) + .ForMember(d => d.Location, opt => opt.MapFrom(s => s.Location)) + .ForMember(d => d.Tags, opt => opt.MapFrom(s => s.Tags)) + .ForMember(d => d.Zones, opt => opt.MapFrom(s => s.Zones)) + // Convert flattened string IDs to SubResource objects + .ForMember(d => d.AvailabilitySetReference, opt => opt.MapFrom(s => + !string.IsNullOrEmpty(s.AvailabilitySetId) ? new FROM.SubResource(s.AvailabilitySetId) : null)) + .ForMember(d => d.VirtualMachineScaleSet, opt => opt.MapFrom(s => + !string.IsNullOrEmpty(s.VirtualMachineScaleSetId) ? new FROM.SubResource(s.VirtualMachineScaleSetId) : null)) + .ForMember(d => d.ProximityPlacementGroup, opt => opt.MapFrom(s => + !string.IsNullOrEmpty(s.ProximityPlacementGroupId) ? new FROM.SubResource(s.ProximityPlacementGroupId) : null)) + .ForMember(d => d.Host, opt => opt.MapFrom(s => + !string.IsNullOrEmpty(s.HostId) ? new FROM.SubResource(s.HostId) : null)) + .ForMember(d => d.HostGroup, opt => opt.MapFrom(s => + !string.IsNullOrEmpty(s.HostGroupId) ? new FROM.SubResource(s.HostGroupId) : null)) + // Convert BootDiagnostics to DiagnosticsProfile wrapper + .ForMember(d => d.DiagnosticsProfile, opt => opt.MapFrom(s => + s.BootDiagnostics != null ? new FROM.DiagnosticsProfile + { + BootDiagnostics = new FROM.BootDiagnostics + { + Enabled = s.BootDiagnostics.Enabled, + StorageUri = s.BootDiagnostics.StorageUri + } + } : null)) + // Convert BillingMaxPrice to BillingProfile wrapper + .ForMember(d => d.BillingProfile, opt => opt.MapFrom(s => + s.BillingMaxPrice.HasValue ? new FROM.BillingProfile { MaxPrice = s.BillingMaxPrice.Value } : null)) + // Convert GalleryApplications list to ApplicationProfile wrapper + .ForMember(d => d.ApplicationProfile, opt => opt.MapFrom(s => + s.GalleryApplications != null && s.GalleryApplications.Count > 0 + ? new AutomationModels.PSApplicationProfile + { + GalleryApplications = s.GalleryApplications.Select(ga => new AutomationModels.PSVMGalleryApplication + { + PackageReferenceId = ga.PackageReferenceId, + ConfigurationReference = ga.ConfigurationReference, + Tags = ga.Tags, + Order = ga.Order, + TreatFailureAsDeploymentFailure = ga.TreatFailureAsDeploymentFailure, + EnableAutomaticUpgrade = ga.EnableAutomaticUpgrade + }).ToList() + } + : null)) + // Convert CapacityReservationGroupId to CapacityReservationProfile + .ForMember(d => d.CapacityReservation, opt => opt.MapFrom(s => + !string.IsNullOrEmpty(s.CapacityReservationGroupId) + ? new FROM.CapacityReservationProfile + { + CapacityReservationGroup = new FROM.SubResource(s.CapacityReservationGroupId) + } + : null)) + // Map profiles - AutoMapper will handle nested conversions if we set them up + .ForMember(d => d.HardwareProfile, opt => opt.MapFrom(s => s.HardwareProfile)) + .ForMember(d => d.StorageProfile, opt => opt.MapFrom(s => s.StorageProfile)) + .ForMember(d => d.NetworkProfile, opt => opt.MapFrom(s => s.NetworkProfile)) + .ForMember(d => d.OSProfile, opt => opt.MapFrom(s => s.OSProfile)) + .ForMember(d => d.SecurityProfile, opt => opt.MapFrom(s => s.SecurityProfile)) + .ForMember(d => d.AdditionalCapabilities, opt => opt.MapFrom(s => s.AdditionalCapabilities)) + // Map extensions (Resources -> Extensions) + .ForMember(d => d.Extensions, opt => opt.MapFrom(s => s.Resources)) + // Map instance view and extract top-level properties + .ForMember(d => d.InstanceView, opt => opt.MapFrom(s => s.InstanceView)) + .ForMember(d => d.OsName, opt => opt.MapFrom(s => s.InstanceView != null ? s.InstanceView.OsName : null)) + .ForMember(d => d.OsVersion, opt => opt.MapFrom(s => s.InstanceView != null ? s.InstanceView.OsVersion : null)) + .ForMember(d => d.HyperVGeneration, opt => opt.MapFrom(s => s.InstanceView != null ? s.InstanceView.HyperVGeneration : null)) + // Map other properties + .ForMember(d => d.Plan, opt => opt.MapFrom(s => s.Plan)) + .ForMember(d => d.Identity, opt => opt.MapFrom(s => s.Identity)) + .ForMember(d => d.ExtendedLocation, opt => opt.MapFrom(s => s.ExtendedLocation)) + .ForMember(d => d.LicenseType, opt => opt.MapFrom(s => s.LicenseType)) + .ForMember(d => d.ProvisioningState, opt => opt.MapFrom(s => s.ProvisioningState)) + .ForMember(d => d.Priority, opt => opt.MapFrom(s => s.Priority)) + .ForMember(d => d.EvictionPolicy, opt => opt.MapFrom(s => s.EvictionPolicy)) + .ForMember(d => d.UserData, opt => opt.MapFrom(s => s.UserData)) + .ForMember(d => d.PlatformFaultDomain, opt => opt.MapFrom(s => s.PlatformFaultDomain)) + .ForMember(d => d.TimeCreated, opt => opt.MapFrom(s => s.TimeCreated)) + .ForMember(d => d.Etag, opt => opt.MapFrom(s => s.ETag)) + .ForMember(d => d.Placement, opt => opt.MapFrom(s => s.Placement)) + // Ignore properties not in Track2 or are response-only + .ForMember(d => d.StatusCode, opt => opt.Ignore()) + .ForMember(d => d.RequestId, opt => opt.Ignore()) + .ForMember(d => d.FullyQualifiedDomainName, opt => opt.Ignore()) + .ForMember(d => d.DisplayHint, opt => opt.Ignore()) + .ForMember(d => d.AddProxyAgentExtension, opt => opt.Ignore()); + + // TODO: Add mappings for nested profile types if AutoMapper doesn't handle them automatically + // cfg.CreateMap(); + // cfg.CreateMap(); + // etc. + // => PSComputeLongrunningOperation cfg.CreateMap() .ForMember(c => c.OperationId, o => o.MapFrom(r => ComputeClientBaseCmdlet.GetOperationIdFromUrlString(r.Request.RequestUri.ToString()))) diff --git a/src/Compute/Compute/Models/PSVirtualMachine.cs b/src/Compute/Compute/Models/PSVirtualMachine.cs index c6b2a7b69fce..8b2eb0efebd6 100644 --- a/src/Compute/Compute/Models/PSVirtualMachine.cs +++ b/src/Compute/Compute/Models/PSVirtualMachine.cs @@ -24,6 +24,7 @@ using System.Text.RegularExpressions; using Microsoft.Azure.Commands.Compute.Automation.Models; using System; +using Azure.ResourceManager.Compute; namespace Microsoft.Azure.Commands.Compute.Models { diff --git a/src/Compute/Compute/Models/Track2/PSAdditionalPropertiesTrack2.cs b/src/Compute/Compute/Models/Track2/PSAdditionalPropertiesTrack2.cs new file mode 100644 index 000000000000..c5658d57cced --- /dev/null +++ b/src/Compute/Compute/Models/Track2/PSAdditionalPropertiesTrack2.cs @@ -0,0 +1,110 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Collections.Generic; + +namespace Microsoft.Azure.Commands.Compute.Models.Track2 +{ + // Plan information for marketplace images + public class PSComputePlan + { + public string Name { get; set; } + public string Publisher { get; set; } + public string Product { get; set; } + public string PromotionCode { get; set; } + } + + // Managed Service Identity + public class PSManagedServiceIdentity + { + public string Type { get; set; } + public string PrincipalId { get; set; } + public string TenantId { get; set; } + public IDictionary UserAssignedIdentities { get; set; } + } + + public class PSUserAssignedIdentity + { + public string PrincipalId { get; set; } + public string ClientId { get; set; } + } + + // Extended Location + public class PSExtendedLocation + { + public string Name { get; set; } + public string Type { get; set; } + } + + // Additional Capabilities + public class PSAdditionalCapabilities + { + public bool? UltraSSDEnabled { get; set; } + public bool? HibernationEnabled { get; set; } + } + + // Scheduled Events Policy + public class PSScheduledEventsPolicy + { + public PSUserInitiatedReboot UserInitiatedReboot { get; set; } + public PSUserInitiatedRedeploy UserInitiatedRedeploy { get; set; } + public PSScheduledEventsAdditionalPublishingTargets ScheduledEventsAdditionalPublishingTargets { get; set; } + } + + public class PSUserInitiatedReboot + { + public bool? AutomaticallyApprove { get; set; } + } + + public class PSUserInitiatedRedeploy + { + public bool? AutomaticallyApprove { get; set; } + } + + public class PSScheduledEventsAdditionalPublishingTargets + { + public PSEventGridAndResourceGraph EventGridAndResourceGraph { get; set; } + } + + public class PSEventGridAndResourceGraph + { + public bool? Enable { get; set; } + } + + // Scheduled Events Profile + public class PSComputeScheduledEventsProfile + { + public PSTerminateNotificationProfile TerminateNotificationProfile { get; set; } + public PSOSImageNotificationProfile OSImageNotificationProfile { get; set; } + } + + public class PSTerminateNotificationProfile + { + public bool? Enable { get; set; } + public string NotBeforeTimeout { get; set; } + } + + public class PSOSImageNotificationProfile + { + public bool? Enable { get; set; } + public string NotBeforeTimeout { get; set; } + } + + // VM Placement + public class PSVirtualMachinePlacement + { + public int? PartitionCount { get; set; } + public IList HostIds { get; set; } + } + + // Gallery Application + public class PSVirtualMachineGalleryApplication + { + public string PackageReferenceId { get; set; } + public string ConfigurationReference { get; set; } + public string Tags { get; set; } + public int? Order { get; set; } + public bool? TreatFailureAsDeploymentFailure { get; set; } + public bool? EnableAutomaticUpgrade { get; set; } + } +} \ No newline at end of file diff --git a/src/Compute/Compute/Models/Track2/PSDiagnosticsProfileTrack2.cs b/src/Compute/Compute/Models/Track2/PSDiagnosticsProfileTrack2.cs new file mode 100644 index 000000000000..afb6c34fe19f --- /dev/null +++ b/src/Compute/Compute/Models/Track2/PSDiagnosticsProfileTrack2.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Azure.Commands.Compute.Models.Track2 +{ + // Boot Diagnostics - exposed directly in VirtualMachineData + public class PSBootDiagnostics + { + public bool? Enabled { get; set; } + public string StorageUri { get; set; } + } +} \ No newline at end of file diff --git a/src/Compute/Compute/Models/Track2/PSHardwareProfileTrack2.cs b/src/Compute/Compute/Models/Track2/PSHardwareProfileTrack2.cs new file mode 100644 index 000000000000..d880899b34dc --- /dev/null +++ b/src/Compute/Compute/Models/Track2/PSHardwareProfileTrack2.cs @@ -0,0 +1,15 @@ +// PSHardwareProfileTrack2.cs +namespace Microsoft.Azure.Commands.Compute.Models.Track2 +{ + public class PSHardwareProfile + { + public string VmSize { get; set; } + public PSVMSizeProperties VmSizeProperties { get; set; } + } + + public class PSVMSizeProperties + { + public int? VCPUsAvailable { get; set; } + public int? VCPUsPerCore { get; set; } + } +} \ No newline at end of file diff --git a/src/Compute/Compute/Models/Track2/PSNetworkProfileTrack2.cs b/src/Compute/Compute/Models/Track2/PSNetworkProfileTrack2.cs new file mode 100644 index 000000000000..b5f424a0caf1 --- /dev/null +++ b/src/Compute/Compute/Models/Track2/PSNetworkProfileTrack2.cs @@ -0,0 +1,122 @@ +// PSNetworkProfileTrack2.cs +using System.Collections.Generic; + +namespace Microsoft.Azure.Commands.Compute.Models.Track2 +{ + public class PSNetworkProfile + { + public IList NetworkInterfaces { get; set; } + public PSNetworkApiVersion NetworkApiVersion { get; set; } + public PSNetworkInterfaceConfiguration NetworkInterfaceConfigurations { get; set; } + } + + public class PSNetworkInterfaceReference + { + public string Id { get; set; } + public bool? Primary { get; set; } + public string DeleteOption { get; set; } + } + + public class PSNetworkApiVersion + { + public string Version { get; set; } + } + + public class PSNetworkInterfaceConfiguration + { + public string Name { get; set; } + public bool? Primary { get; set; } + public bool? EnableAcceleratedNetworking { get; set; } + public bool? DisableTcpStateTracking { get; set; } + public bool? EnableFpga { get; set; } + public bool? EnableIPForwarding { get; set; } + public PSNetworkSecurityGroup NetworkSecurityGroup { get; set; } + public PSDnsSettings DnsSettings { get; set; } + public IList IpConfigurations { get; set; } + public string DeleteOption { get; set; } + public PSNetworkInterfaceAuxiliaryMode AuxiliaryMode { get; set; } + public PSNetworkInterfaceAuxiliarySku AuxiliarySku { get; set; } + } + + public class PSNetworkSecurityGroup + { + public string Id { get; set; } + } + + public class PSDnsSettings + { + public IList DnsServers { get; set; } + } + + public class PSIPConfiguration + { + public string Name { get; set; } + public PSSubnet Subnet { get; set; } + public bool? Primary { get; set; } + public PSPublicIPAddressConfiguration PublicIPAddressConfiguration { get; set; } + public string PrivateIPAddressVersion { get; set; } + public IList ApplicationGatewayBackendAddressPools { get; set; } + public IList ApplicationSecurityGroups { get; set; } + public IList LoadBalancerBackendAddressPools { get; set; } + } + + public class PSSubnet + { + public string Id { get; set; } + } + + public class PSPublicIPAddressConfiguration + { + public string Name { get; set; } + public PSPublicIPAddressSku Sku { get; set; } + public int? IdleTimeoutInMinutes { get; set; } + public string DeleteOption { get; set; } + public PSDnsSettings DnsSettings { get; set; } + public IList IpTags { get; set; } + public string PublicIPAddressVersion { get; set; } + public string PublicIPAllocationMethod { get; set; } + public PSPublicIPAddressPrefix PublicIPPrefix { get; set; } + } + + public class PSPublicIPAddressSku + { + public string Name { get; set; } + public string Tier { get; set; } + } + + public class PSIPTag + { + public string IpTagType { get; set; } + public string Tag { get; set; } + } + + public class PSPublicIPAddressPrefix + { + public string Id { get; set; } + } + + public class PSApplicationGatewayBackendAddressPool + { + public string Id { get; set; } + } + + public class PSApplicationSecurityGroup + { + public string Id { get; set; } + } + + public class PSBackendAddressPool + { + public string Id { get; set; } + } + + public class PSNetworkInterfaceAuxiliaryMode + { + public string Mode { get; set; } + } + + public class PSNetworkInterfaceAuxiliarySku + { + public string Sku { get; set; } + } +} \ No newline at end of file diff --git a/src/Compute/Compute/Models/Track2/PSOSProfileTrack2.cs b/src/Compute/Compute/Models/Track2/PSOSProfileTrack2.cs new file mode 100644 index 000000000000..4d9937ff778b --- /dev/null +++ b/src/Compute/Compute/Models/Track2/PSOSProfileTrack2.cs @@ -0,0 +1,99 @@ +// PSOSProfileTrack2.cs +using System.Collections.Generic; + +namespace Microsoft.Azure.Commands.Compute.Models.Track2 +{ + public class PSOSProfile + { + public string ComputerName { get; set; } + public string AdminUsername { get; set; } + public string AdminPassword { get; set; } + public string CustomData { get; set; } + public PSWindowsConfiguration WindowsConfiguration { get; set; } + public PSLinuxConfiguration LinuxConfiguration { get; set; } + public IList Secrets { get; set; } + public bool? AllowExtensionOperations { get; set; } + public bool? RequireGuestProvisionSignal { get; set; } + } + + public class PSWindowsConfiguration + { + public bool? ProvisionVMAgent { get; set; } + public bool? EnableAutomaticUpdates { get; set; } + public string TimeZone { get; set; } + public IList AdditionalUnattendContent { get; set; } + public PSPatchSettings PatchSettings { get; set; } + public PSWinRMConfiguration WinRM { get; set; } + public bool? EnableVMAgentPlatformUpdates { get; set; } + } + + public class PSLinuxConfiguration + { + public bool? DisablePasswordAuthentication { get; set; } + public PSSshConfiguration Ssh { get; set; } + public bool? ProvisionVMAgent { get; set; } + public PSPatchSettings PatchSettings { get; set; } + public bool? EnableVMAgentPlatformUpdates { get; set; } + } + + public class PSAdditionalUnattendContent + { + public string PassName { get; set; } + public string ComponentName { get; set; } + public string SettingName { get; set; } + public string Content { get; set; } + } + + public class PSPatchSettings + { + public string PatchMode { get; set; } + public bool? EnableHotpatching { get; set; } + public string AssessmentMode { get; set; } + public PSWindowsVMGuestPatchAutomaticByPlatformSettings AutomaticByPlatformSettings { get; set; } + } + + public class PSWindowsVMGuestPatchAutomaticByPlatformSettings + { + public string RebootSetting { get; set; } + public bool? BypassPlatformSafetyChecksOnUserSchedule { get; set; } + } + + public class PSWinRMConfiguration + { + public IList Listeners { get; set; } + } + + public class PSWinRMListener + { + public string Protocol { get; set; } + public string CertificateUrl { get; set; } + } + + public class PSSshConfiguration + { + public IList PublicKeys { get; set; } + } + + public class PSSshPublicKey + { + public string Path { get; set; } + public string KeyData { get; set; } + } + + public class PSVaultSecretGroup + { + public PSKeyVaultReference SourceVault { get; set; } + public IList VaultCertificates { get; set; } + } + + public class PSKeyVaultReference + { + public string Id { get; set; } + } + + public class PSVaultCertificate + { + public string CertificateUrl { get; set; } + public string CertificateStore { get; set; } + } +} \ No newline at end of file diff --git a/src/Compute/Compute/Models/Track2/PSSecurityProfileTrack2.cs b/src/Compute/Compute/Models/Track2/PSSecurityProfileTrack2.cs new file mode 100644 index 000000000000..ec9f18323142 --- /dev/null +++ b/src/Compute/Compute/Models/Track2/PSSecurityProfileTrack2.cs @@ -0,0 +1,57 @@ +// PSSecurityProfile.cs +using System.Collections.Generic; + +namespace Microsoft.Azure.Commands.Compute.Models.Track2 +{ + public class PSSecurityProfile + { + public PSUefiSettings UefiSettings { get; set; } + public string EncryptionAtHost { get; set; } + public string SecurityType { get; set; } + public PSProxyAgentSettings ProxyAgentSettings { get; set; } + public PSEncryptionIdentity EncryptionIdentity { get; set; } + } + + public class PSUefiSettings + { + public bool? SecureBootEnabled { get; set; } + public bool? VTpmEnabled { get; set; } + } + + public class PSProxyAgentSettings + { + public bool? Enabled { get; set; } + public string Mode { get; set; } + public string KeyIncarnationId { get; set; } + } + + public class PSEncryptionIdentity + { + public string UserAssignedIdentityResourceId { get; set; } + } + + public class PSDiskEncryptionSettings + { + public PSDiskEncryptionSettingsElement DiskEncryptionKey { get; set; } + public PSKeyEncryptionKey KeyEncryptionKey { get; set; } + public bool? Enabled { get; set; } + } + + public class PSDiskEncryptionSettingsElement + { + public PSKeyVaultSecretReference SecretUrl { get; set; } + public PSKeyVaultReference SourceVault { get; set; } + } + + public class PSKeyEncryptionKey + { + public string KeyUrl { get; set; } + public PSKeyVaultReference SourceVault { get; set; } + } + + public class PSKeyVaultSecretReference + { + public string SecretUrl { get; set; } + public PSKeyVaultReference SourceVault { get; set; } + } +} \ No newline at end of file diff --git a/src/Compute/Compute/Models/Track2/PSStorageProfileTrack2.cs b/src/Compute/Compute/Models/Track2/PSStorageProfileTrack2.cs new file mode 100644 index 000000000000..b38169e374f2 --- /dev/null +++ b/src/Compute/Compute/Models/Track2/PSStorageProfileTrack2.cs @@ -0,0 +1,82 @@ +// PSStorageProfileTrack2.cs +using System.Collections.Generic; + +namespace Microsoft.Azure.Commands.Compute.Models.Track2 +{ + public class PSStorageProfile + { + public PSImageReference ImageReference { get; set; } + public PSOSDisk OsDisk { get; set; } + public IList DataDisks { get; set; } + public PSDiskControllerType DiskControllerType { get; set; } + } + + public class PSImageReference + { + public string Id { get; set; } + public string Publisher { get; set; } + public string Offer { get; set; } + public string Sku { get; set; } + public string Version { get; set; } + public string ExactVersion { get; set; } + public string SharedGalleryImageId { get; set; } + public string CommunityGalleryImageId { get; set; } + } + + public class PSOSDisk + { + public string OsType { get; set; } + public PSVirtualHardDisk EncryptionSettings { get; set; } + public string Name { get; set; } + public PSVirtualHardDisk Vhd { get; set; } + public PSVirtualHardDisk Image { get; set; } + public string Caching { get; set; } + public bool? WriteAcceleratorEnabled { get; set; } + public string DiffDiskSettings { get; set; } + public string CreateOption { get; set; } + public int? DiskSizeGB { get; set; } + public PSManagedDiskParameters ManagedDisk { get; set; } + public bool? DeleteOption { get; set; } + } + + public class PSDataDisk + { + public int Lun { get; set; } + public string Name { get; set; } + public PSVirtualHardDisk Vhd { get; set; } + public PSVirtualHardDisk Image { get; set; } + public string Caching { get; set; } + public bool? WriteAcceleratorEnabled { get; set; } + public string CreateOption { get; set; } + public int? DiskSizeGB { get; set; } + public PSManagedDiskParameters ManagedDisk { get; set; } + public string ToBeDetached { get; set; } + public long? DiskIOPSReadWrite { get; set; } + public long? DiskMBpsReadWrite { get; set; } + public string DetachOption { get; set; } + public string DeleteOption { get; set; } + } + + public class PSVirtualHardDisk + { + public string Uri { get; set; } + } + + public class PSManagedDiskParameters + { + public string Id { get; set; } + public string StorageAccountType { get; set; } + public PSDiskEncryptionSetParameters DiskEncryptionSet { get; set; } + public PSSecurityProfile SecurityProfile { get; set; } + } + + public class PSDiskEncryptionSetParameters + { + public string Id { get; set; } + } + + public class PSDiskControllerType + { + public string Type { get; set; } + } +} \ No newline at end of file diff --git a/src/Compute/Compute/Models/Track2/PSVirtualMachineExtensionTrack2.cs b/src/Compute/Compute/Models/Track2/PSVirtualMachineExtensionTrack2.cs new file mode 100644 index 000000000000..c0c277b5486d --- /dev/null +++ b/src/Compute/Compute/Models/Track2/PSVirtualMachineExtensionTrack2.cs @@ -0,0 +1,27 @@ +// PSVirtualMachineExtensionTrack2.cs +using System.Collections.Generic; + +namespace Microsoft.Azure.Commands.Compute.Models.Track2 +{ + public class PSVirtualMachineExtension + { + public string Id { get; set; } + public string Name { get; set; } + public string Type { get; set; } + public string Location { get; set; } + public IDictionary Tags { get; set; } + + public string ForceUpdateTag { get; set; } + public string Publisher { get; set; } + public string VirtualMachineExtensionType { get; set; } + public string TypeHandlerVersion { get; set; } + public bool? AutoUpgradeMinorVersion { get; set; } + public bool? EnableAutomaticUpgrade { get; set; } + public object Settings { get; set; } + public object ProtectedSettings { get; set; } + public string ProvisioningState { get; set; } + public PSVirtualMachineExtensionInstanceView InstanceView { get; set; } + public bool? SuppressFailures { get; set; } + public PSKeyVaultSecretReference ProtectedSettingsFromKeyVault { get; set; } + } +} \ No newline at end of file diff --git a/src/Compute/Compute/Models/Track2/PSVirtualMachineInstanceViewTrack2.cs b/src/Compute/Compute/Models/Track2/PSVirtualMachineInstanceViewTrack2.cs new file mode 100644 index 000000000000..f1cfe0b2301e --- /dev/null +++ b/src/Compute/Compute/Models/Track2/PSVirtualMachineInstanceViewTrack2.cs @@ -0,0 +1,146 @@ +// PSVirtualMachineInstanceViewTrack2.cs +using System; +using System.Collections.Generic; + +namespace Microsoft.Azure.Commands.Compute.Models.Track2 +{ + public class PSVirtualMachineInstanceView + { + public int? PlatformUpdateDomain { get; set; } + public int? PlatformFaultDomain { get; set; } + public string ComputerName { get; set; } + public string OsName { get; set; } + public string OsVersion { get; set; } + public string HyperVGeneration { get; set; } + public string RdpThumbPrint { get; set; } + public PSVirtualMachineAgentInstanceView VmAgent { get; set; } + public PSMaintenanceRedeployStatus MaintenanceRedeployStatus { get; set; } + public IList Disks { get; set; } + public IList Extensions { get; set; } + public PSVirtualMachineHealthStatus VmHealth { get; set; } + public PSBootDiagnosticsInstanceView BootDiagnostics { get; set; } + public string AssignedHost { get; set; } + public IList Statuses { get; set; } + public PSPatchStatus PatchStatus { get; set; } + public bool? IsVMInStandbyPool { get; set; } + } + + public class PSVirtualMachineAgentInstanceView + { + public string VmAgentVersion { get; set; } + public IList ExtensionHandlers { get; set; } + public IList Statuses { get; set; } + } + + public class PSVirtualMachineExtensionHandlerInstanceView + { + public string Type { get; set; } + public string TypeHandlerVersion { get; set; } + public PSInstanceViewStatus Status { get; set; } + } + + public class PSInstanceViewStatus + { + public string Code { get; set; } + public string Level { get; set; } + public string DisplayStatus { get; set; } + public string Message { get; set; } + public DateTimeOffset? Time { get; set; } + } + + public class PSMaintenanceRedeployStatus + { + public bool? IsCustomerInitiatedMaintenanceAllowed { get; set; } + public DateTimeOffset? PreMaintenanceWindowStartTime { get; set; } + public DateTimeOffset? PreMaintenanceWindowEndTime { get; set; } + public DateTimeOffset? MaintenanceWindowStartTime { get; set; } + public DateTimeOffset? MaintenanceWindowEndTime { get; set; } + public string LastOperationResultCode { get; set; } + public string LastOperationMessage { get; set; } + } + + public class PSDiskInstanceView + { + public string Name { get; set; } + public IList EncryptionSettings { get; set; } + public IList Statuses { get; set; } + } + + public class PSVirtualMachineExtensionInstanceView + { + public string Name { get; set; } + public string Type { get; set; } + public string TypeHandlerVersion { get; set; } + public IList Substatuses { get; set; } + public IList Statuses { get; set; } + } + + public class PSVirtualMachineHealthStatus + { + public PSInstanceViewStatus Status { get; set; } + } + + public class PSBootDiagnosticsInstanceView + { + public string ConsoleScreenshotBlobUri { get; set; } + public string SerialConsoleLogBlobUri { get; set; } + public PSInstanceViewStatus Status { get; set; } + } + + public class PSPatchStatus + { + public PSAvailablePatchSummary AvailablePatchSummary { get; set; } + public PSLastPatchInstallationSummary LastPatchInstallationSummary { get; set; } + public IList ConfigurationStatuses { get; set; } + } + + public class PSAvailablePatchSummary + { + public string Status { get; set; } + public string AssessmentActivityId { get; set; } + public bool? RebootPending { get; set; } + public int? CriticalAndSecurityPatchCount { get; set; } + public int? OtherPatchCount { get; set; } + public DateTimeOffset? StartTime { get; set; } + public DateTimeOffset? LastModifiedTime { get; set; } + public PSApiError Error { get; set; } + } + + public class PSLastPatchInstallationSummary + { + public string Status { get; set; } + public string InstallationActivityId { get; set; } + public bool? MaintenanceWindowExceeded { get; set; } + public bool? RebootStatus { get; set; } + public int? NotSelectedPatchCount { get; set; } + public int? ExcludedPatchCount { get; set; } + public int? PendingPatchCount { get; set; } + public int? InstalledPatchCount { get; set; } + public int? FailedPatchCount { get; set; } + public DateTimeOffset? StartTime { get; set; } + public DateTimeOffset? LastModifiedTime { get; set; } + public PSApiError Error { get; set; } + } + + public class PSApiError + { + public IList Details { get; set; } + public PSInnerError Innererror { get; set; } + public string Code { get; set; } + public string Target { get; set; } + public string Message { get; set; } + } + + public class PSApiErrorBase + { + public string Code { get; set; } + public string Target { get; set; } + public string Message { get; set; } + } + + public class PSInnerError + { + public string Exceptiontype { get; set; } + public string Errordetail { get; set; } + } +} \ No newline at end of file diff --git a/src/Compute/Compute/Models/Track2/PSVirtualMachineTrack2.cs b/src/Compute/Compute/Models/Track2/PSVirtualMachineTrack2.cs new file mode 100644 index 000000000000..c08f63737596 --- /dev/null +++ b/src/Compute/Compute/Models/Track2/PSVirtualMachineTrack2.cs @@ -0,0 +1,107 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Azure.Core; +using Azure.ResourceManager.Compute.Models; +using Azure.ResourceManager.Models; +using System; +using System.Collections.Generic; +using System.Text.RegularExpressions; + +namespace Microsoft.Azure.Commands.Compute.Models.Track2 +{ + /// + /// Track2 SDK-specific writable VM model for internal mapping from VirtualMachineData + /// + public class PSVirtualMachine + { + // ARM Resource Properties + public string ResourceGroupName + { + get + { + if (string.IsNullOrEmpty(Id)) return null; + Regex r = new Regex(@"(.*?)/resourcegroups/(?\S+)/providers/(.*?)", RegexOptions.IgnoreCase); + Match m = r.Match(Id); + return m.Success ? m.Groups["rgname"].Value : null; + } + } + public string Id { get; set; } + public string Name { get; set; } + public string ResourceType { get; set; } // Maps from ResourceType, not Type + public string Location { get; set; } + public IDictionary Tags { get; set; } + + // VM Properties + public string VmId { get; set; } + public IList Zones { get; set; } + + // Plan + public PSComputePlan Plan { get; set; } + + // Identity + public PSManagedServiceIdentity Identity { get; set; } + + // Extended Location + public PSExtendedLocation ExtendedLocation { get; set; } + + // Profiles + public PSHardwareProfile HardwareProfile { get; set; } + public PSStorageProfile StorageProfile { get; set; } + public PSNetworkProfile NetworkProfile { get; set; } + public PSOSProfile OSProfile { get; set; } + public PSSecurityProfile SecurityProfile { get; set; } + + // Note: DiagnosticsProfile is internal in VirtualMachineData + // Only BootDiagnostics is exposed publicly + public PSBootDiagnostics BootDiagnostics { get; set; } + + // Additional Capabilities + public PSAdditionalCapabilities AdditionalCapabilities { get; set; } + + // Flattened ResourceIdentifiers ( pattern) + public string AvailabilitySetId { get; set; } + public string VirtualMachineScaleSetId { get; set; } + public string ProximityPlacementGroupId { get; set; } + public string HostId { get; set; } + public string HostGroupId { get; set; } + public string CapacityReservationGroupId { get; set; } + + // Scheduling and Events + public PSScheduledEventsPolicy ScheduledEventsPolicy { get; set; } + public PSComputeScheduledEventsProfile ScheduledEventsProfile { get; set; } + + // Spot VM Properties + public string Priority { get; set; } + public string EvictionPolicy { get; set; } + + // Note: BillingProfile is internal in VirtualMachineData + // Only MaxPrice is exposed publicly + public double? BillingMaxPrice { get; set; } + + // Note: ApplicationProfile is internal in VirtualMachineData + // Only GalleryApplications is exposed publicly + public IList GalleryApplications { get; set; } + + // License and User Data + public string LicenseType { get; set; } + public string UserData { get; set; } + + // Placement + public PSVirtualMachinePlacement Placement { get; set; } + public int? PlatformFaultDomain { get; set; } + + // Instance View (read-only) + public PSVirtualMachineInstanceView InstanceView { get; set; } + + // Extensions (Resources in Track2) + public IList Resources { get; set; } + + // Metadata + public string ProvisioningState { get; set; } + public DateTimeOffset? TimeCreated { get; set; } + public string ExtensionsTimeBudget { get; set; } + public string ETag { get; set; } + public string ManagedBy { get; set; } + } +} \ No newline at end of file diff --git a/src/Compute/Compute/VirtualMachine/Operation/GetAzureVMCommand.cs b/src/Compute/Compute/VirtualMachine/Operation/GetAzureVMCommand.cs index 36aa45f7f606..3996d9cc6fa2 100644 --- a/src/Compute/Compute/VirtualMachine/Operation/GetAzureVMCommand.cs +++ b/src/Compute/Compute/VirtualMachine/Operation/GetAzureVMCommand.cs @@ -187,16 +187,13 @@ public override void ExecuteCmdlet() VirtualMachineData data = vmResource.Data; - //var result = this.VirtualMachineClient.GetWithHttpMessagesAsync( - // this.ResourceGroupName, this.Name).GetAwaiter().GetResult(); - - var psResult = ComputeAutoMapperProfile.Mapper.Map(vmResource.Data); if (vmResource.Data != null) { - psResult = ComputeAutoMapperProfile.Mapper.Map(vmResource.Data, psResult); + var psResultTrack2 = ComputeAutoMapperProfile.Mapper.Map(vmResource.Data); + // convert psResultTrack2 to psResult of PSVirtualMachine type + var psResult = ComputeAutoMapperProfile.Mapper.Map(data); + WriteObject(psResult); } - psResult.DisplayHint = this.DisplayHint; - WriteObject(psResult); } } else @@ -208,6 +205,8 @@ public override void ExecuteCmdlet() }); } + + private void ReturnListVMObject(AzureOperationResponse> vmListResult, Func>, CancellationToken, Task>>> listNextFunction) {