From 881741d7721a744621ea4b1a84e9478ab213ac7b Mon Sep 17 00:00:00 2001 From: Gabriel Prestemon Date: Wed, 19 Dec 2018 13:45:15 -0800 Subject: [PATCH 001/141] Use login credentials from new Az module. Remove username/password authentication. Get login credentials from Az module, instead of AddAzureASAccount. This is currently a work in progress. --- .../Commands/AddAzureASAccount.cs | 199 --- .../Commands/Export-AzureAsInstanceLog.cs | 122 +- .../Commands/Restart-AzureAsInstance.cs | 88 +- .../Commands/Synchronize-AzureASInstance.cs | 249 +--- .../Models/ASAzureContext.cs | 51 - .../Models/AsAzureAuthenticationProvider.cs | 170 --- .../Models/AsAzureClientSession.cs | 165 --- .../Models/AsAzureDataplaneClient.cs | 231 +++ .../Models/AsAzureDataplaneCmdletBase.cs | 151 ++ ...{AsAzureAccount.cs => AsAzureEndpoints.cs} | 31 +- .../Models/AsAzureProfile.cs | 65 - .../InMemoryTests/AddAzureASAccountTests.cs | 80 -- .../InMemoryTests/DataPlaneCommandTests.cs | 1260 ++++++++--------- 13 files changed, 1124 insertions(+), 1738 deletions(-) delete mode 100644 src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Commands/AddAzureASAccount.cs delete mode 100644 src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/ASAzureContext.cs delete mode 100644 src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureAuthenticationProvider.cs delete mode 100644 src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureClientSession.cs create mode 100644 src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureDataplaneClient.cs create mode 100644 src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs rename src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/{AsAzureAccount.cs => AsAzureEndpoints.cs} (54%) delete mode 100644 src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureProfile.cs delete mode 100644 src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Test/InMemoryTests/AddAzureASAccountTests.cs diff --git a/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Commands/AddAzureASAccount.cs b/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Commands/AddAzureASAccount.cs deleted file mode 100644 index d5864f70b0dd..000000000000 --- a/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Commands/AddAzureASAccount.cs +++ /dev/null @@ -1,199 +0,0 @@ -// ---------------------------------------------------------------------------------- -// -// 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 Microsoft.Azure.Commands.Common.Authentication; -using Microsoft.Azure.Commands.Common.Authentication.Models; -using System.IO; -using System.Management.Automation; -using System.Reflection; -using System.Security; -using Microsoft.Azure.Commands.AnalysisServices.Dataplane.Properties; -using Microsoft.WindowsAzure.Commands.Utilities.Common; -using Microsoft.Azure.Commands.Common.Authentication.Abstractions; -using Microsoft.WindowsAzure.Commands.Common; -using System; - -namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane -{ - /// - /// Cmdlet to log into an Analysis Services environment - /// - [Cmdlet("Add", ResourceManager.Common.AzureRMConstants.AzurePrefix + "AnalysisServicesAccount", DefaultParameterSetName = "UserParameterSetName", SupportsShouldProcess =true)] - [Alias("Login-AzureAsAccount", "Login-AzAsAccount")] - [OutputType(typeof(AsAzureProfile))] - public class AddAzureASAccountCommand : AzurePSCmdlet - { - private const string UserParameterSet = "UserParameterSetName"; - private const string ServicePrincipalWithPasswordParameterSet = "ServicePrincipalWithPasswordParameterSetName"; - private const string ServicePrincipalWithCertificateParameterSet = "ServicePrincipalWithCertificateParameterSetName"; - - [Parameter(ParameterSetName = UserParameterSet, - Mandatory = false, HelpMessage = "Name of the Azure Analysis Services environment to which to logon to", Position = 0)] - [Parameter(ParameterSetName = ServicePrincipalWithPasswordParameterSet, - Mandatory = true, HelpMessage = "Name of the Azure Analysis Services environment to which to logon to")] - [Parameter(ParameterSetName = ServicePrincipalWithCertificateParameterSet, - Mandatory = true, HelpMessage = "Name of the Azure Analysis Services environment to which to logon to")] - public string RolloutEnvironment { get; set; } - - [Parameter(ParameterSetName = UserParameterSet, - Mandatory = false, HelpMessage = "Login credentials to the Azure Analysis Services environment", Position = 1)] - [Parameter(ParameterSetName = ServicePrincipalWithPasswordParameterSet, - Mandatory = true, HelpMessage = "Login credentials to the Azure Analysis Services environment")] - public PSCredential Credential { get; set; } - - [Parameter(ParameterSetName = ServicePrincipalWithPasswordParameterSet, - Mandatory = true)] - [Parameter(ParameterSetName = ServicePrincipalWithCertificateParameterSet, - Mandatory = true)] - public SwitchParameter ServicePrincipal { get; set; } - - [Parameter(ParameterSetName = ServicePrincipalWithPasswordParameterSet, - Mandatory = true, HelpMessage = "Tenant name or ID")] - [Parameter(ParameterSetName = ServicePrincipalWithCertificateParameterSet, - Mandatory = true, HelpMessage = "Tenant name or ID")] - [ValidateNotNullOrEmpty] - public string TenantId { get; set; } - - [Parameter(ParameterSetName = ServicePrincipalWithCertificateParameterSet, - Mandatory = true, HelpMessage = "The application ID.")] - [ValidateNotNullOrEmpty] - public string ApplicationId { get; set; } - - [Parameter(ParameterSetName = ServicePrincipalWithCertificateParameterSet, - Mandatory = true, HelpMessage = "Certificate Hash (Thumbprint)")] - [ValidateNotNullOrEmpty] - public string CertificateThumbprint { get; set; } - - protected AsAzureEnvironment AsEnvironment; - - protected override IAzureContext DefaultContext - { - get - { - // Nothing to do with Azure Resource Management context - return null; - } - } - - protected override string DataCollectionWarning - { - get - { - return Resources.ARMDataCollectionMessage; - } - } - - protected override void BeginProcessing() - { - this._dataCollectionProfile = new AzurePSDataCollectionProfile(false); - - if (string.IsNullOrEmpty(RolloutEnvironment)) - { - RolloutEnvironment = AsAzureClientSession.GetDefaultEnvironmentName(); - } - - if (AsAzureClientSession.Instance.Profile.Environments.ContainsKey(RolloutEnvironment)) - { - AsEnvironment = (AsAzureEnvironment)AsAzureClientSession.Instance.Profile.Environments[RolloutEnvironment]; - } - else - { - AsEnvironment = AsAzureClientSession.Instance.Profile.CreateEnvironment(RolloutEnvironment); - } - base.BeginProcessing(); - } - - protected override void InitializeQosEvent() - { - // nothing to do here. - } - - protected override void SetupDebuggingTraces() - { - // nothing to do here. - } - - protected override void TearDownDebuggingTraces() - { - // nothing to do here. - } - - protected override void SetupHttpClientPipeline() - { - // nothing to do here. - } - - protected override void TearDownHttpClientPipeline() - { - // nothing to do here. - } - - public override void ExecuteCmdlet() - { - var azureAccount = new AsAzureAccount - { - Type = ServicePrincipal ? AsAzureAccount.AccountType.ServicePrincipal : AsAzureAccount.AccountType.User - }; - - SecureString password = null; - if (Credential != null) - { - azureAccount.Id = Credential.UserName; - password = Credential.Password; - } - - if (ServicePrincipal) - { - azureAccount.Tenant = TenantId; - - if (!string.IsNullOrEmpty(ApplicationId)) - { - azureAccount.Id = ApplicationId; - } - if (!string.IsNullOrEmpty(CertificateThumbprint)) - { - azureAccount.CertificateThumbprint = CertificateThumbprint; - } - } - - if (ShouldProcess(string.Format(Resources.LoginTarget, AsEnvironment.Name), "log in")) - { - var currentProfile = AsAzureClientSession.Instance.Profile; - var currentContext = currentProfile.Context; - - // If there is no current context create one. If there is one already then - // if the current credentials (userid) match the one that is already in context then use it. - // if either the userid that is logging in or the environment to which login is happening is - // different than the one in the context then clear the current context and proceed to login. - // At any given point in time, we should only have one context i.e. one user logged in to one - // environment. - if (currentContext == null || Credential == null || - string.IsNullOrEmpty(currentContext.Account.Id) || - !currentContext.Account.Id.Equals(Credential.UserName) || - !RolloutEnvironment.Equals(currentContext.Environment.Name)) - { - AsAzureClientSession.Instance.SetCurrentContext(azureAccount, AsEnvironment); - } -// TODO: Remove IfDef -#if NETSTANDARD - var asAzureProfile = AsAzureClientSession.Instance.Login(currentProfile.Context, password, WriteWarning); -#else - var asAzureProfile = AsAzureClientSession.Instance.Login(currentProfile.Context, password); -#endif - - WriteObject(asAzureProfile); - } - } - } -} diff --git a/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Commands/Export-AzureAsInstanceLog.cs b/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Commands/Export-AzureAsInstanceLog.cs index 3366cb2385aa..2c9b7ab58391 100644 --- a/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Commands/Export-AzureAsInstanceLog.cs +++ b/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Commands/Export-AzureAsInstanceLog.cs @@ -15,27 +15,21 @@ using System; using System.Globalization; using System.Management.Automation; -using System.Net.Http; -using System.Net.Http.Headers; using Microsoft.Azure.Commands.Common.Authentication; using Microsoft.Azure.Commands.AnalysisServices.Dataplane.Models; using Microsoft.Azure.Commands.AnalysisServices.Dataplane.Properties; using Microsoft.Azure.Commands.Common.Authentication.Abstractions; -using Microsoft.WindowsAzure.Commands.Utilities.Common; -using Newtonsoft.Json.Linq; namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane { /// /// Cmdlet to export an Analysis Services server log to file /// - [Cmdlet("Export", ResourceManager.Common.AzureRMConstants.AzurePrefix + "AnalysisServicesInstanceLog", SupportsShouldProcess=true)] + [Cmdlet("Export", ResourceManager.Common.AzureRMConstants.AzurePrefix + "AnalysisServicesInstanceLog", SupportsShouldProcess = true)] [Alias("Export-AzureAsInstanceLog", "Export-AzAsInstanceLog")] [OutputType(typeof(void))] - public class ExportAzureAnalysisServerLog : AzurePSCmdlet + public class ExportAzureAnalysisServerLog : AsAzureDataplaneCmdletBase { - private string _serverName; - [Parameter(Mandatory = true, HelpMessage = "Name of the Azure Analysis Services which log will be fetched")] [ValidateNotNullOrEmpty] public string Instance { get; set; } @@ -48,20 +42,8 @@ public class ExportAzureAnalysisServerLog : AzurePSCmdlet [ValidateNotNullOrEmpty] public SwitchParameter Force { get; set; } - public IAsAzureHttpClient AsAzureHttpClient { get; private set; } - - public ITokenCacheItemProvider TokenCacheItemProvider { get; private set; } - public ExportAzureAnalysisServerLog() { - AsAzureHttpClient = new AsAzureHttpClient(() => new HttpClient()); - TokenCacheItemProvider = new TokenCacheItemProvider(); - } - - public ExportAzureAnalysisServerLog(IAsAzureHttpClient asAzureHttpClient, ITokenCacheItemProvider tokenCacheItemProvider) - { - AsAzureHttpClient = asAzureHttpClient; - TokenCacheItemProvider = tokenCacheItemProvider; } protected override IAzureContext DefaultContext @@ -84,46 +66,7 @@ protected override string DataCollectionWarning protected override void BeginProcessing() { base.BeginProcessing(); - - if (AsAzureClientSession.Instance.Profile.Environments.Count == 0) - { - throw new PSInvalidOperationException(string.Format(Resources.NotLoggedInMessage, "")); - } - - _serverName = Instance; - Uri uriResult; - - // if the user specifies the FQN of the server, then extract the server name out of that. - // and set the current context - if (Uri.TryCreate(Instance, UriKind.Absolute, out uriResult) && uriResult.Scheme == "asazure") - { - _serverName = uriResult.PathAndQuery.Trim('/'); - if (string.Compare(AsAzureClientSession.Instance.Profile.Context.Environment.Name, uriResult.DnsSafeHost, StringComparison.InvariantCultureIgnoreCase) != 0) - { - AsAzureClientSession.Instance.SetCurrentContext( - new AsAzureAccount(), - AsAzureClientSession.Instance.Profile.CreateEnvironment(uriResult.DnsSafeHost)); - } - } - else - { - var currentContext = AsAzureClientSession.Instance.Profile.Context; - if (currentContext != null - && AsAzureClientSession.AsAzureRolloutEnvironmentMapping.ContainsKey(currentContext.Environment.Name)) - { - throw new PSInvalidOperationException(string.Format(Resources.InvalidServerName, _serverName)); - } - } - - if (AsAzureHttpClient == null) - { - AsAzureHttpClient = new AsAzureHttpClient(() => new HttpClient()); - } - - if (TokenCacheItemProvider == null) - { - TokenCacheItemProvider = new TokenCacheItemProvider(); - } + this.CommonBeginProcessing(Instance); } protected override void InitializeQosEvent() @@ -133,58 +76,23 @@ protected override void InitializeQosEvent() public override void ExecuteCmdlet() { - if (ShouldProcess(Instance, Resources.ExportingLogFromAnalysisServicesServer)) + if (!ShouldProcess(Instance, Resources.ExportingLogFromAnalysisServicesServer)) { - var context = AsAzureClientSession.Instance.Profile.Context; - AsAzureClientSession.Instance.Login(context, null); - - var accessToken = TokenCacheItemProvider.GetTokenFromTokenCache( - AsAzureClientSession.TokenCache, context.Account.UniqueId); - - var logfileBaseUri = new Uri($"{Uri.UriSchemeHttps}{Uri.SchemeDelimiter}{context.Environment.Name}"); - - var resolvedUriBuilder = new UriBuilder(logfileBaseUri) - { - Host = ClusterResolve(logfileBaseUri, accessToken, _serverName) - }; - - var logfileEndpoint = string.Format( - (string) context.Environment.Endpoints[AsAzureEnvironment.AsRolloutEndpoints.LogfileEndpointFormat], - _serverName); - - AsAzureHttpClient.resetHttpClient(); - using (var message = AsAzureHttpClient.CallGetAsync( - resolvedUriBuilder.Uri, - logfileEndpoint, - accessToken).ConfigureAwait(false).GetAwaiter().GetResult()) - { - message.EnsureSuccessStatusCode(); - var actionWarning = string.Format(CultureInfo.CurrentCulture, Resources.ExportingLogOverwriteWarning, OutputPath); - if (AzureSession.Instance.DataStore.FileExists(OutputPath) && !Force.IsPresent && !ShouldContinue(actionWarning, Resources.Confirm)) - { - return; - } - AzureSession.Instance.DataStore.WriteFile(OutputPath, message.Content.ReadAsStringAsync().Result); - } + return; } - } - private string ClusterResolve(Uri clusterUri, string accessToken, string serverName) - { - const string resolveEndpoint = "/webapi/clusterResolve"; - var content = new StringContent($"ServerName={serverName}"); - content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/x-www-form-urlencoded"); - - using (var message = AsAzureHttpClient.CallPostAsync( - clusterUri, - resolveEndpoint, - accessToken, - content).Result) + var logfileEndpoint = string.Format(AsAzureEndpoints.LogfileEndpointPathFormat, ServerName); + + AsAzureDataplaneClient.resetHttpClient(); + using (var message = AsAzureDataplaneClient.CallGetAsync(logfileEndpoint).ConfigureAwait(false).GetAwaiter().GetResult()) { message.EnsureSuccessStatusCode(); - var rawResult = message.Content.ReadAsStringAsync().Result; - var jsonResult = JObject.Parse(rawResult); - return jsonResult["clusterFQDN"].ToString(); + var actionWarning = string.Format(CultureInfo.CurrentCulture, Resources.ExportingLogOverwriteWarning, OutputPath); + if (AzureSession.Instance.DataStore.FileExists(OutputPath) && !Force.IsPresent && !ShouldContinue(actionWarning, Resources.Confirm)) + { + return; + } + AzureSession.Instance.DataStore.WriteFile(OutputPath, message.Content.ReadAsStringAsync().Result); } } } diff --git a/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Commands/Restart-AzureAsInstance.cs b/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Commands/Restart-AzureAsInstance.cs index 42173b9a7df4..3e96751016e7 100644 --- a/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Commands/Restart-AzureAsInstance.cs +++ b/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Commands/Restart-AzureAsInstance.cs @@ -12,12 +12,9 @@ // limitations under the License. // ---------------------------------------------------------------------------------- -using System; using System.Management.Automation; -using System.Net.Http; using Microsoft.Azure.Commands.AnalysisServices.Dataplane.Models; using Microsoft.Azure.Commands.AnalysisServices.Dataplane.Properties; -using Microsoft.WindowsAzure.Commands.Utilities.Common; using Microsoft.Azure.Commands.Common.Authentication.Abstractions; namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane @@ -25,12 +22,11 @@ namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane /// /// Cmdlet to log into an Analysis Services environment /// - [Cmdlet("Restart", ResourceManager.Common.AzureRMConstants.AzurePrefix + "AnalysisServicesInstance", SupportsShouldProcess=true)] + [Cmdlet("Restart", ResourceManager.Common.AzureRMConstants.AzurePrefix + "AnalysisServicesInstance", SupportsShouldProcess = true)] [Alias("Restart-AzureAsInstance", "Restart-AzAsInstance")] [OutputType(typeof(bool))] - public class RestartAzureAnalysisServer : AzurePSCmdlet + public class RestartAzureAnalysisServer : AsAzureDataplaneCmdletBase { - private string _serverName; [Parameter(Mandatory = true, HelpMessage = "Name of the Azure Analysis Services server to restart")] [ValidateNotNullOrEmpty] @@ -39,21 +35,8 @@ public class RestartAzureAnalysisServer : AzurePSCmdlet [Parameter(Mandatory = false)] public SwitchParameter PassThru { get; set; } - public IAsAzureHttpClient AsAzureHttpClient { get; private set; } - - public ITokenCacheItemProvider TokenCacheItemProvider { get; private set; } - public RestartAzureAnalysisServer() { - AsAzureHttpClient = new AsAzureHttpClient(() => new HttpClient()); - TokenCacheItemProvider = new TokenCacheItemProvider(); - - } - - public RestartAzureAnalysisServer(IAsAzureHttpClient asAzureHttpClient, ITokenCacheItemProvider tokenCacheItemProvider) - { - AsAzureHttpClient = asAzureHttpClient; - TokenCacheItemProvider = tokenCacheItemProvider; } protected override IAzureContext DefaultContext @@ -76,46 +59,7 @@ protected override string DataCollectionWarning protected override void BeginProcessing() { base.BeginProcessing(); - - if (AsAzureClientSession.Instance.Profile.Environments.Count == 0) - { - throw new PSInvalidOperationException(string.Format(Resources.NotLoggedInMessage, "")); - } - - _serverName = Instance; - Uri uriResult; - - // if the user specifies the FQN of the server, then extract the server name out of that. - // and set the current context - if (Uri.TryCreate(Instance, UriKind.Absolute, out uriResult) && uriResult.Scheme == "asazure") - { - _serverName = uriResult.PathAndQuery.Trim('/'); - if (string.Compare(AsAzureClientSession.Instance.Profile.Context.Environment.Name, uriResult.DnsSafeHost, StringComparison.InvariantCultureIgnoreCase) != 0) - { - AsAzureClientSession.Instance.SetCurrentContext( - new AsAzureAccount(), - AsAzureClientSession.Instance.Profile.CreateEnvironment(uriResult.DnsSafeHost)); - } - } - else - { - var currentContext = AsAzureClientSession.Instance.Profile.Context; - if (currentContext != null - && AsAzureClientSession.AsAzureRolloutEnvironmentMapping.ContainsKey(currentContext.Environment.Name)) - { - throw new PSInvalidOperationException(string.Format(Resources.InvalidServerName, _serverName)); - } - } - - if (AsAzureHttpClient == null) - { - AsAzureHttpClient = new AsAzureHttpClient(() => new HttpClient()); - } - - if (TokenCacheItemProvider == null) - { - TokenCacheItemProvider = new TokenCacheItemProvider(); - } + this.CommonBeginProcessing(Instance); } protected override void InitializeQosEvent() @@ -125,27 +69,19 @@ protected override void InitializeQosEvent() public override void ExecuteCmdlet() { - if (ShouldProcess(Instance, Resources.RestartingAnalysisServicesServer)) + if (!ShouldProcess(Instance, Resources.RestartingAnalysisServicesServer)) { - var context = AsAzureClientSession.Instance.Profile.Context; - AsAzureClientSession.Instance.Login(context, null); - - var accessToken = TokenCacheItemProvider.GetTokenFromTokenCache(AsAzureClientSession.TokenCache, context.Account.UniqueId); - - var restartBaseUri = new Uri($"{Uri.UriSchemeHttps}{Uri.SchemeDelimiter}{context.Environment.Name}"); + return; + } - var restartEndpoint = string.Format((string)context.Environment.Endpoints[AsAzureEnvironment.AsRolloutEndpoints.RestartEndpointFormat], _serverName); + var restartEndpoint = string.Format(AsAzureEndpoints.RestartEndpointPathFormat, ServerName); - using (var message = AsAzureHttpClient.CallPostAsync( - restartBaseUri, - restartEndpoint, - accessToken).Result) + using (var message = AsAzureDataplaneClient.CallPostAsync(restartEndpoint).Result) + { + message.EnsureSuccessStatusCode(); + if (PassThru.IsPresent) { - message.EnsureSuccessStatusCode(); - if (PassThru.IsPresent) - { - WriteObject(true); - } + WriteObject(true); } } } diff --git a/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Commands/Synchronize-AzureASInstance.cs b/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Commands/Synchronize-AzureASInstance.cs index 3ffc0911a8ba..af2edd725c08 100644 --- a/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Commands/Synchronize-AzureASInstance.cs +++ b/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Commands/Synchronize-AzureASInstance.cs @@ -13,22 +13,17 @@ // ---------------------------------------------------------------------------------- using System; -using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Management.Automation; using System.Net; using System.Net.Http; using System.Net.Http.Headers; -using System.Text; using System.Threading.Tasks; using Microsoft.Azure.Commands.AnalysisServices.Dataplane.Models; using Microsoft.Azure.Commands.AnalysisServices.Dataplane.Properties; using Microsoft.Azure.Commands.Common.Authentication.Abstractions; -using Microsoft.WindowsAzure.Commands.Common; -using Microsoft.WindowsAzure.Commands.Utilities.Common; using Newtonsoft.Json; -using Newtonsoft.Json.Linq; namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane { @@ -38,17 +33,15 @@ namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane [Cmdlet("Sync", ResourceManager.Common.AzureRMConstants.AzurePrefix + "AnalysisServicesInstance", SupportsShouldProcess = true)] [Alias("Sync-AzureAsInstance", "Sync-AzAsInstance")] [OutputType(typeof(ScaleOutServerDatabaseSyncDetails))] - public class SynchronizeAzureAzureAnalysisServer : AzurePSCmdlet + public class SynchronizeAzureAzureAnalysisServer : AsAzureDataplaneCmdletBase { private static TimeSpan DefaultPollingInterval = TimeSpan.FromSeconds(30); public static TimeSpan DefaultRetryIntervalForPolling = TimeSpan.FromSeconds(10); - private static string RootActivityIdHeaderName = "x-ms-root-activity-id"; + private readonly string RootActivityIdHeaderName = "x-ms-root-activity-id"; - private static string CurrentUtcDateHeaderName = "x-ms-current-utc-date"; - - private string serverName; + private readonly string CurrentUtcDateHeaderName = "x-ms-current-utc-date"; private ClusterResolutionResult clusterResolveResult; @@ -77,6 +70,13 @@ public class SynchronizeAzureAzureAnalysisServer : AzurePSCmdlet [Parameter(Mandatory = false)] public SwitchParameter PassThru { get; set; } + public SynchronizeAzureAzureAnalysisServer() + { + this.syncRequestRootActivityId = string.Empty; + this.correlationId = Guid.Empty; + this.syncRequestTimeStamp = string.Empty; + } + protected override IAzureContext DefaultContext { get @@ -86,29 +86,19 @@ protected override IAzureContext DefaultContext } } - public IAsAzureHttpClient AsAzureHttpClient { get; private set; } - - public ITokenCacheItemProvider TokenCacheItemProvider { get; private set; } - - public SynchronizeAzureAzureAnalysisServer() + protected override string DataCollectionWarning { - this.AsAzureHttpClient = new AsAzureHttpClient(() => + get { - HttpClientHandler httpClientHandler = new HttpClientHandler(); - httpClientHandler.AllowAutoRedirect = false; - return new HttpClient(httpClientHandler); - }); - - this.TokenCacheItemProvider = new TokenCacheItemProvider(); - this.syncRequestRootActivityId = string.Empty; - this.correlationId = Guid.Empty; - this.syncRequestTimeStamp = string.Empty; + return Resources.ARMDataCollectionMessage; + } } - public SynchronizeAzureAzureAnalysisServer(IAsAzureHttpClient AsAzureHttpClient, ITokenCacheItemProvider TokenCacheItemProvider) + protected override void BeginProcessing() { - this.AsAzureHttpClient = AsAzureHttpClient; - this.TokenCacheItemProvider = TokenCacheItemProvider; + this._dataCollectionProfile = new AzurePSDataCollectionProfile(false); + base.BeginProcessing(); + this.CommonBeginProcessing(Instance); } protected override void SetupDebuggingTraces() @@ -130,145 +120,80 @@ protected override void TearDownHttpClientPipeline() { // nothing to do here. } - + protected override void InitializeQosEvent() + { + // No data collection for this commandlet + } public override void ExecuteCmdlet() { - if (ShouldProcess(Instance, Resources.SynchronizingAnalysisServicesServer)) + if (!ShouldProcess(Instance, Resources.SynchronizingAnalysisServicesServer)) { - correlationId = Guid.NewGuid(); - WriteObject(string.Format("Sending sync request for database '{0}' to server '{1}'. Correlation Id: '{2}'.", Database, Instance, correlationId.ToString())); - var context = AsAzureClientSession.Instance.Profile.Context; - AsAzureClientSession.Instance.Login(context); - WriteProgress(new ProgressRecord(0, "Sync-AzAnalysisServicesInstance.", string.Format("Authenticating user for '{0}' environment.", context.Environment.Name))); - var clusterResolveResult = ClusterResolve(context, serverName); - var virtualServerName = clusterResolveResult.CoreServerName.Split(":".ToCharArray())[0]; - if (!serverName.Equals(virtualServerName) && !clusterResolveResult.CoreServerName.EndsWith(":rw")) - { - throw new SynchronizationFailedException("Sync request can only be sent to the management endpoint"); - } - - this.clusterResolveResult = clusterResolveResult; - Uri clusterBaseUri = new Uri(string.Format("{0}{1}{2}", Uri.UriSchemeHttps, Uri.SchemeDelimiter, clusterResolveResult.ClusterFQDN)); - var accessToken = this.TokenCacheItemProvider.GetTokenFromTokenCache(AsAzureClientSession.TokenCache, context.Account.UniqueId, context.Environment.Name); - - ScaleOutServerDatabaseSyncDetails syncResult = null; - try - { - WriteProgress(new ProgressRecord(0, "Sync-AzAnalysisServicesInstance.", string.Format("Successfully authenticated for '{0}' environment.", context.Environment.Name))); - syncResult = SynchronizeDatabaseAsync(context, clusterBaseUri, Database, accessToken).GetAwaiter().GetResult(); - } - catch (AggregateException aex) - { - foreach (var innerException in aex.Flatten().InnerExceptions) - { - WriteExceptionError(innerException); - } - } - catch (Exception ex) - { - WriteExceptionError(ex); - } + return; + } - if (syncResult == null) - { - throw new SynchronizationFailedException(string.Format(Resources.SyncASPollStatusUnknownMessage.FormatInvariant( - this.clusterResolveResult.CoreServerName, - correlationId, - DateTime.Now.ToString(CultureInfo.InvariantCulture), - string.Format("RootActivityId: {0}, Date Time UTC: {1}", syncRequestRootActivityId, syncRequestTimeStamp)))); - } + correlationId = Guid.NewGuid(); - if (syncResult.SyncState != DatabaseSyncState.Completed) - { - var serializedDetails = JsonConvert.SerializeObject(syncResult); - throw new SynchronizationFailedException(serializedDetails); - } + WriteObject(string.Format("Sending sync request for database '{0}' to server '{1}'. Correlation Id: '{2}'.", Database, Instance, correlationId.ToString())); - if (PassThru.IsPresent) - { - WriteObject(syncResult, true); - } + var clusterResolveResult = ClusterResolve(ServerName); + var virtualServerName = clusterResolveResult.CoreServerName.Split(":".ToCharArray())[0]; + if (!ServerName.Equals(virtualServerName) && !clusterResolveResult.CoreServerName.EndsWith(":rw")) + { + throw new SynchronizationFailedException("Sync request can only be sent to the management endpoint"); } - } - protected override void BeginProcessing() - { - this._dataCollectionProfile = new AzurePSDataCollectionProfile(false); + this.clusterResolveResult = clusterResolveResult; + Uri clusterBaseUri = new Uri(string.Format("{0}{1}{2}", Uri.UriSchemeHttps, Uri.SchemeDelimiter, clusterResolveResult.ClusterFQDN)); - if (AsAzureClientSession.Instance.Profile.Environments.Count == 0) + ScaleOutServerDatabaseSyncDetails syncResult = null; + try { - throw new PSInvalidOperationException(string.Format(Resources.NotLoggedInMessage, "")); + WriteProgress(new ProgressRecord(0, "Sync-AzAnalysisServicesInstance.", string.Format("Successfully authenticated for '{0}' environment.", DnsSafeHost))); + syncResult = SynchronizeDatabaseAsync(clusterBaseUri, Database).GetAwaiter().GetResult(); } - - serverName = Instance; - Uri uriResult; - - // if the user specifies the FQN of the server, then extract the servername out of that. - // and set the current context - if (Uri.TryCreate(Instance, UriKind.Absolute, out uriResult) && uriResult.Scheme == "asazure") + catch (AggregateException aex) { - serverName = uriResult.PathAndQuery.Trim('/'); - if (string.Compare(AsAzureClientSession.Instance.Profile.Context.Environment.Name, uriResult.DnsSafeHost, StringComparison.InvariantCultureIgnoreCase) != 0) + foreach (var innerException in aex.Flatten().InnerExceptions) { - throw new PSInvalidOperationException(string.Format(Resources.NotLoggedInMessage, Instance)); + WriteExceptionError(innerException); } } - else + catch (Exception ex) { - var currentContext = AsAzureClientSession.Instance.Profile.Context; - if (currentContext != null - && AsAzureClientSession.AsAzureRolloutEnvironmentMapping.ContainsKey(currentContext.Environment.Name)) - { - throw new PSInvalidOperationException(string.Format(Resources.InvalidServerName, serverName)); - } + WriteExceptionError(ex); } - if (this.AsAzureHttpClient == null) + if (syncResult == null) { - this.AsAzureHttpClient = new AsAzureHttpClient(() => - { - HttpClientHandler httpClientHandler = new HttpClientHandler(); - httpClientHandler.AllowAutoRedirect = false; - return new HttpClient(); - }); + throw new SynchronizationFailedException(string.Format(Resources.SyncASPollStatusUnknownMessage.FormatInvariant( + this.clusterResolveResult.CoreServerName, + correlationId, + DateTime.Now.ToString(CultureInfo.InvariantCulture), + string.Format("RootActivityId: {0}, Date Time UTC: {1}", syncRequestRootActivityId, syncRequestTimeStamp)))); } - if (this.TokenCacheItemProvider == null) + if (syncResult.SyncState != DatabaseSyncState.Completed) { - this.TokenCacheItemProvider = new TokenCacheItemProvider(); + var serializedDetails = JsonConvert.SerializeObject(syncResult); + throw new SynchronizationFailedException(serializedDetails); } - base.BeginProcessing(); - } - - protected override void InitializeQosEvent() - { - // No data collection for this commandlet - } - - protected override string DataCollectionWarning - { - get + if (PassThru.IsPresent) { - return Resources.ARMDataCollectionMessage; + WriteObject(syncResult, true); } } /// /// Worker Method for the synchronize request. /// - /// The AS azure context /// Base Uri for sync /// Database name - /// Access token - /// Max number of retries for get command /// private async Task SynchronizeDatabaseAsync( - AsAzureContext context, Uri syncBaseUri, - string databaseName, - string accessToken) + string databaseName) { Tuple pollingUrlAndRetryAfter = new Tuple(null, null); ScaleOutServerDatabaseSyncDetails syncResult = null; @@ -277,14 +202,12 @@ private async Task SynchronizeDatabaseAsync( { try { - var synchronize = string.Format((string)context.Environment.Endpoints[AsAzureEnvironment.AsRolloutEndpoints.SyncEndpoint], this.serverName, databaseName); - this.AsAzureHttpClient.resetHttpClient(); - using (var message = await AsAzureHttpClient.CallPostAsync( - syncBaseUri, - synchronize, - accessToken, - correlationId, - null)) + var syncEndpoint = string.Format(AsAzureEndpoints.SynchronizeEndpointPathFormat, this.ServerName, databaseName); + this.AsAzureDataplaneClient.resetHttpClient(); + using (var message = await AsAzureDataplaneClient.CallPostAsync( + baseUri: syncBaseUri, + requestUrl: syncEndpoint, + correlationId: correlationId)) { this.syncRequestRootActivityId = message.Headers.Contains(RootActivityIdHeaderName) ? message.Headers.GetValues(RootActivityIdHeaderName).FirstOrDefault() : string.Empty; this.syncRequestTimeStamp = message.Headers.Contains(CurrentUtcDateHeaderName) ? message.Headers.GetValues(CurrentUtcDateHeaderName).FirstOrDefault() : string.Empty; @@ -307,7 +230,7 @@ private async Task SynchronizeDatabaseAsync( return syncResult; } - pollingUrlAndRetryAfter = new Tuple< Uri, RetryConditionHeaderValue>(message.Headers.Location, message.Headers.RetryAfter); + pollingUrlAndRetryAfter = new Tuple(message.Headers.Location, message.Headers.RetryAfter); } } @@ -338,7 +261,6 @@ private async Task SynchronizeDatabaseAsync( { ScaleOutServerDatabaseSyncResult result = await this.PollSyncStatusWithRetryAsync( databaseName, - accessToken, pollingUrl, retryAfter.Delta ?? DefaultPollingInterval); syncResult = ScaleOutServerDatabaseSyncDetails.FromResult(result, correlationId.ToString()); @@ -354,7 +276,7 @@ private async Task SynchronizeDatabaseAsync( Database = databaseName, SyncState = DatabaseSyncState.Invalid, Details = Resources.SyncASPollStatusFailureMessage.FormatInvariant( - serverName, + ServerName, string.Empty, timestampNow.ToString(CultureInfo.InvariantCulture), string.Format(e.StackTrace)), @@ -371,12 +293,11 @@ private async Task SynchronizeDatabaseAsync( /// /// /// Database name - /// Access token /// URL for polling /// Polling interval set by the post response /// Max number of attempts for each poll before the attempt is declared a failure /// - private async Task PollSyncStatusWithRetryAsync(string databaseName, string accessToken, Uri pollingUrl, TimeSpan pollingInterval, int maxNumberOfAttempts = 3) + private async Task PollSyncStatusWithRetryAsync(string databaseName, Uri pollingUrl, TimeSpan pollingInterval, int maxNumberOfAttempts = 3) { return await Task.Run(async () => { @@ -396,12 +317,11 @@ private async Task PollSyncStatusWithRetryAsyn await Task.Delay(DefaultRetryIntervalForPolling); } - this.AsAzureHttpClient.resetHttpClient(); - using (HttpResponseMessage message = await AsAzureHttpClient.CallGetAsync( - pollingUrl, - string.Empty, - accessToken, - correlationId)) + this.AsAzureDataplaneClient.resetHttpClient(); + using (HttpResponseMessage message = await AsAzureDataplaneClient.CallGetAsync( + baseUri: pollingUrl, + requestUrl: string.Empty, + correlationId: correlationId)) { bool shouldRetry = false; if (message.IsSuccessStatusCode && message.Content != null) @@ -432,7 +352,7 @@ private async Task PollSyncStatusWithRetryAsyn shouldRetry = true; } - if(shouldRetry) + if (shouldRetry) { retryCount++; response = new ScaleOutServerDatabaseSyncResult() @@ -463,33 +383,14 @@ private async Task PollSyncStatusWithRetryAsyn } /// - /// Resolves the cluster to which the request needs to be sent for the current environment + /// Resolves the cluster to which the request needs to be sent for the current environment. /// - /// /// - /// - private ClusterResolutionResult ClusterResolve(AsAzureContext context, string serverName) + /// The . + private ClusterResolutionResult ClusterResolve(string serverName) { - Uri clusterResolveBaseUri = new Uri(string.Format("{0}{1}{2}", Uri.UriSchemeHttps, Uri.SchemeDelimiter, context.Environment.Name)); - UriBuilder resolvedUriBuilder = new UriBuilder(clusterResolveBaseUri); - string rolloutAccessToken = this.TokenCacheItemProvider.GetTokenFromTokenCache(AsAzureClientSession.TokenCache, context.Account.UniqueId, context.Environment.Name); - - var resolveEndpoint = "/webapi/clusterResolve"; - var content = new StringContent($"ServerName={serverName}"); - content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/x-www-form-urlencoded"); - - this.AsAzureHttpClient.resetHttpClient(); - using (HttpResponseMessage message = AsAzureHttpClient.CallPostAsync( - clusterResolveBaseUri, - resolveEndpoint, - rolloutAccessToken, - content).Result) - { - message.EnsureSuccessStatusCode(); - var rawResult = message.Content.ReadAsStringAsync().Result; - ClusterResolutionResult result = JsonConvert.DeserializeObject(rawResult); - return result; - } + Uri clusterResolveBaseUri = new Uri(string.Format("{0}{1}{2}", Uri.UriSchemeHttps, Uri.SchemeDelimiter, DnsSafeHost)); + return ClusterResolve(clusterResolveBaseUri, serverName); } } } diff --git a/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/ASAzureContext.cs b/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/ASAzureContext.cs deleted file mode 100644 index 068c41247508..000000000000 --- a/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/ASAzureContext.cs +++ /dev/null @@ -1,51 +0,0 @@ -// ---------------------------------------------------------------------------------- -// -// 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 System; - -namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane -{ - /// - /// Represents current AS Azure client context. - /// - [Serializable] - public class AsAzureContext - { - /// - /// Creates new instance of AsAzureContext. - /// - /// The AS azure account object - /// The AS azure environment object - public AsAzureContext(AsAzureAccount account, AsAzureEnvironment environment) - { - Account = account; - Environment = environment; - } - - /// - /// Gets the AS azure account. - /// - public AsAzureAccount Account { get; private set; } - - /// - /// Gets the AS Azure environment. - /// - public AsAzureEnvironment Environment { get; private set; } - - /// - /// Gets or sets the token cache contents. - /// - public byte[] TokenCache { get; set; } - } -} diff --git a/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureAuthenticationProvider.cs b/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureAuthenticationProvider.cs deleted file mode 100644 index df18308a617b..000000000000 --- a/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureAuthenticationProvider.cs +++ /dev/null @@ -1,170 +0,0 @@ -// ---------------------------------------------------------------------------------- -// -// 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 System; -using System.Runtime.Serialization; -using System.Security; -using Microsoft.IdentityModel.Clients.ActiveDirectory; -using Microsoft.WindowsAzure.Commands.Common.Properties; -using Microsoft.Azure.Commands.Common.Authentication.Abstractions; -// TODO: Remove IfDef -#if NETSTANDARD -using Microsoft.WindowsAzure.Commands.Common; -#endif - -namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane.Models -{ - [DataContract] - public class AsAzureAuthInfo - { - [DataMember] - public string DefaultResourceUriSuffix { get; set; } - - [DataMember] - public string AuthorityUrl { get; set; } - } - - public interface IAsAzureAuthenticationProvider - { -// TODO: Remove IfDef -#if NETSTANDARD - string GetAadAuthenticatedToken(AsAzureContext asAzureContext, SecureString password, Action promptAction, string clientId, string resourceUri, Uri resourceRedirectUri); -#else - string GetAadAuthenticatedToken(AsAzureContext asAzureContext, SecureString password, PromptBehavior promptBehavior, string clientId, string resourceUri, Uri resourceRedirectUri); -#endif - } - - public class AsAzureAuthenticationProvider : IAsAzureAuthenticationProvider - { -// TODO: Remove IfDef -#if NETSTANDARD - public string GetAadAuthenticatedToken(AsAzureContext asAzureContext, SecureString password, Action promptAction, string clientId, string resourceUri, Uri resourceRedirectUri) -#else - public string GetAadAuthenticatedToken(AsAzureContext asAzureContext, SecureString password, PromptBehavior promptBehavior, string clientId, string resourceUri, Uri resourceRedirectUri) -#endif - { - var authUriBuilder = new UriBuilder((string)asAzureContext.Environment.Endpoints[AsAzureEnvironment.AsRolloutEndpoints.AdAuthorityBaseUrl]) - { - Path = string.IsNullOrEmpty(asAzureContext.Account.Tenant) - ? "common" - : asAzureContext.Account.Tenant - }; - - var authenticationContext = new AuthenticationContext( - authUriBuilder.ToString(), - AsAzureClientSession.TokenCache); - - AuthenticationResult result = null; - var accountType = string.IsNullOrEmpty(asAzureContext.Account.Type) ? AsAzureAccount.AccountType.User : asAzureContext.Account.Type; - - if (password == null && accountType == AsAzureAccount.AccountType.User) - { - if (asAzureContext.Account.Id != null) - { -// TODO: Remove IfDef -#if NETSTANDARD - result = authenticationContext.AcquireTokenAsync( - resourceUri, - clientId, - resourceRedirectUri, - new PlatformParameters(), - new UserIdentifier(asAzureContext.Account.Id, UserIdentifierType.OptionalDisplayableId)).Result; -#else - result = authenticationContext.AcquireToken( - resourceUri, - clientId, - resourceRedirectUri, - promptBehavior, - new UserIdentifier(asAzureContext.Account.Id, UserIdentifierType.OptionalDisplayableId)); -#endif - } - else - { -// TODO: Remove IfDef -#if NETSTANDARD - result = authenticationContext.AcquireTokenAsync( - resourceUri, - clientId, - resourceRedirectUri, - new PlatformParameters()).Result; -#else - result = authenticationContext.AcquireToken( - resourceUri, - clientId, - resourceRedirectUri, - promptBehavior); -#endif - } - - asAzureContext.Account.Id = result.UserInfo.DisplayableId; - asAzureContext.Account.Tenant = result.TenantId; - asAzureContext.Account.UniqueId = result.UserInfo.UniqueId; - } - else - { - if (accountType == AsAzureAccount.AccountType.User) - { -// TODO: Remove IfDef -#if NETSTANDARD - //https://stackoverflow.com/a/39393039/294804 - //https://github.com/AzureAD/azure-activedirectory-library-for-dotnet/issues/482 - //https://github.com/Azure-Samples/active-directory-dotnet-deviceprofile/blob/5d5499d09c918ae837810d457822474df97600e9/DirSearcherClient/Program.cs#L206-L210 - // Note: More robust implementation in UserTokenProvider.Netcore.cs in DoAcquireToken - var codeResult = authenticationContext.AcquireDeviceCodeAsync(resourceUri, clientId).Result; - promptAction(codeResult?.Message); - result = authenticationContext.AcquireTokenByDeviceCodeAsync(codeResult).Result; -#else - UserCredential userCredential = new UserCredential(asAzureContext.Account.Id, password); - result = authenticationContext.AcquireToken(resourceUri, clientId, userCredential); -#endif - - asAzureContext.Account.Id = result.UserInfo.DisplayableId; - asAzureContext.Account.Tenant = result.TenantId; - asAzureContext.Account.UniqueId = result.UserInfo.UniqueId; - } - else if (accountType == AsAzureAccount.AccountType.ServicePrincipal) - { - if (string.IsNullOrEmpty(asAzureContext.Account.CertificateThumbprint)) - { -// TODO: Remove IfDef -#if NETSTANDARD - var credential = new ClientCredential(asAzureContext.Account.Id, ConversionUtilities.SecureStringToString(password)); - result = authenticationContext.AcquireTokenAsync(resourceUri, credential).Result; -#else - ClientCredential credential = new ClientCredential(asAzureContext.Account.Id, password); - result = authenticationContext.AcquireToken(resourceUri, credential); -#endif - } - else - { - var dataStore = new DiskDataStore(); - var certificate = dataStore.GetCertificate(asAzureContext.Account.CertificateThumbprint); - if (certificate == null) - { - throw new ArgumentException(string.Format(Resources.CertificateNotFoundInStore, asAzureContext.Account.CertificateThumbprint)); - } -// TODO: Remove IfDef -#if NETSTANDARD - result = authenticationContext.AcquireTokenAsync(resourceUri, new ClientAssertionCertificate(asAzureContext.Account.Id, certificate)).Result; -#else - result = authenticationContext.AcquireToken(resourceUri, new ClientAssertionCertificate(asAzureContext.Account.Id, certificate)); -#endif - } - } - } - - return result?.AccessToken; - } - } -} diff --git a/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureClientSession.cs b/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureClientSession.cs deleted file mode 100644 index fb1ea10ef4d8..000000000000 --- a/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureClientSession.cs +++ /dev/null @@ -1,165 +0,0 @@ -// ---------------------------------------------------------------------------------- -// -// 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 Microsoft.IdentityModel.Clients.ActiveDirectory; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Security; -using Microsoft.Azure.Commands.AnalysisServices.Dataplane.Models; - -namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane -{ - /// - /// Represents current AS Azure session. - /// - public class AsAzureClientSession - { - public const string RestartEndpointPathFormat = "/webapi/servers/{0}/restart?api-version=2016-10-01"; - public const string LogfileEndpointPathFormat = "/webapi/servers/{0}/logfileHere"; - public const string SynchronizeEndpointPathFormat = "/servers/{0}/models/{1}/sync"; - public const string AsAzureClientId = "cf710c6e-dfcc-4fa8-a093-d47294e44c66"; - public static readonly Uri RedirectUri = new Uri("urn:ietf:wg:oauth:2.0:oob"); - public static string DefaultRolloutEnvironmentKey = "asazure.windows.net"; - - public static Dictionary AsAzureRolloutEnvironmentMapping = new Dictionary - { - { "asazure.windows.net", new AsAzureAuthInfo - { - AuthorityUrl = "https://login.windows.net" , - DefaultResourceUriSuffix = "*.asazure.windows.net" - } - }, - { "asazure-int.windows.net", new AsAzureAuthInfo - { - AuthorityUrl = "https://login.windows-ppe.net" , - DefaultResourceUriSuffix = "*.asazure-int.windows.net" - } - } - }; - - /// - /// Gets or sets the token cache store. - /// - public static TokenCache TokenCache { get; set; } - - private IAsAzureAuthenticationProvider _asAzureAuthenticationProvider; - - static AsAzureClientSession() - { - Instance = new AsAzureClientSession(); - } - - private AsAzureClientSession() - { - TokenCache = new TokenCache(); - Profile = new AsAzureProfile(); - _asAzureAuthenticationProvider = new AsAzureAuthenticationProvider(); - } - - public void SetAsAzureAuthenticationProvider(IAsAzureAuthenticationProvider asAzureAuthenticationProvider) - { - _asAzureAuthenticationProvider = asAzureAuthenticationProvider; - } - - public static AsAzureClientSession Instance { get; private set; } - - /// - /// As Azure Profile - /// - public AsAzureProfile Profile { get; set; } -// TODO: Remove IfDef -#if NETSTANDARD - public AsAzureProfile Login(AsAzureContext asAzureContext, SecureString password, Action promptAction = null) -#else - public AsAzureProfile Login(AsAzureContext asAzureContext, SecureString password) -#endif - { - var resourceUri = new UriBuilder(Uri.UriSchemeHttps, GetResourceUriSuffix(asAzureContext.Environment.Name)).ToString(); - resourceUri = resourceUri.TrimEnd('/'); -// TODO: Remove IfDef -#if NETSTANDARD - _asAzureAuthenticationProvider.GetAadAuthenticatedToken(asAzureContext, password, promptAction, AsAzureClientId, resourceUri, RedirectUri); -#else - _asAzureAuthenticationProvider.GetAadAuthenticatedToken(asAzureContext, password, password == null ? PromptBehavior.Always : PromptBehavior.Auto, AsAzureClientId, resourceUri, RedirectUri); -#endif - - Profile.Context.TokenCache = TokenCache.Serialize(); - - if (!Profile.Environments.ContainsKey(asAzureContext.Environment.Name)) - { - Profile.Environments.Add(asAzureContext.Environment.Name, asAzureContext.Environment); - } - - return Profile; - } - - public AsAzureProfile Login(AsAzureContext asAzureContext) - { - var resourceUri = new UriBuilder(Uri.UriSchemeHttps, GetResourceUriSuffix(asAzureContext.Environment.Name)).ToString(); - resourceUri = resourceUri.TrimEnd('/'); -// TODO: Remove IfDef -#if NETSTANDARD - _asAzureAuthenticationProvider.GetAadAuthenticatedToken(asAzureContext, null, null, AsAzureClientId, resourceUri, RedirectUri); -#else - _asAzureAuthenticationProvider.GetAadAuthenticatedToken(asAzureContext, null, PromptBehavior.RefreshSession, AsAzureClientId, resourceUri, RedirectUri); -#endif - - Profile.Context.TokenCache = TokenCache.Serialize(); - - if (!Profile.Environments.ContainsKey(asAzureContext.Environment.Name)) - { - Profile.Environments.Add(asAzureContext.Environment.Name, asAzureContext.Environment); - } - - return Profile; - } - - public static string GetAuthorityUrlForEnvironment(AsAzureEnvironment environment) - { - var environmentKey = AsAzureRolloutEnvironmentMapping.Keys.FirstOrDefault(s => environment.Name.Contains(s)); - AsAzureAuthInfo authInfo; - if (string.IsNullOrEmpty(environmentKey) || !AsAzureRolloutEnvironmentMapping.TryGetValue(environmentKey, out authInfo)) - { - throw new ArgumentException(Properties.Resources.UnknownEnvironment); - } - - return authInfo.AuthorityUrl; - } - - public void SetCurrentContext(AsAzureAccount azureAccount, AsAzureEnvironment asEnvironment) - { - Profile.Context = new AsAzureContext(azureAccount, asEnvironment) - { - TokenCache = TokenCache.Serialize() - }; - } - - public static string GetDefaultEnvironmentName() - { - return AsAzureRolloutEnvironmentMapping[DefaultRolloutEnvironmentKey].DefaultResourceUriSuffix; - } - - public static string GetResourceUriSuffix(string environmentName) - { - if (string.IsNullOrEmpty(environmentName)) - { - return AsAzureRolloutEnvironmentMapping[DefaultRolloutEnvironmentKey].DefaultResourceUriSuffix; - } - - var authoInfo = AsAzureRolloutEnvironmentMapping.FirstOrDefault(kv => kv.Key.Equals(environmentName)).Value; - return authoInfo != null ? authoInfo.DefaultResourceUriSuffix : environmentName; - } - } -} diff --git a/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureDataplaneClient.cs b/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureDataplaneClient.cs new file mode 100644 index 000000000000..e1c6931be189 --- /dev/null +++ b/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureDataplaneClient.cs @@ -0,0 +1,231 @@ +// ---------------------------------------------------------------------------------- +// +// 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 System; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Rest; + +namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane.Models +{ + /// + /// Contains properties and logic for . + /// All permutations of CallGetAsync, and CallPostAsync are in the partial class in order to make this partial class more readable. + /// + /// Most modifications will likely be in this part of the class. + public partial class AsAzureDataplaneClient : ServiceClient, IAsAzureHttpClient + { + /// + /// The base Uri of the service. + /// + public Uri BaseUri { get; set; } + + /// + /// Credentials needed for the client to connect to Azure. + /// + public ServiceClientCredentials Credentials { get; private set; } + + private Func HttpClientProvider { get; set; } + + // This may cause problems, but is necessary for mulitple inheritance. + public new HttpClient HttpClient { get; set; } + + public AsAzureDataplaneClient(Uri baseUri, ServiceClientCredentials credentials, Func httpClientProvider, params DelegatingHandler[] handlers) : base(handlers) + { + this.BaseUri = baseUri ?? throw new ArgumentNullException(nameof(baseUri)); + this.Credentials = credentials ?? throw new ArgumentNullException(nameof(credentials)); + this.HttpClientProvider = httpClientProvider ?? throw new ArgumentNullException(nameof(httpClientProvider)); + this.Credentials.InitializeServiceClient(this); + this.resetHttpClient(); + } + + public AsAzureDataplaneClient(Uri baseUri, ServiceClientCredentials credentials, Func httpClientProvider, HttpClientHandler rootHandler, params DelegatingHandler[] handlers) : base(rootHandler, handlers) + { + this.BaseUri = baseUri ?? throw new ArgumentNullException(nameof(baseUri)); + this.Credentials = credentials ?? throw new ArgumentNullException(nameof(credentials)); + this.HttpClientProvider = httpClientProvider ?? throw new ArgumentNullException(nameof(httpClientProvider)); + this.Credentials.InitializeServiceClient(this); + this.resetHttpClient(); + } + + public void resetHttpClient() + { + this.HttpClient = this.HttpClientProvider(); + } + + #region GetMethodAsyncOverloads + + /// + /// Calls SendRequestAsync() for a GET using a blank correlationId. + /// + /// The base Uri to call. + /// The request Url. + /// The access token (will be discarded). + /// The http response message. + public async Task CallGetAsync(Uri baseUri, string requestUrl, string accessToken) + { + return await CallGetAsync(baseUri: baseUri, requestUrl: requestUrl, accessToken: accessToken, correlationId: new Guid()); + } + + /// + /// Calls SendRequestAsync() for a GET. + /// + /// The base Uri to call. + /// The request Url. + /// The access token (will be discarded). + /// The CorrelationId + /// The http response message. + public async Task CallGetAsync(Uri baseUri, string requestUrl, string accessToken = null, Guid correlationId = new Guid()) + { + return await SendRequestAsync(HttpMethod.Get, baseUri: baseUri, requestUrl: requestUrl, correlationId: correlationId); + } + + /// + /// Calls SendRequestAsync() for a GET using the default BaseUri and a blank correlationId. + /// + /// The Request Url. + /// The http response message. + public async Task CallGetAsync(string requestUrl) + { + return await CallGetAsync(requestUrl, new Guid()); + } + + /// + /// Calls SendRequestAsync() for a GET using the default BaseUri. + /// + /// The Request Url. + /// The CorrelationId + /// The http response message. + public async Task CallGetAsync(string requestUrl, Guid correlationId) + { + return await SendRequestAsync(HttpMethod.Get, BaseUri, requestUrl, correlationId); + } + + /// + /// Calls SendRequestAsync() for a POST using a blank correlationId. + /// + /// The base Uri to call. + /// The request Url. + /// The access token (will be discarded). + /// The content to post (optional). + /// The http response message. + public async Task CallPostAsync(Uri baseUri, string requestUrl, string accessToken, HttpContent content = null) + { + return await CallPostAsync(baseUri: baseUri, requestUrl: requestUrl, accessToken: accessToken, correlationId: new Guid(), content: content); + } + + /// + /// Calls SendRequestAsync() for a POST. + /// + /// The base Uri to call. + /// The request Url. + /// The access token (will be discarded). + /// The CorrelationId + /// The content to post (optional). + /// The http response message. + public async Task CallPostAsync(Uri baseUri, string requestUrl, string accessToken = null, Guid correlationId = new Guid(), HttpContent content = null) + { + return await SendRequestAsync(HttpMethod.Post, baseUri: baseUri, requestUrl: requestUrl, correlationId: correlationId, content: content); + } + + /// + /// Calls SendRequestAsync() for a POST using the default BaseUri and a blank correlationId. + /// + /// The Request Url. + /// The content to post (optional). + /// The http response message. + public async Task CallPostAsync(string requestUrl, HttpContent content = null) + { + return await CallPostAsync(requestUrl, new Guid(), content); + } + + /// + /// Calls SendRequestAsync() for a POST using the default BaseUri. + /// + /// The Request Url. + /// The CorrelationId + /// The content to post (optional). + /// The http response message. + public async Task CallPostAsync(string requestUrl, Guid correlationId, HttpContent content = null) + { + return await SendRequestAsync(HttpMethod.Post, BaseUri, requestUrl, correlationId, content); + } + + #endregion + + private async Task SendRequestAsync( + HttpMethod method, + Uri baseUri, + string requestUrl, + Guid correlationId, + HttpContent content = null, + CancellationToken cancellationToken = default(CancellationToken)) + { + // Construct URL + ////List queryParameters = new List(); + + // Create HTTP transport objects + HttpRequestMessage httpRequest = new HttpRequestMessage() + { + Method = method, + RequestUri = new Uri(baseUri, requestUrl), + Content = content + }; + + // Set Headers + AddHeader(httpRequest.Headers, "x-ms-client-request-id", correlationId.ToString()); + + // TODO: Where is this flag located? + ////if (this.Client.AcceptLanguage != null) + ////{ + //// AddHeader(httpRequest.Headers, "accept-language", this.Client.AcceptLanguage); + ////} + + // TODO: Where are the custom headers coming from? + ////if (customHeaders != null) + ////{ + //// foreach (var header in customHeaders) + //// { + //// AddHeader(httpRequest.Headers, header.Key, header.Value); + //// } + ////} + + // Set Credentials + if (Credentials != null) + { + cancellationToken.ThrowIfCancellationRequested(); + await Credentials.ProcessHttpRequestAsync(httpRequest, cancellationToken).ConfigureAwait(false); + } + + return await this.HttpClient.SendAsync(httpRequest, cancellationToken).ConfigureAwait(false); + } + + /// + /// Adds a header to the list object. + /// + /// The request headers list object. + /// The name of the header to add. + /// The value of the header. + private static void AddHeader(HttpRequestHeaders headers, string name, string value) + { + if (headers.Contains(name)) + { + headers.Remove(name); + } + headers.TryAddWithoutValidation(name, value); + } + } +} diff --git a/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs b/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs new file mode 100644 index 000000000000..021273a89a6d --- /dev/null +++ b/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs @@ -0,0 +1,151 @@ +// ---------------------------------------------------------------------------------- +// +// 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 Microsoft.Azure.Commands.Common.Authentication; +using Microsoft.Azure.Commands.Common.Authentication.Abstractions; +using Microsoft.Azure.Commands.Common.Authentication.Properties; +using Microsoft.WindowsAzure.Commands.Utilities.Common; +using Newtonsoft.Json; +using System; +using System.Management.Automation; +using System.Net.Http; +using System.Net.Http.Headers; + +namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane.Models +{ + /// + /// The base class for all Microsoft Azure Analysis Services Management cmdlets + /// + public abstract class AsAzureDataplaneCmdletBase : AzurePSCmdlet + { + private AsAzureDataplaneClient _asAzureDataplaneClient; + + private IAzureContext _currentContext; + + /// + /// The fully qualified absolute URI of the server instance. + /// (scheme.region.azureAsEndpoint/serverName) + /// + /// asazure://westus.asazure.windows.net/testserver + protected string ServerUri; + + /// + /// A DNS safe host name for the server. + /// (region.azureAsEndpoint) + /// + /// westus.asazure.windows.net + protected string DnsSafeHost; + + /// + /// The name of the server. + /// + /// testserver + protected string ServerName; + + protected override IAzureContext DefaultContext + { + get + { + // Nothing to do with Azure Resource Management context + return null; + } + } + + protected IAzureContext CurrentContext + { + get + { + if (_currentContext == null) + { + _currentContext = AzureRmProfileProvider.Instance.Profile.DefaultContext; + } + + return _currentContext; + } + + set { _currentContext = value; } + } + + public AsAzureDataplaneClient AsAzureDataplaneClient + { + get + { + if (_asAzureDataplaneClient == null) + { + _asAzureDataplaneClient = CreateAsAzureDataplaneClient(DnsSafeHost, CurrentContext, () => { return new HttpClient(); }); + } + + return _asAzureDataplaneClient; + } + + set { _asAzureDataplaneClient = value; } + } + + protected void CommonBeginProcessing(string instance) + { + // user must specify the fully qualified server name. For example, westus2.asazure.windows.net/testserver + if (!Uri.TryCreate(instance, UriKind.Absolute, out var uriResult) || uriResult.Scheme != AsAzureEndpoints.UriSchemeAsAzure) + { + throw new PSInvalidOperationException(string.Format(Properties.Resources.InvalidServerName, instance)); + } + + // derive all bits of the url from the input + ServerUri = uriResult.AbsoluteUri; + DnsSafeHost = uriResult.DnsSafeHost; + ServerName = uriResult.PathAndQuery.Trim('/'); + + AsAzureDataplaneClient = CreateAsAzureDataplaneClient(DnsSafeHost, CurrentContext, () => { return new HttpClient(); }); + } + + protected ClusterResolutionResult ClusterResolve(Uri clusterUri, string serverName) + { + var content = new StringContent($"ServerName={serverName}"); + content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/x-www-form-urlencoded"); + + this.AsAzureDataplaneClient.resetHttpClient(); + using (var message = AsAzureDataplaneClient.CallPostAsync( + baseUri: clusterUri, + requestUrl: AsAzureEndpoints.ClusterResolveEndpoint, + content: content).Result) + { + message.EnsureSuccessStatusCode(); + var rawResult = message.Content.ReadAsStringAsync().Result; + return JsonConvert.DeserializeObject(rawResult); + } + } + + internal static AsAzureDataplaneClient CreateAsAzureDataplaneClient(string hostUri, IAzureContext context, Func httpClientProvider, bool parameterizedBaseUri = false) + { + if (context == null) + { + throw new ApplicationException(Resources.NoSubscriptionInContext); + } + + if (string.IsNullOrEmpty(hostUri)) + { + throw new ArgumentNullException(nameof(hostUri)); + } + + if (httpClientProvider == null) + { + throw new ArgumentNullException(nameof(httpClientProvider)); + } + + var baseUri = new Uri(string.Format("{0}{1}{2}", Uri.UriSchemeHttps, Uri.SchemeDelimiter, hostUri)); + var credentials = AzureSession.Instance.AuthenticationFactory.GetServiceClientCredentials(context, AzureEnvironment.ExtendedEndpoint.AnalysisServicesEndpointSuffix); + var handlers = AzureSession.Instance.ClientFactory.GetCustomHandlers(); + return AzureSession.Instance.ClientFactory.CreateCustomArmClient(baseUri, credentials, httpClientProvider, handlers); + } + } +} diff --git a/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureAccount.cs b/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureEndpoints.cs similarity index 54% rename from src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureAccount.cs rename to src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureEndpoints.cs index 1b7efc2a65a3..61cad1c83501 100644 --- a/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureAccount.cs +++ b/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureEndpoints.cs @@ -12,30 +12,19 @@ // limitations under the License. // ---------------------------------------------------------------------------------- -using System; - -namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane +namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane.Models { - [Serializable] - public partial class AsAzureAccount + /// + /// Class to hold the endpoint format strings for dataplane cmdlets. + /// + class AsAzureEndpoints { - public string Id { get; set; } - - public string UniqueId { get; set; } - - public string Tenant { get; set; } - - public string Type { get; set; } + public const string RestartEndpointPathFormat = "/webapi/servers/{0}/restart?api-version=2016-10-01"; + public const string LogfileEndpointPathFormat = "/webapi/servers/{0}/logfileHere"; + public const string SynchronizeEndpointPathFormat = "/servers/{0}/models/{1}/sync"; - public string CertificateThumbprint { get; set; } + public const string ClusterResolveEndpoint = "/webapi/clusterResolve"; - /// - /// string constants for known credential types - /// - public static class AccountType - { - public const string User = "User", - ServicePrincipal = "ServicePrincipal"; - } + public const string UriSchemeAsAzure = "asazure"; } } diff --git a/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureProfile.cs b/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureProfile.cs deleted file mode 100644 index 586257b40797..000000000000 --- a/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureProfile.cs +++ /dev/null @@ -1,65 +0,0 @@ -// ---------------------------------------------------------------------------------- -// -// 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 Newtonsoft.Json; -using System; -using System.Collections; -using System.Collections.Generic; - -namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane -{ - /// - /// Represents AS Azure profile structure with default context, environments and token cache. - /// - [Serializable] - public sealed class AsAzureProfile - { - /// - /// Gets or sets AS Azure environments. - /// - public Hashtable Environments { get; set; } - - /// - /// Gets or sets the AS azure context object. - /// - public AsAzureContext Context { get; set; } - - /// - /// Initializes a new instance of AsAzureProfile and loads its content from specified path. - /// - public AsAzureProfile() - { - this.Environments = new Hashtable(); - } - - /// - /// Serializes the current profile and return its contents. - /// - /// The current string. - public override string ToString() - { - return JsonConvert.SerializeObject(this, Formatting.Indented); - } - - public AsAzureEnvironment CreateEnvironment(string environmentName) - { - var env = new AsAzureEnvironment(environmentName); - env.Endpoints.Add(AsAzureEnvironment.AsRolloutEndpoints.AdAuthorityBaseUrl, AsAzureClientSession.GetAuthorityUrlForEnvironment(env)); - env.Endpoints.Add(AsAzureEnvironment.AsRolloutEndpoints.RestartEndpointFormat, AsAzureClientSession.RestartEndpointPathFormat); - env.Endpoints.Add(AsAzureEnvironment.AsRolloutEndpoints.LogfileEndpointFormat, AsAzureClientSession.LogfileEndpointPathFormat); - env.Endpoints.Add(AsAzureEnvironment.AsRolloutEndpoints.SyncEndpoint, AsAzureClientSession.SynchronizeEndpointPathFormat); - return env; - } - } -} diff --git a/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Test/InMemoryTests/AddAzureASAccountTests.cs b/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Test/InMemoryTests/AddAzureASAccountTests.cs deleted file mode 100644 index 68320d9285df..000000000000 --- a/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Test/InMemoryTests/AddAzureASAccountTests.cs +++ /dev/null @@ -1,80 +0,0 @@ -// ---------------------------------------------------------------------------------- -// -// 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 System; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Management.Automation; -using System.Security; -using System.Text; -using System.Threading.Tasks; -using Microsoft.Azure.Commands.AnalysisServices.Dataplane; -using Microsoft.Azure.Commands.AnalysisServices.Test.ScenarioTests; -using Microsoft.Azure.ServiceManagement.Common.Models; -using Microsoft.WindowsAzure.Commands.Common; -using Microsoft.WindowsAzure.Commands.ScenarioTest; -using Microsoft.WindowsAzure.Commands.Utilities.Common; -using Moq; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Azure.Commands.AnalysisServices.Test.InMemoryTests -{ - public class AddAzureASAccountTests : AsTestsBase - { - private const string testAsAzureEnvironment = "westcentralus.asazure.windows.net"; - - private const string testUser = "testuser"; - - private const string testPassword = "testpassword"; - - public AddAzureASAccountTests(ITestOutputHelper output) - { - XunitTracingInterceptor.AddToContext(new XunitTracingInterceptor(output)); - } - - [Fact(Skip = "Issue to investigate, Environments not becoming populated")] - [Trait(Category.AcceptanceType, Category.CheckIn)] - public void CreatesNewPSResourceGroup() - { - Mock commandRuntimeMock = new Mock(); - AddAzureASAccountCommand cmdlet = new AddAzureASAccountCommand() - { - CommandRuntime = commandRuntimeMock.Object - }; - // Setup - cmdlet.RolloutEnvironment = testAsAzureEnvironment; - var password = new SecureString(); - var testpwd = testPassword; - testpwd.All(c => { - password.AppendChar(c); - return true; - }); - cmdlet.Credential = new PSCredential(testUser, password); - - cmdlet.InvokeBeginProcessing(); - cmdlet.ExecuteCmdlet(); - cmdlet.InvokeEndProcessing(); - - // Act - Assert.NotEmpty(AsAzureClientSession.Instance.Profile.Environments); - Assert.NotNull(AsAzureClientSession.Instance.Profile.Environments[testAsAzureEnvironment]); - var environment = (AsAzureEnvironment)AsAzureClientSession.Instance.Profile.Environments[testAsAzureEnvironment]; - Assert.Equal("", environment.Endpoints[AsAzureEnvironment.AsRolloutEndpoints.AdAuthorityBaseUrl]); - Assert.NotNull(environment.Endpoints[AsAzureEnvironment.AsRolloutEndpoints.RestartEndpointFormat]); - } - } -} diff --git a/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Test/InMemoryTests/DataPlaneCommandTests.cs b/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Test/InMemoryTests/DataPlaneCommandTests.cs index a01e2b6e979e..4991c30cc5a8 100644 --- a/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Test/InMemoryTests/DataPlaneCommandTests.cs +++ b/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Test/InMemoryTests/DataPlaneCommandTests.cs @@ -1,632 +1,632 @@ -// ---------------------------------------------------------------------------------- -// -// 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 System; -using System.Linq; -using System.Management.Automation; -using System.Net; -using System.Net.Http; -using System.Reflection; -using System.Security; -using System.Text; -using System.Threading.Tasks; -using Microsoft.Azure.Commands.AnalysisServices.Dataplane; -using Microsoft.Azure.Commands.AnalysisServices.Dataplane.Models; -using Microsoft.Azure.Commands.AnalysisServices.Test.ScenarioTests; -using Microsoft.Azure.ServiceManagement.Common.Models; -using Microsoft.IdentityModel.Clients.ActiveDirectory; -using Microsoft.WindowsAzure.Commands.ScenarioTest; -using Microsoft.WindowsAzure.Commands.Utilities.Common; -using Moq; -using Xunit; -using Xunit.Abstractions; -using System.Collections.Generic; -using System.Net.Http.Headers; -using Newtonsoft.Json; - -namespace Microsoft.Azure.Commands.AnalysisServices.Test.InMemoryTests -{ - public class DataPlaneCommandTests : AsTestsBase - { - private const string testAsAzureEnvironment = "westcentralus.asazure.windows.net"; - - private const string testServer = "testserver"; - - private const string testUser = "testuser@contoso.com"; - - private const string testPassword = "testpassword"; - - private const string testToken = "eyJ0eXAiOi" - + "JKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IjFpOWlmMDllc0YzaU9sS0I2SW9meVVGSUxnQSIsImtpZC" - + "I6IjFpOWlmMDllc0YzaU9sS0I2SW9meVVGSUxnQSJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY" - + "29yZS53aW5kb3dzLm5ldC8iLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLXBwZS5uZXQvMDQ1NDZiY" - + "zAtYmMxOS00Y2I2LWIxNmQtNTc0OTQxNzFhNGJjLyIsImlhdCI6MTQ4MDU1NjY0MywibmJmIjoxNDgwN" - + "TU2NjQzLCJleHAiOjE0ODA1NjA1NDMsImFjciI6IjEiLCJhbXIiOlsicHdkIl0sImFwcGlkIjoiMTk1M" - + "GEyNTgtMjI3Yi00ZTMxLWE5Y2YtNzE3NDk1OTQ1ZmMyIiwiYXBwaWRhY3IiOiIwIiwiZV9leHAiOjEwO" - + "DAwLCJmYW1pbHlfbmFtZSI6IlN1c21hbiIsImdpdmVuX25hbWUiOiJEZXJ5YSIsImdyb3VwcyI6WyI0Y" - + "zNmNjNiNy1mZWU1LTQ1ZWItOTAwMy03YWQ1ZDM5MzMzMDIiXSwiaXBhZGRyIjoiMTY3LjIyMC4wLjExM" - + "yIsIm5hbWUiOiJEZXJ5YSBTdXNtYW4iLCJvaWQiOiJhODMyOWI5OS01NGI1LTQwNDctOTU5NS1iNWZkN" - + "2VhMzgyZjYiLCJwbGF0ZiI6IjMiLCJwdWlkIjoiMTAwMzAwMDA5QUJGRTQyRiIsInNjcCI6InVzZXJfa" - + "W1wZXJzb25hdGlvbiIsInN1YiI6ImEyUE5ZZW9KSnk3VnFFVWVkb0ZxS0J6UUNjOWNUN2tCVWtSYm5BM" - + "ldLcnciLCJ0aWQiOiIwNDU0NmJjMC1iYzE5LTRjYjYtYjE2ZC01NzQ5NDE3MWE0YmMiLCJ1bmlxdWVfb" - + "mFtZSI6ImF6dGVzdDBAc3RhYmxldGVzdC5jY3NjdHAubmV0IiwidXBuIjoiYXp0ZXN0MEBzdGFibGV0Z" - + "XN0LmNjc2N0cC5uZXQiLCJ2ZXIiOiIxLjAiLCJ3aWRzIjpbIjYyZTkwMzk0LTY5ZjUtNDIzNy05MTkwL" - + "TAxMjE3NzE0NWUxMCJdfQ.W9eVq_TXGBjWCCl_tRGXM31OZn5G4UBIi6B9xZphvrpaAvu5tnzYm6XWah" - + "jwA_iE1djOpZM3rxFxP4ZFecVyZGHYVddSJ0rg6vw-L4J5jIPDSojqiGoSLtU8yFxEDRaro0SM4LdQ_N" - + "dF-oUwfUQGy88vLOejQdiKzfC-yFvtVSmYoyJSnkZLglDEbhySvLtjXGfpOgiyGLoncV5wTk6Vbf7VLe" - + "65kxhZWVUbTHaPuEvg03ZQ3esDb6wxQewJPAL-GARg6S9wIN776Esw8-53AWhzFu0fIut-9FXGma6jV7" - + "MYPoUUcFuQzLZgphecPyMPXSVhummVCdBwX9sizxnmFA"; - - public DataPlaneCommandTests(ITestOutputHelper output) - { - XunitTracingInterceptor.AddToContext(new XunitTracingInterceptor(output)); - - SynchronizeAzureAzureAnalysisServer.DefaultRetryIntervalForPolling = TimeSpan.FromSeconds(0); - } - - [Fact] - [Trait(Category.AcceptanceType, Category.CheckIn)] - public void TestAddAzureASAccountCommand() - { - Mock commandRuntimeMock = new Mock(); - var addAmdlet = new AddAzureASAccountCommand() - { - CommandRuntime = commandRuntimeMock.Object - }; - var expectedProfile = new AsAzureProfile - { - Context = new AsAzureContext( - new AsAzureAccount() - { - Id = testUser, - Tenant = null - }, - new AsAzureEnvironment(testAsAzureEnvironment)) - }; - expectedProfile.Context.Environment.Endpoints.Add(AsAzureEnvironment.AsRolloutEndpoints.AdAuthorityBaseUrl, AsAzureClientSession.GetAuthorityUrlForEnvironment(expectedProfile.Context.Environment)); - expectedProfile.Context.Environment.Endpoints.Add(AsAzureEnvironment.AsRolloutEndpoints.RestartEndpointFormat, AsAzureClientSession.RestartEndpointPathFormat); - expectedProfile.Environments.Add(testAsAzureEnvironment, expectedProfile.Context.Environment); - expectedProfile.Context.TokenCache = Encoding.ASCII.GetBytes(testToken); - - // Setup - // Clear the the current profile - AsAzureClientSession.Instance.Profile.Environments.Clear(); - - var mockAuthenticationProvider = new Mock(); - mockAuthenticationProvider.Setup( - authProvider => authProvider.GetAadAuthenticatedToken( - It.IsAny(), - It.IsAny(), -#if NETSTANDARD - It.IsAny>(), -#else - It.IsAny(), -#endif - It.IsAny(), - It.IsAny(), - It.IsAny())).Returns(testToken); - AsAzureClientSession.Instance.SetAsAzureAuthenticationProvider(mockAuthenticationProvider.Object); - - addAmdlet.RolloutEnvironment = testAsAzureEnvironment; - var password = new SecureString(); - var testpwd = testPassword; - testpwd.All(c => { - password.AppendChar(c); - return true; - }); - addAmdlet.Credential = new PSCredential(testUser, password); - commandRuntimeMock.Setup(f => f.ShouldProcess(It.IsAny(), It.IsAny())).Returns(true); - commandRuntimeMock.Setup(f => f.WriteObject(expectedProfile)); - - // Act - addAmdlet.InvokeBeginProcessing(); - Assert.Empty(AsAzureClientSession.Instance.Profile.Environments); - addAmdlet.ExecuteCmdlet(); - Assert.True(AsAzureClientSession.Instance.Profile.Environments.Count == 1); - Assert.NotNull(AsAzureClientSession.Instance.Profile.Environments[testAsAzureEnvironment]); - - // Call InvokeBeginProcessing again to get coverage. It should use the existing environment in memory not create a new one. - addAmdlet.InvokeBeginProcessing(); - Assert.True(AsAzureClientSession.Instance.Profile.Environments.Count == 1); - Assert.NotNull(AsAzureClientSession.Instance.Profile.Environments[testAsAzureEnvironment]); - - addAmdlet.InvokeEndProcessing(); - - var environment = (AsAzureEnvironment)AsAzureClientSession.Instance.Profile.Environments[testAsAzureEnvironment]; - Assert.Equal(environment.Endpoints[AsAzureEnvironment.AsRolloutEndpoints.AdAuthorityBaseUrl], AsAzureClientSession.GetAuthorityUrlForEnvironment(environment)); - Assert.NotNull(environment.Endpoints[AsAzureEnvironment.AsRolloutEndpoints.RestartEndpointFormat]); - - commandRuntimeMock.Verify(f => f.WriteObject(AsAzureClientSession.Instance.Profile)); - mockAuthenticationProvider.Verify(authProvider => authProvider.GetAadAuthenticatedToken(It.IsAny(), - It.IsAny(), -#if NETSTANDARD - It.IsAny>(), -#else - It.IsAny(), -#endif - It.IsAny(), - It.IsAny(), - It.IsAny()), Times.Once); - } - - [Fact] - [Trait(Category.AcceptanceType, Category.CheckIn)] - public void RestartAzureASInstance_Succeeds() - { - Mock commandRuntimeMock = new Mock(); - // Setup - // Clear the the current profile - AsAzureClientSession.Instance.Profile.Environments.Clear(); - var mockAuthenticationProvider = new Mock(); - mockAuthenticationProvider.Setup( - authProvider => authProvider.GetAadAuthenticatedToken( - It.IsAny(), - It.IsAny(), -#if NETSTANDARD - It.IsAny>(), -#else - It.IsAny(), -#endif - It.IsAny(), - It.IsAny(), - It.IsAny())).Returns(testToken); - AsAzureClientSession.Instance.SetAsAzureAuthenticationProvider(mockAuthenticationProvider.Object); - commandRuntimeMock.Setup(f => f.ShouldProcess(It.IsAny(), It.IsAny())).Returns(true); - - // Set up AsAzureHttpClient mock - var mockAsAzureHttpClient = new Mock(); - mockAsAzureHttpClient - .Setup(obj => obj.CallPostAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .Returns(Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK))); - - var mockTokenCacheItemProvider = new Mock(); - mockTokenCacheItemProvider - .Setup(obj => obj.GetTokenFromTokenCache(It.IsAny(), It.IsAny())) - .Returns(testToken); - var restartCmdlet = new RestartAzureAnalysisServer(mockAsAzureHttpClient.Object, mockTokenCacheItemProvider.Object) - { - CommandRuntime = commandRuntimeMock.Object - }; - - var addAmdlet = new AddAzureASAccountCommand() - { - CommandRuntime = commandRuntimeMock.Object - }; - - DoLogin(addAmdlet); - restartCmdlet.Instance = testServer; - - // Act - restartCmdlet.InvokeBeginProcessing(); - restartCmdlet.ExecuteCmdlet(); - restartCmdlet.InvokeEndProcessing(); - } - - [Fact] - [Trait(Category.AcceptanceType, Category.CheckIn)] - public void RestartAzureASInstance_NullInstanceThrows() - { - Mock commandRuntimeMock = new Mock(); - - var mockAsAzureHttpClient = new Mock(); - var mockTokenCacheItemProvider = new Mock(); - var restartCmdlet = new RestartAzureAnalysisServer(mockAsAzureHttpClient.Object, mockTokenCacheItemProvider.Object) - { - CommandRuntime = commandRuntimeMock.Object - }; - - // Setup - // Clear the the current profile - AsAzureClientSession.Instance.Profile.Environments.Clear(); - var mockAuthenticationProvider = new Mock(); - mockAuthenticationProvider.Setup( - authProvider => authProvider.GetAadAuthenticatedToken( - It.IsAny(), - It.IsAny(), -#if NETSTANDARD - It.IsAny>(), -#else - It.IsAny(), -#endif - It.IsAny(), - It.IsAny(), - It.IsAny())).Returns(testToken); - AsAzureClientSession.Instance.SetAsAzureAuthenticationProvider(mockAuthenticationProvider.Object); - commandRuntimeMock.Setup(f => f.ShouldProcess(It.IsAny(), It.IsAny())).Returns(true); - - restartCmdlet.Instance = null; - // Act - Assert.Throws(() => restartCmdlet.InvokeBeginProcessing()); - } - - [Fact] - [Trait(Category.AcceptanceType, Category.CheckIn)] - public void RestartAzureASInstance_NotLoggedInThrows() - { - Mock commandRuntimeMock = new Mock(); - - var mockAsAzureHttpClient = new Mock(); - var mockTokenCacheItemProvider = new Mock(); - var restartCmdlet = new RestartAzureAnalysisServer(mockAsAzureHttpClient.Object, mockTokenCacheItemProvider.Object) - { - CommandRuntime = commandRuntimeMock.Object - }; - - // Setup - // Clear the the current profile - AsAzureClientSession.Instance.Profile.Environments.Clear(); - var mockAuthenticationProvider = new Mock(); - mockAuthenticationProvider.Setup( - authProvider => authProvider.GetAadAuthenticatedToken( - It.IsAny(), - It.IsAny(), -#if NETSTANDARD - It.IsAny>(), -#else - It.IsAny(), -#endif - It.IsAny(), - It.IsAny(), - It.IsAny())).Returns(testToken); - AsAzureClientSession.Instance.SetAsAzureAuthenticationProvider(mockAuthenticationProvider.Object); - commandRuntimeMock.Setup(f => f.ShouldProcess(It.IsAny(), It.IsAny())).Returns(true); - restartCmdlet.Instance = testServer; - - // Act - try - { - restartCmdlet.InvokeBeginProcessing(); - } - catch(Exception ex) - { - Assert.IsType(ex); - } - } - - [Fact] - [Trait(Category.AcceptanceType, Category.CheckIn)] - public void ExportAzureASInstanceLogTest() - { - Mock commandRuntimeMock = new Mock(); - // Setup - // Clear the the current profile - AsAzureClientSession.Instance.Profile.Environments.Clear(); - var mockAuthenticationProvider = new Mock(); - mockAuthenticationProvider.Setup( - authProvider => authProvider.GetAadAuthenticatedToken( - It.IsAny(), - It.IsAny(), -#if NETSTANDARD - It.IsAny>(), -#else - It.IsAny(), -#endif - It.IsAny(), - It.IsAny(), - It.IsAny())).Returns(testToken); - AsAzureClientSession.Instance.SetAsAzureAuthenticationProvider(mockAuthenticationProvider.Object); - commandRuntimeMock.Setup(f => f.ShouldProcess(It.IsAny(), It.IsAny())).Returns(true); - - // Set up AsAzureHttpClient mock - var mockAsAzureHttpClient = new Mock(); - mockAsAzureHttpClient - .Setup(obj => obj.CallPostAsync( - It.IsAny(), - It.Is(s => s.Contains("clusterResolve")), - It.IsAny(), - It.IsAny())) - .Returns(Task.FromResult( - new HttpResponseMessage(HttpStatusCode.OK) - { - Content = new StringContent("{\"clusterFQDN\": \"resolved.westcentralus.asazure.windows.net\"}") - })); - mockAsAzureHttpClient.Setup(obj => obj.CallGetAsync(It.IsAny(), It.IsAny(), It.IsAny())).Returns( - Task.FromResult( - new HttpResponseMessage(HttpStatusCode.OK) - { - Content = new StringContent("MOCKED STREAM CONTENT") - })); - - var mockTokenCacheItemProvider = new Mock(); - mockTokenCacheItemProvider - .Setup(obj => obj.GetTokenFromTokenCache(It.IsAny(), It.IsAny())) - .Returns(testToken); - - var exportLogCmdlet = new ExportAzureAnalysisServerLog(mockAsAzureHttpClient.Object, mockTokenCacheItemProvider.Object) - { - CommandRuntime = commandRuntimeMock.Object - }; - - var addAmdlet = new AddAzureASAccountCommand() - { - CommandRuntime = commandRuntimeMock.Object - }; - - DoLogin(addAmdlet); - exportLogCmdlet.Instance = testServer; - try - { - exportLogCmdlet.OutputPath = System.IO.Path.GetTempFileName(); - exportLogCmdlet.InvokeBeginProcessing(); - exportLogCmdlet.ExecuteCmdlet(); - exportLogCmdlet.InvokeEndProcessing(); - } - finally - { - if (System.IO.File.Exists(exportLogCmdlet.OutputPath)) - { - System.IO.File.Delete(exportLogCmdlet.OutputPath); - } - } - } - - [Fact] - [Trait(Category.AcceptanceType, Category.CheckIn)] - public void SynchronizeAzureASInstance_SingleDB_Succeeds() - { - Mock commandRuntimeMock = new Mock(); +////// ---------------------------------------------------------------------------------- +////// +////// 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 System; +////using System.Linq; +////using System.Management.Automation; +////using System.Net; +////using System.Net.Http; +////using System.Reflection; +////using System.Security; +////using System.Text; +////using System.Threading.Tasks; +////using Microsoft.Azure.Commands.AnalysisServices.Dataplane; +////using Microsoft.Azure.Commands.AnalysisServices.Dataplane.Models; +////using Microsoft.Azure.Commands.AnalysisServices.Test.ScenarioTests; +////using Microsoft.Azure.ServiceManagement.Common.Models; +////using Microsoft.IdentityModel.Clients.ActiveDirectory; +////using Microsoft.WindowsAzure.Commands.ScenarioTest; +////using Microsoft.WindowsAzure.Commands.Utilities.Common; +////using Moq; +////using Xunit; +////using Xunit.Abstractions; +////using System.Collections.Generic; +////using System.Net.Http.Headers; +////using Newtonsoft.Json; + +////namespace Microsoft.Azure.Commands.AnalysisServices.Test.InMemoryTests +////{ +//// public class DataPlaneCommandTests : AsTestsBase +//// { +//// private const string testAsAzureEnvironment = "westcentralus.asazure.windows.net"; + +//// private const string testServer = "testserver"; + +//// private const string testUser = "testuser@contoso.com"; + +//// private const string testPassword = "testpassword"; + +//// private const string testToken = "eyJ0eXAiOi" +//// + "JKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IjFpOWlmMDllc0YzaU9sS0I2SW9meVVGSUxnQSIsImtpZC" +//// + "I6IjFpOWlmMDllc0YzaU9sS0I2SW9meVVGSUxnQSJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY" +//// + "29yZS53aW5kb3dzLm5ldC8iLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLXBwZS5uZXQvMDQ1NDZiY" +//// + "zAtYmMxOS00Y2I2LWIxNmQtNTc0OTQxNzFhNGJjLyIsImlhdCI6MTQ4MDU1NjY0MywibmJmIjoxNDgwN" +//// + "TU2NjQzLCJleHAiOjE0ODA1NjA1NDMsImFjciI6IjEiLCJhbXIiOlsicHdkIl0sImFwcGlkIjoiMTk1M" +//// + "GEyNTgtMjI3Yi00ZTMxLWE5Y2YtNzE3NDk1OTQ1ZmMyIiwiYXBwaWRhY3IiOiIwIiwiZV9leHAiOjEwO" +//// + "DAwLCJmYW1pbHlfbmFtZSI6IlN1c21hbiIsImdpdmVuX25hbWUiOiJEZXJ5YSIsImdyb3VwcyI6WyI0Y" +//// + "zNmNjNiNy1mZWU1LTQ1ZWItOTAwMy03YWQ1ZDM5MzMzMDIiXSwiaXBhZGRyIjoiMTY3LjIyMC4wLjExM" +//// + "yIsIm5hbWUiOiJEZXJ5YSBTdXNtYW4iLCJvaWQiOiJhODMyOWI5OS01NGI1LTQwNDctOTU5NS1iNWZkN" +//// + "2VhMzgyZjYiLCJwbGF0ZiI6IjMiLCJwdWlkIjoiMTAwMzAwMDA5QUJGRTQyRiIsInNjcCI6InVzZXJfa" +//// + "W1wZXJzb25hdGlvbiIsInN1YiI6ImEyUE5ZZW9KSnk3VnFFVWVkb0ZxS0J6UUNjOWNUN2tCVWtSYm5BM" +//// + "ldLcnciLCJ0aWQiOiIwNDU0NmJjMC1iYzE5LTRjYjYtYjE2ZC01NzQ5NDE3MWE0YmMiLCJ1bmlxdWVfb" +//// + "mFtZSI6ImF6dGVzdDBAc3RhYmxldGVzdC5jY3NjdHAubmV0IiwidXBuIjoiYXp0ZXN0MEBzdGFibGV0Z" +//// + "XN0LmNjc2N0cC5uZXQiLCJ2ZXIiOiIxLjAiLCJ3aWRzIjpbIjYyZTkwMzk0LTY5ZjUtNDIzNy05MTkwL" +//// + "TAxMjE3NzE0NWUxMCJdfQ.W9eVq_TXGBjWCCl_tRGXM31OZn5G4UBIi6B9xZphvrpaAvu5tnzYm6XWah" +//// + "jwA_iE1djOpZM3rxFxP4ZFecVyZGHYVddSJ0rg6vw-L4J5jIPDSojqiGoSLtU8yFxEDRaro0SM4LdQ_N" +//// + "dF-oUwfUQGy88vLOejQdiKzfC-yFvtVSmYoyJSnkZLglDEbhySvLtjXGfpOgiyGLoncV5wTk6Vbf7VLe" +//// + "65kxhZWVUbTHaPuEvg03ZQ3esDb6wxQewJPAL-GARg6S9wIN776Esw8-53AWhzFu0fIut-9FXGma6jV7" +//// + "MYPoUUcFuQzLZgphecPyMPXSVhummVCdBwX9sizxnmFA"; + +//// public DataPlaneCommandTests(ITestOutputHelper output) +//// { +//// XunitTracingInterceptor.AddToContext(new XunitTracingInterceptor(output)); + +//// SynchronizeAzureAzureAnalysisServer.DefaultRetryIntervalForPolling = TimeSpan.FromSeconds(0); +//// } + +//// [Fact] +//// [Trait(Category.AcceptanceType, Category.CheckIn)] +//// public void TestAddAzureASAccountCommand() +//// { +//// Mock commandRuntimeMock = new Mock(); +//// var addAmdlet = new AddAzureASAccountCommand() +//// { +//// CommandRuntime = commandRuntimeMock.Object +//// }; +//// var expectedProfile = new AsAzureProfile +//// { +//// Context = new AsAzureContext( +//// new AsAzureAccount() +//// { +//// Id = testUser, +//// Tenant = null +//// }, +//// new AsAzureEnvironment(testAsAzureEnvironment)) +//// }; +//// expectedProfile.Context.Environment.Endpoints.Add(AsAzureEnvironment.AsRolloutEndpoints.AdAuthorityBaseUrl, AsAzureClientSession.GetAuthorityUrlForEnvironment(expectedProfile.Context.Environment)); +//// expectedProfile.Context.Environment.Endpoints.Add(AsAzureEnvironment.AsRolloutEndpoints.RestartEndpointFormat, AsAzureClientSession.RestartEndpointPathFormat); +//// expectedProfile.Environments.Add(testAsAzureEnvironment, expectedProfile.Context.Environment); +//// expectedProfile.Context.TokenCache = Encoding.ASCII.GetBytes(testToken); + +//// // Setup +//// // Clear the the current profile +//// AsAzureClientSession.Instance.Profile.Environments.Clear(); + +//// var mockAuthenticationProvider = new Mock(); +//// mockAuthenticationProvider.Setup( +//// authProvider => authProvider.GetAadAuthenticatedToken( +//// It.IsAny(), +//// It.IsAny(), +////#if NETSTANDARD +//// It.IsAny>(), +////#else +//// It.IsAny(), +////#endif +//// It.IsAny(), +//// It.IsAny(), +//// It.IsAny())).Returns(testToken); +//// AsAzureClientSession.Instance.SetAsAzureAuthenticationProvider(mockAuthenticationProvider.Object); + +//// addAmdlet.RolloutEnvironment = testAsAzureEnvironment; +//// var password = new SecureString(); +//// var testpwd = testPassword; +//// testpwd.All(c => { +//// password.AppendChar(c); +//// return true; +//// }); +//// addAmdlet.Credential = new PSCredential(testUser, password); +//// commandRuntimeMock.Setup(f => f.ShouldProcess(It.IsAny(), It.IsAny())).Returns(true); +//// commandRuntimeMock.Setup(f => f.WriteObject(expectedProfile)); + +//// // Act +//// addAmdlet.InvokeBeginProcessing(); +//// Assert.Empty(AsAzureClientSession.Instance.Profile.Environments); +//// addAmdlet.ExecuteCmdlet(); +//// Assert.True(AsAzureClientSession.Instance.Profile.Environments.Count == 1); +//// Assert.NotNull(AsAzureClientSession.Instance.Profile.Environments[testAsAzureEnvironment]); + +//// // Call InvokeBeginProcessing again to get coverage. It should use the existing environment in memory not create a new one. +//// addAmdlet.InvokeBeginProcessing(); +//// Assert.True(AsAzureClientSession.Instance.Profile.Environments.Count == 1); +//// Assert.NotNull(AsAzureClientSession.Instance.Profile.Environments[testAsAzureEnvironment]); + +//// addAmdlet.InvokeEndProcessing(); + +//// var environment = (AsAzureEnvironment)AsAzureClientSession.Instance.Profile.Environments[testAsAzureEnvironment]; +//// Assert.Equal(environment.Endpoints[AsAzureEnvironment.AsRolloutEndpoints.AdAuthorityBaseUrl], AsAzureClientSession.GetAuthorityUrlForEnvironment(environment)); +//// Assert.NotNull(environment.Endpoints[AsAzureEnvironment.AsRolloutEndpoints.RestartEndpointFormat]); + +//// commandRuntimeMock.Verify(f => f.WriteObject(AsAzureClientSession.Instance.Profile)); +//// mockAuthenticationProvider.Verify(authProvider => authProvider.GetAadAuthenticatedToken(It.IsAny(), +//// It.IsAny(), +////#if NETSTANDARD +//// It.IsAny>(), +////#else +//// It.IsAny(), +////#endif +//// It.IsAny(), +//// It.IsAny(), +//// It.IsAny()), Times.Once); +//// } + +//// [Fact] +//// [Trait(Category.AcceptanceType, Category.CheckIn)] +//// public void RestartAzureASInstance_Succeeds() +//// { +//// Mock commandRuntimeMock = new Mock(); +//// // Setup +//// // Clear the the current profile +//// AsAzureClientSession.Instance.Profile.Environments.Clear(); +//// var mockAuthenticationProvider = new Mock(); +//// mockAuthenticationProvider.Setup( +//// authProvider => authProvider.GetAadAuthenticatedToken( +//// It.IsAny(), +//// It.IsAny(), +////#if NETSTANDARD +//// It.IsAny>(), +////#else +//// It.IsAny(), +////#endif +//// It.IsAny(), +//// It.IsAny(), +//// It.IsAny())).Returns(testToken); +//// AsAzureClientSession.Instance.SetAsAzureAuthenticationProvider(mockAuthenticationProvider.Object); +//// commandRuntimeMock.Setup(f => f.ShouldProcess(It.IsAny(), It.IsAny())).Returns(true); + +//// // Set up AsAzureHttpClient mock +//// var mockAsAzureHttpClient = new Mock(); +//// mockAsAzureHttpClient +//// .Setup(obj => obj.CallPostAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) +//// .Returns(Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK))); + +//// var mockTokenCacheItemProvider = new Mock(); +//// mockTokenCacheItemProvider +//// .Setup(obj => obj.GetTokenFromTokenCache(It.IsAny(), It.IsAny())) +//// .Returns(testToken); +//// var restartCmdlet = new RestartAzureAnalysisServer(mockAsAzureHttpClient.Object, mockTokenCacheItemProvider.Object) +//// { +//// CommandRuntime = commandRuntimeMock.Object +//// }; + +//// var addAmdlet = new AddAzureASAccountCommand() +//// { +//// CommandRuntime = commandRuntimeMock.Object +//// }; + +//// DoLogin(addAmdlet); +//// restartCmdlet.Instance = testServer; + +//// // Act +//// restartCmdlet.InvokeBeginProcessing(); +//// restartCmdlet.ExecuteCmdlet(); +//// restartCmdlet.InvokeEndProcessing(); +//// } + +//// [Fact] +//// [Trait(Category.AcceptanceType, Category.CheckIn)] +//// public void RestartAzureASInstance_NullInstanceThrows() +//// { +//// Mock commandRuntimeMock = new Mock(); + +//// var mockAsAzureHttpClient = new Mock(); +//// var mockTokenCacheItemProvider = new Mock(); +//// var restartCmdlet = new RestartAzureAnalysisServer(mockAsAzureHttpClient.Object, mockTokenCacheItemProvider.Object) +//// { +//// CommandRuntime = commandRuntimeMock.Object +//// }; + +//// // Setup +//// // Clear the the current profile +//// AsAzureClientSession.Instance.Profile.Environments.Clear(); +//// var mockAuthenticationProvider = new Mock(); +//// mockAuthenticationProvider.Setup( +//// authProvider => authProvider.GetAadAuthenticatedToken( +//// It.IsAny(), +//// It.IsAny(), +////#if NETSTANDARD +//// It.IsAny>(), +////#else +//// It.IsAny(), +////#endif +//// It.IsAny(), +//// It.IsAny(), +//// It.IsAny())).Returns(testToken); +//// AsAzureClientSession.Instance.SetAsAzureAuthenticationProvider(mockAuthenticationProvider.Object); +//// commandRuntimeMock.Setup(f => f.ShouldProcess(It.IsAny(), It.IsAny())).Returns(true); + +//// restartCmdlet.Instance = null; +//// // Act +//// Assert.Throws(() => restartCmdlet.InvokeBeginProcessing()); +//// } + +//// [Fact] +//// [Trait(Category.AcceptanceType, Category.CheckIn)] +//// public void RestartAzureASInstance_NotLoggedInThrows() +//// { +//// Mock commandRuntimeMock = new Mock(); + +//// var mockAsAzureHttpClient = new Mock(); +//// var mockTokenCacheItemProvider = new Mock(); +//// var restartCmdlet = new RestartAzureAnalysisServer(mockAsAzureHttpClient.Object, mockTokenCacheItemProvider.Object) +//// { +//// CommandRuntime = commandRuntimeMock.Object +//// }; + +//// // Setup +//// // Clear the the current profile +//// AsAzureClientSession.Instance.Profile.Environments.Clear(); +//// var mockAuthenticationProvider = new Mock(); +//// mockAuthenticationProvider.Setup( +//// authProvider => authProvider.GetAadAuthenticatedToken( +//// It.IsAny(), +//// It.IsAny(), +////#if NETSTANDARD +//// It.IsAny>(), +////#else +//// It.IsAny(), +////#endif +//// It.IsAny(), +//// It.IsAny(), +//// It.IsAny())).Returns(testToken); +//// AsAzureClientSession.Instance.SetAsAzureAuthenticationProvider(mockAuthenticationProvider.Object); +//// commandRuntimeMock.Setup(f => f.ShouldProcess(It.IsAny(), It.IsAny())).Returns(true); +//// restartCmdlet.Instance = testServer; + +//// // Act +//// try +//// { +//// restartCmdlet.InvokeBeginProcessing(); +//// } +//// catch(Exception ex) +//// { +//// Assert.IsType(ex); +//// } +//// } + +//// [Fact] +//// [Trait(Category.AcceptanceType, Category.CheckIn)] +//// public void ExportAzureASInstanceLogTest() +//// { +//// Mock commandRuntimeMock = new Mock(); +//// // Setup +//// // Clear the the current profile +//// AsAzureClientSession.Instance.Profile.Environments.Clear(); +//// var mockAuthenticationProvider = new Mock(); +//// mockAuthenticationProvider.Setup( +//// authProvider => authProvider.GetAadAuthenticatedToken( +//// It.IsAny(), +//// It.IsAny(), +////#if NETSTANDARD +//// It.IsAny>(), +////#else +//// It.IsAny(), +////#endif +//// It.IsAny(), +//// It.IsAny(), +//// It.IsAny())).Returns(testToken); +//// AsAzureClientSession.Instance.SetAsAzureAuthenticationProvider(mockAuthenticationProvider.Object); +//// commandRuntimeMock.Setup(f => f.ShouldProcess(It.IsAny(), It.IsAny())).Returns(true); + +//// // Set up AsAzureHttpClient mock +//// var mockAsAzureHttpClient = new Mock(); +//// mockAsAzureHttpClient +//// .Setup(obj => obj.CallPostAsync( +//// It.IsAny(), +//// It.Is(s => s.Contains("clusterResolve")), +//// It.IsAny(), +//// It.IsAny())) +//// .Returns(Task.FromResult( +//// new HttpResponseMessage(HttpStatusCode.OK) +//// { +//// Content = new StringContent("{\"clusterFQDN\": \"resolved.westcentralus.asazure.windows.net\"}") +//// })); +//// mockAsAzureHttpClient.Setup(obj => obj.CallGetAsync(It.IsAny(), It.IsAny(), It.IsAny())).Returns( +//// Task.FromResult( +//// new HttpResponseMessage(HttpStatusCode.OK) +//// { +//// Content = new StringContent("MOCKED STREAM CONTENT") +//// })); + +//// var mockTokenCacheItemProvider = new Mock(); +//// mockTokenCacheItemProvider +//// .Setup(obj => obj.GetTokenFromTokenCache(It.IsAny(), It.IsAny())) +//// .Returns(testToken); + +//// var exportLogCmdlet = new ExportAzureAnalysisServerLog(mockAsAzureHttpClient.Object, mockTokenCacheItemProvider.Object) +//// { +//// CommandRuntime = commandRuntimeMock.Object +//// }; + +//// var addAmdlet = new AddAzureASAccountCommand() +//// { +//// CommandRuntime = commandRuntimeMock.Object +//// }; + +//// DoLogin(addAmdlet); +//// exportLogCmdlet.Instance = testServer; +//// try +//// { +//// exportLogCmdlet.OutputPath = System.IO.Path.GetTempFileName(); +//// exportLogCmdlet.InvokeBeginProcessing(); +//// exportLogCmdlet.ExecuteCmdlet(); +//// exportLogCmdlet.InvokeEndProcessing(); +//// } +//// finally +//// { +//// if (System.IO.File.Exists(exportLogCmdlet.OutputPath)) +//// { +//// System.IO.File.Delete(exportLogCmdlet.OutputPath); +//// } +//// } +//// } + +//// [Fact] +//// [Trait(Category.AcceptanceType, Category.CheckIn)] +//// public void SynchronizeAzureASInstance_SingleDB_Succeeds() +//// { +//// Mock commandRuntimeMock = new Mock(); - // Setup - // Clear the the current profile - AsAzureClientSession.Instance.Profile.Environments.Clear(); - var mockAuthenticationProvider = new Mock(); - mockAuthenticationProvider.Setup( - authProvider => authProvider.GetAadAuthenticatedToken( - It.IsAny(), - It.IsAny(), -#if NETSTANDARD - It.IsAny>(), -#else - It.IsAny(), -#endif - It.IsAny(), - It.IsAny(), - It.IsAny())).Returns(testToken); - AsAzureClientSession.Instance.SetAsAzureAuthenticationProvider(mockAuthenticationProvider.Object); - commandRuntimeMock.Setup(f => f.ShouldProcess(It.IsAny(), It.IsAny())).Returns(true); - - // Set up AsAzureHttpClient mock - var mockAsAzureHttpClient = new Mock(); - - // set up cluster resolve respnose - ClusterResolutionResult resolveResult = new ClusterResolutionResult() - { - ClusterFQDN = "resolved.westcentralus.asazure.windows.net", - CoreServerName = testServer + ":rw", - TenantId = Guid.NewGuid().ToString() - }; - mockAsAzureHttpClient - .Setup(obj => obj.CallPostAsync( - It.IsAny(), - It.Is(s => s.Contains("clusterResolve")), - It.IsAny(), - It.IsAny())) - .Returns(Task.FromResult( - new HttpResponseMessage(HttpStatusCode.OK) - { - Content = new StringContent(JsonConvert.SerializeObject(resolveResult)) - })); - - // set up sync respnose - var postResponse = new HttpResponseMessage(HttpStatusCode.Accepted); - postResponse.Headers.Location = new Uri("https://done"); - postResponse.Headers.RetryAfter = new RetryConditionHeaderValue(TimeSpan.FromMilliseconds(500)); - postResponse.Headers.Add("x-ms-root-activity-id", Guid.NewGuid().ToString()); - postResponse.Headers.Add("x-ms-current-utc-date", Guid.NewGuid().ToString()); - mockAsAzureHttpClient - .Setup(obj => obj.CallPostAsync( - It.IsAny(), - It.Is(s => s.Contains("sync")), - It.IsAny(), - It.IsAny(), - null)) - .Returns(Task>.FromResult(postResponse)); - - - var getResponse1 = new HttpResponseMessage(HttpStatusCode.SeeOther); - getResponse1.Headers.Location = new Uri("https://done"); - getResponse1.Headers.RetryAfter = new RetryConditionHeaderValue(TimeSpan.FromMilliseconds(500)); - mockAsAzureHttpClient - .Setup(obj => obj.CallGetAsync( - It.Is(u => u.OriginalString.Contains("1")), - string.Empty, - It.IsAny(), - It.IsAny())) - .Returns(Task.FromResult(getResponse1)); - - var getResponseSucceed = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent( - "{\n\"database\":\"db0\",\n\"syncstate\":\"Completed\"\n}", Encoding.UTF8, "application/json") - }; - - var getResponseError = new HttpResponseMessage(HttpStatusCode.InternalServerError); - - var finalResponses = new Queue(new [] { getResponseError, getResponseSucceed }); - mockAsAzureHttpClient - .Setup(obj => obj.CallGetAsync( - It.Is(u => u.OriginalString.Contains("done")), - string.Empty, - It.IsAny(), - It.IsAny())) - .Returns(() => Task.FromResult(finalResponses.Dequeue())); - - var mockTokenCacheItemProvider = new Mock(); - mockTokenCacheItemProvider - .Setup(obj => obj.GetTokenFromTokenCache(It.IsAny(), It.IsAny())) - .Returns(testToken); - var syncCmdlet = new SynchronizeAzureAzureAnalysisServer(mockAsAzureHttpClient.Object, mockTokenCacheItemProvider.Object) - { - CommandRuntime = commandRuntimeMock.Object - }; - - var addAmdlet = new AddAzureASAccountCommand() - { - CommandRuntime = commandRuntimeMock.Object - }; - - DoLogin(addAmdlet); - syncCmdlet.Instance = testServer + ":rw"; - syncCmdlet.Database = "db0"; - - // Act - syncCmdlet.InvokeBeginProcessing(); - syncCmdlet.ExecuteCmdlet(); - syncCmdlet.InvokeEndProcessing(); - } - - [Fact] - [Trait(Category.AcceptanceType, Category.CheckIn)] - public void SynchronizeAzureASInstance_FailsAfterTooManyRetries() - { - Mock commandRuntimeMock = new Mock(); - - // Setup - // Clear the the current profile - AsAzureClientSession.Instance.Profile.Environments.Clear(); - var mockAuthenticationProvider = new Mock(); - mockAuthenticationProvider.Setup( - authProvider => authProvider.GetAadAuthenticatedToken( - It.IsAny(), - It.IsAny(), -#if NETSTANDARD - It.IsAny>(), -#else - It.IsAny(), -#endif - It.IsAny(), - It.IsAny(), - It.IsAny())).Returns(testToken); - AsAzureClientSession.Instance.SetAsAzureAuthenticationProvider(mockAuthenticationProvider.Object); - commandRuntimeMock.Setup(f => f.ShouldProcess(It.IsAny(), It.IsAny())).Returns(true); - - // Set up AsAzureHttpClient mock - var mockAsAzureHttpClient = new Mock(); - - // set up cluster resolve respnose - ClusterResolutionResult resolveResult = new ClusterResolutionResult() - { - ClusterFQDN = "resolved.westcentralus.asazure.windows.net", - CoreServerName = testServer + ":rw", - TenantId = Guid.NewGuid().ToString() - }; - mockAsAzureHttpClient - .Setup(obj => obj.CallPostAsync( - It.IsAny(), - It.Is(s => s.Contains("clusterResolve")), - It.IsAny(), - It.IsAny())) - .Returns(Task.FromResult( - new HttpResponseMessage(HttpStatusCode.OK) - { - Content = new StringContent(JsonConvert.SerializeObject(resolveResult)) - })); - - // set up sync respnose - var postResponse = new HttpResponseMessage(HttpStatusCode.Accepted); - postResponse.Headers.Location = new Uri("https://1"); - postResponse.Headers.RetryAfter = new RetryConditionHeaderValue(TimeSpan.FromMilliseconds(500)); - postResponse.Headers.Add("x-ms-root-activity-id", Guid.NewGuid().ToString()); - postResponse.Headers.Add("x-ms-current-utc-date", Guid.NewGuid().ToString()); - mockAsAzureHttpClient - .Setup(obj => obj.CallPostAsync( - It.IsAny(), - It.Is(s => s.Contains("sync")), - It.IsAny(), - It.IsAny(), - null)) - .Returns(Task>.FromResult(postResponse)); - - var getResponse1 = new HttpResponseMessage(HttpStatusCode.SeeOther); - getResponse1.Headers.Location = new Uri("https://done"); - getResponse1.Headers.RetryAfter = new RetryConditionHeaderValue(TimeSpan.FromMilliseconds(500)); - getResponse1.Headers.Add("x-ms-root-activity-id", Guid.NewGuid().ToString()); - getResponse1.Headers.Add("x-ms-current-utc-date", Guid.NewGuid().ToString()); - mockAsAzureHttpClient - .Setup(obj => obj.CallGetAsync( - It.Is(u => u.OriginalString.Contains("1")), - It.IsAny(), - It.IsAny(), - It.IsAny())) - .Returns(Task.FromResult(getResponse1)); - - var getResponseSucceed = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent( - "{\n\"database\":\"db0\",\n\"syncstate\":\"Completed\"\n}", Encoding.UTF8, "application/json") - }; - getResponseSucceed.Headers.Add("x-ms-root-activity-id", Guid.NewGuid().ToString()); - getResponseSucceed.Headers.Add("x-ms-current-utc-date", Guid.NewGuid().ToString()); - - var getResponseError = new HttpResponseMessage(HttpStatusCode.InternalServerError); - getResponseError.Headers.Add("x-ms-root-activity-id", Guid.NewGuid().ToString()); - getResponseError.Headers.Add("x-ms-current-utc-date", Guid.NewGuid().ToString()); - - var finalResponses = new Queue(new[] { getResponseError, getResponseError, getResponseError, getResponseSucceed }); - mockAsAzureHttpClient - .Setup(obj => obj.CallGetAsync( - It.Is(u => u.OriginalString.Contains("done")), - It.IsAny(), - It.IsAny(), - It.IsAny())) - .Returns(() => Task.FromResult(finalResponses.Dequeue())); - - var mockTokenCacheItemProvider = new Mock(); - mockTokenCacheItemProvider - .Setup(obj => obj.GetTokenFromTokenCache(It.IsAny(), It.IsAny())) - .Returns(testToken); - var syncCmdlet = new SynchronizeAzureAzureAnalysisServer(mockAsAzureHttpClient.Object, mockTokenCacheItemProvider.Object) - { - CommandRuntime = commandRuntimeMock.Object - }; - - var addAmdlet = new AddAzureASAccountCommand() - { - CommandRuntime = commandRuntimeMock.Object - }; - - DoLogin(addAmdlet); - syncCmdlet.Instance = testServer + ":rw"; - syncCmdlet.Database = "db0"; - - // Act - syncCmdlet.InvokeBeginProcessing(); - Assert.Throws(() => syncCmdlet.ExecuteCmdlet()); - syncCmdlet.InvokeEndProcessing(); - } +//// // Setup +//// // Clear the the current profile +//// AsAzureClientSession.Instance.Profile.Environments.Clear(); +//// var mockAuthenticationProvider = new Mock(); +//// mockAuthenticationProvider.Setup( +//// authProvider => authProvider.GetAadAuthenticatedToken( +//// It.IsAny(), +//// It.IsAny(), +////#if NETSTANDARD +//// It.IsAny>(), +////#else +//// It.IsAny(), +////#endif +//// It.IsAny(), +//// It.IsAny(), +//// It.IsAny())).Returns(testToken); +//// AsAzureClientSession.Instance.SetAsAzureAuthenticationProvider(mockAuthenticationProvider.Object); +//// commandRuntimeMock.Setup(f => f.ShouldProcess(It.IsAny(), It.IsAny())).Returns(true); + +//// // Set up AsAzureHttpClient mock +//// var mockAsAzureHttpClient = new Mock(); + +//// // set up cluster resolve respnose +//// ClusterResolutionResult resolveResult = new ClusterResolutionResult() +//// { +//// ClusterFQDN = "resolved.westcentralus.asazure.windows.net", +//// CoreServerName = testServer + ":rw", +//// TenantId = Guid.NewGuid().ToString() +//// }; +//// mockAsAzureHttpClient +//// .Setup(obj => obj.CallPostAsync( +//// It.IsAny(), +//// It.Is(s => s.Contains("clusterResolve")), +//// It.IsAny(), +//// It.IsAny())) +//// .Returns(Task.FromResult( +//// new HttpResponseMessage(HttpStatusCode.OK) +//// { +//// Content = new StringContent(JsonConvert.SerializeObject(resolveResult)) +//// })); + +//// // set up sync respnose +//// var postResponse = new HttpResponseMessage(HttpStatusCode.Accepted); +//// postResponse.Headers.Location = new Uri("https://done"); +//// postResponse.Headers.RetryAfter = new RetryConditionHeaderValue(TimeSpan.FromMilliseconds(500)); +//// postResponse.Headers.Add("x-ms-root-activity-id", Guid.NewGuid().ToString()); +//// postResponse.Headers.Add("x-ms-current-utc-date", Guid.NewGuid().ToString()); +//// mockAsAzureHttpClient +//// .Setup(obj => obj.CallPostAsync( +//// It.IsAny(), +//// It.Is(s => s.Contains("sync")), +//// It.IsAny(), +//// It.IsAny(), +//// null)) +//// .Returns(Task>.FromResult(postResponse)); + + +//// var getResponse1 = new HttpResponseMessage(HttpStatusCode.SeeOther); +//// getResponse1.Headers.Location = new Uri("https://done"); +//// getResponse1.Headers.RetryAfter = new RetryConditionHeaderValue(TimeSpan.FromMilliseconds(500)); +//// mockAsAzureHttpClient +//// .Setup(obj => obj.CallGetAsync( +//// It.Is(u => u.OriginalString.Contains("1")), +//// string.Empty, +//// It.IsAny(), +//// It.IsAny())) +//// .Returns(Task.FromResult(getResponse1)); + +//// var getResponseSucceed = new HttpResponseMessage +//// { +//// StatusCode = HttpStatusCode.OK, +//// Content = new StringContent( +//// "{\n\"database\":\"db0\",\n\"syncstate\":\"Completed\"\n}", Encoding.UTF8, "application/json") +//// }; + +//// var getResponseError = new HttpResponseMessage(HttpStatusCode.InternalServerError); + +//// var finalResponses = new Queue(new [] { getResponseError, getResponseSucceed }); +//// mockAsAzureHttpClient +//// .Setup(obj => obj.CallGetAsync( +//// It.Is(u => u.OriginalString.Contains("done")), +//// string.Empty, +//// It.IsAny(), +//// It.IsAny())) +//// .Returns(() => Task.FromResult(finalResponses.Dequeue())); + +//// var mockTokenCacheItemProvider = new Mock(); +//// mockTokenCacheItemProvider +//// .Setup(obj => obj.GetTokenFromTokenCache(It.IsAny(), It.IsAny())) +//// .Returns(testToken); +//// var syncCmdlet = new SynchronizeAzureAzureAnalysisServer(mockAsAzureHttpClient.Object, mockTokenCacheItemProvider.Object) +//// { +//// CommandRuntime = commandRuntimeMock.Object +//// }; + +//// var addAmdlet = new AddAzureASAccountCommand() +//// { +//// CommandRuntime = commandRuntimeMock.Object +//// }; + +//// DoLogin(addAmdlet); +//// syncCmdlet.Instance = testServer + ":rw"; +//// syncCmdlet.Database = "db0"; + +//// // Act +//// syncCmdlet.InvokeBeginProcessing(); +//// syncCmdlet.ExecuteCmdlet(); +//// syncCmdlet.InvokeEndProcessing(); +//// } + +//// [Fact] +//// [Trait(Category.AcceptanceType, Category.CheckIn)] +//// public void SynchronizeAzureASInstance_FailsAfterTooManyRetries() +//// { +//// Mock commandRuntimeMock = new Mock(); + +//// // Setup +//// // Clear the the current profile +//// AsAzureClientSession.Instance.Profile.Environments.Clear(); +//// var mockAuthenticationProvider = new Mock(); +//// mockAuthenticationProvider.Setup( +//// authProvider => authProvider.GetAadAuthenticatedToken( +//// It.IsAny(), +//// It.IsAny(), +////#if NETSTANDARD +//// It.IsAny>(), +////#else +//// It.IsAny(), +////#endif +//// It.IsAny(), +//// It.IsAny(), +//// It.IsAny())).Returns(testToken); +//// AsAzureClientSession.Instance.SetAsAzureAuthenticationProvider(mockAuthenticationProvider.Object); +//// commandRuntimeMock.Setup(f => f.ShouldProcess(It.IsAny(), It.IsAny())).Returns(true); + +//// // Set up AsAzureHttpClient mock +//// var mockAsAzureHttpClient = new Mock(); + +//// // set up cluster resolve respnose +//// ClusterResolutionResult resolveResult = new ClusterResolutionResult() +//// { +//// ClusterFQDN = "resolved.westcentralus.asazure.windows.net", +//// CoreServerName = testServer + ":rw", +//// TenantId = Guid.NewGuid().ToString() +//// }; +//// mockAsAzureHttpClient +//// .Setup(obj => obj.CallPostAsync( +//// It.IsAny(), +//// It.Is(s => s.Contains("clusterResolve")), +//// It.IsAny(), +//// It.IsAny())) +//// .Returns(Task.FromResult( +//// new HttpResponseMessage(HttpStatusCode.OK) +//// { +//// Content = new StringContent(JsonConvert.SerializeObject(resolveResult)) +//// })); + +//// // set up sync respnose +//// var postResponse = new HttpResponseMessage(HttpStatusCode.Accepted); +//// postResponse.Headers.Location = new Uri("https://1"); +//// postResponse.Headers.RetryAfter = new RetryConditionHeaderValue(TimeSpan.FromMilliseconds(500)); +//// postResponse.Headers.Add("x-ms-root-activity-id", Guid.NewGuid().ToString()); +//// postResponse.Headers.Add("x-ms-current-utc-date", Guid.NewGuid().ToString()); +//// mockAsAzureHttpClient +//// .Setup(obj => obj.CallPostAsync( +//// It.IsAny(), +//// It.Is(s => s.Contains("sync")), +//// It.IsAny(), +//// It.IsAny(), +//// null)) +//// .Returns(Task>.FromResult(postResponse)); + +//// var getResponse1 = new HttpResponseMessage(HttpStatusCode.SeeOther); +//// getResponse1.Headers.Location = new Uri("https://done"); +//// getResponse1.Headers.RetryAfter = new RetryConditionHeaderValue(TimeSpan.FromMilliseconds(500)); +//// getResponse1.Headers.Add("x-ms-root-activity-id", Guid.NewGuid().ToString()); +//// getResponse1.Headers.Add("x-ms-current-utc-date", Guid.NewGuid().ToString()); +//// mockAsAzureHttpClient +//// .Setup(obj => obj.CallGetAsync( +//// It.Is(u => u.OriginalString.Contains("1")), +//// It.IsAny(), +//// It.IsAny(), +//// It.IsAny())) +//// .Returns(Task.FromResult(getResponse1)); + +//// var getResponseSucceed = new HttpResponseMessage +//// { +//// StatusCode = HttpStatusCode.OK, +//// Content = new StringContent( +//// "{\n\"database\":\"db0\",\n\"syncstate\":\"Completed\"\n}", Encoding.UTF8, "application/json") +//// }; +//// getResponseSucceed.Headers.Add("x-ms-root-activity-id", Guid.NewGuid().ToString()); +//// getResponseSucceed.Headers.Add("x-ms-current-utc-date", Guid.NewGuid().ToString()); + +//// var getResponseError = new HttpResponseMessage(HttpStatusCode.InternalServerError); +//// getResponseError.Headers.Add("x-ms-root-activity-id", Guid.NewGuid().ToString()); +//// getResponseError.Headers.Add("x-ms-current-utc-date", Guid.NewGuid().ToString()); + +//// var finalResponses = new Queue(new[] { getResponseError, getResponseError, getResponseError, getResponseSucceed }); +//// mockAsAzureHttpClient +//// .Setup(obj => obj.CallGetAsync( +//// It.Is(u => u.OriginalString.Contains("done")), +//// It.IsAny(), +//// It.IsAny(), +//// It.IsAny())) +//// .Returns(() => Task.FromResult(finalResponses.Dequeue())); + +//// var mockTokenCacheItemProvider = new Mock(); +//// mockTokenCacheItemProvider +//// .Setup(obj => obj.GetTokenFromTokenCache(It.IsAny(), It.IsAny())) +//// .Returns(testToken); +//// var syncCmdlet = new SynchronizeAzureAzureAnalysisServer(mockAsAzureHttpClient.Object, mockTokenCacheItemProvider.Object) +//// { +//// CommandRuntime = commandRuntimeMock.Object +//// }; + +//// var addAmdlet = new AddAzureASAccountCommand() +//// { +//// CommandRuntime = commandRuntimeMock.Object +//// }; + +//// DoLogin(addAmdlet); +//// syncCmdlet.Instance = testServer + ":rw"; +//// syncCmdlet.Database = "db0"; + +//// // Act +//// syncCmdlet.InvokeBeginProcessing(); +//// Assert.Throws(() => syncCmdlet.ExecuteCmdlet()); +//// syncCmdlet.InvokeEndProcessing(); +//// } - private void DoLogin(AddAzureASAccountCommand addCmdlet) - { - Mock commandRuntimeMock = new Mock(); - - addCmdlet.RolloutEnvironment = testAsAzureEnvironment; - var password = new SecureString(); - var testpwd = testPassword; - testpwd.All(c => { - password.AppendChar(c); - return true; - }); - addCmdlet.Credential = new PSCredential(testUser, password); - commandRuntimeMock.Setup(f => f.ShouldProcess(It.IsAny(), It.IsAny())).Returns(true); - - // Act - addCmdlet.InvokeBeginProcessing(); - addCmdlet.ExecuteCmdlet(); - AsAzureClientSession.TokenCache.Deserialize(Encoding.ASCII.GetBytes(testToken)); - addCmdlet.InvokeEndProcessing(); - } - } -} +//// private void DoLogin(AddAzureASAccountCommand addCmdlet) +//// { +//// Mock commandRuntimeMock = new Mock(); + +//// addCmdlet.RolloutEnvironment = testAsAzureEnvironment; +//// var password = new SecureString(); +//// var testpwd = testPassword; +//// testpwd.All(c => { +//// password.AppendChar(c); +//// return true; +//// }); +//// addCmdlet.Credential = new PSCredential(testUser, password); +//// commandRuntimeMock.Setup(f => f.ShouldProcess(It.IsAny(), It.IsAny())).Returns(true); + +//// // Act +//// addCmdlet.InvokeBeginProcessing(); +//// addCmdlet.ExecuteCmdlet(); +//// AsAzureClientSession.TokenCache.Deserialize(Encoding.ASCII.GetBytes(testToken)); +//// addCmdlet.InvokeEndProcessing(); +//// } +//// } +////} From 401ac09d0ca4803446c659efbd88966e605fe008 Mon Sep 17 00:00:00 2001 From: Gabriel Prestemon Date: Tue, 8 Jan 2019 15:57:57 -0800 Subject: [PATCH 002/141] Change export log file endpoint. --- .../Models/AsAzureEndpoints.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureEndpoints.cs b/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureEndpoints.cs index 61cad1c83501..4ff0e3960273 100644 --- a/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureEndpoints.cs +++ b/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureEndpoints.cs @@ -20,7 +20,7 @@ namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane.Models class AsAzureEndpoints { public const string RestartEndpointPathFormat = "/webapi/servers/{0}/restart?api-version=2016-10-01"; - public const string LogfileEndpointPathFormat = "/webapi/servers/{0}/logfileHere"; + public const string LogfileEndpointPathFormat = "/webapi/servers/{0}/logfile"; public const string SynchronizeEndpointPathFormat = "/servers/{0}/models/{1}/sync"; public const string ClusterResolveEndpoint = "/webapi/clusterResolve"; From 7b00a57873f5f16bf4da75343fdc3fd388846400 Mon Sep 17 00:00:00 2001 From: Gabriel Prestemon Date: Tue, 8 Jan 2019 17:07:24 -0800 Subject: [PATCH 003/141] Merge branch 'master' into gapreste/use-new-az-module-credentials -pt2 resolving conflicts # Conflicts: # src/AnalysisServices/AnalysisServices.Dataplane/Commands/AddAzureASAccount.cs # src/AnalysisServices/AnalysisServices.Dataplane/Models/ASAzureContext.cs # src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureAccount.cs # src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureAuthenticationProvider.cs # src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureClientSession.cs # src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureEndpoints.cs # src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureProfile.cs # src/AnalysisServices/AnalysisServices.Test/InMemoryTests/AddAzureASAccountTests.cs # src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureAccount.cs --- .../Models/AsAzureDataplaneClient.cs | 0 .../Models/AsAzureDataplaneCmdletBase.cs | 0 .../Models/AsAzureEndpoints.cs | 0 .../Models/AsAzureEnvironment.cs | 42 ------------------- 4 files changed, 42 deletions(-) rename src/{ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane => AnalysisServices/AnalysisServices.Dataplane}/Models/AsAzureDataplaneClient.cs (100%) rename src/{ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane => AnalysisServices/AnalysisServices.Dataplane}/Models/AsAzureDataplaneCmdletBase.cs (100%) rename src/{ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane => AnalysisServices/AnalysisServices.Dataplane}/Models/AsAzureEndpoints.cs (100%) delete mode 100644 src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureEnvironment.cs diff --git a/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureDataplaneClient.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneClient.cs similarity index 100% rename from src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureDataplaneClient.cs rename to src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneClient.cs diff --git a/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs similarity index 100% rename from src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs rename to src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs diff --git a/src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureEndpoints.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureEndpoints.cs similarity index 100% rename from src/ResourceManager/AnalysisServices/Commands.AnalysisServices.Dataplane/Models/AsAzureEndpoints.cs rename to src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureEndpoints.cs diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureEnvironment.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureEnvironment.cs deleted file mode 100644 index 8c0bfd3646e6..000000000000 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureEnvironment.cs +++ /dev/null @@ -1,42 +0,0 @@ -// ---------------------------------------------------------------------------------- -// -// 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 System; -using System.Collections; -using System.Collections.Generic; - -namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane -{ - [Serializable] - public class AsAzureEnvironment - { - public AsAzureEnvironment(string Name) - { - this.Name = Name; - this.Endpoints = new Hashtable(); - } - - public string Name { get; set; } - - public Hashtable Endpoints { get; set; } - - public enum AsRolloutEndpoints - { - AdAuthorityBaseUrl, - RestartEndpointFormat, - LogfileEndpointFormat, - SyncEndpoint - } - } -} From a82b902e9a88212bae35f8edc243a2149c5e1112 Mon Sep 17 00:00:00 2001 From: Gabriel Prestemon Date: Wed, 9 Jan 2019 12:24:31 -0800 Subject: [PATCH 004/141] Move Instance field to dataplane cmdlet base. Remove unnecessary BeginProcessing() methods in child classes. --- .../Commands/Export-AzureAsInstanceLog.cs | 10 ---------- .../Commands/Restart-AzureAsInstance.cs | 11 ----------- .../Commands/Synchronize-AzureASInstance.cs | 9 --------- .../Models/AsAzureDataplaneCmdletBase.cs | 12 +++++++++--- 4 files changed, 9 insertions(+), 33 deletions(-) diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Export-AzureAsInstanceLog.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Export-AzureAsInstanceLog.cs index 2c9b7ab58391..46e62c538771 100644 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Export-AzureAsInstanceLog.cs +++ b/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Export-AzureAsInstanceLog.cs @@ -30,10 +30,6 @@ namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane [OutputType(typeof(void))] public class ExportAzureAnalysisServerLog : AsAzureDataplaneCmdletBase { - [Parameter(Mandatory = true, HelpMessage = "Name of the Azure Analysis Services which log will be fetched")] - [ValidateNotNullOrEmpty] - public string Instance { get; set; } - [Parameter(Mandatory = true, HelpMessage = "Path to file to write Azure Analysis Services log")] [ValidateNotNullOrEmpty] public string OutputPath { get; set; } @@ -63,12 +59,6 @@ protected override string DataCollectionWarning } } - protected override void BeginProcessing() - { - base.BeginProcessing(); - this.CommonBeginProcessing(Instance); - } - protected override void InitializeQosEvent() { // nothing to do here. diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Restart-AzureAsInstance.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Restart-AzureAsInstance.cs index 3e96751016e7..d8fde4191680 100644 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Restart-AzureAsInstance.cs +++ b/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Restart-AzureAsInstance.cs @@ -27,11 +27,6 @@ namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane [OutputType(typeof(bool))] public class RestartAzureAnalysisServer : AsAzureDataplaneCmdletBase { - - [Parameter(Mandatory = true, HelpMessage = "Name of the Azure Analysis Services server to restart")] - [ValidateNotNullOrEmpty] - public string Instance { get; set; } - [Parameter(Mandatory = false)] public SwitchParameter PassThru { get; set; } @@ -56,12 +51,6 @@ protected override string DataCollectionWarning } } - protected override void BeginProcessing() - { - base.BeginProcessing(); - this.CommonBeginProcessing(Instance); - } - protected override void InitializeQosEvent() { // nothing to do here. diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Synchronize-AzureASInstance.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Synchronize-AzureASInstance.cs index af2edd725c08..6c1d58fe294a 100644 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Synchronize-AzureASInstance.cs +++ b/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Synchronize-AzureASInstance.cs @@ -51,14 +51,6 @@ public class SynchronizeAzureAzureAnalysisServer : AsAzureDataplaneCmdletBase private string syncRequestTimeStamp; - [Parameter( - Mandatory = true, - HelpMessage = "Name of the Azure Analysis Services server to synchronize. E.x. asazure://westus.asazure.windows.net/contososerver:rw", - Position = 0, - ValueFromPipeline = true)] - [ValidateNotNullOrEmpty] - public string Instance { get; set; } - [Parameter( Mandatory = true, HelpMessage = "Identity of the database need to be synchronized", @@ -98,7 +90,6 @@ protected override void BeginProcessing() { this._dataCollectionProfile = new AzurePSDataCollectionProfile(false); base.BeginProcessing(); - this.CommonBeginProcessing(Instance); } protected override void SetupDebuggingTraces() diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs index 021273a89a6d..6bf4a7318185 100644 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs +++ b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs @@ -33,6 +33,10 @@ public abstract class AsAzureDataplaneCmdletBase : AzurePSCmdlet private IAzureContext _currentContext; + [Parameter(Mandatory = true, HelpMessage = "Name of the Azure Analysis Services server")] + [ValidateNotNullOrEmpty] + public string Instance { get; set; } + /// /// The fully qualified absolute URI of the server instance. /// (scheme.region.azureAsEndpoint/serverName) @@ -92,12 +96,14 @@ public AsAzureDataplaneClient AsAzureDataplaneClient set { _asAzureDataplaneClient = value; } } - protected void CommonBeginProcessing(string instance) + protected override void BeginProcessing() { + base.BeginProcessing(); + // user must specify the fully qualified server name. For example, westus2.asazure.windows.net/testserver - if (!Uri.TryCreate(instance, UriKind.Absolute, out var uriResult) || uriResult.Scheme != AsAzureEndpoints.UriSchemeAsAzure) + if (!Uri.TryCreate(Instance, UriKind.Absolute, out var uriResult) || uriResult.Scheme != AsAzureEndpoints.UriSchemeAsAzure) { - throw new PSInvalidOperationException(string.Format(Properties.Resources.InvalidServerName, instance)); + throw new PSInvalidOperationException(string.Format(Properties.Resources.InvalidServerName, Instance)); } // derive all bits of the url from the input From d9e25d588aec391ab4a2d6c7ac62da5b023b8426 Mon Sep 17 00:00:00 2001 From: Gabriel Prestemon Date: Wed, 9 Jan 2019 12:33:41 -0800 Subject: [PATCH 005/141] Remove unnecessary implementation of IAsAzureHttpClient --- .../Models/AsAzureHttpClient.cs | 112 ------------------ .../Models/IAsAzureHttpClient.cs | 35 ++++++ 2 files changed, 35 insertions(+), 112 deletions(-) delete mode 100644 src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureHttpClient.cs create mode 100644 src/AnalysisServices/AnalysisServices.Dataplane/Models/IAsAzureHttpClient.cs diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureHttpClient.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureHttpClient.cs deleted file mode 100644 index d95f950ac74a..000000000000 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureHttpClient.cs +++ /dev/null @@ -1,112 +0,0 @@ -// ---------------------------------------------------------------------------------- -// -// 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 System; -using System.Collections.Generic; -using System.Linq; -using System.Management.Automation; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Text; -using System.Threading.Tasks; -using Microsoft.Azure.Commands.AnalysisServices.Dataplane.Properties; - -namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane.Models -{ - public interface IAsAzureHttpClient - { - HttpClient HttpClient { get; set; } - - Task CallPostAsync(Uri baseURI, string requestURL, string accessToken, HttpContent content = null); - - Task CallPostAsync(Uri baseURI, string requestURL, string accessToken, Guid correlationId, HttpContent content = null); - - Task CallGetAsync(Uri baseURI, string requestURL, string accessToken); - - Task CallGetAsync(Uri baseURI, string requestURL, string accessToken, Guid correlationId); - - void resetHttpClient(); - } - - public class AsAzureHttpClient : IAsAzureHttpClient - { - public const string ParentActivityId = "x-ms-parent-activity-id"; - - public HttpClient HttpClient { get; set; } - - private Func HttpClientProvider { get; set; } - - public AsAzureHttpClient(Func httpClientProvider) - { - this.HttpClientProvider = httpClientProvider; - this.HttpClient = this.HttpClientProvider(); - } - - public async Task CallGetAsync(Uri baseURI, string requestURL, string accessToken) - { - return await CallGetAsync(baseURI, requestURL, accessToken, new Guid()); - } - - public async Task CallGetAsync(Uri baseURI, string requestURL, string accessToken, Guid correlationId) - { - return await CallAsync(HttpMethod.Get, baseURI, requestURL, accessToken, correlationId); - } - - public async Task CallPostAsync(Uri baseURI, string requestURL, string accessToken, HttpContent content = null) - { - return await CallPostAsync(baseURI, requestURL, accessToken, new Guid(), content); - } - - public async Task CallPostAsync(Uri baseURI, string requestURL, string accessToken, Guid correlationId, HttpContent content = null) - { - return await CallAsync(HttpMethod.Post, baseURI, requestURL, accessToken, correlationId, content); - } - - public void resetHttpClient() - { - this.HttpClient = this.HttpClientProvider(); - } - - private async Task CallAsync(HttpMethod method, Uri baseURI, string requestURL, string accessToken, Guid correlationId, HttpContent content = null) - { - using (HttpClient) - { - if (accessToken == null) - { - throw new PSArgumentNullException("accessToken", string.Format(Resources.NotLoggedInMessage, "")); - } - HttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); - - if (correlationId == null || correlationId == Guid.Empty) - { - correlationId = new Guid(); - } - - HttpClient.DefaultRequestHeaders.Add(ParentActivityId, new List() { correlationId.ToString() }); - - HttpClient.BaseAddress = baseURI; - if (method == HttpMethod.Get) - { - return await HttpClient.GetAsync(requestURL); - } - - if (content == null) - { - content = new StringContent(""); - } - return await HttpClient.PostAsync(requestURL, content); - } - } - } -} diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Models/IAsAzureHttpClient.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Models/IAsAzureHttpClient.cs new file mode 100644 index 000000000000..93b27b9b63d0 --- /dev/null +++ b/src/AnalysisServices/AnalysisServices.Dataplane/Models/IAsAzureHttpClient.cs @@ -0,0 +1,35 @@ +// ---------------------------------------------------------------------------------- +// +// 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 System; +using System.Net.Http; +using System.Threading.Tasks; + +namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane.Models +{ + public interface IAsAzureHttpClient + { + HttpClient HttpClient { get; set; } + + Task CallPostAsync(Uri baseURI, string requestURL, string accessToken, HttpContent content = null); + + Task CallPostAsync(Uri baseURI, string requestURL, string accessToken, Guid correlationId, HttpContent content = null); + + Task CallGetAsync(Uri baseURI, string requestURL, string accessToken); + + Task CallGetAsync(Uri baseURI, string requestURL, string accessToken, Guid correlationId); + + void resetHttpClient(); + } +} From 817691caefdc87d0b85d9d937f9cbd95f5ee8a6f Mon Sep 17 00:00:00 2001 From: Gabriel Prestemon Date: Thu, 10 Jan 2019 10:08:42 -0800 Subject: [PATCH 006/141] Removed 'partial' keyword and related documentation because this is no longer a partial class. Changed organizational #region name to include CallGet and CallPost method overloads. Remove unused code in SendRequestAsync(). --- .../Models/AsAzureDataplaneClient.cs | 32 ++++--------------- 1 file changed, 7 insertions(+), 25 deletions(-) diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneClient.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneClient.cs index e1c6931be189..c417535d043d 100644 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneClient.cs +++ b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneClient.cs @@ -22,11 +22,9 @@ namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane.Models { /// - /// Contains properties and logic for . - /// All permutations of CallGetAsync, and CallPostAsync are in the partial class in order to make this partial class more readable. + /// Provides methods for sending HTTP requests and receiving HTTP responses from a resource identified by a URI. /// - /// Most modifications will likely be in this part of the class. - public partial class AsAzureDataplaneClient : ServiceClient, IAsAzureHttpClient + public class AsAzureDataplaneClient : ServiceClient, IAsAzureHttpClient { /// /// The base Uri of the service. @@ -43,7 +41,8 @@ public partial class AsAzureDataplaneClient : ServiceClient httpClientProvider, params DelegatingHandler[] handlers) : base(handlers) + public AsAzureDataplaneClient(Uri baseUri, ServiceClientCredentials credentials, Func httpClientProvider, params DelegatingHandler[] handlers) + : base(handlers) { this.BaseUri = baseUri ?? throw new ArgumentNullException(nameof(baseUri)); this.Credentials = credentials ?? throw new ArgumentNullException(nameof(credentials)); @@ -52,7 +51,8 @@ public AsAzureDataplaneClient(Uri baseUri, ServiceClientCredentials credentials, this.resetHttpClient(); } - public AsAzureDataplaneClient(Uri baseUri, ServiceClientCredentials credentials, Func httpClientProvider, HttpClientHandler rootHandler, params DelegatingHandler[] handlers) : base(rootHandler, handlers) + public AsAzureDataplaneClient(Uri baseUri, ServiceClientCredentials credentials, Func httpClientProvider, HttpClientHandler rootHandler, params DelegatingHandler[] handlers) + : base(rootHandler, handlers) { this.BaseUri = baseUri ?? throw new ArgumentNullException(nameof(baseUri)); this.Credentials = credentials ?? throw new ArgumentNullException(nameof(credentials)); @@ -66,7 +66,7 @@ public void resetHttpClient() this.HttpClient = this.HttpClientProvider(); } - #region GetMethodAsyncOverloads + #region CallHttpMethodAsyncOverloads /// /// Calls SendRequestAsync() for a GET using a blank correlationId. @@ -174,9 +174,6 @@ private async Task SendRequestAsync( HttpContent content = null, CancellationToken cancellationToken = default(CancellationToken)) { - // Construct URL - ////List queryParameters = new List(); - // Create HTTP transport objects HttpRequestMessage httpRequest = new HttpRequestMessage() { @@ -188,21 +185,6 @@ private async Task SendRequestAsync( // Set Headers AddHeader(httpRequest.Headers, "x-ms-client-request-id", correlationId.ToString()); - // TODO: Where is this flag located? - ////if (this.Client.AcceptLanguage != null) - ////{ - //// AddHeader(httpRequest.Headers, "accept-language", this.Client.AcceptLanguage); - ////} - - // TODO: Where are the custom headers coming from? - ////if (customHeaders != null) - ////{ - //// foreach (var header in customHeaders) - //// { - //// AddHeader(httpRequest.Headers, header.Key, header.Value); - //// } - ////} - // Set Credentials if (Credentials != null) { From 5303dd4c8fb1c2108c88c6e930926a1bf7a02c8c Mon Sep 17 00:00:00 2001 From: Gabriel Prestemon Date: Thu, 10 Jan 2019 10:50:46 -0800 Subject: [PATCH 007/141] Remove unneccessary constructors from cmdlet classes. Add null check for Instance field. --- .../Commands/Export-AzureAsInstanceLog.cs | 4 ---- .../Commands/Restart-AzureAsInstance.cs | 4 ---- .../Models/AsAzureDataplaneCmdletBase.cs | 5 +++++ 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Export-AzureAsInstanceLog.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Export-AzureAsInstanceLog.cs index 46e62c538771..f7cd56538eaf 100644 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Export-AzureAsInstanceLog.cs +++ b/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Export-AzureAsInstanceLog.cs @@ -38,10 +38,6 @@ public class ExportAzureAnalysisServerLog : AsAzureDataplaneCmdletBase [ValidateNotNullOrEmpty] public SwitchParameter Force { get; set; } - public ExportAzureAnalysisServerLog() - { - } - protected override IAzureContext DefaultContext { get diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Restart-AzureAsInstance.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Restart-AzureAsInstance.cs index d8fde4191680..a85aaa727388 100644 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Restart-AzureAsInstance.cs +++ b/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Restart-AzureAsInstance.cs @@ -30,10 +30,6 @@ public class RestartAzureAnalysisServer : AsAzureDataplaneCmdletBase [Parameter(Mandatory = false)] public SwitchParameter PassThru { get; set; } - public RestartAzureAnalysisServer() - { - } - protected override IAzureContext DefaultContext { get diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs index 6bf4a7318185..3e38f0d1751d 100644 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs +++ b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs @@ -100,6 +100,11 @@ protected override void BeginProcessing() { base.BeginProcessing(); + if (string.IsNullOrEmpty(Instance)) + { + throw new ArgumentNullException(nameof(Instance)); + } + // user must specify the fully qualified server name. For example, westus2.asazure.windows.net/testserver if (!Uri.TryCreate(Instance, UriKind.Absolute, out var uriResult) || uriResult.Scheme != AsAzureEndpoints.UriSchemeAsAzure) { From 9709ffac527c8fc04ca1e5560ed29d7dbb9b5d8c Mon Sep 17 00:00:00 2001 From: Gabriel Prestemon Date: Thu, 10 Jan 2019 11:01:18 -0800 Subject: [PATCH 008/141] Move common code in cmdlet classes to base class. --- .../Commands/Export-AzureAsInstanceLog.cs | 24 ----------------- .../Commands/Restart-AzureAsInstance.cs | 26 ------------------- .../Commands/Synchronize-AzureASInstance.cs | 24 ----------------- .../Models/AsAzureDataplaneCmdletBase.cs | 22 +++++++++++++--- 4 files changed, 19 insertions(+), 77 deletions(-) diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Export-AzureAsInstanceLog.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Export-AzureAsInstanceLog.cs index f7cd56538eaf..7430b4dffc95 100644 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Export-AzureAsInstanceLog.cs +++ b/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Export-AzureAsInstanceLog.cs @@ -12,13 +12,11 @@ // limitations under the License. // ---------------------------------------------------------------------------------- -using System; using System.Globalization; using System.Management.Automation; using Microsoft.Azure.Commands.Common.Authentication; using Microsoft.Azure.Commands.AnalysisServices.Dataplane.Models; using Microsoft.Azure.Commands.AnalysisServices.Dataplane.Properties; -using Microsoft.Azure.Commands.Common.Authentication.Abstractions; namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane { @@ -38,28 +36,6 @@ public class ExportAzureAnalysisServerLog : AsAzureDataplaneCmdletBase [ValidateNotNullOrEmpty] public SwitchParameter Force { get; set; } - protected override IAzureContext DefaultContext - { - get - { - // Nothing to do with Azure Resource Management context - return null; - } - } - - protected override string DataCollectionWarning - { - get - { - return Resources.ARMDataCollectionMessage; - } - } - - protected override void InitializeQosEvent() - { - // nothing to do here. - } - public override void ExecuteCmdlet() { if (!ShouldProcess(Instance, Resources.ExportingLogFromAnalysisServicesServer)) diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Restart-AzureAsInstance.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Restart-AzureAsInstance.cs index a85aaa727388..195c970302df 100644 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Restart-AzureAsInstance.cs +++ b/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Restart-AzureAsInstance.cs @@ -15,7 +15,6 @@ using System.Management.Automation; using Microsoft.Azure.Commands.AnalysisServices.Dataplane.Models; using Microsoft.Azure.Commands.AnalysisServices.Dataplane.Properties; -using Microsoft.Azure.Commands.Common.Authentication.Abstractions; namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane { @@ -27,31 +26,6 @@ namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane [OutputType(typeof(bool))] public class RestartAzureAnalysisServer : AsAzureDataplaneCmdletBase { - [Parameter(Mandatory = false)] - public SwitchParameter PassThru { get; set; } - - protected override IAzureContext DefaultContext - { - get - { - // Nothing to do with Azure Resource Management context - return null; - } - } - - protected override string DataCollectionWarning - { - get - { - return Resources.ARMDataCollectionMessage; - } - } - - protected override void InitializeQosEvent() - { - // nothing to do here. - } - public override void ExecuteCmdlet() { if (!ShouldProcess(Instance, Resources.RestartingAnalysisServicesServer)) diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Synchronize-AzureASInstance.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Synchronize-AzureASInstance.cs index 6c1d58fe294a..67ea5f03ddd0 100644 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Synchronize-AzureASInstance.cs +++ b/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Synchronize-AzureASInstance.cs @@ -59,9 +59,6 @@ public class SynchronizeAzureAzureAnalysisServer : AsAzureDataplaneCmdletBase [ValidateNotNullOrEmpty] public string Database { get; set; } - [Parameter(Mandatory = false)] - public SwitchParameter PassThru { get; set; } - public SynchronizeAzureAzureAnalysisServer() { this.syncRequestRootActivityId = string.Empty; @@ -69,23 +66,6 @@ public SynchronizeAzureAzureAnalysisServer() this.syncRequestTimeStamp = string.Empty; } - protected override IAzureContext DefaultContext - { - get - { - // Nothing to do with Azure Resource Management context - return null; - } - } - - protected override string DataCollectionWarning - { - get - { - return Resources.ARMDataCollectionMessage; - } - } - protected override void BeginProcessing() { this._dataCollectionProfile = new AzurePSDataCollectionProfile(false); @@ -111,10 +91,6 @@ protected override void TearDownHttpClientPipeline() { // nothing to do here. } - protected override void InitializeQosEvent() - { - // No data collection for this commandlet - } public override void ExecuteCmdlet() { diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs index 3e38f0d1751d..be7c90a07f43 100644 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs +++ b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs @@ -12,9 +12,9 @@ // limitations under the License. // ---------------------------------------------------------------------------------- +using Microsoft.Azure.Commands.AnalysisServices.Dataplane.Properties; using Microsoft.Azure.Commands.Common.Authentication; using Microsoft.Azure.Commands.Common.Authentication.Abstractions; -using Microsoft.Azure.Commands.Common.Authentication.Properties; using Microsoft.WindowsAzure.Commands.Utilities.Common; using Newtonsoft.Json; using System; @@ -37,6 +37,9 @@ public abstract class AsAzureDataplaneCmdletBase : AzurePSCmdlet [ValidateNotNullOrEmpty] public string Instance { get; set; } + [Parameter(Mandatory = false)] + public SwitchParameter PassThru { get; set; } + /// /// The fully qualified absolute URI of the server instance. /// (scheme.region.azureAsEndpoint/serverName) @@ -66,6 +69,19 @@ protected override IAzureContext DefaultContext } } + protected override string DataCollectionWarning + { + get + { + return Resources.ARMDataCollectionMessage; + } + } + + protected override void InitializeQosEvent() + { + // No data collection for this commandlet + } + protected IAzureContext CurrentContext { get @@ -108,7 +124,7 @@ protected override void BeginProcessing() // user must specify the fully qualified server name. For example, westus2.asazure.windows.net/testserver if (!Uri.TryCreate(Instance, UriKind.Absolute, out var uriResult) || uriResult.Scheme != AsAzureEndpoints.UriSchemeAsAzure) { - throw new PSInvalidOperationException(string.Format(Properties.Resources.InvalidServerName, Instance)); + throw new PSInvalidOperationException(string.Format(Resources.InvalidServerName, Instance)); } // derive all bits of the url from the input @@ -140,7 +156,7 @@ internal static AsAzureDataplaneClient CreateAsAzureDataplaneClient(string hostU { if (context == null) { - throw new ApplicationException(Resources.NoSubscriptionInContext); + throw new ApplicationException(Common.Authentication.Properties.Resources.NoSubscriptionInContext); } if (string.IsNullOrEmpty(hostUri)) From 2b61fbfe61547c22c6705a1e15e3a6b79dfae672 Mon Sep 17 00:00:00 2001 From: Gabriel Prestemon Date: Thu, 10 Jan 2019 12:25:03 -0800 Subject: [PATCH 009/141] Rewrite IAsAzureHttpClient to be more relevant to new structure. --- .../Commands/Export-AzureAsInstanceLog.cs | 2 +- .../Commands/Synchronize-AzureASInstance.cs | 14 ++-- .../Models/AsAzureDataplaneClient.cs | 67 ++++--------------- .../Models/AsAzureDataplaneCmdletBase.cs | 7 +- .../Models/IAsAzureHttpClient.cs | 12 ++-- 5 files changed, 26 insertions(+), 76 deletions(-) diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Export-AzureAsInstanceLog.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Export-AzureAsInstanceLog.cs index 7430b4dffc95..e7ef18fb2c71 100644 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Export-AzureAsInstanceLog.cs +++ b/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Export-AzureAsInstanceLog.cs @@ -45,7 +45,7 @@ public override void ExecuteCmdlet() var logfileEndpoint = string.Format(AsAzureEndpoints.LogfileEndpointPathFormat, ServerName); - AsAzureDataplaneClient.resetHttpClient(); + AsAzureDataplaneClient.ResetHttpClient(); using (var message = AsAzureDataplaneClient.CallGetAsync(logfileEndpoint).ConfigureAwait(false).GetAwaiter().GetResult()) { message.EnsureSuccessStatusCode(); diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Synchronize-AzureASInstance.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Synchronize-AzureASInstance.cs index 67ea5f03ddd0..b6a25e71a05e 100644 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Synchronize-AzureASInstance.cs +++ b/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Synchronize-AzureASInstance.cs @@ -170,11 +170,8 @@ private async Task SynchronizeDatabaseAsync( try { var syncEndpoint = string.Format(AsAzureEndpoints.SynchronizeEndpointPathFormat, this.ServerName, databaseName); - this.AsAzureDataplaneClient.resetHttpClient(); - using (var message = await AsAzureDataplaneClient.CallPostAsync( - baseUri: syncBaseUri, - requestUrl: syncEndpoint, - correlationId: correlationId)) + this.AsAzureDataplaneClient.ResetHttpClient(); + using (var message = await AsAzureDataplaneClient.CallPostAsync(syncBaseUri, syncEndpoint, correlationId)) { this.syncRequestRootActivityId = message.Headers.Contains(RootActivityIdHeaderName) ? message.Headers.GetValues(RootActivityIdHeaderName).FirstOrDefault() : string.Empty; this.syncRequestTimeStamp = message.Headers.Contains(CurrentUtcDateHeaderName) ? message.Headers.GetValues(CurrentUtcDateHeaderName).FirstOrDefault() : string.Empty; @@ -284,11 +281,8 @@ private async Task PollSyncStatusWithRetryAsyn await Task.Delay(DefaultRetryIntervalForPolling); } - this.AsAzureDataplaneClient.resetHttpClient(); - using (HttpResponseMessage message = await AsAzureDataplaneClient.CallGetAsync( - baseUri: pollingUrl, - requestUrl: string.Empty, - correlationId: correlationId)) + this.AsAzureDataplaneClient.ResetHttpClient(); + using (HttpResponseMessage message = await AsAzureDataplaneClient.CallGetAsync(pollingUrl, string.Empty, correlationId)) { bool shouldRetry = false; if (message.IsSuccessStatusCode && message.Content != null) diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneClient.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneClient.cs index c417535d043d..c109a41812b6 100644 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneClient.cs +++ b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneClient.cs @@ -38,9 +38,6 @@ public class AsAzureDataplaneClient : ServiceClient, IAs private Func HttpClientProvider { get; set; } - // This may cause problems, but is necessary for mulitple inheritance. - public new HttpClient HttpClient { get; set; } - public AsAzureDataplaneClient(Uri baseUri, ServiceClientCredentials credentials, Func httpClientProvider, params DelegatingHandler[] handlers) : base(handlers) { @@ -48,7 +45,7 @@ public AsAzureDataplaneClient(Uri baseUri, ServiceClientCredentials credentials, this.Credentials = credentials ?? throw new ArgumentNullException(nameof(credentials)); this.HttpClientProvider = httpClientProvider ?? throw new ArgumentNullException(nameof(httpClientProvider)); this.Credentials.InitializeServiceClient(this); - this.resetHttpClient(); + this.ResetHttpClient(); } public AsAzureDataplaneClient(Uri baseUri, ServiceClientCredentials credentials, Func httpClientProvider, HttpClientHandler rootHandler, params DelegatingHandler[] handlers) @@ -58,37 +55,24 @@ public AsAzureDataplaneClient(Uri baseUri, ServiceClientCredentials credentials, this.Credentials = credentials ?? throw new ArgumentNullException(nameof(credentials)); this.HttpClientProvider = httpClientProvider ?? throw new ArgumentNullException(nameof(httpClientProvider)); this.Credentials.InitializeServiceClient(this); - this.resetHttpClient(); + this.ResetHttpClient(); } - public void resetHttpClient() + public void ResetHttpClient() { this.HttpClient = this.HttpClientProvider(); } #region CallHttpMethodAsyncOverloads - /// - /// Calls SendRequestAsync() for a GET using a blank correlationId. - /// - /// The base Uri to call. - /// The request Url. - /// The access token (will be discarded). - /// The http response message. - public async Task CallGetAsync(Uri baseUri, string requestUrl, string accessToken) - { - return await CallGetAsync(baseUri: baseUri, requestUrl: requestUrl, accessToken: accessToken, correlationId: new Guid()); - } - /// /// Calls SendRequestAsync() for a GET. /// /// The base Uri to call. /// The request Url. - /// The access token (will be discarded). /// The CorrelationId /// The http response message. - public async Task CallGetAsync(Uri baseUri, string requestUrl, string accessToken = null, Guid correlationId = new Guid()) + public async Task CallGetAsync(Uri baseUri, string requestUrl, Guid correlationId = new Guid()) { return await SendRequestAsync(HttpMethod.Get, baseUri: baseUri, requestUrl: requestUrl, correlationId: correlationId); } @@ -100,45 +84,32 @@ public async Task CallGetAsync(Uri baseUri, string requestU /// The http response message. public async Task CallGetAsync(string requestUrl) { - return await CallGetAsync(requestUrl, new Guid()); - } - - /// - /// Calls SendRequestAsync() for a GET using the default BaseUri. - /// - /// The Request Url. - /// The CorrelationId - /// The http response message. - public async Task CallGetAsync(string requestUrl, Guid correlationId) - { - return await SendRequestAsync(HttpMethod.Get, BaseUri, requestUrl, correlationId); + return await CallGetAsync(BaseUri, requestUrl, new Guid()); } /// - /// Calls SendRequestAsync() for a POST using a blank correlationId. + /// Calls SendRequestAsync() for a POST. /// /// The base Uri to call. /// The request Url. - /// The access token (will be discarded). + /// The CorrelationId /// The content to post (optional). /// The http response message. - public async Task CallPostAsync(Uri baseUri, string requestUrl, string accessToken, HttpContent content = null) + public async Task CallPostAsync(Uri baseUri, string requestUrl, Guid correlationId, HttpContent content = null) { - return await CallPostAsync(baseUri: baseUri, requestUrl: requestUrl, accessToken: accessToken, correlationId: new Guid(), content: content); + return await SendRequestAsync(HttpMethod.Post, baseUri, requestUrl, correlationId, content); } /// - /// Calls SendRequestAsync() for a POST. + /// Calls SendRequestAsync() for a POST using a blank correlationId. /// /// The base Uri to call. /// The request Url. - /// The access token (will be discarded). - /// The CorrelationId /// The content to post (optional). /// The http response message. - public async Task CallPostAsync(Uri baseUri, string requestUrl, string accessToken = null, Guid correlationId = new Guid(), HttpContent content = null) + public async Task CallPostAsync(Uri baseUri, string requestUrl, HttpContent content = null) { - return await SendRequestAsync(HttpMethod.Post, baseUri: baseUri, requestUrl: requestUrl, correlationId: correlationId, content: content); + return await CallPostAsync(baseUri, requestUrl, new Guid(), content); } /// @@ -149,19 +120,7 @@ public async Task CallPostAsync(Uri baseUri, string request /// The http response message. public async Task CallPostAsync(string requestUrl, HttpContent content = null) { - return await CallPostAsync(requestUrl, new Guid(), content); - } - - /// - /// Calls SendRequestAsync() for a POST using the default BaseUri. - /// - /// The Request Url. - /// The CorrelationId - /// The content to post (optional). - /// The http response message. - public async Task CallPostAsync(string requestUrl, Guid correlationId, HttpContent content = null) - { - return await SendRequestAsync(HttpMethod.Post, BaseUri, requestUrl, correlationId, content); + return await CallPostAsync(BaseUri, requestUrl, content); } #endregion diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs index be7c90a07f43..7129364ff361 100644 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs +++ b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs @@ -140,11 +140,8 @@ protected ClusterResolutionResult ClusterResolve(Uri clusterUri, string serverNa var content = new StringContent($"ServerName={serverName}"); content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/x-www-form-urlencoded"); - this.AsAzureDataplaneClient.resetHttpClient(); - using (var message = AsAzureDataplaneClient.CallPostAsync( - baseUri: clusterUri, - requestUrl: AsAzureEndpoints.ClusterResolveEndpoint, - content: content).Result) + this.AsAzureDataplaneClient.ResetHttpClient(); + using (var message = AsAzureDataplaneClient.CallPostAsync(clusterUri, AsAzureEndpoints.ClusterResolveEndpoint, content).Result) { message.EnsureSuccessStatusCode(); var rawResult = message.Content.ReadAsStringAsync().Result; diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Models/IAsAzureHttpClient.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Models/IAsAzureHttpClient.cs index 93b27b9b63d0..72d541676c27 100644 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Models/IAsAzureHttpClient.cs +++ b/src/AnalysisServices/AnalysisServices.Dataplane/Models/IAsAzureHttpClient.cs @@ -20,16 +20,16 @@ namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane.Models { public interface IAsAzureHttpClient { - HttpClient HttpClient { get; set; } + Task CallGetAsync(string requestURL); - Task CallPostAsync(Uri baseURI, string requestURL, string accessToken, HttpContent content = null); + Task CallGetAsync(Uri baseUri, string requestURL, Guid correlationId); - Task CallPostAsync(Uri baseURI, string requestURL, string accessToken, Guid correlationId, HttpContent content = null); + Task CallPostAsync(string requestURL, HttpContent content = null); - Task CallGetAsync(Uri baseURI, string requestURL, string accessToken); + Task CallPostAsync(Uri baseURI, string requestURL, HttpContent content = null); - Task CallGetAsync(Uri baseURI, string requestURL, string accessToken, Guid correlationId); + Task CallPostAsync(Uri baseURI, string requestURL, Guid correlationId, HttpContent content = null); - void resetHttpClient(); + void ResetHttpClient(); } } From e68bea55ef14d18cc152ace359bfea77878f279c Mon Sep 17 00:00:00 2001 From: Gabriel Prestemon Date: Thu, 10 Jan 2019 12:38:22 -0800 Subject: [PATCH 010/141] Change dataplane client property and field type to interface. --- .../Models/AsAzureDataplaneCmdletBase.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs index 7129364ff361..bba248786058 100644 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs +++ b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs @@ -29,7 +29,7 @@ namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane.Models /// public abstract class AsAzureDataplaneCmdletBase : AzurePSCmdlet { - private AsAzureDataplaneClient _asAzureDataplaneClient; + private IAsAzureHttpClient _asAzureDataplaneClient; private IAzureContext _currentContext; @@ -97,7 +97,7 @@ protected IAzureContext CurrentContext set { _currentContext = value; } } - public AsAzureDataplaneClient AsAzureDataplaneClient + public IAsAzureHttpClient AsAzureDataplaneClient { get { From 2dbc31b813fdf560da556b6bef8fab5bab78e699 Mon Sep 17 00:00:00 2001 From: Gabriel Prestemon Date: Thu, 10 Jan 2019 15:28:48 -0800 Subject: [PATCH 011/141] Remove unused TokenCacheItemProvider. --- .../Models/TokenCacheItemProvider.cs | 62 ------------------- 1 file changed, 62 deletions(-) delete mode 100644 src/AnalysisServices/AnalysisServices.Dataplane/Models/TokenCacheItemProvider.cs diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Models/TokenCacheItemProvider.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Models/TokenCacheItemProvider.cs deleted file mode 100644 index 0ed2c6c642f8..000000000000 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Models/TokenCacheItemProvider.cs +++ /dev/null @@ -1,62 +0,0 @@ -// ---------------------------------------------------------------------------------- -// -// 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 System; -using System.Collections.Generic; -using System.Linq; -using System.Management.Automation; -using System.Text; -using System.Threading.Tasks; -using Microsoft.Azure.Commands.AnalysisServices.Dataplane.Properties; -using Microsoft.IdentityModel.Clients.ActiveDirectory; - -namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane.Models -{ - public interface ITokenCacheItemProvider - { - string GetTokenFromTokenCache(TokenCache tokenCache, string uniqueId); - - string GetTokenFromTokenCache(TokenCache tokenCache, string uniqueId, string environmentName); - } - - public class TokenCacheItemProvider : ITokenCacheItemProvider - { - public string GetTokenFromTokenCache(TokenCache tokenCache, string uniqueId) - { - return GetTokenFromTokenCache(tokenCache, uniqueId, null); - } - - public string GetTokenFromTokenCache(TokenCache tokenCache, string uniqueId, string environmentName) - { - TokenCacheItem tokenCacheItem = null; - if (string.IsNullOrEmpty(uniqueId)) - { - var tokenCacheItems = tokenCache.ReadItems().Where(tokenItem => (string.IsNullOrEmpty(environmentName) || tokenItem.Resource.Contains(environmentName))); - tokenCacheItem = tokenCacheItems.FirstOrDefault(); - } - else - { - var tokenCacheItems = tokenCache.ReadItems().Where(tokenItem => tokenItem.UniqueId.Equals(uniqueId) && (string.IsNullOrEmpty(environmentName) || tokenItem.Resource.Contains(environmentName))); - tokenCacheItem = tokenCacheItems.FirstOrDefault(); - } - - if (tokenCacheItem == null || string.IsNullOrEmpty(tokenCacheItem.AccessToken)) - { - throw new PSInvalidOperationException(string.Format(Resources.NotLoggedInMessage, "")); - } - - return tokenCacheItem.AccessToken; - } - } -} From b3809461fda48a4bd5b1c3222ca7c5929fdfb5f0 Mon Sep 17 00:00:00 2001 From: Gabriel Prestemon Date: Thu, 10 Jan 2019 18:30:46 -0800 Subject: [PATCH 012/141] Rewrite InMemoryTests to fit new code. --- .../Models/AsAzureDataplaneCmdletBase.cs | 15 +- .../InMemoryTests/DataPlaneCommandTests.cs | 943 ++++++------------ 2 files changed, 319 insertions(+), 639 deletions(-) diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs index bba248786058..95d32b210742 100644 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs +++ b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs @@ -77,12 +77,10 @@ protected override string DataCollectionWarning } } - protected override void InitializeQosEvent() - { - // No data collection for this commandlet - } + // No data collection for this commandlet + protected override void InitializeQosEvent() { } - protected IAzureContext CurrentContext + public IAzureContext CurrentContext { get { @@ -121,7 +119,7 @@ protected override void BeginProcessing() throw new ArgumentNullException(nameof(Instance)); } - // user must specify the fully qualified server name. For example, westus2.asazure.windows.net/testserver + // user must specify the fully qualified server name. For example, asazure://westus2.asazure.windows.net/testserver if (!Uri.TryCreate(Instance, UriKind.Absolute, out var uriResult) || uriResult.Scheme != AsAzureEndpoints.UriSchemeAsAzure) { throw new PSInvalidOperationException(string.Format(Resources.InvalidServerName, Instance)); @@ -132,7 +130,10 @@ protected override void BeginProcessing() DnsSafeHost = uriResult.DnsSafeHost; ServerName = uriResult.PathAndQuery.Trim('/'); - AsAzureDataplaneClient = CreateAsAzureDataplaneClient(DnsSafeHost, CurrentContext, () => { return new HttpClient(); }); + if (_asAzureDataplaneClient == null) + { + AsAzureDataplaneClient = CreateAsAzureDataplaneClient(DnsSafeHost, CurrentContext, () => { return new HttpClient(); }); + } } protected ClusterResolutionResult ClusterResolve(Uri clusterUri, string serverName) diff --git a/src/AnalysisServices/AnalysisServices.Test/InMemoryTests/DataPlaneCommandTests.cs b/src/AnalysisServices/AnalysisServices.Test/InMemoryTests/DataPlaneCommandTests.cs index 4991c30cc5a8..a682324be7d2 100644 --- a/src/AnalysisServices/AnalysisServices.Test/InMemoryTests/DataPlaneCommandTests.cs +++ b/src/AnalysisServices/AnalysisServices.Test/InMemoryTests/DataPlaneCommandTests.cs @@ -1,632 +1,311 @@ -////// ---------------------------------------------------------------------------------- -////// -////// 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 System; -////using System.Linq; -////using System.Management.Automation; -////using System.Net; -////using System.Net.Http; -////using System.Reflection; -////using System.Security; -////using System.Text; -////using System.Threading.Tasks; -////using Microsoft.Azure.Commands.AnalysisServices.Dataplane; -////using Microsoft.Azure.Commands.AnalysisServices.Dataplane.Models; -////using Microsoft.Azure.Commands.AnalysisServices.Test.ScenarioTests; -////using Microsoft.Azure.ServiceManagement.Common.Models; -////using Microsoft.IdentityModel.Clients.ActiveDirectory; -////using Microsoft.WindowsAzure.Commands.ScenarioTest; -////using Microsoft.WindowsAzure.Commands.Utilities.Common; -////using Moq; -////using Xunit; -////using Xunit.Abstractions; -////using System.Collections.Generic; -////using System.Net.Http.Headers; -////using Newtonsoft.Json; - -////namespace Microsoft.Azure.Commands.AnalysisServices.Test.InMemoryTests -////{ -//// public class DataPlaneCommandTests : AsTestsBase -//// { -//// private const string testAsAzureEnvironment = "westcentralus.asazure.windows.net"; - -//// private const string testServer = "testserver"; - -//// private const string testUser = "testuser@contoso.com"; - -//// private const string testPassword = "testpassword"; - -//// private const string testToken = "eyJ0eXAiOi" -//// + "JKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IjFpOWlmMDllc0YzaU9sS0I2SW9meVVGSUxnQSIsImtpZC" -//// + "I6IjFpOWlmMDllc0YzaU9sS0I2SW9meVVGSUxnQSJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY" -//// + "29yZS53aW5kb3dzLm5ldC8iLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLXBwZS5uZXQvMDQ1NDZiY" -//// + "zAtYmMxOS00Y2I2LWIxNmQtNTc0OTQxNzFhNGJjLyIsImlhdCI6MTQ4MDU1NjY0MywibmJmIjoxNDgwN" -//// + "TU2NjQzLCJleHAiOjE0ODA1NjA1NDMsImFjciI6IjEiLCJhbXIiOlsicHdkIl0sImFwcGlkIjoiMTk1M" -//// + "GEyNTgtMjI3Yi00ZTMxLWE5Y2YtNzE3NDk1OTQ1ZmMyIiwiYXBwaWRhY3IiOiIwIiwiZV9leHAiOjEwO" -//// + "DAwLCJmYW1pbHlfbmFtZSI6IlN1c21hbiIsImdpdmVuX25hbWUiOiJEZXJ5YSIsImdyb3VwcyI6WyI0Y" -//// + "zNmNjNiNy1mZWU1LTQ1ZWItOTAwMy03YWQ1ZDM5MzMzMDIiXSwiaXBhZGRyIjoiMTY3LjIyMC4wLjExM" -//// + "yIsIm5hbWUiOiJEZXJ5YSBTdXNtYW4iLCJvaWQiOiJhODMyOWI5OS01NGI1LTQwNDctOTU5NS1iNWZkN" -//// + "2VhMzgyZjYiLCJwbGF0ZiI6IjMiLCJwdWlkIjoiMTAwMzAwMDA5QUJGRTQyRiIsInNjcCI6InVzZXJfa" -//// + "W1wZXJzb25hdGlvbiIsInN1YiI6ImEyUE5ZZW9KSnk3VnFFVWVkb0ZxS0J6UUNjOWNUN2tCVWtSYm5BM" -//// + "ldLcnciLCJ0aWQiOiIwNDU0NmJjMC1iYzE5LTRjYjYtYjE2ZC01NzQ5NDE3MWE0YmMiLCJ1bmlxdWVfb" -//// + "mFtZSI6ImF6dGVzdDBAc3RhYmxldGVzdC5jY3NjdHAubmV0IiwidXBuIjoiYXp0ZXN0MEBzdGFibGV0Z" -//// + "XN0LmNjc2N0cC5uZXQiLCJ2ZXIiOiIxLjAiLCJ3aWRzIjpbIjYyZTkwMzk0LTY5ZjUtNDIzNy05MTkwL" -//// + "TAxMjE3NzE0NWUxMCJdfQ.W9eVq_TXGBjWCCl_tRGXM31OZn5G4UBIi6B9xZphvrpaAvu5tnzYm6XWah" -//// + "jwA_iE1djOpZM3rxFxP4ZFecVyZGHYVddSJ0rg6vw-L4J5jIPDSojqiGoSLtU8yFxEDRaro0SM4LdQ_N" -//// + "dF-oUwfUQGy88vLOejQdiKzfC-yFvtVSmYoyJSnkZLglDEbhySvLtjXGfpOgiyGLoncV5wTk6Vbf7VLe" -//// + "65kxhZWVUbTHaPuEvg03ZQ3esDb6wxQewJPAL-GARg6S9wIN776Esw8-53AWhzFu0fIut-9FXGma6jV7" -//// + "MYPoUUcFuQzLZgphecPyMPXSVhummVCdBwX9sizxnmFA"; - -//// public DataPlaneCommandTests(ITestOutputHelper output) -//// { -//// XunitTracingInterceptor.AddToContext(new XunitTracingInterceptor(output)); - -//// SynchronizeAzureAzureAnalysisServer.DefaultRetryIntervalForPolling = TimeSpan.FromSeconds(0); -//// } - -//// [Fact] -//// [Trait(Category.AcceptanceType, Category.CheckIn)] -//// public void TestAddAzureASAccountCommand() -//// { -//// Mock commandRuntimeMock = new Mock(); -//// var addAmdlet = new AddAzureASAccountCommand() -//// { -//// CommandRuntime = commandRuntimeMock.Object -//// }; -//// var expectedProfile = new AsAzureProfile -//// { -//// Context = new AsAzureContext( -//// new AsAzureAccount() -//// { -//// Id = testUser, -//// Tenant = null -//// }, -//// new AsAzureEnvironment(testAsAzureEnvironment)) -//// }; -//// expectedProfile.Context.Environment.Endpoints.Add(AsAzureEnvironment.AsRolloutEndpoints.AdAuthorityBaseUrl, AsAzureClientSession.GetAuthorityUrlForEnvironment(expectedProfile.Context.Environment)); -//// expectedProfile.Context.Environment.Endpoints.Add(AsAzureEnvironment.AsRolloutEndpoints.RestartEndpointFormat, AsAzureClientSession.RestartEndpointPathFormat); -//// expectedProfile.Environments.Add(testAsAzureEnvironment, expectedProfile.Context.Environment); -//// expectedProfile.Context.TokenCache = Encoding.ASCII.GetBytes(testToken); - -//// // Setup -//// // Clear the the current profile -//// AsAzureClientSession.Instance.Profile.Environments.Clear(); - -//// var mockAuthenticationProvider = new Mock(); -//// mockAuthenticationProvider.Setup( -//// authProvider => authProvider.GetAadAuthenticatedToken( -//// It.IsAny(), -//// It.IsAny(), -////#if NETSTANDARD -//// It.IsAny>(), -////#else -//// It.IsAny(), -////#endif -//// It.IsAny(), -//// It.IsAny(), -//// It.IsAny())).Returns(testToken); -//// AsAzureClientSession.Instance.SetAsAzureAuthenticationProvider(mockAuthenticationProvider.Object); - -//// addAmdlet.RolloutEnvironment = testAsAzureEnvironment; -//// var password = new SecureString(); -//// var testpwd = testPassword; -//// testpwd.All(c => { -//// password.AppendChar(c); -//// return true; -//// }); -//// addAmdlet.Credential = new PSCredential(testUser, password); -//// commandRuntimeMock.Setup(f => f.ShouldProcess(It.IsAny(), It.IsAny())).Returns(true); -//// commandRuntimeMock.Setup(f => f.WriteObject(expectedProfile)); - -//// // Act -//// addAmdlet.InvokeBeginProcessing(); -//// Assert.Empty(AsAzureClientSession.Instance.Profile.Environments); -//// addAmdlet.ExecuteCmdlet(); -//// Assert.True(AsAzureClientSession.Instance.Profile.Environments.Count == 1); -//// Assert.NotNull(AsAzureClientSession.Instance.Profile.Environments[testAsAzureEnvironment]); - -//// // Call InvokeBeginProcessing again to get coverage. It should use the existing environment in memory not create a new one. -//// addAmdlet.InvokeBeginProcessing(); -//// Assert.True(AsAzureClientSession.Instance.Profile.Environments.Count == 1); -//// Assert.NotNull(AsAzureClientSession.Instance.Profile.Environments[testAsAzureEnvironment]); - -//// addAmdlet.InvokeEndProcessing(); - -//// var environment = (AsAzureEnvironment)AsAzureClientSession.Instance.Profile.Environments[testAsAzureEnvironment]; -//// Assert.Equal(environment.Endpoints[AsAzureEnvironment.AsRolloutEndpoints.AdAuthorityBaseUrl], AsAzureClientSession.GetAuthorityUrlForEnvironment(environment)); -//// Assert.NotNull(environment.Endpoints[AsAzureEnvironment.AsRolloutEndpoints.RestartEndpointFormat]); - -//// commandRuntimeMock.Verify(f => f.WriteObject(AsAzureClientSession.Instance.Profile)); -//// mockAuthenticationProvider.Verify(authProvider => authProvider.GetAadAuthenticatedToken(It.IsAny(), -//// It.IsAny(), -////#if NETSTANDARD -//// It.IsAny>(), -////#else -//// It.IsAny(), -////#endif -//// It.IsAny(), -//// It.IsAny(), -//// It.IsAny()), Times.Once); -//// } - -//// [Fact] -//// [Trait(Category.AcceptanceType, Category.CheckIn)] -//// public void RestartAzureASInstance_Succeeds() -//// { -//// Mock commandRuntimeMock = new Mock(); -//// // Setup -//// // Clear the the current profile -//// AsAzureClientSession.Instance.Profile.Environments.Clear(); -//// var mockAuthenticationProvider = new Mock(); -//// mockAuthenticationProvider.Setup( -//// authProvider => authProvider.GetAadAuthenticatedToken( -//// It.IsAny(), -//// It.IsAny(), -////#if NETSTANDARD -//// It.IsAny>(), -////#else -//// It.IsAny(), -////#endif -//// It.IsAny(), -//// It.IsAny(), -//// It.IsAny())).Returns(testToken); -//// AsAzureClientSession.Instance.SetAsAzureAuthenticationProvider(mockAuthenticationProvider.Object); -//// commandRuntimeMock.Setup(f => f.ShouldProcess(It.IsAny(), It.IsAny())).Returns(true); - -//// // Set up AsAzureHttpClient mock -//// var mockAsAzureHttpClient = new Mock(); -//// mockAsAzureHttpClient -//// .Setup(obj => obj.CallPostAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) -//// .Returns(Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK))); - -//// var mockTokenCacheItemProvider = new Mock(); -//// mockTokenCacheItemProvider -//// .Setup(obj => obj.GetTokenFromTokenCache(It.IsAny(), It.IsAny())) -//// .Returns(testToken); -//// var restartCmdlet = new RestartAzureAnalysisServer(mockAsAzureHttpClient.Object, mockTokenCacheItemProvider.Object) -//// { -//// CommandRuntime = commandRuntimeMock.Object -//// }; - -//// var addAmdlet = new AddAzureASAccountCommand() -//// { -//// CommandRuntime = commandRuntimeMock.Object -//// }; - -//// DoLogin(addAmdlet); -//// restartCmdlet.Instance = testServer; - -//// // Act -//// restartCmdlet.InvokeBeginProcessing(); -//// restartCmdlet.ExecuteCmdlet(); -//// restartCmdlet.InvokeEndProcessing(); -//// } - -//// [Fact] -//// [Trait(Category.AcceptanceType, Category.CheckIn)] -//// public void RestartAzureASInstance_NullInstanceThrows() -//// { -//// Mock commandRuntimeMock = new Mock(); - -//// var mockAsAzureHttpClient = new Mock(); -//// var mockTokenCacheItemProvider = new Mock(); -//// var restartCmdlet = new RestartAzureAnalysisServer(mockAsAzureHttpClient.Object, mockTokenCacheItemProvider.Object) -//// { -//// CommandRuntime = commandRuntimeMock.Object -//// }; - -//// // Setup -//// // Clear the the current profile -//// AsAzureClientSession.Instance.Profile.Environments.Clear(); -//// var mockAuthenticationProvider = new Mock(); -//// mockAuthenticationProvider.Setup( -//// authProvider => authProvider.GetAadAuthenticatedToken( -//// It.IsAny(), -//// It.IsAny(), -////#if NETSTANDARD -//// It.IsAny>(), -////#else -//// It.IsAny(), -////#endif -//// It.IsAny(), -//// It.IsAny(), -//// It.IsAny())).Returns(testToken); -//// AsAzureClientSession.Instance.SetAsAzureAuthenticationProvider(mockAuthenticationProvider.Object); -//// commandRuntimeMock.Setup(f => f.ShouldProcess(It.IsAny(), It.IsAny())).Returns(true); - -//// restartCmdlet.Instance = null; -//// // Act -//// Assert.Throws(() => restartCmdlet.InvokeBeginProcessing()); -//// } - -//// [Fact] -//// [Trait(Category.AcceptanceType, Category.CheckIn)] -//// public void RestartAzureASInstance_NotLoggedInThrows() -//// { -//// Mock commandRuntimeMock = new Mock(); - -//// var mockAsAzureHttpClient = new Mock(); -//// var mockTokenCacheItemProvider = new Mock(); -//// var restartCmdlet = new RestartAzureAnalysisServer(mockAsAzureHttpClient.Object, mockTokenCacheItemProvider.Object) -//// { -//// CommandRuntime = commandRuntimeMock.Object -//// }; - -//// // Setup -//// // Clear the the current profile -//// AsAzureClientSession.Instance.Profile.Environments.Clear(); -//// var mockAuthenticationProvider = new Mock(); -//// mockAuthenticationProvider.Setup( -//// authProvider => authProvider.GetAadAuthenticatedToken( -//// It.IsAny(), -//// It.IsAny(), -////#if NETSTANDARD -//// It.IsAny>(), -////#else -//// It.IsAny(), -////#endif -//// It.IsAny(), -//// It.IsAny(), -//// It.IsAny())).Returns(testToken); -//// AsAzureClientSession.Instance.SetAsAzureAuthenticationProvider(mockAuthenticationProvider.Object); -//// commandRuntimeMock.Setup(f => f.ShouldProcess(It.IsAny(), It.IsAny())).Returns(true); -//// restartCmdlet.Instance = testServer; - -//// // Act -//// try -//// { -//// restartCmdlet.InvokeBeginProcessing(); -//// } -//// catch(Exception ex) -//// { -//// Assert.IsType(ex); -//// } -//// } - -//// [Fact] -//// [Trait(Category.AcceptanceType, Category.CheckIn)] -//// public void ExportAzureASInstanceLogTest() -//// { -//// Mock commandRuntimeMock = new Mock(); -//// // Setup -//// // Clear the the current profile -//// AsAzureClientSession.Instance.Profile.Environments.Clear(); -//// var mockAuthenticationProvider = new Mock(); -//// mockAuthenticationProvider.Setup( -//// authProvider => authProvider.GetAadAuthenticatedToken( -//// It.IsAny(), -//// It.IsAny(), -////#if NETSTANDARD -//// It.IsAny>(), -////#else -//// It.IsAny(), -////#endif -//// It.IsAny(), -//// It.IsAny(), -//// It.IsAny())).Returns(testToken); -//// AsAzureClientSession.Instance.SetAsAzureAuthenticationProvider(mockAuthenticationProvider.Object); -//// commandRuntimeMock.Setup(f => f.ShouldProcess(It.IsAny(), It.IsAny())).Returns(true); - -//// // Set up AsAzureHttpClient mock -//// var mockAsAzureHttpClient = new Mock(); -//// mockAsAzureHttpClient -//// .Setup(obj => obj.CallPostAsync( -//// It.IsAny(), -//// It.Is(s => s.Contains("clusterResolve")), -//// It.IsAny(), -//// It.IsAny())) -//// .Returns(Task.FromResult( -//// new HttpResponseMessage(HttpStatusCode.OK) -//// { -//// Content = new StringContent("{\"clusterFQDN\": \"resolved.westcentralus.asazure.windows.net\"}") -//// })); -//// mockAsAzureHttpClient.Setup(obj => obj.CallGetAsync(It.IsAny(), It.IsAny(), It.IsAny())).Returns( -//// Task.FromResult( -//// new HttpResponseMessage(HttpStatusCode.OK) -//// { -//// Content = new StringContent("MOCKED STREAM CONTENT") -//// })); - -//// var mockTokenCacheItemProvider = new Mock(); -//// mockTokenCacheItemProvider -//// .Setup(obj => obj.GetTokenFromTokenCache(It.IsAny(), It.IsAny())) -//// .Returns(testToken); - -//// var exportLogCmdlet = new ExportAzureAnalysisServerLog(mockAsAzureHttpClient.Object, mockTokenCacheItemProvider.Object) -//// { -//// CommandRuntime = commandRuntimeMock.Object -//// }; - -//// var addAmdlet = new AddAzureASAccountCommand() -//// { -//// CommandRuntime = commandRuntimeMock.Object -//// }; - -//// DoLogin(addAmdlet); -//// exportLogCmdlet.Instance = testServer; -//// try -//// { -//// exportLogCmdlet.OutputPath = System.IO.Path.GetTempFileName(); -//// exportLogCmdlet.InvokeBeginProcessing(); -//// exportLogCmdlet.ExecuteCmdlet(); -//// exportLogCmdlet.InvokeEndProcessing(); -//// } -//// finally -//// { -//// if (System.IO.File.Exists(exportLogCmdlet.OutputPath)) -//// { -//// System.IO.File.Delete(exportLogCmdlet.OutputPath); -//// } -//// } -//// } - -//// [Fact] -//// [Trait(Category.AcceptanceType, Category.CheckIn)] -//// public void SynchronizeAzureASInstance_SingleDB_Succeeds() -//// { -//// Mock commandRuntimeMock = new Mock(); - -//// // Setup -//// // Clear the the current profile -//// AsAzureClientSession.Instance.Profile.Environments.Clear(); -//// var mockAuthenticationProvider = new Mock(); -//// mockAuthenticationProvider.Setup( -//// authProvider => authProvider.GetAadAuthenticatedToken( -//// It.IsAny(), -//// It.IsAny(), -////#if NETSTANDARD -//// It.IsAny>(), -////#else -//// It.IsAny(), -////#endif -//// It.IsAny(), -//// It.IsAny(), -//// It.IsAny())).Returns(testToken); -//// AsAzureClientSession.Instance.SetAsAzureAuthenticationProvider(mockAuthenticationProvider.Object); -//// commandRuntimeMock.Setup(f => f.ShouldProcess(It.IsAny(), It.IsAny())).Returns(true); - -//// // Set up AsAzureHttpClient mock -//// var mockAsAzureHttpClient = new Mock(); - -//// // set up cluster resolve respnose -//// ClusterResolutionResult resolveResult = new ClusterResolutionResult() -//// { -//// ClusterFQDN = "resolved.westcentralus.asazure.windows.net", -//// CoreServerName = testServer + ":rw", -//// TenantId = Guid.NewGuid().ToString() -//// }; -//// mockAsAzureHttpClient -//// .Setup(obj => obj.CallPostAsync( -//// It.IsAny(), -//// It.Is(s => s.Contains("clusterResolve")), -//// It.IsAny(), -//// It.IsAny())) -//// .Returns(Task.FromResult( -//// new HttpResponseMessage(HttpStatusCode.OK) -//// { -//// Content = new StringContent(JsonConvert.SerializeObject(resolveResult)) -//// })); - -//// // set up sync respnose -//// var postResponse = new HttpResponseMessage(HttpStatusCode.Accepted); -//// postResponse.Headers.Location = new Uri("https://done"); -//// postResponse.Headers.RetryAfter = new RetryConditionHeaderValue(TimeSpan.FromMilliseconds(500)); -//// postResponse.Headers.Add("x-ms-root-activity-id", Guid.NewGuid().ToString()); -//// postResponse.Headers.Add("x-ms-current-utc-date", Guid.NewGuid().ToString()); -//// mockAsAzureHttpClient -//// .Setup(obj => obj.CallPostAsync( -//// It.IsAny(), -//// It.Is(s => s.Contains("sync")), -//// It.IsAny(), -//// It.IsAny(), -//// null)) -//// .Returns(Task>.FromResult(postResponse)); - - -//// var getResponse1 = new HttpResponseMessage(HttpStatusCode.SeeOther); -//// getResponse1.Headers.Location = new Uri("https://done"); -//// getResponse1.Headers.RetryAfter = new RetryConditionHeaderValue(TimeSpan.FromMilliseconds(500)); -//// mockAsAzureHttpClient -//// .Setup(obj => obj.CallGetAsync( -//// It.Is(u => u.OriginalString.Contains("1")), -//// string.Empty, -//// It.IsAny(), -//// It.IsAny())) -//// .Returns(Task.FromResult(getResponse1)); - -//// var getResponseSucceed = new HttpResponseMessage -//// { -//// StatusCode = HttpStatusCode.OK, -//// Content = new StringContent( -//// "{\n\"database\":\"db0\",\n\"syncstate\":\"Completed\"\n}", Encoding.UTF8, "application/json") -//// }; - -//// var getResponseError = new HttpResponseMessage(HttpStatusCode.InternalServerError); - -//// var finalResponses = new Queue(new [] { getResponseError, getResponseSucceed }); -//// mockAsAzureHttpClient -//// .Setup(obj => obj.CallGetAsync( -//// It.Is(u => u.OriginalString.Contains("done")), -//// string.Empty, -//// It.IsAny(), -//// It.IsAny())) -//// .Returns(() => Task.FromResult(finalResponses.Dequeue())); - -//// var mockTokenCacheItemProvider = new Mock(); -//// mockTokenCacheItemProvider -//// .Setup(obj => obj.GetTokenFromTokenCache(It.IsAny(), It.IsAny())) -//// .Returns(testToken); -//// var syncCmdlet = new SynchronizeAzureAzureAnalysisServer(mockAsAzureHttpClient.Object, mockTokenCacheItemProvider.Object) -//// { -//// CommandRuntime = commandRuntimeMock.Object -//// }; - -//// var addAmdlet = new AddAzureASAccountCommand() -//// { -//// CommandRuntime = commandRuntimeMock.Object -//// }; - -//// DoLogin(addAmdlet); -//// syncCmdlet.Instance = testServer + ":rw"; -//// syncCmdlet.Database = "db0"; - -//// // Act -//// syncCmdlet.InvokeBeginProcessing(); -//// syncCmdlet.ExecuteCmdlet(); -//// syncCmdlet.InvokeEndProcessing(); -//// } - -//// [Fact] -//// [Trait(Category.AcceptanceType, Category.CheckIn)] -//// public void SynchronizeAzureASInstance_FailsAfterTooManyRetries() -//// { -//// Mock commandRuntimeMock = new Mock(); - -//// // Setup -//// // Clear the the current profile -//// AsAzureClientSession.Instance.Profile.Environments.Clear(); -//// var mockAuthenticationProvider = new Mock(); -//// mockAuthenticationProvider.Setup( -//// authProvider => authProvider.GetAadAuthenticatedToken( -//// It.IsAny(), -//// It.IsAny(), -////#if NETSTANDARD -//// It.IsAny>(), -////#else -//// It.IsAny(), -////#endif -//// It.IsAny(), -//// It.IsAny(), -//// It.IsAny())).Returns(testToken); -//// AsAzureClientSession.Instance.SetAsAzureAuthenticationProvider(mockAuthenticationProvider.Object); -//// commandRuntimeMock.Setup(f => f.ShouldProcess(It.IsAny(), It.IsAny())).Returns(true); - -//// // Set up AsAzureHttpClient mock -//// var mockAsAzureHttpClient = new Mock(); - -//// // set up cluster resolve respnose -//// ClusterResolutionResult resolveResult = new ClusterResolutionResult() -//// { -//// ClusterFQDN = "resolved.westcentralus.asazure.windows.net", -//// CoreServerName = testServer + ":rw", -//// TenantId = Guid.NewGuid().ToString() -//// }; -//// mockAsAzureHttpClient -//// .Setup(obj => obj.CallPostAsync( -//// It.IsAny(), -//// It.Is(s => s.Contains("clusterResolve")), -//// It.IsAny(), -//// It.IsAny())) -//// .Returns(Task.FromResult( -//// new HttpResponseMessage(HttpStatusCode.OK) -//// { -//// Content = new StringContent(JsonConvert.SerializeObject(resolveResult)) -//// })); - -//// // set up sync respnose -//// var postResponse = new HttpResponseMessage(HttpStatusCode.Accepted); -//// postResponse.Headers.Location = new Uri("https://1"); -//// postResponse.Headers.RetryAfter = new RetryConditionHeaderValue(TimeSpan.FromMilliseconds(500)); -//// postResponse.Headers.Add("x-ms-root-activity-id", Guid.NewGuid().ToString()); -//// postResponse.Headers.Add("x-ms-current-utc-date", Guid.NewGuid().ToString()); -//// mockAsAzureHttpClient -//// .Setup(obj => obj.CallPostAsync( -//// It.IsAny(), -//// It.Is(s => s.Contains("sync")), -//// It.IsAny(), -//// It.IsAny(), -//// null)) -//// .Returns(Task>.FromResult(postResponse)); - -//// var getResponse1 = new HttpResponseMessage(HttpStatusCode.SeeOther); -//// getResponse1.Headers.Location = new Uri("https://done"); -//// getResponse1.Headers.RetryAfter = new RetryConditionHeaderValue(TimeSpan.FromMilliseconds(500)); -//// getResponse1.Headers.Add("x-ms-root-activity-id", Guid.NewGuid().ToString()); -//// getResponse1.Headers.Add("x-ms-current-utc-date", Guid.NewGuid().ToString()); -//// mockAsAzureHttpClient -//// .Setup(obj => obj.CallGetAsync( -//// It.Is(u => u.OriginalString.Contains("1")), -//// It.IsAny(), -//// It.IsAny(), -//// It.IsAny())) -//// .Returns(Task.FromResult(getResponse1)); - -//// var getResponseSucceed = new HttpResponseMessage -//// { -//// StatusCode = HttpStatusCode.OK, -//// Content = new StringContent( -//// "{\n\"database\":\"db0\",\n\"syncstate\":\"Completed\"\n}", Encoding.UTF8, "application/json") -//// }; -//// getResponseSucceed.Headers.Add("x-ms-root-activity-id", Guid.NewGuid().ToString()); -//// getResponseSucceed.Headers.Add("x-ms-current-utc-date", Guid.NewGuid().ToString()); - -//// var getResponseError = new HttpResponseMessage(HttpStatusCode.InternalServerError); -//// getResponseError.Headers.Add("x-ms-root-activity-id", Guid.NewGuid().ToString()); -//// getResponseError.Headers.Add("x-ms-current-utc-date", Guid.NewGuid().ToString()); - -//// var finalResponses = new Queue(new[] { getResponseError, getResponseError, getResponseError, getResponseSucceed }); -//// mockAsAzureHttpClient -//// .Setup(obj => obj.CallGetAsync( -//// It.Is(u => u.OriginalString.Contains("done")), -//// It.IsAny(), -//// It.IsAny(), -//// It.IsAny())) -//// .Returns(() => Task.FromResult(finalResponses.Dequeue())); - -//// var mockTokenCacheItemProvider = new Mock(); -//// mockTokenCacheItemProvider -//// .Setup(obj => obj.GetTokenFromTokenCache(It.IsAny(), It.IsAny())) -//// .Returns(testToken); -//// var syncCmdlet = new SynchronizeAzureAzureAnalysisServer(mockAsAzureHttpClient.Object, mockTokenCacheItemProvider.Object) -//// { -//// CommandRuntime = commandRuntimeMock.Object -//// }; - -//// var addAmdlet = new AddAzureASAccountCommand() -//// { -//// CommandRuntime = commandRuntimeMock.Object -//// }; - -//// DoLogin(addAmdlet); -//// syncCmdlet.Instance = testServer + ":rw"; -//// syncCmdlet.Database = "db0"; - -//// // Act -//// syncCmdlet.InvokeBeginProcessing(); -//// Assert.Throws(() => syncCmdlet.ExecuteCmdlet()); -//// syncCmdlet.InvokeEndProcessing(); -//// } - -//// private void DoLogin(AddAzureASAccountCommand addCmdlet) -//// { -//// Mock commandRuntimeMock = new Mock(); - -//// addCmdlet.RolloutEnvironment = testAsAzureEnvironment; -//// var password = new SecureString(); -//// var testpwd = testPassword; -//// testpwd.All(c => { -//// password.AppendChar(c); -//// return true; -//// }); -//// addCmdlet.Credential = new PSCredential(testUser, password); -//// commandRuntimeMock.Setup(f => f.ShouldProcess(It.IsAny(), It.IsAny())).Returns(true); - -//// // Act -//// addCmdlet.InvokeBeginProcessing(); -//// addCmdlet.ExecuteCmdlet(); -//// AsAzureClientSession.TokenCache.Deserialize(Encoding.ASCII.GetBytes(testToken)); -//// addCmdlet.InvokeEndProcessing(); -//// } -//// } -////} +// ---------------------------------------------------------------------------------- +// +// 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 System; +using System.Management.Automation; +using System.Net; +using System.Net.Http; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Azure.Commands.AnalysisServices.Dataplane; +using Microsoft.Azure.Commands.AnalysisServices.Dataplane.Models; +using Microsoft.Azure.Commands.AnalysisServices.Test.ScenarioTests; +using Microsoft.Azure.Commands.Profile.Models.Core; +using Microsoft.Azure.ServiceManagement.Common.Models; +using Microsoft.WindowsAzure.Commands.ScenarioTest; +using Microsoft.WindowsAzure.Commands.Utilities.Common; +using Moq; +using Xunit; +using Xunit.Abstractions; +using System.Collections.Generic; +using System.Net.Http.Headers; +using Newtonsoft.Json; + +namespace Microsoft.Azure.Commands.AnalysisServices.Test.InMemoryTests +{ + public class DataPlaneCommandTests : AsTestsBase + { + private const string testInstance = "asazure://westcentralus.asazure.windows.net/testserver"; + + private const string testToken = "eyJ0eXAiOi" + + "JKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IjFpOWlmMDllc0YzaU9sS0I2SW9meVVGSUxnQSIsImtpZC" + + "I6IjFpOWlmMDllc0YzaU9sS0I2SW9meVVGSUxnQSJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY" + + "29yZS53aW5kb3dzLm5ldC8iLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLXBwZS5uZXQvMDQ1NDZiY" + + "zAtYmMxOS00Y2I2LWIxNmQtNTc0OTQxNzFhNGJjLyIsImlhdCI6MTQ4MDU1NjY0MywibmJmIjoxNDgwN" + + "TU2NjQzLCJleHAiOjE0ODA1NjA1NDMsImFjciI6IjEiLCJhbXIiOlsicHdkIl0sImFwcGlkIjoiMTk1M" + + "GEyNTgtMjI3Yi00ZTMxLWE5Y2YtNzE3NDk1OTQ1ZmMyIiwiYXBwaWRhY3IiOiIwIiwiZV9leHAiOjEwO" + + "DAwLCJmYW1pbHlfbmFtZSI6IlN1c21hbiIsImdpdmVuX25hbWUiOiJEZXJ5YSIsImdyb3VwcyI6WyI0Y" + + "zNmNjNiNy1mZWU1LTQ1ZWItOTAwMy03YWQ1ZDM5MzMzMDIiXSwiaXBhZGRyIjoiMTY3LjIyMC4wLjExM" + + "yIsIm5hbWUiOiJEZXJ5YSBTdXNtYW4iLCJvaWQiOiJhODMyOWI5OS01NGI1LTQwNDctOTU5NS1iNWZkN" + + "2VhMzgyZjYiLCJwbGF0ZiI6IjMiLCJwdWlkIjoiMTAwMzAwMDA5QUJGRTQyRiIsInNjcCI6InVzZXJfa" + + "W1wZXJzb25hdGlvbiIsInN1YiI6ImEyUE5ZZW9KSnk3VnFFVWVkb0ZxS0J6UUNjOWNUN2tCVWtSYm5BM" + + "ldLcnciLCJ0aWQiOiIwNDU0NmJjMC1iYzE5LTRjYjYtYjE2ZC01NzQ5NDE3MWE0YmMiLCJ1bmlxdWVfb" + + "mFtZSI6ImF6dGVzdDBAc3RhYmxldGVzdC5jY3NjdHAubmV0IiwidXBuIjoiYXp0ZXN0MEBzdGFibGV0Z" + + "XN0LmNjc2N0cC5uZXQiLCJ2ZXIiOiIxLjAiLCJ3aWRzIjpbIjYyZTkwMzk0LTY5ZjUtNDIzNy05MTkwL" + + "TAxMjE3NzE0NWUxMCJdfQ.W9eVq_TXGBjWCCl_tRGXM31OZn5G4UBIi6B9xZphvrpaAvu5tnzYm6XWah" + + "jwA_iE1djOpZM3rxFxP4ZFecVyZGHYVddSJ0rg6vw-L4J5jIPDSojqiGoSLtU8yFxEDRaro0SM4LdQ_N" + + "dF-oUwfUQGy88vLOejQdiKzfC-yFvtVSmYoyJSnkZLglDEbhySvLtjXGfpOgiyGLoncV5wTk6Vbf7VLe" + + "65kxhZWVUbTHaPuEvg03ZQ3esDb6wxQewJPAL-GARg6S9wIN776Esw8-53AWhzFu0fIut-9FXGma6jV7" + + "MYPoUUcFuQzLZgphecPyMPXSVhummVCdBwX9sizxnmFA"; + + public DataPlaneCommandTests(ITestOutputHelper output) + { + XunitTracingInterceptor.AddToContext(new XunitTracingInterceptor(output)); + SynchronizeAzureAzureAnalysisServer.DefaultRetryIntervalForPolling = TimeSpan.FromSeconds(0); + } + + #region TestAuthentication + + private class TestAuthenticationCmdlet : AsAzureDataplaneCmdletBase { } + + // TODO: this needs a valid mocked context in order to test authentication. + //[Fact] + //[Trait(Category.AcceptanceType, Category.CheckIn)] + //public void Authentication_Succeeds() + //{ + // var context = new PSAzureContext(); + // var cmdlet = new TestAuthenticationCmdlet() + // { + // CurrentContext = context + // }; + + // cmdlet.InvokeBeginProcessing(); + // cmdlet.InvokeEndProcessing(); + //} + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void Authentication_FailsFromNullContext() + { + var cmdlet = new TestAuthenticationCmdlet() + { + CurrentContext = null + }; + Assert.Throws(() => cmdlet.InvokeBeginProcessing()); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void Authentication_FailsFromBadContext() + { + var cmdlet = new TestAuthenticationCmdlet() + { + CurrentContext = new PSAzureContext() + }; + Assert.Throws(() => cmdlet.InvokeBeginProcessing()); + } + + #endregion + #region TestRestart + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void RestartAzureASInstance_NullInstanceThrows() + { + var restartCmdlet = CreateTestRestartCmdlet(null); + Assert.Throws(() => restartCmdlet.InvokeBeginProcessing()); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void RestartAzureASInstance_InvalidInstanceThrows() + { + var restartCmdlet = CreateTestRestartCmdlet("https://bad.uri.com"); + Assert.Throws(() => restartCmdlet.InvokeBeginProcessing()); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void RestartAzureASInstance_Succeeds() + { + var restartCmdlet = CreateTestRestartCmdlet(testInstance); + // Set up mock http client + var mockHttpClient = new Mock(); + mockHttpClient + .Setup(m => m.CallPostAsync(It.IsAny(), It.IsAny())) + .Returns(Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK))); + restartCmdlet.AsAzureDataplaneClient = mockHttpClient.Object; + + restartCmdlet.InvokeBeginProcessing(); + restartCmdlet.ExecuteCmdlet(); + restartCmdlet.InvokeEndProcessing(); + } + + private static RestartAzureAnalysisServer CreateTestRestartCmdlet(string instance) + { + var commandRuntimeMock = new Mock(); + commandRuntimeMock.Setup(f => f.ShouldProcess(It.IsAny(), It.IsAny())).Returns(true); + + var cmdlet = new RestartAzureAnalysisServer() + { + CommandRuntime = commandRuntimeMock.Object, + Instance = instance + }; + + return cmdlet; + } + + #endregion + #region TestExportLog + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void ExportAzureASInstanceLogTest() + { + var commandRuntimeMock = new Mock(); + commandRuntimeMock.Setup(f => f.ShouldProcess(It.IsAny(), It.IsAny())).Returns(true); + + var mockHttpClient = new Mock(); + mockHttpClient + .Setup(m => m.CallGetAsync(It.IsAny())) + .Returns(Task.FromResult( + new HttpResponseMessage(HttpStatusCode.OK) + { + Content = new StringContent("MOCKED STREAM CONTENT") + })); + + var exportCmdlet = new ExportAzureAnalysisServerLog() + { + CommandRuntime = commandRuntimeMock.Object, + Instance = testInstance, + OutputPath = System.IO.Path.GetTempFileName(), + AsAzureDataplaneClient = mockHttpClient.Object + }; + + try + { + exportCmdlet.InvokeBeginProcessing(); + exportCmdlet.ExecuteCmdlet(); + exportCmdlet.InvokeEndProcessing(); + } + finally + { + if (System.IO.File.Exists(exportCmdlet.OutputPath)) + { + System.IO.File.Delete(exportCmdlet.OutputPath); + } + } + } + + #endregion + #region TestSync + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void SynchronizeAzureASInstance_SingleDB_Succeeds() + { + var syncCmdlet = CreateTestSyncCmdlet(); + syncCmdlet.InvokeBeginProcessing(); + syncCmdlet.ExecuteCmdlet(); + syncCmdlet.InvokeEndProcessing(); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void SynchronizeAzureASInstance_FailsAfterTooManyRetries() + { + var syncCmdlet = CreateTestSyncCmdlet(tooManyRetries: true); + syncCmdlet.InvokeBeginProcessing(); + Assert.Throws(() => syncCmdlet.ExecuteCmdlet()); + syncCmdlet.InvokeEndProcessing(); + } + + private SynchronizeAzureAzureAnalysisServer CreateTestSyncCmdlet(bool tooManyRetries = false) + { + // Set up mock http client + var mockHttpClient = new Mock(); + + ClusterResolutionResult resolveResult = new ClusterResolutionResult() + { + ClusterFQDN = "resolved.westcentralus.asazure.windows.net", + CoreServerName = testInstance + ":rw", + TenantId = Guid.NewGuid().ToString() + }; + mockHttpClient + .Setup(m => m.CallPostAsync( + It.IsAny(), + It.Is(s => s.Contains("clusterResolve")), + It.IsAny())) + .Returns(Task.FromResult( + new HttpResponseMessage(HttpStatusCode.OK) + { + Content = new StringContent(JsonConvert.SerializeObject(resolveResult)) + })); + + var postResponse = new HttpResponseMessage(HttpStatusCode.Accepted); + postResponse.Headers.Location = new Uri("https://done"); + postResponse.Headers.RetryAfter = new RetryConditionHeaderValue(TimeSpan.FromMilliseconds(500)); + postResponse.Headers.Add("x-ms-root-activity-id", Guid.NewGuid().ToString()); + postResponse.Headers.Add("x-ms-current-utc-date", Guid.NewGuid().ToString()); + mockHttpClient + .Setup(m => m.CallPostAsync( + It.IsAny(), + It.Is(s => s.Contains("sync")), + It.IsAny(), + null)) + .Returns(Task>.FromResult(postResponse)); + + var getResponse = new HttpResponseMessage(HttpStatusCode.SeeOther); + getResponse.Headers.Location = new Uri("https://done"); + getResponse.Headers.RetryAfter = new RetryConditionHeaderValue(TimeSpan.FromMilliseconds(500)); + getResponse.Headers.Add("x-ms-root-activity-id", Guid.NewGuid().ToString()); + getResponse.Headers.Add("x-ms-current-utc-date", Guid.NewGuid().ToString()); + mockHttpClient + .Setup(m => m.CallGetAsync( + It.Is(u => u.OriginalString.Contains("1")), + string.Empty, + It.IsAny())) + .Returns(Task.FromResult(getResponse)); + + var getResponseSucceed = new HttpResponseMessage + { + StatusCode = HttpStatusCode.OK, + Content = new StringContent("{\n\"database\":\"db0\",\n\"syncstate\":\"Completed\"\n}", Encoding.UTF8, "application/json") + }; + getResponseSucceed.Headers.Add("x-ms-root-activity-id", Guid.NewGuid().ToString()); + getResponseSucceed.Headers.Add("x-ms-current-utc-date", Guid.NewGuid().ToString()); + + var getResponseError = new HttpResponseMessage(HttpStatusCode.InternalServerError); + getResponseError.Headers.Add("x-ms-root-activity-id", Guid.NewGuid().ToString()); + getResponseError.Headers.Add("x-ms-current-utc-date", Guid.NewGuid().ToString()); + + var finalResponses = tooManyRetries ? + new Queue(new[] { getResponseError, getResponseError, getResponseError, getResponseSucceed }) : + new Queue(new[] { getResponseError, getResponseSucceed }); + + mockHttpClient + .Setup(m => m.CallGetAsync( + It.Is(u => u.OriginalString.Contains("done")), + string.Empty, + It.IsAny())) + .Returns(() => Task.FromResult(finalResponses.Dequeue())); + + Mock commandRuntimeMock = new Mock(); + commandRuntimeMock.Setup(f => f.ShouldProcess(It.IsAny(), It.IsAny())).Returns(true); + + var cmdlet = new SynchronizeAzureAzureAnalysisServer() + { + CommandRuntime = commandRuntimeMock.Object, + Instance = testInstance + ":rw", + Database = "db0", + AsAzureDataplaneClient = mockHttpClient.Object + }; + + return cmdlet; + } + + #endregion + } +} From d2768adccc48821658e9678e44dec8578929e7b2 Mon Sep 17 00:00:00 2001 From: Gabriel Prestemon Date: Fri, 11 Jan 2019 09:49:19 -0800 Subject: [PATCH 013/141] Move common authentication test code into its own method. --- .../InMemoryTests/DataPlaneCommandTests.cs | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/src/AnalysisServices/AnalysisServices.Test/InMemoryTests/DataPlaneCommandTests.cs b/src/AnalysisServices/AnalysisServices.Test/InMemoryTests/DataPlaneCommandTests.cs index a682324be7d2..bc19784c1505 100644 --- a/src/AnalysisServices/AnalysisServices.Test/InMemoryTests/DataPlaneCommandTests.cs +++ b/src/AnalysisServices/AnalysisServices.Test/InMemoryTests/DataPlaneCommandTests.cs @@ -32,6 +32,7 @@ using System.Collections.Generic; using System.Net.Http.Headers; using Newtonsoft.Json; +using Microsoft.Azure.Commands.Common.Authentication.Abstractions; namespace Microsoft.Azure.Commands.AnalysisServices.Test.InMemoryTests { @@ -76,35 +77,31 @@ private class TestAuthenticationCmdlet : AsAzureDataplaneCmdletBase { } //public void Authentication_Succeeds() //{ // var context = new PSAzureContext(); - // var cmdlet = new TestAuthenticationCmdlet() - // { - // CurrentContext = context - // }; - - // cmdlet.InvokeBeginProcessing(); - // cmdlet.InvokeEndProcessing(); + // TestAuthentication(context); //} [Fact] [Trait(Category.AcceptanceType, Category.CheckIn)] public void Authentication_FailsFromNullContext() { - var cmdlet = new TestAuthenticationCmdlet() - { - CurrentContext = null - }; - Assert.Throws(() => cmdlet.InvokeBeginProcessing()); + Assert.Throws(() => TestAuthentication(null)); } [Fact] [Trait(Category.AcceptanceType, Category.CheckIn)] public void Authentication_FailsFromBadContext() + { + Assert.Throws(() => TestAuthentication(new PSAzureContext())); + } + + private void TestAuthentication(IAzureContext context) { var cmdlet = new TestAuthenticationCmdlet() { - CurrentContext = new PSAzureContext() + CurrentContext = context }; - Assert.Throws(() => cmdlet.InvokeBeginProcessing()); + cmdlet.InvokeBeginProcessing(); + cmdlet.InvokeEndProcessing(); } #endregion From 7845fc7800b01f41ffbea154985db82712c6e14b Mon Sep 17 00:00:00 2001 From: Gabriel Prestemon Date: Fri, 11 Jan 2019 11:36:54 -0800 Subject: [PATCH 014/141] Add cmdlet markdown help files generated by platyPS. --- .../help/Add-AzAnalysisServicesAccount.md | 224 ------------------ .../help/Az.AnalysisServices.md | 5 +- .../Export-AzAnalysisServicesInstanceLog.md | 21 +- .../help/Get-AzAnalysisServicesServer.md | 2 +- .../New-AzAnalysisServicesFirewallConfig.md | 2 +- .../New-AzAnalysisServicesFirewallRule.md | 2 +- .../help/New-AzAnalysisServicesServer.md | 2 +- .../help/Remove-AzAnalysisServicesServer.md | 2 +- .../Restart-AzAnalysisServicesInstance.md | 2 +- .../help/Resume-AzAnalysisServicesServer.md | 2 +- .../help/Set-AzAnalysisServicesServer.md | 2 +- .../help/Suspend-AzAnalysisServicesServer.md | 2 +- .../help/Sync-AzAnalysisServicesInstance.md | 8 +- .../help/Test-AzAnalysisServicesServer.md | 2 +- 14 files changed, 33 insertions(+), 245 deletions(-) delete mode 100644 src/AnalysisServices/AnalysisServices/help/Add-AzAnalysisServicesAccount.md diff --git a/src/AnalysisServices/AnalysisServices/help/Add-AzAnalysisServicesAccount.md b/src/AnalysisServices/AnalysisServices/help/Add-AzAnalysisServicesAccount.md deleted file mode 100644 index ce74bfff3171..000000000000 --- a/src/AnalysisServices/AnalysisServices/help/Add-AzAnalysisServicesAccount.md +++ /dev/null @@ -1,224 +0,0 @@ ---- -external help file: Microsoft.Azure.PowerShell.Cmdlets.AnalysisServices.Dataplane.dll-Help.xml -Module Name: Az.AnalysisServices -online version: https://docs.microsoft.com/en-us/powershell/module/az.analysisservices/add-azanalysisservicesaccount -schema: 2.0.0 ---- - -# Add-AzAnalysisServicesAccount - -## SYNOPSIS -Adds an authenticated account to use for Azure Analysis Services server cmdlet requests. - -## SYNTAX - -### UserParameterSetName (Default) -``` -Add-AzAnalysisServicesAccount [[-RolloutEnvironment] ] [[-Credential] ] [-WhatIf] - [-Confirm] [] -``` - -### ServicePrincipalWithPasswordParameterSetName -``` -Add-AzAnalysisServicesAccount [-RolloutEnvironment] [-Credential] [-ServicePrincipal] - -TenantId [-WhatIf] [-Confirm] [] -``` - -### ServicePrincipalWithCertificateParameterSetName -``` -Add-AzAnalysisServicesAccount [-RolloutEnvironment] [-ServicePrincipal] -TenantId - -ApplicationId -CertificateThumbprint [-WhatIf] [-Confirm] [] -``` - -## DESCRIPTION -The Add-AzAnalysisServicesAccount cmdlet is used to login to an instance of Azure Analysis Services server - -## EXAMPLES - -### Example 1 -``` -PS C:\>Add-AzAnalysisServicesAccount -RolloutEnvironment: westcentralus.asazure.windows.net -Credential: $UserCredential -``` - -This example will add the account specified by the $UserCredential variable to the westcentralus.asazure.windows.net Analysis Services environment. - -### Example 2 -``` -PS C:\>$ApplicationCredential = Get-Credential -PS C:\>Add-AzAnalysisServicesAccount -RolloutEnvironment 'westcentralus.asazure.windows.net' -ServicePrincipal -Credential $ApplicationCredential -TenantId "xxxx-xxxx-xxxx-xxxx" -``` - -The first command gets the application service principal credentials, and then stores them in the $ApplicationCredential variable. -The second command add the application service principal account specified by the $ApplicationCredential variable and TenantId to the westcentralus.asazure.windows.net Analysis Services environment. - -### Example 3 -``` -PS C:\>Add-AzAnalysisServicesAccount -RolloutEnvironment 'westcentralus.asazure.windows.net' -ServicePrincipal -ApplicationId "yyyy-yyyy-yyyy-yyyy" -CertificateThumbprint 'zzzzzzzzzzzzzzzz' -TenantId "xxxx-xxxx-xxxx-xxxx" -``` - -This example will add the application service principal account specified by the ApplicationId, TenantId and CertificateThumbprint to the westcentralus.asazure.windows.net Analysis Services environment. - -## PARAMETERS - -### -ApplicationId -The application ID. - -```yaml -Type: System.String -Parameter Sets: ServicePrincipalWithCertificateParameterSetName -Aliases: - -Required: True -Position: Named -Default value: None -Accept pipeline input: False -Accept wildcard characters: False -``` - -### -CertificateThumbprint -Certificate Hash (Thumbprint) - -```yaml -Type: System.String -Parameter Sets: ServicePrincipalWithCertificateParameterSetName -Aliases: - -Required: True -Position: Named -Default value: None -Accept pipeline input: False -Accept wildcard characters: False -``` - -### -Credential -Login credentials - -```yaml -Type: System.Management.Automation.PSCredential -Parameter Sets: UserParameterSetName -Aliases: - -Required: False -Position: 1 -Default value: None -Accept pipeline input: False -Accept wildcard characters: False -``` - -```yaml -Type: System.Management.Automation.PSCredential -Parameter Sets: ServicePrincipalWithPasswordParameterSetName -Aliases: - -Required: True -Position: 1 -Default value: None -Accept pipeline input: False -Accept wildcard characters: False -``` - -### -RolloutEnvironment -Name of the Azure Analysis Services environment to which to logon to. Given the full name of the server for example asazure://westcentralus.asazure.windows.net/testserver , the correct value for this variable will be westcentralus.asazure.windows.net - -```yaml -Type: System.String -Parameter Sets: UserParameterSetName -Aliases: - -Required: False -Position: 0 -Default value: None -Accept pipeline input: False -Accept wildcard characters: False -``` - -```yaml -Type: System.String -Parameter Sets: ServicePrincipalWithPasswordParameterSetName, ServicePrincipalWithCertificateParameterSetName -Aliases: - -Required: True -Position: 0 -Default value: None -Accept pipeline input: False -Accept wildcard characters: False -``` - -### -ServicePrincipal -Indicates that this account authenticates by providing service principal credentials. - -```yaml -Type: System.Management.Automation.SwitchParameter -Parameter Sets: ServicePrincipalWithPasswordParameterSetName, ServicePrincipalWithCertificateParameterSetName -Aliases: - -Required: True -Position: Named -Default value: None -Accept pipeline input: False -Accept wildcard characters: False -``` - -### -TenantId -Tenant name or ID - -```yaml -Type: System.String -Parameter Sets: ServicePrincipalWithPasswordParameterSetName, ServicePrincipalWithCertificateParameterSetName -Aliases: - -Required: True -Position: Named -Default value: None -Accept pipeline input: False -Accept wildcard characters: False -``` - -### -Confirm -Prompts you for confirmation before running the cmdlet. - -```yaml -Type: System.Management.Automation.SwitchParameter -Parameter Sets: (All) -Aliases: cf - -Required: False -Position: Named -Default value: None -Accept pipeline input: False -Accept wildcard characters: False -``` - -### -WhatIf -Shows what would happen if the cmdlet runs. -The cmdlet is not run. - -```yaml -Type: System.Management.Automation.SwitchParameter -Parameter Sets: (All) -Aliases: wi - -Required: False -Position: Named -Default value: None -Accept pipeline input: False -Accept wildcard characters: False -``` - -### CommonParameters -This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). - -## INPUTS - -### None - -## OUTPUTS - -### Microsoft.Azure.Commands.AnalysisServices.Dataplane.AsAzureProfile - -## NOTES -Alias: Login-AzAsAccount - -## RELATED LINKS diff --git a/src/AnalysisServices/AnalysisServices/help/Az.AnalysisServices.md b/src/AnalysisServices/AnalysisServices/help/Az.AnalysisServices.md index eac6ad4059e2..3f4ef0c59e8e 100644 --- a/src/AnalysisServices/AnalysisServices/help/Az.AnalysisServices.md +++ b/src/AnalysisServices/AnalysisServices/help/Az.AnalysisServices.md @@ -1,4 +1,4 @@ ---- +--- Module Name: Az.AnalysisServices Module Guid: acace26c-1775-4100-85c0-20c4d71eaa21 Download Help Link: https://docs.microsoft.com/en-us/powershell/module/az.analysisservices @@ -11,9 +11,6 @@ Locale: en-US This topic displays help topics for the Azure AnalysisServices cmdlets. ## Az.AnalysisServices Cmdlets -### [Add-AzAnalysisServicesAccount](Add-AzAnalysisServicesAccount.md) -Adds an authenticated account to use for Azure Analysis Services server cmdlet requests. - ### [Export-AzAnalysisServicesInstanceLog](Export-AzAnalysisServicesInstanceLog.md) Exports a log from an instance of Analysis Services server in the currently logged in Environment as specified in Add-AzAnalysisServicesAccount command diff --git a/src/AnalysisServices/AnalysisServices/help/Export-AzAnalysisServicesInstanceLog.md b/src/AnalysisServices/AnalysisServices/help/Export-AzAnalysisServicesInstanceLog.md index c7214c454c2e..6d7dcdf6fc65 100644 --- a/src/AnalysisServices/AnalysisServices/help/Export-AzAnalysisServicesInstanceLog.md +++ b/src/AnalysisServices/AnalysisServices/help/Export-AzAnalysisServicesInstanceLog.md @@ -1,4 +1,4 @@ ---- +--- external help file: Microsoft.Azure.PowerShell.Cmdlets.AnalysisServices.Dataplane.dll-Help.xml Module Name: Az.AnalysisServices online version: https://docs.microsoft.com/en-us/powershell/module/az.analysisservices/export-azanalysisservicesinstancelog @@ -13,8 +13,8 @@ Exports a log from an instance of Analysis Services server in the currently logg ## SYNTAX ``` -Export-AzAnalysisServicesInstanceLog -Instance -OutputPath [-Force] [-WhatIf] [-Confirm] - [] +Export-AzAnalysisServicesInstanceLog -OutputPath [-Force] -Instance [-PassThru] [-WhatIf] + [-Confirm] [] ``` ## DESCRIPTION @@ -77,6 +77,21 @@ Accept pipeline input: False Accept wildcard characters: False ``` +### -PassThru +{{Fill PassThru Description}} + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ### -Confirm Prompts you for confirmation before running the cmdlet. diff --git a/src/AnalysisServices/AnalysisServices/help/Get-AzAnalysisServicesServer.md b/src/AnalysisServices/AnalysisServices/help/Get-AzAnalysisServicesServer.md index 47ea00eb0d91..420e3cd40359 100644 --- a/src/AnalysisServices/AnalysisServices/help/Get-AzAnalysisServicesServer.md +++ b/src/AnalysisServices/AnalysisServices/help/Get-AzAnalysisServicesServer.md @@ -1,4 +1,4 @@ ---- +--- external help file: Microsoft.Azure.PowerShell.Cmdlets.AnalysisServices.dll-Help.xml Module Name: Az.AnalysisServices online version: https://docs.microsoft.com/en-us/powershell/module/az.analysisservices/get-azanalysisservicesserver diff --git a/src/AnalysisServices/AnalysisServices/help/New-AzAnalysisServicesFirewallConfig.md b/src/AnalysisServices/AnalysisServices/help/New-AzAnalysisServicesFirewallConfig.md index 3be5b9d32442..bf794512924b 100644 --- a/src/AnalysisServices/AnalysisServices/help/New-AzAnalysisServicesFirewallConfig.md +++ b/src/AnalysisServices/AnalysisServices/help/New-AzAnalysisServicesFirewallConfig.md @@ -1,4 +1,4 @@ ---- +--- external help file: Microsoft.Azure.PowerShell.Cmdlets.AnalysisServices.dll-Help.xml Module Name: Az.AnalysisServices online version: https://docs.microsoft.com/en-us/powershell/module/az.analysisservices/new-azanalysisservicesfirewallconfig diff --git a/src/AnalysisServices/AnalysisServices/help/New-AzAnalysisServicesFirewallRule.md b/src/AnalysisServices/AnalysisServices/help/New-AzAnalysisServicesFirewallRule.md index 422d4ba42c53..e57b945abbd9 100644 --- a/src/AnalysisServices/AnalysisServices/help/New-AzAnalysisServicesFirewallRule.md +++ b/src/AnalysisServices/AnalysisServices/help/New-AzAnalysisServicesFirewallRule.md @@ -1,4 +1,4 @@ ---- +--- external help file: Microsoft.Azure.PowerShell.Cmdlets.AnalysisServices.dll-Help.xml Module Name: Az.AnalysisServices online version: https://docs.microsoft.com/en-us/powershell/module/az.analysisservices/new-azanalysisservicesfirewallrule diff --git a/src/AnalysisServices/AnalysisServices/help/New-AzAnalysisServicesServer.md b/src/AnalysisServices/AnalysisServices/help/New-AzAnalysisServicesServer.md index 295ff5c4bbe7..ef018a64faf5 100644 --- a/src/AnalysisServices/AnalysisServices/help/New-AzAnalysisServicesServer.md +++ b/src/AnalysisServices/AnalysisServices/help/New-AzAnalysisServicesServer.md @@ -1,4 +1,4 @@ ---- +--- external help file: Microsoft.Azure.PowerShell.Cmdlets.AnalysisServices.dll-Help.xml Module Name: Az.AnalysisServices online version: https://docs.microsoft.com/en-us/powershell/module/az.analysisservices/new-azanalysisservicesserver diff --git a/src/AnalysisServices/AnalysisServices/help/Remove-AzAnalysisServicesServer.md b/src/AnalysisServices/AnalysisServices/help/Remove-AzAnalysisServicesServer.md index 16883b9951fc..e633b9db9556 100644 --- a/src/AnalysisServices/AnalysisServices/help/Remove-AzAnalysisServicesServer.md +++ b/src/AnalysisServices/AnalysisServices/help/Remove-AzAnalysisServicesServer.md @@ -1,4 +1,4 @@ ---- +--- external help file: Microsoft.Azure.PowerShell.Cmdlets.AnalysisServices.dll-Help.xml Module Name: Az.AnalysisServices online version: https://docs.microsoft.com/en-us/powershell/module/az.analysisservices/remove-azanalysisservicesserver diff --git a/src/AnalysisServices/AnalysisServices/help/Restart-AzAnalysisServicesInstance.md b/src/AnalysisServices/AnalysisServices/help/Restart-AzAnalysisServicesInstance.md index 0ff0a2b8b0b9..a9f6f5bf5157 100644 --- a/src/AnalysisServices/AnalysisServices/help/Restart-AzAnalysisServicesInstance.md +++ b/src/AnalysisServices/AnalysisServices/help/Restart-AzAnalysisServicesInstance.md @@ -1,4 +1,4 @@ ---- +--- external help file: Microsoft.Azure.PowerShell.Cmdlets.AnalysisServices.Dataplane.dll-Help.xml Module Name: Az.AnalysisServices online version: https://docs.microsoft.com/en-us/powershell/module/az.analysisservices/restart-azanalysisservicesinstance diff --git a/src/AnalysisServices/AnalysisServices/help/Resume-AzAnalysisServicesServer.md b/src/AnalysisServices/AnalysisServices/help/Resume-AzAnalysisServicesServer.md index 0c22936dab93..b1ced000a4c4 100644 --- a/src/AnalysisServices/AnalysisServices/help/Resume-AzAnalysisServicesServer.md +++ b/src/AnalysisServices/AnalysisServices/help/Resume-AzAnalysisServicesServer.md @@ -1,4 +1,4 @@ ---- +--- external help file: Microsoft.Azure.PowerShell.Cmdlets.AnalysisServices.dll-Help.xml Module Name: Az.AnalysisServices online version: https://docs.microsoft.com/en-us/powershell/module/az.analysisservices/resume-azanalysisservicesserver diff --git a/src/AnalysisServices/AnalysisServices/help/Set-AzAnalysisServicesServer.md b/src/AnalysisServices/AnalysisServices/help/Set-AzAnalysisServicesServer.md index a6958c9e93aa..d04ed846d46f 100644 --- a/src/AnalysisServices/AnalysisServices/help/Set-AzAnalysisServicesServer.md +++ b/src/AnalysisServices/AnalysisServices/help/Set-AzAnalysisServicesServer.md @@ -1,4 +1,4 @@ ---- +--- external help file: Microsoft.Azure.PowerShell.Cmdlets.AnalysisServices.dll-Help.xml Module Name: Az.AnalysisServices online version: https://docs.microsoft.com/en-us/powershell/module/az.analysisservices/set-azanalysisservicesserver diff --git a/src/AnalysisServices/AnalysisServices/help/Suspend-AzAnalysisServicesServer.md b/src/AnalysisServices/AnalysisServices/help/Suspend-AzAnalysisServicesServer.md index f59cf13aad65..6aca543ac679 100644 --- a/src/AnalysisServices/AnalysisServices/help/Suspend-AzAnalysisServicesServer.md +++ b/src/AnalysisServices/AnalysisServices/help/Suspend-AzAnalysisServicesServer.md @@ -1,4 +1,4 @@ ---- +--- external help file: Microsoft.Azure.PowerShell.Cmdlets.AnalysisServices.dll-Help.xml Module Name: Az.AnalysisServices online version: https://docs.microsoft.com/en-us/powershell/module/az.analysisservices/suspend-azanalysisservicesserver diff --git a/src/AnalysisServices/AnalysisServices/help/Sync-AzAnalysisServicesInstance.md b/src/AnalysisServices/AnalysisServices/help/Sync-AzAnalysisServicesInstance.md index 902cf1a0046e..93eecd5405b6 100644 --- a/src/AnalysisServices/AnalysisServices/help/Sync-AzAnalysisServicesInstance.md +++ b/src/AnalysisServices/AnalysisServices/help/Sync-AzAnalysisServicesInstance.md @@ -1,4 +1,4 @@ ---- +--- external help file: Microsoft.Azure.PowerShell.Cmdlets.AnalysisServices.Dataplane.dll-Help.xml Module Name: Az.AnalysisServices online version: https://docs.microsoft.com/en-us/powershell/module/az.analysisservices/sync-azanalysisservicesinstance @@ -14,7 +14,7 @@ Synchronizes a specified database on the specified instance of Analysis Services ## SYNTAX ``` -Sync-AzAnalysisServicesInstance [-Instance] [-Database] [-PassThru] [-WhatIf] [-Confirm] +Sync-AzAnalysisServicesInstance [-Database] -Instance [-PassThru] [-WhatIf] [-Confirm] [] ``` @@ -60,9 +60,9 @@ Parameter Sets: (All) Aliases: Required: True -Position: 0 +Position: Named Default value: None -Accept pipeline input: True (ByValue) +Accept pipeline input: False Accept wildcard characters: False ``` diff --git a/src/AnalysisServices/AnalysisServices/help/Test-AzAnalysisServicesServer.md b/src/AnalysisServices/AnalysisServices/help/Test-AzAnalysisServicesServer.md index 553fe3040d79..3b58cc6cacbc 100644 --- a/src/AnalysisServices/AnalysisServices/help/Test-AzAnalysisServicesServer.md +++ b/src/AnalysisServices/AnalysisServices/help/Test-AzAnalysisServicesServer.md @@ -1,4 +1,4 @@ ---- +--- external help file: Microsoft.Azure.PowerShell.Cmdlets.AnalysisServices.dll-Help.xml Module Name: Az.AnalysisServices online version: https://docs.microsoft.com/en-us/powershell/module/az.analysisservices/test-azanalysisservicesserver From 4df833dfd1e87addf972be60ef8bc5d2114ef0d9 Mon Sep 17 00:00:00 2001 From: Gabriel Prestemon Date: Mon, 14 Jan 2019 09:29:16 -0800 Subject: [PATCH 015/141] Move ClusterResolve() from base class to Sync-AzureASInstance, since it is not used in any other derived classes. --- .../Commands/Synchronize-AzureASInstance.cs | 14 ++++++++++++-- .../Models/AsAzureDataplaneCmdletBase.cs | 14 -------------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Synchronize-AzureASInstance.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Synchronize-AzureASInstance.cs index b6a25e71a05e..4681e8866a67 100644 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Synchronize-AzureASInstance.cs +++ b/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Synchronize-AzureASInstance.cs @@ -350,8 +350,18 @@ private async Task PollSyncStatusWithRetryAsyn /// The . private ClusterResolutionResult ClusterResolve(string serverName) { - Uri clusterResolveBaseUri = new Uri(string.Format("{0}{1}{2}", Uri.UriSchemeHttps, Uri.SchemeDelimiter, DnsSafeHost)); - return ClusterResolve(clusterResolveBaseUri, serverName); + Uri clusterUri = new Uri(string.Format("{0}{1}{2}", Uri.UriSchemeHttps, Uri.SchemeDelimiter, DnsSafeHost)); + + var content = new StringContent($"ServerName={serverName}"); + content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/x-www-form-urlencoded"); + + this.AsAzureDataplaneClient.ResetHttpClient(); + using (var message = AsAzureDataplaneClient.CallPostAsync(clusterUri, AsAzureEndpoints.ClusterResolveEndpoint, content).Result) + { + message.EnsureSuccessStatusCode(); + var rawResult = message.Content.ReadAsStringAsync().Result; + return JsonConvert.DeserializeObject(rawResult); + } } } } diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs index 95d32b210742..2ff51e94893b 100644 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs +++ b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs @@ -136,20 +136,6 @@ protected override void BeginProcessing() } } - protected ClusterResolutionResult ClusterResolve(Uri clusterUri, string serverName) - { - var content = new StringContent($"ServerName={serverName}"); - content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/x-www-form-urlencoded"); - - this.AsAzureDataplaneClient.ResetHttpClient(); - using (var message = AsAzureDataplaneClient.CallPostAsync(clusterUri, AsAzureEndpoints.ClusterResolveEndpoint, content).Result) - { - message.EnsureSuccessStatusCode(); - var rawResult = message.Content.ReadAsStringAsync().Result; - return JsonConvert.DeserializeObject(rawResult); - } - } - internal static AsAzureDataplaneClient CreateAsAzureDataplaneClient(string hostUri, IAzureContext context, Func httpClientProvider, bool parameterizedBaseUri = false) { if (context == null) From 5a1f515e74386a483dd3ff91d007869f4dc076b0 Mon Sep 17 00:00:00 2001 From: Gabriel Prestemon Date: Mon, 14 Jan 2019 12:36:45 -0800 Subject: [PATCH 016/141] Add documentation. Remove unnecessary BaseUri public set in AsAzureDataplaneClient. Remove unused argument parameterizedBaseUri in method AsAzureDataplaneCmdletBase.CreateAsAzureDataplaneClient(). --- .../Commands/Export-AzureAsInstanceLog.cs | 4 +- .../Commands/Restart-AzureAsInstance.cs | 4 +- .../Commands/Synchronize-AzureASInstance.cs | 50 +++++++++---- .../Models/AsAzureDataplaneClient.cs | 71 ++++++++++--------- .../Models/AsAzureDataplaneCmdletBase.cs | 34 +++++++-- .../Models/IAsAzureHttpClient.cs | 36 ++++++++++ 6 files changed, 145 insertions(+), 54 deletions(-) diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Export-AzureAsInstanceLog.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Export-AzureAsInstanceLog.cs index e7ef18fb2c71..54edeb0868ff 100644 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Export-AzureAsInstanceLog.cs +++ b/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Export-AzureAsInstanceLog.cs @@ -17,11 +17,12 @@ using Microsoft.Azure.Commands.Common.Authentication; using Microsoft.Azure.Commands.AnalysisServices.Dataplane.Models; using Microsoft.Azure.Commands.AnalysisServices.Dataplane.Properties; +using Microsoft.WindowsAzure.Commands.Utilities.Common; namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane { /// - /// Cmdlet to export an Analysis Services server log to file + /// Cmdlet to export an Analysis Services server log to file. /// [Cmdlet("Export", ResourceManager.Common.AzureRMConstants.AzurePrefix + "AnalysisServicesInstanceLog", SupportsShouldProcess = true)] [Alias("Export-AzureAsInstanceLog", "Export-AzAsInstanceLog")] @@ -36,6 +37,7 @@ public class ExportAzureAnalysisServerLog : AsAzureDataplaneCmdletBase [ValidateNotNullOrEmpty] public SwitchParameter Force { get; set; } + /// public override void ExecuteCmdlet() { if (!ShouldProcess(Instance, Resources.ExportingLogFromAnalysisServicesServer)) diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Restart-AzureAsInstance.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Restart-AzureAsInstance.cs index 195c970302df..c3a1d251f631 100644 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Restart-AzureAsInstance.cs +++ b/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Restart-AzureAsInstance.cs @@ -15,17 +15,19 @@ using System.Management.Automation; using Microsoft.Azure.Commands.AnalysisServices.Dataplane.Models; using Microsoft.Azure.Commands.AnalysisServices.Dataplane.Properties; +using Microsoft.WindowsAzure.Commands.Utilities.Common; namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane { /// - /// Cmdlet to log into an Analysis Services environment + /// Cmdlet to restart an Analysis Services server instance. /// [Cmdlet("Restart", ResourceManager.Common.AzureRMConstants.AzurePrefix + "AnalysisServicesInstance", SupportsShouldProcess = true)] [Alias("Restart-AzureAsInstance", "Restart-AzAsInstance")] [OutputType(typeof(bool))] public class RestartAzureAnalysisServer : AsAzureDataplaneCmdletBase { + /// public override void ExecuteCmdlet() { if (!ShouldProcess(Instance, Resources.RestartingAnalysisServicesServer)) diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Synchronize-AzureASInstance.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Synchronize-AzureASInstance.cs index 4681e8866a67..6c428ab59bfd 100644 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Synchronize-AzureASInstance.cs +++ b/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Synchronize-AzureASInstance.cs @@ -23,33 +23,58 @@ using Microsoft.Azure.Commands.AnalysisServices.Dataplane.Models; using Microsoft.Azure.Commands.AnalysisServices.Dataplane.Properties; using Microsoft.Azure.Commands.Common.Authentication.Abstractions; +using Microsoft.WindowsAzure.Commands.Utilities.Common; using Newtonsoft.Json; namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane { /// - /// Cmdlet to log into an Analysis Services environment + /// Cmdlet to sync Analysis Services server databases. /// [Cmdlet("Sync", ResourceManager.Common.AzureRMConstants.AzurePrefix + "AnalysisServicesInstance", SupportsShouldProcess = true)] [Alias("Sync-AzureAsInstance", "Sync-AzAsInstance")] [OutputType(typeof(ScaleOutServerDatabaseSyncDetails))] public class SynchronizeAzureAzureAnalysisServer : AsAzureDataplaneCmdletBase { - private static TimeSpan DefaultPollingInterval = TimeSpan.FromSeconds(30); + /// + /// Default time interval to wait before first poll for sync status. + /// + private static readonly TimeSpan DefaultPollingInterval = TimeSpan.FromSeconds(30); + /// + /// Default time interval to wait between polls for sync status. + /// public static TimeSpan DefaultRetryIntervalForPolling = TimeSpan.FromSeconds(10); + /// + /// Http Header name for root activity id. + /// private readonly string RootActivityIdHeaderName = "x-ms-root-activity-id"; + /// + /// Http Header name for current UTC date and time. + /// private readonly string CurrentUtcDateHeaderName = "x-ms-current-utc-date"; + /// + /// The Cluster Resolution Result object. + /// private ClusterResolutionResult clusterResolveResult; - private Guid correlationId; + /// + /// Correlation ID for http requests. + /// + private Guid correlationId = Guid.Empty; - private string syncRequestRootActivityId; + /// + /// The root activity id for this sync activity. + /// + private string syncRequestRootActivityId = string.Empty; - private string syncRequestTimeStamp; + /// + /// Time stamp for the sync request. + /// + private string syncRequestTimeStamp = string.Empty; [Parameter( Mandatory = true, @@ -59,39 +84,38 @@ public class SynchronizeAzureAzureAnalysisServer : AsAzureDataplaneCmdletBase [ValidateNotNullOrEmpty] public string Database { get; set; } - public SynchronizeAzureAzureAnalysisServer() - { - this.syncRequestRootActivityId = string.Empty; - this.correlationId = Guid.Empty; - this.syncRequestTimeStamp = string.Empty; - } - + /// protected override void BeginProcessing() { this._dataCollectionProfile = new AzurePSDataCollectionProfile(false); base.BeginProcessing(); } + /// protected override void SetupDebuggingTraces() { // nothing to do here. } + /// protected override void TearDownDebuggingTraces() { // nothing to do here. } + /// protected override void SetupHttpClientPipeline() { // nothing to do here. } + /// protected override void TearDownHttpClientPipeline() { // nothing to do here. } + /// public override void ExecuteCmdlet() { if (!ShouldProcess(Instance, Resources.SynchronizingAnalysisServicesServer)) @@ -254,7 +278,7 @@ private async Task SynchronizeDatabaseAsync( } /// - /// + /// Worker Method for the synchronize request. /// /// Database name /// URL for polling diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneClient.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneClient.cs index c109a41812b6..9e6bf87ecdc6 100644 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneClient.cs +++ b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneClient.cs @@ -29,15 +29,25 @@ public class AsAzureDataplaneClient : ServiceClient, IAs /// /// The base Uri of the service. /// - public Uri BaseUri { get; set; } + public Uri BaseUri { get; } /// /// Credentials needed for the client to connect to Azure. /// public ServiceClientCredentials Credentials { get; private set; } + /// + /// Function for providing an for this class. + /// private Func HttpClientProvider { get; set; } + /// + /// Initializes a new instance of the class. + /// + /// The base uri to send http requests to. + /// for authenticating requests. + /// Function for providing an . + /// Additional delegating handlers to be passed to the base class. public AsAzureDataplaneClient(Uri baseUri, ServiceClientCredentials credentials, Func httpClientProvider, params DelegatingHandler[] handlers) : base(handlers) { @@ -48,6 +58,14 @@ public AsAzureDataplaneClient(Uri baseUri, ServiceClientCredentials credentials, this.ResetHttpClient(); } + /// + /// Initializes a new instance of the class. + /// + /// The base uri to send http requests to. + /// for authenticating requests. + /// Function for providing an . + /// The root to be passed to the base class. + /// Additional delegating handlers to be passed to the base class. public AsAzureDataplaneClient(Uri baseUri, ServiceClientCredentials credentials, Func httpClientProvider, HttpClientHandler rootHandler, params DelegatingHandler[] handlers) : base(rootHandler, handlers) { @@ -58,6 +76,9 @@ public AsAzureDataplaneClient(Uri baseUri, ServiceClientCredentials credentials, this.ResetHttpClient(); } + /// + /// Invokes the HttpClientProvider function to reset the HttpClient to a new instance. + /// public void ResetHttpClient() { this.HttpClient = this.HttpClientProvider(); @@ -65,59 +86,31 @@ public void ResetHttpClient() #region CallHttpMethodAsyncOverloads - /// - /// Calls SendRequestAsync() for a GET. - /// - /// The base Uri to call. - /// The request Url. - /// The CorrelationId - /// The http response message. + /// public async Task CallGetAsync(Uri baseUri, string requestUrl, Guid correlationId = new Guid()) { return await SendRequestAsync(HttpMethod.Get, baseUri: baseUri, requestUrl: requestUrl, correlationId: correlationId); } - /// - /// Calls SendRequestAsync() for a GET using the default BaseUri and a blank correlationId. - /// - /// The Request Url. - /// The http response message. + /// public async Task CallGetAsync(string requestUrl) { return await CallGetAsync(BaseUri, requestUrl, new Guid()); } - /// - /// Calls SendRequestAsync() for a POST. - /// - /// The base Uri to call. - /// The request Url. - /// The CorrelationId - /// The content to post (optional). - /// The http response message. + /// public async Task CallPostAsync(Uri baseUri, string requestUrl, Guid correlationId, HttpContent content = null) { return await SendRequestAsync(HttpMethod.Post, baseUri, requestUrl, correlationId, content); } - /// - /// Calls SendRequestAsync() for a POST using a blank correlationId. - /// - /// The base Uri to call. - /// The request Url. - /// The content to post (optional). - /// The http response message. + /// public async Task CallPostAsync(Uri baseUri, string requestUrl, HttpContent content = null) { return await CallPostAsync(baseUri, requestUrl, new Guid(), content); } - /// - /// Calls SendRequestAsync() for a POST using the default BaseUri and a blank correlationId. - /// - /// The Request Url. - /// The content to post (optional). - /// The http response message. + /// public async Task CallPostAsync(string requestUrl, HttpContent content = null) { return await CallPostAsync(BaseUri, requestUrl, content); @@ -125,6 +118,16 @@ public async Task CallPostAsync(string requestUrl, HttpCont #endregion + /// + /// Asynchronosly send an http request. + /// + /// The http method for this request. + /// The base URI to send the request to. + /// The URL endpoint to send the request to. + /// The correlation ID for the request. + /// HttpContent for a POST request. + /// The cancelation token. + /// The of the request. private async Task SendRequestAsync( HttpMethod method, Uri baseUri, diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs index 2ff51e94893b..9838e1d73dcc 100644 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs +++ b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs @@ -16,11 +16,9 @@ using Microsoft.Azure.Commands.Common.Authentication; using Microsoft.Azure.Commands.Common.Authentication.Abstractions; using Microsoft.WindowsAzure.Commands.Utilities.Common; -using Newtonsoft.Json; using System; using System.Management.Automation; using System.Net.Http; -using System.Net.Http.Headers; namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane.Models { @@ -29,8 +27,15 @@ namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane.Models /// public abstract class AsAzureDataplaneCmdletBase : AzurePSCmdlet { + /// + /// Field for the dataplane http client. + /// private IAsAzureHttpClient _asAzureDataplaneClient; + + /// + /// Field for the current azure context, for the environment and profile. + /// private IAzureContext _currentContext; [Parameter(Mandatory = true, HelpMessage = "Name of the Azure Analysis Services server")] @@ -60,6 +65,7 @@ public abstract class AsAzureDataplaneCmdletBase : AzurePSCmdlet /// testserver protected string ServerName; + /// protected override IAzureContext DefaultContext { get @@ -69,6 +75,7 @@ protected override IAzureContext DefaultContext } } + /// protected override string DataCollectionWarning { get @@ -77,9 +84,15 @@ protected override string DataCollectionWarning } } - // No data collection for this commandlet - protected override void InitializeQosEvent() { } + /// + protected override void InitializeQosEvent() + { + // No data collection for this cmdlet + } + /// + /// Gets or sets the . + /// public IAzureContext CurrentContext { get @@ -95,6 +108,9 @@ public IAzureContext CurrentContext set { _currentContext = value; } } + /// + /// Gets or sets the . + /// public IAsAzureHttpClient AsAzureDataplaneClient { get @@ -110,6 +126,7 @@ public IAsAzureHttpClient AsAzureDataplaneClient set { _asAzureDataplaneClient = value; } } + /// protected override void BeginProcessing() { base.BeginProcessing(); @@ -136,7 +153,14 @@ protected override void BeginProcessing() } } - internal static AsAzureDataplaneClient CreateAsAzureDataplaneClient(string hostUri, IAzureContext context, Func httpClientProvider, bool parameterizedBaseUri = false) + /// + /// Creates an instance of an based on parameters. + /// + /// The Uri to derive the from. + /// The to retrieve ServiceClientCredentials from. + /// . + /// An instance of an . + internal static AsAzureDataplaneClient CreateAsAzureDataplaneClient(string hostUri, IAzureContext context, Func httpClientProvider) { if (context == null) { diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Models/IAsAzureHttpClient.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Models/IAsAzureHttpClient.cs index 72d541676c27..68b93cf06f23 100644 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Models/IAsAzureHttpClient.cs +++ b/src/AnalysisServices/AnalysisServices.Dataplane/Models/IAsAzureHttpClient.cs @@ -18,16 +18,52 @@ namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane.Models { + /// + /// Interface for the necessary httpclient methods for dataplane cmdlets. + /// public interface IAsAzureHttpClient { + /// + /// Calls SendRequestAsync() for a GET using the default BaseUri and a blank correlationId. + /// + /// The Request Url. + /// The http response message. Task CallGetAsync(string requestURL); + /// + /// Calls SendRequestAsync() for a GET. + /// + /// The base Uri to call. + /// The request Url. + /// The CorrelationId + /// The http response message. Task CallGetAsync(Uri baseUri, string requestURL, Guid correlationId); + /// + /// Calls SendRequestAsync() for a POST using the default BaseUri and a blank correlationId. + /// + /// The Request Url. + /// The content to post (optional). + /// The http response message. Task CallPostAsync(string requestURL, HttpContent content = null); + /// + /// Calls SendRequestAsync() for a POST using a blank correlationId. + /// + /// The base Uri to call. + /// The request Url. + /// The content to post (optional). + /// The http response message. Task CallPostAsync(Uri baseURI, string requestURL, HttpContent content = null); + /// + /// Calls SendRequestAsync() for a POST. + /// + /// The base Uri to call. + /// The request Url. + /// The CorrelationId + /// The content to post (optional). + /// The http response message. Task CallPostAsync(Uri baseURI, string requestURL, Guid correlationId, HttpContent content = null); void ResetHttpClient(); From 44e3dface89bad8eb4bab11655dc0a73218faf20 Mon Sep 17 00:00:00 2001 From: Gabriel Prestemon Date: Mon, 14 Jan 2019 12:43:47 -0800 Subject: [PATCH 017/141] Undo changes in ASCII art in generated help markdown files. --- .../AnalysisServices/help/Get-AzAnalysisServicesServer.md | 2 +- .../help/New-AzAnalysisServicesFirewallConfig.md | 2 +- .../AnalysisServices/help/New-AzAnalysisServicesFirewallRule.md | 2 +- .../AnalysisServices/help/New-AzAnalysisServicesServer.md | 2 +- .../AnalysisServices/help/Remove-AzAnalysisServicesServer.md | 2 +- .../AnalysisServices/help/Restart-AzAnalysisServicesInstance.md | 2 +- .../AnalysisServices/help/Resume-AzAnalysisServicesServer.md | 2 +- .../AnalysisServices/help/Set-AzAnalysisServicesServer.md | 2 +- .../AnalysisServices/help/Suspend-AzAnalysisServicesServer.md | 2 +- .../AnalysisServices/help/Test-AzAnalysisServicesServer.md | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/AnalysisServices/AnalysisServices/help/Get-AzAnalysisServicesServer.md b/src/AnalysisServices/AnalysisServices/help/Get-AzAnalysisServicesServer.md index 420e3cd40359..47ea00eb0d91 100644 --- a/src/AnalysisServices/AnalysisServices/help/Get-AzAnalysisServicesServer.md +++ b/src/AnalysisServices/AnalysisServices/help/Get-AzAnalysisServicesServer.md @@ -1,4 +1,4 @@ ---- +--- external help file: Microsoft.Azure.PowerShell.Cmdlets.AnalysisServices.dll-Help.xml Module Name: Az.AnalysisServices online version: https://docs.microsoft.com/en-us/powershell/module/az.analysisservices/get-azanalysisservicesserver diff --git a/src/AnalysisServices/AnalysisServices/help/New-AzAnalysisServicesFirewallConfig.md b/src/AnalysisServices/AnalysisServices/help/New-AzAnalysisServicesFirewallConfig.md index bf794512924b..3be5b9d32442 100644 --- a/src/AnalysisServices/AnalysisServices/help/New-AzAnalysisServicesFirewallConfig.md +++ b/src/AnalysisServices/AnalysisServices/help/New-AzAnalysisServicesFirewallConfig.md @@ -1,4 +1,4 @@ ---- +--- external help file: Microsoft.Azure.PowerShell.Cmdlets.AnalysisServices.dll-Help.xml Module Name: Az.AnalysisServices online version: https://docs.microsoft.com/en-us/powershell/module/az.analysisservices/new-azanalysisservicesfirewallconfig diff --git a/src/AnalysisServices/AnalysisServices/help/New-AzAnalysisServicesFirewallRule.md b/src/AnalysisServices/AnalysisServices/help/New-AzAnalysisServicesFirewallRule.md index e57b945abbd9..422d4ba42c53 100644 --- a/src/AnalysisServices/AnalysisServices/help/New-AzAnalysisServicesFirewallRule.md +++ b/src/AnalysisServices/AnalysisServices/help/New-AzAnalysisServicesFirewallRule.md @@ -1,4 +1,4 @@ ---- +--- external help file: Microsoft.Azure.PowerShell.Cmdlets.AnalysisServices.dll-Help.xml Module Name: Az.AnalysisServices online version: https://docs.microsoft.com/en-us/powershell/module/az.analysisservices/new-azanalysisservicesfirewallrule diff --git a/src/AnalysisServices/AnalysisServices/help/New-AzAnalysisServicesServer.md b/src/AnalysisServices/AnalysisServices/help/New-AzAnalysisServicesServer.md index ef018a64faf5..295ff5c4bbe7 100644 --- a/src/AnalysisServices/AnalysisServices/help/New-AzAnalysisServicesServer.md +++ b/src/AnalysisServices/AnalysisServices/help/New-AzAnalysisServicesServer.md @@ -1,4 +1,4 @@ ---- +--- external help file: Microsoft.Azure.PowerShell.Cmdlets.AnalysisServices.dll-Help.xml Module Name: Az.AnalysisServices online version: https://docs.microsoft.com/en-us/powershell/module/az.analysisservices/new-azanalysisservicesserver diff --git a/src/AnalysisServices/AnalysisServices/help/Remove-AzAnalysisServicesServer.md b/src/AnalysisServices/AnalysisServices/help/Remove-AzAnalysisServicesServer.md index e633b9db9556..16883b9951fc 100644 --- a/src/AnalysisServices/AnalysisServices/help/Remove-AzAnalysisServicesServer.md +++ b/src/AnalysisServices/AnalysisServices/help/Remove-AzAnalysisServicesServer.md @@ -1,4 +1,4 @@ ---- +--- external help file: Microsoft.Azure.PowerShell.Cmdlets.AnalysisServices.dll-Help.xml Module Name: Az.AnalysisServices online version: https://docs.microsoft.com/en-us/powershell/module/az.analysisservices/remove-azanalysisservicesserver diff --git a/src/AnalysisServices/AnalysisServices/help/Restart-AzAnalysisServicesInstance.md b/src/AnalysisServices/AnalysisServices/help/Restart-AzAnalysisServicesInstance.md index a9f6f5bf5157..0ff0a2b8b0b9 100644 --- a/src/AnalysisServices/AnalysisServices/help/Restart-AzAnalysisServicesInstance.md +++ b/src/AnalysisServices/AnalysisServices/help/Restart-AzAnalysisServicesInstance.md @@ -1,4 +1,4 @@ ---- +--- external help file: Microsoft.Azure.PowerShell.Cmdlets.AnalysisServices.Dataplane.dll-Help.xml Module Name: Az.AnalysisServices online version: https://docs.microsoft.com/en-us/powershell/module/az.analysisservices/restart-azanalysisservicesinstance diff --git a/src/AnalysisServices/AnalysisServices/help/Resume-AzAnalysisServicesServer.md b/src/AnalysisServices/AnalysisServices/help/Resume-AzAnalysisServicesServer.md index b1ced000a4c4..0c22936dab93 100644 --- a/src/AnalysisServices/AnalysisServices/help/Resume-AzAnalysisServicesServer.md +++ b/src/AnalysisServices/AnalysisServices/help/Resume-AzAnalysisServicesServer.md @@ -1,4 +1,4 @@ ---- +--- external help file: Microsoft.Azure.PowerShell.Cmdlets.AnalysisServices.dll-Help.xml Module Name: Az.AnalysisServices online version: https://docs.microsoft.com/en-us/powershell/module/az.analysisservices/resume-azanalysisservicesserver diff --git a/src/AnalysisServices/AnalysisServices/help/Set-AzAnalysisServicesServer.md b/src/AnalysisServices/AnalysisServices/help/Set-AzAnalysisServicesServer.md index d04ed846d46f..a6958c9e93aa 100644 --- a/src/AnalysisServices/AnalysisServices/help/Set-AzAnalysisServicesServer.md +++ b/src/AnalysisServices/AnalysisServices/help/Set-AzAnalysisServicesServer.md @@ -1,4 +1,4 @@ ---- +--- external help file: Microsoft.Azure.PowerShell.Cmdlets.AnalysisServices.dll-Help.xml Module Name: Az.AnalysisServices online version: https://docs.microsoft.com/en-us/powershell/module/az.analysisservices/set-azanalysisservicesserver diff --git a/src/AnalysisServices/AnalysisServices/help/Suspend-AzAnalysisServicesServer.md b/src/AnalysisServices/AnalysisServices/help/Suspend-AzAnalysisServicesServer.md index 6aca543ac679..f59cf13aad65 100644 --- a/src/AnalysisServices/AnalysisServices/help/Suspend-AzAnalysisServicesServer.md +++ b/src/AnalysisServices/AnalysisServices/help/Suspend-AzAnalysisServicesServer.md @@ -1,4 +1,4 @@ ---- +--- external help file: Microsoft.Azure.PowerShell.Cmdlets.AnalysisServices.dll-Help.xml Module Name: Az.AnalysisServices online version: https://docs.microsoft.com/en-us/powershell/module/az.analysisservices/suspend-azanalysisservicesserver diff --git a/src/AnalysisServices/AnalysisServices/help/Test-AzAnalysisServicesServer.md b/src/AnalysisServices/AnalysisServices/help/Test-AzAnalysisServicesServer.md index 3b58cc6cacbc..553fe3040d79 100644 --- a/src/AnalysisServices/AnalysisServices/help/Test-AzAnalysisServicesServer.md +++ b/src/AnalysisServices/AnalysisServices/help/Test-AzAnalysisServicesServer.md @@ -1,4 +1,4 @@ ---- +--- external help file: Microsoft.Azure.PowerShell.Cmdlets.AnalysisServices.dll-Help.xml Module Name: Az.AnalysisServices online version: https://docs.microsoft.com/en-us/powershell/module/az.analysisservices/test-azanalysisservicesserver From 8af4d33148685127742901c3c4e75831653520c9 Mon Sep 17 00:00:00 2001 From: Gabriel Prestemon Date: Mon, 14 Jan 2019 13:40:21 -0800 Subject: [PATCH 018/141] Change null context error to throw a more appropriate exception. --- .../Models/AsAzureDataplaneCmdletBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs index 9838e1d73dcc..76913af22ee8 100644 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs +++ b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs @@ -164,7 +164,7 @@ internal static AsAzureDataplaneClient CreateAsAzureDataplaneClient(string hostU { if (context == null) { - throw new ApplicationException(Common.Authentication.Properties.Resources.NoSubscriptionInContext); + throw new ArgumentException(Common.Authentication.Properties.Resources.ArmAccountNotFound); } if (string.IsNullOrEmpty(hostUri)) From 7cfaec1e77ce16e8f2dd6a55f89631df7ed8e6eb Mon Sep 17 00:00:00 2001 From: Gabriel Prestemon Date: Mon, 14 Jan 2019 13:51:40 -0800 Subject: [PATCH 019/141] Add documentation to dataplane InMemoryTests. --- .../InMemoryTests/DataPlaneCommandTests.cs | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/AnalysisServices/AnalysisServices.Test/InMemoryTests/DataPlaneCommandTests.cs b/src/AnalysisServices/AnalysisServices.Test/InMemoryTests/DataPlaneCommandTests.cs index bc19784c1505..d6ad83d3c889 100644 --- a/src/AnalysisServices/AnalysisServices.Test/InMemoryTests/DataPlaneCommandTests.cs +++ b/src/AnalysisServices/AnalysisServices.Test/InMemoryTests/DataPlaneCommandTests.cs @@ -80,6 +80,9 @@ private class TestAuthenticationCmdlet : AsAzureDataplaneCmdletBase { } // TestAuthentication(context); //} + /// + /// Assert that cmdlets will fail authentication when provided null context. + /// [Fact] [Trait(Category.AcceptanceType, Category.CheckIn)] public void Authentication_FailsFromNullContext() @@ -87,6 +90,9 @@ public void Authentication_FailsFromNullContext() Assert.Throws(() => TestAuthentication(null)); } + /// + /// Assert that cmdlets will fail authentication when provided bad context. + /// [Fact] [Trait(Category.AcceptanceType, Category.CheckIn)] public void Authentication_FailsFromBadContext() @@ -94,6 +100,10 @@ public void Authentication_FailsFromBadContext() Assert.Throws(() => TestAuthentication(new PSAzureContext())); } + /// + /// Common code used for testing authentication. + /// + /// private void TestAuthentication(IAzureContext context) { var cmdlet = new TestAuthenticationCmdlet() @@ -107,6 +117,9 @@ private void TestAuthentication(IAzureContext context) #endregion #region TestRestart + /// + /// Assert that the restart cmdlet will fail if given a null instance. + /// [Fact] [Trait(Category.AcceptanceType, Category.CheckIn)] public void RestartAzureASInstance_NullInstanceThrows() @@ -115,6 +128,9 @@ public void RestartAzureASInstance_NullInstanceThrows() Assert.Throws(() => restartCmdlet.InvokeBeginProcessing()); } + /// + /// Assert that the restart cmdlet will fail if given a bad instance url. + /// [Fact] [Trait(Category.AcceptanceType, Category.CheckIn)] public void RestartAzureASInstance_InvalidInstanceThrows() @@ -123,6 +139,9 @@ public void RestartAzureASInstance_InvalidInstanceThrows() Assert.Throws(() => restartCmdlet.InvokeBeginProcessing()); } + /// + /// Assert that the restart cmdlet executes successfully. + /// [Fact] [Trait(Category.AcceptanceType, Category.CheckIn)] public void RestartAzureASInstance_Succeeds() @@ -140,6 +159,11 @@ public void RestartAzureASInstance_Succeeds() restartCmdlet.InvokeEndProcessing(); } + /// + /// Create a properly mocked restart cmdlet. + /// + /// The test server instance name. + /// A properly mocked restart cmdlet. private static RestartAzureAnalysisServer CreateTestRestartCmdlet(string instance) { var commandRuntimeMock = new Mock(); @@ -157,6 +181,9 @@ private static RestartAzureAnalysisServer CreateTestRestartCmdlet(string instanc #endregion #region TestExportLog + /// + /// Assert that the export cmdlet works. + /// [Fact] [Trait(Category.AcceptanceType, Category.CheckIn)] public void ExportAzureASInstanceLogTest() @@ -199,6 +226,9 @@ public void ExportAzureASInstanceLogTest() #endregion #region TestSync + /// + /// Assert that the sync cmdlet succeeds syncing a single db instance. + /// [Fact] [Trait(Category.AcceptanceType, Category.CheckIn)] public void SynchronizeAzureASInstance_SingleDB_Succeeds() @@ -209,6 +239,9 @@ public void SynchronizeAzureASInstance_SingleDB_Succeeds() syncCmdlet.InvokeEndProcessing(); } + /// + /// Assert that the sync cmdlet will fail after too many retries. + /// [Fact] [Trait(Category.AcceptanceType, Category.CheckIn)] public void SynchronizeAzureASInstance_FailsAfterTooManyRetries() @@ -219,6 +252,11 @@ public void SynchronizeAzureASInstance_FailsAfterTooManyRetries() syncCmdlet.InvokeEndProcessing(); } + /// + /// Create a properly mocked Sync cmdlet for testing. + /// + /// Flag to set the planned failures to be greater than the retry count. + /// A properly mocked sync cmdlet for testing. private SynchronizeAzureAzureAnalysisServer CreateTestSyncCmdlet(bool tooManyRetries = false) { // Set up mock http client From d90d9afd03a06c8c874ffd50c51f3a57e425cbcb Mon Sep 17 00:00:00 2001 From: Gabriel Prestemon Date: Mon, 14 Jan 2019 14:20:50 -0800 Subject: [PATCH 020/141] Update changelog --- src/AnalysisServices/AnalysisServices/ChangeLog.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/AnalysisServices/AnalysisServices/ChangeLog.md b/src/AnalysisServices/AnalysisServices/ChangeLog.md index c9bd0a9de890..915e2840e76b 100644 --- a/src/AnalysisServices/AnalysisServices/ChangeLog.md +++ b/src/AnalysisServices/AnalysisServices/ChangeLog.md @@ -18,6 +18,9 @@ - Additional information about change #1 --> ## Upcoming Release +* Removed Add-AzAnalysisServicesAccount cmdlet + - Removed Add-AzAnalysisServicesAccount cmdlet and associated classes and logic. + - Users will now use Connect-AzAccount to login, and credentials and authentication for Analysis Services will be retrieved from the Azure Session in Powershell. ## Version 1.0.0 * General availability of `Az.AnalysisServices` module \ No newline at end of file From 5f4893832372d79902376af96303237bb0ab4b04 Mon Sep 17 00:00:00 2001 From: Gabriel Prestemon Date: Tue, 15 Jan 2019 12:51:48 -0800 Subject: [PATCH 021/141] Remove ClusterResolve method and ClusterResolveResult. It is no longer needed, since the cmdlet is now called with the full server name. Move public field DefaultRetryIntervalForPolling below private fields. --- .../Commands/Synchronize-AzureASInstance.cs | 58 ++++--------------- .../Models/AsAzureDataplaneClient.cs | 18 ------ .../Models/ClusterResolutionResult.cs | 33 ----------- .../InMemoryTests/DataPlaneCommandTests.cs | 17 ------ 4 files changed, 11 insertions(+), 115 deletions(-) delete mode 100644 src/AnalysisServices/AnalysisServices.Dataplane/Models/ClusterResolutionResult.cs diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Synchronize-AzureASInstance.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Synchronize-AzureASInstance.cs index 6c428ab59bfd..e2e554af64d9 100644 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Synchronize-AzureASInstance.cs +++ b/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Synchronize-AzureASInstance.cs @@ -41,11 +41,6 @@ public class SynchronizeAzureAzureAnalysisServer : AsAzureDataplaneCmdletBase /// private static readonly TimeSpan DefaultPollingInterval = TimeSpan.FromSeconds(30); - /// - /// Default time interval to wait between polls for sync status. - /// - public static TimeSpan DefaultRetryIntervalForPolling = TimeSpan.FromSeconds(10); - /// /// Http Header name for root activity id. /// @@ -56,11 +51,6 @@ public class SynchronizeAzureAzureAnalysisServer : AsAzureDataplaneCmdletBase /// private readonly string CurrentUtcDateHeaderName = "x-ms-current-utc-date"; - /// - /// The Cluster Resolution Result object. - /// - private ClusterResolutionResult clusterResolveResult; - /// /// Correlation ID for http requests. /// @@ -76,6 +66,11 @@ public class SynchronizeAzureAzureAnalysisServer : AsAzureDataplaneCmdletBase /// private string syncRequestTimeStamp = string.Empty; + /// + /// Default time interval to wait between polls for sync status. + /// + public static TimeSpan DefaultRetryIntervalForPolling = TimeSpan.FromSeconds(10); + [Parameter( Mandatory = true, HelpMessage = "Identity of the database need to be synchronized", @@ -123,24 +118,14 @@ public override void ExecuteCmdlet() return; } + WriteProgress(new ProgressRecord(0, "Sync-AzAnalysisServicesInstance.", string.Format("Successfully authenticated for '{0}' environment.", DnsSafeHost))); correlationId = Guid.NewGuid(); - - WriteObject(string.Format("Sending sync request for database '{0}' to server '{1}'. Correlation Id: '{2}'.", Database, Instance, correlationId.ToString())); - - var clusterResolveResult = ClusterResolve(ServerName); - var virtualServerName = clusterResolveResult.CoreServerName.Split(":".ToCharArray())[0]; - if (!ServerName.Equals(virtualServerName) && !clusterResolveResult.CoreServerName.EndsWith(":rw")) - { - throw new SynchronizationFailedException("Sync request can only be sent to the management endpoint"); - } - - this.clusterResolveResult = clusterResolveResult; - Uri clusterBaseUri = new Uri(string.Format("{0}{1}{2}", Uri.UriSchemeHttps, Uri.SchemeDelimiter, clusterResolveResult.ClusterFQDN)); - + Uri clusterBaseUri = new Uri(string.Format("{0}{1}{2}", Uri.UriSchemeHttps, Uri.SchemeDelimiter, DnsSafeHost)); ScaleOutServerDatabaseSyncDetails syncResult = null; + try { - WriteProgress(new ProgressRecord(0, "Sync-AzAnalysisServicesInstance.", string.Format("Successfully authenticated for '{0}' environment.", DnsSafeHost))); + WriteObject(string.Format("Sending sync request for database '{0}' to server '{1}'. Correlation Id: '{2}'.", Database, Instance, correlationId.ToString())); syncResult = SynchronizeDatabaseAsync(clusterBaseUri, Database).GetAwaiter().GetResult(); } catch (AggregateException aex) @@ -158,7 +143,7 @@ public override void ExecuteCmdlet() if (syncResult == null) { throw new SynchronizationFailedException(string.Format(Resources.SyncASPollStatusUnknownMessage.FormatInvariant( - this.clusterResolveResult.CoreServerName, + ServerName, correlationId, DateTime.Now.ToString(CultureInfo.InvariantCulture), string.Format("RootActivityId: {0}, Date Time UTC: {1}", syncRequestRootActivityId, syncRequestTimeStamp)))); @@ -233,7 +218,7 @@ private async Task SynchronizeDatabaseAsync( Database = databaseName, SyncState = DatabaseSyncState.Invalid, Details = Resources.PostSyncRequestFailureMessage.FormatInvariant( - this.clusterResolveResult.CoreServerName, + ServerName, this.syncRequestRootActivityId, this.syncRequestTimeStamp, string.Format(e.Message)), @@ -366,26 +351,5 @@ private async Task PollSyncStatusWithRetryAsyn return response; }); } - - /// - /// Resolves the cluster to which the request needs to be sent for the current environment. - /// - /// - /// The . - private ClusterResolutionResult ClusterResolve(string serverName) - { - Uri clusterUri = new Uri(string.Format("{0}{1}{2}", Uri.UriSchemeHttps, Uri.SchemeDelimiter, DnsSafeHost)); - - var content = new StringContent($"ServerName={serverName}"); - content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/x-www-form-urlencoded"); - - this.AsAzureDataplaneClient.ResetHttpClient(); - using (var message = AsAzureDataplaneClient.CallPostAsync(clusterUri, AsAzureEndpoints.ClusterResolveEndpoint, content).Result) - { - message.EnsureSuccessStatusCode(); - var rawResult = message.Content.ReadAsStringAsync().Result; - return JsonConvert.DeserializeObject(rawResult); - } - } } } diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneClient.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneClient.cs index 9e6bf87ecdc6..084a35a68621 100644 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneClient.cs +++ b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneClient.cs @@ -58,24 +58,6 @@ public AsAzureDataplaneClient(Uri baseUri, ServiceClientCredentials credentials, this.ResetHttpClient(); } - /// - /// Initializes a new instance of the class. - /// - /// The base uri to send http requests to. - /// for authenticating requests. - /// Function for providing an . - /// The root to be passed to the base class. - /// Additional delegating handlers to be passed to the base class. - public AsAzureDataplaneClient(Uri baseUri, ServiceClientCredentials credentials, Func httpClientProvider, HttpClientHandler rootHandler, params DelegatingHandler[] handlers) - : base(rootHandler, handlers) - { - this.BaseUri = baseUri ?? throw new ArgumentNullException(nameof(baseUri)); - this.Credentials = credentials ?? throw new ArgumentNullException(nameof(credentials)); - this.HttpClientProvider = httpClientProvider ?? throw new ArgumentNullException(nameof(httpClientProvider)); - this.Credentials.InitializeServiceClient(this); - this.ResetHttpClient(); - } - /// /// Invokes the HttpClientProvider function to reset the HttpClient to a new instance. /// diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Models/ClusterResolutionResult.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Models/ClusterResolutionResult.cs deleted file mode 100644 index ea48bd6e2fda..000000000000 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Models/ClusterResolutionResult.cs +++ /dev/null @@ -1,33 +0,0 @@ -// ---------------------------------------------------------------------------------- -// -// 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 System; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane.Models -{ - [DataContract] - public sealed class ClusterResolutionResult - { - [DataMember(Name = "clusterFQDN")] - public string ClusterFQDN { get; set; } - - [DataMember(Name = "coreServerName")] - public string CoreServerName { get; set; } - - [DataMember(Name = "tenantId")] - public string TenantId { get; set; } - } -} diff --git a/src/AnalysisServices/AnalysisServices.Test/InMemoryTests/DataPlaneCommandTests.cs b/src/AnalysisServices/AnalysisServices.Test/InMemoryTests/DataPlaneCommandTests.cs index d6ad83d3c889..e9777b2745d8 100644 --- a/src/AnalysisServices/AnalysisServices.Test/InMemoryTests/DataPlaneCommandTests.cs +++ b/src/AnalysisServices/AnalysisServices.Test/InMemoryTests/DataPlaneCommandTests.cs @@ -262,23 +262,6 @@ private SynchronizeAzureAzureAnalysisServer CreateTestSyncCmdlet(bool tooManyRet // Set up mock http client var mockHttpClient = new Mock(); - ClusterResolutionResult resolveResult = new ClusterResolutionResult() - { - ClusterFQDN = "resolved.westcentralus.asazure.windows.net", - CoreServerName = testInstance + ":rw", - TenantId = Guid.NewGuid().ToString() - }; - mockHttpClient - .Setup(m => m.CallPostAsync( - It.IsAny(), - It.Is(s => s.Contains("clusterResolve")), - It.IsAny())) - .Returns(Task.FromResult( - new HttpResponseMessage(HttpStatusCode.OK) - { - Content = new StringContent(JsonConvert.SerializeObject(resolveResult)) - })); - var postResponse = new HttpResponseMessage(HttpStatusCode.Accepted); postResponse.Headers.Location = new Uri("https://done"); postResponse.Headers.RetryAfter = new RetryConditionHeaderValue(TimeSpan.FromMilliseconds(500)); From ffa1491038ee4b031ed4ca43451fe35bd91fa1b9 Mon Sep 17 00:00:00 2001 From: Gabriel Prestemon Date: Tue, 15 Jan 2019 13:07:44 -0800 Subject: [PATCH 022/141] Rearrange fields, properties, constructors and methods, according to StyleCop guidelines. --- .../Commands/Synchronize-AzureASInstance.cs | 88 +++++++-------- .../Models/AsAzureDataplaneClient.cs | 30 ++--- .../Models/AsAzureDataplaneCmdletBase.cs | 105 +++++++++--------- 3 files changed, 111 insertions(+), 112 deletions(-) diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Synchronize-AzureASInstance.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Synchronize-AzureASInstance.cs index e2e554af64d9..7565e383223a 100644 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Synchronize-AzureASInstance.cs +++ b/src/AnalysisServices/AnalysisServices.Dataplane/Commands/Synchronize-AzureASInstance.cs @@ -36,6 +36,19 @@ namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane [OutputType(typeof(ScaleOutServerDatabaseSyncDetails))] public class SynchronizeAzureAzureAnalysisServer : AsAzureDataplaneCmdletBase { + /// + /// Default time interval to wait between polls for sync status. + /// + public static TimeSpan DefaultRetryIntervalForPolling = TimeSpan.FromSeconds(10); + + [Parameter( + Mandatory = true, + HelpMessage = "Identity of the database need to be synchronized", + Position = 1, + ValueFromPipeline = true)] + [ValidateNotNullOrEmpty] + public string Database { get; set; } + /// /// Default time interval to wait before first poll for sync status. /// @@ -66,50 +79,6 @@ public class SynchronizeAzureAzureAnalysisServer : AsAzureDataplaneCmdletBase /// private string syncRequestTimeStamp = string.Empty; - /// - /// Default time interval to wait between polls for sync status. - /// - public static TimeSpan DefaultRetryIntervalForPolling = TimeSpan.FromSeconds(10); - - [Parameter( - Mandatory = true, - HelpMessage = "Identity of the database need to be synchronized", - Position = 1, - ValueFromPipeline = true)] - [ValidateNotNullOrEmpty] - public string Database { get; set; } - - /// - protected override void BeginProcessing() - { - this._dataCollectionProfile = new AzurePSDataCollectionProfile(false); - base.BeginProcessing(); - } - - /// - protected override void SetupDebuggingTraces() - { - // nothing to do here. - } - - /// - protected override void TearDownDebuggingTraces() - { - // nothing to do here. - } - - /// - protected override void SetupHttpClientPipeline() - { - // nothing to do here. - } - - /// - protected override void TearDownHttpClientPipeline() - { - // nothing to do here. - } - /// public override void ExecuteCmdlet() { @@ -161,6 +130,37 @@ public override void ExecuteCmdlet() } } + /// + protected override void BeginProcessing() + { + this._dataCollectionProfile = new AzurePSDataCollectionProfile(false); + base.BeginProcessing(); + } + + /// + protected override void SetupDebuggingTraces() + { + // nothing to do here. + } + + /// + protected override void TearDownDebuggingTraces() + { + // nothing to do here. + } + + /// + protected override void SetupHttpClientPipeline() + { + // nothing to do here. + } + + /// + protected override void TearDownHttpClientPipeline() + { + // nothing to do here. + } + /// /// Worker Method for the synchronize request. /// diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneClient.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneClient.cs index 084a35a68621..e954ca7e7a92 100644 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneClient.cs +++ b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneClient.cs @@ -100,6 +100,21 @@ public async Task CallPostAsync(string requestUrl, HttpCont #endregion + /// + /// Adds a header to the list object. + /// + /// The request headers list object. + /// The name of the header to add. + /// The value of the header. + private static void AddHeader(HttpRequestHeaders headers, string name, string value) + { + if (headers.Contains(name)) + { + headers.Remove(name); + } + headers.TryAddWithoutValidation(name, value); + } + /// /// Asynchronosly send an http request. /// @@ -138,20 +153,5 @@ private async Task SendRequestAsync( return await this.HttpClient.SendAsync(httpRequest, cancellationToken).ConfigureAwait(false); } - - /// - /// Adds a header to the list object. - /// - /// The request headers list object. - /// The name of the header to add. - /// The value of the header. - private static void AddHeader(HttpRequestHeaders headers, string name, string value) - { - if (headers.Contains(name)) - { - headers.Remove(name); - } - headers.TryAddWithoutValidation(name, value); - } } } diff --git a/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs index 76913af22ee8..f2bd6372d830 100644 --- a/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs +++ b/src/AnalysisServices/AnalysisServices.Dataplane/Models/AsAzureDataplaneCmdletBase.cs @@ -27,17 +27,6 @@ namespace Microsoft.Azure.Commands.AnalysisServices.Dataplane.Models /// public abstract class AsAzureDataplaneCmdletBase : AzurePSCmdlet { - /// - /// Field for the dataplane http client. - /// - private IAsAzureHttpClient _asAzureDataplaneClient; - - - /// - /// Field for the current azure context, for the environment and profile. - /// - private IAzureContext _currentContext; - [Parameter(Mandatory = true, HelpMessage = "Name of the Azure Analysis Services server")] [ValidateNotNullOrEmpty] public string Instance { get; set; } @@ -65,30 +54,15 @@ public abstract class AsAzureDataplaneCmdletBase : AzurePSCmdlet /// testserver protected string ServerName; - /// - protected override IAzureContext DefaultContext - { - get - { - // Nothing to do with Azure Resource Management context - return null; - } - } - - /// - protected override string DataCollectionWarning - { - get - { - return Resources.ARMDataCollectionMessage; - } - } + /// + /// Field for the current azure context, for the environment and profile. + /// + private IAzureContext _currentContext; - /// - protected override void InitializeQosEvent() - { - // No data collection for this cmdlet - } + /// + /// Field for the dataplane http client. + /// + private IAsAzureHttpClient _asAzureDataplaneClient; /// /// Gets or sets the . @@ -126,30 +100,22 @@ public IAsAzureHttpClient AsAzureDataplaneClient set { _asAzureDataplaneClient = value; } } - /// - protected override void BeginProcessing() + /// + protected override IAzureContext DefaultContext { - base.BeginProcessing(); - - if (string.IsNullOrEmpty(Instance)) - { - throw new ArgumentNullException(nameof(Instance)); - } - - // user must specify the fully qualified server name. For example, asazure://westus2.asazure.windows.net/testserver - if (!Uri.TryCreate(Instance, UriKind.Absolute, out var uriResult) || uriResult.Scheme != AsAzureEndpoints.UriSchemeAsAzure) + get { - throw new PSInvalidOperationException(string.Format(Resources.InvalidServerName, Instance)); + // Nothing to do with Azure Resource Management context + return null; } + } - // derive all bits of the url from the input - ServerUri = uriResult.AbsoluteUri; - DnsSafeHost = uriResult.DnsSafeHost; - ServerName = uriResult.PathAndQuery.Trim('/'); - - if (_asAzureDataplaneClient == null) + /// + protected override string DataCollectionWarning + { + get { - AsAzureDataplaneClient = CreateAsAzureDataplaneClient(DnsSafeHost, CurrentContext, () => { return new HttpClient(); }); + return Resources.ARMDataCollectionMessage; } } @@ -182,5 +148,38 @@ internal static AsAzureDataplaneClient CreateAsAzureDataplaneClient(string hostU var handlers = AzureSession.Instance.ClientFactory.GetCustomHandlers(); return AzureSession.Instance.ClientFactory.CreateCustomArmClient(baseUri, credentials, httpClientProvider, handlers); } + + /// + protected override void InitializeQosEvent() + { + // No data collection for this cmdlet + } + + /// + protected override void BeginProcessing() + { + base.BeginProcessing(); + + if (string.IsNullOrEmpty(Instance)) + { + throw new ArgumentNullException(nameof(Instance)); + } + + // user must specify the fully qualified server name. For example, asazure://westus2.asazure.windows.net/testserver + if (!Uri.TryCreate(Instance, UriKind.Absolute, out var uriResult) || uriResult.Scheme != AsAzureEndpoints.UriSchemeAsAzure) + { + throw new PSInvalidOperationException(string.Format(Resources.InvalidServerName, Instance)); + } + + // derive all bits of the url from the input + ServerUri = uriResult.AbsoluteUri; + DnsSafeHost = uriResult.DnsSafeHost; + ServerName = uriResult.PathAndQuery.Trim('/'); + + if (_asAzureDataplaneClient == null) + { + AsAzureDataplaneClient = CreateAsAzureDataplaneClient(DnsSafeHost, CurrentContext, () => { return new HttpClient(); }); + } + } } } From 07cc4261b221ab0ab7fa2f9dd9cb8b93043c26e0 Mon Sep 17 00:00:00 2001 From: Wei Wei Date: Thu, 7 Mar 2019 18:14:08 +0800 Subject: [PATCH 023/141] [Storage] Add -asjob for longrunning cmdlets --- .../Blob/Cmdlet/GetAzureStorageBlobContent.cs | 23 +++++++++++- .../Blob/Cmdlet/SetAzureStorageBlobContent.cs | 35 +++++++++++++++++-- .../Blob/Cmdlet/StartAzureStorageBlobCopy.cs | 3 ++ .../Blob/StorageDataMovementCmdletBase.cs | 19 ++++++++++ .../File/Cmdlet/GetAzureStorageFileContent.cs | 21 ++++++++++- .../File/Cmdlet/SetAzureStorageFileContent.cs | 22 +++++++++++- .../File/Cmdlet/StartAzureStorageFileCopy.cs | 3 ++ .../StorageFileDataManagementCmdletBase.cs | 19 ++++++++++ src/Storage/Storage/Resources.Designer.cs | 13 ++++++- src/Storage/Storage/Resources.resx | 6 +++- 10 files changed, 156 insertions(+), 8 deletions(-) diff --git a/src/Storage/Storage/Blob/Cmdlet/GetAzureStorageBlobContent.cs b/src/Storage/Storage/Blob/Cmdlet/GetAzureStorageBlobContent.cs index 3c4319f84142..2d85ec442bd3 100644 --- a/src/Storage/Storage/Blob/Cmdlet/GetAzureStorageBlobContent.cs +++ b/src/Storage/Storage/Blob/Cmdlet/GetAzureStorageBlobContent.cs @@ -253,7 +253,12 @@ internal void GetBlobContent(CloudBlob blob, string fileName, bool isValidBlob = /// full file path if file path is valid, otherwise throw an exception internal string GetFullReceiveFilePath(string fileName, string blobName, DateTimeOffset? snapshotTime) { - String filePath = Path.Combine(CurrentPath(), fileName); + // With -asjob, only absolute path works, so fileName should be absolute path. + String filePath = fileName; + if (!AsJob.IsPresent) + { + filePath = Path.Combine(CurrentPath(), fileName); + } fileName = Path.GetFileName(filePath); String dirPath = Path.GetDirectoryName(filePath); @@ -286,6 +291,17 @@ internal string GetFullReceiveFilePath(string fileName, string blobName, DateTim [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] public override void ExecuteCmdlet() { + if (AsJob.IsPresent) + { + BeginProcessingImplement(); + } + + if (AsJob.IsPresent && !Path.IsPathRooted(FileName)) + { + throw new ArgumentException(String.Format(Resources.InvalidPathForAsJob, "Destination", FileName), "Destination"); + } + FileName = ResolveUserPath(FileName); + switch (ParameterSetName) { case BlobParameterSet: @@ -309,6 +325,11 @@ public override void ExecuteCmdlet() } break; } + + if (AsJob.IsPresent) + { + EndProcessingImplement(); + } } } } diff --git a/src/Storage/Storage/Blob/Cmdlet/SetAzureStorageBlobContent.cs b/src/Storage/Storage/Blob/Cmdlet/SetAzureStorageBlobContent.cs index b246fb0f5e46..0a79c4036a9f 100644 --- a/src/Storage/Storage/Blob/Cmdlet/SetAzureStorageBlobContent.cs +++ b/src/Storage/Storage/Blob/Cmdlet/SetAzureStorageBlobContent.cs @@ -169,7 +169,7 @@ public PremiumPageBlobTier PremiumPageBlobTier private PremiumPageBlobTier? pageBlobTier = null; private BlobUploadRequestQueue UploadRequests = new BlobUploadRequestQueue(); - + /// /// Initializes a new instance of the SetAzureBlobContentCommand class. /// @@ -262,7 +262,13 @@ internal string GetFullSendFilePath(string fileName) throw new ArgumentException(Resources.FileNameCannotEmpty); } - String filePath = Path.Combine(CurrentPath(), fileName); + // With -asjob, only absolute path works, so fileName should be absolute path. + String filePath = fileName; + if (!AsJob.IsPresent) + { + filePath = Path.GetFullPath(fileName); + } + fileName = Path.GetFileName(filePath); return filePath; } @@ -315,6 +321,14 @@ internal void SetAzureBlobContent(string fileName, string blobName) } protected override void EndProcessing() + { + if (!AsJob.IsPresent) + { + EndProcessingImplement(); + } + } + + protected override void EndProcessingImplement() { while (!UploadRequests.IsEmpty()) { @@ -324,7 +338,7 @@ protected override void EndProcessing() RunTask(taskGenerator); } - base.EndProcessing(); + base.EndProcessingImplement(); } //only support the common blob properties for block blob and page blob @@ -491,7 +505,17 @@ protected override void OnTaskSuccessful(DataMovementUserData data) /// public override void ExecuteCmdlet() { + if(AsJob.IsPresent) + { + BeginProcessingImplement(); + } + + if (AsJob.IsPresent && !Path.IsPathRooted(FileName)) + { + throw new ArgumentException(String.Format(Resources.InvalidPathForAsJob, "File", FileName), "File"); + } FileName = ResolveUserPath(FileName); + ValidateBlobTier(string.Equals(blobType, PageBlobType, StringComparison.InvariantCultureIgnoreCase)? StorageBlob.BlobType.PageBlob : StorageBlob.BlobType.Unspecified, pageBlobTier); @@ -541,6 +565,11 @@ public override void ExecuteCmdlet() break; } + + if (AsJob.IsPresent) + { + EndProcessingImplement(); + } } } } diff --git a/src/Storage/Storage/Blob/Cmdlet/StartAzureStorageBlobCopy.cs b/src/Storage/Storage/Blob/Cmdlet/StartAzureStorageBlobCopy.cs index 957d1bccd34b..fdcd450d9abc 100644 --- a/src/Storage/Storage/Blob/Cmdlet/StartAzureStorageBlobCopy.cs +++ b/src/Storage/Storage/Blob/Cmdlet/StartAzureStorageBlobCopy.cs @@ -215,6 +215,9 @@ public PremiumPageBlobTier PremiumPageBlobTier [Parameter(HelpMessage = "Destination Storage context object", Mandatory = false)] public IStorageContext DestContext { get; set; } + // Overwrite the useless parameter + public override SwitchParameter AsJob { get; set; } + private bool skipSourceChannelInit; /// diff --git a/src/Storage/Storage/Blob/StorageDataMovementCmdletBase.cs b/src/Storage/Storage/Blob/StorageDataMovementCmdletBase.cs index 0261c4538bdd..a331a853e73e 100644 --- a/src/Storage/Storage/Blob/StorageDataMovementCmdletBase.cs +++ b/src/Storage/Storage/Blob/StorageDataMovementCmdletBase.cs @@ -43,6 +43,9 @@ public SwitchParameter Force protected bool overwrite; + [Parameter(Mandatory = false, HelpMessage = "Run cmdlet in the background")] + public virtual SwitchParameter AsJob { get; set; } + /// /// Confirm the overwrite operation /// @@ -77,6 +80,14 @@ protected virtual void OnTaskSuccessful(DataMovementUserData data) /// Cmdlet begin processing /// protected override void BeginProcessing() + { + if (!AsJob.IsPresent) + { + BeginProcessingImplement(); + } + } + + protected void BeginProcessingImplement() { base.BeginProcessing(); OutputStream.ConfirmWriter = (s1, s2, s3) => ShouldContinue(s2, s3); @@ -112,6 +123,14 @@ protected SingleTransferContext GetTransferContext(DataMovementUserData userData } protected override void EndProcessing() + { + if (!AsJob.IsPresent) + { + EndProcessingImplement(); + } + } + + protected virtual void EndProcessingImplement() { try { diff --git a/src/Storage/Storage/File/Cmdlet/GetAzureStorageFileContent.cs b/src/Storage/Storage/File/Cmdlet/GetAzureStorageFileContent.cs index 2df430335730..62c8a17e049c 100644 --- a/src/Storage/Storage/File/Cmdlet/GetAzureStorageFileContent.cs +++ b/src/Storage/Storage/File/Cmdlet/GetAzureStorageFileContent.cs @@ -113,6 +113,11 @@ public SwitchParameter CheckMd5 public override void ExecuteCmdlet() { + if (AsJob.IsPresent) + { + BeginProcessingImplement(); + } + CloudFile fileToBeDownloaded; string[] path = NamingUtil.ValidatePath(this.Path, true); switch (this.ParameterSetName) @@ -138,8 +143,17 @@ public override void ExecuteCmdlet() throw new PSArgumentException(string.Format(CultureInfo.InvariantCulture, "Invalid parameter set name: {0}", this.ParameterSetName)); } - string resolvedDestination = this.GetUnresolvedProviderPathFromPSPath( + // With -asjob, only absolute path works, so Destination must be absolute path. + if (AsJob.IsPresent && !System.IO.Path.IsPathRooted(this.Destination)) + { + throw new System.ArgumentException(string.Format(Resources.InvalidPathForAsJob, "Destination", this.Destination), "Destination"); + } + string resolvedDestination = this.Destination; + if (!AsJob.IsPresent) + { + resolvedDestination = this.GetUnresolvedProviderPathFromPSPath( string.IsNullOrWhiteSpace(this.Destination) ? "." : this.Destination); + } FileMode mode = this.Force ? FileMode.Create : FileMode.CreateNew; string targetFile; @@ -193,6 +207,11 @@ await DataMovementTransferHelper.DoTransfer(() => } }); } + + if (AsJob.IsPresent) + { + EndProcessingImplement(); + } } } } diff --git a/src/Storage/Storage/File/Cmdlet/SetAzureStorageFileContent.cs b/src/Storage/Storage/File/Cmdlet/SetAzureStorageFileContent.cs index 90c8e28d1d7e..d528c4752777 100644 --- a/src/Storage/Storage/File/Cmdlet/SetAzureStorageFileContent.cs +++ b/src/Storage/Storage/File/Cmdlet/SetAzureStorageFileContent.cs @@ -73,8 +73,23 @@ public class SetAzureStorageFileContent : StorageFileDataManagementCmdletBase public override void ExecuteCmdlet() { + if (AsJob.IsPresent) + { + BeginProcessingImplement(); + } + // Step 1: Validate source file. - FileInfo localFile = new FileInfo(this.GetUnresolvedProviderPathFromPSPath(this.Source)); + // With -asjob, only absolute path works, so Source must be absolute path. + if (AsJob.IsPresent && !System.IO.Path.IsPathRooted(this.Source)) + { + throw new System.ArgumentException(string.Format(Resources.InvalidPathForAsJob, "Source", this.Source), "Source"); + } + string filePath = this.Source; + if (!AsJob.IsPresent) + { + filePath = this.GetUnresolvedProviderPathFromPSPath(this.Source); + } + FileInfo localFile = new FileInfo(filePath); if (!localFile.Exists) { throw new FileNotFoundException(string.Format(CultureInfo.CurrentCulture, Resources.SourceFileNotFound, this.Source)); @@ -119,6 +134,11 @@ await DataMovementTransferHelper.DoTransfer(() => } }); } + + if (AsJob.IsPresent) + { + EndProcessingImplement(); + } } private async Task BuildCloudFileInstanceFromPathAsync(string defaultFileName, string[] path, bool pathIsDirectory) diff --git a/src/Storage/Storage/File/Cmdlet/StartAzureStorageFileCopy.cs b/src/Storage/Storage/File/Cmdlet/StartAzureStorageFileCopy.cs index 3e62380a0d27..5ad7a469f76b 100644 --- a/src/Storage/Storage/File/Cmdlet/StartAzureStorageFileCopy.cs +++ b/src/Storage/Storage/File/Cmdlet/StartAzureStorageFileCopy.cs @@ -132,6 +132,9 @@ public class StartAzureStorageFileCopyCommand : StorageFileDataManagementCmdletB [Parameter(HelpMessage = "Destination Storage context object", ParameterSetName = UriFilePathParameterSet)] public IStorageContext DestContext { get; set; } + // Overwrite the useless parameter + public override SwitchParameter AsJob { get; set; } + private IStorageBlobManagement blobChannel = null; private BlobToAzureFileNameResolver nameResolver = new BlobToAzureFileNameResolver(() => NameUtil.MaxFileNameLength); diff --git a/src/Storage/Storage/File/StorageFileDataManagementCmdletBase.cs b/src/Storage/Storage/File/StorageFileDataManagementCmdletBase.cs index 3f058eb1a752..b474e395c74a 100644 --- a/src/Storage/Storage/File/StorageFileDataManagementCmdletBase.cs +++ b/src/Storage/Storage/File/StorageFileDataManagementCmdletBase.cs @@ -48,6 +48,9 @@ public SwitchParameter Force set; } + [Parameter(Mandatory = false, HelpMessage = "Run cmdlet in the background")] + public virtual SwitchParameter AsJob { get; set; } + /// /// Confirm the overwrite operation /// @@ -71,6 +74,14 @@ protected async Task ConfirmOverwriteAsync(object source, object destinati } protected override void BeginProcessing() + { + if (!AsJob.IsPresent) + { + BeginProcessingImplement(); + } + } + + protected void BeginProcessingImplement() { base.BeginProcessing(); @@ -79,6 +90,14 @@ protected override void BeginProcessing() } protected override void EndProcessing() + { + if (!AsJob.IsPresent) + { + EndProcessingImplement(); + } + } + + protected void EndProcessingImplement() { try { diff --git a/src/Storage/Storage/Resources.Designer.cs b/src/Storage/Storage/Resources.Designer.cs index dcb645120e99..64905c92086b 100644 --- a/src/Storage/Storage/Resources.Designer.cs +++ b/src/Storage/Storage/Resources.Designer.cs @@ -986,7 +986,18 @@ internal static string InvalidPageBlobSize { return ResourceManager.GetString("InvalidPageBlobSize", resourceCulture); } } - + + /// + /// Looks up a localized string similar to With -Asjob, Parameter '{0}' must be an absolute path. But now it's: {1} '{0}' + /// + internal static string InvalidPathForAsJob + { + get + { + return ResourceManager.GetString("InvalidPathForAsJob", resourceCulture); + } + } + /// /// Looks up a localized string similar to Queue name '{0}' is invalid. Valid names start and end with a lower case letter or a number and has in between a lower case letter, number or dash with no consecutive dashes and is 3 through 63 characters long.. /// diff --git a/src/Storage/Storage/Resources.resx b/src/Storage/Storage/Resources.resx index 50e43640e268..6f41b511f733 100644 --- a/src/Storage/Storage/Resources.resx +++ b/src/Storage/Storage/Resources.resx @@ -521,7 +521,7 @@ User specified blob type does not match the blob type of the existing destination blob. - + The stop copy operation on blob '{0}' in container '{1}' is cancelled. 0 for blob name, 1 for container name. @@ -734,4 +734,8 @@ Failed: {2}. Parameter -StartTime and -NoStartTime are mutually exclusive + + With -Asjob, Parameter '{0}' must be an absolute path. But now it's: {1} + 0 for parameter name for the Path, 1 for the path value + \ No newline at end of file From 9d5c3db5d4902a6a68fbe7e958c8b8715efd4f94 Mon Sep 17 00:00:00 2001 From: Wei Wei Date: Mon, 11 Mar 2019 16:46:52 +0800 Subject: [PATCH 024/141] [Storage] Help change for Add -Asjob --- .../help/Get-AzStorageBlobContent.md | 26 +++++++++++++--- .../help/Get-AzStorageFileContent.md | 31 ++++++++++++++----- .../help/Set-AzStorageBlobContent.md | 28 +++++++++++++---- .../help/Set-AzStorageFileContent.md | 25 ++++++++++++--- .../Blob/Cmdlet/GetAzureStorageBlobContent.cs | 2 +- .../Blob/Cmdlet/SetAzureStorageBlobContent.cs | 6 ++-- .../File/Cmdlet/GetAzureStorageFileContent.cs | 10 +++--- .../File/Cmdlet/SetAzureStorageFileContent.cs | 2 +- 8 files changed, 98 insertions(+), 32 deletions(-) diff --git a/src/Storage/Storage.Management/help/Get-AzStorageBlobContent.md b/src/Storage/Storage.Management/help/Get-AzStorageBlobContent.md index cb6c0600ba1e..1401435135fc 100644 --- a/src/Storage/Storage.Management/help/Get-AzStorageBlobContent.md +++ b/src/Storage/Storage.Management/help/Get-AzStorageBlobContent.md @@ -1,4 +1,4 @@ ---- +--- external help file: Microsoft.Azure.PowerShell.Cmdlets.Storage.dll-Help.xml Module Name: Az.Storage ms.assetid: C091D654-E113-4AE0-A6C8-24630D1294A4 @@ -16,14 +16,14 @@ Downloads a storage blob. ### ReceiveManual (Default) ``` Get-AzStorageBlobContent [-Blob] [-Container] [-Destination ] [-CheckMd5] [-Force] - [-Context ] [-ServerTimeoutPerRequest ] [-ClientTimeoutPerRequest ] + [-AsJob] [-Context ] [-ServerTimeoutPerRequest ] [-ClientTimeoutPerRequest ] [-DefaultProfile ] [-ConcurrentTaskCount ] [-WhatIf] [-Confirm] [] ``` ### BlobPipeline ``` -Get-AzStorageBlobContent -CloudBlob [-Destination ] [-CheckMd5] [-Force] +Get-AzStorageBlobContent -CloudBlob [-Destination ] [-CheckMd5] [-Force] [-AsJob] [-Context ] [-ServerTimeoutPerRequest ] [-ClientTimeoutPerRequest ] [-DefaultProfile ] [-ConcurrentTaskCount ] [-WhatIf] [-Confirm] [] @@ -32,7 +32,7 @@ Get-AzStorageBlobContent -CloudBlob [-Destination ] [-CheckM ### ContainerPipeline ``` Get-AzStorageBlobContent -CloudBlobContainer [-Blob] [-Destination ] - [-CheckMd5] [-Force] [-Context ] [-ServerTimeoutPerRequest ] + [-CheckMd5] [-Force] [-AsJob] [-Context ] [-ServerTimeoutPerRequest ] [-ClientTimeoutPerRequest ] [-DefaultProfile ] [-ConcurrentTaskCount ] [-WhatIf] [-Confirm] [] ``` @@ -66,6 +66,22 @@ This example uses the asterisk wildcard character and the pipeline to find and d ## PARAMETERS +### -AsJob +Run cmdlet in the background. +With this parameter, *Destination* parameter must be an absolute Path. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ### -Blob Specifies the name of the blob to be downloaded. @@ -212,7 +228,7 @@ Accept wildcard characters: False ``` ### -Destination -Specifies the location to store the downloaded file. +Specifies the location to store the downloaded file. With *Asjob* parameter, it must be an absolute Path. ```yaml Type: System.String diff --git a/src/Storage/Storage.Management/help/Get-AzStorageFileContent.md b/src/Storage/Storage.Management/help/Get-AzStorageFileContent.md index 4842fe55fbd9..8a33aa581bfa 100644 --- a/src/Storage/Storage.Management/help/Get-AzStorageFileContent.md +++ b/src/Storage/Storage.Management/help/Get-AzStorageFileContent.md @@ -1,4 +1,4 @@ ---- +--- external help file: Microsoft.Azure.PowerShell.Cmdlets.Storage.dll-Help.xml Module Name: Az.Storage ms.assetid: 6420CBE1-BF9D-493D-BCA8-E8C6688FAF3B @@ -16,7 +16,7 @@ Downloads the contents of a file. ### ShareName (Default) ``` Get-AzStorageFileContent [-ShareName] [-Path] [[-Destination] ] [-CheckMd5] - [-PassThru] [-Force] [-Context ] [-ServerTimeoutPerRequest ] + [-PassThru] [-Force] [-AsJob] [-Context ] [-ServerTimeoutPerRequest ] [-ClientTimeoutPerRequest ] [-DefaultProfile ] [-ConcurrentTaskCount ] [-WhatIf] [-Confirm] [] ``` @@ -24,7 +24,7 @@ Get-AzStorageFileContent [-ShareName] [-Path] [[-Destination] ### Share ``` Get-AzStorageFileContent [-Share] [-Path] [[-Destination] ] [-CheckMd5] - [-PassThru] [-Force] [-ServerTimeoutPerRequest ] [-ClientTimeoutPerRequest ] + [-PassThru] [-Force] [-AsJob] [-ServerTimeoutPerRequest ] [-ClientTimeoutPerRequest ] [-DefaultProfile ] [-ConcurrentTaskCount ] [-WhatIf] [-Confirm] [] ``` @@ -32,15 +32,15 @@ Get-AzStorageFileContent [-Share] [-Path] [[-Destinati ### Directory ``` Get-AzStorageFileContent [-Directory] [-Path] [[-Destination] ] - [-CheckMd5] [-PassThru] [-Force] [-ServerTimeoutPerRequest ] [-ClientTimeoutPerRequest ] - [-DefaultProfile ] [-ConcurrentTaskCount ] [-WhatIf] [-Confirm] - [] + [-CheckMd5] [-PassThru] [-Force] [-AsJob] [-ServerTimeoutPerRequest ] + [-ClientTimeoutPerRequest ] [-DefaultProfile ] [-ConcurrentTaskCount ] + [-WhatIf] [-Confirm] [] ``` ### File ``` Get-AzStorageFileContent [-File] [[-Destination] ] [-CheckMd5] [-PassThru] [-Force] - [-ServerTimeoutPerRequest ] [-ClientTimeoutPerRequest ] + [-AsJob] [-ServerTimeoutPerRequest ] [-ClientTimeoutPerRequest ] [-DefaultProfile ] [-ConcurrentTaskCount ] [-WhatIf] [-Confirm] [] ``` @@ -67,6 +67,22 @@ This example downloads the files under sample file share ## PARAMETERS +### -AsJob +Run cmdlet in the background. +With this parameter, *Destination* parameter must be an absolute Path. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ### -CheckMd5 If you specify the path of a file that does not exist, this cmdlet creates that file, and saves the contents in the new file. If you specify a path of a file that already exists and you specify the *Force* parameter, the cmdlet overwrites the file. @@ -156,6 +172,7 @@ Accept wildcard characters: False ### -Destination Specifies the destination path. +With *Asjob* parameter, it must be an absolute Path. This cmdlet downloads the file contents to the location that this parameter specifies. If you specify the path of a file that does not exist, this cmdlet creates that file, and saves the contents in the new file. If you specify a path of a file that already exists and you specify the *Force* parameter, the cmdlet overwrites the file. diff --git a/src/Storage/Storage.Management/help/Set-AzStorageBlobContent.md b/src/Storage/Storage.Management/help/Set-AzStorageBlobContent.md index 19511e6027f2..1576787ca980 100644 --- a/src/Storage/Storage.Management/help/Set-AzStorageBlobContent.md +++ b/src/Storage/Storage.Management/help/Set-AzStorageBlobContent.md @@ -1,4 +1,4 @@ ---- +--- external help file: Microsoft.Azure.PowerShell.Cmdlets.Storage.dll-Help.xml Module Name: Az.Storage ms.assetid: F20A5FD3-6EC3-4EFE-988C-75F8583961A4 @@ -17,7 +17,7 @@ Uploads a local file to an Azure Storage blob. ``` Set-AzStorageBlobContent [-File] [-Container] [-Blob ] [-BlobType ] [-Properties ] [-Metadata ] [-PremiumPageBlobTier ] [-Force] - [-Context ] [-ServerTimeoutPerRequest ] [-ClientTimeoutPerRequest ] + [-AsJob] [-Context ] [-ServerTimeoutPerRequest ] [-ClientTimeoutPerRequest ] [-DefaultProfile ] [-ConcurrentTaskCount ] [-WhatIf] [-Confirm] [] ``` @@ -26,7 +26,7 @@ Set-AzStorageBlobContent [-File] [-Container] [-Blob ] ``` Set-AzStorageBlobContent [-File] [-Blob ] -CloudBlobContainer [-BlobType ] [-Properties ] [-Metadata ] - [-PremiumPageBlobTier ] [-Force] [-Context ] + [-PremiumPageBlobTier ] [-Force] [-AsJob] [-Context ] [-ServerTimeoutPerRequest ] [-ClientTimeoutPerRequest ] [-DefaultProfile ] [-ConcurrentTaskCount ] [-WhatIf] [-Confirm] [] @@ -35,8 +35,8 @@ Set-AzStorageBlobContent [-File] [-Blob ] -CloudBlobContainer < ### BlobPipeline ``` Set-AzStorageBlobContent [-File] -CloudBlob [-BlobType ] [-Properties ] - [-Metadata ] [-PremiumPageBlobTier ] [-Force] [-Context ] - [-ServerTimeoutPerRequest ] [-ClientTimeoutPerRequest ] + [-Metadata ] [-PremiumPageBlobTier ] [-Force] [-AsJob] + [-Context ] [-ServerTimeoutPerRequest ] [-ClientTimeoutPerRequest ] [-DefaultProfile ] [-ConcurrentTaskCount ] [-WhatIf] [-Confirm] [] ``` @@ -99,6 +99,22 @@ This command uploads the file that is named ContosoPlanning to the container na ## PARAMETERS +### -AsJob +Run cmdlet in the background. +With this parameter, *File* parameter must be an absolute Path. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ### -Blob Specifies the name of a blob. This cmdlet uploads a file to the Azure Storage blob that this parameter specifies. @@ -253,7 +269,7 @@ Accept wildcard characters: False ``` ### -File -Specifies a local file path for a file to upload as blob content. +Specifies a local file path for a file to upload as blob content. With *Asjob* parameter, it must be an absolute Path. ```yaml Type: System.String diff --git a/src/Storage/Storage.Management/help/Set-AzStorageFileContent.md b/src/Storage/Storage.Management/help/Set-AzStorageFileContent.md index 6dc54449cbee..5dddc855d0f0 100644 --- a/src/Storage/Storage.Management/help/Set-AzStorageFileContent.md +++ b/src/Storage/Storage.Management/help/Set-AzStorageFileContent.md @@ -1,4 +1,4 @@ ---- +--- external help file: Microsoft.Azure.PowerShell.Cmdlets.Storage.dll-Help.xml Module Name: Az.Storage ms.assetid: FA98E64B-D589-4653-9ACC-86573FAF4550 @@ -16,7 +16,7 @@ Uploads the contents of a file. ### ShareName (Default) ``` Set-AzStorageFileContent [-ShareName] [-Source] [[-Path] ] [-PassThru] [-Force] - [-Context ] [-ServerTimeoutPerRequest ] [-ClientTimeoutPerRequest ] + [-AsJob] [-Context ] [-ServerTimeoutPerRequest ] [-ClientTimeoutPerRequest ] [-DefaultProfile ] [-ConcurrentTaskCount ] [-WhatIf] [-Confirm] [] ``` @@ -24,7 +24,7 @@ Set-AzStorageFileContent [-ShareName] [-Source] [[-Path] [-Source] [[-Path] ] [-PassThru] [-Force] - [-ServerTimeoutPerRequest ] [-ClientTimeoutPerRequest ] + [-AsJob] [-ServerTimeoutPerRequest ] [-ClientTimeoutPerRequest ] [-DefaultProfile ] [-ConcurrentTaskCount ] [-WhatIf] [-Confirm] [] ``` @@ -32,7 +32,7 @@ Set-AzStorageFileContent [-Share] [-Source] [[-Path] < ### Directory ``` Set-AzStorageFileContent [-Directory] [-Source] [[-Path] ] [-PassThru] - [-Force] [-ServerTimeoutPerRequest ] [-ClientTimeoutPerRequest ] + [-Force] [-AsJob] [-ServerTimeoutPerRequest ] [-ClientTimeoutPerRequest ] [-DefaultProfile ] [-ConcurrentTaskCount ] [-WhatIf] [-Confirm] [] ``` @@ -70,6 +70,22 @@ For more information about script blocks, type `Get-Help about_Script_Blocks`. ## PARAMETERS +### -AsJob +Run cmdlet in the background. +With this parameter, *Source* parameter must be an absolute Path. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ### -ClientTimeoutPerRequest Specifies the client-side time-out interval, in seconds, for one service request. If the previous call fails in the specified interval, this cmdlet retries the request. @@ -258,6 +274,7 @@ Accept wildcard characters: False ### -Source Specifies the source file that this cmdlet uploads. +With *Asjob* parameter, it must be an absolute Path. If you specify a file that does not exist, this cmdlet returns an error. ```yaml diff --git a/src/Storage/Storage/Blob/Cmdlet/GetAzureStorageBlobContent.cs b/src/Storage/Storage/Blob/Cmdlet/GetAzureStorageBlobContent.cs index 2d85ec442bd3..e0168da57376 100644 --- a/src/Storage/Storage/Blob/Cmdlet/GetAzureStorageBlobContent.cs +++ b/src/Storage/Storage/Blob/Cmdlet/GetAzureStorageBlobContent.cs @@ -76,7 +76,7 @@ public string Container private string ContainerName = String.Empty; [Alias("Path")] - [Parameter(HelpMessage = "File Path")] + [Parameter(HelpMessage = "File Path. With -Asjob, it must be an absolute Path.")] public string Destination { get { return FileName; } diff --git a/src/Storage/Storage/Blob/Cmdlet/SetAzureStorageBlobContent.cs b/src/Storage/Storage/Blob/Cmdlet/SetAzureStorageBlobContent.cs index 0a79c4036a9f..7ca16f617d9f 100644 --- a/src/Storage/Storage/Blob/Cmdlet/SetAzureStorageBlobContent.cs +++ b/src/Storage/Storage/Blob/Cmdlet/SetAzureStorageBlobContent.cs @@ -67,11 +67,11 @@ public class SetAzureBlobContentCommand : StorageDataMovementCmdletBase private const string AppendBlobType = "Append"; [Alias("FullName")] - [Parameter(Position = 0, Mandatory = true, HelpMessage = "file Path", + [Parameter(Position = 0, Mandatory = true, HelpMessage = "file Path. With -Asjob, it must be an absolute Path.", ValueFromPipelineByPropertyName = true, ParameterSetName = ManualParameterSet)] - [Parameter(Position = 0, Mandatory = true, HelpMessage = "file Path", + [Parameter(Position = 0, Mandatory = true, HelpMessage = "file Path. With -Asjob, it must be an absolute Path.", ParameterSetName = ContainerParameterSet)] - [Parameter(Position = 0, Mandatory = true, HelpMessage = "file Path", + [Parameter(Position = 0, Mandatory = true, HelpMessage = "file Path. With -Asjob, it must be an absolute Path.", ParameterSetName = BlobParameterSet)] public string File { diff --git a/src/Storage/Storage/File/Cmdlet/GetAzureStorageFileContent.cs b/src/Storage/Storage/File/Cmdlet/GetAzureStorageFileContent.cs index 62c8a17e049c..65b2ee142fc4 100644 --- a/src/Storage/Storage/File/Cmdlet/GetAzureStorageFileContent.cs +++ b/src/Storage/Storage/File/Cmdlet/GetAzureStorageFileContent.cs @@ -85,19 +85,19 @@ public class GetAzureStorageFileContent : StorageFileDataManagementCmdletBase [Parameter( Position = 2, ParameterSetName = LocalConstants.ShareNameParameterSetName, - HelpMessage = "Path to the local file or directory when the downloaded file would be put.")] + HelpMessage = "Path to the local file or directory when the downloaded file would be put. With -Asjob, it must be an absolute Path.")] [Parameter( Position = 2, ParameterSetName = LocalConstants.ShareParameterSetName, - HelpMessage = "Path to the local file or directory when the downloaded file would be put.")] + HelpMessage = "Path to the local file or directory when the downloaded file would be put. With -Asjob, it must be an absolute Path.")] [Parameter( Position = 2, ParameterSetName = LocalConstants.DirectoryParameterSetName, - HelpMessage = "Path to the local file or directory when the downloaded file would be put.")] + HelpMessage = "Path to the local file or directory when the downloaded file would be put. With -Asjob, it must be an absolute Path.")] [Parameter( Position = 1, ParameterSetName = LocalConstants.FileParameterSetName, - HelpMessage = "Path to the local file or directory when the downloaded file would be put.")] + HelpMessage = "Path to the local file or directory when the downloaded file would be put. With -Asjob, it must be an absolute Path.")] [ValidateNotNullOrEmpty] public string Destination { get; set; } @@ -152,7 +152,7 @@ public override void ExecuteCmdlet() if (!AsJob.IsPresent) { resolvedDestination = this.GetUnresolvedProviderPathFromPSPath( - string.IsNullOrWhiteSpace(this.Destination) ? "." : this.Destination); + string.IsNullOrWhiteSpace(this.Destination) ? "." : this.Destination); } FileMode mode = this.Force ? FileMode.Create : FileMode.CreateNew; diff --git a/src/Storage/Storage/File/Cmdlet/SetAzureStorageFileContent.cs b/src/Storage/Storage/File/Cmdlet/SetAzureStorageFileContent.cs index d528c4752777..e01dfaf42d3d 100644 --- a/src/Storage/Storage/File/Cmdlet/SetAzureStorageFileContent.cs +++ b/src/Storage/Storage/File/Cmdlet/SetAzureStorageFileContent.cs @@ -58,7 +58,7 @@ public class SetAzureStorageFileContent : StorageFileDataManagementCmdletBase Position = 1, Mandatory = true, ValueFromPipelineByPropertyName = true, - HelpMessage = "Path to the local file to be uploaded.")] + HelpMessage = "Path to the local file to be uploaded. With -Asjob, it must be an absolute Path.")] [ValidateNotNullOrEmpty] public string Source { get; set; } From ce68236686f540c361a1c5c8dbd5edf16de2b1e1 Mon Sep 17 00:00:00 2001 From: cormacpayne Date: Tue, 12 Mar 2019 10:54:24 -0700 Subject: [PATCH 025/141] Update docs in repository --- CONTRIBUTING.md | 156 +-- README.md | 22 +- .../Debugging-StaticAnalysis-Errors.md | 2 +- .../azure-powershell-design-guidelines.md | 326 ------ .../azure-powershell-developer-guide.md | 97 +- .../design-guidelines/README.md | 34 + .../cmdlet-best-practices.md | 160 +++ .../module-best-practices.md | 193 +++ .../parameter-best-practices.md | 157 +++ .../piping-best-practices.md} | 289 ++--- .../should-process-confirm-impact.md | 28 +- .../development-docs/examples/README.md | 21 + .../examples/get-cmdlet-example.md | 157 +++ .../examples/new-cmdlet-example.md | 178 +++ .../examples/remove-cmdlet-example.md | 177 +++ .../examples/set-cmdlet-example.md | 235 ++++ .../examples/update-cmdlet-example.md | 221 ++++ .../generate-format.ps1xml-file.md | 2 +- .../patterns-for-standard-cmdlets.md | 1042 ----------------- 19 files changed, 1755 insertions(+), 1742 deletions(-) delete mode 100644 documentation/development-docs/azure-powershell-design-guidelines.md create mode 100644 documentation/development-docs/design-guidelines/README.md create mode 100644 documentation/development-docs/design-guidelines/cmdlet-best-practices.md create mode 100644 documentation/development-docs/design-guidelines/module-best-practices.md create mode 100644 documentation/development-docs/design-guidelines/parameter-best-practices.md rename documentation/development-docs/{piping-in-powershell.md => design-guidelines/piping-best-practices.md} (58%) rename documentation/development-docs/{ => design-guidelines}/should-process-confirm-impact.md (71%) create mode 100644 documentation/development-docs/examples/README.md create mode 100644 documentation/development-docs/examples/get-cmdlet-example.md create mode 100644 documentation/development-docs/examples/new-cmdlet-example.md create mode 100644 documentation/development-docs/examples/remove-cmdlet-example.md create mode 100644 documentation/development-docs/examples/set-cmdlet-example.md create mode 100644 documentation/development-docs/examples/update-cmdlet-example.md delete mode 100644 documentation/development-docs/patterns-for-standard-cmdlets.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9af4401ebb07..ba87b69e8943 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,67 +1,40 @@ -# Contribute Code or Provide Feedback for Azure PowerShell +# Contributing to Azure PowerShell This repository contains PowerShell cmdlets for developers and administrators to develop, deploy, and manage Microsoft Azure applications. ## Basics -If you would like to become an active contributor to this project, please follow the instructions provided in [Microsoft Azure Projects Contribution Guidelines](http://azure.github.io/guidelines/). - -In the Azure Developer Experience, you are at Step 5: - -[API Design Review](https://github.com/Azure/adx-documentation-pr#begin-api-design-review) -> [Engage with ADX team](https://github.com/Azure/adx-documentation-pr/blob/master/README.md#engage-with-adx-team) -> [Swagger specification](https://github.com/Azure/adx-documentation-pr#create-swagger-specification) -> [SDKs](https://github.com/Azure/adx-documentation-pr#sdks) -> _**[CLIs](https://github.com/Azure/adx-documentation-pr#clis)**_ - -## Table of Contents - -[Before Starting](#before-starting) -- [Onboarding](#onboarding) -- [GitHub Basics](#github-basics) - - [GitHub Workflow](#github-workflow) - - [Forking the Azure/azure-powershell repository](#forking-the-azureazure-powershell-repository) -- [Code of Conduct](#code-of-conduct) - -[Filing Issues](#filing-issues) - -[Submitting Changes](#submitting-changes) -- [Pull Requests](#pull-requests) -- [SDK for .NET](#sdk-for-net) -- [Pull Request Guidelines](#pull-request-guidelines) - - [Cleaning up commits](#cleaning-up-commits) - - [Updating the change log](#updating-the-change-log) - - [General guidelines](#general-guidelines) - - [Testing guidelines](#testing-guidelines) - - [Cmdlet signature guidelines](#cmdlet-signature-guidelines) - - [Cmdlet parameter guidelines](#cmdlet-parameter-guidelines) - - [Cmdlet pipeline guidelines](#cmdlet-pipeline-guidelines) +If you would like to become an active contributor to this project (or any other open source Microsoft project), please see the list of resources found on [this page](https://opensource.microsoft.com/resources). ## Before Starting ### Onboarding -Make sure that your GitHub account is part of the Azure organization. [Use this page](http://aka.ms/azuregithub) to link your account. +All users must sign the [Microsoft Contributor License Agreement (CLA)](https://cla.opensource.microsoft.com/) before any code contribution can be made. For Microsoft employees, make sure that your GitHub account is part of the Azure organization. [Use this page](http://aka.ms/azuregithub) to link your account. -Before cloning this repository, please make sure you have started in our [documentation repository](https://github.com/Azure/adx-documentation-pr) (you will only have access to that page if you are part of the Azure organization). +### Code of Conduct + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. ### GitHub Basics #### GitHub Workflow -If you don't have experience with Git and GitHub, some of the terminology and process can be confusing. [Here is a guide to understanding the GitHub flow](https://guides.github.com/introduction/flow/) and [here is a guide to understanding the basic Git commands](https://education.github.com/git-cheat-sheet-education.pdf). +If you don't have much experience using GitHub or Git, [here is a guide to understanding the GitHub flow](https://guides.github.com/introduction/flow/) and [here is a guide to understanding the basic Git commands](https://education.github.com/git-cheat-sheet-education.pdf). #### Forking the Azure/azure-powershell repository Unless you are working with multiple contributors on the same file, we ask that you fork the repository and submit your pull request from there. [Here is a guide to forks in GitHub](https://guides.github.com/activities/forking/). -### Code of Conduct - -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. - ## Filing Issues You can find all of the issues that have been filed in the [Issues](https://github.com/Azure/azure-powershell/issues) section of the repository. -If you encounter any bugs with Microsoft Azure PowerShell, please file an issue [here](https://github.com/Azure/azure-powershell/issues/new) and make sure to fill out the provided template with the requested information. +To file an issue, first select one of the [provided templates](https://github.com/Azure/azure-powershell/issues/new/choose) to ensure that the proper information is provided. The following are a few of the templates we have: -To suggest a new feature or changes that could be made to Azure PowerShell, file an issue the same way you would for a bug, but remove the provided template and replace it with information about your suggestion. +- [_Az module bug report_](https://github.com/Azure/azure-powershell/issues/new?assignees=&labels=&template=az-module-bug-report.md&title=) +- [_AzureRM module bug report_](https://github.com/Azure/azure-powershell/issues/new?assignees=&labels=&template=azurerm-module-bug-report.md&title=) +- [_Feature request_](https://github.com/Azure/azure-powershell/issues/new?assignees=&labels=Feature+Request&template=feature_request.md&title=) You can find the code complete and release dates of the next three Azure PowerShell releases in the [Milestones](https://github.com/Azure/azure-powershell/milestones) section of the Issue page. Each milestone will display the issues that are being worked on for the corresponding release. @@ -71,110 +44,57 @@ You can find the code complete and release dates of the next three Azure PowerSh You can find all of the pull requests that have been opened in the [Pull Request](https://github.com/Azure/azure-powershell/pulls) section of the repository. -To open your own pull request, click [here](https://github.com/Azure/azure-powershell/compare). When creating a pull request, keep the following in mind: +When creating a pull request, keep the following in mind: - Make sure you are pointing to the fork and branch that your changes were made in - Choose the correct branch you want your pull request to be merged into - The **master** branch is for active development; changes in this branch will be in the next Azure PowerShell release + - The **preview** branch is a snapshot of the last `AzureRM` release and _should not_ be used for active development - The **release-X.X.X** branch is for active development during a release - The pull request template that is provided **should be filled out**; this is not something that should just be deleted or ignored when the pull request is created - Deleting or ignoring this template will elongate the time it takes for your pull request to be reviewed - The SLA for reviewing pull requests is **two business days** -### SDK for .NET - -If your changes require a new version of an Azure management library, please ensure that the corresponding NuGet package has been published from the [Azure SDK for .NET repository](https://github.com/Azure/azure-sdk-for-net). - -For more information on how to make changes to the SDK for .NET repository and publish packages to NuGet, please see the [`README.md`](https://github.com/Azure/azure-sdk-for-net/blob/psSdkJson6/README.md) in the Azure SDK for .NET repository. - ### Pull Request Guidelines A pull request template will automatically be included as a part of your PR. Please fill out the checklist as specified. Pull requests **will not be reviewed** unless they include a properly completed checklist. -The following is a list of guidelines that pull requests opened in the Azure PowerShell repository must adhere to. You can find a more complete discussion of Azure PowerShell design guidelines [here](documentation/development-docs/azure-powershell-design-guidelines.md). - -#### Cleaning up Commits - -If you are thinking about making a large change to your Azure PowerShell cmdlets, **break up the change into small, logical, testable chunks, and organize your pull requests accordingly**. - -Often when a pull request is created with a large number of files changed and/or a large number of lines of code added and/or removed, GitHub will have a difficult time opening up the changes on their site. This forces the Azure PowerShell team to uses separate software, such as CodeFlow or Beyond Compare, to do a code review on the pull request. +The following is a list of guidelines that pull requests opened in the Azure PowerShell repository must adhere to. You can find a more complete discussion of Azure PowerShell design guidelines [here](documentation/development-docs/design-guidelines). -If you find yourself creating a pull request and are unable to see all the changes on GitHub, we recommend **splitting the pull request into multiple pull requests that are able to be reviewed on GitHub**. +#### General guidelines -If splitting up the pull request is not an option, we recommend **creating individual commits for different parts of the pull request, which can be reviewed individually on GitHub**. +The following guidelines must be followed in **EVERY** pull request that is opened. -For more information on cleaning up the commits in a pull request, such as how to rebase, squash, and cherry-pick, click [here](documentation/development-docs/cleaning-up-commits.md). +- Title of the pull request is clear and informative +- The appropriate `ChangeLog.md` file has been updated with a snippet describing the changes being made +- There are a [small number of commits](documentation/development-docs/cleaning-up-commits.md) that each have an informative message +- All files shipped with a module should contain a proper Microsoft license header +- For public API changes to cmdlets: + - a cmdlet design review was approved for the changes in [this repository](https://github.com/Azure/azure-powershell-cmdlet-review-pr) + - the markdown help files have been regenerated using the commands listed [here](https://github.com/Azure/azure-powershell/blob/master/documentation/development-docs/help-generation.md#updating-all-markdown-files-in-a-module) -#### Updating the change log +#### Testing guidelines -Any changes that are made must be reflected in the respecitve service's change log under the `Upcoming Release` header. This change log will allow customers to easily track what has been changed between releases of a service. +The following guidelines must be followed in **EVERY** pull request that is opened. -For ARM service projects, the change log is located at `src/{{service}}/{{service}}/ChangeLog.md`. +- Changes made have corresponding test coverage +- Tests should not include any hardcoded values, such as location, resource id, etc. +- Tests should have proper setup of resources to ensure any user can re-record the test if necessary +- No existing tests should be skipped -#### Breaking Changes +#### Cmdlet guidelines -Breaking changes should **not** be introduced into the repository without giving customers at least six months notice. For a description of breaking changes in Azure PowerShell and how to declare them in the code using the [various breaking change attributes](documentation/breaking-changes/breaking-changes-attribute-help.md), see [here](documentation/breaking-changes/breaking-changes-definition.md). +Please see the [_Cmdlet Best Practices_](./documentation/development-docs/design-guidelines/cmdlet-best-practices.md) document for information about cmdlet design guidelines. -Whenever a service team announces a breaking change, they must add it to the `upcoming-breaking-changes.md` file in their respective service folder. When the service team is ready to release the module with the breaking change, they must move the corresponding information from `upcoming-breaking-changes.md` into the `current-breaking-changes.md` file located in their service folder. +Examples of standard cmdlets that follow Azure PowerShell patterns and best practices can be found [here](./documentation/development-docs/examples). -#### General guidelines +#### Parameter guidelines -The following guidelines must be followed in **EVERY** pull request that is opened. +Please see the [_Parameter Best Practices_](./documentation/development-docs/design-guidelines/parameter-best-practices.md) document for information about parameter design guidelines. -- Title of the pull request is clear and informative -- There are a small number of commits that each have an informative message -- A description of the changes the pull request makes is included, and a reference to the bug/issue the pull request fixes is included, if applicable -- All files have the Microsoft copyright header -- Cmdlets refer to the management libraries through NuGet references - no dlls are checked in -- The pull request does not introduce [breaking changes](documentation/breaking-changes/breaking-changes-definition.md) (unless a major version change occurs in the assembly and module) +#### Piping guidelines -#### Testing guidelines +Please see the [_Piping Best Practices_](./documentation/development-docs/design-guidelines/piping-best-practices.md) document for information about piping design guidelines. -The following guidelines must be followed in **EVERY** pull request that is opened. +#### Module guidelines -- Pull request includes test coverage for the included changes -- Tests must use xunit, and should either use Moq to mock management client calls, or use the scenario test framework -- Test code should not contain hard coded values for resource names, resource locations, subscriptions, tenants, or similar values. Test scripts, when run live, should be executable using any subscription and any location in Azure -- PowerShell scripts used in tests must do any necessary setup as part of the test or suite setup, and should not use hard-coded values for existing resources -- Test should not use App.config files for settings -- Tests should use the built-in PowerShell functions for generating random names when unique names are necessary - this will store names in the test recording -- Tests should use `Wait-Seconds` for PowerShell and `TestUtilities.Wait` for C# to pause rather than `Start-Sleep` or `Thread.Sleep` respectively - -#### Cmdlet signature guidelines - -The following guidelines must be followed in pull requests that add, edit, or remove a cmdlet. - -- Cmdlet name uses an approved PowerShell verb - use enums for `VerbsCommon`, `VerbsCommunication`, `VerbsData`, `VerbsDiagnostic`, `VerbsLifecycle`, `VerbsOther`, and `VerbsSecurity` whenever possible - - Note that you can see a list of all approved PowerShell verbs by running `Get-Verb` in PowerShell - - When a verb you would like to use is not in the list of approved verbs, or to get ideas on how to use verbs, consult the [Approved Verbs for Windows PowerShell Commands](https://msdn.microsoft.com/en-us/library/ms714428\(v=vs.85\).aspx) documentation where you will find descriptions of approved verbs as well as related verbs in the comments so that you can find one appropriate for your command -- Cmdlet noun name uses the AzureRm prefix for management cmdlets, and the Azure prefix for data plane cmdlets -- Cmdlet specifies the `OutputType` attribute; if the cmdlet produces no output, it should have an `OutputType` of `bool` and implement a `PassThrough` parameter -- If the cmdlet makes changes or has side effects, it should implement `ShouldProcess` and have `SupportsShouldProcess = true` specified in the cmdlet attribute. See a discussion about correct `ShouldProcess` implementation [here](documentation/development-docs/should-process-confirm-impact.md). -- Cmdlets should derive from [`AzureRmCmdlet`](https://github.com/Azure/azure-powershell-common/blob/master/src/ResourceManager/Version2016_09_01/AzureRMCmdlet.cs) class for management cmdlets, and [`AzureDataCmdlet`](https://github.com/Azure/azure-powershell-common/blob/master/src/Common/AzureDataCmdlet.cs) for data cmdlets -- If multiple parameter sets are implemented, the cmdlet should specify a `DefaultParameterSetName` in its cmdlet attribute - -#### Cmdlet parameter guidelines - -The following guidelines must be followed in pull requests that add, edit, or remove a parameter. - -- Cmdlets should have no more than four positional parameters -- Cmdlet parameter sets should be mutually exclusive - each parameter set must have at least one mandatory parameter not in other parameter sets -- Parameter types should not expose types from the management library - complex parameter types should be defined in the module -- Complex parameter types are discouraged - a parameter type should be simple types as often as possible. If complex types are used, they should be shallow and easily creatable from a constructor or another cmdlet -- Parameters should be explicitly marked as `Mandatory` or not, and should contain a `HelpMessage` -- No parameter is of type `object` -- Management cmdlets should have the following parameters and aliases: - - `ResourceGroupName` with (optional) alias to `ResourceGroupName` type `string` marked as `[ValueFromPipelineByPropertyName]` - - `Name` with alias to `ResourceName` type `string` marked as `[ValueFromPipelineByPropertyName]` - - `Location` (if appropriate) type `string` - - `Tag` type `HashTable` - -#### Cmdlet pipeline guidelines - -The following guidelines must be followed in pull requests that make changes to pipeline parameters. - -- Complex parameters should take values from the pipeline when possible, and certainly when they match the output type of another cmdlets -- Only one parameter should use `ValueFromPipeline` per parameter set; parameters from different parameter sets may have this attribute, but should not be convertible -- No parameter is of type `object` -- Each management cmdlet should have a parameter set that takes `ResourceGroupName` and `Name` from the pipeline by property value -- For a given resource type, it should be possible to pipe the output of `Get` and `New` cmdlets to the input of `Set`, `Update`, `Remove` and other action cmdlets for that resource -- More information can be found [here](https://github.com/Azure/azure-powershell/blob/master/documentation/development-docs/piping-in-powershell.md) +Please see the [_Module Best Practices_](./documentation/development-docs/design-guidelines/module-best-practices.md) document for information about module design guidelines. diff --git a/README.md b/README.md index 7ae0e9d81042..1a165cd3c732 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,9 @@ Try it out in Azure Cloud Shell! ## Modules Below is a table containing our Azure PowerShell rollup module. -Description | Module Name | PowerShell Gallery Link -------------------------------------- | --------------------------------------- | ----------------------- -Azure PowerShell | `Az` | [![Az]][AzGallery] +Description | Module Name | PowerShell Gallery Link +----------------- | ------------ | ----------------------- +Azure PowerShell | `Az` | [![Az]][AzGallery] For a full list of modules found in this repository, please see the [Azure PowerShell Modules][AzurePowerShelModules] document. @@ -27,7 +27,7 @@ Run the following command in an elevated PowerShell session to install the rollu Install-Module -Name Az ``` -This module runs on Windows PowerShell with [.NET Framework 4.7.2][DotNetFramework] or greater, or [PowerShell Core][PowerShellCore]. The Az module replaces AzureRM. You should not install Az side-by-side with AzureRM. +This module runs on Windows PowerShell with [.NET Framework 4.7.2][DotNetFramework] or greater, or [PowerShell Core][PowerShellCore]. The `Az` module replaces `AzureRM`. You should not install `Az` side-by-side with `AzureRM`. If you have an earlier version of the Azure PowerShell modules installed from the PowerShell Gallery and would like to update to the latest version, run the following commands in an elevated PowerShell session: @@ -43,7 +43,7 @@ For detailed instructions on installing Azure PowerShell, please refer to the [i ### Log into Azure -To connect to Azure, use the [Connect-AzAccount][ConnectAzAccount] cmdlet: +To connect to Azure, use the [`Connect-AzAccount`][ConnectAzAccount] cmdlet: ```powershell # Device Code login - Provides a link to sign into Azure via your web browser @@ -53,7 +53,7 @@ Connect-AzAccount Connect-AzAccount -ServicePrincipal -ApplicationId 'http://my-app' -Credential $PSCredential -TenantId $TenantId ``` -To log into a specific cloud (_AzureChinaCloud_, _AzureCloud_, _AzureGermanCloud_, _AzureUSGovernment_), use the `Environment` parameter: +To log into a specific cloud (_AzureChinaCloud_, _AzureCloud_, _AzureGermanCloud_, _AzureUSGovernment_), use the `-Environment` parameter: ```powershell # Specific cloud login - Logs into the Azure China cloud @@ -62,7 +62,7 @@ Connect-AzAccount -Environment AzureChinaCloud ### Getting and setting your Azure PowerShell session context -A session context persists login information across Azure PowerShell modules and PowerShell instances. To view the context you are using in the current session, which contains the subscription and tenant, use the [Get-AzContext][GetAzContext] cmdlet: +A session context persists login information across Azure PowerShell modules and PowerShell instances. To view the context you are using in the current session, which contains the subscription and tenant, use the [`Get-AzContext`][GetAzContext] cmdlet: ```powershell # Gets the Azure PowerShell context for the current PowerShell session @@ -72,7 +72,7 @@ Get-AzContext Get-AzContext -ListAvailable ``` -To get the subscriptions in a tenant, use the [Get-AzSubscription][GetAzSubscription] cmdlet: +To get the subscriptions in a tenant, use the [`Get-AzSubscription`][GetAzSubscription] cmdlet: ```powershell # Get all of the Azure subscriptions in your current Azure tenant @@ -82,7 +82,7 @@ Get-AzSubscription Get-AzSubscription -TenantId $TenantId ``` -To change the subscription that you are using for your current context, use the [Set-AzContext][SetAzContext] cmdlet: +To change the subscription that you are using for your current context, use the [`Set-AzContext`][SetAzContext] cmdlet: ```powershell # Set the Azure PowerShell context to a specific Azure subscription @@ -139,13 +139,13 @@ Alternatively, be sure to check out the [Azure Community Support](https://azure. ### Feedback -If there is a feature you would like to see in Azure PowerShell, please use the [Send-Feedback][SendFeedback] cmdlet, or file an issue in our [GitHub issues][GitHubIssues] page to provide the Azure PowerShell team direct feedback. +If there is a feature you would like to see in Azure PowerShell, please use the [`Send-Feedback`][SendFeedback] cmdlet, or file an issue in our [GitHub issues][GitHubIssues] page to provide the Azure PowerShell team direct feedback. ## Contribute Code If you would like to become an active contributor to this project, please follow the instructions provided in [Microsoft Azure Projects Contribution Guidelines][ContributionGuidelines]. -Additional information about contributing to this repository can be found in the [Contributing][Contributing] document and the [Azure PowerShell Developer Guide][DeveloperGuide] document. +Additional information about contributing to this repository can be found in the [`CONTRIBUTING.md`][Contributing] document and the [_Azure PowerShell Developer Guide_][DeveloperGuide] document. ## Learn More diff --git a/documentation/Debugging-StaticAnalysis-Errors.md b/documentation/Debugging-StaticAnalysis-Errors.md index a8afebf2d40b..c7ab2bcca422 100644 --- a/documentation/Debugging-StaticAnalysis-Errors.md +++ b/documentation/Debugging-StaticAnalysis-Errors.md @@ -42,7 +42,7 @@ _Note_: Sometimes the error listed in the .csv file can be a false positive (for We take breaking changes very seriously, so please be mindful about the violations that you suppress in our repo. ### Signature Issues -Signature issues occur when your cmdlets do not follow PowerShell standards. Please check [this page](https://github.com/Azure/azure-powershell/blob/master/documentation/development-docs/azure-powershell-design-guidelines.md) to ensure you are following PowerShell guidelines. Issues with severity 0 or 1 must be addressed, while issues with severity 2 are advisory. If you have an issue with severity 0 or 1 that has been approved by the Azure PowerShell team, you can suppress them following these steps: +Signature issues occur when your cmdlets do not follow PowerShell standards. Please check the [_Cmdlet Best Practices_](https://github.com/Azure/azure-powershell/blob/master/documentation/development-docs/design-guidelines/cmdlet-best-practices.md) and the [_Parameter Best Practices_](https://github.com/Azure/azure-powershell/blob/master/documentation/development-docs/design-guidelines/parameter-best-practices.md) documents to ensure you are following PowerShell guidelines. Issues with severity 0 or 1 must be addressed, while issues with severity 2 are advisory. If you have an issue with severity 0 or 1 that has been approved by the Azure PowerShell team, you can suppress them following these steps: - Download the `SignatureIssues.csv` file from the Jenkins build - Open the file using a text editor (such as VS Code) and copy each of the errors you'd like to suppress diff --git a/documentation/development-docs/azure-powershell-design-guidelines.md b/documentation/development-docs/azure-powershell-design-guidelines.md deleted file mode 100644 index 5f49f8a7adae..000000000000 --- a/documentation/development-docs/azure-powershell-design-guidelines.md +++ /dev/null @@ -1,326 +0,0 @@ -# Azure PowerShell Design Guidelines - -## Table of Contents - -- [Cmdlet Guidelines](#cmdlet-guidelines) - - [Cmdlet Naming Conventions](#cmdlet-naming-conventions) - - [Verb-Noun Format](#verb-noun-format) - - [Pascal Case](#pascal-case) - - [Noun Prefix](#noun-prefix) - - [Specific Noun and Noun Singularity](#specific-noun-and-noun-singularity) - - [Set vs. Update](#set-vs-update) - - [Cmdlet Alias](#cmdlet-alias) - - [Output Type](#output-type) - - [Returning Wrapped SDK Types](#returning-wrapped-sdk-types) - - [Returning No Output](#returning-no-output) - - [ShouldProcess](#should-process) - - [When to Add the Force Parameter](#when-to-add-the-force-parameter) -- [Parameter Guidelines](#parameter-guidelines) - - [Parameter Naming Conventions](#parameter-naming-conventions) - - [Standard Parameter Name](#standard-parameter-name) - - [Pascal Case](#pascal-case) - - [Singularity](#singularity) - - [Parameter Alias](#parameter-alias) - - [Bool vs. SwitchParameter](#bool-vs-switchparameter) - - [Closed Set of Values](#closed-set-of-values) - - [Consistent Parameter Types](#consistent-parameter-types) -- [Parameter Set Guidelines](#parameter-set-guidelines) - - [Parameter Set Naming Conventions](#parameter-set-naming-conventions) - - [Pascal Case](#pascal-case) - - [Attribute Guidelines](#attribute-guidelines) - - [Mutually Exclusive Parameter Sets](#mutually-exclusive-parameter-sets) - - [Positional Parameters Limit](#positional-parameters-limit) - - [ValueFromPipeline Limit](#valuefrompipeline-limit) - - [Required Parameter Sets](#required-parameter-sets) - - [Interactive Parameter Set](#interactive-parameter-set) - - [ResourceId Parameter Set](#resourceid-parameter-set) - - [InputObject Parameter Set](#inputobject-parameter-set) -- [Piping Guidelines](#piping-guidelines) - - [ResourceId](#resourceid) - - [InputObject](#inputobject) -- [AsJob Parameter](#asjob-parameter) -- [Argument Completers](#argument-completers) - -## Expected Patterns for Standard Cmdlets - -For information and examples on standard cmdlet implementation (`Get-*`, `New-*`, `Remove-*` and `Set/Update-*`) for resources and child resources, please see our [Expected Patterns for Standard Cmdlets](./patterns-for-standard-cmdlets.md) document. - -## Cmdlet Guidelines - -### Cmdlet Naming Conventions - -The following are naming conventions to keep in mind when coming up with a name for your cmdlet. - -#### Verb-Noun Format - -Cmdlet names should follow the _Verb-Noun_ format, where the verb is from the [list of approved PowerShell verbs](https://docs.microsoft.com/en-us/powershell/developer/cmdlet/approved-verbs-for-windows-powershell-commands), and the noun is a specific noun describing a resource within your service. - -#### Pascal Case - -From the [Strongly Encouraged Development Guidelines](https://docs.microsoft.com/en-us/powershell/developer/cmdlet/strongly-encouraged-development-guidelines#use-pascal-case-for-cmdlet-names-sd02): - -> _Use Pascal case for cmdlet names. In other words, capitalize the first letter of the verb and all terms used in the noun. For example, "Clear-ItemProperty"._ - -#### Noun Prefix - -For ARM cmdlets, the noun must be prefixed with `Az`. - -#### Specific Noun and Noun Singularity - -From the [Strongly Encouraged Development Guidelines](https://docs.microsoft.com/en-us/powershell/developer/cmdlet/strongly-encouraged-development-guidelines#use-a-specific-noun-for-a-cmdlet-name-sd01): - -> _Nouns used in cmdlet naming need to be very specific so that the user can discover your cmdlets. Prefix generic nouns such as "server" with a shortened version of the product name. For example, if a noun refers to a server that is running an instance of Microsoft SQL Server, use a noun such as "SQLServer". The combination of specific nouns and the short list of approved verbs enable the user to quickly discover and anticipate functionality while avoiding duplication among cmdlet names._ -> -> _To enhance the user experience, the noun that you choose for a cmdlet name should be singular. For example, use the name `Get-Process` instead of `Get-Processes`. It is best to follow this rule for all cmdlet names, even when a cmdlet is likely to act upon more than one item._ - -#### Set vs. Update - -If your cmdlet is performing a **PATCH** operation (_i.e._, a partial replacement on the server), then the cmdlet should use the verb `Update`. - -If your cmdlet is performing a **PUT** operation (_i.e._, a full replacement on the server), the the cmdlet should use the verb `Set`. - -#### Cmdlet Alias - -If you there is a separate nomenclature for your service and/or resource, or if you would like to shorten the name of the cmdlet so it's easier to remember, you can add an alias attribute to your cmdlet to allow for this functionality. - -### Output Type - -Specified by the `OutputType` attribute, this piece of metadata lets the user know what the type of the object returned by the cmdlet is (found in the **Outputs** section of a cmdlet's help content). - -#### Returning Wrapped SDK Types - -In most cases, cmdlets will be returning an object corresponding to a resource(s) that a user is performing an action on. Rather than returning the .NET SDK type for that resource (exposing .NET SDK types in PowerShell cmdlets is _strongly_ discouraged), we suggest creating a new class that wraps this .NET SDK type, allowing for breaking changes in the underlying type while avoiding breaking changes in the PowerShell type. - -For example, the `Get-AzVM` cmdlet uses the .NET SDK to retrieve objects of the `VirtualMachine` type, but a new class, `PSVirtualMachine`, was created to wrap the type from the .NET SDK, and is returned by the cmdlet. If, in the future, the `VirtualMachine` type in the .NET SDK has a property removed, that property can still be maintained in PowerShell by adding it to the `PSVirtualMachine` and recreating the value, thus avoiding a breaking change in the cmdlet(s). - -#### Returning No Output - -In the case where your cmdlet doesn't return any output (_e.g._, removing, starting, stopping a resource), the cmdlet should implement the `PassThru` parameter and the `OutputType` should be set to `bool`. The `PassThru` parameter is a `SwitchParameter` set by the user to signal that they would like to receive output from a cmdlet which does not return anything. If the `PassThru` parameter is provided, you should return the value `true` so the user is made aware that the operation was successful. If the operation was unsuccessful, then the cmdlet should throw an exception. - -### ShouldProcess - -If a cmdlet makes any changes to an object on the server (_e.g._, create, delete, update, start, stop a resource), the cmdlet should implement `ShouldProcess`. This property adds the `WhatIf` and `Confirm` parameters to the cmdlet: `WhatIf` is a `SwitchParameter` that, when provided by the user, doesn't execute the part of the cmdlet responsible for making the changes to the object, but rather displays a message alerting the user of the action that is to be performed on the object; `Confirm` is a `SwitchParameter` that, when provided by the user, prompts the user for confirmation that they want to continue with the execution of the cmdlet. - -More information about `ShouldProcess` can be found in the [Should Process and Confirm Impact](./should-process-confirm-impact.md) document. - -#### When to Add the Force Parameter - -The `Force` parameter is reserved for special scenarios where additional confirmation from the user is required. From the above document on [Should Process and Confirm Impact](./should-process-confirm-impact.md) document: - -> _Some cmdlets required additional confirmation. For example, if a cmdlet would destroy existing resources in some circumstances, the cmdlet might detect that condition and prompt the user to verify before continuing. Overwriting an existing resource during resource creation, overwriting a file when downloading data, deleting a resource that is currently in use, or deleting a container that contains additional resources are all example of this pattern. To implement additional confirmation, and allow scripts to opt out of additional prompts, the above pattern is enhanced with calles to `ShouldContinue()` and the `Force` parameter._ - -## Parameter Guidelines - -### Parameter Naming Conventions - -The following are naming conventions to keep in mind when coming up with a name for your parameters. - -In addition, a recommended list of parameter names can be found [here](https://docs.microsoft.com/en-us/powershell/developer/cmdlet/standard-cmdlet-parameter-names-and-types). - -#### Standard Parameter Name - -From the [Strongly Encouraged Development Guidelines](https://docs.microsoft.com/en-us/powershell/developer/cmdlet/strongly-encouraged-development-guidelines#use-standard-parameter-names): - -> _Your cmdlet should use standard parameter names so that the user can quickly determine what a particular parameter means. If a more specific name is required, use a standard parameter name, and then specify a more specific name as an alias. For example, the `Get-Service` cmdlet has a parameter that has a generic name (**Name**) and a more specific alias (**ServiceName**). Both terms can be used to specify the parameter._ - -#### Pascal Case - -Similar to cmdlets (mentioned above), parameters should follow pascal casing.From the [Strongly Encouraged Development Guidelines](https://docs.microsoft.com/en-us/powershell/developer/cmdlet/strongly-encouraged-development-guidelines#use-pascal-case-for-parameter-names): - -> _Use Pascal case for parameter names. In other words, capitalize the first letter of each word in the parameter name, including the first letter of the name._ - -#### Singularity - -From the [Strongly Encouraged Development Guidelines](https://docs.microsoft.com/en-us/powershell/developer/cmdlet/strongly-encouraged-development-guidelines#use-singular-parameter-names): - -> _Avoid using plural names for parameters whose value is a single element. This includes parameters that take arrays or lists because the user might supply an array or list with only one element._ -> ->_Plural parameter names should be used only in those cases where the value of the parameter is always a multiple-element value. In these cases, the cmdlet should verify that multiple elements are supplied, and the cmdlet should display a warning to the user if multiple elements are not supplied._ - -#### Parameter Alias - -If you there is a separate nomenclature for the parameter name, or if you would like to shorten the name of the parameter so it's easier to remember, you can add an alias attribute to your parameter to allow for this functionality. - -### Bool vs. SwitchParameter - -Parameters of type `bool` are _strongly_ discouraged in PowerShell. The `SwitchParameter` type of a parameter acts a flag that signals whether or not some action should be taken based on if the parameter was provided or not. From the [Strongly Encouraged Development Guidelines](https://docs.microsoft.com/en-us/powershell/developer/cmdlet/strongly-encouraged-development-guidelines#parameters-that-take-true-and-false): - -> _If your parameter takes only true and false, define the parameter as type SwitchParameter. A switch parameter is treated as true when it is specified in a command. If the parameter is not included in a command, Windows PowerShell considers the value of the parameter to be false. Do not define Boolean parameters._ - -### Closed Set of Values - -If there is a closed set of values applicable for a given parameter, use either a `ValidateSet`, enumeration type, or an `ArgumentCompleter`. This functionality allows users to tab through the different values they can provide. From the [Strongly Encouraged Development Guidelines](https://docs.microsoft.com/en-us/powershell/developer/cmdlet/strongly-encouraged-development-guidelines#parameters-that-take-a-list-of-options): - -> _There are two ways to create a parameter whose value can be selected from a set of options._ -> -> - _Define an enumeration type (or use an existing type) that specifies the valid values. Then, use the enumeration type to create a parameter of that type._ -> - _Add the **ValidateSet** attribute to the parameter declaration._ - -In addition, you can choose to add an `ArgumentCompleter` to a parameter to allow users to tab through a closed set of values, _but this does not restrict users on the values they can provide._ For more information on `ArgumentCompleters`, please see the [below section](#argument-completers) - -### Consistent Parameter Types - -From the [Strongly Encouraged Development Guidelines](https://docs.microsoft.com/en-us/powershell/developer/cmdlet/strongly-encouraged-development-guidelines#use-consistent-parameter-types): - -> _When the same parameter is used by multiple cmdlets, always use the same parameter type. For example, if the **Process** parameter is an **Int16** type for one cmdlet, do not make the **Process** parameter for another cmdlet a **UInt16** type._ - -## Parameter Set Guidelines - -### Parameter Set Naming Conventions - -The following are naming conventions to keep in mind when coming up with a name for your parameter set. - -#### Pascal Case - -Similar to cmdlets (mentioned above), parameter set names should follow pascal casing. From the [Strongly Encouraged Development Guidelines](https://docs.microsoft.com/en-us/powershell/developer/cmdlet/strongly-encouraged-development-guidelines#use-pascal-case-for-cmdlet-names-sd02): - -> _Use Pascal case for cmdlet names. In other words, capitalize the first letter of the verb and all terms used in the noun. For example, "Clear-ItemProperty"._ - -### Attribute Guidelines - -The following are guidelines that should be followed when working with the attributes of a parameter set. - -#### Mutually Exclusive Parameter Sets - -For PowerShell to determine which parameter set a user is intending to use with a set of provided parameters, the parameter sets need to be designed in such a way that they are mutually exclusive. From the remarks section of [Parameter Attribute Declaration](https://docs.microsoft.com/en-us/powershell/developer/cmdlet/parameter-attribute-declaration#remarks): - -> _Each parameter set must have at least one unique parameter. Good cmdlet design indicates this unique parameter should also be mandatory if possible. If your cmdlet is designed to be run without parameters, the unique parameter cannot be mandatory._ - -#### Positional Parameters Limit - -It is possibile to call a PowerShell cmdlet without providing the parameter names, but just the values you would like to pass through. This is done by specifying the position at which the value of each parameter should be provided by using the `Position` property for a parameter. However, when there are too many positional parameters in a single parameter set, it can be difficult for the user to remember the exact ordering in which the parameter values should be provided. From the remarks section of [Parameter Attribute Declaration](https://docs.microsoft.com/en-us/powershell/developer/cmdlet/parameter-attribute-declaration#remarks): - -> _When you specify positional parameters, limit the number of positional parameters in a parameter set to less than five. And, positional parameters do not have to be contiguous. Positions 5, 100, and 250 work the same as positions 0, 1, and 2._ - -In addition, there should be no two parameters with the same position in the same parameter set. From the remarks section of [Parameter Attribute Declaration](https://docs.microsoft.com/en-us/powershell/developer/cmdlet/parameter-attribute-declaration#remarks): - -> _No parameter set should contain more than one positional parameter with the same position._ - -#### ValueFromPipeline Limit - -Allowing the user to pipe an object from one cmdlet to another is a major scenario in PowerShell, but allowing multiple parameters in the same parameter set to accept their value from the pipeline can cause issues. From the remarks section of [Parameter Attribute Declaration](https://docs.microsoft.com/en-us/powershell/developer/cmdlet/parameter-attribute-declaration#remarks): - -> _Only one parameter in a parameter set should declare ValueFromPipeline = true. Multiple parameters can define ValueFromPipelineByPropertyName = true._ - -### Required Parameter Sets - -In most Azure PowerShell cmdlets, there is a bare minimum of three parameter sets that need to be implemented. - -#### Interactive Parameter Set - -This parameter set should be implemented by _every_ cmdlet - in most cases, the user provides the name of the resource that they are acting upon (`Name`) and the resource group in which they are acting in (`ResourceGroupName`). - -The interactive parameter set **will always be the default parameter set** for a cmdlet (specified by the `DefaultParameterSetName` property in the `Cmdlet` attribute). This means that when PowerShell is unable to determine which parameter set a user is in, it will default to the interactive parameter set and prompt the user to provide values for the missing mandatory parameters. - -#### ResourceId Parameter Set - -This parameter set should be implemented by _every_ cmdlet - the user is able to provide a `ResourceId` string or GUID from the Azure Portal, or from one of the generic resources cmdlets (more information about that below in the piping section), and act upon the given resource associated with the id. The typical `Name` and `ResourceGroupName` parameters are replaced by a single `ResourceId` parameter of type string. - -#### InputObject Parameter Set - -This parameter should be implemented by _most_ cmdlets - the user is able to take the object returned from the `Get`, `New`, or `Set` cmdlets (or other cmdlets that return the common resource) and provide it to the `InputObject` parameter for a cmdlet that acts upon the same resource. The typical `Name` and `ResourceGroupName` parameters are retrieved from the `InputObject` that the user is passing through. - -## Piping Guidelines - -Piping is an important scenario for cmdlets to have enabled in PowerShell. For more information on how piping works and for examples of its usage, please see the [Piping in PowerShell](./piping-in-powershell.md) document. - -Below are the two main piping scenarios that should be applied in the cmdlets with the corresponding parameter sets. - -### ResourceId - -In this scenario, the user is able to pipe the result of a generic resources cmdlet into a cmdlet that accepts `ResourceId`. The below example shows how a user can use the generic resources cmdlet `Find-AzResource` to get all resources of type `Foo` and remove them: - -```powershell -Find-AzResource -ResourceType Microsoft.Foo/foo | Remove-AzFoo -``` - -For more information on enabling the `ResourceId` piping scenario and more examples, please see the ["Using the `ResourceId` parameter"](./piping-in-powershell.md#using-the-resourceid-parameter) section of the _Piping in PowerShell_ document. - -### InputObject - -In this scenario, the user is able to pipe the result of a cmdlet that returns a resource into a cmdlet that accepts that resource as an `InputObject`. The below example shows how a user can get a `Foo` object from one cmdlet and pipe it to a cmdlet that removes it: - -```powershell -Get-AzFoo -Name "FooName" -ResourceGroupName "RG" | Remove-AzFoo -``` - -For more information on enabling the `InputObject` piping scenario and more examples, please see the ["Using the `InputObject` parameter"](./piping-in-powershell.md#using-the-inputobject-parameter) section of the _Piping in PowerShell_ document. - -## AsJob Parameter - -All long running operations must implement the `-AsJob` parameter, which will allow the user to create jobs in the background. For more information about PowerShell jobs and the -AsJob parameter, read [this doc](https://docs.microsoft.com/en-us/powershell/azure/using-psjobs). - -To implement the `-AsJob` parameter, simply add the parameter to the end of the parameter list: - -````cs -[Parameter(Mandatory = false, HelpMessage = "Run cmdlet in the background")] -public SwitchParameter AsJob { get; set; } -```` - -Once you add the parameter, please manually test that the job is created and successfully completes when the parameter is specified. Additionally, please ensure that the help files are updated with this parameter. - -To ensure that `-AsJob` is not broken in future changes, please add a test for this parameter. To update tests to include this parameter, use the following pattern: - -````powershell -$job = Get-AzSubscription -$job | Wait-Job -$subcriptions = $job | Receive-Job -```` - -To set a custom job name, please use [SetBackgroupJobDescription(string name)](https://github.com/Azure/azure-powershell-common/blob/master/src/Common/AzurePSCmdlet.cs#L810). The default job description is: "Long Running Operation for '{cmdlet name}' on resource '{resource name}'" - -## Argument Completers - -PowerShell uses Argument Completers to provide tab completion for users. At the moment, Azure PowerShell has two specific argument completers that should be applied to relevant parameters, and one generic argument completer that can be used to tab complete with a given list of values. - -### Resource Group Completer - -For any parameter that takes a resource group name, the `ResourceGroupCompleter` should be applied as an attribute. This will allow the user to tab through all resource groups in the current subscription. - -```cs -using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; -... -[Parameter(Mandatory = false, HelpMessage = "The resource group name")] -[ResourceGroupCompleter] -public string ResourceGroupName { get; set; } -``` - -### Resource Name Completer - -For any parameter that takes a resource name, the `ResourceNameCompleter` should be applied as an attribute. This will allow the user to tab through all resource names for the ResourceType in the current subscription. This completer will filter based upon the current parent resources provided (for instance, if ResourceGroupName is provided, only the resources in that particular resource group will be returned). For this completer, please provide the ResourceType as the first argument, followed by the parameter name for all parent resources starting at the top level. - -```cs -using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; -... -[Parameter(Mandatory = false, HelpMessage = "The parent server name")] -[ResourceNameCompleter("Microsoft.Sql/servers", nameof(ResourceGroupName))] -public string ServerName { get; set; } - -[Parameter(Mandatory = false, HelpMessage = "The database name")] -[ResourceNameCompleter("Microsoft.Sql/servers/databases", nameof(ResourceGroupName), nameof(ServerName))] -public string Name { get; set; } -``` - -### Location Completer - -For any parameter that takes a location, the `LocationCompleter` should be applied as an attribute. In order to use the `LocationCompleter`, you must input as an argument all of the Providers/ResourceTypes used by the cmdlet. The user will then be able to tab through locations that are valid for all of the Providers/ResourceTypes specified. - -```cs -using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; -... -[Parameter(Mandatory = false, HelpMessage = "The location of the resource")] -[LocationCompleter("Microsoft.Batch/operations")] -public string Location { get; set; } -``` - -### Generic Argument Completer - -For any parameter which you would like the user to tab through a list of suggested values (but you do not want to limit the users to only these values), the generic argument completer should be added. - -```cs -using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; -... -[Parameter(Mandatory = false, HelpMessage = "The tiers of the plan")] -[PSArgumentCompleter("Basic", "Premium", "Elite")] -public string Tier { get; set; } -``` diff --git a/documentation/development-docs/azure-powershell-developer-guide.md b/documentation/development-docs/azure-powershell-developer-guide.md index a95e447c4208..ab180d22bd4c 100644 --- a/documentation/development-docs/azure-powershell-developer-guide.md +++ b/documentation/development-docs/azure-powershell-developer-guide.md @@ -98,17 +98,19 @@ Alternatively, you can open any command prompt (Command Prompt, Windows PowerShe PS C:\azure-powershell> dotnet msbuild build.proj ``` -### Skipping Help Generation During Build +### Running StaticAnalysis and Help Generation -By default, we build the `dll-Help.xml` files (used to display the help content for cmdlets in PowerShell) from markdown using the `platyPS` module. Since this help generation step can take 10-15 minutes, we have added the ability to skip it as a part of the command line build process: +By default, StaticAnalysis and help generation are not run as a part of the local build (`msbuild build.proj`); to run these locally, you will need to add the `/p:RunStaticAnalysis=true` property to your current `msbuild` command, like so: ``` -msbuild build.proj /p:SkipHelp=true +msbuild build.proj /p:RunStaticAnalysis=true ``` +_Note_: this can add 10-15 minutes to your build time due to help generation. + ## Running Tests -Launch `VS Developer Command Prompt` and run the following command (from the root of the repository) to run all of the tests: +Launch `VS Developer Command Prompt` and run the following command (from the root of the repository) to run all of the tests in playback: ``` msbuild build.proj /t:Test @@ -132,7 +134,7 @@ For more information about on-boarding a new library in the SDK for .NET reposit Before development, you must meet with the Azure PowerShell team to have a design review for your proposed PowerShell cmdlets. We advise that this review is held no earlier than three weeks out from code complete of the release you want to ship the cmdlets with. For a small number of cmdlet changes and/or additions, an email containing the markdown files for the proposed changes is suggested. For a large number of changes and/or additions, a meeting is required with the Azure PowerShell team. -Before submitting a design review, please be sure that you have read the [Azure PowerShell Design Guidelines](azure-powershell-design-guidelines.md) document. +Before submitting a design review, please be sure that you have read the documents found in the [Azure PowerShell Design Guidelines](./design-guidelines) folder. Please submit a design review here: https://github.com/Azure/azure-powershell-cmdlet-review-pr @@ -181,7 +183,7 @@ After the solution file is updated, save and close it. Now, open the solution fi ``` **Note**: This is not needed since this is a new project and does not use legacy namespace conventions. - + - Update this entry to use your SDK: ```xml @@ -200,7 +202,7 @@ There are a few existing projects that need to be added before developing any cm ## PowerShell Cmdlet Design Guidelines -Please check out the [PowerShell Cmdlet Design Guidelines](azure-powershell-design-guidelines.md) page for more information on how to create cmdlets that follow the PowerShell guidelines. +Please check out the [_Cmdlet Best Practices_](./design-guidelines/cmdlet-best-practices.md) document for more information on how to create cmdlets that follow the PowerShell guidelines. ## Enable Running PowerShell when Debugging @@ -208,7 +210,7 @@ Please check out the [PowerShell Cmdlet Design Guidelines](azure-powershell-desi - Right click on your project in the **Solution Explorer** and select **Set as StartUp project** - Right-click on the project and select **Properties** - Go to the **Debug** tab -- Under **Start Action**, pick _Start external program_ and type the PowerShell 6.0 directory +- Under **Start Action**, pick _Start external program_ and type the PowerShell 6.0 directory - For example, `C:\Program Files\PowerShell\6\pwsh.exe` ### Importing Modules @@ -298,81 +300,4 @@ Whenver you make updates to a project, please make sure to update the correspond ## Publish to PowerShell Gallery -To publish your module to the [official PowerShell gallery](http://www.powershellgallery.com/) or the test gallery site, contact the Azure PowerShell team - -## AsJob Parameter - -All long running operations must implement the `-AsJob` parameter, which will allow the user to create jobs in the background. For more information about PowerShell jobs and the -AsJob parameter, read [this doc](https://docs.microsoft.com/en-us/powershell/azure/using-psjobs). - -To implement the `-AsJob` parameter, simply add the parameter to the end of the parameter list: - -````cs -[Parameter(Mandatory = false, HelpMessage = "Run cmdlet in the background")] -public SwitchParameter AsJob { get; set; } -```` - -Once you add the parameter, please manually test that the job is created and successfully completes when the parameter is specified. Additionally, please ensure that the help files are updated with this parameter. - -To ensure that `-AsJob` is not broken in future changes, please add a test for this parameter. To update tests to include this parameter, use the following pattern: - -````powershell -$job = Get-AzSubscription -$job | Wait-Job -$subcriptions = $job | Receive-Job -```` - -## Argument Completers - -PowerShell uses Argument Completers to provide tab completion for users. At the moment, Azure PowerShell has two specific argument completers that should be applied to relevant parameters, and one generic argument completer that can be used to tab complete with a given list of values. To test the completers, run a complete build after you have added the completers (`msbuild build.proj`) and ensure that the psm1 file (`Az..psm1`) has been added to the psd1 file found in `artifacts/Debug/Az./Az..psd1` under "Root Module". - -### Resource Group Completer - -For any parameter that takes a resource group name, the `ResourceGroupCompleter` should be applied as an attribute. This will allow the user to tab through all resource groups in the current subscription. - -```cs -using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; -... -[Parameter(Mandatory = false, HelpMessage = "The resource group name")] -[ResourceGroupCompleter] -public string ResourceGroupName { get; set; } -``` - -### Resource Name Completer - -For any parameter that takes a resource name, the `ResourceNameCompleter` should be applied as an attribute. This will allow the user to tab through all resource names for the ResourceType in the current subscription. This completer will filter based upon the current parent resources provided (for instance, if ResourceGroupName is provided, only the resources in that particular resource group will be returned). For this completer, please provide the ResourceType as the first argument, followed by the parameter name for all parent resources starting at the top level. - -```cs -using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; -... -[Parameter(Mandatory = false, HelpMessage = "The parent server name")] -[ResourceNameCompleter("Microsoft.Sql/servers", nameof(ResourceGroupName))] -public string ServerName { get; set; } - -[Parameter(Mandatory = false, HelpMessage = "The database name")] -[ResourceNameCompleter("Microsoft.Sql/servers/databases", nameof(ResourceGroupName), nameof(ServerName))] -public string Name { get; set; } -``` - -### Location Completer - -For any parameter that takes a location, the `LocationCompleter` should be applied as an attribute. In order to use the `LocationCompleter`, you must input as an argument all of the Providers/ResourceTypes used by the cmdlet. The user will then be able to tab through locations that are valid for all of the Providers/ResourceTypes specified. - -```cs -using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; -... -[Parameter(Mandatory = false, HelpMessage = "The location of the resource")] -[LocationCompleter("Microsoft.Batch/operations")] -public string Location { get; set; } -``` - -### Generic Argument Completer - -For any parameter which you would like the user to tab through a list of suggested values (but you do not want to limit the users to only these values), the generic argument completer should be added. - -```cs -using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; -... -[Parameter(Mandatory = false, HelpMessage = "The tiers of the plan")] -[PSArgumentCompleter("Basic", "Premium", "Elite")] -public string Tier { get; set; } -``` +To publish your module to the [official PowerShell gallery](http://www.powershellgallery.com/) or the test gallery site, contact the Azure PowerShell team \ No newline at end of file diff --git a/documentation/development-docs/design-guidelines/README.md b/documentation/development-docs/design-guidelines/README.md new file mode 100644 index 000000000000..32715098fcdd --- /dev/null +++ b/documentation/development-docs/design-guidelines/README.md @@ -0,0 +1,34 @@ +## Azure PowerShell Design Guidelines + +In this folder, you will find best practices and design guidelines for different components of Azure PowerShell. + +### Table of contents + +- [Cmdlet Best Practices](./cmdlet-best-practices.md) + - [Cmdlet Naming Conventions](./cmdlet-best-practices.md#cmdlet-naming-conventions) + - [Output Type](./cmdlet-best-practices.md#output-type) + - [`ShouldProcess`](./cmdlet-best-practices.md#shouldprocess) + - [`AsJob`](./cmdlet-best-practices.md#asjob) + - [Required Parameter Sets](./cmdlet-best-practices.md#required-parameter-sets) +- [Module Best Practices](./module-best-practices.md) + - [Module Metadata](./module-best-practices.md#module-metadata) + - [Module Dependencies](./module-best-practices.md#module-dependencies) +- [Parameter Best Practices](./parameter-best-practices.md) + - [Parameter Guidelines](./parameter-best-practices.md#parameter-guidelines) + - [Parameter Naming Conventions(./parameter-best-practices.md#parameter-naming-conventions)] + - [Parameter Types](./parameter-best-practices.md#parameter-types) + - [Argument Completers](./parameter-best-practices.md#argument-completers) + - [Parameter Set Guidelines](./parameter-best-practices.md#parameter-set-guidelines) + - [Parameter Set Naming Conventions](./parameter-best-practices.md#parameter-set-naming-conventions) + - [Attribute Guidelines](./parameter-best-practices.md#attribute-guidelines) +- [Piping Best Practices](./piping-best-practices.md) + - [Piping in PowerShell](./piping-best-practices.md#piping-in-powershell) + - [Understanding Piping](./piping-best-practices.md#understanding-piping) + - [More Information](./piping-best-practices.md#more-information) + - [Piping in Azure PowerShell](./piping-best-practices.md#piping-in-azure-powershell) + - [Using the `-InputObject` Parameter](./piping-best-practices.md#using-the-inputobject-parameter) + - [Using the `-ResourceId` Parameter](./piping-best-practices.md#using-the-resourceid-parameter) + - [Summary](./piping-best-practices.md#summary) +- [`ShouldProcess` and `ConfirmImpact`](./should-process-confirm-impact.md) + - [`ShouldProcess`](./should-process-confirm-impact.md#shouldprocess) + - [`ConfirmImpact`](./should-process-confirm-impact.md#confirmimpact) \ No newline at end of file diff --git a/documentation/development-docs/design-guidelines/cmdlet-best-practices.md b/documentation/development-docs/design-guidelines/cmdlet-best-practices.md new file mode 100644 index 000000000000..9f23e1667d3e --- /dev/null +++ b/documentation/development-docs/design-guidelines/cmdlet-best-practices.md @@ -0,0 +1,160 @@ +# Cmdlet Best Practices + +### Cmdlet Naming Conventions + +The following are naming conventions to keep in mind when coming up with a name for your cmdlet. + +#### Verb-Noun Format + +Cmdlet names should follow the _Verb-Noun_ format, where the verb is from the [list of approved PowerShell verbs](https://docs.microsoft.com/en-us/powershell/developer/cmdlet/approved-verbs-for-windows-powershell-commands), and the noun is a specific noun describing a resource within your service. + +#### Noun Prefix + +For ARM cmdlets, the noun must be prefixed with `Az`. + +#### Pascal Case + +From the [_Strongly Encouraged Development Guidelines_](https://docs.microsoft.com/en-us/powershell/developer/cmdlet/strongly-encouraged-development-guidelines#use-pascal-case-for-cmdlet-names-sd02): + +> _Use Pascal case for cmdlet names. In other words, capitalize the first letter of the verb and all terms used in the noun. For example, "Clear-ItemProperty"._ + +#### Specific Noun and Noun Singularity + +From the [_Strongly Encouraged Development Guidelines_](https://docs.microsoft.com/en-us/powershell/developer/cmdlet/strongly-encouraged-development-guidelines#use-a-specific-noun-for-a-cmdlet-name-sd01): + +> _Nouns used in cmdlet naming need to be very specific so that the user can discover your cmdlets. Prefix generic nouns such as "server" with a shortened version of the product name. For example, if a noun refers to a server that is running an instance of Microsoft SQL Server, use a noun such as "SQLServer". The combination of specific nouns and the short list of approved verbs enable the user to quickly discover and anticipate functionality while avoiding duplication among cmdlet names._ +> +> _To enhance the user experience, the noun that you choose for a cmdlet name should be singular. For example, use the name `Get-Process` instead of `Get-Processes`. It is best to follow this rule for all cmdlet names, even when a cmdlet is likely to act upon more than one item._ + +#### Set vs. Update + +If your cmdlet is performing a **PATCH** operation (_i.e._, a partial replacement on the server), then the cmdlet should use the verb `Update`. + +If your cmdlet is performing a **PUT** operation (_i.e._, a full replacement on the server), the the cmdlet should use the verb `Set`. + +#### Cmdlet Alias + +If you there is a separate nomenclature for your service and/or resource, or if you would like to shorten the name of the cmdlet so it's easier to remember, you can add an alias attribute to your cmdlet to allow for this functionality. + +### Output Type + +Specified by the `OutputType` attribute, this piece of metadata lets the user know what the type of the object returned by the cmdlet is (found in the **Outputs** section of a cmdlet's help content). The type specified here should always be a single element and not an enumeration of elements (_e.g._, `PSVirtualMachine` instead of `List`). + +#### Valid Output Types + +If the cmdlet returns an object, the type of the object returned must be defined; the output type for a cmdlet should _never_ be `object`, `PSObject`, `PSCustomObject` or the like. Returning these types of objects makes it difficult for the user to anticipate what properties will be found on the object returned from the cmdlet, as well as makes it impossible for the breaking change analyzer to detect if a breaking change was introduced to the cmdlet as the type is not defined. + +In order to preserve proper piping scenarios, the output type for a cmdlet should _never_ be a `string`. If a cmdlet is expected to return a `string`, the suggestion is to introduce a new type that encapsulates the `string` information as a property and return that object. The PowerShell language revolves around objects and passing them around cmdlets; returning `string` objects can introduce inconsistencies in the piping experience for users. + +#### Returning Wrapped SDK Types + +In most cases, cmdlets will be returning an object corresponding to a resource that a user is performing an action on. Rather than returning the .NET SDK type for that resource (exposing .NET SDK types in PowerShell cmdlets is _strongly_ discouraged), we suggest creating a new class that wraps this .NET SDK type, allowing for breaking changes in the underlying type while avoiding breaking changes in the PowerShell type. + +For example, the `Get-AzVM` cmdlet uses the .NET SDK to retrieve objects of the `VirtualMachine` type, but a new class, `PSVirtualMachine`, was created to wrap the type from the .NET SDK, and is returned by the cmdlet. If, in the future, the `VirtualMachine` type in the .NET SDK has a property removed, that property can still be maintained in PowerShell by adding it to the `PSVirtualMachine` type and recreating the value, thus avoiding a breaking change in the corresponding cmdlet(s). + +#### Returning No Output + +In the case where your cmdlet doesn't return any output (_e.g._, deleting, starting, stopping a resource), the cmdlet should implement the `-PassThru` parameter and the `OutputType` should be set to `bool`. The `-PassThru` parameter is a `SwitchParameter` set by the user to signal that they would like to receive output from a cmdlet which does not return anything. If the `-PassThru` parameter is provided, you should return the value `true` so the user is made aware that the operation was successful. If the operation was unsuccessful, then the cmdlet should throw an exception. + +From the [_Strongly Encouraged Development Guidelines_](https://docs.microsoft.com/en-us/powershell/developer/cmdlet/strongly-encouraged-development-guidelines#support-the-passthru-parameter): + +> _By default, many cmdlets that modify the system, such as the `Stop-Process` cmdlet, act as "sinks" for objects and do not return a result. These cmdlet should implement the `-PassThru` parameter to force the cmdlet to return an object._ + +The code below shows how this should look in a cmdlet: + +```cs +[Cmdlet(...), OutputType(typeof(bool))] +public class MySampleCmdlet : MyBaseCmdlet +{ + // other parameters omitted + + [Parameter(Mandatory = false)] + public SwitchParameter PassThru { get; set; } + + public override void ExecuteCmdlet() + { + // other code omitted + + if (this.IsPassThru.IsPresent) + { + WriteObject(true); + } + } +} +``` + +### `ShouldProcess` + +If a cmdlet makes any changes to an object on the server (_e.g._, create, delete, update, start, stop a resource), the cmdlet should implement `ShouldProcess`. This property adds the `-WhatIf` and `-Confirm` parameters to the cmdlet: + +- `-WhatIf` is a `SwitchParameter` that, when provided by the user, doesn't execute the part of the cmdlet responsible for making the changes to the object, but rather displays a message alerting the user of the action that is to be performed on the object +- `-Confirm` is a `SwitchParameter` that, when provided by the user, prompts the user for confirmation that they want to continue with the execution of the cmdlet. + +The code below showshow this should look in a cmdlet: + +```cs +[Cmdlet(..., SupportsShouldProcess = true), OutputType(typeof(...))] +public class MySampleCmdlet : MyBaseCmdlet +{ + // parameters omitted + + public override void ExecuteCmdlet() + { + // other code omitted + + if (ShouldProcess(targetResource, actionMessage)) + { + // make the change + } + } +} +``` + +More information about `ShouldProcess` can be found in the [_Should Process and Confirm Impact_](./should-process-confirm-impact.md) document. + +#### When to Add the Force Parameter + +The `-Force` parameter is reserved for special scenarios where additional confirmation from the user is required. From the above document on [_Should Process and Confirm Impact_](./should-process-confirm-impact.md) document: + +> _Some cmdlets require additional confirmation. For example, if a cmdlet would destroy existing resources in some circumstances, the cmdlet might detect that condition and prompt the user to verify before continuing. Overwriting an existing resource during resource creation, overwriting a file when downloading data, deleting a resource that is currently in use, or deleting a container that contains additional resources are all example of this pattern. To implement additional confirmation, and allow scripts to opt out of additional prompts, the above pattern is enhanced with calls to `ShouldContinue()` and the `-Force` parameter._ + +### `AsJob` + +All long running operations must implement the `-AsJob` parameter, which will allow the user to create jobs in the background. For more information about PowerShell jobs and the `-AsJob` parameter, read [this doc](https://docs.microsoft.com/en-us/powershell/azure/using-psjobs). + +To implement the `-AsJob` parameter, simply add the parameter to the end of the parameter list: + +````cs +[Parameter(Mandatory = false, HelpMessage = "Run cmdlet in the background")] +public SwitchParameter AsJob { get; set; } +```` + +Once you add the parameter, please manually test that the job is created and successfully completes when the parameter is specified. Additionally, please ensure that the help files are updated with this parameter. + +To ensure that `-AsJob` is not broken in future changes, please add a test for this parameter. To update tests to include this parameter, use the following pattern: + +````powershell +$job = Get-AzSubscription -AsJob +$job | Wait-Job +$subcriptions = $job | Receive-Job +```` + +To set a custom job name, please use [`SetBackgroupJobDescription`](https://github.com/Azure/azure-powershell-common/blob/master/src/Common/AzurePSCmdlet.cs#L810). The default job description is: "Long Running Operation for '{cmdlet name}' on resource '{resource name}'" + +### Required Parameter Sets + +In most Azure PowerShell cmdlets, there is a bare minimum of three parameter sets that need to be implemented. + +#### Interactive Parameter Set + +This parameter set should be implemented by _every_ cmdlet - in most cases, the user provides the name of the resource that they are acting upon (`-Name`) and the resource group in which they are acting in (`-ResourceGroupName`). + +The interactive parameter set **will always be the default parameter set** for a cmdlet (specified by the `DefaultParameterSetName` property in the `Cmdlet` attribute). This means that when PowerShell is unable to determine which parameter set a user is in, it will default to the interactive parameter set and prompt the user to provide values for the missing mandatory parameters. + +#### ResourceId Parameter Set + +This parameter set should be implemented by _every_ cmdlet - the user is able to provide a `-ResourceId` string or GUID from the Azure Portal, or from one of the generic resources cmdlets (more information about that below in the piping section), and act upon the given resource associated with the id. The typical `-Name` and `-ResourceGroupName` parameters are replaced by a single `-ResourceId` parameter of type string. + +#### InputObject Parameter Set + +This parameter should be implemented by _most_ cmdlets - the user is able to take the object returned from the `Get`, `New`, or `Set` cmdlets (or other cmdlets that return the common resource) and provide it to the `-InputObject` parameter for a cmdlet that acts upon the same resource. The typical `-Name` and `-ResourceGroupName` parameters are retrieved from the `-InputObject` that the user is passing through. \ No newline at end of file diff --git a/documentation/development-docs/design-guidelines/module-best-practices.md b/documentation/development-docs/design-guidelines/module-best-practices.md new file mode 100644 index 000000000000..e9fcd41eac1d --- /dev/null +++ b/documentation/development-docs/design-guidelines/module-best-practices.md @@ -0,0 +1,193 @@ +# Module Best Practices + +## Module Metadata + +### Module Naming + +Unless otherwise stated, the name of the module should be similar to that of provider called in the cmdlets. For example, if the cmdlets in a module called the `Microsoft.Compute` provider, then the module should be named `Az.Compute`. + +### Module Manifest + +The module manifest file, found in the format of `Az.MyService.psd1`, contains all necessary metadata information about a module, and can be initially generated using the `New-ModuleManifest` cmdlet. + +Below is sample `Az.MyService.psd1` file that can be used as a template for new `.psd1` files as well. Press the "Click to expand" text below to reveal the file: + +
Click to expand +

+ +``` +# +# Module manifest for module 'Az.MyService' +# +# Generated by: Microsoft Corporation +# +# Generated on: 3/11/2019 +# + +@{ + +# Script module or binary module file associated with this manifest. +# RootModule = '' + +# Version number of this module. +ModuleVersion = '0.1.0' + +# Supported PSEditions +CompatiblePSEditions = 'Core', 'Desktop' + +# ID used to uniquely identify this module +GUID = 'be0b7de9-01c3-4d05-adcf-848546dd70e7' + +# Author of this module +Author = 'Microsoft Corporation' + +# Company or vendor of this module +CompanyName = 'Microsoft Corporation' + +# Copyright statement for this module +Copyright = 'Microsoft Corporation. All rights reserved.' + +# Description of the functionality provided by this module +Description = '' + +# Minimum version of the PowerShell engine required by this module +PowerShellVersion = '5.1' + +# Name of the PowerShell host required by this module +# PowerShellHostName = '' + +# Minimum version of the PowerShell host required by this module +# PowerShellHostVersion = '' + +# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. +DotNetFrameworkVersion = '4.7.2' + +# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. +# CLRVersion = '' + +# Processor architecture (None, X86, Amd64) required by this module +# ProcessorArchitecture = '' + +# Modules that must be imported into the global environment prior to importing this module +RequiredModules = @(@{ModuleName = 'Az.Accounts'; ModuleVersion = '1.4.0'; }) + +# Assemblies that must be loaded prior to importing this module +RequiredAssemblies = '.\Microsoft.Azure.Management.MyService.dll' + +# Script files (.ps1) that are run in the caller's environment prior to importing this module. +# ScriptsToProcess = @() + +# Type files (.ps1xml) to be loaded when importing this module +# TypesToProcess = @() + +# Format files (.ps1xml) to be loaded when importing this module +FormatsToProcess = '.\MyService.format.ps1xml' + +# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess +NestedModules = '.\Microsoft.Azure.PowerShell.Cmdlets.MyService.dll' + +# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. +FunctionsToExport = @() + +# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. +CmdletsToExport = 'Get-AzMyServiceResource', 'New-AzMyServiceResource', + 'Remove-AzMyServiceResource', 'Update-AzMyServiceResource' + +# Variables to export from this module +# VariablesToExport = @() + +# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. +AliasesToExport = @() + +# DSC resources to export from this module +# DscResourcesToExport = @() + +# List of all modules packaged with this module +# ModuleList = @() + +# List of all files packaged with this module +# FileList = @() + +# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. +PrivateData = @{ + + PSData = @{ + + # Tags applied to this module. These help with module discovery in online galleries. + Tags = 'Azure','ResourceManager','ARM' + + # A URL to the license for this module. + LicenseUri = 'https://aka.ms/azps-license' + + # A URL to the main website for this project. + ProjectUri = 'https://github.com/Azure/azure-powershell' + + # A URL to an icon representing this module. + # IconUri = '' + + # ReleaseNotes of this module + ReleaseNotes = '' + + # Prerelease string of this module + # Prerelease = '' + + # Flag to indicate whether the module requires explicit user acceptance for install/update + # RequireLicenseAcceptance = $false + + # External dependent modules of this module + # ExternalModuleDependencies = @() + + } # End of PSData hashtable + + } # End of PrivateData hashtable + +# HelpInfo URI of this module +# HelpInfoURI = '' + +# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. +# DefaultCommandPrefix = '' + +} +``` + +

+
+ +Below is a table with some information about important fields of the module manifest file: + +| Field | Detail | +| -------------------- | ------ | +| `ModuleVersion` | This should not be touched unless otherwise specified to do so. Preview modules are noted by this version being `0.x.x`, or with the `preview` prefix specified in the `Prerelease` field at the bottom of the file. All other versions should signal that the module is stable. | +| `Description` | This should be updated to include information about the service, as well as a link to any corresponding service docs found on https://docs.microsoft.com. | +| `RequiredModules` | This should only contain a module dependency on the `Az.Accounts` module, unless otherwise noted. The version should be the latest version of `Az.Accounts` (found in the `Az.Accounts.psd1` file). | +| `RequiredAssemblies` | This should only contain assemblies that the module needs to run all of the cmdlets successfully. At a minimum, the service's SDK should be included in this list. Any other additional modules should be verified by the Azure PowerShell team. **No external service team SDK should be included in this field**. | +| `FormatsToProcess` | This should contain any formatting files that are used by the module to alter the display of cmdlets' output. | +| `NestedModules` | This should contain any assembly built with your project that contains cmdlet code. There is usually only one assembly found in this field unless the module contains multiple services. | +| `CmdletsToExport` | All cmdlets found in the module should be listed in this field. | +| `AliasesToExport` | All aliases found in the module should be listed in this field. | +| `Tags` | This should only include service-specific words or phrases to help users find the module in the PowerShell Gallery. **There should be no spaces in any of the tags added to this field; any tags with spaces will cause publishing to PowerShell Gallery to fail**. | +| `ReleaseNotes` | This should not be touched unless otherwise specified to do so. This field will be updated as a part of the release process for the module. | +| `Prerelease` | This should be set to `preview` if generating a preview version of a stable module. This will append a `-preview` string to the end of the module version. | + +## Module Dependencies + +### Common Assemblies + +Every module's `.csproj` file must import the [`Common.Netcore.Dependencies.targets`](../../../tools/Common.Netcore.Dependencies.targets) file to ensure that the correct version of each common assembly is referenced by the module. These assemblies are packaged with the `Az.Accounts` module and are loaded into a PowerShell session when `Az.Accounts` is imported (which is also done automatically when importing the service module). + +Some of the assemblies included in this `.targets` file: + +- `Microsoft.Azure.PowerShell.Clients.*` +- `Microsoft.Rest.ClientRuntime` +- `Microsoft.Rest.ClientRuntime.Azure` +- `Newtonsoft.Json` + +### SDK Assemblies + +A module should have a dependency on only its SDK and no other service's SDK; if a module takes a dependency on another service's SDK, this can introduce conflicting assembly versions between the version of the SDK referenced by the service team's module and the external service team's module, which will result in assembly loading issues for the user in PowerShell. + +If an external service's SDK is required by a module, the Azure PowerShell team must be consulted to resolve this issue. In most cases, the issue is resolved by grabbing a snapshot of the service's SDK and putting it in the [`azure-powershell-common`](https://github.com/Azure/azure-powershell-common) repository, which can then be referenced by any module. This allows the service team to continue shipping with their own SDK without worrying about external service teams from taking a dependency on the same SDK and introducing these potential assembly loading issues. + +### Other Assemblies + +All other assemblies referenced by a module should be verified by the Azure PowerShell team to ensure that they aren't introducing additional dependencies that will clash with packages already being shipped. \ No newline at end of file diff --git a/documentation/development-docs/design-guidelines/parameter-best-practices.md b/documentation/development-docs/design-guidelines/parameter-best-practices.md new file mode 100644 index 000000000000..e31033edead8 --- /dev/null +++ b/documentation/development-docs/design-guidelines/parameter-best-practices.md @@ -0,0 +1,157 @@ +# Parameter Best Practices + +## Parameter Guidelines + +### Parameter Naming Conventions + +The following are naming conventions to keep in mind when coming up with a name for your parameters. + +In addition, a recommended list of parameter names can be found [here](https://docs.microsoft.com/en-us/powershell/developer/cmdlet/standard-cmdlet-parameter-names-and-types). + +#### Standard Parameter Name + +From the [_Strongly Encouraged Development Guidelines_](https://docs.microsoft.com/en-us/powershell/developer/cmdlet/strongly-encouraged-development-guidelines#use-standard-parameter-names): + +> _Your cmdlet should use standard parameter names so that the user can quickly determine what a particular parameter means. If a more specific name is required, use a standard parameter name, and then specify a more specific name as an alias. For example, the `Get-Service` cmdlet has a parameter that has a generic name (**Name**) and a more specific alias (**ServiceName**). Both terms can be used to specify the parameter._ + +#### Pascal Case + +Similar to cmdlets, parameters should follow pascal casing.From the [_Strongly Encouraged Development Guidelines_](https://docs.microsoft.com/en-us/powershell/developer/cmdlet/strongly-encouraged-development-guidelines#use-pascal-case-for-parameter-names): + +> _Use Pascal case for parameter names. In other words, capitalize the first letter of each word in the parameter name, including the first letter of the name._ + +#### Singularity + +From the [_Strongly Encouraged Development Guidelines_](https://docs.microsoft.com/en-us/powershell/developer/cmdlet/strongly-encouraged-development-guidelines#use-singular-parameter-names): + +> _Avoid using plural names for parameters whose value is a single element. This includes parameters that take arrays or lists because the user might supply an array or list with only one element._ +> +> _Plural parameter names should be used only in those cases where the value of the parameter is always a multiple-element value. In these cases, the cmdlet should verify that multiple elements are supplied, and the cmdlet should display a warning to the user if multiple elements are not supplied._ + +#### Parameter Alias + +If you there is a separate nomenclature for the parameter name, or if you would like to shorten the name of the parameter so it's easier to remember, you can add an alias attribute to your parameter to allow for this functionality. + +### Parameter Types + +#### Valid Parameter Types + +The type of parameters should always be defined; a parameter should never be of type `object`, `PSObject`, `PSCustomObject` or the like. Defining a parameter with any of these types can make it difficult for the user to know what value they should be providing to the parameter, as well as makes it difficult for the breaking change analyzer to detect any breaking changes made to the parameter since it has no knowledge about changes in the types' properties. + +#### Consistent Parameter Types + +From the [_Strongly Encouraged Development Guidelines_](https://docs.microsoft.com/en-us/powershell/developer/cmdlet/strongly-encouraged-development-guidelines#use-consistent-parameter-types): + +> _When the same parameter is used by multiple cmdlets, always use the same parameter type. For example, if the **Process** parameter is an **Int16** type for one cmdlet, do not make the **Process** parameter for another cmdlet a **UInt16** type._ + +#### Array vs. Enumerable Types + +For parameters that require a collection of elements to be provided, use an array instead of any other enumerable type to represent this collection. + +From the [_Strongly Encouraged Development Guidelines_](https://docs.microsoft.com/en-us/powershell/developer/cmdlet/strongly-encouraged-development-guidelines#support-arrays-for-parameters): + +> _Frequently, users must perform the same operation against multiple arguments. For these users, a cmdlet should accept an array as parameter input so that a user can pass the arguments into the parameter as a Windows PowerShell variable. For example, the `Get-Process` cmdlet uses an array for the strings that identify the names of the processes to retrieve._ + +#### Secret Parameters + +For parameters that represent a value that should be kept secret in some fashion (such as a password, secret, key, etc.), the type of the parameter should be `SecureString` to avoid any sensitive information about the parameter from leaking during cmdlet execution. + +#### Bool vs. SwitchParameter + +Parameters of type `bool` are _strongly_ discouraged in PowerShell. The `SwitchParameter` type of a parameter acts a flag that signals whether or not some action should be taken based on if the parameter was provided or not. From the [_Strongly Encouraged Development Guidelines_](https://docs.microsoft.com/en-us/powershell/developer/cmdlet/strongly-encouraged-development-guidelines#parameters-that-take-true-and-false): + +> _If your parameter takes only true and false, define the parameter as type SwitchParameter. A switch parameter is treated as true when it is specified in a command. If the parameter is not included in a command, Windows PowerShell considers the value of the parameter to be false. Do not define Boolean parameters._ + +### Argument Completers + +PowerShell uses Argument Completers to provide tab completion for users. Azure PowerShell has multiple specific argument completers that should be applied to relevant parameters, as well as a generic argument completer that can be used to tab complete with a given list of values. + +#### Resource Group Completer + +For any parameter that takes a resource group name, the `ResourceGroupCompleter` should be applied as an attribute. This will allow the user to tab through all resource groups in the current subscription. + +```cs +using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; +... +[Parameter(Mandatory = false, HelpMessage = "The resource group name")] +[ResourceGroupCompleter] +public string ResourceGroupName { get; set; } +``` + +#### Resource Name Completer + +For any parameter that takes a resource name, the `ResourceNameCompleter` should be applied as an attribute. This will allow the user to tab through all resource names for the ResourceType in the current subscription. This completer will filter based upon the current parent resources provided (for instance, if ResourceGroupName is provided, only the resources in that particular resource group will be returned). For this completer, please provide the ResourceType as the first argument, followed by the parameter name for all parent resources starting at the top level. + +```cs +using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; +... +[Parameter(Mandatory = false, HelpMessage = "The parent server name")] +[ResourceNameCompleter("Microsoft.Sql/servers", nameof(ResourceGroupName))] +public string ServerName { get; set; } + +[Parameter(Mandatory = false, HelpMessage = "The database name")] +[ResourceNameCompleter("Microsoft.Sql/servers/databases", nameof(ResourceGroupName), nameof(ServerName))] +public string Name { get; set; } +``` + +#### Location Completer + +For any parameter that takes a location, the `LocationCompleter` should be applied as an attribute. In order to use the `LocationCompleter`, you must input as an argument all of the Providers/ResourceTypes used by the cmdlet. The user will then be able to tab through locations that are valid for all of the Providers/ResourceTypes specified. + +```cs +using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; +... +[Parameter(Mandatory = false, HelpMessage = "The location of the resource")] +[LocationCompleter("Microsoft.Batch/operations")] +public string Location { get; set; } +``` + +#### Generic Argument Completer + +For any parameter which you would like the user to tab through a list of suggested values (but you do not want to limit the users to only these values), the generic argument completer should be added. + +```cs +using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; +... +[Parameter(Mandatory = false, HelpMessage = "The tiers of the plan")] +[PSArgumentCompleter("Basic", "Premium", "Elite")] +public string Tier { get; set; } +``` + +## Parameter Set Guidelines + +### Parameter Set Naming Conventions + +The following are naming conventions to keep in mind when coming up with a name for your parameter set. + +#### Pascal Case + +Similar to parameters (mentioned above), parameter set names should follow pascal casing. From the [_Strongly Encouraged Development Guidelines_](https://docs.microsoft.com/en-us/powershell/developer/cmdlet/strongly-encouraged-development-guidelines#use-pascal-case-for-cmdlet-names-sd02): + +> _Use Pascal case for cmdlet names. In other words, capitalize the first letter of the verb and all terms used in the noun. For example, "Clear-ItemProperty"._ + +### Attribute Guidelines + +The following are guidelines that should be followed when working with the attributes of a parameter set. + +#### Mutually Exclusive Parameter Sets + +For PowerShell to determine which parameter set a user is intending to use with a set of provided parameters, the parameter sets need to be designed in such a way that they are mutually exclusive. From the remarks section of [_Parameter Attribute Declaration_](https://docs.microsoft.com/en-us/powershell/developer/cmdlet/parameter-attribute-declaration#remarks): + +> _Each parameter set must have at least one unique parameter. Good cmdlet design indicates this unique parameter should also be mandatory if possible. If your cmdlet is designed to be run without parameters, the unique parameter cannot be mandatory._ + +#### Positional Parameters Limit + +It is possibile to call a PowerShell cmdlet without providing the parameter names, but just the values you would like to pass through. This is done by specifying the position at which the value of each parameter should be provided by using the `Position` property for a parameter. However, when there are too many positional parameters in a single parameter set, it can be difficult for the user to remember the exact ordering in which the parameter values should be provided. From the remarks section of [_Parameter Attribute Declaration_](https://docs.microsoft.com/en-us/powershell/developer/cmdlet/parameter-attribute-declaration#remarks): + +> _When you specify positional parameters, limit the number of positional parameters in a parameter set to less than five. And, positional parameters do not have to be contiguous. Positions 5, 100, and 250 work the same as positions 0, 1, and 2._ + +In addition, there should be no two parameters with the same position in the same parameter set. From the remarks section of [_Parameter Attribute Declaration_](https://docs.microsoft.com/en-us/powershell/developer/cmdlet/parameter-attribute-declaration#remarks): + +> _No parameter set should contain more than one positional parameter with the same position._ + +#### ValueFromPipeline Limit + +Allowing the user to pipe an object from one cmdlet to another is a major scenario in PowerShell, but allowing multiple parameters in the same parameter set to accept their value from the pipeline can cause issues. From the remarks section of [_Parameter Attribute Declaration_](https://docs.microsoft.com/en-us/powershell/developer/cmdlet/parameter-attribute-declaration#remarks): + +> _Only one parameter in a parameter set should declare ValueFromPipeline = true. Multiple parameters can define ValueFromPipelineByPropertyName = true._ \ No newline at end of file diff --git a/documentation/development-docs/piping-in-powershell.md b/documentation/development-docs/design-guidelines/piping-best-practices.md similarity index 58% rename from documentation/development-docs/piping-in-powershell.md rename to documentation/development-docs/design-guidelines/piping-best-practices.md index d1a1ab8a6fe5..523992dc5504 100644 --- a/documentation/development-docs/piping-in-powershell.md +++ b/documentation/development-docs/design-guidelines/piping-best-practices.md @@ -1,143 +1,8 @@ -# Azure PowerShell Piping Scenarios - -There are two main scenarios that we wish to enable in cmdlets for Azure PowerShell: -- piping by value using an `InputObject` parameter -- piping by property name using a `ResourceId` parameter - -## Using the `InputObject` parameter - -### Short explanation -For all resources, `InputObject` should be implemented for the Remove/Set/Update cmdlets (and any other cmdlet where an existing resource is being operated on). The implementation of this will be a new parameter set: - -```powershell -Remove/Set/Update-Az -InputObject -``` - -For all child resources, `InputObject` should also be implemented for the Get/New cmdlets. The implementation of this will be a new parameter set: - -```powershell -Get/New-Az -ParentObject -``` - -### Long explanation -This scenario should be used when piping objects around within the same module. For example, if you have a set of `Get-AzFoo`, `Remove-AzFoo`, and `Set-AzFoo` cmdlets, the `Remove-AzFoo` and `Set-AzFoo` cmdlets should have a parameter set that takes the `InputObject` parameter of type `PSFoo` so that a user can do the following: - -```powershell -# --- Piping scenario --- -# Setting and removing an individual object -Get-AzFoo -Name "FooName" -ResourceGroupName "RG" | Set-AzFoo -Get-AzFoo -Name "FooName" -ResourceGroupName "RG" | Remove-AzFoo - -# Setting and removing a collection of objects -Get-AzFoo | Set-AzFoo -Get-AzFoo | Remove-AzFoo +# Piping Best Practices +## Piping in PowerShell -# --- Non-piping scenario --- -# Setting and removing an individual object -$foo = Get-AzFoo -Name "FooName" -ResourceGroupName "RG" -Set-AzFoo -InputObject $foo -Remove-AzFoo -InputObject $foo - -# Setting and removing a collection of objects -Get-AzFoo | ForEach-Object { Set-AzFoo -InputObject $_ } -Get-AzFoo | ForEach-Object { Remove-AzFoo -InputObject $_ } -``` - -Another time that this scenario applies is when you have cmdlets for child resources that need information about the parent (top-level) resource. For example you can pipe in the whole parent object to the `New-AzFooBar` and `Get-AzFooBar` cmdlets to get the child resources, and then pipe the child resource object to the `Remove-AzFooBar` and `Set-AzFooBar` cmdlets. - -```powershell -# --- Piping scenario --- -# Getting all of child resources from all of the parent resources and removing them -Get-AzFoo | Get-AzFooBar | Remove-AzFooBar - -# Getting all of the child resources from all of the parent resources in a resource group and removing them -Get-AzFoo -ResourceGroupName "RG" | Get-AzFooBar | Remove-AzFooBar - -# Getting all of the child resources from a specific parent resource and removing them -Get-AzFoo -ResourceGroupName "RG" -Name "FooName" | Get-AzFooBar | Remove-AzFooBar - - -# --- Non-piping scenario --- -# Getting all of the child resources from a specific parent resource and removing them -$foo = Get-AzFoo -ResourceGroupName "RG" -Name "FooName" -$fooBar = Get-AzFooBar -InputObject $foo -Remove-AzFooBar -InputObject $fooBar -``` - -## Using the `ResourceId` parameter - -### Short explanation -For all resources, `ResourceId` should be implemented for the Remove/Set/Update cmdlets (and any other cmdlet where an existing resource is being operated on). The implementation of this will be a new parameter set: - -```powershell -Remove/Set/Update-Az -ResourceId -``` - -For all child resources, `ResourceId` should also be implemented for the Get/New cmdlets. The implementation of this will be a new parameter set: - -```powershell -Get/New-Az -ParentResourceId -``` - -### Long explanation - -In this scenario, we are using the generic cmdlets found in the `Az.Resources` module. These cmdlets, `Find-AzResource` and `Get-AzResource`, return a `PSCustomObject` that has a `ResourceId` property, which is the unique identifier for the given resource. Since this identifier can parsed to get the name and resource group name for a top-level resource, we can create a parameter set that has a `ResourceId` parameter that accepts its value from the pipeline by property name, allowing us to accept piping from these generic cmdlets. - -```powershell -# --- Piping scenario --- -# Remove all Foo objects in the current subscription -Find-AzResource -ResourceType Microsoft.Foo/foo | Remove-AzFoo - -# Remove all Foo objects in a given resource group -Find-AzResource -ResourceType Microsoft.Foo/foo -ResourceGroupEquals "RG" | Remove-AzFoo - -# Remove a specific Foo object -Find-AzResource -ResourceGroupEquals "RG" -ResourceNameEquals "FooName" | Remove-AzFoo - - -# -- Non-piping scenario --- -# Removing all Foo objects in the current subscription -Find-AzResource -ResourceType Microsoft.Foo/foo | ForEach-Object { Remove-AzFoo -ResourceId $_.ResourceId } - -# Remove all Foo objects in a given resource group -Find-AzResource -ResourceType Microsoft.Foo/foo -ResourceGroupEquals "RG" | ForEach-Object { Remove-AzFoo -ResourceId $_.ResourceId } - -# Remove a specific Foo object -Find-AzResource -ResourceGroupEquals "RG" -ResourceNameEquals "FooName" | ForEach-Object { Remove-AzFoo -ResourceId $_.ResourceId } -``` - -To implement this scenario, please see the [`ResourceIdentifier`](https://github.com/Azure/azure-powershell-common/blob/master/src/ResourceManager/Version2016_09_01/Utilities/Models/ResourceIdentifier.cs) class in the `ResourceManager` project. This class will allow you to create a `ResourceIdentifier` object that accepts a `ResourceId` string in its constructor and has properties `ResourceName`, `ResourceGroupName`, and others. - -## Summary -For all Remove/Set/Update cmdlets (and any other cmdlet where an existing resource is being operated on), you will have three parameter sets (and potentially a multiple of three if you have initially have multiple parameter sets): -```powershell -Remove/Set/Update-Az -Remove/Set/Update-Az -InputObject -Remove/Set/Update-Az -ResourceId -``` -For example, for child resource "Widget" with parent "Foo", there will be these three parameter sets for Remove: -```powershell -Remove-AzWidget -ResourceGroupName -FooName -Name -Remove-AzWidget -InputObject -Remove-AzWidget -ResourceId -``` -For all child resources, Get/New cmdlets will also have these three parameter sets: -```powershell -Get/New-Az -Get-Az -InputObject -Get/New-Az -ResourceId -``` -For example, for child resource "Widget" with parent "Foo", there will be these three parameter sets for New: -```powershell -New-AzWidget -ResourceGroupName -FooName -Name -New-AzWidget -WidgetObject -Name -New-AzWidget -WidgetResourceId -Name -``` - -# Piping in PowerShell (additional information) - -## Understanding Piping +### Understanding Piping In PowerShell, cmdlets pipe objects between one another; cmdlets should return objects, not text (strings). @@ -151,7 +16,7 @@ The cmdlet `Get-AzEnvironment` will return a set of `Environment` objects, and t When an object is being piped to a cmdlet, PowerShell will first check to see if it can bind that object to a parameter with the same type and has the property `ValueFromPipeline = true`. If this cannot be done, PowerShell will then see if it can bind the properties of the object with parameters that share the same name and have the property `ValueFromPipelineByPropertyName = true`. -### ValueFromPipeline +#### `ValueFromPipeline` property In this scenario, the object piped to the cmdlet will be bound to a parameter with the same type that has the property `ValueFromPipeline = true`. @@ -182,9 +47,9 @@ Remove-AzFoo -InputObject $foo Get-AzFoo | ForEach-Object { Remove-AzFoo -InputObject $_ } ``` -The `PSFoo` object(s) that is returned by the `Get-AzFoo` call will be piped to the `Remove-AzFoo` cmdlet, and becuase that cmdlet has a parameter that accepts a `PSFoo` object by value, PowerShell will bind the object being sent through the pipeline to this `InputObject` parameter. +The `PSFoo` object(s) that is returned by the `Get-AzFoo` call will be piped to the `Remove-AzFoo` cmdlet, and becuase that cmdlet has a parameter that accepts a `PSFoo` object by value, PowerShell will bind the object being sent through the pipeline to this `-InputObject` parameter. -### ValueFromPipelineByPropertyName +#### `ValueFromPipelineByPropertyName` property In this scenario, the properties of the object being piped to the cmdlet will be bound to parameters with the same name that have the property `ValueFromPipelineByPropertyName = true`. @@ -217,7 +82,7 @@ Get-AzFoo | ForEach-Object { Remove-AzFoo -ResourceId } The `PSFoo` object(s) that is returned by the `Get-AzFoo` call will be piped to the `Remove-AzFoo` cmdlet, and because that cmdlet has parameters that accept their value from the pipeline by property name, PowerShell will check each of these parameters and see if it can find a corresponding property in the `PSFoo` object that it shares a name with, and bind the value. -### Writing to the Pipeline +#### Writing to the Pipeline To write to the pipeline, use the `WriteObject` method from the `AzurePSCmdlet` class in the `Commands.Common` project. If you are writing **only one** object to the pipeline, then you should use the overload `WriteObject(object sendToPipeline)`, but if you are writing **more than one** objects to the pipeline, you should use the overload `WriteObject(object sendToPipeline, bool enumerateCollection)`. @@ -241,6 +106,142 @@ public override void ExecuteCmdlet() } ``` -## More Information +### More Information + +For more information on piping, see the article [_Understanding pipelines_](https://docs.microsoft.com/en-us/powershell/scripting/learn/understanding-the-powershell-pipeline). + +## Piping in Azure PowerShell + +There are two main scenarios that we wish to enable in cmdlets for Azure PowerShell: +- piping by value using an `-InputObject` parameter +- piping by property name using a `-ResourceId` parameter + +### Using the `-InputObject` Parameter + +#### Short explanation +For all resources, `-InputObject` should be implemented for at least the `Remove-*`, `Set-*` and `Update-*` cmdlets (and any other cmdlet where an existing resource is being operated on, such as `Start-*`, `Stop-*`, etc.). The implementation of this will be a new parameter set, like the following: + +``` +Remove-AzSampleResource -InputObject [...] [-PassThru] [-WhatIf] [-Confirm] +``` + +For all child resources, the same functionality should be added for the cmdlets above, but for `Get-*` and `New-*` cmdlets, rather than using the `-InputObject` parameter, a separate object parameter should be added to allow piping the object representation of the parent resource. The implementation of this will be a new parameter set, like the following: + +``` +Get-AzChildResource -TopLevelResourceObject [...] +``` + +#### Long explanation +This scenario should be used when piping objects around within the same module. For example, if you have a set of `Get-AzFoo`, `Remove-AzFoo`, and `Set-AzFoo` cmdlets, the `Remove-AzFoo` and `Set-AzFoo` cmdlets should have a parameter set that takes the `-InputObject` parameter of type `PSFoo` so that a user can do the following: + +```powershell +# --- Piping scenario --- +# Setting and removing an individual object +Get-AzFoo -Name "FooName" -ResourceGroupName "RG" | Set-AzFoo @additionalParams +Get-AzFoo -Name "FooName" -ResourceGroupName "RG" | Remove-AzFoo + +# Setting and removing a collection of objects +Get-AzFoo | Set-AzFoo @additionalParams +Get-AzFoo | Remove-AzFoo + + +# --- Non-piping scenario --- +# Setting and removing an individual object +$foo = Get-AzFoo -Name "FooName" -ResourceGroupName "RG" +Set-AzFoo -InputObject $foo @additionalParams +Remove-AzFoo -InputObject $foo + +# Setting and removing a collection of objects +Get-AzFoo | ForEach-Object { Set-AzFoo -InputObject $_ @additionalParams } +Get-AzFoo | ForEach-Object { Remove-AzFoo -InputObject $_ } +``` + +Another time that this scenario applies is when you have cmdlets for child resources that need information about the parent (top-level) resource. For example you can pipe in the whole parent object to the `New-AzFooBar` and `Get-AzFooBar` cmdlets to get the child resources, and then pipe the child resource object to the `Remove-AzFooBar` and `Set-AzFooBar` cmdlets. + +```powershell +# --- Piping scenario --- +# Getting all of child resources from all of the parent resources and removing them +Get-AzFoo | Get-AzFooBar | Remove-AzFooBar + +# Getting all of the child resources from all of the parent resources in a resource group and removing them +Get-AzFoo -ResourceGroupName "RG" | Get-AzFooBar | Remove-AzFooBar + +# Getting all of the child resources from a specific parent resource and removing them +Get-AzFoo -ResourceGroupName "RG" -Name "FooName" | Get-AzFooBar | Remove-AzFooBar + + +# --- Non-piping scenario --- +# Getting all of the child resources from a specific parent resource and removing them +$foo = Get-AzFoo -ResourceGroupName "RG" -Name "FooName" +$fooBar = Get-AzFooBar -InputObject $foo +Remove-AzFooBar -InputObject $fooBar +``` + +### Using the `-ResourceId` Parameter + +#### Short explanation +For all resources, `-ResourceId` should be implemented for the `Remove-*`, `Set-*` and `Update-*` cmdlets (and any other cmdlet where an existing resource is being operated on, such as `Start-*`, `Stop-*`, etc.). The implementation of this will be a new parameter set, like the following: + +``` +RemoveAzSampleResource -ResourceId [...] [-PassThru] [-WhatIf] [-Confirm] +``` + +#### Long explanation + +In this scenario, we are using the generic cmdlets found in the `Az.Resources` module. These cmdlets, `Find-AzResource` and `Get-AzResource`, return a `PSCustomObject` that has a `ResourceId` property, which is the unique identifier for the given resource. Since this identifier can parsed to get the name and resource group name for a top-level resource, we can create a parameter set that has a `ResourceId` parameter that accepts its value from the pipeline by property name, allowing us to accept piping from these generic cmdlets. + +```powershell +# --- Piping scenario --- +# Remove all Foo objects in the current subscription +Get-AzResource -ResourceType Microsoft.Foo/foo | Remove-AzFoo + +# Remove all Foo objects in a given resource group +Get-AzResource -ResourceType Microsoft.Foo/foo -ResourceGroupEquals "RG" | Remove-AzFoo + +# Remove a specific Foo object +Get-AzResource -ResourceGroupEquals "RG" -ResourceNameEquals "FooName" | Remove-AzFoo + + +# -- Non-piping scenario --- +# Removing all Foo objects in the current subscription +Get-AzResource -ResourceType Microsoft.Foo/foo | ForEach-Object { Remove-AzFoo -ResourceId $_.ResourceId } + +# Remove all Foo objects in a given resource group +Get-AzResource -ResourceType Microsoft.Foo/foo -ResourceGroupEquals "RG" | ForEach-Object { Remove-AzFoo -ResourceId $_.ResourceId } + +# Remove a specific Foo object +Get-AzResource -ResourceGroupEquals "RG" -ResourceNameEquals "FooName" | ForEach-Object { Remove-AzFoo -ResourceId $_.ResourceId } +``` + +To implement this scenario, please see the [`ResourceIdentifier`](https://github.com/Azure/azure-powershell-common/blob/52fc157798d0fdd83f20755106e131aec1689ceb/src/ResourceManager/Version2016_09_01/Utilities/Models/ResourceIdentifier.cs) class in the `ResourceManager` project. This class will allow you to create a `ResourceIdentifier` object that accepts a `ResourceId` string in its constructor and has properties `ResourceName`, `ResourceGroupName`, and others. + +### Summary +For all `Remove-*`, `Set-*` and `Update-*` cmdlets (and any other cmdlet where an existing resource is being operated on, such as `Start-*`, `Stop-*`, etc.), you will have three parameter sets (and potentially a multiple of three if you have initially have multiple parameter sets): + +``` +Remove-AzSampleResource -ResourceGroupName -Name [...] [-PassThru] [-WhatIf] [-Confirm] + +Remove-AzSampleResource -InputObject [...] [-PassThru] [-WhatIf] [-Confirm] + +Remove-AzSampleResource -ResourceId [...] [-PassThru] [-WhatIf] [-Confirm] +``` + +For child resources, there will be the following three parameter sets for `Remove-*`: + +``` +Remove-AzChildResource -ResourceGroupName -TopLevelResourceName -Name [...] [-PassThru] [-WhatIf] [-Confirm] + +Remove-AzChildResource -InputObject [...] [-PassThru] [-WhatIf] [-Confirm] + +Remove-AzChildResource -ResourceId [...] [-PassThru] [-WhatIf] [-Confirm] +``` + +For all child resources, `Get-*` cmdlets will also the following three parameter sets: + +``` +Get-AzChildResource -ResourceGroupName -TopLevelResourceName [-Name ] [...] + +Get-AzChildResource -TopLevelResourceObject [...] -For more information on piping, see the article ["Understanding the Windows PowerShell Pipeline"](https://msdn.microsoft.com/en-us/powershell/scripting/getting-started/fundamental/understanding-the-windows-powershell-pipeline). +Get-AzChildResource -ResourceId [...] +``` \ No newline at end of file diff --git a/documentation/development-docs/should-process-confirm-impact.md b/documentation/development-docs/design-guidelines/should-process-confirm-impact.md similarity index 71% rename from documentation/development-docs/should-process-confirm-impact.md rename to documentation/development-docs/design-guidelines/should-process-confirm-impact.md index 0dc123fb61d4..9b169b60eb45 100644 --- a/documentation/development-docs/should-process-confirm-impact.md +++ b/documentation/development-docs/design-guidelines/should-process-confirm-impact.md @@ -1,10 +1,12 @@ ## ShouldProcess -From [Cmdlet Attribute Declaration](https://msdn.microsoft.com/en-us/library/system.management.automation.cmdletcommonmetadataattribute.supportsshouldprocess(v=vs.85).aspx): +From [_Cmdlet Attribute Declaration_](https://docs.microsoft.com/en-us/powershell/developer/cmdlet/cmdlet-attribute-declaration): -> _All commands that change the system should include the **SupportsShouldProcess** keyword when declaring the attribute. If the ShouldProcess method returns true, the command should perform its action. If the ShouldProcess method returns false, the action should not be taken._ -> -> _If a command supports the ShouldProcess method, the **Confirm** and **WhatIf** parameters are added to the command by the Windows PowerShell runtime._ +> _All cmdlets that change resources outside of PowerShell should include the `SupportsShouldProcess` keyword when the `Cmdlet` attribute is declared, which allows the cmdlet to call the `ShouldProcess` method before the cmdlet performs its action. If the `ShouldProcess` call returns false, the action should not be taken._ +> +> _The `-Confirm` and `-WhatIf` cmdlet parameters are available only for cmdlets that support `ShouldProcess` calls._ + +Below is an example of the declaration of this property in the `Cmdlet` attribute and the subsequent call to `ShouldProcess` in the body of the cmdlet: ```cs [Cmdlet(VerbsCommon.Remove, "Foo", SupportsShouldProcess = true)] @@ -89,18 +91,18 @@ void ConfirmAction(bool force, string continueMessage, string processMessage, st ## ConfirmImpact -From [Cmdlet Attribute Declaration](https://msdn.microsoft.com/en-us/library/system.management.automation.confirmimpact(v=vs.85).aspx): +From [_Cmdlet Attribute Declaration_](https://docs.microsoft.com/en-us/powershell/developer/cmdlet/cmdlet-attribute-declaration): -> _Defines the impact level of the action performed by the cmdlet. For example, cmdlets may have a high, medium, or low risk of losing data._ +> _Specifies when the action of the cmdlet should be confirmed by a call to the `ShouldProcess` method. `ShouldProcess` will only be called when the `ConfirmImpact` value of the cmdlet (by default, Medium) is equal to or greater than the value of the `$ConfirmPreference` variable. This parameter should be specified only when the `SupportsShouldProcess` parameter is specified._ -Below are the possible `ConfirmImpact` values +Below are the possible `ConfirmImpact` values: -| Member name | Description | -|----------------------|----------------------------------------------------------------------------------------------------------------| -| High | This action is potentially highly "destructive" and should be confirmed by default unless otherwise specified. | -| Low | This action only needs to be confirmed when the user has requested the low-impact changes must be confirmed. | -| Medium | This action should be confirmed in most scenarios where confirmation is requested. | -| None | There is never any need to confirm this action. | +| Member name | Description | +|-------------|----------------------------------------------------------------------------------------------------------------| +| High | This action is potentially highly "destructive" and should be confirmed by default unless otherwise specified. | +| Low | This action only needs to be confirmed when the user has requested the low-impact changes must be confirmed. | +| Medium | This action should be confirmed in most scenarios where confirmation is requested. | +| None | There is never any need to confirm this action. | ```cs [Cmdlet(VerbsCommon.Remove, "Foo", SupportsShouldProcess = true, ConfirmImpact = ConfirmImpact.Medium)] diff --git a/documentation/development-docs/examples/README.md b/documentation/development-docs/examples/README.md new file mode 100644 index 000000000000..f38b8f8889b2 --- /dev/null +++ b/documentation/development-docs/examples/README.md @@ -0,0 +1,21 @@ +## Examples of standard Azure PowerShell cmdlets + +In this folder, you will find patterns and examples for standard Azure PowerShell cmdlets that should be implemented for a service. Both top-level and child resource scenarios are covered in each of the documents. + +### Table of contents + +- [`Get-*` cmdlet](.\get-cmdlet-example.md) + - [Top-level resource](.\get-cmdlet-example.md#top-level-resource) + - [Child resource](.\get-cmdlet-example.md#child-resource) +- [`New-*` cmdlet](.\new-cmdlet-example.md) + - [Top-level resource](.\new-cmdlet-example.md#top-level-resource) + - [Child resource](.\new-cmdlet-example.md#child-resource) +- [`Remove-*` cmdlet](.\remove-cmdlet-example.md) + - [Top-level resource](.\remove-cmdlet-example.md#top-level-resource) + - [Child resource](.\remove-cmdlet-example.md#child-resource) +- [`Set-*` cmdlet](.\set-cmdlet-example.md) + - [Top-level resource](.\set-cmdlet-example.md#top-level-resource) + - [Child resource](.\set-cmdlet-example.md#child-resource) +- [`Update-*` cmdlet](.\update-cmdlet-example.md) + - [Top-level resource](.\update-cmdlet-example.md#top-level-resource) + - [Child resource](.\update-cmdlet-example.md#child-resource) \ No newline at end of file diff --git a/documentation/development-docs/examples/get-cmdlet-example.md b/documentation/development-docs/examples/get-cmdlet-example.md new file mode 100644 index 000000000000..5ed9ea5a3870 --- /dev/null +++ b/documentation/development-docs/examples/get-cmdlet-example.md @@ -0,0 +1,157 @@ +## `Get-*` cmdlet example + +### Top-level resource + +All top-level resources should have a `Get-*` cmdlet that allows users to list the resources in their subscription or a resource group, as well as get a specific resource. In addition, users should be able to provide the resource id of the resource they want to get, and the cmdlet will parse the string to get the necessary identity information. + +#### Parameter sets + +To enable the scenarios mentioned previously, the cmdlet will need three parameter sets: + +``` +Get-AzTopLevelResource [-ResourceGroupName ] + +Get-AzTopLevelResource -ResourceGroupName -Name + +Get-AzTopLevelResource -ResourceId +``` + +The first parameter set has an optional `-ResourceGroupName` parameter, which allows the user to list all resources in a subscription or in a resource group. The second parameter set has required `-ResourceGroupName` and `-Name` parameters, which allows the user to get a specific resource. The third parameter set has a required `-ResourceId` parameter, which allows the user to get a specific resource by resource id. + +#### C# example + +```cs +namespace Microsoft.Azure.Commands.Service +{ + [Cmdlet(VerbsCommon.Get, "AzTopLevelResource", DefaultParameterSetName = ListParameterSet), OutputType(typeof(PSTopLevelResource))] + public class GetTopLevelResourceCommand : ServiceBaseCmdlet + { + private const string ListParameterSet = "ListParameterSet"; + private const string GetByNameParameterSet = "GetByNameParameterSet";" + private const string GetByResourceIdParameterSet = "GetByResourceIdParameterSet"; + + [Parameter(Mandatory = false, ParameterSetName = ListParameterSet)] + [Parameter(Mandatory = true, ParameterSetName = GetByNameParameterSet)] + [ResourceGroupCompleter] + [ValidateNotNullOrEmpty] + public string ResourceGroupName { get; set; } + + [Parameter(Mandatory = true, ParameterSetName = GetByNameParameterSet)] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, ParameterSetName = GetByResourceIdParameterSet )] + [ValidateNotNullOrEmpty] + public string ResourceId { get; set; } + + public override void ExecuteCmdlet() + { + if (this.IsParameterBound(c => c.ResourceId)) + { + var resourceIdentifier = new ResourceIdentifier(this.ResourceId); + this.ResourceGroupName = resourceIdentifier.ResourceGroupName; + this.Name = resourceIdentifier.ResourceName; + } + + if (!string.IsNullOrEmpty(this.Name)) + { + var result = new PSTopLevelResource(this.MySDKClient.TopLevelResource.Get(this.ResourceGroupName, this.Name)); + WriteObject(result); + } + else if (!string.IsNullOrEmpty(this.ResourceGroupName)) + { + var result = this.MySDKClient.TopLevelResource.ListByResourceGroup(this.ResourceGroupName).Select(r => new PSTopLevelResource(r)); + WriteObject(result, true); + } + else + { + var result = this.MySDKClient.TopLevelResource.List().Select(r => new PSTopLevelResource(r)); + WriteObject(result, true); + } + } + } +} +``` + +### Child resource + +All child resources should have a `Get-*` cmdlet that allows users to list the child resources under a parent resource, as well as get a specific resource. In addition, users should be able to provide the resource id of the resource they want to get, and the cmdlet will parse the string to get the necessary identity information. + +#### Parameter sets + +To enable the scenarios mentioned previously, the cmdlet will need three parameter sets: + +``` +Get-AzChildResource -ResourceGroupName -TopLevelResourceName [-Name ] + +Get-AzChildResource -TopLevelResourceObject [-Name ] + +Get-AzChildResource -ResourceId +``` + +The first parameter set has mandatory `-ResourceGroupName` and `-TopLevelResourceName` parameters to get the identity information about the parent resource, and then an optional `-Name` parameter to allow the user to either list all child resources contained in the given parent or get the specific child resource. The second parameter set has required `-TopLevelResourceObject` parameter, which can be piped from the parent `Get-*` or `Set/Update-*` cmdlet, and an optional `-Name` parameter. The third parameter set has a required `-ResourceId` parameter, which allows the user to get a specific child resource by resource id. + +#### C# example + +```cs +namespace Microsoft.Azure.Commands.Service +{ + [Cmdlet(VerbsCommon.Get, "AzChildResource", DefaultParameterSetName = GetByNameParameterSet), OutputType(typeof(PSChildResource))] + public class GetChildResourceCommand : ServiceBaseCmdlet + { + private const string GetByNameParameterSet = "GetByNameParameterSet"; + private const string GetByParentObjectParameterSet = "GetByParentObjectParameterSet"; + private const string GetByResourceIdParameterSet = "GetByResourceIdParameterSet"; + + [Parameter(Mandatory = true, ParameterSetName = GetByNameParameterSet)] + [ResourceGroupCompleter] + [ValidateNotNullOrEmpty] + public string ResourceGroupName { get; set; } + + [Parameter(Mandatory = true, ParameterSetName = GetByNameParameterSet)] + [ValidateNotNullOrEmpty] + public string TopLevelResourceName { get; set; } + + [Parameter(Mandatory = false, ParameterSetName = GetByNameParameterSet)] + [Parameter(Mandatory = false, ParameterSetName = GetByParentObjectParameterSet)] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter(Mandatory = true, ValueFromPipeline = true, ParameterSetName = GetByParentObjectParameterSet)] + [ValidateNotNull] + public PSTopLevelResource TopLevelResourceObject { get; set; } + + [Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, ParameterSetName = GetByResourceIdParameterSet)] + [ValidateNotNullOrEmpty] + public string ResourceId { get; set; } + + public override void ExecuteCmdlet() + { + if (this.IsParameterBound(c => c.ResourceId)) + { + var resourceIdentifier = new ResourceIdentifier(this.ResourceId); + this.ResourceGroupName = resourceIdentifier.ResourceGroupName; + this.TopLevelResourceName = resourceIdentifier.ParentResource + this.Name = resourceIdentifier.ResourceName; + } + + if (this.IsParameterBound(c => c.TopLevelResourceObject)) + { + this.ResourceGroupName = this.TopLevelResourceObject.ResourceGroupName; + this.TopLevelResourceName = this.TopLevelResourceObject.Name; + } + + if (!string.IsNullOrEmpty(this.Name)) + { + var result = new PSChildResource(this.MySDKClient.ChildResource.Get(this.ResourceGroupName, this.TopLevelResourceName, this.Name)); + WriteObject(result); + } + else + { + var result = this.MySDKClient.ChildResource.List(this.ResourceGroupName, this.TopLevelResourceName).Select(r => new PSChildResource(r)); + WriteObject(result, true); + } + } + } +} +``` \ No newline at end of file diff --git a/documentation/development-docs/examples/new-cmdlet-example.md b/documentation/development-docs/examples/new-cmdlet-example.md new file mode 100644 index 000000000000..8a241b3f0e98 --- /dev/null +++ b/documentation/development-docs/examples/new-cmdlet-example.md @@ -0,0 +1,178 @@ +## `New-*` cmdlet example + +### Top-level resource + +All top-level resources should have a `New-*` cmdlet that allows users to create a resource with given properties. Properties that are required by the API should be mandatory parameters, and in the case where different combinations of properties are needed depending on a provided value (_e.g._, Windows and Linux VMs have different properties), multiple parameter sets should be used. This cmdlet should implement `SupportsShouldProcess` to allow users to provide the `-WhatIf` parameter and see what the result of executing the cmdlet is without the resource actually being created. + +_Note_: for long-running operations (~15s or longer), it is advised to add the [`-AsJob`](../design-guidelines/cmdlet-best-practices.md#asjob) to your cmdlet. + + +#### Parameter sets + +To enable the above scenario, only one parameter set is needed: + +``` +New-AzTopLevelResource -ResourceGroupName -Name [-Property1 ] [-Property2 ] ... [-WhatIf] [-Confirm] +``` + +This parameter set has required `-ResourceGroupName` and `-Name` parameters to satisfy the identity properties of the resource, as well as a few optional `-PropertyX` parameters that allows the user to set values for properties. The parameter set also has optional `-WhatIf` and `-Confirm` parameters that are automatically included from the implementation of `SupportsShouldProcess`. + +#### C# example + +```cs +namespace Microsoft.Azure.Commands.Service +{ + [Cmdlet(VerbsCommon.New, "AzTopLevelResource", DefaultParameterSetName = CreateParameterSet, SupportsShouldProcess = true), OutputType(typeof(PSTopLevelResource))] + public class NewTopLevelResourceCommand : ServiceBaseCmdlet + { + private const string CreateParameterSet = "CreateParameterSet"; + + [Parameter(Mandatory = true, ParameterSetName = CreateParameterSet)] + [ResourceGroupCompleter] + [ValidateNotNullOrEmpty] + public string ResourceGroupName { get; set; } + + [Parameter(Mandatory = true, ParameterSetName = CreateParameterSet)] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter(Mandatory = false, ParameterSetName = CreateParameterSet)] + public Type1 Property1 { get; set; } + + [Parameter(Mandatory = false, ParameterSetName = CreateParameterSet)] + public Type2 Property2 { get; set; } + + // Excluding other property parameters + + public override void ExecuteCmdlet() + { + TopLevelResource existingResource = null; + try + { + existingResource = this.MySDKClient.TopLevelResource.Get(this.ResourceGroupName, this.Name); + } + catch + { + existingResource = null; + } + + if (existingResource != null) + { + throw new Exception(string.Format("A TopLevelResource with name '{0}' in resource group '{1}' already exists. Please use Set/Update-AzTopLevelResource to update an existing TopLevelResource.", this.Name, this.ResourceGroupName)); + } + + existingResource = new TopLevelResource() + { + Name = this.Name, + ResourceGroupName = this.ResourceGroupName, + Property1 = this.Property1, + Property2 = this.Property2, + ... + } + + if (this.ShouldProcess(this.Name, string.Format("Creating a new TopLevelResource in resource group '{0}' with name '{1}'.", this.ResourceGroupName, this.Name)) + { + var result = new PSTopLevelResource(this.MySDKClient.TopLevelResource.CreateOrUpdate(existingResource)); + WriteObject(result); + } + } + } +} +``` + +### Child resource + +All child resources should have a `New-*` cmdlet that allows users to create a child resource with given properties. Properties that are required by the API should be mandatory parameters, and in the case where different combinations of properties are needed depending on a provided value (_e.g._, Windows and Linux VMs have different properties), multiple parameter sets should be used. This cmdlet should implement `SupportsShouldProcess` to allow users to provide the `-WhatIf` parameter and see what the result of executing the cmdlet is without the resource actually being created. + +_Note_: for long-running operations (~15s or longer), it is advised to add the [`-AsJob`](../design-guidelines/cmdlet-best-practices.md#asjob) to your cmdlet. + +#### Parameter sets + +To enable the above scenario, the cmdlet will need two parameter sets: + +``` +New-AzChildResource -ResourceGroupName -TopLevelResourceName -Name [-Property1 ] [-Property2 ] ... [-WhatIf] [-Confirm] + +New-AzChildResource -TopLevelResourceObject -Name [-Property1 ] [-Property2 ] ... [-WhatIf] [-Confirm] +``` + +The first parameter set has required `-ResourceGroupName`, `-TopLevelResource` and `-Name` parameters to satisfy the identity properties of the child resource, as well as a few optional `-PropertyX` parameters that allows the user to set values for the properties. The second parameter set has a required `-TopLevelResourceObject` parameter that can be piped from the parent resource's `Get-*` and `Set/Update-*` cmdlets. + +#### C# example + +```cs +namespace Microsoft.Azure.Commands.Service +{ + [Cmdlet(VerbsCommon.New, "AzChildResource", DefaultParameterSetName = CreateByNameParameterSet, SupportsShouldProcess = true), OutputType(typeof(PSChildResource))] + public class NewChildResourceCommand : ServiceBaseCmdlet + { + private const string CreateByNameParameterSet = "CreateByNameParameterSet"; + private const string CreateByParentObjectParameterSet = "CreateByParentObjectParameterSet"; + + [Parameter(Mandatory = true, ParameterSetName = CreateByNameParameterSet)] + [ResourceGroupCompleter] + [ValidateNotNullOrEmpty] + public string ResourceGroupName { get; set; } + + [Parameter(Mandatory = true, ParameterSetName = CreateByNameParameterSet)] + [ValidateNotNullOrEmpty] + public string TopLevelResourceName { get; set; } + + [Parameter(Mandatory = true, ValueFromPipeline = true, ParameterSetName = CreateByParentObjectParameterSet)] + [ValidateNotNull] + public PSTopLevelResource TopLevelResourceObject { get; set; } + + [Parameter(Mandatory = true)] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter(Mandatory = false)] + public Type1 Property1 { get; set; } + + [Parameter(Mandatory = false)] + public Type2 Property2 { get; set; } + + // Excluding other property parameters + + public override void ExecuteCmdlet() + { + if (this.IsParameterBound(c => c.TopLevelResourceObject)) + { + this.ResourceGroupName = this.TopLevelResourceObject.ResourceGroupName; + this.TopLevelResourceName = this.TopLevelResourceObject.Name; + } + + ChildResource existingChildResource = null; + try + { + existingChildResource = this.MySDKClient.ChildResource.Get(this.ResourceGroupName, this.TopLevelResourceName, this.Name); + } + catch + { + existingChildResource = null; + } + + if (existingChildResource != null) + { + throw new Exception(string.Format("A ChildResource with name '{0}' in resource group '{1}' under parent TopLevelResource '{2}' already exists. Please use Set/Update-AzChildResource to update an existing ChildResource.", this.Name, this.ResourceGroupName, this.TopLevelResourceName)); + } + + existingChildResource = new ChildResource() + { + Name = this.Name, + TopLevelResourceName = this.TopLevelResourceName, + ResourceGroupName = this.ResourceGroupName, + Property1 = this.Property1, + Property2 = this.Property2, + ... + } + + if (this.ShouldProcess(this.Name, string.Format("Creating a new ChildResource in resource group '{0}' under parent TopLevelResource '{1}' with name '{2}'.", this.ResourceGroupName, this.TopLevelResourceName, this.Name)) + { + var result = new PSChildResource(this.MySDKClient.ChildResource.CreateOrUpdate(existingChildResource)); + WriteObject(result); + } + } + } +} +``` \ No newline at end of file diff --git a/documentation/development-docs/examples/remove-cmdlet-example.md b/documentation/development-docs/examples/remove-cmdlet-example.md new file mode 100644 index 000000000000..17ae2220a57f --- /dev/null +++ b/documentation/development-docs/examples/remove-cmdlet-example.md @@ -0,0 +1,177 @@ +## `Remove-*` cmdlet example + +### Top-level resource + +All top-level resources should have a `Remove-*` cmdlet that allows users to delete a specific resource. The user can delete a resource by providing all identity properties, the resource id, or the object representation of the resource. This cmdlet should implement `SupportsShouldProcess` to allow users to provide the `-WhatIf` parameter and see what the result of executing the cmdlet is without the resource actually being deleted. This cmdlet should also implement the [`-PassThru`](../design-guidelines/cmdlet-best-practices.md#returning-no-output) parameter, which allows the user to receive output when no output would normally be provided. + +#### Parameter sets + +To enable the scenarios mentioned previously, the cmdlet will need three parameter sets: + +``` +Remove-AzTopLevelResource -ResourceGroupName -Name [-PassThru] [-WhatIf] [-Confirm] + +Remove-AzTopLevelResource -InputObject [-PassThru] [-WhatIf] [-Confirm] + +Remove-AzTopLevelResource -ResourceId [-PassThru] [-WhatIf] [-Confirm] +``` + +The first parameter set has required `-ResourceGroupName` and `-Name` parameters, which allows the user to explicitly provide the identity properties of the resource that they want to delete. The second parameter has a required `-InputObject` parameter, which allows the user to pipe the result of the `Get-*` and `Set/Update-*` cmdlets to this cmdlet and delete the corresponding resource. The third parameter has a required `-ResourceId` parameter, which allows the user to delete a specific resource by resource id. + +#### C# example + +```cs +namespace Microsoft.Azure.Commands.Service +{ + [Cmdlet(VerbsCommon.Remove, "AzTopLevelResource", DefaultParameterSetName = DeleteByNameParameterSet, SupportsShouldProcess = true), OutputType(typeof(bool))] + public class RemoveTopLevelResourceCommand : ServiceBaseCmdlet + { + private const string DeleteByNameParameterSet = "DeleteByNameParameterSet"; + private const string DeleteByInputObjectParameterSet = "DeleteByInputObjectParameterSet"; + private const string DeleteByResourceIdParameterSet = "DeleteByResourceIdParameterSet"; + + [Parameter(Mandatory = true, ParameterSetName = DeleteByNameParameterSet)] + [ResourceGroupCompleter] + [ValidateNotNullOrEmpty] + public string ResourceGroupName { get; set; } + + [Parameter(Mandatory = true, ParameterSetName = DeleteByNameParameterSet)] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter(Mandatory = true, ValueFromPipeline = true, ParameterSetName = DeleteByInputObjectParameterSet)] + [ValidateNotNull] + public PSTopLevelResource InputObject { get; set; } + + [Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, ParameterSetName = DeleteByResourceIdParameterSet)] + [ValidateNotNullOrEmpty] + public string ResourceId { get; set; } + + [Parameter(Mandatory = false)] + public SwitchParameter PassThru { get; set; } + + public override void ExecuteCmdlet() + { + if (this.IsParameterBound(c => c.InputObject)) + { + this.ResourceGroupName = this.InputObject.ResourceGroupName; + this.Name = this.InputObject.Name; + } + + if (this.IsParameterBound(c => c.ResourceId)) + { + var resourceIdentifier = new ResourceIdentifier(this.ResourceId); + this.ResourceGroupName = resourceIdentifier.ResourceGroupName; + this.Name = resourceIdentifier.ResourceName; + } + + if (this.ShouldProcess(this.Name, string.Format("Deleting TopLevelResource '{0}' in resource group {0}", this.Name, this.ResourceGroupName))) + { + this.MySDKClient.TopLevelResource.Delete(this.ResourceGroupName, this.Name); + if (this.IsPassThru.IsPresent) + { + WriteObject(true); + } + } + } + } +} +``` + +### Child resource + +All child resources should have a `Remove-*` cmdlet that allows users to delete a specific child resource. The user can delete a child resource by providing all identity properties, the resource id of the child resource, or the object representation of the child resource. This cmdlet should implement `SupportsShouldProcess` to allow users to provide the `-WhatIf` parameter and see what the result of executing the cmdlet is without the child resource actually being deleted. This cmdlet should also implement the [`-PassThru`](../design-guidelines/cmdlet-best-practices.md#returning-no-output) parameter, which allows the user to receive the output when no output would normally be provided. + +#### Parameter sets + +To enable the scenarios mentioned previously, the cmdlet will need four parameter sets: + +``` +Remove-AzChildResource -ResourceGroupName -TopLevelResourceName -Name [-PassThru] [-WhatIf] [-Confirm] + +Remove-AzChildResource -TopLeveResourceObject -Name [-PassThru] [-WhatIf] [-Confirm] + +Remove-AzChildResource -InputObject [-PassThru] [-WhatIf] [-Confirm] + +Remove-AzChildResource -ResourceId [-PassThru] [-WhatIf] [-Confirm] +``` + +The first parameter set has required `-ResourceGroupName`, `-TopLevelResourceName` and `-Name` parameters, which allows the user to explicitly provide the identity properties of the child resource that they want to delete. The second parameter has a required `-TopLeveResourceObject` parameter, which allows the user to pipe the result of the parent resource's `Get-*` and `Set/Update-*` cmdlets to this cmdlet, as well as a required `-Name` parameter. The third parameter has a required `-InputObject` parameter, which allows the user to pipe the result of the `Get-*` and `Set/Update-*` cmdlets to this cmdlet and delete the corresponding child resource. The fourth parameter has a required `-ResourceId` parameter, which allows the user to delete the specific child resource by resource id. + +#### C# example + +```cs +namespace Microsoft.Azure.Commands.Service +{ + [Cmdlet(VerbsCommon.Remove, "AzChildResource", DefaultParameterSetName = DeleteByNameParameterSet, SupportsShouldProcess = true), OutputType(typeof(bool))] + public class RemoveChildResourceCommand : ServiceBaseCmdlet + { + private const string DeleteByNameParameterSet = "DeleteByNameParameterSet"; + private const string DeleteByParentObjectParameterSet = "DeleteByParentObjectParameterSet"; + private const string DeleteByInputObjectParameterSet = "DeleteByInputObjectParameterSet"; + private const string DeleteByResourceIdParameterSet = "DeleteByResourceIdParameterSet"; + + [Parameter(Mandatory = true, ParameterSetName = DeleteByNameParameterSet)] + [ResourceGroupCompleter] + [ValidateNotNullOrEmpty] + public string ResourceGroupName { get; set; } + + [Parameter(Mandatory = true, ParameterSetName = DeleteByNameParameterSet)] + [ValidateNotNullOrEmpty] + public string TopLevelResourceName { get; set; } + + [Parameter(Mandatory = true, ParameterSetName = DeleteByNameParameterSet)] + [Parameter(Mandatory = true, ParameterSetName = DeleteByParentObjectParameterSet)] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter(Mandatory = true, ValueFromPipeline = true, ParameterSetName = DeleteByParentObjectParameterSet)] + [ValidateNotNull] + public PSTopLevelResource TopLeveResourceObject { get; set; } + + [Parameter(Mandatory = true, ValueFromPipeline = true, ParameterSetName = DeleteByInputObjectParameterSet)] + [ValidateNotNull] + public PSChildResource InputObject { get; set; } + + [Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, ParameterSetName = DeleteByResourceIdParameterSet)] + [ValidateNotNullOrEmpty] + public string ResourceId { get; set; } + + [Parameter(Mandatory = false)] + public SwitchParameter PassThru { get; set; } + + public override void ExecuteCmdlet() + { + if (this.IsParameterBound(c => c.TopLeveResourceObject)) + { + this.ResourceGroupName = this.TopLeveResourceObject.ResourceGroupName; + this.TopLevelResourceName = this.TopLeveResourceObject.Name; + } + + if (this.IsParameterBound(c => c.InputObject)) + { + this.ResourceGroupName = this.InputObject.ResourceGroupName; + this.TopLevelResourceName = this.InputObject.TopLevelResourceName; + this.Name = this.InputObject.Name; + } + + if (this.IsParameterBound(c => c.ResourceId)) + { + var resourceIdentifier = new ResourceIdentifier(this.ResourceId); + this.ResourceGroupName = resourceIdentifier.ResourceGroupName; + this.TopLevelResourceName = resourceIdentifier.ParentResource; + this.Name = resourceIdentifier.ResourceName; + } + + if (this.ShouldProcess(this.Name, string.Format("Deleting ChildResource '{0}' in resource group '{1}' under parent TopLevelResource '{2}'.", this.Name, this.ResourceGroupName, this.TopLevelResourceName))) + { + this.MySDKClient.ChildResource.Delete(this.ResourceGroupName, this.TopLevelResourceName, this.Name); + if (this.IsPassThru.IsPresent) + { + WriteObject(true); + } + } + } + } +} +``` \ No newline at end of file diff --git a/documentation/development-docs/examples/set-cmdlet-example.md b/documentation/development-docs/examples/set-cmdlet-example.md new file mode 100644 index 000000000000..22ef6e73a82d --- /dev/null +++ b/documentation/development-docs/examples/set-cmdlet-example.md @@ -0,0 +1,235 @@ +## `Set-*` cmdlet example + +### Top-level resource + +All top-level resources should have a `Set-*` cmdlet that allows users to update an existing resource _if the API follows `PUT` semantics_. If the API supports `PATCH` semantics, then the cmdlet should be `Update-*` (see below). The user can update an existing resource by providing all identity properties, the resource id, or the object representation of the resource. Similar to the `New-*` cmdlet, properties that are required by the API should be mandatory parameters, and in the case where different combinations of properties are needed depending on a provided value (_e.g._, Windows and Linux VMs have different properties), multiple parameter sets should be used. This cmdlet should implement `SupportsShouldProcess` to allow users to provide the `-WhatIf` parameter and see what the result of executing the cmdlet is without the resource actually being updated. + +#### Parameter Sets + +To enable the scenarios mentioned previously, the cmdlet will need three parameter sets: + +``` +Set-AzTopLevelResource -ResourceGroupName -Name -Property1 -Property2 ... [-WhatIf] [-Confirm] + +Set-AzTopLevelResource -InputObject [-Property1 ] -[Property2 ] ... [-WhatIf] [-Confirm] + +Set-AzTopLevelResource -ResourceId -Property1 -Property2 ... [-WhatIf] [-Confirm] +``` + +The first parameter set has required `-ResourceGroupName` and `-Name` parameters, as well as required property parameters to set their values on the resource. The second parameter has a required `-InputObject` parameter, as well as optional property parameters that override the value of the property on the given object if provided. The third parameter has a required `-ResourceId` parameter, as well as required property parameters to set their values on the resource. + +#### C# example + +```cs +namespace Microsoft.Azure.Commands.Service +{ + [Cmdlet(VerbsCommon.Set, "AzTopLevelResource", DefaultParameterSet = SetByNameParameterSet, SupportsShouldProcess = true), OutputType(typeof(PSTopLevelResource))] + public class SetTopLevelResourceCommand : ServiceBaseCmdlet + { + private const string SetByNameParameterSet = "SetByNameParameterSet"; + private const string SetByInputObjectParameterSet = "SetByInputObjectParameterSet"; + private const string SetByResourceIdParameterSet = "SetByResourceIdParameterSet"; + + [Parameter(Mandatory = true, ParameterSetName = SetByNameParameterSet)] + [ResourceGroupCompleter] + [ValidateNotNullOrEmpty] + public string ResourceGroupName { get; set; } + + [Parameter(Mandatory = true, ParameterSetName = SetByNameParameterSet)] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter(Mandatory = true, ValueFromPipeline = true, ParameterSetName = SetByInputObjectParameterSet)] + [ValidateNotNull] + public PSTopLevelResource InputObject { get; set; } + + [Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, ParameterSetName = SetByResourceIdParameterSet)] + [ValidateNotNullOrEmpty] + public string ResourceId { get; set; } + + [Parameter(Mandatory = true, ParameterSetName = SetByNameParameterSet)] + [Parameter(Mandatory = true, ParameterSetName = SetByResourceIdParameterSet)] + [Parameter(Mandatory = false, ParameterSetName = SetByInputObjectParameterSet)] + public Type1 Property1 { get; set; } + + [Parameter(Mandatory = true, ParameterSetName = SetByNameParameterSet)] + [Parameter(Mandatory = true, ParameterSetName = SetByResourceIdParameterSet)] + [Parameter(Mandatory = false, ParameterSetName = SetByInputObjectParameterSet)] + public Type2 Property2 { get; set; } + + // Excluding other property parameters + + public override void ExecuteCmdlet() + { + if (this.IsParameterBound(c => c.InputObject)) + { + this.ResourceGroupName = this.InputObject.ResourceGroupName; + this.Name = this.InputObject.Name; + this.Property1 = this.IsParameterBound(c => c.Property1) ? this.Property1 : this.InputObject.Property1; + this.Property2 = this.IsParameterBound(c => c.Property2) ? this.Property2 : this.InputObject.Property2; + ... + } + + if (this.IsParameterBound(c => c.ResourceId)) + { + var resourceIdentifier = new ResourceIdentifier(this.ResourceId); + this.ResourceGroupName = resourceIdentifier.ResourceGroupName; + this.Name = resourceIdentifier.ResourceName; + } + + TopLevelResource existingResource = null; + try + { + existingResource = this.MySDKClient.TopLevelResource.Get(this.ResourceGroupName, this.Name); + } + catch + { + existingResource = null; + } + + if (existingResource == null) + { + throw new Exception(string.Format("A TopLevelResource with name '{0}' in resource group '{1}' does not exist. Please use New-AzTopLevelResource to create a TopLevelResource with these properties.", this.Name, this.ResourceGroupName)); + } + + existingResource.Property1 = this.Property1; + existingResource.Property2 = this.Property2; + ... + + if (this.ShouldProcess(this.Name, string.Format("Updating TopLevelResource '{0}' in resource group '{1}'.", this.Name, this.ResourceGroupName))) + { + var result = new PSTopLevelResource(this.MySDKClient.TopLevelResource.Update(this.ResourceGroupName, this.Name, existingResource)); + WriteObject(result); + } + } + } +} +``` + +### Child resource + +All child resources should have a `Set-*` cmdlet that allows users to update an existing child resource _if the API follows `PUT` semantics_. If the API supports `PATCH` semantics, then the cmdlet should be `Update-*` (see below). The user can update an existing child resource by providing all identity properties, the resource id, or the object representation of the child resource. Similar to the `New-*` cmdlet, properties that are required by the API should be mandatory parameters, and in the case where different combinations of properties are needed depending on a provided value (_e.g._, Windows and Linux VMs have different properties), multiple parameter sets should be used. This cmdlet should implement `SupportsShouldProcess` to allow users to provide the `-WhatIf` parameter and see what the result of executing the cmdlet is without the resource actually being updated. + +#### Parameter sets + +To enable the scenarios mentioned previously, the cmdlet will need four parameter sets: + +``` +Set-AzChildResource -ResourceGroupName -TopLevelResourceName -Name -Property1 -Property2 ... [-WhatIf] [-Confirm] + +Set-AzChildResource -TopLevelResourceObject -Name -Property1 -Property2 ... [-WhatIf] [-Confirm] + +Set-AzChildResource -InputObject [-Property1 ] [-Property2 ] ... [-WhatIf] [-Confirm] + +Set-AzChildResource -ResourceId -Property1 -Property2 ... [-WhatIf] [-Confirm] +``` + +The first parameter set has required `-ResourceGroupName`, `-TopLevelResourceName` and `-Name` parameters, as well as required property parameters to set their values on the child resource. The second parameter set has a required `-TopLevelResourceObject` parameter, which allows the user to pipe the result of the parent resource's `Get-*` and `Set/Update-*` cmdlets to this cmdlet, as well as required property parameters. The third parameter set has a required `-InputObject` parameter, as well as optional property parameters that override the value of the property on the given object if provided. The fourth parameter set has a required `-ResourceIid` parameter, as well as required property parameters to set their values on the child resource. + +#### C# example + +```cs +namespace Microsoft.Azure.Commands.Service +{ + [Cmdlet(VerbsCommon.Set, "AzChildResource", DefaultParameterSet = SetByNameParameterSet, SupportsShouldProcess = true), OutputType(typeof(PSChildResource))] + public class SetChildResourceCommand : ServiceBaseCmdlet + { + private const string SetByNameParameterSet = "SetByNameParameterSet"; + private const string SetByParentObjectParameterSet = "SetByParentObjectParameterSet"; + private const string SetByInputObjectParameterSet = "SetByInputObjectParameterSet"; + private const string SetByResourceIdParameterSet = "SetByResourceIdParameterSet"; + + [Parameter(Mandatory = true, ParameterSetName = SetByNameParameterSet)] + [ResourceGroupCompleter] + [ValidateNotNullOrEmpty] + public string ResourceGroupName { get; set; } + + [Parameter(Mandatory = true, ParameterSetName = SetByNameParameterSet) + [ValidateNotNullOrEmpty] + public string TopLevelResourceName { get; set; } + + [Parameter(Mandatory = true, ParameterSetName = SetByNameParameterSet)] + [Parameter(Mandatory = true, ParameterSetName = SetByParentObjectParameterSet)] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter(Mandatory = true, ValueFromPipeline = true, ParameterSetName = SetByParentObjectParameterSet)] + [ValidateNotNull] + public PSTopLevelResource TopLevelResourceObject { get; set; } + + [Parameter(Mandatory = true, ValueFromPipeline = true, ParameterSetName = SetByInputObjectParameterSet)] + [ValidateNotNull] + public PSChildResource InputObject { get; set; } + + [Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, ParameterSetName = SetByResourceIdParameterSet)] + [ValidateNotNullOrEmpty] + public string ResourceId { get; set; } + + [Parameter(Mandatory = true, ParameterSetName = SetByNameParameterSet)] + [Parameter(Mandatory = true, ParameterSetName = SetByParentObjectParameterSet)] + [Parameter(Mandatory = true, ParameterSetName = SetByResourceIdParameterSet)] + [Parameter(Mandatory = false, ParameterSetName = SetByInputObjectParameterSet)] + public Type1 Property1 { get; set; } + + [Parameter(Mandatory = true, ParameterSetName = SetByNameParameterSet)] + [Parameter(Mandatory = true, ParameterSetName = SetByParentObjectParameterSet)] + [Parameter(Mandatory = true, ParameterSetName = SetByResourceIdParameterSet)] + [Parameter(Mandatory = false, ParameterSetName = SetByInputObjectParameterSet)] + public Type2 Property2 { get; set; } + + // Excluding other property parameters + + public override void ExecuteCmdlet() + { + if (this.IsParameterBound(c => c.TopLevelResourceObject)) + { + this.ResourceGroupName = this.TopLevelResourceObject.ResourceGroupName; + this.TopLevelResourceName = this.TopLevelResourceObject.Name; + } + + if (this.IsParameterBound(c => c.InputObject)) + { + this.ResourceGroupName = this.InputObject.ResourceGroupName; + this.TopLevelResourceName = this.InputObject.TopLevelResourceName; + this.Name = this.InputObject.Name; + this.Property1 = this.IsParameterBound(c => c.Property1) ? this.Property1 : this.InputObject.Property1; + this.Property2 = this.IsParameterBound(c => c.Property2) ? this.Property2 : this.InputObject.Property2; + ... + } + + if (this.IsParameterBound(c => c.ResourceId)) + { + var resourceIdentifier = new ResourceIdentifier(this.ResourceId); + this.ResourceGroupName = resourceIdentifier.ResourceGroupName; + this.TopLevelResourceName = resourceIdentifier.ParentResource; + this.Name = resourceIdentifier.ResourceName; + } + + ChildResource childResource = null; + try + { + childResource = this.MySDKClient.ChildResource.Get(this.ResourceGroupName, this.TopLevelResourceName, this.Name); + } + catch + { + childResource = null; + } + + if (childResource == null) + { + throw new Exception(string.Format("A ChildResource with name '{0}' in resource group '{1}' under parent TopLevelResource '{2}' does not exist. Please use New-AzChildResource to create a ChildResource with these properties.", this.Name, this.ResourceGroupName, this.TopLevelResourceName)); + } + + childResource.Property1 = this.Property1; + childResource.Property2 = this.Property2; + ... + + if (this.ShouldProcess(this.Name, string.Format("Updating ChildResource '{0}' in resource group '{1}' under parent TopLevelResource '{2}'.", this.Name, this.ResourceGroupName, this.TopLevelResourceName))) + { + var result = new PSChildResource(this.MySDKClient.ChildResource.Update(this.ResourceGroupName, this.TopLevelResourceName, this.Name, childResource)); + WriteObject(result); + } + } + } +} +``` \ No newline at end of file diff --git a/documentation/development-docs/examples/update-cmdlet-example.md b/documentation/development-docs/examples/update-cmdlet-example.md new file mode 100644 index 000000000000..b17029ee1d93 --- /dev/null +++ b/documentation/development-docs/examples/update-cmdlet-example.md @@ -0,0 +1,221 @@ +## `Update-*` cmdlet example + +### Top-level resource + +All top-level resources should have an `Update-*` cmdlet that allows users to update an existing resource _if the API follows `PATCH` semantics_. If the API supports `PUT` semantics, then the cmdlet should be `Set-*` (see above). The user can update an existing resource by providing all identity properties, the resource id, or the object representation of the resource. Similar to the `New-*` cmdlet, properties that are required by the API should be mandatory parameters, and in the case where different combinations of properties are needed depending on a provided value (_e.g._, Windows and Linux VMs have different properties), multiple parameter sets should be used. This cmdlet should implement `SupportsShouldProcess` to allow users to provide the `-WhatIf` parameter and see what the result of executing the cmdlet is without the resource actually being updated. + +_Note_: if the only property that a user is able to update through the `PATCH` API is tags, then this cmdlet should not be implemented. + +#### Parameter Sets + +To enable the scenarios mentioned previously, the cmdlet will need three parameter sets: + +``` +Update-AzTopLevelResource -ResourceGroupName -Name [-Property1 ] [-Property2 ] ... [-WhatIf] [-Confirm] + +Update-AzTopLevelResource -InputObject [-Property1 ] [-Property2 ] ... [-WhatIf] [-Confirm] + +Update-AzTopLevelResource -ResourceId [-Property1 ] [-Property2 ] ... [-WhatIf] [-Confirm] +``` + +The first parameter set has required `-ResourceGroupName` and `-Name` parameters, the second parameter set has a required `-InputObject` parameter, and the third parameter set has a required `-ResourceId` parameter. All three parameter sets have optional property parameters that can be used to override the value of the property set on the retrieved/provided resource. + +#### C# example + +```cs +namespace Microsoft.Azure.Commands.Service +{ + [Cmdlet(VerbsData.Update, "AzTopLevelResource", DefaultParameterSet = UpdateByNameParameterSet, SupportsShouldProcess = true), OutputType(typeof(PSTopLevelResource))] + public class UpdateTopLevelResourceCommand : ServiceBaseCmdlet + { + private const string UpdateByNameParameterSet = "UpdateByNameParameterSet"; + private const string UpdateByInputObjectParameterSet = "UpdateByInputObjectParameterSet"; + private const string UpdateByResourceIdParameterSet = "UpdateByResourceIdParameterSet"; + + [Parameter(Mandatory = true, ParameterSetName = UpdateByNameParameterSet)] + [ResourceGroupCompleter] + [ValidateNotNullOrEmpty] + public string ResourceGroupName { get; set; } + + [Parameter(Mandatory = true, ParameterSetName = UpdateByNameParameterSet)] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter(Mandatory = true, ValueFromPipeline = true, ParameterSetName = UpdateByInputObjectParameterSet)] + [ValidateNotNull] + public PSTopLevelResource InputObject { get; set; } + + [Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, ParameterSetName = UpdateByResourceIdParameterSet)] + [ValidateNotNullOrEmpty] + public string ResourceId { get; set; } + + [Parameter(Mandatory = false)] + public Type1 Property1 { get; set; } + + [Parameter(Mandatory = false)] + public Type2 Property2 { get; set; } + + // Excluding other property parameters + + public override void ExecuteCmdlet() + { + if (this.IsParameterBound(c => c.InputObject)) + { + this.ResourceGroupName = this.InputObject.ResourceGroupName; + this.Name = this.InputObject.Name; + } + + if (this.IsParameterBound(c => c.ResourceId)) + { + var resourceIdentifier = new ResourceIdentifier(this.ResourceId); + this.ResourceGroupName = resourceIdentifier.ResourceGroupName; + this.Name = resourceIdentifier.ResourceName; + } + + TopLevelResource existingResource = null; + try + { + existingResource = this.MySDKClient.TopLevelResource.Get(this.ResourceGroupName, this.Name); + } + catch + { + existingResource = null; + } + + if (existingResource == null) + { + throw new Exception(string.Format("A TopLevelResource with name '{0}' in resource group '{1}' does not exist. Please use New-AzTopLevelResource to create a TopLevelResource with these properties.", this.Name, this.ResourceGroupName)); + } + + existingResource.Property1 = this.IsParameterBound(c => c.Property1) ? this.Property1 : existingResource.Property1; + existingResource.Property2 = this.IsParameterBound(c => c.Property2) ? this.Property2 : existingResource.Property2; + ... + + if (this.ShouldProcess(this.Name, string.Format("Updating TopLevelResource '{0}' in resource group '{1}'.", this.Name, this.ResourceGroupName))) + { + var result = new PSTopLevelResource(this.MySDKClient.TopLevelResource.Update(this.ResourceGroupName, this.Name, existingResource)); + WriteObject(result); + } + } + } +} +``` + +### Child resource + +All child resources should have an `Update-*` cmdlet that allows users to update an existing child resource _if the API follows `PATCH` semantics_. If the API supports `PUT` semantics, then the cmdlet should be `Set-*` (See above). The user can update an existing child resource by providing all identity properties, the resource id, or the object representation of the child resource. Similar to the `New-*` cmdlet, properties that are required by the API should be mandatory parameters, and in the case where different combinations of properties are needed depending on a provided value (_e.g._, Windows and Linux VMs have different properties), multiple parameter sets should be used. This cmdlet should implement `SupportsShouldProcess` to allow users to provide the `-WhatIf` parameter and see what the result of executing the cmdlet is without the resource actually being updated. + +#### Parameter sets + +To enable the scenarios mentioned previously, the cmdlet will need four parameter sets: + +``` +Update-AzChildResource -ResourceGroupName -TopLevelResourceName -Name [-Property1 ] [-Property2 ] ... [-WhatIf] [-Confirm] + +Update-AzChildResource -TopLevelResourceObject -Name [-Property1 ] [-Property2 ] ... [-WhatIf] [-Confirm] + +Update-AzChildResource -InputObject [-Property1 ] [-Property2 ] ... [-WhatIf] [-Confirm] + +Update-AzChildResource -ResourceId [-Property1 ] [-Property2 ] ... [-WhatIf] [-Confirm] +``` + +The first parameter set has required `-ResourceGroupName`, `-TopLevelResourceName` and `-Name` parameters, the second parameter set has required `-TopLevelResourceObject` and `-Name` parameters, the third parameter set has a required `-InputObject` parameter, and the fourth parameter set has a required `-ResourceId` parameter. All four parameter sets have optional property parameters that can be used to override the value of the property set on the retrieved/provided resource. + +#### C# example + +```cs +namespace Microsoft.Azure.Commands.Service +{ + [Cmdlet(VerbsData.Update, "AzChildResource", DefaultParameterSet = UpdateByNameParameterSet, SupportsShouldProcess = true), OutputType(typeof(PSChildResource))] + public class UpdateChildResourceCommand : ServiceBaseCmdlet + { + private const string UpdateByNameParameterSet = "UpdateByNameParameterSet"; + private const string UpdateByParentObjectParameterSet = "UpdateByParentObjectParameterSet"; + private const string UpdateByInputObjectParameterSet = "UpdateByInputObjectParameterSet"; + private const string UpdateByResourceIdParameterSet = "UpdateByResourceIdParameterSet"; + + [Parameter(Mandatory = true, ParameterSetName = UpdateByNameParameterSet)] + [ResourceGroupCompleter] + [ValidateNotNullOrEmpty] + public string ResourceGroupName { get; set; } + + [Parameter(Mandatory = true, ParameterSetName = UpdateByNameParameterSet)] + [ValidateNotNullOrEmpty] + public string TopLevelResourceName { get; set; } + + [Parameter(Mandatory = true, ParameterSetName = UpdateByNameParameterSet)] + [Parameter(Mandatory = true, ParameterSetName = UpdateByParentObjectParameterSet)] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter(Mandatory = true, ValueFromPipeline = true, ParameterSetName = UpdateByParentObjectParameterSet)] + [ValidateNotNull] + public PSTopLevelResource TopLevelResourceObject { get; set; } + + [Parameter(Mandatory = true, ValueFromPipeline = true, ParameterSetName = UpdateByInputObjectParameterSet)] + [ValidateNotNull] + public PSTopLevelResource InputObject { get; set; } + + [Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, ParameterSetName = UpdateByResourceIdParameterSet)] + [ValidateNotNullOrEmpty] + public string ResourceId { get; set; } + + [Parameter(Mandatory = false)] + public Type1 Property1 { get; set; } + + [Parameter(Mandatory = false)] + public Type2 Property2 { get; set; } + + // Excluding other property parameters + + public override void ExecuteCmdlet() + { + if (this.IsParameterBound(c => c.TopLevelResourceObject)) + { + this.ResourceGroupName = this.TopLevelResourceObject.ResourceGroupName; + this.TopLevelResourceName = this.TopLevelResourceObject.Name; + } + + if (this.IsParameterBound(c => c.InputObject)) + { + this.ResourceGroupName = this.InputObject.ResourceGroupName; + this.TopLevelResourceName = this.InputObject.TopLevelResourceName; + this.Name = this.InputObject.Name; + } + + if (this.IsParameterBound(c => c.ResourceId)) + { + var resourceIdentifier = new ResourceIdentifier(this.ResourceId); + this.ResourceGroupName = resourceIdentifier.ResourceGroupName; + this.TopLevelResourceName = resourceIdentifer.ParentResource; + this.Name = resourceIdentifier.ResourceName; + } + + ChildResource childResource = null; + try + { + childResource = this.MySDKClient.ChildResource.Get(this.ResourceGroupName, this.TopLevelResourceName, this.Name); + } + catch + { + childResource = null; + } + + if (childResource == null) + { + throw new Exception(string.Format("A ChildResource with name '{0}' in resource group '{1}' under parent TopLevelResource '{2}' does not exist. Please use New-AzChildResource to create a ChildResource with these properties.", this.Name, this.ResourceGroupName, this.TopLevelResourceName)); + } + + childResource.Property1 = this.IsParameterBound(c => c.Property1) ? this.Property1 : childResource.Property1; + childResource.Property2 = this.IsParameterBound(c => c.Property2) ? this.Property2 : childResource.Property2; + ... + + if (this.ShouldProcess(this.Name, string.Format("Updating ChildResource '{0}' in resource group '{1}' under parent TopLevelResource '{2}'.", this.Name, this.ResourceGroupName, this.TopLevelResourceName))) + { + var result = new PSChildResource(this.MySDKClient.ChildResource.Update(this.ResourceGroupName, this.TopLevelResourceName, this.Name, childResource)); + WriteObject(result); + } + } + } +} +``` \ No newline at end of file diff --git a/documentation/development-docs/generate-format.ps1xml-file.md b/documentation/development-docs/generate-format.ps1xml-file.md index fb84c877fc9a..b34d70a89647 100644 --- a/documentation/development-docs/generate-format.ps1xml-file.md +++ b/documentation/development-docs/generate-format.ps1xml-file.md @@ -115,7 +115,7 @@ To provide a better PowerShell Azure cmdlets output experience we worked out a m 2. Run the New-FormatPs1Xml cmdlet to generate the format.ps1xml file. --- - We presume that for the [output type](https://github.com/Azure/azure-powershell/blob/master/documentation/development-docs/azure-powershell-design-guidelines.md#output-type) you created a new class that, for example, wraps a returning .NET SDK type, rather than PSObject. + We presume that for the [output type](./design-guidelines/cmdlet-best-practices.md#output-type) you created a new class that, for example, wraps a returning .NET SDK type, rather than PSObject. --- diff --git a/documentation/development-docs/patterns-for-standard-cmdlets.md b/documentation/development-docs/patterns-for-standard-cmdlets.md deleted file mode 100644 index c31fc399532d..000000000000 --- a/documentation/development-docs/patterns-for-standard-cmdlets.md +++ /dev/null @@ -1,1042 +0,0 @@ -# Expected Patterns for Standard Cmdlets - -## Table of Contents - -- [Top-level Resources](#top---level-resources) - - [`Get-*` cmdlet](#get--cmdlet) - - [`New-*` cmdlet](#new--cmdlet) - - [`Remove-*` cmdlet](#remove--cmdlet) - - [`Set-*` cmdlet](#set--cmdlet) - - [`Update-*` cmdlet](#update--cmdlet) -- [Child Resources](#child-resources) - - [`Get-*` cmdlet](#get--cmdlet-1) - - [`New-*` cmdlet](#new--cmdlet-1) - - [`Remove-*` cmdlet](#remove--cmdlet-1) - - [`Set-*` cmdlet](#set--cmdlet-1) - - [`Update-*` cmdlet](#update--cmdlet-1) - -## Top-level Resources - -### `Get-*` cmdlet - -All top-level resources should have a `Get-*` cmdlet that allows users to list the resources in their subscription or a resource group, as well as get a specific resource. In addition, users should be able to provide the resource id of the resource they want to get, and the cmdlet will parse the string to get the necessary identity information. - -#### Parameter sets - -To enable the scenarios mentioned previously, the cmdlet will need three parameter sets: - -``` -Get-AzFoo [-ResourceGroupName ] - -Get-AzFoo -ResourceGroupName -Name - -Get-AzFoo -ResourceId -``` - -The first parameter set has an optional `-ResourceGroupName` parameter, which allows the user to list all resources in a subscription or in a resource group. The second parameter set has required `-ResourceGroupName` and `-Name` parameters, which allows the user to get a specific resource. The third parameter set has a required `-ResourceId` parameter, which allows the user to get a specific resource by resource id. - -#### C# example - -
Click to expand example -

- -```cs -namespace Microsoft.Azure.Commands.Foo -{ - [Cmdlet(VerbsCommon.Get, "AzFoo", DefaultParameterSetName = ListParameterSet), OutputType(typeof(PSFoo))] - public class GetFooCommand : FooBaseCmdlet - { - private const string ListParameterSet = "ListParameterSet"; - private const string GetByNameParameterSet = "GetByNameParameterSet";" - private const string GetByResourceIdParameterSet = "GetByResourceIdParameterSet"; - - [Parameter(Mandatory = false, ParameterSetName = ListParameterSet)] - [Parameter(Mandatory = true, ParameterSetName = GetByNameParameterSet)] - [ResourceGroupCompleter] - [ValidateNotNullOrEmpty] - public string ResourceGroupName { get; set; } - - [Parameter(Mandatory = true, ParameterSetName = GetByNameParameterSet)] - [ValidateNotNullOrEmpty] - public string Name { get; set; } - - [Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, ParameterSetName = GetByResourceIdParameterSet )] - [ValidateNotNullOrEmpty] - public string ResourceId { get; set; } - - public override void ExecuteCmdlet() - { - if (this.IsParameterBound(c => c.ResourceId)) - { - var resourceIdentifier = new ResourceIdentifier(this.ResourceId); - this.ResourceGroupName = resourceIdentifier.ResourceGroupName; - this.Name = resourceIdentifier.ResourceName; - } - - if (!string.IsNullOrEmpty(this.Name)) - { - var result = new PSFoo(this.MySDKClient.Foo.Get(this.ResourceGroupName, this.Name)); - WriteObject(result); - } - else if (!string.IsNullOrEmpty(this.ResourceGroupName)) - { - var result = this.MySDKClient.Foo.ListByResourceGroup(this.ResourceGroupName).Select(f => new PSFoo(f)); - WriteObject(result, true); - } - else - { - var result = this.MySDKClient.Foo.List().Select(f => new PSFoo(f)); - WriteObject(result, true); - } - } - } -} -``` - -

-
- -### `New-*` cmdlet - -All top-level resources should have a `New-*` cmdlet that allows users to create a resource with given properties. Properties that are required by the API should be mandatory parameters, and in the case where different combinations of properties are needed depending on a provided value (_e.g._, Windows and Linux VMs have different properties), multiple parameter sets should be used. This cmdlet should implement `SupportsShouldProcess` to allow users to provide the `-WhatIf` parameter and see what the result of executing the cmdlet is without the resource actually being created. - -_Note_: for long-running operations (~15s or longer), it is advised to add the [`-AsJob`](.\azure-powershell-design-guidelines#asjob-parameter) to your cmdlet. - -#### Parameter sets - -To enable the above scenario, only one parameter set is needed: - -``` -New-AzFoo -ResourceGroupName -Name [-Property1 ] [-Property2 ] ... [-WhatIf] [-Confirm] -``` - -This parameter set has required `-ResourceGroupName` and `-Name` parameters to satisfy the identity properties of the resource, as well as a few optional `-PropertyX` parameters that allows the user to set values for properties. The parameter set also has optional `-WhatIf` and `-Confirm` parameters that are automatically included from the implementation of `SupportsShouldProcess`. - -#### C# example - -
Click to expand example -

- -```cs -namespace Microsoft.Azure.Commands.Foo -{ - [Cmdlet(VerbsCommon.New, "AzFoo", DefaultParameterSetName = CreateParameterSet, SupportsShouldProcess = true), OutputType(typeof(PSFoo))] - public class NewFooCommand : FooBaseCmdlet - { - private const string CreateParameterSet = "CreateParameterSet"; - - [Parameter(Mandatory = true, ParameterSetName = CreateParameterSet)] - [ResourceGroupCompleter] - [ValidateNotNullOrEmpty] - public string ResourceGroupName { get; set; } - - [Parameter(Mandatory = true, ParameterSetName = CreateParameterSet)] - [ValidateNotNullOrEmpty] - public string Name { get; set; } - - [Parameter(Mandatory = false, ParameterSetName = CreateParameterSet)] - public Type1 Property1 { get; set; } - - [Parameter(Mandatory = false, ParameterSetName = CreateParameterSet)] - public Type2 Property2 { get; set; } - - // Excluding other property parameters - - public override void ExecuteCmdlet() - { - Foo existingFoo = null; - try - { - existingFoo = this.MySDKClient.Foo.Get(this.ResourceGroupName, this.Name); - } - catch - { - existingFoo = null; - } - - if (existingFoo != null) - { - throw new Exception(string.Format("A Foo with name '{0}' in resource group '{1}' already exists. Please use Set/Update-AzFoo to update an existing Foo.", this.Name, this.ResourceGroupName)); - } - - existingFoo = new Foo() - { - Name = this.Name, - ResourceGroupName = this.ResourceGroupName, - Property1 = this.Property1, - Property2 = this.Property2, - ... - } - - if (this.ShouldProcess(this.Name, string.Format("Creating a new Foo in resource group '{0}' with name '{1}'.", this.ResourceGroupName, this.Name)) - { - var result = new PSFoo(this.MySDKClient.Foo.CreateOrUpdate(existingFoo)); - WriteObject(result); - } - } - } -} -``` - -

-
- -### `Remove-*` cmdlet - -All top-level resources should have a `Remove-*` cmdlet that allows users to delete a specific resource. The user can delete a resource by providing all identity properties, the resource id, or the object representation of the resource. This cmdlet should implement `SupportsShouldProcess` to allow users to provide the `-WhatIf` parameter and see what the result of executing the cmdlet is without the resource actually being deleted. This cmdlet should also implement the [`-PassThru`](.\azure-powershell-design-guidelines.md#returning-no-output) parameter, which allows the user to receive output when no output would normally be provided. - -#### Parameter sets - -To enable the scenarios mentioned previously, the cmdlet will need three parameter sets: - -``` -Remove-AzFoo -ResourceGroupName -Name [-PassThru] [-WhatIf] [-Confirm] - -Remove-AzFoo -InputObject [-PassThru] [-WhatIf] [-Confirm] - -Remove-AzFoo -ResourceId [-PassThru] [-WhatIf] [-Confirm] -``` - -The first parameter set has required `-ResourceGroupName` and `-Name` parameters, which allows the user to explicitly provide the identity properties of the resource that they want to delete. The second parameter has a required `-InputObject` parameter, which allows the user to pipe the result of the `Get-*` and `Set/Update-*` cmdlets to this cmdlet and delete the corresponding resource. The third parameter has a required `-ResourceId` parameter, which allows the user to delete a specific resource by resource id. - -#### C# example - -
Click to expand example -

- -```cs -namespace Microsoft.Azure.Commands.Foo -{ - [Cmdlet(VerbsCommon.Remove, "AzFoo", DefaultParameterSetName = DeleteByNameParameterSet, SupportsShouldProcess = true), OutputType(typeof(bool))] - public class RemoveFooCommand : FooBaseCmdlet - { - private const string DeleteByNameParameterSet = "DeleteByNameParameterSet"; - private const string DeleteByInputObjectParameterSet = "DeleteByInputObjectParameterSet"; - private const string DeleteByResourceIdParameterSet = "DeleteByResourceIdParameterSet"; - - [Parameter(Mandatory = true, ParameterSetName = DeleteByNameParameterSet)] - [ResourceGroupCompleter] - [ValidateNotNullOrEmpty] - public string ResourceGroupName { get; set; } - - [Parameter(Mandatory = true, ParameterSetName = DeleteByNameParameterSet)] - [ValidateNotNullOrEmpty] - public string Name { get; set; } - - [Parameter(Mandatory = true, ValueFromPipeline = true, ParameterSetName = DeleteByInputObjectParameterSet)] - [ValidateNotNull] - public PSFoo InputObject { get; set; } - - [Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, ParameterSetName = DeleteByResourceIdParameterSet)] - [ValidateNotNullOrEmpty] - public string ResourceId { get; set; } - - [Parameter(Mandatory = false)] - public SwitchParameter PassThru { get; set; } - - public override void ExecuteCmdlet() - { - if (this.IsParameterBound(c => c.InputObject)) - { - this.ResourceGroupName = this.InputObject.ResourceGroupName; - this.Name = this.InputObject.Name; - } - - if (this.IsParameterBound(c => c.ResourceId)) - { - var resourceIdentifier = new ResourceIdentifier(this.ResourceId); - this.ResourceGroupName = resourceIdentifier.ResourceGroupName; - this.Name = resourceIdentifier.ResourceName; - } - - if (this.ShouldProcess(this.Name, string.Format("Deleting Foo '{0}' in resource group {0}", this.Name, this.ResourceGroupName))) - { - this.MySDKClient.Foo.Delete(this.ResourceGroupName, this.Name); - if (this.IsPassThru.IsPresent) - { - WriteObject(true); - } - } - } - } -} -``` - -

-
- -### `Set-*` cmdlet - -All top-level resources should have a `Set-*` cmdlet that allows users to update an existing resource _if the API follows `PUT` semantics_. If the API supports `PATCH` semantics, then the cmdlet should be `Update-*` (see below). The user can update an existing resource by providing all identity properties, the resource id, or the object representation of the resource. Similar to the `New-*` cmdlet, properties that are required by the API should be mandatory parameters, and in the case where different combinations of properties are needed depending on a provided value (_e.g._, Windows and Linux VMs have different properties), multiple parameter sets should be used. This cmdlet should implement `SupportsShouldProcess` to allow users to provide the `-WhatIf` parameter and see what the result of executing the cmdlet is without the resource actually being updated. - -#### Parameter Sets - -To enable the scenarios mentioned previously, the cmdlet will need three parameter sets: - -``` -Set-AzFoo -ResourceGroupName -Name -Property1 -Property2 ... [-WhatIf] [-Confirm] - -Set-AzFoo -InputObject [-Property1 ] -[Property2 ] ... [-WhatIf] [-Confirm] - -Set-AzFoo -ResourceId -Property1 -Property2 ... [-WhatIf] [-Confirm] -``` - -The first parameter set has required `-ResourceGroupName` and `-Name` parameters, as well as required property parameters to set their values on the resource. The second parameter has a required `-InputObject` parameter, as well as optional property parameters that override the value of the property on the given object if provided. The third parameter has a required `-ResourceId` parameter, as well as required property parameters to set their values on the resource. - -#### C# example - -
Click to expand example -

- -```cs -namespace Microsoft.Azure.Commands.Foo -{ - [Cmdlet(VerbsCommon.Set, "AzFoo", DefaultParameterSet = SetByNameParameterSet, SupportsShouldProcess = true), OutputType(typeof(PSFoo))] - public class SetFooCommand : FooBaseCmdlet - { - private const string SetByNameParameterSet = "SetByNameParameterSet"; - private const string SetByInputObjectParameterSet = "SetByInputObjectParameterSet"; - private const string SetByResourceIdParameterSet = "SetByResourceIdParameterSet"; - - [Parameter(Mandatory = true, ParameterSetName = SetByNameParameterSet)] - [ResourceGroupCompleter] - [ValidateNotNullOrEmpty] - public string ResourceGroupName { get; set; } - - [Parameter(Mandatory = true, ParameterSetName = SetByNameParameterSet)] - [ValidateNotNullOrEmpty] - public string Name { get; set; } - - [Parameter(Mandatory = true, ValueFromPipeline = true, ParameterSetName = SetByInputObjectParameterSet)] - [ValidateNotNull] - public PSFoo InputObject { get; set; } - - [Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, ParameterSetName = SetByResourceIdParameterSet)] - [ValidateNotNullOrEmpty] - public string ResourceId { get; set; } - - [Parameter(Mandatory = true, ParameterSetName = SetByNameParameterSet)] - [Parameter(Mandatory = true, ParameterSetName = SetByResourceIdParameterSet)] - [Parameter(Mandatory = false, ParameterSetName = SetByInputObjectParameterSet)] - public Type1 Property1 { get; set; } - - [Parameter(Mandatory = true, ParameterSetName = SetByNameParameterSet)] - [Parameter(Mandatory = true, ParameterSetName = SetByResourceIdParameterSet)] - [Parameter(Mandatory = false, ParameterSetName = SetByInputObjectParameterSet)] - public Type2 Property2 { get; set; } - - // Excluding other property parameters - - public override void ExecuteCmdlet() - { - if (this.IsParameterBound(c => c.InputObject)) - { - this.ResourceGroupName = this.InputObject.ResourceGroupName; - this.Name = this.InputObject.Name; - this.Property1 = this.IsParameterBound(c => c.Property1) ? this.Property1 : this.InputObject.Property1; - this.Property2 = this.IsParameterBound(c => c.Property2) ? this.Property2 : this.InputObject.Property2; - ... - } - - if (this.IsParameterBound(c => c.ResourceId)) - { - var resourceIdentifier = new ResourceIdentifier(this.ResourceId); - this.ResourceGroupName = resourceIdentifier.ResourceGroupName; - this.Name = resourceIdentifier.ResourceName; - } - - Foo foo = null; - try - { - foo = this.MySDKClient.Foo.Get(this.ResourceGroupName, this.Name); - } - catch - { - foo = null; - } - - if (foo == null) - { - throw new Exception(string.Format("A Foo with name '{0}' in resource group '{1}' does not exist. Please use New-AzFoo to create a Foo with these properties.", this.Name, this.ResourceGroupName)); - } - - foo.Property1 = this.Property1; - foo.Property2 = this.Property2; - ... - - if (this.ShouldProcess(this.Name, string.Format("Updating Foo '{0}' in resource group '{1}'.", this.Name, this.ResourceGroupName))) - { - var result = new PSFoo(this.MySDKClient.Foo.Update(this.ResourceGroupName, this.Name, foo) - WriteObject(result); - } - } - } -} -``` - -

-
- -### `Update-*` cmdlet - -All top-level resources should have an `Update-*` cmdlet that allows users to update an existing resource _if the API follows `PATCH` semantics_. If the API supports `PUT` semantics, then the cmdlet should be `Set-*` (see above). The user can update an existing resource by providing all identity properties, the resource id, or the object representation of the resource. Similar to the `New-*` cmdlet, properties that are required by the API should be mandatory parameters, and in the case where different combinations of properties are needed depending on a provided value (_e.g._, Windows and Linux VMs have different properties), multiple parameter sets should be used. This cmdlet should implement `SupportsShouldProcess` to allow users to provide the `-WhatIf` parameter and see what the result of executing the cmdlet is without the resource actually being updated. - -_Note_: if the only property that a user is able to update through the `PATCH` API is tags, then this cmdlet should not be implemented. - -#### Parameter Sets - -To enable the scenarios mentioned previously, the cmdlet will need three parameter sets: - -``` -Update-AzFoo -ResourceGroupName -Name [-Property1 ] [-Property2 ] ... [-WhatIf] [-Confirm] - -Update-AzFoo -InputObject [-Property1 ] [-Property2 ] ... [-WhatIf] [-Confirm] - -Update-AzFoo -ResourceId [-Property1 ] [-Property2 ] ... [-WhatIf] [-Confirm] -``` - -The first parameter set has required `-ResourceGroupName` and `-Name` parameters, the second parameter set has a required `-InputObject` parameter, and the third parameter set has a required `-ResourceId` parameter. All three parameter sets have optional property parameters that can be used to override the value of the property set on the retrieved/provided resource. - -#### C# example - -
Click to expand example -

- -```cs -namespace Microsoft.Azure.Commands.Foo -{ - [Cmdlet(VerbsData.Update, "AzFoo", DefaultParameterSet = UpdateByNameParameterSet, SupportsShouldProcess = true), OutputType(typeof(PSFoo))] - public class UpdateFooCommand : FooBaseCmdlet - { - private const string UpdateByNameParameterSet = "UpdateByNameParameterSet"; - private const string UpdateByInputObjectParameterSet = "UpdateByInputObjectParameterSet"; - private const string UpdateByResourceIdParameterSet = "UpdateByResourceIdParameterSet"; - - [Parameter(Mandatory = true, ParameterSetName = UpdateByNameParameterSet)] - [ResourceGroupCompleter] - [ValidateNotNullOrEmpty] - public string ResourceGroupName { get; set; } - - [Parameter(Mandatory = true, ParameterSetName = UpdateByNameParameterSet)] - [ValidateNotNullOrEmpty] - public string Name { get; set; } - - [Parameter(Mandatory = true, ValueFromPipeline = true, ParameterSetName = UpdateByInputObjectParameterSet)] - [ValidateNotNull] - public PSFoo InputObject { get; set; } - - [Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, ParameterSetName = UpdateByResourceIdParameterSet)] - [ValidateNotNullOrEmpty] - public string ResourceId { get; set; } - - [Parameter(Mandatory = false)] - public Type1 Property1 { get; set; } - - [Parameter(Mandatory = false)] - public Type2 Property2 { get; set; } - - // Excluding other property parameters - - public override void ExecuteCmdlet() - { - if (this.IsParameterBound(c => c.InputObject)) - { - this.ResourceGroupName = this.InputObject.ResourceGroupName; - this.Name = this.InputObject.Name; - } - - if (this.IsParameterBound(c => c.ResourceId)) - { - var resourceIdentifier = new ResourceIdentifier(this.ResourceId); - this.ResourceGroupName = resourceIdentifier.ResourceGroupName; - this.Name = resourceIdentifier.ResourceName; - } - - Foo foo = null; - try - { - foo = this.MySDKClient.Foo.Get(this.ResourceGroupName, this.Name); - } - catch - { - foo = null; - } - - if (foo == null) - { - throw new Exception(string.Format("A Foo with name '{0}' in resource group '{1}' does not exist. Please use New-AzFoo to create a Foo with these properties.", this.Name, this.ResourceGroupName)); - } - - foo.Property1 = this.IsParameterBound(c => c.Property1) ? this.Property1 : foo.Property1; - foo.Property2 = this.IsParameterBound(c => c.Property2) ? this.Property2 : foo.Property2; - ... - - if (this.ShouldProcess(this.Name, string.Format("Updating Foo '{0}' in resource group '{1}'.", this.Name, this.ResourceGroupName))) - { - var result = new PSFoo(this.MySDKClient.Foo.Update(this.ResourceGroupName, this.Name, foo) - WriteObject(result); - } - } - } -} -``` - -

-
- -## Child Resources - -### `Get-*` cmdlet - -All child resources should have a `Get-*` cmdlet that allows users to list the child resources under a parent resource, as well as get a specific resource. In addition, users should be able to provide the resource id of the resource they want to get, and the cmdlet will parse the string to get the necessary identity information. - -#### Parameter sets - -To enable the scenarios mentioned previously, the cmdlet will need three parameter sets: - -``` -Get-AzChildFoo -ResourceGroupName -FooName [-Name ] - -Get-AzChildFoo -FooObject [-Name ] - -Get-AzChildFoo -ResourceId -``` - -The first parameter set has mandatory `-ResourceGroupName` and `-FooName` parameters to get the identity information about the parent resource, and then an optional `-Name` parameter to allow the user to either list all child resources contained in the given parent or get the specific child resource. The second parameter set has required `-FooObject` parameter, which can be piped from the parent `Get-*` or `Set/Update-*` cmdlet, and an optional `-Name` parameter. The third parameter set has a required `-ResourceId` parameter, which allows the user to get a specific child resource by resource id. - -#### C# example - -
Click to expand example -

- -```cs -namespace Microsoft.Azure.Commands.Foo -{ - [Cmdlet(VerbsCommon.Get, "AzChildFoo", DefaultParameterSetName = GetByNameParameterSet), OutputType(typeof(PSChildFoo))] - public class GetChildFooCommand : FooBaseCmdlet - { - private const string GetByNameParameterSet = "GetByNameParameterSet"; - private const string GetByParentObjectParameterSet = "GetByParentObjectParameterSet"; - private const string GetByResourceIdParameterSet = "GetByResourceIdParameterSet"; - - [Parameter(Mandatory = true, ParameterSetName = GetByNameParameterSet)] - [ResourceGroupCompleter] - [ValidateNotNullOrEmpty] - public string ResourceGroupName { get; set; } - - [Parameter(Mandatory = true, ParameterSetName = GetByNameParameterSet)] - [ValidateNotNullOrEmpty] - public string FooName { get; set; } - - [Parameter(Mandatory = false, ParameterSetName = GetByNameParameterSet)] - [Parameter(Mandatory = false, ParameterSetName = GetByParentObjectParameterSet)] - [ValidateNotNullOrEmpty] - public string Name { get; set; } - - [Parameter(Mandatory = true, ValueFromPipeline = true, ParameterSetName = GetByParentObjectParameterSet)] - [ValidateNotNull] - public PSFoo FooObject { get; set; } - - [Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, ParameterSetName = GetByResourceIdParameterSet)] - [ValidateNotNullOrEmpty] - public string ResourceId { get; set; } - - public override void ExecuteCmdlet() - { - if (this.IsParameterBound(c => c.ResourceId)) - { - var resourceIdentifier = new ResourceIdentifier(this.ResourceId); - this.ResourceGroupName = resourceIdentifier.ResourceGroupName; - this.FooName = resourceIdentifier.ParentResource - this.Name = resourceIdentifier.ResourceName; - } - - if (this.IsParameterBound(c => c.FooObject)) - { - this.ResourceGroupName = this.FooObject.ResourceGroupName; - this.FooName = this.FooObject.Name; - } - - if (!string.IsNullOrEmpty(this.Name)) - { - var result = new PSChildFoo(this.MySDKClient.ChildFoo.Get(this.ResourceGroupName, this.FooName, this.Name)); - WriteObject(result); - } - else - { - var result = this.MySDKClient.ChildFoo.ListByFoo(this.ResourceGroupName, this.FooName).Select(f => new PSChildFoo(f)); - WriteObject(result, true); - } - } - } -} -``` - -

-
- -### `New-*` cmdlet - -All child resources should have a `New-*` cmdlet that allows users to create a child resource with given properties. Properties that are required by the API should be mandatory parameters, and in the case where different combinations of properties are needed depending on a provided value (_e.g._, Windows and Linux VMs have different properties), multiple parameter sets should be used. This cmdlet should implement `SupportsShouldProcess` to allow users to provide the `-WhatIf` parameter and see what the result of executing the cmdlet is without the resource actually being created. - -_Note_: for long-running operations (~15s or longer), it is advised to add the [`-AsJob`](.\azure-powershell-design-guidelines#asjob-parameter) to your cmdlet. - -#### Parameter sets - -To enable the above scenario, the cmdlet will need two parameter sets: - -``` -New-AzChildFoo -ResourceGroupName -FooName -Name [-Property1 ] [-Property2 ] ... [-WhatIf] [-Confirm] - -New-AzChildFoo -FooObject -Name [-Property1 ] [-Property2 ] ... [-WhatIf] [-Confirm] -``` - -The first parameter set has required `-ResourceGroupName`, `-FooName` and `-Name` parameters to satisfy the identity properties of the child resource, as well as a few optional `-PropertyX` parameters that allows the user to set values for the properties. The second parameter set has a required `-FooObject` parameter that can be piped from the parent resource's `Get-*` and `Set/Update-*` cmdlets. - -#### C# example - -
Click to expand example -

- -```cs -namespace Microsoft.Azure.Commands.Foo -{ - [Cmdlet(VerbsCommon.New, "AzChildFoo", DefaultParameterSetName = CreateByNameParameterSet, SupportsShouldProcess = true), OutputType(typeof(PSChildFoo))] - public class NewChildFooCommand : FooBaseCmdlet - { - private const string CreateByNameParameterSet = "CreateByNameParameterSet"; - private const string CreateByParentObjectParameterSet = "CreateByParentObjectParameterSet"; - - [Parameter(Mandatory = true, ParameterSetName = CreateByNameParameterSet)] - [ResourceGroupCompleter] - [ValidateNotNullOrEmpty] - public string ResourceGroupName { get; set; } - - [Parameter(Mandatory = true, ParameterSetName = CreateByNameParameterSet)] - [ValidateNotNullOrEmpty] - public string FooName { get; set; } - - [Parameter(Mandatory = true, ValueFromPipeline = true, ParameterSetName = CreateByParentObjectParameterSet)] - [ValidateNotNull] - public PSFoo FooObject { get; set; } - - [Parameter(Mandatory = true)] - [ValidateNotNullOrEmpty] - public string Name { get; set; } - - [Parameter(Mandatory = false)] - public Type1 Property1 { get; set; } - - [Parameter(Mandatory = false)] - public Type2 Property2 { get; set; } - - // Excluding other property parameters - - public override void ExecuteCmdlet() - { - if (this.IsParameterBound(c => c.FooObject)) - { - this.ResourceGroupName = this.FooObject.ResourceGroupName; - this.FooName = this.FooObject.FooName; - } - - ChildFoo existingFoo = null; - try - { - existingChildFoo = this.MySDKClient.ChildFoo.Get(this.ResourceGroupName, this.FooName, this.Name); - } - catch - { - existingChildFoo = null; - } - - if (existingChildFoo != null) - { - throw new Exception(string.Format("A ChildFoo with name '{0}' in resource group '{1}' under parent Foo '{2}' already exists. Please use Set/Update-AzChildFoo to update an existing ChildFoo.", this.Name, this.ResourceGroupName, this.FooName)); - } - - existingChildFoo = new ChildFoo() - { - Name = this.Name, - FooName = this.FooName, - ResourceGroupName = this.ResourceGroupName, - Property1 = this.Property1, - Property2 = this.Property2, - ... - } - - if (this.ShouldProcess(this.Name, string.Format("Creating a new ChildFoo in resource group '{0}' under parent Foo '{1}' with name '{2}'.", this.ResourceGroupName, this.FooName, this.Name)) - { - var result = new PSChildFoo(this.MySDKClient.ChildFoo.CreateOrUpdate(existingChildFoo)); - WriteObject(result); - } - } - } -} -``` - -

-
- -### `Remove-*` cmdlet - -All child resources should have a `Remove-*` cmdlet that allows users to delete a specific child resource. The user can delete a child resource by providing all identity properties, the resource id of the child resource, or the object representation of the child resource. This cmdlet should implement `SupportsShouldProcess` to allow users to provide the `-WhatIf` parameter and see what the result of executing the cmdlet is without the child resource actually being deleted. This cmdlet should also implement the [`-PassThru`](.\azure-powershell-design-guidelines.md#returning-no-output) parameter, which allows the user to receive the output when no output would normally be provided. - -#### Parameter sets - -To enable the scenarios mentioned previously, the cmdlet will need four parameter sets: - -``` -Remove-AzChildFoo -ResourceGroupName -FooName -Name [-PassThru] [-WhatIf] [-Confirm] - -Remove-AzChildFoo -FooObject -Name [-PassThru] [-WhatIf] [-Confirm] - -Remove-AzChildFoo -InputObject [-PassThru] [-WhatIf] [-Confirm] - -Remove-AzChildFoo -ResourceId [-PassThru] [-WhatIf] [-Confirm] -``` - -The first parameter set has required `-ResourceGroupName`, `-FooName` and `-Name` parameters, which allows the user to explicitly provide the identity properties of the child resource that they want to delete. The second parameter has a required `-FooObject` parameter, which allows the user to pipe the result of the parent resource's `Get-*` and `Set/Update-*` cmdlets to this cmdlet, as well as a required `-Name` parameter. The third parameter has a required `-InputObject` parameter, which allows the user to pipe the result of the `Get-*` and `Set/Update-*` cmdlets to this cmdlet and delete the corresponding child resource. The fourth parameter has a required `-ResourceId` parameter, which allows the user to delete the specific child resource by resource id. - -#### C# example - -
Click to expand example -

- -```cs -namespace Microsoft.Azure.Commands.Foo -{ - [Cmdlet(VerbsCommon.Remove, "AzChildFoo", DefaultParameterSetName = DeleteByNameParameterSet, SupportsShouldProcess = true), OutputType(typeof(bool))] - public class RemoveChildFooCommand : FooBaseCmdlet - { - private const string DeleteByNameParameterSet = "DeleteByNameParameterSet"; - private const string DeleteByParentObjectParameterSet = "DeleteByParentObjectParameterSet"; - private const string DeleteByInputObjectParameterSet = "DeleteByInputObjectParameterSet"; - private const string DeleteByResourceIdParameterSet = "DeleteByResourceIdParameterSet"; - - [Parameter(Mandatory = true, ParameterSetName = DeleteByNameParameterSet)] - [ResourceGroupCompleter] - [ValidateNotNullOrEmpty] - public string ResourceGroupName { get; set; } - - [Parameter(Mandatory = true, ParameterSetName = DeleteByNameParameterSet)] - [ValidateNotNullOrEmpty] - public string FooName { get; set; } - - [Parameter(Mandatory = true, ParameterSetName = DeleteByNameParameterSet)] - [Parameter(Mandatory = true, ParameterSetName = DeleteByParentObjectParameterSet)] - [ValidateNotNullOrEmpty] - public string Name { get; set; } - - [Parameter(Mandatory = true, ValueFromPipeline = true, ParameterSetName = DeleteByParentObjectParameterSet)] - [ValidateNotNull] - public PSFoo FooObject { get; set; } - - [Parameter(Mandatory = true, ValueFromPipeline = true, ParameterSetName = DeleteByInputObjectParameterSet)] - [ValidateNotNull] - public PSChildFoo InputObject { get; set; } - - [Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, ParameterSetName = DeleteByResourceIdParameterSet)] - [ValidateNotNullOrEmpty] - public string ResourceId { get; set; } - - [Parameter(Mandatory = false)] - public SwitchParameter PassThru { get; set; } - - public override void ExecuteCmdlet() - { - if (this.IsParameterBound(c => c.FooObject)) - { - this.ResourceGroupName = this.FooObject.ResourceGroupName; - this.FooName = this.FooObject.Name; - } - - if (this.IsParameterBound(c => c.InputObject)) - { - this.ResourceGroupName = this.InputObject.ResourceGroupName; - this.FooName = this.InputObject.FooName; - this.Name = this.InputObject.Name; - } - - if (this.IsParameterBound(c => c.ResourceId)) - { - var resourceIdentifier = new ResourceIdentifier(this.ResourceId); - this.ResourceGroupName = resourceIdentifier.ResourceGroupName; - this.FooName = resourceIdentifier.ParentResource; - this.Name = resourceIdentifier.ResourceName; - } - - if (this.ShouldProcess(this.Name, string.Format("Deleting ChildFoo '{0}' in resource group '{1}' under parent Foo '{2}'.", this.Name, this.ResourceGroupName, this.FooName))) - { - this.MySDKClient.ChildFoo.Delete(this.ResourceGroupName, this.FooName, this.Name); - if (this.IsPassThru.IsPresent) - { - WriteObject(true); - } - } - } - } -} -``` - -

-
- -### `Set-*` cmdlet - -All child resources should have a `Set-*` cmdlet that allows users to update an existing child resource _if the API follows `PUT` semantics_. If the API supports `PATCH` semantics, then the cmdlet should be `Update-*` (see below). The user can update an existing child resource by providing all identity properties, the resource id, or the object representation of the child resource. Similar to the `New-*` cmdlet, properties that are required by the API should be mandatory parameters, and in the case where different combinations of properties are needed depending on a provided value (_e.g._, Windows and Linux VMs have different properties), multiple parameter sets should be used. This cmdlet should implement `SupportsShouldProcess` to allow users to provide the `-WhatIf` parameter and see what the result of executing the cmdlet is without the resource actually being updated. - -#### Parameter sets - -To enable the scenarios mentioned previously, the cmdlet will need four parameter sets: - -``` -Set-AzChildFoo -ResourceGroupName -FooName -Name -Property1 -Property2 ... [-WhatIf] [-Confirm] - -Set-AzChildFoo -FooObject -Name -Property1 -Property2 ... [-WhatIf] [-Confirm] - -Set-AzChildFoo -InputObject [-Property1 ] [-Property2 ] ... [-WhatIf] [-Confirm] - -Set-AzChildFoo -ResourceId -Property1 -Property2 ... [-WhatIf] [-Confirm] -``` - -The first parameter set has required `-ResourceGroupName`, `-FooName` and `-Name` parameters, as well as required property parameters to set their values on the child resource. The second parameter set has a required `-FooObject` parameter, which allows the user to pipe the result of the parent resource's `Get-*` and `Set/Update-*` cmdlets to this cmdlet, as well as required property parameters. The third parameter set has a required `-InputObject` parameter, as well as optional property parameters that override the value of the property on the given object if provided. The fourth parameter set has a required `-ResourceIid` parameter, as well as required property parameters to set their values on the child resource. - -#### C# example - -
Click to expand example -

- -```cs -namespace Microsoft.Azure.Commands.Foo -{ - [Cmdlet(VerbsCommon.Set, "AzChildFoo", DefaultParameterSet = SetByNameParameterSet, SupportsShouldProcess = true), OutputType(typeof(PSChildFoo))] - public class SetChildFooCommand : FooBaseCmdlet - { - private const string SetByNameParameterSet = "SetByNameParameterSet"; - private const string SetByParentObjectParameterSet = "SetByParentObjectParameterSet"; - private const string SetByInputObjectParameterSet = "SetByInputObjectParameterSet"; - private const string SetByResourceIdParameterSet = "SetByResourceIdParameterSet"; - - [Parameter(Mandatory = true, ParameterSetName = SetByNameParameterSet)] - [ResourceGroupCompleter] - [ValidateNotNullOrEmpty] - public string ResourceGroupName { get; set; } - - [Parameter(Mandatory = true, ParameterSetName = SetByNameParameterSet) - [ValidateNotNullOrEmpty] - public string FooName { get; set; } - - [Parameter(Mandatory = true, ParameterSetName = SetByNameParameterSet)] - [Parameter(Mandatory = true, ParameterSetName = SetByParentObjectParameterSet)] - [ValidateNotNullOrEmpty] - public string Name { get; set; } - - [Parameter(Mandatory = true, ValueFromPipeline = true, ParameterSetName = SetByParentObjectParameterSet)] - [ValidateNotNull] - public PSFoo FooObject { get; set; } - - [Parameter(Mandatory = true, ValueFromPipeline = true, ParameterSetName = SetByInputObjectParameterSet)] - [ValidateNotNull] - public PSChildFoo InputObject { get; set; } - - [Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, ParameterSetName = SetByResourceIdParameterSet)] - [ValidateNotNullOrEmpty] - public string ResourceId { get; set; } - - [Parameter(Mandatory = true, ParameterSetName = SetByNameParameterSet)] - [Parameter(Mandatory = true, ParameterSetName = SetByParentObjectParameterSet)] - [Parameter(Mandatory = true, ParameterSetName = SetByResourceIdParameterSet)] - [Parameter(Mandatory = false, ParameterSetName = SetByInputObjectParameterSet)] - public Type1 Property1 { get; set; } - - [Parameter(Mandatory = true, ParameterSetName = SetByNameParameterSet)] - [Parameter(Mandatory = true, ParameterSetName = SetByParentObjectParameterSet)] - [Parameter(Mandatory = true, ParameterSetName = SetByResourceIdParameterSet)] - [Parameter(Mandatory = false, ParameterSetName = SetByInputObjectParameterSet)] - public Type2 Property2 { get; set; } - - // Excluding other property parameters - - public override void ExecuteCmdlet() - { - if (this.IsParameterBound(c => c.FooObject)) - { - this.ResourceGroupName = this.FooObject.ResourceGroupName; - this.FooName = this.FooObject.Name; - } - - if (this.IsParameterBound(c => c.InputObject)) - { - this.ResourceGroupName = this.InputObject.ResourceGroupName; - this.FooName = this.InputObject.FooName; - this.Name = this.InputObject.Name; - this.Property1 = this.IsParameterBound(c => c.Property1) ? this.Property1 : this.InputObject.Property1; - this.Property2 = this.IsParameterBound(c => c.Property2) ? this.Property2 : this.InputObject.Property2; - ... - } - - if (this.IsParameterBound(c => c.ResourceId)) - { - var resourceIdentifier = new ResourceIdentifier(this.ResourceId); - this.ResourceGroupName = resourceIdentifier.ResourceGroupName; - this.FooName = resourceIdentifier.ParentResource; - this.Name = resourceIdentifier.ResourceName; - } - - ChildFoo childFoo = null; - try - { - childFoo = this.MySDKClient.ChildFoo.Get(this.ResourceGroupName, this.FooName, this.Name); - } - catch - { - childFoo = null; - } - - if (childFoo == null) - { - throw new Exception(string.Format("A ChildFoo with name '{0}' in resource group '{1}' under parent Foo '{2}' does not exist. Please use New-AzChildFoo to create a ChildFoo with these properties.", this.Name, this.ResourceGroupName, this.FooName)); - } - - childFoo.Property1 = this.Property1; - childFoo.Property2 = this.Property2; - ... - - if (this.ShouldProcess(this.Name, string.Format("Updating Foo '{0}' in resource group '{1}' under parent Foo '{2}'.", this.Name, this.ResourceGroupName, this.FooName))) - { - var result = new PSChildFoo(this.MySDKClient.ChildFoo.Update(this.ResourceGroupName, this.FooName, this.Name, childFoo) - WriteObject(result); - } - } - } -} -``` - -

-
- -### `Update-*` cmdlet - -All child resources should have an `Update-*` cmdlet that allows users to update an existing child resource _if the API follows `PATCH` semantics_. If the API supports `PUT` semantics, then the cmdlet should be `Set-*` (See above). The user can update an existing child resource by providing all identity properties, the resource id, or the object representation of the child resource. Similar to the `New-*` cmdlet, properties that are required by the API should be mandatory parameters, and in the case where different combinations of properties are needed depending on a provided value (_e.g._, Windows and Linux VMs have different properties), multiple parameter sets should be used. This cmdlet should implement `SupportsShouldProcess` to allow users to provide the `-WhatIf` parameter and see what the result of executing the cmdlet is without the resource actually being updated. - -#### Parameter sets - -To enable the scenarios mentioned previously, the cmdlet will need four parameter sets: - -``` -Update-AzChildFoo -ResourceGroupName -FooName -Name [-Property1 ] [-Property2 ] ... [-WhatIf] [-Confirm] - -Update-AzChildFoo -FooObject -Name [-Property1 ] [-Property2 ] ... [-WhatIf] [-Confirm] - -Update-AzChildFoo -InputObject [-Property1 ] [-Property2 ] ... [-WhatIf] [-Confirm] - -Update-AzChildFoo -ResourceId [-Property1 ] [-Property2 ] ... [-WhatIf] [-Confirm] -``` - -The first parameter set has required `-ResourceGroupName`, `-FooName` and `-Name` parameters, the second parameter set has required `-FooObject` and `-Name` parameters, the third parameter set has a required `-InputObject` parameter, and the fourth parameter set has a required `-ResourceId` parameter. All four parameter sets have optional property parameters that can be used to override the value of the property set on the retrieved/provided resource. - -#### C# example - -
Click to expand example -

- -```cs -namespace Microsoft.Azure.Commands.Foo -{ - [Cmdlet(VerbsData.Update, "AzChildFoo", DefaultParameterSet = UpdateByNameParameterSet, SupportsShouldProcess = true), OutputType(typeof(PSChildFoo))] - public class UpdateChildFooCommand : FooBaseCmdlet - { - private const string UpdateByNameParameterSet = "UpdateByNameParameterSet"; - private const string UpdateByParentObjectParameterSet = "UpdateByParentObjectParameterSet"; - private const string UpdateByInputObjectParameterSet = "UpdateByInputObjectParameterSet"; - private const string UpdateByResourceIdParameterSet = "UpdateByResourceIdParameterSet"; - - [Parameter(Mandatory = true, ParameterSetName = UpdateByNameParameterSet)] - [ResourceGroupCompleter] - [ValidateNotNullOrEmpty] - public string ResourceGroupName { get; set; } - - [Parameter(Mandatory = true, ParameterSetName = UpdateByNameParameterSet)] - [ValidateNotNullOrEmpty] - public string FooName { get; set; } - - [Parameter(Mandatory = true, ParameterSetName = UpdateByNameParameterSet)] - [Parameter(Mandatory = true, ParameterSetName = UpdateByParentObjectParameterSet)] - [ValidateNotNullOrEmpty] - public string Name { get; set; } - - [Parameter(Mandatory = true, ValueFromPipeline = true, ParameterSetName = UpdateByParentObjectParameterSet)] - [ValidateNotNull] - public PSFoo FooObject { get; set; } - - [Parameter(Mandatory = true, ValueFromPipeline = true, ParameterSetName = UpdateByInputObjectParameterSet)] - [ValidateNotNull] - public PSFoo InputObject { get; set; } - - [Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, ParameterSetName = UpdateByResourceIdParameterSet)] - [ValidateNotNullOrEmpty] - public string ResourceId { get; set; } - - [Parameter(Mandatory = false)] - public Type1 Property1 { get; set; } - - [Parameter(Mandatory = false)] - public Type2 Property2 { get; set; } - - // Excluding other property parameters - - public override void ExecuteCmdlet() - { - if (this.IsParameterBound(c => c.FooObject)) - { - this.ResourceGroupName = this.FooObject.ResourceGroupName; - this.FooName = this.FooObject.Name; - } - - if (this.IsParameterBound(c => c.InputObject)) - { - this.ResourceGroupName = this.InputObject.ResourceGroupName; - this.FooName = this.InputObject.FooName; - this.Name = this.InputObject.Name; - } - - if (this.IsParameterBound(c => c.ResourceId)) - { - var resourceIdentifier = new ResourceIdentifier(this.ResourceId); - this.ResourceGroupName = resourceIdentifier.ResourceGroupName; - this.FooName = resourceIdentifer.ParentResource; - this.Name = resourceIdentifier.ResourceName; - } - - ChildFoo childFoo = null; - try - { - childFoo = this.MySDKClient.ChildFoo.Get(this.ResourceGroupName, this.FooName, this.Name); - } - catch - { - childFoo = null; - } - - if (childFoo == null) - { - throw new Exception(string.Format("A ChildFoo with name '{0}' in resource group '{1}' under parent Foo '{2}' does not exist. Please use New-AzChildFoo to create a ChildFoo with these properties.", this.Name, this.ResourceGroupName, this.FooName)); - } - - childFoo.Property1 = this.IsParameterBound(c => c.Property1) ? this.Property1 : childFoo.Property1; - childFoo.Property2 = this.IsParameterBound(c => c.Property2) ? this.Property2 : childFoo.Property2; - ... - - if (this.ShouldProcess(this.Name, string.Format("Updating Foo '{0}' in resource group '{1}' under parent Foo '{2}'.", this.Name, this.ResourceGroupName, this.FooName))) - { - var result = new PSChildFoo(this.MySDKClient.ChildFoo.Update(this.ResourceGroupName, this.FooName, this.Name, childFoo) - WriteObject(result); - } - } - } -} -``` - -

-
\ No newline at end of file From e7943e188a001d189aa304bf6e6c660b4817d070 Mon Sep 17 00:00:00 2001 From: Cormac McCarthy Date: Tue, 12 Mar 2019 11:02:45 -0700 Subject: [PATCH 026/141] Fix broken link in README.md for design-guidelines folder --- documentation/development-docs/design-guidelines/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation/development-docs/design-guidelines/README.md b/documentation/development-docs/design-guidelines/README.md index 32715098fcdd..c2ebc0b0f8aa 100644 --- a/documentation/development-docs/design-guidelines/README.md +++ b/documentation/development-docs/design-guidelines/README.md @@ -15,7 +15,7 @@ In this folder, you will find best practices and design guidelines for different - [Module Dependencies](./module-best-practices.md#module-dependencies) - [Parameter Best Practices](./parameter-best-practices.md) - [Parameter Guidelines](./parameter-best-practices.md#parameter-guidelines) - - [Parameter Naming Conventions(./parameter-best-practices.md#parameter-naming-conventions)] + - [Parameter Naming Conventions](./parameter-best-practices.md#parameter-naming-conventions) - [Parameter Types](./parameter-best-practices.md#parameter-types) - [Argument Completers](./parameter-best-practices.md#argument-completers) - [Parameter Set Guidelines](./parameter-best-practices.md#parameter-set-guidelines) @@ -31,4 +31,4 @@ In this folder, you will find best practices and design guidelines for different - [Summary](./piping-best-practices.md#summary) - [`ShouldProcess` and `ConfirmImpact`](./should-process-confirm-impact.md) - [`ShouldProcess`](./should-process-confirm-impact.md#shouldprocess) - - [`ConfirmImpact`](./should-process-confirm-impact.md#confirmimpact) \ No newline at end of file + - [`ConfirmImpact`](./should-process-confirm-impact.md#confirmimpact) From 9e55067840aae4bf2c4aa2321fe5371e9e72dd57 Mon Sep 17 00:00:00 2001 From: cormacpayne Date: Thu, 14 Mar 2019 18:25:54 -0700 Subject: [PATCH 027/141] Resolve review feedback, add document for installing modules, other minor changes --- README.md | 16 +- .../design-guidelines/README.md | 3 +- .../piping-best-practices.md | 195 ++++-------------- .../should-process-confirm-impact.md | 2 + .../examples/get-cmdlet-example.md | 2 + .../examples/new-cmdlet-example.md | 2 + .../examples/remove-cmdlet-example.md | 2 + .../examples/set-cmdlet-example.md | 2 + .../examples/update-cmdlet-example.md | 2 + .../{ => images}/MicrosoftAzure-32px.png | Bin .../MicrosoftPowerShellCore-32px.png | Bin documentation/installing-az-modules.md | 69 +++++++ 12 files changed, 132 insertions(+), 163 deletions(-) rename documentation/{ => images}/MicrosoftAzure-32px.png (100%) rename documentation/{ => images}/MicrosoftPowerShellCore-32px.png (100%) create mode 100644 documentation/installing-az-modules.md diff --git a/README.md b/README.md index 1a165cd3c732..09b16aac05d2 100644 --- a/README.md +++ b/README.md @@ -162,8 +162,8 @@ _This project has adopted the [Microsoft Open Source Code of Conduct][CodeOfCond [Contributing]: CONTRIBUTING.md -[AzureIcon]: documentation/MicrosoftAzure-32px.png -[PowershellIcon]: documentation/MicrosoftPowerShellCore-32px.png +[AzureIcon]: documentation/images/MicrosoftAzure-32px.png +[PowershellIcon]: documentation/images/MicrosoftPowerShellCore-32px.png [AzurePowerShelModules]: documentation/azure-powershell-modules.md [DeveloperGuide]: documentation/development-docs/azure-powershell-developer-guide.md @@ -186,12 +186,12 @@ _This project has adopted the [Microsoft Open Source Code of Conduct][CodeOfCond [MicrosoftAzureDocs]: https://docs.microsoft.com/en-us/azure/ [PowerShellDocs]: https://docs.microsoft.com/en-us/powershell/ -[InstallationGuide]: https://docs.microsoft.com/en-us/powershell/azure/install-azurerm-ps +[InstallationGuide]: https://docs.microsoft.com/en-us/powershell/azure/install-az-ps [GettingStartedGuide]: https://docs.microsoft.com/en-us/powershell/azure/get-started-azureps [PersistedCredentialsGuide]: https://docs.microsoft.com/en-us/powershell/azure/context-persistence -[ConnectAzAccount]: https://docs.microsoft.com/en-us/powershell/module/azurerm.profile/connect-azurermaccount -[GetAzContext]: https://docs.microsoft.com/en-us/powershell/module/azurerm.profile/get-azurermcontext -[GetAzSubscription]: https://docs.microsoft.com/en-us/powershell/module/azurerm.profile/get-azurermsubscription -[SetAzContext]: https://docs.microsoft.com/en-us/powershell/module/azurerm.profile/set-azurermcontext -[SendFeedback]: https://docs.microsoft.com/en-us/powershell/module/azurerm.profile/send-feedback +[ConnectAzAccount]: https://docs.microsoft.com/en-us/powershell/module/az.accounts/connect-azaccount +[GetAzContext]: https://docs.microsoft.com/en-us/powershell/module/az.accounts/get-azcontext +[GetAzSubscription]: https://docs.microsoft.com/en-us/powershell/module/az.accounts/get-azsubscription +[SetAzContext]: https://docs.microsoft.com/en-us/powershell/module/az.accounts/set-azcontext +[SendFeedback]: https://docs.microsoft.com/en-us/powershell/module/az.accounts/send-feedback diff --git a/documentation/development-docs/design-guidelines/README.md b/documentation/development-docs/design-guidelines/README.md index c2ebc0b0f8aa..6611903aecdc 100644 --- a/documentation/development-docs/design-guidelines/README.md +++ b/documentation/development-docs/design-guidelines/README.md @@ -24,11 +24,10 @@ In this folder, you will find best practices and design guidelines for different - [Piping Best Practices](./piping-best-practices.md) - [Piping in PowerShell](./piping-best-practices.md#piping-in-powershell) - [Understanding Piping](./piping-best-practices.md#understanding-piping) - - [More Information](./piping-best-practices.md#more-information) - [Piping in Azure PowerShell](./piping-best-practices.md#piping-in-azure-powershell) - [Using the `-InputObject` Parameter](./piping-best-practices.md#using-the-inputobject-parameter) - [Using the `-ResourceId` Parameter](./piping-best-practices.md#using-the-resourceid-parameter) - - [Summary](./piping-best-practices.md#summary) + - [Full examples](./piping-best-practices.md#full-examples) - [`ShouldProcess` and `ConfirmImpact`](./should-process-confirm-impact.md) - [`ShouldProcess`](./should-process-confirm-impact.md#shouldprocess) - [`ConfirmImpact`](./should-process-confirm-impact.md#confirmimpact) diff --git a/documentation/development-docs/design-guidelines/piping-best-practices.md b/documentation/development-docs/design-guidelines/piping-best-practices.md index 523992dc5504..903ebe489dd8 100644 --- a/documentation/development-docs/design-guidelines/piping-best-practices.md +++ b/documentation/development-docs/design-guidelines/piping-best-practices.md @@ -1,5 +1,7 @@ # Piping Best Practices +_Note_: for the below examples, the string "TopLevelResource" would be replaced with the name of your top-level resource (_e.g._, "VirtualMachine", "VirtualNetwork", "SqlServer"), and the string "ChildResource" would be replaced with the name of your child resource (_e.g._, "VirtualMachineExtension", "VirtualNetworkPeering", "SqlDatabase") + ## Piping in PowerShell ### Understanding Piping @@ -14,99 +16,7 @@ Get-AzEnvironment | Remove-AzEnviornment The cmdlet `Get-AzEnvironment` will return a set of `Environment` objects, and those objects will be individually piped to the `Remove-AzEnvironment` cmdlet, where they will be removed. -When an object is being piped to a cmdlet, PowerShell will first check to see if it can bind that object to a parameter with the same type and has the property `ValueFromPipeline = true`. If this cannot be done, PowerShell will then see if it can bind the properties of the object with parameters that share the same name and have the property `ValueFromPipelineByPropertyName = true`. - -#### `ValueFromPipeline` property - -In this scenario, the object piped to the cmdlet will be bound to a parameter with the same type that has the property `ValueFromPipeline = true`. - -For example, you have a `Remove-AzFoo` cmdlet with the following parameter: - -```cs -[Parameter(ParameterSetName = "ByInputObject", ValueFromPipeline = true)] -public PSFoo InputObject { get; set; } -``` - -If there is a corresponding `Get-AzFoo` cmdlet that returns a `PSFoo` object, the following scenario is enabled: - -```powershell -# --- Piping scenario --- -# Remove an individual PSFoo object -Get-AzFoo -Name "FooName" -ResourceGroupName "RG" | Remove-AzFoo - -# Remove all PSFoo objects -Get-AzFoo | Remove-AzFoo - - -# --- Non-piping scenarios --- -# Remove an individual PSFoo object -$foo = Get-AzFoo -Name "FooName" -ResourceGroupName "RG" -Remove-AzFoo -InputObject $foo - -# Remove all PSFoo objects -Get-AzFoo | ForEach-Object { Remove-AzFoo -InputObject $_ } -``` - -The `PSFoo` object(s) that is returned by the `Get-AzFoo` call will be piped to the `Remove-AzFoo` cmdlet, and becuase that cmdlet has a parameter that accepts a `PSFoo` object by value, PowerShell will bind the object being sent through the pipeline to this `-InputObject` parameter. - -#### `ValueFromPipelineByPropertyName` property - -In this scenario, the properties of the object being piped to the cmdlet will be bound to parameters with the same name that have the property `ValueFromPipelineByPropertyName = true`. - -For example, you have a `Remove-AzFoo` cmdlet with the following parameters: - -```cs -[Parameter(ParameterSetName = "ByPropertyName", ValueFromPipelineByPropertyName = true)] -public string ResourceId { get; set; } -``` - -If there is a corresponding `Get-AzFoo` cmdlet that returns a `PSFoo` object (that has properties `Name` and `ResourceGroupName`), the following scenario is enabled: - -```powershell -# --- Piping scenario --- -# Remove an individual PSFoo object -Get-AzResource -ResourceId | Remove-AzFoo - -# Remove all PSFoo objects -Get-AzResource -ResourceType Foo | Remove-AzFoo - - -# --- Non-piping scenario --- -# Remove an individual PSFoo object -$foo = Get-AzResource -ResourceId -Remove-AzFoo -ResourceId - -# Remove all PSFoo objects -Get-AzFoo | ForEach-Object { Remove-AzFoo -ResourceId } -``` - -The `PSFoo` object(s) that is returned by the `Get-AzFoo` call will be piped to the `Remove-AzFoo` cmdlet, and because that cmdlet has parameters that accept their value from the pipeline by property name, PowerShell will check each of these parameters and see if it can find a corresponding property in the `PSFoo` object that it shares a name with, and bind the value. - -#### Writing to the Pipeline - -To write to the pipeline, use the `WriteObject` method from the `AzurePSCmdlet` class in the `Commands.Common` project. If you are writing **only one** object to the pipeline, then you should use the overload `WriteObject(object sendToPipeline)`, but if you are writing **more than one** objects to the pipeline, you should use the overload `WriteObject(object sendToPipeline, bool enumerateCollection)`. - -If you use the `WriteObject(object sendToPipeline)` overload when writing a collection of objects to the pipeline, this will cause errors in the piping scenario, specifically, it will pipe a collection to the next cmdlet, rather than the individual objects. - -```cs -public override void ExecuteCmdlet() -{ - if (!string.IsNullOrEmpty(this.Name)) - { - // If the Name is not empty, write a single object to the pipeline - var result = client.Foo.List(this.Name); - WriteObject(result); - } - else - { - // If the Name is empty, write a collection of objects to the pipeline - var result = client.Foo.List(); - WriteObject(result, true); - } -} -``` - -### More Information +When an object is being piped to a cmdlet, PowerShell will first check to see if it can bind the input object to a parameter with the same type and has the property `ValueFromPipeline = true`. If no parameters are bound at this point, PowerShell will do the same check for parameters with the `ValueFromPipeline = true` parameter, but it will see if it can convert the input object to the type of the parameter. If no parameters are bound at this point, PowerShell will then see if it can bind the properties of the input object with parameters that share the same name and have the property `ValueFromPipelineByPropertyName = true` that are all in the same parameter set. For more information on piping, see the article [_Understanding pipelines_](https://docs.microsoft.com/en-us/powershell/scripting/learn/understanding-the-powershell-pipeline). @@ -122,7 +32,7 @@ There are two main scenarios that we wish to enable in cmdlets for Azure PowerSh For all resources, `-InputObject` should be implemented for at least the `Remove-*`, `Set-*` and `Update-*` cmdlets (and any other cmdlet where an existing resource is being operated on, such as `Start-*`, `Stop-*`, etc.). The implementation of this will be a new parameter set, like the following: ``` -Remove-AzSampleResource -InputObject [...] [-PassThru] [-WhatIf] [-Confirm] +Remove-AzTopLevelResource -InputObject [...] [-PassThru] [-WhatIf] [-Confirm] ``` For all child resources, the same functionality should be added for the cmdlets above, but for `Get-*` and `New-*` cmdlets, rather than using the `-InputObject` parameter, a separate object parameter should be added to allow piping the object representation of the parent resource. The implementation of this will be a new parameter set, like the following: @@ -132,49 +42,49 @@ Get-AzChildResource -TopLevelResourceObject [...] ``` #### Long explanation -This scenario should be used when piping objects around within the same module. For example, if you have a set of `Get-AzFoo`, `Remove-AzFoo`, and `Set-AzFoo` cmdlets, the `Remove-AzFoo` and `Set-AzFoo` cmdlets should have a parameter set that takes the `-InputObject` parameter of type `PSFoo` so that a user can do the following: +This scenario should be used when piping objects around within the same module. For example, if you have a set of `Get-AzTopLevelResource`, `Remove-AzTopLevelResource`, and `Set-AzTopLevelResource` cmdlets, the `Remove-AzTopLevelResource` and `Set-AzTopLevelResource` cmdlets should have a parameter set that takes the `-InputObject` parameter of type `PSTopLevelResource` so that a user can do the following: ```powershell # --- Piping scenario --- # Setting and removing an individual object -Get-AzFoo -Name "FooName" -ResourceGroupName "RG" | Set-AzFoo @additionalParams -Get-AzFoo -Name "FooName" -ResourceGroupName "RG" | Remove-AzFoo +Get-AzTopLevelResource -ResourceGroupName "MyResourceGroup" -Name "MyTopLevelResource" | Set-AzTopLevelResource @additionalParams +Get-AzTopLevelResource -ResourceGroupName "MyResourceGroup" -Name "MyTopLevelResource" | Remove-AzTopLevelResource # Setting and removing a collection of objects -Get-AzFoo | Set-AzFoo @additionalParams -Get-AzFoo | Remove-AzFoo +Get-AzTopLevelResource | Set-AzTopLevelResource @additionalParams +Get-AzTopLevelResource | Remove-AzTopLevelResource # --- Non-piping scenario --- # Setting and removing an individual object -$foo = Get-AzFoo -Name "FooName" -ResourceGroupName "RG" -Set-AzFoo -InputObject $foo @additionalParams -Remove-AzFoo -InputObject $foo +$resource = Get-AzTopLevelResource -ResourceGroupName "MyResourceGroup" -Name "MyTopLevelResource" +Set-AzTopLevelResource -InputObject $resource @additionalParams +Remove-AzTopLevelResource -InputObject $resource # Setting and removing a collection of objects -Get-AzFoo | ForEach-Object { Set-AzFoo -InputObject $_ @additionalParams } -Get-AzFoo | ForEach-Object { Remove-AzFoo -InputObject $_ } +Get-AzTopLevelResource | ForEach-Object { Set-AzTopLevelResource -InputObject $_ @additionalParams } +Get-AzTopLevelResource | ForEach-Object { Remove-AzTopLevelResource -InputObject $_ } ``` -Another time that this scenario applies is when you have cmdlets for child resources that need information about the parent (top-level) resource. For example you can pipe in the whole parent object to the `New-AzFooBar` and `Get-AzFooBar` cmdlets to get the child resources, and then pipe the child resource object to the `Remove-AzFooBar` and `Set-AzFooBar` cmdlets. +Another time that this scenario applies is when you have cmdlets for child resources that need information about the parent (top-level) resource. For example you can pipe in the whole parent object to the `New-AzChildResource` and `Get-AzChildResource` cmdlets to get the child resources, and then pipe the child resource object to the `Remove-AzChildResource` and `Set-AzChildResource` cmdlets. ```powershell # --- Piping scenario --- # Getting all of child resources from all of the parent resources and removing them -Get-AzFoo | Get-AzFooBar | Remove-AzFooBar +Get-AzTopLevelResource | Get-AzChildResource | Remove-AzChildResource # Getting all of the child resources from all of the parent resources in a resource group and removing them -Get-AzFoo -ResourceGroupName "RG" | Get-AzFooBar | Remove-AzFooBar +Get-AzTopLevelResource -ResourceGroupName "MyResourceGroup" | Get-AzChildResource | Remove-AzChildResource # Getting all of the child resources from a specific parent resource and removing them -Get-AzFoo -ResourceGroupName "RG" -Name "FooName" | Get-AzFooBar | Remove-AzFooBar +Get-AzTopLevelResource -ResourceGroupName "MyResourceGroup" -Name "MyTopLevelResource" | Get-AzChildResource | Remove-AzChildResource # --- Non-piping scenario --- # Getting all of the child resources from a specific parent resource and removing them -$foo = Get-AzFoo -ResourceGroupName "RG" -Name "FooName" -$fooBar = Get-AzFooBar -InputObject $foo -Remove-AzFooBar -InputObject $fooBar +$resource = Get-AzTopLevelResource -ResourceGroupName "MyResourceGroup" -Name "MyTopLevelResource" +$childResource = Get-AzChildResource -InputObject $resource +Remove-AzChildResource -InputObject $childResource ``` ### Using the `-ResourceId` Parameter @@ -183,65 +93,44 @@ Remove-AzFooBar -InputObject $fooBar For all resources, `-ResourceId` should be implemented for the `Remove-*`, `Set-*` and `Update-*` cmdlets (and any other cmdlet where an existing resource is being operated on, such as `Start-*`, `Stop-*`, etc.). The implementation of this will be a new parameter set, like the following: ``` -RemoveAzSampleResource -ResourceId [...] [-PassThru] [-WhatIf] [-Confirm] +Remove-AzTopLevelResource -ResourceId [...] [-PassThru] [-WhatIf] [-Confirm] ``` #### Long explanation -In this scenario, we are using the generic cmdlets found in the `Az.Resources` module. These cmdlets, `Find-AzResource` and `Get-AzResource`, return a `PSCustomObject` that has a `ResourceId` property, which is the unique identifier for the given resource. Since this identifier can parsed to get the name and resource group name for a top-level resource, we can create a parameter set that has a `ResourceId` parameter that accepts its value from the pipeline by property name, allowing us to accept piping from these generic cmdlets. +In this scenario, we are using the generic cmdlet, `Get-AzResource`, found in the `Az.Resources` module. This cmdlet returns a `PSResource` that has a `ResourceId` property, which is the unique identifier for the given resource. Since this identifier can parsed to get the name and resource group name for a top-level resource (as well as the child resource name), we can create a parameter set that has a `-ResourceId` parameter that accepts its value from the pipeline by property name, allowing us to accept piping from these generic cmdlets. ```powershell # --- Piping scenario --- -# Remove all Foo objects in the current subscription -Get-AzResource -ResourceType Microsoft.Foo/foo | Remove-AzFoo +# Remove all TopLevelResource objects in the current subscription +Get-AzResource -ResourceType "Microsoft.SomeProvider/topLevelResource" | Remove-AzTopLevelResource -# Remove all Foo objects in a given resource group -Get-AzResource -ResourceType Microsoft.Foo/foo -ResourceGroupEquals "RG" | Remove-AzFoo +# Remove all TopLevelResource objects in a given resource group +Get-AzResource -ResourceType "Microsoft.SomeProvider/topLevelResource" -ResourceGroupEquals "MyResourceGroup" | Remove-AzTopLevelResource -# Remove a specific Foo object -Get-AzResource -ResourceGroupEquals "RG" -ResourceNameEquals "FooName" | Remove-AzFoo +# Remove a specific TopLevelResource object +Get-AzResource -ResourceType "Microsoft.SomeProvider/topLevelResource" -ResourceGroupEquals "MyResourceGroup" -Name "MyTopLevelResource" | Remove-AzTopLevelResource # -- Non-piping scenario --- -# Removing all Foo objects in the current subscription -Get-AzResource -ResourceType Microsoft.Foo/foo | ForEach-Object { Remove-AzFoo -ResourceId $_.ResourceId } +# Removing all TopLevelResource objects in the current subscription +Get-AzResource -ResourceType "Microsoft.SomeProvider/topLevelResource" | ForEach-Object { Remove-AzTopLevelResource -ResourceId $_.ResourceId } -# Remove all Foo objects in a given resource group -Get-AzResource -ResourceType Microsoft.Foo/foo -ResourceGroupEquals "RG" | ForEach-Object { Remove-AzFoo -ResourceId $_.ResourceId } +# Remove all TopLevelResource objects in a given resource group +Get-AzResource -ResourceType "Microsoft.SomeProvider/topLevelResource" -ResourceGroupEquals "MyResourceGroup" | ForEach-Object { Remove-AzTopLevelResource -ResourceId $_.ResourceId } -# Remove a specific Foo object -Get-AzResource -ResourceGroupEquals "RG" -ResourceNameEquals "FooName" | ForEach-Object { Remove-AzFoo -ResourceId $_.ResourceId } +# Remove a specific TopLevelResource object +Get-AzResource -ResourceType "Microsoft.SomeProvider/topLevelResource" -ResourceGroupEquals "MyResourceGroup" -ResourceNameEquals "MyTopLevelResource" | ForEach-Object { Remove-AzTopLevelResource -ResourceId $_.ResourceId } ``` To implement this scenario, please see the [`ResourceIdentifier`](https://github.com/Azure/azure-powershell-common/blob/52fc157798d0fdd83f20755106e131aec1689ceb/src/ResourceManager/Version2016_09_01/Utilities/Models/ResourceIdentifier.cs) class in the `ResourceManager` project. This class will allow you to create a `ResourceIdentifier` object that accepts a `ResourceId` string in its constructor and has properties `ResourceName`, `ResourceGroupName`, and others. -### Summary -For all `Remove-*`, `Set-*` and `Update-*` cmdlets (and any other cmdlet where an existing resource is being operated on, such as `Start-*`, `Stop-*`, etc.), you will have three parameter sets (and potentially a multiple of three if you have initially have multiple parameter sets): - -``` -Remove-AzSampleResource -ResourceGroupName -Name [...] [-PassThru] [-WhatIf] [-Confirm] - -Remove-AzSampleResource -InputObject [...] [-PassThru] [-WhatIf] [-Confirm] +### Full examples -Remove-AzSampleResource -ResourceId [...] [-PassThru] [-WhatIf] [-Confirm] -``` - -For child resources, there will be the following three parameter sets for `Remove-*`: - -``` -Remove-AzChildResource -ResourceGroupName -TopLevelResourceName -Name [...] [-PassThru] [-WhatIf] [-Confirm] - -Remove-AzChildResource -InputObject [...] [-PassThru] [-WhatIf] [-Confirm] - -Remove-AzChildResource -ResourceId [...] [-PassThru] [-WhatIf] [-Confirm] -``` - -For all child resources, `Get-*` cmdlets will also the following three parameter sets: - -``` -Get-AzChildResource -ResourceGroupName -TopLevelResourceName [-Name ] [...] - -Get-AzChildResource -TopLevelResourceObject [...] +The following cmdlet examples containing these piping scenarios can be found in [this folder](../examples): -Get-AzChildResource -ResourceId [...] -``` \ No newline at end of file +- [`Get-*` cmdlet](../examples/get-cmdlet-example.md) +- [`New-*` cmdlet](../examples/new-cmdlet-example.md) +- [`Remove-*` cmdlet](../examples/remove-cmdlet-example.md) +- [`Set-*` cmdlet](../examples/set-cmdlet-example.md) +- [`Update-*` cmdlet](../examples/update-cmdlet-example.md) \ No newline at end of file diff --git a/documentation/development-docs/design-guidelines/should-process-confirm-impact.md b/documentation/development-docs/design-guidelines/should-process-confirm-impact.md index 9b169b60eb45..e5c034c93966 100644 --- a/documentation/development-docs/design-guidelines/should-process-confirm-impact.md +++ b/documentation/development-docs/design-guidelines/should-process-confirm-impact.md @@ -24,6 +24,8 @@ public class RemoveFoo } ``` +Please see the example cmdlets found in our [`examples`](../examples) folder for additional implementations of `ShouldProcess`. + By default, `ShouldProcess` interacts with the cmdlet `ConfirmImpact` and the user's `$ConfirmPreference` setting to decide whether to prompt the user before continuing cmdlet processing. The `$ConfirmPreference` determines the level at which confirmation automatically occurs, and no prompt is shown. If the `ConfirmImpact` specified in a cmdlet is at or below the level of `$ConfirmPreference`, then processing occurs automatically without displaying a prompt. Since both `ConfirmImpact` and `$ConfirmPreference` are set by default to `Medium`, this means that, by default, no confirmation prompt is shown and the cmdlet executes normally. PowerShell has several tools that allow users to explore and control what happens during execution of cmdlets, and this change in implementation allows them to use these tools. diff --git a/documentation/development-docs/examples/get-cmdlet-example.md b/documentation/development-docs/examples/get-cmdlet-example.md index 5ed9ea5a3870..2a68b2aeab6c 100644 --- a/documentation/development-docs/examples/get-cmdlet-example.md +++ b/documentation/development-docs/examples/get-cmdlet-example.md @@ -1,5 +1,7 @@ ## `Get-*` cmdlet example +_Note_: for the below examples, the string "TopLevelResource" would be replaced with the name of your top-level resource (_e.g._, "VirtualMachine", "VirtualNetwork", "SqlServer"), and the string "ChildResource" would be replaced with the name of your child resource (_e.g._, "VirtualMachineExtension", "VirtualNetworkPeering", "SqlDatabase") + ### Top-level resource All top-level resources should have a `Get-*` cmdlet that allows users to list the resources in their subscription or a resource group, as well as get a specific resource. In addition, users should be able to provide the resource id of the resource they want to get, and the cmdlet will parse the string to get the necessary identity information. diff --git a/documentation/development-docs/examples/new-cmdlet-example.md b/documentation/development-docs/examples/new-cmdlet-example.md index 8a241b3f0e98..dad8d79a8302 100644 --- a/documentation/development-docs/examples/new-cmdlet-example.md +++ b/documentation/development-docs/examples/new-cmdlet-example.md @@ -1,5 +1,7 @@ ## `New-*` cmdlet example +_Note_: for the below examples, the string "TopLevelResource" would be replaced with the name of your top-level resource (_e.g._, "VirtualMachine", "VirtualNetwork", "SqlServer"), and the string "ChildResource" would be replaced with the name of your child resource (_e.g._, "VirtualMachineExtension", "VirtualNetworkPeering", "SqlDatabase") + ### Top-level resource All top-level resources should have a `New-*` cmdlet that allows users to create a resource with given properties. Properties that are required by the API should be mandatory parameters, and in the case where different combinations of properties are needed depending on a provided value (_e.g._, Windows and Linux VMs have different properties), multiple parameter sets should be used. This cmdlet should implement `SupportsShouldProcess` to allow users to provide the `-WhatIf` parameter and see what the result of executing the cmdlet is without the resource actually being created. diff --git a/documentation/development-docs/examples/remove-cmdlet-example.md b/documentation/development-docs/examples/remove-cmdlet-example.md index 17ae2220a57f..27e346ac8f1c 100644 --- a/documentation/development-docs/examples/remove-cmdlet-example.md +++ b/documentation/development-docs/examples/remove-cmdlet-example.md @@ -1,5 +1,7 @@ ## `Remove-*` cmdlet example +_Note_: for the below examples, the string "TopLevelResource" would be replaced with the name of your top-level resource (_e.g._, "VirtualMachine", "VirtualNetwork", "SqlServer"), and the string "ChildResource" would be replaced with the name of your child resource (_e.g._, "VirtualMachineExtension", "VirtualNetworkPeering", "SqlDatabase") + ### Top-level resource All top-level resources should have a `Remove-*` cmdlet that allows users to delete a specific resource. The user can delete a resource by providing all identity properties, the resource id, or the object representation of the resource. This cmdlet should implement `SupportsShouldProcess` to allow users to provide the `-WhatIf` parameter and see what the result of executing the cmdlet is without the resource actually being deleted. This cmdlet should also implement the [`-PassThru`](../design-guidelines/cmdlet-best-practices.md#returning-no-output) parameter, which allows the user to receive output when no output would normally be provided. diff --git a/documentation/development-docs/examples/set-cmdlet-example.md b/documentation/development-docs/examples/set-cmdlet-example.md index 22ef6e73a82d..844f5581ff48 100644 --- a/documentation/development-docs/examples/set-cmdlet-example.md +++ b/documentation/development-docs/examples/set-cmdlet-example.md @@ -1,5 +1,7 @@ ## `Set-*` cmdlet example +_Note_: for the below examples, the string "TopLevelResource" would be replaced with the name of your top-level resource (_e.g._, "VirtualMachine", "VirtualNetwork", "SqlServer"), and the string "ChildResource" would be replaced with the name of your child resource (_e.g._, "VirtualMachineExtension", "VirtualNetworkPeering", "SqlDatabase") + ### Top-level resource All top-level resources should have a `Set-*` cmdlet that allows users to update an existing resource _if the API follows `PUT` semantics_. If the API supports `PATCH` semantics, then the cmdlet should be `Update-*` (see below). The user can update an existing resource by providing all identity properties, the resource id, or the object representation of the resource. Similar to the `New-*` cmdlet, properties that are required by the API should be mandatory parameters, and in the case where different combinations of properties are needed depending on a provided value (_e.g._, Windows and Linux VMs have different properties), multiple parameter sets should be used. This cmdlet should implement `SupportsShouldProcess` to allow users to provide the `-WhatIf` parameter and see what the result of executing the cmdlet is without the resource actually being updated. diff --git a/documentation/development-docs/examples/update-cmdlet-example.md b/documentation/development-docs/examples/update-cmdlet-example.md index b17029ee1d93..c36ce3f92bf0 100644 --- a/documentation/development-docs/examples/update-cmdlet-example.md +++ b/documentation/development-docs/examples/update-cmdlet-example.md @@ -1,5 +1,7 @@ ## `Update-*` cmdlet example +_Note_: for the below examples, the string "TopLevelResource" would be replaced with the name of your top-level resource (_e.g._, "VirtualMachine", "VirtualNetwork", "SqlServer"), and the string "ChildResource" would be replaced with the name of your child resource (_e.g._, "VirtualMachineExtension", "VirtualNetworkPeering", "SqlDatabase") + ### Top-level resource All top-level resources should have an `Update-*` cmdlet that allows users to update an existing resource _if the API follows `PATCH` semantics_. If the API supports `PUT` semantics, then the cmdlet should be `Set-*` (see above). The user can update an existing resource by providing all identity properties, the resource id, or the object representation of the resource. Similar to the `New-*` cmdlet, properties that are required by the API should be mandatory parameters, and in the case where different combinations of properties are needed depending on a provided value (_e.g._, Windows and Linux VMs have different properties), multiple parameter sets should be used. This cmdlet should implement `SupportsShouldProcess` to allow users to provide the `-WhatIf` parameter and see what the result of executing the cmdlet is without the resource actually being updated. diff --git a/documentation/MicrosoftAzure-32px.png b/documentation/images/MicrosoftAzure-32px.png similarity index 100% rename from documentation/MicrosoftAzure-32px.png rename to documentation/images/MicrosoftAzure-32px.png diff --git a/documentation/MicrosoftPowerShellCore-32px.png b/documentation/images/MicrosoftPowerShellCore-32px.png similarity index 100% rename from documentation/MicrosoftPowerShellCore-32px.png rename to documentation/images/MicrosoftPowerShellCore-32px.png diff --git a/documentation/installing-az-modules.md b/documentation/installing-az-modules.md new file mode 100644 index 000000000000..ac46edb1d475 --- /dev/null +++ b/documentation/installing-az-modules.md @@ -0,0 +1,69 @@ +# Installing `Az` Modules + +## Overview + +By default, modules are installed from the [PowerShell Gallery](https://www.powershellgallery.com/), which is the central repository for accessing published PowerShell modules (equivalent to NuGet for .NET, npm for JavaScript, etc.). With the [`Install-Module`](https://docs.microsoft.com/en-us/powershell/module/powershellget/install-module) cmdlet, users can specify which modules they want to install; in addition, users can provide the `-Repository` parameter to specify which repository they want to install modules from (if this parameter isn't provided, then the cmdlet defaults to using PowerShell Gallery). + +## Removing Modules + +In some cases, existing `Az` modules will need to be removed before a new version can be installed. Since the `Uninstall-Module` cmdlet does not currently remove modules and their dependencies, users will need to manually delete the folders where the modules were installed to. + +To figure out if you have any `Az` modules currently installed, as well as the location they are found, use the following command: + +``` +Get-Module -Name Az* -ListAvailable +``` + +This command will list all modules installed on your machine that are found in your `$env:PSModulePath`. Deleting the corresponding `Az.*` folders in the file explorer will remove these modules from your machine. + +## Registering Repositories + +In some cases, users will need to install modules from a different repository than the PowerShell Gallery -- this can be a new endpoint, or even a local folder containing `.nupkg` files. In either case, the [`Register-PSRepository`](https://docs.microsoft.com/en-us/powershell/module/powershellget/register-psrepository) cmdlet should be used to create a new local repository that can be used to install modules from. + +Below is an example of registering a new repository from a local folder containing `.nupkg` files: + +``` +Register-PSRepository -Name "{{repository_name}}" -SourceLocation "{{folder_with_nupkg_files}}" -PackageManagementProvider NuGet -Installation +``` + +## Installing Modules + +To install a module from the PowerShell Gallery, run the following command: + +``` +Install-Module -Name "{{module_name}}" +``` + +To install a module from a specific repository, run the following command: + +``` +Install-Module -Name "{{module_name}}" -Repository "{{repository_name}}" +``` + +### Installing `Az` Modules + +To install the latest stable `Az` modules from the PowerShell Gallery, run the following command: + +``` +Install-Module -Name Az +``` + +To install a specific `Az` module from the PowerShell Gallery, run the following command: + +``` +Install-Module -Name Az.{{service}} +``` + +To install a preview version of a specific `Az` module, run the following command: + +``` +Install-Module -Name Az.{{service}} -RequiredVersion {{version}} -AllowPrelease +``` + +_Note_: to install preview versions of modules, version 1.6.0 or greater of the `PowerShellGet` module will be needed. Users can run the following command to get the latest version of this module: + +``` +Install-Module -Name PowerShellGet -Force +``` + +Full documentation around installing the `Az` module can be found in the [_Install the Azure PowerShell module_](https://docs.microsoft.com/en-us/powershell/azure/install-az-ps) article. \ No newline at end of file From e6235773c2910055db5a27b5f4139fbfe7dcb550 Mon Sep 17 00:00:00 2001 From: Devesh Guha Oleti Muni Date: Fri, 15 Mar 2019 15:20:58 -0700 Subject: [PATCH 028/141] Add DeploymentManager module --- ...ands.DeploymentManager.Test.Netcore.csproj | 47 + .../Commands.DeploymentManager.Test.csproj | 21 + .../MSSharedLibKey.snk | Bin 0 -> 160 bytes .../Properties/AssemblyInfo.cs | 37 + .../ScenarioTests/CreateRollout.json | 34 + .../CreateRollout_FailureRollout.json | 29 + .../DeploymentManagerController.cs | 112 + .../ScenarioTests/DeploymentManagerTests.cs | 40 + .../ScenarioTests/DeploymentManagerTests.ps1 | 489 ++ .../EndToEndFunctionalTests.json | 6251 +++++++++++++++++ .../packages.config | 27 + .../Az.DeploymentManager.psd1 | 155 + .../AzureRM.DeploymentManager.psd1 | 155 + .../Commands.DeploymentManager/ChangeLog.md | 29 + .../Client/DeploymentManagerClient.cs | 312 + .../Commands.DeploymentManager.NetCore.csproj | 57 + .../Commands.DeploymentManager.csproj | 17 + .../Commands/DeploymentManagerBaseCmdlet.cs | 65 + .../Commands/GetArtifactSource.cs | 91 + .../Commands/GetRollout.cs | 96 + .../Commands/GetService.cs | 167 + .../Commands/GetServiceTopology.cs | 91 + .../Commands/GetServiceUnit.cs | 251 + .../Commands/GetStep.cs | 91 + .../Commands/NewArtifactSource.cs | 112 + .../Commands/NewService.cs | 133 + .../Commands/NewServiceTopology.cs | 86 + .../Commands/NewServiceUnit.cs | 227 + .../Commands/NewStep.cs | 106 + .../Commands/RemoveArtifactSource.cs | 120 + .../Commands/RemoveRollout.cs | 118 + .../Commands/RemoveService.cs | 187 + .../Commands/RemoveServiceTopology.cs | 125 + .../Commands/RemoveServiceUnit.cs | 261 + .../Commands/RemoveStep.cs | 120 + .../Commands/RestartRollout.cs | 113 + .../Commands/RolloutCmdletBase.cs | 352 + .../Commands/SetArtifactSource.cs | 47 + .../Commands/SetService.cs | 47 + .../Commands/SetServiceTopology.cs | 46 + .../Commands/SetServiceUnit.cs | 46 + .../Commands/SetStep.cs | 47 + .../Commands/StopRollout.cs | 112 + .../MSSharedLibKey.snk | Bin 0 -> 160 bytes .../Messages.Designer.cs | 423 ++ .../Commands.DeploymentManager/Messages.resx | 240 + .../Models/ArtifactSource/PSArtifactSource.cs | 68 + .../Models/ArtifactSource/PSAuthentication.cs | 29 + .../ArtifactSource/PSSasAuthentication.cs | 39 + .../Models/PSIdentity.cs | 53 + .../Models/Rollout/PSBaseOperationInfo.cs | 58 + .../Models/Rollout/PSMessage.cs | 47 + .../Models/Rollout/PSResource.cs | 61 + .../Models/Rollout/PSResourceOperation.cs | 91 + .../Models/Rollout/PSRollout.cs | 122 + .../Models/Rollout/PSRolloutOperationInfo.cs | 43 + .../Models/Rollout/PSRolloutStep.cs | 90 + .../Models/Rollout/PSService.cs | 71 + .../Models/Rollout/PSServiceUnit.cs | 114 + .../Models/Rollout/PSStepOperationInfo.cs | 43 + .../ServiceTopology/PSServiceResource.cs | 69 + .../PSServiceTopologyResource.cs | 56 + .../ServiceTopology/PSServiceUnitResource.cs | 111 + .../Models/Steps/PSStepProperties.cs | 31 + .../Models/Steps/PSStepResource.cs | 59 + .../Models/Steps/PSWaitStepProperties.cs | 37 + .../Properties/AssemblyInfo.cs | 36 + .../Utilities/EnumerationUtilities.cs | 48 + .../Utilities/StringUtilities.cs | 168 + .../help/AzureRM.DeploymentManager.md | 85 + ...-AzureRmDeploymentManagerArtifactSource.md | 158 + .../Get-AzureRmDeploymentManagerRollout.md | 181 + .../Get-AzureRmDeploymentManagerService.md | 215 + ...AzureRmDeploymentManagerServiceTopology.md | 158 + ...Get-AzureRmDeploymentManagerServiceUnit.md | 273 + .../help/Get-AzureRmDeploymentManagerStep.md | 156 + ...rosoft.Azure.Commands.DeploymentManager.md | 72 + ...-AzureRmDeploymentManagerArtifactSource.md | 194 + .../New-AzureRmDeploymentManagerService.md | 252 + ...AzureRmDeploymentManagerServiceTopology.md | 186 + ...New-AzureRmDeploymentManagerServiceUnit.md | 406 ++ .../help/New-AzureRmDeploymentManagerStep.md | 174 + ...-AzureRmDeploymentManagerArtifactSource.md | 217 + .../Remove-AzureRmDeploymentManagerRollout.md | 217 + .../Remove-AzureRmDeploymentManagerService.md | 275 + ...AzureRmDeploymentManagerServiceTopology.md | 218 + ...ove-AzureRmDeploymentManagerServiceUnit.md | 335 + .../Remove-AzureRmDeploymentManagerStep.md | 213 + ...Restart-AzureRmDeploymentManagerRollout.md | 203 + ...-AzureRmDeploymentManagerArtifactSource.md | 115 + .../Set-AzureRmDeploymentManagerService.md | 115 + ...AzureRmDeploymentManagerServiceTopology.md | 115 + ...Set-AzureRmDeploymentManagerServiceUnit.md | 115 + .../help/Set-AzureRmDeploymentManagerStep.md | 111 + .../Stop-AzureRmDeploymentManagerRollout.md | 203 + .../packages.config | 7 + src/DeploymentManager/DeploymentManager.sln | 31 + src/DeploymentManager/NuGet.Config | 6 + .../documentation/current-breaking-changes.md | 41 + .../upcoming-breaking-changes.md | 28 + 100 files changed, 18351 insertions(+) create mode 100644 src/DeploymentManager/Commands.DeploymentManager.Test/Commands.DeploymentManager.Test.Netcore.csproj create mode 100644 src/DeploymentManager/Commands.DeploymentManager.Test/Commands.DeploymentManager.Test.csproj create mode 100644 src/DeploymentManager/Commands.DeploymentManager.Test/MSSharedLibKey.snk create mode 100644 src/DeploymentManager/Commands.DeploymentManager.Test/Properties/AssemblyInfo.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager.Test/ScenarioTests/CreateRollout.json create mode 100644 src/DeploymentManager/Commands.DeploymentManager.Test/ScenarioTests/CreateRollout_FailureRollout.json create mode 100644 src/DeploymentManager/Commands.DeploymentManager.Test/ScenarioTests/DeploymentManagerController.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager.Test/ScenarioTests/DeploymentManagerTests.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager.Test/ScenarioTests/DeploymentManagerTests.ps1 create mode 100644 src/DeploymentManager/Commands.DeploymentManager.Test/SessionRecords/Microsoft.Azure.Commands.DeploymentManager.Test.ScenarioTests.DeploymentManagerTests/EndToEndFunctionalTests.json create mode 100644 src/DeploymentManager/Commands.DeploymentManager.Test/packages.config create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Az.DeploymentManager.psd1 create mode 100644 src/DeploymentManager/Commands.DeploymentManager/AzureRM.DeploymentManager.psd1 create mode 100644 src/DeploymentManager/Commands.DeploymentManager/ChangeLog.md create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Client/DeploymentManagerClient.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Commands.DeploymentManager.NetCore.csproj create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Commands.DeploymentManager.csproj create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Commands/DeploymentManagerBaseCmdlet.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Commands/GetArtifactSource.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Commands/GetRollout.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Commands/GetService.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Commands/GetServiceTopology.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Commands/GetServiceUnit.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Commands/GetStep.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Commands/NewArtifactSource.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Commands/NewService.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Commands/NewServiceTopology.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Commands/NewServiceUnit.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Commands/NewStep.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveArtifactSource.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveRollout.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveService.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveServiceTopology.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveServiceUnit.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveStep.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Commands/RestartRollout.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Commands/RolloutCmdletBase.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Commands/SetArtifactSource.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Commands/SetService.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Commands/SetServiceTopology.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Commands/SetServiceUnit.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Commands/SetStep.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Commands/StopRollout.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/MSSharedLibKey.snk create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Messages.Designer.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Messages.resx create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Models/ArtifactSource/PSArtifactSource.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Models/ArtifactSource/PSAuthentication.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Models/ArtifactSource/PSSasAuthentication.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Models/PSIdentity.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSBaseOperationInfo.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSMessage.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSResource.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSResourceOperation.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSRollout.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSRolloutOperationInfo.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSRolloutStep.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSService.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSServiceUnit.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSStepOperationInfo.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Models/ServiceTopology/PSServiceResource.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Models/ServiceTopology/PSServiceTopologyResource.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Models/ServiceTopology/PSServiceUnitResource.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Models/Steps/PSStepProperties.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Models/Steps/PSStepResource.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Models/Steps/PSWaitStepProperties.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Properties/AssemblyInfo.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Utilities/EnumerationUtilities.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/Utilities/StringUtilities.cs create mode 100644 src/DeploymentManager/Commands.DeploymentManager/help/AzureRM.DeploymentManager.md create mode 100644 src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerArtifactSource.md create mode 100644 src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerRollout.md create mode 100644 src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerService.md create mode 100644 src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerServiceTopology.md create mode 100644 src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerServiceUnit.md create mode 100644 src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerStep.md create mode 100644 src/DeploymentManager/Commands.DeploymentManager/help/Microsoft.Azure.Commands.DeploymentManager.md create mode 100644 src/DeploymentManager/Commands.DeploymentManager/help/New-AzureRmDeploymentManagerArtifactSource.md create mode 100644 src/DeploymentManager/Commands.DeploymentManager/help/New-AzureRmDeploymentManagerService.md create mode 100644 src/DeploymentManager/Commands.DeploymentManager/help/New-AzureRmDeploymentManagerServiceTopology.md create mode 100644 src/DeploymentManager/Commands.DeploymentManager/help/New-AzureRmDeploymentManagerServiceUnit.md create mode 100644 src/DeploymentManager/Commands.DeploymentManager/help/New-AzureRmDeploymentManagerStep.md create mode 100644 src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerArtifactSource.md create mode 100644 src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerRollout.md create mode 100644 src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerService.md create mode 100644 src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerServiceTopology.md create mode 100644 src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerServiceUnit.md create mode 100644 src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerStep.md create mode 100644 src/DeploymentManager/Commands.DeploymentManager/help/Restart-AzureRmDeploymentManagerRollout.md create mode 100644 src/DeploymentManager/Commands.DeploymentManager/help/Set-AzureRmDeploymentManagerArtifactSource.md create mode 100644 src/DeploymentManager/Commands.DeploymentManager/help/Set-AzureRmDeploymentManagerService.md create mode 100644 src/DeploymentManager/Commands.DeploymentManager/help/Set-AzureRmDeploymentManagerServiceTopology.md create mode 100644 src/DeploymentManager/Commands.DeploymentManager/help/Set-AzureRmDeploymentManagerServiceUnit.md create mode 100644 src/DeploymentManager/Commands.DeploymentManager/help/Set-AzureRmDeploymentManagerStep.md create mode 100644 src/DeploymentManager/Commands.DeploymentManager/help/Stop-AzureRmDeploymentManagerRollout.md create mode 100644 src/DeploymentManager/Commands.DeploymentManager/packages.config create mode 100644 src/DeploymentManager/DeploymentManager.sln create mode 100644 src/DeploymentManager/NuGet.Config create mode 100644 src/DeploymentManager/documentation/current-breaking-changes.md create mode 100644 src/DeploymentManager/documentation/upcoming-breaking-changes.md diff --git a/src/DeploymentManager/Commands.DeploymentManager.Test/Commands.DeploymentManager.Test.Netcore.csproj b/src/DeploymentManager/Commands.DeploymentManager.Test/Commands.DeploymentManager.Test.Netcore.csproj new file mode 100644 index 000000000000..295d7c82544b --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager.Test/Commands.DeploymentManager.Test.Netcore.csproj @@ -0,0 +1,47 @@ + + + + + + netcoreapp2.1;netcoreapp2.0;net472 + Microsoft.Azure.Commands.RedisCache.Test + Microsoft.Azure.Commands.RedisCache.Test + false + true + + false + + + + false + TRACE;DEBUG;NETSTANDARD + + + + true + true + MSSharedLibKey.snk + TRACE;RELEASE;NETSTANDARD;SIGN + + + + + + + + + + ..\..\..\Package\$(Configuration)\ResourceManager\AzureResourceManager\Az.RedisCache\Microsoft.Azure.Commands.RedisCache.dll + + + + + + PreserveNewest + + + PreserveNewest + + + + \ No newline at end of file diff --git a/src/DeploymentManager/Commands.DeploymentManager.Test/Commands.DeploymentManager.Test.csproj b/src/DeploymentManager/Commands.DeploymentManager.Test/Commands.DeploymentManager.Test.csproj new file mode 100644 index 000000000000..6274590f685d --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager.Test/Commands.DeploymentManager.Test.csproj @@ -0,0 +1,21 @@ + + + + DeploymentManager + + + + + + $(LegacyAssemblyPrefix)$(PsModuleName)$(AzTestAssemblySuffix) + + + + + + + + + + + \ No newline at end of file diff --git a/src/DeploymentManager/Commands.DeploymentManager.Test/MSSharedLibKey.snk b/src/DeploymentManager/Commands.DeploymentManager.Test/MSSharedLibKey.snk new file mode 100644 index 0000000000000000000000000000000000000000..695f1b38774e839e5b90059bfb7f32df1dff4223 GIT binary patch literal 160 zcmV;R0AK$ABme*efB*oL000060ssI2Bme+XQ$aBR1ONa50098C{E+7Ye`kjtcRG*W zi8#m|)B?I?xgZ^2Sw5D;l4TxtPwG;3)3^j?qDHjEteSTF{rM+4WI`v zCD?tsZ^;k+S&r1&HRMb=j738S=;J$tCKNrc$@P|lZ new DeploymentManagerController(); + + private void SetupManagementClients(MockContext context) + { + DeploymentManagerClient = GetDeploymentManagementClient(context); + ResourceManagementClient = GetResourceManagementClient(context); + StorageClient = GetStorageManagementClient(context); + _helper.SetupManagementClients( + DeploymentManagerClient, + StorageClient, + ResourceManagementClient); + } + + public void RunPowerShellTest(XunitTracingInterceptor logger, params string[] scripts) + { + var sf = new StackTrace().GetFrame(1); + var callingClassType = sf.GetMethod().ReflectedType?.ToString(); + var mockName = sf.GetMethod().Name; + + _helper.TracingInterceptor = logger; + + var d = new Dictionary + { + {"Microsoft.Resources", null}, + {"Microsoft.Features", null}, + {"Microsoft.Authorization", null} + }; + var providersToIgnore = new Dictionary(); + HttpMockServer.Matcher = new PermissiveRecordMatcherWithApiExclusion(true, d, providersToIgnore); + + HttpMockServer.RecordsDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "SessionRecords"); + using (var context = MockContext.Start(callingClassType, mockName)) + { + SetupManagementClients(context); + + var callingClassName = callingClassType?.Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries).Last(); + _helper.SetupEnvironment(AzureModule.AzureResourceManager); + _helper.SetupModules(AzureModule.AzureResourceManager, + "ScenarioTests\\" + callingClassName + ".ps1", + _helper.RMProfileModule, + "AzureRM.Storage.ps1", + _helper.GetRMModulePath(@"AzureRM.DeploymentManager.psd1"), + "AzureRM.Resources.ps1"); + + if (scripts != null) + { + _helper.RunPowerShellTest(scripts); + } + } + } + + private static StorageManagementClient GetStorageManagementClient(MockContext context) + { + return context.GetServiceClient(TestEnvironmentFactory.GetTestEnvironment()); + } + + private static AzureDeploymentManagerClient GetDeploymentManagementClient(MockContext context) + { + return context.GetServiceClient(TestEnvironmentFactory.GetTestEnvironment()); + } + + private static Management.Internal.Resources.ResourceManagementClient GetResourceManagementClient(MockContext context) + { + return context.GetServiceClient(TestEnvironmentFactory.GetTestEnvironment()); + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager.Test/ScenarioTests/DeploymentManagerTests.cs b/src/DeploymentManager/Commands.DeploymentManager.Test/ScenarioTests/DeploymentManagerTests.cs new file mode 100644 index 000000000000..0ac587f2fa5e --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager.Test/ScenarioTests/DeploymentManagerTests.cs @@ -0,0 +1,40 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Test.ScenarioTests +{ + using Microsoft.WindowsAzure.Commands.ScenarioTest; + using Microsoft.WindowsAzure.Commands.Test.Utilities.Common; + using ServiceManagemenet.Common.Models; + using Xunit; + using Xunit.Abstractions; + + public class DeploymentManagerTests : RMTestBase + { + public XunitTracingInterceptor _logger; + + public DeploymentManagerTests(ITestOutputHelper output) + { + _logger = new XunitTracingInterceptor(output); + XunitTracingInterceptor.AddToContext(_logger); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void EndToEndFunctionalTests() + { + DeploymentManagerController.NewInstance.RunPowerShellTest(_logger, "Test-EndToEndFunctionalTests"); + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager.Test/ScenarioTests/DeploymentManagerTests.ps1 b/src/DeploymentManager/Commands.DeploymentManager.Test/ScenarioTests/DeploymentManagerTests.ps1 new file mode 100644 index 000000000000..da983a7b8f07 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager.Test/ScenarioTests/DeploymentManagerTests.ps1 @@ -0,0 +1,489 @@ +<# +.SYNOPSIS +Test all resource operations +#> +function Test-EndToEndFunctionalTests +{ + # Setup + $resourceGroupName = "adm-powershell-test-rg" + $subscriptionId = "53012dcb-5039-4e96-8e6c-5d913da1cdb5" + $artifactSourceName = "powershell-sdk-tests-functional" + $updatedArtifactSourceName = "powershell-sdk-tests" + + $location = "Central US" + + # Create resource group + $resourceGroup = New-AzureRmResourceGroup -Name $resourceGroupName -Location $location + Assert-NotNull $resourceGroup "Created resource group is null." + + $artifactSource = New-ArtifactSource $resourceGroupName $artifactSourceName + + # Test all service topology and rollout operation + Test-ServiceTopology $resourceGroupName $location $artifactSource $updatedArtifactSourceName $subscriptionId + + Remove-AzureRmDeploymentManagerArtifactSource -ResourceGroupName $resourceGroupName -Name $artifactSourceName -Force + + $getArtifactSource = $null + try + { + $getArtifactSource = Get-AzureRmDeploymentManagerArtifactSource -ResourceGroupName $resourceGroupName -Name $artifactSourceName + } + catch + { + $errorString = $_.Exception.Message + Assert-True { $errorString.Contains("was not found") } + } + + Assert-Null $getArtifactSource +} + +function Test-ServiceTopology +{ + param + ( + $resourceGroupName, + $location, + $artifactSource, + $updatedArtifactSourceName, + $subscriptionId + ) + + $serviceTopologyName = "powershell-sdk-tests" + + $serviceTopology = New-AzureRmDeploymentManagerServiceTopology -ResourceGroupName $resourceGroupName -Location $location -Name $serviceTopologyName -ArtifactSourceId $artifactSource.Id + Validate-Topology $serviceTopology $resourceGroupName $location $serviceTopologyName $artifactSource.Id + $getResponse = Get-AzureRmDeploymentManagerServiceTopology -ResourceGroupName $resourceGroupName -Name $serviceTopologyName + + Validate-Topology $getResponse $resourceGroupName $location $serviceTopologyName $artifactSource.Id + + # Test Service CRUD operations + Test-Service $resourceGroupName $location $artifactSource $serviceTopology $subscriptionId + + # Test Set-ServiceTopology + $updatedArtifactSource = New-ArtifactSource $resourceGroupName $updatedArtifactSourceName + $getResponse.ArtifactSourceId = $updatedArtifactSource.Id + + $updatedServiceTopology = Set-AzureRmDeploymentManagerServiceTopology $getResponse + Validate-Topology $updatedServiceTopology $resourceGroupName $location $serviceTopologyName $updatedArtifactSource.Id + + # Test Set-ServiceTopology + Remove-AzureRmDeploymentManagerServiceTopology -ResourceGroupName $resourceGroupName -Name $serviceTopologyName -Force + $getResponse = $null + try + { + $getResponse = Get-AzureRmDeploymentManagerServiceTopology -ResourceGroupName $resourceGroupName -Name $serviceTopologyName + } + catch + { + $errorString = $_.Exception.Message + Assert-True { $errorString.Contains("was not found") } + } + + Assert-Null $getResponse +} + +function Validate-Topology +{ + param + ( + $serviceTopology, + $resourceGroupName, + $location, + $serviceTopologyName, + $artifactSourceId + ) + + Assert-NotNull $serviceTopology "Created ServiceTopology is null" + Assert-AreEqual $location $serviceTopology.Location + Assert-AreEqual $serviceTopologyName $serviceTopology.Name + Assert-AreEqual $artifactSourceId $serviceTopology.ArtifactSourceId +} + +function Test-Service +{ + param + ( + $resourceGroupName, + $location, + $artifactSource, + $serviceTopology, + $subscriptionId) + + $serviceName = "Contoso_Service" + $targetLocation = "East US 2" + $targetSubscriptionId = "53012dcb-5039-4e96-8e6c-5d913da1cdb5" + + $service = New-AzureRmDeploymentManagerService -ResourceGroupName $resourceGroupName -Location $location -Name $serviceName -ServiceTopology $serviceTopology -TargetLocation $targetLocation -TargetSubscriptionId $targetSubscriptionId + + Validate-Service $service $resourceGroupName $location $serviceTopology.Name $serviceName $targetLocation $targetSubscriptionId + + $getResponse = Get-AzureRmDeploymentManagerService -ResourceGroupName $resourceGroupName -Name $serviceName -ServiceTopologyName $serviceTopology.Name + + Validate-Service $getResponse $resourceGroupName $location $serviceTopology.Name $serviceName $targetLocation $targetSubscriptionId + + # Test Service Unit CRUD operations + Test-ServiceUnit $resourceGroupName $location $artifactSource $serviceTopology $getResponse + + # Test Set-Service + $getResponse.TargetSubscriptionId = "1e591dc1-b014-4754-b53b-58b67bcab1cd" + $updatedService = Set-AzureRmDeploymentManagerService $getResponse + + Validate-Service $updatedService $resourceGroupName $location $serviceTopologyName $serviceName $targetLocation $getResponse.TargetSubscriptionId + + # Test Remove-Service + Remove-AzureRmDeploymentManagerService -ResourceGroupName $resourceGroupName -Name $serviceName -ServiceTopologyName $serviceTopology.Name -Force + + $getResponse = $null + + try + { + $getResponse = Get-AzureRmDeploymentManagerService -ResourceGroupName $resourceGroupName -Name $serviceName -ServiceTopologyName $serviceTopology.Name + } + catch + { + $errorString = $_.Exception.Message + Assert-True { $errorString.Contains("not found") } + } + + Assert-Null $getResponse +} + +function Validate-Service +{ + param + ( + $service, + $resourceGroupName, + $location, + $serviceTopologyName, + $serviceName, + $targetLocation, + $subscriptionId + ) + + Assert-NotNull $service "Created service is null" + Assert-AreEqual $location $service.Location + Assert-AreEqual $serviceName $service.Name + Assert-AreEqual $serviceTopologyName $service.ServiceTopologyName + Assert-AreEqual $targetLocation $service.TargetLocation + Assert-AreEqual $subscriptionId $service.TargetSubscriptionId +} + +function Test-ServiceUnit +{ + param + ( + $resourceGroupName, + $location, + $artifactSource, + $serviceTopology, + $service) + + $serviceUnitName = "Contoso_WebApp" + $targetResourceGroup = "sdk-net-targetResourceGroup" + $deploymentMode = "Incremental" + $parametersArtifactSourceRelativePath = "Parameters/WebApp.Parameters.json" + $templateArtifactSourceRelativePath = "Templates/WebApp.Template.json" + + $serviceUnit = New-AzureRmDeploymentManagerServiceUnit ` + -ResourceGroupName $resourceGroupName ` + -Location $location ` + -ServiceTopology $serviceTopology ` + -ServiceName $service.Name ` + -Name $serviceUnitName ` + -TargetResourceGroup $targetResourceGroup ` + -DeploymentMode $deploymentMode ` + -ParametersArtifactSourceRelativePath $parametersArtifactSourceRelativePath ` + -TemplateArtifactSourceRelativePath $templateArtifactSourceRelativePath + + Validate-ServiceUnit $serviceUnit $resourceGroupName $location $serviceTopology.Name $service.Name $serviceUnitName $targetResourceGroup $deploymentMode $templateArtifactSourceRelativePath $parametersArtifactSourceRelativePath + + $getResponse = Get-AzureRmDeploymentManagerServiceUnit ` + -ResourceGroupName $resourceGroupName ` + -ServiceTopologyName $serviceTopology.Name ` + -ServiceName $serviceName ` + -Name $serviceUnitName + + Validate-ServiceUnit $getResponse $resourceGroupName $location $serviceTopology.Name $service.Name $serviceUnitName $targetResourceGroup $deploymentMode $templateArtifactSourceRelativePath $parametersArtifactSourceRelativePath + + # Test rollout CRUD operations + # Create a service unit with invalid parameters file for testing restart-rollout scenari + $invalidParametersArtifactSourceRelativePath = "Parameters/WebApp.Invalid.Parameters.json" + $invalidServiceUnitName = "Contoso_WebApp_Invalid" + + $invalidServiceUnit = New-AzureRmDeploymentManagerServiceUnit ` + -ResourceGroupName $resourceGroupName ` + -Location $location ` + -ServiceTopology $serviceTopology ` + -ServiceName $service.Name ` + -Name $invalidServiceUnitName ` + -TargetResourceGroup $targetResourceGroup ` + -DeploymentMode $deploymentMode ` + -ParametersArtifactSourceRelativePath $invalidParametersArtifactSourceRelativePath ` + -TemplateArtifactSourceRelativePath $templateArtifactSourceRelativePath + Validate-ServiceUnit $invalidServiceUnit $resourceGroupName $location $serviceTopology.Name $service.Name $invalidServiceUnitName $targetResourceGroup $deploymentMode $templateArtifactSourceRelativePath $invalidParametersArtifactSourceRelativePath + + # Test Step operations and rollout CRUD operations that depend on Service Units + Test-Steps $resourceGroupName $location $serviceTopology $artifactSource $serviceUnit + + # Test Set-ServiceUnit + $getResponse.DeploymentMode = "Complete" + $getResponse.ParametersArtifactSourceRelativePath = "Parameters/WebApp.Parameters.Dup.json" + $getResponse.TemplateArtifactSourceRelativePath = "Templates/WebApp.Template.Dup.json" + + $updatedServiceUnit = Set-AzureRmDeploymentManagerServiceUnit $getResponse + + Validate-ServiceUnit $updatedServiceUnit $resourceGroupName $location $serviceTopology.Name $service.Name $serviceUnitName $targetResourceGroup $getResponse.DeploymentMode $getResponse.TemplateArtifactSourceRelativePath $getResponse.ParametersArtifactSourceRelativePath + + # Test Remove-ServiceUnit + Remove-AzureRmDeploymentManagerServiceUnit -ResourceGroupName $resourceGroupName -ServiceTopologyName $serviceTopology.Name -ServiceName $service.Name -Name $serviceUnitName -Force + + # Remove second service unit created for failure rollout case + Remove-AzureRmDeploymentManagerServiceUnit -ResourceGroupName $resourceGroupName -ServiceTopologyName $serviceTopology.Name -ServiceName $service.Name -Name $invalidServiceUnitName -Force + + $getResponse = $null + try + { + $getResponse = Get-AzureRmDeploymentManagerServiceUnit -ResourceGroupName $resourceGroupName -ServiceTopologyName $serviceTopology.Name -ServiceName $service.Name -Name $serviceUnitName + } + catch + { + $errorString = $_.Exception.Message + Assert-True { $errorString.Contains("was not found") } + } + + Assert-Null $getResponse +} + +function Validate-Serviceunit +{ + param + ( + $serviceUnit, + $resourceGroupName, + $location, + $serviceTopologyName, + $serviceName, + $serviceUnitName, + $targetResourceGroup, + $deploymentMode, + $templateArtifactSourceRelativePath, + $parametersArtifactSourceRelativePath) + Assert-NotNull $serviceUnit "Created service unit is null" + Assert-AreEqual $location $serviceUnit.Location + Assert-AreEqual $serviceUnitName $serviceUnit.Name + Assert-AreEqual $serviceTopologyName $serviceUnit.ServiceTopologyName + Assert-AreEqual $serviceName $serviceUnit.ServiceName + Assert-AreEqual $targetResourceGroup $serviceUnit.TargetResourceGroup + Assert-AreEqual $deploymentMode $serviceUnit.DeploymentMode + Assert-AreEqual $parametersArtifactSourceRelativePath $serviceUnit.ParametersArtifactSourceRelativePath + Assert-AreEqual $templateArtifactSourceRelativePath $serviceUnit.TemplateArtifactSourceRelativePath +} + +function Test-Steps +{ + param + ( + $resourceGroupName, + $location, + $serviceTopology, + $artifactSource, + $serviceUnit) + + $stepName = "WaitStep" + $duration = "PT5M" + $updatedDuration = "PT10M" + + $step = New-AzureRmDeploymentManagerStep -Name $stepName -ResourceGroupName $resourceGroupName -Location $location -Duration $duration + Validate-Step $step $stepName $location $resourceGroupName $duration + + $getResponse = Get-AzureRmDeploymentManagerStep -ResourceGroupName $resourceGroupName -Name $stepName + Validate-Step $getResponse $stepName $location $resourceGroupName $duration + + Test-Rollout $resourceGroupName $location $serviceTopology $artifactSource $serviceUnit + + # Test Set-Step + $getResponse.StepProperties.Duration = $updatedDuration + + $updatedStep = Set-AzureRmDeploymentManagerStep $getResponse + Validate-Step $updatedStep $stepName $location $resourceGroupName $updatedDuration + + # Test Remove-Step + Remove-AzureRmDeploymentManagerStep -ResourceGroupName $resourceGroupName -Name $stepName -Force + $getResponse = $null + + try + { + $getResponse = Get-AzureRmDeploymentManagerStep -ResourceGroupName $resourceGroupName -Name $stepName + } + catch + { + $errorString = $_.Exception.Message + Assert-True { $errorString.Contains("was not found") } + } + + Assert-Null $getResponse +} + +function Validate-Step +{ + param + ( + $step, + $stepName, + $location, + $resourceGroupName, + $duration) + + Assert-NotNull $step "Created step is null" + Assert-AreEqual $location $step.Location + Assert-AreEqual $resourceGroupName $step.ResourceGroupName + Assert-AreEqual $stepName $step.Name + Assert-AreEqual $duration $step.StepProperties.Duration +} + +function Test-Rollout +{ + param + ( + $resourceGroupName, + $location, + $serviceTopology, + $artifactSource, + $serviceUnit) + + $rolloutName = "adm-powershell-tests-rollout" + $failedRolloutName = "adm-powershell-tests-invalidRollout" + + New-AzureRmResourceGroup -Name $rolloutName -Location $location + New-AzureRmResourceGroup -Name $failedRolloutName -Location $location + + $deployment = New-AzureRmResourceGroupDeployment -Name $rolloutName -ResourceGroupName $rolloutName -TemplateFile ".\ScenarioTests\CreateRollout.json" + + $getResponse = Get-AzureRmDeploymentManagerRollout -ResourceGroupName $rolloutName -Name $rolloutName + Validate-Rollout $getResponse $rolloutName $location $rolloutName @('Running') $serviceTopology $artifactSource + + # Test Stop-Rollout + $canceledRollout = Stop-AzureRmDeploymentManagerRollout -Rollout $getResponse -Force + Validate-Rollout $canceledRollout $rolloutName $location $rolloutName @('Canceling', 'Canceled') $serviceTopology $artifactSource + + # Wait for rollout to finish + while ($canceledRollout.Status -eq "Canceling") + { + Start-TestSleep 120000 + $canceledRollout = Get-AzureRmDeploymentManagerRollout -ResourceGroupName $rolloutName -Name $rolloutName + } + + Assert-AreEqual "Canceled" $canceledRollout.Status + + $failedDeployment = New-AzureRmResourceGroupDeployment -Name $failedRolloutName -ResourceGroupName $failedRolloutName -TemplateFile ".\ScenarioTests\CreateRollout_FailureRollout.json" + + $ErrorActionPreference = "SilentlyContinue" + $Error.Clear() + $failedRollout = Get-AzureRmDeploymentManagerRollout -ResourceGroupName $failedRolloutName -Name $failedRolloutName 2>$null + + # Wait for the invalid rollout to fail + while ($failedRollout.Status -eq "Running") + { + Start-TestSleep 60000 + $failedRollout = Get-AzureRmDeploymentManagerRollout -ResourceGroupName $failedRolloutName -Name $failedRolloutName 2>$null + } + + $Error.Clear() + Assert-AreEqual "Failed" $failedRollout.Status + # Validate-Rollout $failedRollout $failedRolloutName $location $failedRolloutName @('Failed') $serviceTopology $artifactSource + + # Write-Verbose "Completed assert on failed rollout. Restarting rollout" + + $restartRollout = Restart-AzureRmDeploymentManagerRollout -ResourceGroupName $failedRolloutName -Name $failedRolloutName -SkipSucceeded + Validate-Rollout $restartRollout $failedRolloutName $location $failedRolloutName @('Running') $serviceTopology $artifactSource $true 1 + + Remove-AzureRmDeploymentManagerRollout -ResourceGroupName $rolloutName -Name $rolloutName -Force + $getResponse = Get-AzureRmDeploymentManagerRollout -ResourceGroupName $rolloutName -Name $rolloutName + Assert-Null $getResponse +} + +function Validate-Rollout +{ + param + ( + $rollout, + $resourceGroupName, + $location, + $rolloutName, + $rolloutStatus, + $serviceTopology, + $artifactSource, + $skipSucceeded = $false, + $retryAttempt = 0) + + Assert-NotNull $rollout "Created rollout is null" + Assert-AreEqual $location $rollout.Location + Assert-AreEqual $resourceGroupName $rollout.ResourceGroupName + Assert-True { $rolloutStatus.Contains($rollout.Status) } + Assert-AreEqual $serviceTopology.Id $rollout.TargetServiceTopologyId + Assert-AreEqual $artifactSource.Id $rollout.ArtifactSourceId + Assert-AreEqual $retryAttempt $rollout.OperationInfo.RetryAttempt + Assert-AreEqual $skipSucceeded $rollout.OperationInfo.SkipSucceededOnRetry +} + +function New-ArtifactSource +{ + param + ( + $resourceGroupName, + $artifactSourceName + ) + + $artifactRoot = "builds/1.0.0.0" + $storageAccountResourceGroup = "adm-sdk-tests" + $storageAccountName = "sdktests" + $containerName = "artifacts" + + $sasKeyForContainer = "" + Get-SasForContainer $storageAccountResourceGroup $storageAccountName $containerName ([ref]$sasKeyForContainer) + $artifactSource = New-AzureRmDeploymentManagerArtifactSource -ResourceGroupName $resourceGroupName -Name $artifactSourceName -Location $location -SasUri $sasKeyForContainer -ArtifactRoot $artifactRoot + + Assert-AreEqual $artifactSourceName $artifactSource.Name + Assert-AreEqual $resourceGroupName $artifactSource.ResourceGroupName + Assert-AreEqual $location $artifactSource.Location + Assert-AreEqual "Microsoft.DeploymentManager/artifactSources" $artifactSource.Type + Assert-AreEqual $artifactRoot $artifactSource.ArtifactRoot + + return $artifactSource +} + +function Get-SasForContainer +{ + param + ( + $resourceGroupName, + $storageName, + $storageContainerName, + [ref] $sasKeyForContainer + ) + if ([Microsoft.Azure.Test.HttpRecorder.HttpMockServer]::Mode -ne [Microsoft.Azure.Test.HttpRecorder.HttpRecorderMode]::Playback) + { + # Get storage account context + $storageAccountContext = New-AzureStorageContext -StorageAccountName $storageName -StorageAccountKey (Get-AzureRmStorageAccountKey -ResourceGroupName $resourceGroupName -Name $storageName).Value[0] + + # Get SAS token for container + $sasKeyForContainer.Value = New-AzureStorageContainerSASToken -Name $storageContainerName -Permission "rl" -StartTime ([System.DateTime]::Now).AddHours(-20) -ExpiryTime ([System.DateTime]::Now).AddHours(48) -Context $storageAccountContext -FullUri + } + else + { + $sasKeyForContainer.Value = "dummysasforcontainer" + } +} + +<# +.SYNOPSIS +Sleeps but only during recording. +#> +function Start-TestSleep($milliseconds) +{ + if ([Microsoft.Azure.Test.HttpRecorder.HttpMockServer]::Mode -ne [Microsoft.Azure.Test.HttpRecorder.HttpRecorderMode]::Playback) + { + Start-Sleep -Milliseconds $milliseconds + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager.Test/SessionRecords/Microsoft.Azure.Commands.DeploymentManager.Test.ScenarioTests.DeploymentManagerTests/EndToEndFunctionalTests.json b/src/DeploymentManager/Commands.DeploymentManager.Test/SessionRecords/Microsoft.Azure.Commands.DeploymentManager.Test.ScenarioTests.DeploymentManagerTests/EndToEndFunctionalTests.json new file mode 100644 index 000000000000..ea1779b62951 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager.Test/SessionRecords/Microsoft.Azure.Commands.DeploymentManager.Test.ScenarioTests.DeploymentManagerTests/EndToEndFunctionalTests.json @@ -0,0 +1,6251 @@ +{ + "Entries": [ + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlZ3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3Qtcmc/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "PUT", + "RequestBody": "{\r\n \"location\": \"Central US\"\r\n}", + "RequestHeaders": { + "x-ms-client-request-id": [ + "616ab72f-5877-4306-bd0f-ce93e61a8615" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Content-Length": [ + "32" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1199" + ], + "x-ms-request-id": [ + "3c98b789-ccd0-431b-a994-ff2eba4cbf60" + ], + "x-ms-correlation-request-id": [ + "3c98b789-ccd0-431b-a994-ff2eba4cbf60" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183056Z:3c98b789-ccd0-431b-a994-ff2eba4cbf60" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:30:55 GMT" + ], + "Content-Length": [ + "200" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg\",\r\n \"name\": \"adm-powershell-test-rg\",\r\n \"location\": \"centralus\",\r\n \"properties\": {\r\n \"provisioningState\": \"Succeeded\"\r\n }\r\n}", + "StatusCode": 201 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-sdk-tests/providers/Microsoft.Storage/storageAccounts/sdktests/listKeys?api-version=2017-06-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1zZGstdGVzdHMvcHJvdmlkZXJzL01pY3Jvc29mdC5TdG9yYWdlL3N0b3JhZ2VBY2NvdW50cy9zZGt0ZXN0cy9saXN0S2V5cz9hcGktdmVyc2lvbj0yMDE3LTA2LTAx", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "5e4528b8-29f1-4142-a199-7d842a29fc4a" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Storage.StorageManagementClient/6.5.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-request-id": [ + "a3620ec4-06b2-40aa-bbaa-e9f215c99fcd" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1199" + ], + "x-ms-correlation-request-id": [ + "26e73fc0-9223-4f8d-b3c2-20405289b910" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183056Z:26e73fc0-9223-4f8d-b3c2-20405289b910" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:30:55 GMT" + ], + "Server": [ + "Microsoft-Azure-Storage-Resource-Provider/1.0,Microsoft-HTTPAPI/2.0 Microsoft-HTTPAPI/2.0" + ], + "Content-Length": [ + "288" + ], + "Content-Type": [ + "application/json" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"keys\": [\r\n {\r\n \"keyName\": \"key1\",\r\n \"value\": \"RLZtDAk4JJch3Mo4w5IFI8RVukyHR126iZdA4+V5LE5Sf8rQWzg0MYqYR64aS6Pk1EVwOIarAHeIoqxC7u0Z8w==\",\r\n \"permissions\": \"FULL\"\r\n },\r\n {\r\n \"keyName\": \"key2\",\r\n \"value\": \"Sg3aTntH8JvErHxBx/ZpJq5G6vjcsG4TWjlghK9v+61+jqObdSCcgulblvNvmSYdTpAXTgWzIOhkY/jRVqtn2g==\",\r\n \"permissions\": \"FULL\"\r\n }\r\n ]\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-sdk-tests/providers/Microsoft.Storage/storageAccounts/sdktests/listKeys?api-version=2017-06-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1zZGstdGVzdHMvcHJvdmlkZXJzL01pY3Jvc29mdC5TdG9yYWdlL3N0b3JhZ2VBY2NvdW50cy9zZGt0ZXN0cy9saXN0S2V5cz9hcGktdmVyc2lvbj0yMDE3LTA2LTAx", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "97566dff-a3b3-4217-b380-d8391ded2785" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Storage.StorageManagementClient/6.5.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-request-id": [ + "cc960eee-5bc9-40d5-b8dc-68cd7d5d5edc" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1193" + ], + "x-ms-correlation-request-id": [ + "53e45372-2246-4f25-aa52-be6cbfe5d2f6" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183846Z:53e45372-2246-4f25-aa52-be6cbfe5d2f6" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:38:45 GMT" + ], + "Server": [ + "Microsoft-Azure-Storage-Resource-Provider/1.0,Microsoft-HTTPAPI/2.0 Microsoft-HTTPAPI/2.0" + ], + "Content-Length": [ + "288" + ], + "Content-Type": [ + "application/json" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"keys\": [\r\n {\r\n \"keyName\": \"key1\",\r\n \"value\": \"RLZtDAk4JJch3Mo4w5IFI8RVukyHR126iZdA4+V5LE5Sf8rQWzg0MYqYR64aS6Pk1EVwOIarAHeIoqxC7u0Z8w==\",\r\n \"permissions\": \"FULL\"\r\n },\r\n {\r\n \"keyName\": \"key2\",\r\n \"value\": \"Sg3aTntH8JvErHxBx/ZpJq5G6vjcsG4TWjlghK9v+61+jqObdSCcgulblvNvmSYdTpAXTgWzIOhkY/jRVqtn2g==\",\r\n \"permissions\": \"FULL\"\r\n }\r\n ]\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "64b21580-c46a-4d43-a821-15253b0b9019" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1198" + ], + "x-ms-request-id": [ + "76dac1a1-343a-4e8f-98b4-478aaa40d2ee" + ], + "x-ms-correlation-request-id": [ + "76dac1a1-343a-4e8f-98b4-478aaa40d2ee" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183059Z:76dac1a1-343a-4e8f-98b4-478aaa40d2ee" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:30:58 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "0808521a-a4ed-435b-8206-32e36dad51f7" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1199" + ], + "x-ms-request-id": [ + "dcb95421-4d5d-4140-8253-61e0a4dc6799" + ], + "x-ms-correlation-request-id": [ + "dcb95421-4d5d-4140-8253-61e0a4dc6799" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183103Z:dcb95421-4d5d-4140-8253-61e0a4dc6799" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:31:02 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "40fa0aa5-c87e-4427-ab95-01267f831c97" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1197" + ], + "x-ms-request-id": [ + "c0102843-b845-4de3-b196-19d0d6ab9965" + ], + "x-ms-correlation-request-id": [ + "c0102843-b845-4de3-b196-19d0d6ab9965" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183108Z:c0102843-b845-4de3-b196-19d0d6ab9965" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:31:07 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "30bc98dc-61a3-49e0-8959-4b06dae9275c" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1196" + ], + "x-ms-request-id": [ + "d57d2da8-ddc6-40f9-854f-77539c7fa5f7" + ], + "x-ms-correlation-request-id": [ + "d57d2da8-ddc6-40f9-854f-77539c7fa5f7" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183109Z:d57d2da8-ddc6-40f9-854f-77539c7fa5f7" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:31:09 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "d7945b5f-bdad-4a83-aaa8-61279f462b7f" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1195" + ], + "x-ms-request-id": [ + "22f47658-9939-4f76-be60-7cd382b6b527" + ], + "x-ms-correlation-request-id": [ + "22f47658-9939-4f76-be60-7cd382b6b527" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183112Z:22f47658-9939-4f76-be60-7cd382b6b527" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:31:11 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "b6ef42cb-758a-4858-820f-b846861f1284" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1194" + ], + "x-ms-request-id": [ + "baa1e54b-2fce-474e-8c41-d26c9d209187" + ], + "x-ms-correlation-request-id": [ + "baa1e54b-2fce-474e-8c41-d26c9d209187" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183113Z:baa1e54b-2fce-474e-8c41-d26c9d209187" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:31:12 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "c7472082-2237-4155-9777-34526b662f81" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1193" + ], + "x-ms-request-id": [ + "2af1c101-4e03-475e-871e-1aa33ad4cab7" + ], + "x-ms-correlation-request-id": [ + "2af1c101-4e03-475e-871e-1aa33ad4cab7" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183114Z:2af1c101-4e03-475e-871e-1aa33ad4cab7" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:31:13 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "594d2c6b-4fc1-47a5-87ea-c373d0251102" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1199" + ], + "x-ms-request-id": [ + "9e2462d0-eafd-4c62-84ad-1665c2b04b60" + ], + "x-ms-correlation-request-id": [ + "9e2462d0-eafd-4c62-84ad-1665c2b04b60" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183118Z:9e2462d0-eafd-4c62-84ad-1665c2b04b60" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:31:18 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "dc25c908-023e-4c91-b923-a72540dcda79" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1198" + ], + "x-ms-request-id": [ + "055beb63-dedb-46c1-b432-bfa561534344" + ], + "x-ms-correlation-request-id": [ + "055beb63-dedb-46c1-b432-bfa561534344" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183121Z:055beb63-dedb-46c1-b432-bfa561534344" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:31:20 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "7e06b0c0-d081-4e7f-9f65-28e2622abbd7" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1197" + ], + "x-ms-request-id": [ + "4f9fff58-c1aa-433b-a8cb-8e1a85e96b81" + ], + "x-ms-correlation-request-id": [ + "4f9fff58-c1aa-433b-a8cb-8e1a85e96b81" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183122Z:4f9fff58-c1aa-433b-a8cb-8e1a85e96b81" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:31:21 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "b9e78885-d18a-4e39-a0cc-cafe3300729e" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1196" + ], + "x-ms-request-id": [ + "4df45dc4-cc6a-408b-95cf-aeca2fac45b1" + ], + "x-ms-correlation-request-id": [ + "4df45dc4-cc6a-408b-95cf-aeca2fac45b1" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183157Z:4df45dc4-cc6a-408b-95cf-aeca2fac45b1" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:31:57 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "76be6938-7364-435b-9670-1beafd17b61c" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1195" + ], + "x-ms-request-id": [ + "5f4b72ac-f9df-4c65-ac7b-147fb5e13ed6" + ], + "x-ms-correlation-request-id": [ + "5f4b72ac-f9df-4c65-ac7b-147fb5e13ed6" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183219Z:5f4b72ac-f9df-4c65-ac7b-147fb5e13ed6" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:32:18 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "99309d25-1161-4e1e-b5c7-76509615f3a5" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1194" + ], + "x-ms-request-id": [ + "9b0045ee-5986-48e7-849a-5329b9f9f128" + ], + "x-ms-correlation-request-id": [ + "9b0045ee-5986-48e7-849a-5329b9f9f128" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183220Z:9b0045ee-5986-48e7-849a-5329b9f9f128" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:32:19 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "64bdf7d3-a2e3-4b80-b8df-c071f94184ef" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1199" + ], + "x-ms-request-id": [ + "22fd2c85-596b-4f12-b6a2-43f7a259bfd6" + ], + "x-ms-correlation-request-id": [ + "22fd2c85-596b-4f12-b6a2-43f7a259bfd6" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183319Z:22fd2c85-596b-4f12-b6a2-43f7a259bfd6" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:33:19 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "80033fe0-59b3-42d8-a553-720616e83cea" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1198" + ], + "x-ms-request-id": [ + "ca72180b-31b6-48cd-b0f0-d4f52d7953ac" + ], + "x-ms-correlation-request-id": [ + "ca72180b-31b6-48cd-b0f0-d4f52d7953ac" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183320Z:ca72180b-31b6-48cd-b0f0-d4f52d7953ac" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:33:20 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "a0d2d39c-4df3-481d-9a95-b4baae7f80a5" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1197" + ], + "x-ms-request-id": [ + "8352eddf-4c6c-4140-b37f-75c32a5b7a5f" + ], + "x-ms-correlation-request-id": [ + "8352eddf-4c6c-4140-b37f-75c32a5b7a5f" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183323Z:8352eddf-4c6c-4140-b37f-75c32a5b7a5f" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:33:22 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "2dccd97b-c9b9-4958-b576-1dce8a6045a3" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1196" + ], + "x-ms-request-id": [ + "36320b93-7d67-43fd-8969-036a58ab0d16" + ], + "x-ms-correlation-request-id": [ + "36320b93-7d67-43fd-8969-036a58ab0d16" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183429Z:36320b93-7d67-43fd-8969-036a58ab0d16" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:34:28 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "14b58be0-4312-4290-898a-22d8d8b503f1" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1195" + ], + "x-ms-request-id": [ + "715e19bd-a42a-4b81-8d96-1a8261361c98" + ], + "x-ms-correlation-request-id": [ + "715e19bd-a42a-4b81-8d96-1a8261361c98" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183431Z:715e19bd-a42a-4b81-8d96-1a8261361c98" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:34:30 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "f23cbaef-96a8-415d-921c-d8d8fd5be357" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1199" + ], + "x-ms-request-id": [ + "b7e75dfe-ae85-43d1-badd-9f30c241967a" + ], + "x-ms-correlation-request-id": [ + "b7e75dfe-ae85-43d1-badd-9f30c241967a" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183633Z:b7e75dfe-ae85-43d1-badd-9f30c241967a" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:36:33 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "eff5d4d0-a62e-46cf-b21d-2fb67a5d3282" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1199" + ], + "x-ms-request-id": [ + "f4cfc2ca-3131-4b7e-88f8-d26637b76f61" + ], + "x-ms-correlation-request-id": [ + "f4cfc2ca-3131-4b7e-88f8-d26637b76f61" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183740Z:f4cfc2ca-3131-4b7e-88f8-d26637b76f61" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:37:40 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "04e0eb73-74d4-4a5b-b109-c2d39c383c70" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1198" + ], + "x-ms-request-id": [ + "1dedf714-a9c7-4c18-be84-0d84e8454ec8" + ], + "x-ms-correlation-request-id": [ + "1dedf714-a9c7-4c18-be84-0d84e8454ec8" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183743Z:1dedf714-a9c7-4c18-be84-0d84e8454ec8" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:37:42 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "5364a75d-6275-41d0-b75b-b22591d39fd9" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1196" + ], + "x-ms-request-id": [ + "b321b81c-7bc9-4a94-9d89-2d5b3a7da14a" + ], + "x-ms-correlation-request-id": [ + "b321b81c-7bc9-4a94-9d89-2d5b3a7da14a" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183746Z:b321b81c-7bc9-4a94-9d89-2d5b3a7da14a" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:37:46 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "48e242a9-caa7-45ed-bbf8-db45c1dd386e" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1199" + ], + "x-ms-request-id": [ + "771b18cb-ddb8-452e-9510-852306582c12" + ], + "x-ms-correlation-request-id": [ + "771b18cb-ddb8-452e-9510-852306582c12" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183751Z:771b18cb-ddb8-452e-9510-852306582c12" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:37:51 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "37161a93-0aeb-464c-bd54-4c712590f2df" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1198" + ], + "x-ms-request-id": [ + "44670223-4afc-40da-a536-8f172a54e91e" + ], + "x-ms-correlation-request-id": [ + "44670223-4afc-40da-a536-8f172a54e91e" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183752Z:44670223-4afc-40da-a536-8f172a54e91e" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:37:52 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "9f6c3dbf-67b8-4d8b-b80e-901d9c00a65d" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1197" + ], + "x-ms-request-id": [ + "d31667a6-7ee4-4acd-9958-5832c7ad7d72" + ], + "x-ms-correlation-request-id": [ + "d31667a6-7ee4-4acd-9958-5832c7ad7d72" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183754Z:d31667a6-7ee4-4acd-9958-5832c7ad7d72" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:37:54 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "d5918b1c-1fc5-4229-aaac-aced436a14cd" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1196" + ], + "x-ms-request-id": [ + "9e4dc4dc-1fd1-4f62-a890-46de3ecf584d" + ], + "x-ms-correlation-request-id": [ + "9e4dc4dc-1fd1-4f62-a890-46de3ecf584d" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183756Z:9e4dc4dc-1fd1-4f62-a890-46de3ecf584d" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:37:56 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "8df4dd97-f7d4-4358-aa26-b7c6c56937cc" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1195" + ], + "x-ms-request-id": [ + "62bf6087-d853-4560-8bbe-4842989e551c" + ], + "x-ms-correlation-request-id": [ + "62bf6087-d853-4560-8bbe-4842989e551c" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183757Z:62bf6087-d853-4560-8bbe-4842989e551c" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:37:57 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "cd822f67-7bcd-434d-89bb-798f736699ce" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1194" + ], + "x-ms-request-id": [ + "acea30d2-7675-4107-a3f7-6a7d09a23b3f" + ], + "x-ms-correlation-request-id": [ + "acea30d2-7675-4107-a3f7-6a7d09a23b3f" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183836Z:acea30d2-7675-4107-a3f7-6a7d09a23b3f" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:38:36 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "012d4034-18d8-44e0-9e86-7a800c9d369c" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1193" + ], + "x-ms-request-id": [ + "5c795282-9477-4eb7-a62b-dae8f5f0e626" + ], + "x-ms-correlation-request-id": [ + "5c795282-9477-4eb7-a62b-dae8f5f0e626" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183838Z:5c795282-9477-4eb7-a62b-dae8f5f0e626" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:38:38 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "39833ac4-ded6-46e2-b0a3-66cf5685ec65" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1192" + ], + "x-ms-request-id": [ + "6fcb6433-3a89-4ebd-a082-64dc914db5a8" + ], + "x-ms-correlation-request-id": [ + "6fcb6433-3a89-4ebd-a082-64dc914db5a8" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183840Z:6fcb6433-3a89-4ebd-a082-64dc914db5a8" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:38:40 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "6f7ba739-16d1-4724-91bf-b5fe9db3b09f" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1191" + ], + "x-ms-request-id": [ + "b8c9c51d-13ab-40e1-b342-c9f84c412211" + ], + "x-ms-correlation-request-id": [ + "b8c9c51d-13ab-40e1-b342-c9f84c412211" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183841Z:b8c9c51d-13ab-40e1-b342-c9f84c412211" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:38:41 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "6276202d-f114-4556-918f-f9b23d754dab" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1190" + ], + "x-ms-request-id": [ + "0742c797-4a60-45ba-9b1b-101d0ede7752" + ], + "x-ms-correlation-request-id": [ + "0742c797-4a60-45ba-9b1b-101d0ede7752" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183844Z:0742c797-4a60-45ba-9b1b-101d0ede7752" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:38:43 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "a179b348-0748-4229-a548-6ede04bdbd67" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1189" + ], + "x-ms-request-id": [ + "0abed314-0277-4edf-8c32-aaa322d8c847" + ], + "x-ms-correlation-request-id": [ + "0abed314-0277-4edf-8c32-aaa322d8c847" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183846Z:0abed314-0277-4edf-8c32-aaa322d8c847" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:38:45 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "81aed46e-3ff8-454f-8e12-76876e539a85" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1192" + ], + "x-ms-request-id": [ + "1bd2c998-2c04-48c3-843d-98b254d7612a" + ], + "x-ms-correlation-request-id": [ + "1bd2c998-2c04-48c3-843d-98b254d7612a" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183847Z:1bd2c998-2c04-48c3-843d-98b254d7612a" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:38:47 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "ab5084d0-d9f4-4a42-bfea-a203fbd73da8" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1191" + ], + "x-ms-request-id": [ + "abf3aefa-87b6-4f82-b634-1b3e4afd4971" + ], + "x-ms-correlation-request-id": [ + "abf3aefa-87b6-4f82-b634-1b3e4afd4971" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183848Z:abf3aefa-87b6-4f82-b634-1b3e4afd4971" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:38:48 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "10f21943-f851-4dbc-99d5-59d58f3aa613" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1190" + ], + "x-ms-request-id": [ + "6485236b-602a-46e3-a153-ecff1c0dd7c7" + ], + "x-ms-correlation-request-id": [ + "6485236b-602a-46e3-a153-ecff1c0dd7c7" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183851Z:6485236b-602a-46e3-a153-ecff1c0dd7c7" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:38:50 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "bf2f2325-b216-4e68-9e38-7b816cb80a75" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1189" + ], + "x-ms-request-id": [ + "309e016b-38c2-428b-abe3-a18e3316276d" + ], + "x-ms-correlation-request-id": [ + "309e016b-38c2-428b-abe3-a18e3316276d" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183853Z:309e016b-38c2-428b-abe3-a18e3316276d" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:38:52 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "ac932a46-5282-4555-a41a-8260bf833c53" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1188" + ], + "x-ms-request-id": [ + "59c704e9-33dd-4c47-9330-ce956f5d1606" + ], + "x-ms-correlation-request-id": [ + "59c704e9-33dd-4c47-9330-ce956f5d1606" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183855Z:59c704e9-33dd-4c47-9330-ce956f5d1606" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:38:54 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "d4cbb339-1bc3-423a-8bb2-3b4d643fd9fb" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1187" + ], + "x-ms-request-id": [ + "c35fe2e0-8a28-4999-98de-a05fac0658bb" + ], + "x-ms-correlation-request-id": [ + "c35fe2e0-8a28-4999-98de-a05fac0658bb" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183856Z:c35fe2e0-8a28-4999-98de-a05fac0658bb" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:38:55 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager/register?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcmVnaXN0ZXI/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "9f7cdbeb-2785-4a96-847c-9fca3e1a4cab" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1186" + ], + "x-ms-request-id": [ + "af18c43f-f6c9-438d-a436-eecb4d2ac431" + ], + "x-ms-correlation-request-id": [ + "af18c43f-f6c9-438d-a436-eecb4d2ac431" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183858Z:af18c43f-f6c9-438d-a436-eecb4d2ac431" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:38:58 GMT" + ], + "Content-Length": [ + "1523" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/providers/Microsoft.DeploymentManager\",\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"authorizations\": [\r\n {\r\n \"applicationId\": \"5b306cba-9c71-49db-96c3-d17ca2379c4d\"\r\n }\r\n ],\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"artifactSources\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"serviceTopologies/services/serviceUnits\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"steps\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"Central US\",\r\n \"East US 2\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ],\r\n \"capabilities\": \"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove\"\r\n },\r\n {\r\n \"resourceType\": \"operationResults\",\r\n \"locations\": [\r\n \"global\"\r\n ],\r\n \"apiVersions\": [\r\n \"2018-09-01-preview\"\r\n ]\r\n }\r\n ],\r\n \"registrationState\": \"Registered\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/artifactSources/powershell-sdk-tests-functional?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9hcnRpZmFjdFNvdXJjZXMvcG93ZXJzaGVsbC1zZGstdGVzdHMtZnVuY3Rpb25hbD9hcGktdmVyc2lvbj0yMDE4LTA5LTAxLXByZXZpZXc=", + "RequestMethod": "GET", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "985057fd-08d5-4657-a0c1-328cb63deb28" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-failure-cause": [ + "gateway" + ], + "x-ms-request-id": [ + "a1faf2aa-579d-4e87-9924-b4a7e21dfef6" + ], + "x-ms-correlation-request-id": [ + "a1faf2aa-579d-4e87-9924-b4a7e21dfef6" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183101Z:a1faf2aa-579d-4e87-9924-b4a7e21dfef6" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:31:00 GMT" + ], + "Content-Length": [ + "201" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"error\": {\r\n \"code\": \"ResourceNotFound\",\r\n \"message\": \"The Resource 'Microsoft.DeploymentManager/artifactSources/powershell-sdk-tests-functional' under resource group 'adm-powershell-test-rg' was not found.\"\r\n }\r\n}", + "StatusCode": 404 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/artifactSources/powershell-sdk-tests-functional?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9hcnRpZmFjdFNvdXJjZXMvcG93ZXJzaGVsbC1zZGstdGVzdHMtZnVuY3Rpb25hbD9hcGktdmVyc2lvbj0yMDE4LTA5LTAxLXByZXZpZXc=", + "RequestMethod": "GET", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "24adc3b4-1781-4162-879f-f9a821e9b235" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-failure-cause": [ + "gateway" + ], + "x-ms-request-id": [ + "11fdc155-4e63-4c53-b2de-79e727250e78" + ], + "x-ms-correlation-request-id": [ + "11fdc155-4e63-4c53-b2de-79e727250e78" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183859Z:11fdc155-4e63-4c53-b2de-79e727250e78" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:38:58 GMT" + ], + "Content-Length": [ + "201" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"error\": {\r\n \"code\": \"ResourceNotFound\",\r\n \"message\": \"The Resource 'Microsoft.DeploymentManager/artifactSources/powershell-sdk-tests-functional' under resource group 'adm-powershell-test-rg' was not found.\"\r\n }\r\n}", + "StatusCode": 404 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/artifactSources/powershell-sdk-tests-functional?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9hcnRpZmFjdFNvdXJjZXMvcG93ZXJzaGVsbC1zZGstdGVzdHMtZnVuY3Rpb25hbD9hcGktdmVyc2lvbj0yMDE4LTA5LTAxLXByZXZpZXc=", + "RequestMethod": "PUT", + "RequestBody": "{\r\n \"properties\": {\r\n \"sourceType\": \"AzureStorage\",\r\n \"artifactRoot\": \"builds/1.0.0.0\",\r\n \"authentication\": {\r\n \"type\": \"Sas\",\r\n \"properties\": {\r\n \"sasUri\": \"https://sdktests.blob.core.windows.net/artifacts?sv=2017-07-29&sr=c&sig=lANfKqVRCWkl7S%2FxOggDeDoSmbpFoKG1YVGKL2A3zEQ%3D&st=2019-03-14T22%3A30%3A56Z&se=2019-03-17T18%3A30%3A56Z&sp=rl\"\r\n }\r\n }\r\n },\r\n \"location\": \"Central US\"\r\n}", + "RequestHeaders": { + "x-ms-client-request-id": [ + "3b320ce8-1d88-4fc8-8f45-ce19f50f4620" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Content-Length": [ + "421" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-client-request-id": [ + "3b320ce8-1d88-4fc8-8f45-ce19f50f4620" + ], + "x-ms-correlation-request-id": [ + "adea6bf0-2c61-4d59-a1e0-8d3e2cc3d2b2" + ], + "x-ms-request-id": [ + "6f424882-1dd2-44d8-8887-fa15aff69186" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "X-Frame-Options": [ + "DENY" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1199" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183106Z:adea6bf0-2c61-4d59-a1e0-8d3e2cc3d2b2" + ], + "Cache-Control": [ + "no-store, no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:31:05 GMT" + ], + "Content-Length": [ + "684" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"properties\": {\r\n \"sourceType\": \"AzureStorage\",\r\n \"artifactRoot\": \"builds/1.0.0.0\",\r\n \"authentication\": {\r\n \"type\": \"Sas\",\r\n \"properties\": {\r\n \"sasUri\": \"https://sdktests.blob.core.windows.net/artifacts?sv=2017-07-29&sr=c&sig=lANfKqVRCWkl7S%2FxOggDeDoSmbpFoKG1YVGKL2A3zEQ%3D&st=2019-03-14T22%3A30%3A56Z&se=2019-03-17T18%3A30%3A56Z&sp=rl\"\r\n }\r\n },\r\n \"provisioningState\": \"Succeeded\"\r\n },\r\n \"type\": \"Microsoft.DeploymentManager/artifactSources\",\r\n \"apiVersion\": \"2018-09-01-preview\",\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/artifactSources/powershell-sdk-tests-functional\",\r\n \"name\": \"powershell-sdk-tests-functional\",\r\n \"location\": \"Central US\"\r\n}", + "StatusCode": 201 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9zZXJ2aWNlVG9wb2xvZ2llcy9wb3dlcnNoZWxsLXNkay10ZXN0cz9hcGktdmVyc2lvbj0yMDE4LTA5LTAxLXByZXZpZXc=", + "RequestMethod": "GET", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "8709aa55-5264-4868-8e7d-4d410cefe5a4" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-failure-cause": [ + "gateway" + ], + "x-ms-request-id": [ + "a5e2305d-03e2-46d2-9aca-032c25c2263f" + ], + "x-ms-correlation-request-id": [ + "a5e2305d-03e2-46d2-9aca-032c25c2263f" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183108Z:a5e2305d-03e2-46d2-9aca-032c25c2263f" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:31:08 GMT" + ], + "Content-Length": [ + "192" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"error\": {\r\n \"code\": \"ResourceNotFound\",\r\n \"message\": \"The Resource 'Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests' under resource group 'adm-powershell-test-rg' was not found.\"\r\n }\r\n}", + "StatusCode": 404 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9zZXJ2aWNlVG9wb2xvZ2llcy9wb3dlcnNoZWxsLXNkay10ZXN0cz9hcGktdmVyc2lvbj0yMDE4LTA5LTAxLXByZXZpZXc=", + "RequestMethod": "GET", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "c28d8f10-bcad-4d3d-8efb-2a0d431354f5" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-client-request-id": [ + "c28d8f10-bcad-4d3d-8efb-2a0d431354f5" + ], + "x-ms-correlation-request-id": [ + "8c4c1b9f-1243-4c98-a1e1-10509ca0df9c" + ], + "x-ms-request-id": [ + "b1761b86-ef1c-4036-87a0-8ef78a2e9637" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "X-Frame-Options": [ + "DENY" + ], + "x-ms-ratelimit-remaining-subscription-reads": [ + "11997" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183112Z:8c4c1b9f-1243-4c98-a1e1-10509ca0df9c" + ], + "Cache-Control": [ + "no-store, no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:31:11 GMT" + ], + "Content-Length": [ + "530" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"properties\": {\r\n \"artifactSourceId\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/artifactSources/powershell-sdk-tests-functional\"\r\n },\r\n \"type\": \"Microsoft.DeploymentManager/servicetopologies\",\r\n \"apiVersion\": \"2018-09-01-preview\",\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests\",\r\n \"name\": \"powershell-sdk-tests\",\r\n \"location\": \"Central US\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9zZXJ2aWNlVG9wb2xvZ2llcy9wb3dlcnNoZWxsLXNkay10ZXN0cz9hcGktdmVyc2lvbj0yMDE4LTA5LTAxLXByZXZpZXc=", + "RequestMethod": "GET", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "36ca10ec-437b-4450-bfc5-f0ba9eeeca6f" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-failure-cause": [ + "gateway" + ], + "x-ms-request-id": [ + "a0829b00-68cf-4985-97b8-09d8f4e6cdc7" + ], + "x-ms-correlation-request-id": [ + "a0829b00-68cf-4985-97b8-09d8f4e6cdc7" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183855Z:a0829b00-68cf-4985-97b8-09d8f4e6cdc7" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:38:54 GMT" + ], + "Content-Length": [ + "192" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"error\": {\r\n \"code\": \"ResourceNotFound\",\r\n \"message\": \"The Resource 'Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests' under resource group 'adm-powershell-test-rg' was not found.\"\r\n }\r\n}", + "StatusCode": 404 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9zZXJ2aWNlVG9wb2xvZ2llcy9wb3dlcnNoZWxsLXNkay10ZXN0cz9hcGktdmVyc2lvbj0yMDE4LTA5LTAxLXByZXZpZXc=", + "RequestMethod": "PUT", + "RequestBody": "{\r\n \"properties\": {\r\n \"artifactSourceId\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/artifactSources/powershell-sdk-tests-functional\"\r\n },\r\n \"location\": \"Central US\"\r\n}", + "RequestHeaders": { + "x-ms-client-request-id": [ + "4cef983e-4468-41ed-9d8c-acb100b4581e" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Content-Length": [ + "260" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-client-request-id": [ + "4cef983e-4468-41ed-9d8c-acb100b4581e" + ], + "x-ms-correlation-request-id": [ + "3f5c1a03-ff69-46f6-b63f-04a9a040b70f" + ], + "x-ms-request-id": [ + "d2141120-7566-4f78-8d6e-061cfb252b54" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "X-Frame-Options": [ + "DENY" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1198" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183110Z:3f5c1a03-ff69-46f6-b63f-04a9a040b70f" + ], + "Cache-Control": [ + "no-store, no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:31:10 GMT" + ], + "Content-Length": [ + "562" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"properties\": {\r\n \"artifactSourceId\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/artifactSources/powershell-sdk-tests-functional\",\r\n \"provisioningState\": \"Succeeded\"\r\n },\r\n \"type\": \"Microsoft.DeploymentManager/servicetopologies\",\r\n \"apiVersion\": \"2018-09-01-preview\",\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests\",\r\n \"name\": \"powershell-sdk-tests\",\r\n \"location\": \"Central US\"\r\n}", + "StatusCode": 201 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9zZXJ2aWNlVG9wb2xvZ2llcy9wb3dlcnNoZWxsLXNkay10ZXN0cz9hcGktdmVyc2lvbj0yMDE4LTA5LTAxLXByZXZpZXc=", + "RequestMethod": "PUT", + "RequestBody": "{\r\n \"properties\": {\r\n \"artifactSourceId\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/artifactSources/powershell-sdk-tests\"\r\n },\r\n \"location\": \"Central US\"\r\n}", + "RequestHeaders": { + "x-ms-client-request-id": [ + "88fe7e52-1ac2-45aa-a767-6b5443d3c796" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Content-Length": [ + "249" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-client-request-id": [ + "88fe7e52-1ac2-45aa-a767-6b5443d3c796" + ], + "x-ms-correlation-request-id": [ + "700600d4-c87d-4f4c-b32a-c774aeef7f79" + ], + "x-ms-request-id": [ + "7aa822a3-d88b-4ddf-8a12-326b229a40d1" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "X-Frame-Options": [ + "DENY" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1194" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183852Z:700600d4-c87d-4f4c-b32a-c774aeef7f79" + ], + "Cache-Control": [ + "no-store, no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:38:51 GMT" + ], + "Content-Length": [ + "551" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"properties\": {\r\n \"artifactSourceId\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/artifactSources/powershell-sdk-tests\",\r\n \"provisioningState\": \"Succeeded\"\r\n },\r\n \"type\": \"Microsoft.DeploymentManager/servicetopologies\",\r\n \"apiVersion\": \"2018-09-01-preview\",\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests\",\r\n \"name\": \"powershell-sdk-tests\",\r\n \"location\": \"Central US\"\r\n}", + "StatusCode": 201 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9zZXJ2aWNlVG9wb2xvZ2llcy9wb3dlcnNoZWxsLXNkay10ZXN0cy9zZXJ2aWNlcy9Db250b3NvX1NlcnZpY2U/YXBpLXZlcnNpb249MjAxOC0wOS0wMS1wcmV2aWV3", + "RequestMethod": "GET", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "80d641e0-ce83-4399-8a07-ba0b30fd005c" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-failure-cause": [ + "gateway" + ], + "x-ms-request-id": [ + "38bfda1d-b682-4895-b473-d021a07b73d9" + ], + "x-ms-correlation-request-id": [ + "38bfda1d-b682-4895-b473-d021a07b73d9" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183113Z:38bfda1d-b682-4895-b473-d021a07b73d9" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:31:12 GMT" + ], + "Content-Length": [ + "217" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"error\": {\r\n \"code\": \"ResourceNotFound\",\r\n \"message\": \"The Resource 'Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service' under resource group 'adm-powershell-test-rg' was not found.\"\r\n }\r\n}", + "StatusCode": 404 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9zZXJ2aWNlVG9wb2xvZ2llcy9wb3dlcnNoZWxsLXNkay10ZXN0cy9zZXJ2aWNlcy9Db250b3NvX1NlcnZpY2U/YXBpLXZlcnNpb249MjAxOC0wOS0wMS1wcmV2aWV3", + "RequestMethod": "GET", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "dea4a7eb-3c70-4596-a9c1-991c9ffb90e4" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-client-request-id": [ + "dea4a7eb-3c70-4596-a9c1-991c9ffb90e4" + ], + "x-ms-correlation-request-id": [ + "1e9bbe42-ea67-4b37-b738-101d5148b7f0" + ], + "x-ms-request-id": [ + "c25e815e-b65a-45ec-a8c5-52c1eae6564e" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "X-Frame-Options": [ + "DENY" + ], + "x-ms-ratelimit-remaining-subscription-reads": [ + "11999" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183119Z:1e9bbe42-ea67-4b37-b738-101d5148b7f0" + ], + "Cache-Control": [ + "no-store, no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:31:18 GMT" + ], + "Content-Length": [ + "485" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"properties\": {\r\n \"targetSubscriptionId\": \"53012dcb-5039-4e96-8e6c-5d913da1cdb5\",\r\n \"targetLocation\": \"East US 2\",\r\n \"provisioningState\": \"Succeeded\"\r\n },\r\n \"type\": \"Microsoft.DeploymentManager/serviceTopologies/services\",\r\n \"apiVersion\": \"2018-09-01-preview\",\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service\",\r\n \"name\": \"Contoso_Service\",\r\n \"location\": \"Central US\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9zZXJ2aWNlVG9wb2xvZ2llcy9wb3dlcnNoZWxsLXNkay10ZXN0cy9zZXJ2aWNlcy9Db250b3NvX1NlcnZpY2U/YXBpLXZlcnNpb249MjAxOC0wOS0wMS1wcmV2aWV3", + "RequestMethod": "GET", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "49a9daed-4256-446f-88d5-5bff561efa54" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-failure-cause": [ + "gateway" + ], + "x-ms-request-id": [ + "e8f29bdd-bba3-4034-aee4-f97d02f11e1c" + ], + "x-ms-correlation-request-id": [ + "e8f29bdd-bba3-4034-aee4-f97d02f11e1c" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183846Z:e8f29bdd-bba3-4034-aee4-f97d02f11e1c" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:38:45 GMT" + ], + "Content-Length": [ + "217" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"error\": {\r\n \"code\": \"ResourceNotFound\",\r\n \"message\": \"The Resource 'Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service' under resource group 'adm-powershell-test-rg' was not found.\"\r\n }\r\n}", + "StatusCode": 404 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9zZXJ2aWNlVG9wb2xvZ2llcy9wb3dlcnNoZWxsLXNkay10ZXN0cy9zZXJ2aWNlcy9Db250b3NvX1NlcnZpY2U/YXBpLXZlcnNpb249MjAxOC0wOS0wMS1wcmV2aWV3", + "RequestMethod": "PUT", + "RequestBody": "{\r\n \"properties\": {\r\n \"targetLocation\": \"East US 2\",\r\n \"targetSubscriptionId\": \"53012dcb-5039-4e96-8e6c-5d913da1cdb5\"\r\n },\r\n \"location\": \"Central US\"\r\n}", + "RequestHeaders": { + "x-ms-client-request-id": [ + "52f1abec-9a58-4fa4-8f5b-47aad279078d" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Content-Length": [ + "161" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-client-request-id": [ + "52f1abec-9a58-4fa4-8f5b-47aad279078d" + ], + "x-ms-correlation-request-id": [ + "138785af-0ac0-49c2-abcf-cee441fdd69c" + ], + "x-ms-request-id": [ + "bbaf65fc-cab8-4f8c-bb09-6b7f2b7a123c" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "X-Frame-Options": [ + "DENY" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1199" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183116Z:138785af-0ac0-49c2-abcf-cee441fdd69c" + ], + "Cache-Control": [ + "no-store, no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:31:16 GMT" + ], + "Content-Length": [ + "485" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"properties\": {\r\n \"targetSubscriptionId\": \"53012dcb-5039-4e96-8e6c-5d913da1cdb5\",\r\n \"targetLocation\": \"East US 2\",\r\n \"provisioningState\": \"Succeeded\"\r\n },\r\n \"type\": \"Microsoft.DeploymentManager/serviceTopologies/services\",\r\n \"apiVersion\": \"2018-09-01-preview\",\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service\",\r\n \"name\": \"Contoso_Service\",\r\n \"location\": \"Central US\"\r\n}", + "StatusCode": 201 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9zZXJ2aWNlVG9wb2xvZ2llcy9wb3dlcnNoZWxsLXNkay10ZXN0cy9zZXJ2aWNlcy9Db250b3NvX1NlcnZpY2U/YXBpLXZlcnNpb249MjAxOC0wOS0wMS1wcmV2aWV3", + "RequestMethod": "PUT", + "RequestBody": "{\r\n \"properties\": {\r\n \"targetLocation\": \"East US 2\",\r\n \"targetSubscriptionId\": \"1e591dc1-b014-4754-b53b-58b67bcab1cd\"\r\n },\r\n \"location\": \"Central US\"\r\n}", + "RequestHeaders": { + "x-ms-client-request-id": [ + "4fd006e4-2609-435e-9857-59e8dd9347ac" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Content-Length": [ + "161" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-client-request-id": [ + "4fd006e4-2609-435e-9857-59e8dd9347ac" + ], + "x-ms-correlation-request-id": [ + "6d29ee07-7378-42e6-8cad-a155a86fd3de" + ], + "x-ms-request-id": [ + "c98201b0-159a-4ab2-8687-29a30877c7d8" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "X-Frame-Options": [ + "DENY" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1197" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183842Z:6d29ee07-7378-42e6-8cad-a155a86fd3de" + ], + "Cache-Control": [ + "no-store, no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:38:42 GMT" + ], + "Content-Length": [ + "485" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"properties\": {\r\n \"targetSubscriptionId\": \"1e591dc1-b014-4754-b53b-58b67bcab1cd\",\r\n \"targetLocation\": \"East US 2\",\r\n \"provisioningState\": \"Succeeded\"\r\n },\r\n \"type\": \"Microsoft.DeploymentManager/serviceTopologies/services\",\r\n \"apiVersion\": \"2018-09-01-preview\",\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service\",\r\n \"name\": \"Contoso_Service\",\r\n \"location\": \"Central US\"\r\n}", + "StatusCode": 201 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service/serviceUnits/Contoso_WebApp?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9zZXJ2aWNlVG9wb2xvZ2llcy9wb3dlcnNoZWxsLXNkay10ZXN0cy9zZXJ2aWNlcy9Db250b3NvX1NlcnZpY2Uvc2VydmljZVVuaXRzL0NvbnRvc29fV2ViQXBwP2FwaS12ZXJzaW9uPTIwMTgtMDktMDEtcHJldmlldw==", + "RequestMethod": "GET", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "b32d38a0-0e33-45ed-acde-1dd1506bb89a" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-failure-cause": [ + "gateway" + ], + "x-ms-request-id": [ + "f7557a4a-536e-4cac-accb-9ecf6ac581a9" + ], + "x-ms-correlation-request-id": [ + "f7557a4a-536e-4cac-accb-9ecf6ac581a9" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183121Z:f7557a4a-536e-4cac-accb-9ecf6ac581a9" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:31:20 GMT" + ], + "Content-Length": [ + "245" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"error\": {\r\n \"code\": \"ResourceNotFound\",\r\n \"message\": \"The Resource 'Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service/serviceUnits/Contoso_WebApp' under resource group 'adm-powershell-test-rg' was not found.\"\r\n }\r\n}", + "StatusCode": 404 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service/serviceUnits/Contoso_WebApp?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9zZXJ2aWNlVG9wb2xvZ2llcy9wb3dlcnNoZWxsLXNkay10ZXN0cy9zZXJ2aWNlcy9Db250b3NvX1NlcnZpY2Uvc2VydmljZVVuaXRzL0NvbnRvc29fV2ViQXBwP2FwaS12ZXJzaW9uPTIwMTgtMDktMDEtcHJldmlldw==", + "RequestMethod": "GET", + "RequestBody": "", + "RequestHeaders": { + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-client-request-id": [ + "c4bd91e4-8521-44e4-bbf7-fb870907bf69" + ], + "x-ms-correlation-request-id": [ + "63463ceb-c5a6-416e-973c-e7e67d8d6432" + ], + "x-ms-request-id": [ + "9efec023-f825-4952-bcc0-0c1c5727d736" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "X-Frame-Options": [ + "DENY" + ], + "x-ms-ratelimit-remaining-subscription-reads": [ + "11996" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183156Z:63463ceb-c5a6-416e-973c-e7e67d8d6432" + ], + "Cache-Control": [ + "no-store, no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:31:56 GMT" + ], + "Content-Length": [ + "676" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"properties\": {\r\n \"targetResourceGroup\": \"sdk-net-targetResourceGroup\",\r\n \"deploymentMode\": \"Incremental\",\r\n \"artifacts\": {\r\n \"templateArtifactSourceRelativePath\": \"Templates/WebApp.Template.json\",\r\n \"parametersArtifactSourceRelativePath\": \"Parameters/WebApp.Parameters.json\"\r\n },\r\n \"provisioningState\": \"Succeeded\"\r\n },\r\n \"type\": \"Microsoft.DeploymentManager/serviceTopologies/services/serviceUnits\",\r\n \"apiVersion\": \"2018-09-01-preview\",\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service/serviceUnits/Contoso_WebApp\",\r\n \"name\": \"Contoso_WebApp\",\r\n \"location\": \"Central US\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service/serviceUnits/Contoso_WebApp?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9zZXJ2aWNlVG9wb2xvZ2llcy9wb3dlcnNoZWxsLXNkay10ZXN0cy9zZXJ2aWNlcy9Db250b3NvX1NlcnZpY2Uvc2VydmljZVVuaXRzL0NvbnRvc29fV2ViQXBwP2FwaS12ZXJzaW9uPTIwMTgtMDktMDEtcHJldmlldw==", + "RequestMethod": "GET", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "f0346076-c7b6-490b-9f5a-ec7bba8d9778" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-client-request-id": [ + "f0346076-c7b6-490b-9f5a-ec7bba8d9778" + ], + "x-ms-correlation-request-id": [ + "09f78600-5828-451d-a170-a023c0e639df" + ], + "x-ms-request-id": [ + "a1da47fd-5920-4aa1-88c2-d01fb471947f" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "X-Frame-Options": [ + "DENY" + ], + "x-ms-ratelimit-remaining-subscription-reads": [ + "11995" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183217Z:09f78600-5828-451d-a170-a023c0e639df" + ], + "Cache-Control": [ + "no-store, no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:32:17 GMT" + ], + "Content-Length": [ + "676" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"properties\": {\r\n \"targetResourceGroup\": \"sdk-net-targetResourceGroup\",\r\n \"deploymentMode\": \"Incremental\",\r\n \"artifacts\": {\r\n \"templateArtifactSourceRelativePath\": \"Templates/WebApp.Template.json\",\r\n \"parametersArtifactSourceRelativePath\": \"Parameters/WebApp.Parameters.json\"\r\n },\r\n \"provisioningState\": \"Succeeded\"\r\n },\r\n \"type\": \"Microsoft.DeploymentManager/serviceTopologies/services/serviceUnits\",\r\n \"apiVersion\": \"2018-09-01-preview\",\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service/serviceUnits/Contoso_WebApp\",\r\n \"name\": \"Contoso_WebApp\",\r\n \"location\": \"Central US\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service/serviceUnits/Contoso_WebApp?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9zZXJ2aWNlVG9wb2xvZ2llcy9wb3dlcnNoZWxsLXNkay10ZXN0cy9zZXJ2aWNlcy9Db250b3NvX1NlcnZpY2Uvc2VydmljZVVuaXRzL0NvbnRvc29fV2ViQXBwP2FwaS12ZXJzaW9uPTIwMTgtMDktMDEtcHJldmlldw==", + "RequestMethod": "GET", + "RequestBody": "", + "RequestHeaders": { + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-client-request-id": [ + "429d2a4b-7613-4726-b284-684655d0100d" + ], + "x-ms-correlation-request-id": [ + "0c629033-e53b-45dd-b04e-658e38ab5d6c" + ], + "x-ms-request-id": [ + "8509b35c-7724-48fc-b412-d9551290b267" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "X-Frame-Options": [ + "DENY" + ], + "x-ms-ratelimit-remaining-subscription-reads": [ + "11996" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183835Z:0c629033-e53b-45dd-b04e-658e38ab5d6c" + ], + "Cache-Control": [ + "no-store, no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:38:35 GMT" + ], + "Content-Length": [ + "681" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"properties\": {\r\n \"targetResourceGroup\": \"sdk-net-targetResourceGroup\",\r\n \"deploymentMode\": \"Complete\",\r\n \"artifacts\": {\r\n \"templateArtifactSourceRelativePath\": \"Templates/WebApp.Template.Dup.json\",\r\n \"parametersArtifactSourceRelativePath\": \"Parameters/WebApp.Parameters.Dup.json\"\r\n },\r\n \"provisioningState\": \"Succeeded\"\r\n },\r\n \"type\": \"Microsoft.DeploymentManager/serviceTopologies/services/serviceUnits\",\r\n \"apiVersion\": \"2018-09-01-preview\",\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service/serviceUnits/Contoso_WebApp\",\r\n \"name\": \"Contoso_WebApp\",\r\n \"location\": \"Central US\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service/serviceUnits/Contoso_WebApp?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9zZXJ2aWNlVG9wb2xvZ2llcy9wb3dlcnNoZWxsLXNkay10ZXN0cy9zZXJ2aWNlcy9Db250b3NvX1NlcnZpY2Uvc2VydmljZVVuaXRzL0NvbnRvc29fV2ViQXBwP2FwaS12ZXJzaW9uPTIwMTgtMDktMDEtcHJldmlldw==", + "RequestMethod": "GET", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "73c92330-9ca0-45ba-b479-73b8ea4070fc" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-failure-cause": [ + "gateway" + ], + "x-ms-request-id": [ + "190ec849-93c4-4b3d-a7b9-586778d073f8" + ], + "x-ms-correlation-request-id": [ + "190ec849-93c4-4b3d-a7b9-586778d073f8" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183840Z:190ec849-93c4-4b3d-a7b9-586778d073f8" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:38:40 GMT" + ], + "Content-Length": [ + "245" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"error\": {\r\n \"code\": \"ResourceNotFound\",\r\n \"message\": \"The Resource 'Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service/serviceUnits/Contoso_WebApp' under resource group 'adm-powershell-test-rg' was not found.\"\r\n }\r\n}", + "StatusCode": 404 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service/serviceUnits/Contoso_WebApp?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9zZXJ2aWNlVG9wb2xvZ2llcy9wb3dlcnNoZWxsLXNkay10ZXN0cy9zZXJ2aWNlcy9Db250b3NvX1NlcnZpY2Uvc2VydmljZVVuaXRzL0NvbnRvc29fV2ViQXBwP2FwaS12ZXJzaW9uPTIwMTgtMDktMDEtcHJldmlldw==", + "RequestMethod": "PUT", + "RequestBody": "{\r\n \"properties\": {\r\n \"targetResourceGroup\": \"sdk-net-targetResourceGroup\",\r\n \"deploymentMode\": \"Incremental\",\r\n \"artifacts\": {\r\n \"templateArtifactSourceRelativePath\": \"Templates/WebApp.Template.json\",\r\n \"parametersArtifactSourceRelativePath\": \"Parameters/WebApp.Parameters.json\"\r\n }\r\n },\r\n \"location\": \"Central US\"\r\n}", + "RequestHeaders": { + "x-ms-client-request-id": [ + "df51580b-dfd2-48ca-a1ec-e3dc382323aa" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Content-Length": [ + "343" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "Retry-After": [ + "31" + ], + "Azure-AsyncOperation": [ + "https://management.azure.com/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/operationResults/d5cfccd1-5cee-4452-be0f-1a6ba5164930?api-version=2018-09-01-preview" + ], + "x-ms-client-request-id": [ + "df51580b-dfd2-48ca-a1ec-e3dc382323aa" + ], + "x-ms-correlation-request-id": [ + "4c31355e-25be-4a86-aebc-fd25e7fc0ce5" + ], + "x-ms-request-id": [ + "d5cfccd1-5cee-4452-be0f-1a6ba5164930" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "X-Frame-Options": [ + "DENY" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1198" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183124Z:4c31355e-25be-4a86-aebc-fd25e7fc0ce5" + ], + "Cache-Control": [ + "no-store, no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:31:23 GMT" + ], + "Location": [ + "https://management.azure.com/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/operationResults/d5cfccd1-5cee-4452-be0f-1a6ba5164930?api-version=2018-09-01-preview" + ], + "Content-Length": [ + "674" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"properties\": {\r\n \"targetResourceGroup\": \"sdk-net-targetResourceGroup\",\r\n \"deploymentMode\": \"Incremental\",\r\n \"artifacts\": {\r\n \"templateArtifactSourceRelativePath\": \"Templates/WebApp.Template.json\",\r\n \"parametersArtifactSourceRelativePath\": \"Parameters/WebApp.Parameters.json\"\r\n },\r\n \"provisioningState\": \"Running\"\r\n },\r\n \"type\": \"Microsoft.DeploymentManager/serviceTopologies/services/serviceUnits\",\r\n \"apiVersion\": \"2018-09-01-preview\",\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service/serviceUnits/Contoso_WebApp\",\r\n \"name\": \"Contoso_WebApp\",\r\n \"location\": \"Central US\"\r\n}", + "StatusCode": 201 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service/serviceUnits/Contoso_WebApp?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9zZXJ2aWNlVG9wb2xvZ2llcy9wb3dlcnNoZWxsLXNkay10ZXN0cy9zZXJ2aWNlcy9Db250b3NvX1NlcnZpY2Uvc2VydmljZVVuaXRzL0NvbnRvc29fV2ViQXBwP2FwaS12ZXJzaW9uPTIwMTgtMDktMDEtcHJldmlldw==", + "RequestMethod": "PUT", + "RequestBody": "{\r\n \"properties\": {\r\n \"targetResourceGroup\": \"sdk-net-targetResourceGroup\",\r\n \"deploymentMode\": \"Complete\",\r\n \"artifacts\": {\r\n \"templateArtifactSourceRelativePath\": \"Templates/WebApp.Template.Dup.json\",\r\n \"parametersArtifactSourceRelativePath\": \"Parameters/WebApp.Parameters.Dup.json\"\r\n }\r\n },\r\n \"location\": \"Central US\"\r\n}", + "RequestHeaders": { + "x-ms-client-request-id": [ + "eb5e5f71-ae9e-4540-b21a-bbcc2aec69f7" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Content-Length": [ + "348" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "Retry-After": [ + "35" + ], + "Azure-AsyncOperation": [ + "https://management.azure.com/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/operationResults/30905b59-e548-4c0a-b7d8-9db0e4567238?api-version=2018-09-01-preview" + ], + "x-ms-client-request-id": [ + "eb5e5f71-ae9e-4540-b21a-bbcc2aec69f7" + ], + "x-ms-correlation-request-id": [ + "5e7f90ba-3557-43b1-acad-2122d08d1f3b" + ], + "x-ms-request-id": [ + "30905b59-e548-4c0a-b7d8-9db0e4567238" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "X-Frame-Options": [ + "DENY" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1198" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183759Z:5e7f90ba-3557-43b1-acad-2122d08d1f3b" + ], + "Cache-Control": [ + "no-store, no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:37:58 GMT" + ], + "Location": [ + "https://management.azure.com/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/operationResults/30905b59-e548-4c0a-b7d8-9db0e4567238?api-version=2018-09-01-preview" + ], + "Content-Length": [ + "679" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"properties\": {\r\n \"targetResourceGroup\": \"sdk-net-targetResourceGroup\",\r\n \"deploymentMode\": \"Complete\",\r\n \"artifacts\": {\r\n \"templateArtifactSourceRelativePath\": \"Templates/WebApp.Template.Dup.json\",\r\n \"parametersArtifactSourceRelativePath\": \"Parameters/WebApp.Parameters.Dup.json\"\r\n },\r\n \"provisioningState\": \"Running\"\r\n },\r\n \"type\": \"Microsoft.DeploymentManager/serviceTopologies/services/serviceUnits\",\r\n \"apiVersion\": \"2018-09-01-preview\",\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service/serviceUnits/Contoso_WebApp\",\r\n \"name\": \"Contoso_WebApp\",\r\n \"location\": \"Central US\"\r\n}", + "StatusCode": 201 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/operationResults/d5cfccd1-5cee-4452-be0f-1a6ba5164930?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlZ3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9vcGVyYXRpb25SZXN1bHRzL2Q1Y2ZjY2QxLTVjZWUtNDQ1Mi1iZTBmLTFhNmJhNTE2NDkzMD9hcGktdmVyc2lvbj0yMDE4LTA5LTAxLXByZXZpZXc=", + "RequestMethod": "GET", + "RequestBody": "", + "RequestHeaders": { + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "Retry-After": [ + "30" + ], + "x-ms-client-request-id": [ + "37a23c70-fadc-4272-9488-a799c8dc04fb" + ], + "x-ms-correlation-request-id": [ + "f31e018c-42cf-49df-b573-60e6d8cd2eb9" + ], + "x-ms-request-id": [ + "a07c310f-51c0-4078-ae2e-8726e96f7f2c" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "X-Frame-Options": [ + "DENY" + ], + "x-ms-ratelimit-remaining-subscription-reads": [ + "11997" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183156Z:f31e018c-42cf-49df-b573-60e6d8cd2eb9" + ], + "Cache-Control": [ + "no-store, no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:31:55 GMT" + ], + "Location": [ + "https://management.azure.com/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service/serviceUnits/Contoso_WebApp?api-version=2018-09-01-preview" + ], + "Content-Length": [ + "106" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"status\": \"Succeeded\",\r\n \"startTime\": \"2019-03-15T18:31:23.721Z\",\r\n \"endTime\": \"2019-03-15T18:31:27.002Z\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service/serviceUnits/Contoso_WebApp_Invalid?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9zZXJ2aWNlVG9wb2xvZ2llcy9wb3dlcnNoZWxsLXNkay10ZXN0cy9zZXJ2aWNlcy9Db250b3NvX1NlcnZpY2Uvc2VydmljZVVuaXRzL0NvbnRvc29fV2ViQXBwX0ludmFsaWQ/YXBpLXZlcnNpb249MjAxOC0wOS0wMS1wcmV2aWV3", + "RequestMethod": "GET", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "947e8ec2-961a-4d2c-8ba7-723e641cdae7" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-failure-cause": [ + "gateway" + ], + "x-ms-request-id": [ + "c8433ab6-95b4-411a-96b0-666524bdb209" + ], + "x-ms-correlation-request-id": [ + "c8433ab6-95b4-411a-96b0-666524bdb209" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183219Z:c8433ab6-95b4-411a-96b0-666524bdb209" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:32:18 GMT" + ], + "Content-Length": [ + "253" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"error\": {\r\n \"code\": \"ResourceNotFound\",\r\n \"message\": \"The Resource 'Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service/serviceUnits/Contoso_WebApp_Invalid' under resource group 'adm-powershell-test-rg' was not found.\"\r\n }\r\n}", + "StatusCode": 404 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service/serviceUnits/Contoso_WebApp_Invalid?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9zZXJ2aWNlVG9wb2xvZ2llcy9wb3dlcnNoZWxsLXNkay10ZXN0cy9zZXJ2aWNlcy9Db250b3NvX1NlcnZpY2Uvc2VydmljZVVuaXRzL0NvbnRvc29fV2ViQXBwX0ludmFsaWQ/YXBpLXZlcnNpb249MjAxOC0wOS0wMS1wcmV2aWV3", + "RequestMethod": "GET", + "RequestBody": "", + "RequestHeaders": { + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-client-request-id": [ + "67ec4281-33e7-43b4-9cd8-240ad2017288" + ], + "x-ms-correlation-request-id": [ + "5e1da007-c6ed-4431-8466-766b0aa765cd" + ], + "x-ms-request-id": [ + "b3aaad90-686d-4321-9eff-d8211fe539d5" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "X-Frame-Options": [ + "DENY" + ], + "x-ms-ratelimit-remaining-subscription-reads": [ + "11999" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183317Z:5e1da007-c6ed-4431-8466-766b0aa765cd" + ], + "Cache-Control": [ + "no-store, no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:33:16 GMT" + ], + "Content-Length": [ + "700" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"properties\": {\r\n \"targetResourceGroup\": \"sdk-net-targetResourceGroup\",\r\n \"deploymentMode\": \"Incremental\",\r\n \"artifacts\": {\r\n \"templateArtifactSourceRelativePath\": \"Templates/WebApp.Template.json\",\r\n \"parametersArtifactSourceRelativePath\": \"Parameters/WebApp.Invalid.Parameters.json\"\r\n },\r\n \"provisioningState\": \"Succeeded\"\r\n },\r\n \"type\": \"Microsoft.DeploymentManager/serviceTopologies/services/serviceUnits\",\r\n \"apiVersion\": \"2018-09-01-preview\",\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service/serviceUnits/Contoso_WebApp_Invalid\",\r\n \"name\": \"Contoso_WebApp_Invalid\",\r\n \"location\": \"Central US\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service/serviceUnits/Contoso_WebApp_Invalid?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9zZXJ2aWNlVG9wb2xvZ2llcy9wb3dlcnNoZWxsLXNkay10ZXN0cy9zZXJ2aWNlcy9Db250b3NvX1NlcnZpY2Uvc2VydmljZVVuaXRzL0NvbnRvc29fV2ViQXBwX0ludmFsaWQ/YXBpLXZlcnNpb249MjAxOC0wOS0wMS1wcmV2aWV3", + "RequestMethod": "PUT", + "RequestBody": "{\r\n \"properties\": {\r\n \"targetResourceGroup\": \"sdk-net-targetResourceGroup\",\r\n \"deploymentMode\": \"Incremental\",\r\n \"artifacts\": {\r\n \"templateArtifactSourceRelativePath\": \"Templates/WebApp.Template.json\",\r\n \"parametersArtifactSourceRelativePath\": \"Parameters/WebApp.Invalid.Parameters.json\"\r\n }\r\n },\r\n \"location\": \"Central US\"\r\n}", + "RequestHeaders": { + "x-ms-client-request-id": [ + "f2eeacf4-d7f5-47c1-954a-596fc7ae254e" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Content-Length": [ + "351" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "Retry-After": [ + "51" + ], + "Azure-AsyncOperation": [ + "https://management.azure.com/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/operationResults/b833d91d-cd57-4d3d-9967-8df244082018?api-version=2018-09-01-preview" + ], + "x-ms-client-request-id": [ + "f2eeacf4-d7f5-47c1-954a-596fc7ae254e" + ], + "x-ms-correlation-request-id": [ + "8bb7e9a2-a655-4174-a8c7-d16cf5a8834d" + ], + "x-ms-request-id": [ + "b833d91d-cd57-4d3d-9967-8df244082018" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "X-Frame-Options": [ + "DENY" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1197" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183222Z:8bb7e9a2-a655-4174-a8c7-d16cf5a8834d" + ], + "Cache-Control": [ + "no-store, no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:32:21 GMT" + ], + "Location": [ + "https://management.azure.com/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/operationResults/b833d91d-cd57-4d3d-9967-8df244082018?api-version=2018-09-01-preview" + ], + "Content-Length": [ + "698" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"properties\": {\r\n \"targetResourceGroup\": \"sdk-net-targetResourceGroup\",\r\n \"deploymentMode\": \"Incremental\",\r\n \"artifacts\": {\r\n \"templateArtifactSourceRelativePath\": \"Templates/WebApp.Template.json\",\r\n \"parametersArtifactSourceRelativePath\": \"Parameters/WebApp.Invalid.Parameters.json\"\r\n },\r\n \"provisioningState\": \"Running\"\r\n },\r\n \"type\": \"Microsoft.DeploymentManager/serviceTopologies/services/serviceUnits\",\r\n \"apiVersion\": \"2018-09-01-preview\",\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service/serviceUnits/Contoso_WebApp_Invalid\",\r\n \"name\": \"Contoso_WebApp_Invalid\",\r\n \"location\": \"Central US\"\r\n}", + "StatusCode": 201 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/operationResults/b833d91d-cd57-4d3d-9967-8df244082018?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlZ3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9vcGVyYXRpb25SZXN1bHRzL2I4MzNkOTFkLWNkNTctNGQzZC05OTY3LThkZjI0NDA4MjAxOD9hcGktdmVyc2lvbj0yMDE4LTA5LTAxLXByZXZpZXc=", + "RequestMethod": "GET", + "RequestBody": "", + "RequestHeaders": { + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "Retry-After": [ + "30" + ], + "x-ms-client-request-id": [ + "eba57aeb-4d9e-47cd-be73-c97185d7a290" + ], + "x-ms-correlation-request-id": [ + "a4d0febe-4cf6-4c32-9917-b8d1dbdcbe07" + ], + "x-ms-request-id": [ + "f4557058-6ab4-4636-9370-065ea41e184e" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "X-Frame-Options": [ + "DENY" + ], + "x-ms-ratelimit-remaining-subscription-reads": [ + "11993" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183314Z:a4d0febe-4cf6-4c32-9917-b8d1dbdcbe07" + ], + "Cache-Control": [ + "no-store, no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:33:13 GMT" + ], + "Location": [ + "https://management.azure.com/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service/serviceUnits/Contoso_WebApp_Invalid?api-version=2018-09-01-preview" + ], + "Content-Length": [ + "106" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"status\": \"Succeeded\",\r\n \"startTime\": \"2019-03-15T18:32:21.288Z\",\r\n \"endTime\": \"2019-03-15T18:32:24.368Z\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/steps/WaitStep?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9zdGVwcy9XYWl0U3RlcD9hcGktdmVyc2lvbj0yMDE4LTA5LTAxLXByZXZpZXc=", + "RequestMethod": "GET", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "ad85129b-e945-48bd-9fde-0f6d6af1eb41" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-failure-cause": [ + "gateway" + ], + "x-ms-request-id": [ + "2b9619f4-64fa-400a-b2d4-35cb04589eb6" + ], + "x-ms-correlation-request-id": [ + "2b9619f4-64fa-400a-b2d4-35cb04589eb6" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183319Z:2b9619f4-64fa-400a-b2d4-35cb04589eb6" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:33:19 GMT" + ], + "Content-Length": [ + "168" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"error\": {\r\n \"code\": \"ResourceNotFound\",\r\n \"message\": \"The Resource 'Microsoft.DeploymentManager/steps/WaitStep' under resource group 'adm-powershell-test-rg' was not found.\"\r\n }\r\n}", + "StatusCode": 404 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/steps/WaitStep?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9zdGVwcy9XYWl0U3RlcD9hcGktdmVyc2lvbj0yMDE4LTA5LTAxLXByZXZpZXc=", + "RequestMethod": "GET", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "303a5fe9-fa29-47ec-b5eb-9472d94158b5" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-client-request-id": [ + "303a5fe9-fa29-47ec-b5eb-9472d94158b5" + ], + "x-ms-correlation-request-id": [ + "898cfd5c-a0d5-4a3e-ae87-3c4b0969f946" + ], + "x-ms-request-id": [ + "e2574648-aff5-4ff8-a633-2d6dcbfa086d" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "X-Frame-Options": [ + "DENY" + ], + "x-ms-ratelimit-remaining-subscription-reads": [ + "11997" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183323Z:898cfd5c-a0d5-4a3e-ae87-3c4b0969f946" + ], + "Cache-Control": [ + "no-store, no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:33:22 GMT" + ], + "Content-Length": [ + "368" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"properties\": {\r\n \"stepType\": \"Wait\",\r\n \"attributes\": {\r\n \"duration\": \"PT5M\"\r\n },\r\n \"provisioningState\": \"Succeeded\"\r\n },\r\n \"type\": \"Microsoft.DeploymentManager/steps\",\r\n \"apiVersion\": \"2018-09-01-preview\",\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/steps/WaitStep\",\r\n \"name\": \"WaitStep\",\r\n \"location\": \"Central US\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/steps/WaitStep?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9zdGVwcy9XYWl0U3RlcD9hcGktdmVyc2lvbj0yMDE4LTA5LTAxLXByZXZpZXc=", + "RequestMethod": "GET", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "65b4e90d-4f3e-4b5c-9718-64de458c6566" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-failure-cause": [ + "gateway" + ], + "x-ms-request-id": [ + "157a47b4-e1e5-4959-b681-0dcfaac6ee9d" + ], + "x-ms-correlation-request-id": [ + "157a47b4-e1e5-4959-b681-0dcfaac6ee9d" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183756Z:157a47b4-e1e5-4959-b681-0dcfaac6ee9d" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:37:56 GMT" + ], + "Content-Length": [ + "168" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"error\": {\r\n \"code\": \"ResourceNotFound\",\r\n \"message\": \"The Resource 'Microsoft.DeploymentManager/steps/WaitStep' under resource group 'adm-powershell-test-rg' was not found.\"\r\n }\r\n}", + "StatusCode": 404 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/steps/WaitStep?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9zdGVwcy9XYWl0U3RlcD9hcGktdmVyc2lvbj0yMDE4LTA5LTAxLXByZXZpZXc=", + "RequestMethod": "PUT", + "RequestBody": "{\r\n \"properties\": {\r\n \"stepType\": \"Wait\",\r\n \"attributes\": {\r\n \"duration\": \"PT5M\"\r\n }\r\n },\r\n \"location\": \"Central US\"\r\n}", + "RequestHeaders": { + "x-ms-client-request-id": [ + "ecc88cf1-440c-4949-a8a1-7965a217ca12" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Content-Length": [ + "136" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-client-request-id": [ + "ecc88cf1-440c-4949-a8a1-7965a217ca12" + ], + "x-ms-correlation-request-id": [ + "924a590d-9d5f-46af-beed-f27e05eb9122" + ], + "x-ms-request-id": [ + "ca4e6ad1-9cbe-4739-aeb7-784478e06979" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "X-Frame-Options": [ + "DENY" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1199" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183322Z:924a590d-9d5f-46af-beed-f27e05eb9122" + ], + "Cache-Control": [ + "no-store, no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:33:21 GMT" + ], + "Content-Length": [ + "368" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"properties\": {\r\n \"stepType\": \"Wait\",\r\n \"attributes\": {\r\n \"duration\": \"PT5M\"\r\n },\r\n \"provisioningState\": \"Succeeded\"\r\n },\r\n \"type\": \"Microsoft.DeploymentManager/steps\",\r\n \"apiVersion\": \"2018-09-01-preview\",\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/steps/WaitStep\",\r\n \"name\": \"WaitStep\",\r\n \"location\": \"Central US\"\r\n}", + "StatusCode": 201 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/steps/WaitStep?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9zdGVwcy9XYWl0U3RlcD9hcGktdmVyc2lvbj0yMDE4LTA5LTAxLXByZXZpZXc=", + "RequestMethod": "PUT", + "RequestBody": "{\r\n \"properties\": {\r\n \"stepType\": \"Wait\",\r\n \"attributes\": {\r\n \"duration\": \"PT10M\"\r\n }\r\n },\r\n \"location\": \"Central US\"\r\n}", + "RequestHeaders": { + "x-ms-client-request-id": [ + "a234f1a4-e39f-4a08-aba1-55029676a4f4" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Content-Length": [ + "137" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-client-request-id": [ + "a234f1a4-e39f-4a08-aba1-55029676a4f4" + ], + "x-ms-correlation-request-id": [ + "f51be496-e7ec-4f09-b87e-95df0266f141" + ], + "x-ms-request-id": [ + "d55a71dd-f47c-4b7f-a14c-3f64e9c879ec" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "X-Frame-Options": [ + "DENY" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1199" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183753Z:f51be496-e7ec-4f09-b87e-95df0266f141" + ], + "Cache-Control": [ + "no-store, no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:37:53 GMT" + ], + "Content-Length": [ + "369" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"properties\": {\r\n \"stepType\": \"Wait\",\r\n \"attributes\": {\r\n \"duration\": \"PT10M\"\r\n },\r\n \"provisioningState\": \"Succeeded\"\r\n },\r\n \"type\": \"Microsoft.DeploymentManager/steps\",\r\n \"apiVersion\": \"2018-09-01-preview\",\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/steps/WaitStep\",\r\n \"name\": \"WaitStep\",\r\n \"location\": \"Central US\"\r\n}", + "StatusCode": 201 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-tests-rollout?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlZ3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3RzLXJvbGxvdXQ/YXBpLXZlcnNpb249MjAxNi0wOS0wMQ==", + "RequestMethod": "PUT", + "RequestBody": "{\r\n \"location\": \"Central US\"\r\n}", + "RequestHeaders": { + "x-ms-client-request-id": [ + "90145d4b-276c-43e8-bff6-ad5c1b55eec1" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Content-Length": [ + "32" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1198" + ], + "x-ms-request-id": [ + "0fe9bcbe-f8a0-4197-b926-f34fcd918983" + ], + "x-ms-correlation-request-id": [ + "0fe9bcbe-f8a0-4197-b926-f34fcd918983" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183324Z:0fe9bcbe-f8a0-4197-b926-f34fcd918983" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:33:23 GMT" + ], + "Content-Length": [ + "212" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-tests-rollout\",\r\n \"name\": \"adm-powershell-tests-rollout\",\r\n \"location\": \"centralus\",\r\n \"properties\": {\r\n \"provisioningState\": \"Succeeded\"\r\n }\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-tests-invalidRollout?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlZ3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3RzLWludmFsaWRSb2xsb3V0P2FwaS12ZXJzaW9uPTIwMTYtMDktMDE=", + "RequestMethod": "PUT", + "RequestBody": "{\r\n \"location\": \"Central US\"\r\n}", + "RequestHeaders": { + "x-ms-client-request-id": [ + "c8ffa70f-5c7a-4412-9f27-602842d2566b" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Content-Length": [ + "32" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1197" + ], + "x-ms-request-id": [ + "396fd9d2-2b4f-48df-8bb0-b8fa774c8456" + ], + "x-ms-correlation-request-id": [ + "396fd9d2-2b4f-48df-8bb0-b8fa774c8456" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183324Z:396fd9d2-2b4f-48df-8bb0-b8fa774c8456" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:33:23 GMT" + ], + "Content-Length": [ + "226" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-tests-invalidRollout\",\r\n \"name\": \"adm-powershell-tests-invalidRollout\",\r\n \"location\": \"centralus\",\r\n \"properties\": {\r\n \"provisioningState\": \"Succeeded\"\r\n }\r\n}", + "StatusCode": 201 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-tests-rollout/providers/Microsoft.Resources/deployments/adm-powershell-tests-rollout?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlZ3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3RzLXJvbGxvdXQvcHJvdmlkZXJzL01pY3Jvc29mdC5SZXNvdXJjZXMvZGVwbG95bWVudHMvYWRtLXBvd2Vyc2hlbGwtdGVzdHMtcm9sbG91dD9hcGktdmVyc2lvbj0yMDE2LTA5LTAx", + "RequestMethod": "PUT", + "RequestBody": "{\r\n \"properties\": {\r\n \"template\": {\r\n \"$schema\": \"http://schema.management.azure.com/schemas/2014-04-01-preview/deploymentTemplate.json\",\r\n \"resources\": [\r\n {\r\n \"location\": \"Central US\",\r\n \"apiVersion\": \"2018-09-01-preview\",\r\n \"type\": \"Microsoft.DeploymentManager/rollouts\",\r\n \"name\": \"adm-powershell-tests-rollout\",\r\n \"Identity\": {\r\n \"type\": \"userAssigned\",\r\n \"identityIds\": [\r\n \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-sdk-tests/providers/Microsoft.ManagedIdentity/userassignedidentities/admsdktests\"\r\n ]\r\n },\r\n \"properties\": {\r\n \"buildVersion\": \"1.0.0\",\r\n \"targetServiceTopologyId\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests\",\r\n \"artifactSourceId\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/artifactSources/powershell-sdk-tests-functional\",\r\n \"stepGroups\": [\r\n {\r\n \"name\": \"PilotRegion\",\r\n \"preDeploymentSteps\": [\r\n {\r\n \"stepId\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/steps/WaitStep\"\r\n }\r\n ],\r\n \"deploymentTargetId\": \"/serviceTopologies/powershell-sdk-tests/services/Contoso_Service/serviceUnits/Contoso_WebApp\"\r\n }\r\n ]\r\n }\r\n }\r\n ],\r\n \"contentVersion\": \"1.0.0.0\"\r\n },\r\n \"mode\": \"Incremental\"\r\n }\r\n}", + "RequestHeaders": { + "x-ms-client-request-id": [ + "6517c570-9bdf-4eaa-b47a-27bb4a61298f" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Content-Length": [ + "1793" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "Azure-AsyncOperation": [ + "https://management.azure.com/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-tests-rollout/providers/Microsoft.Resources/deployments/adm-powershell-tests-rollout/operationStatuses/08586489320792339250?api-version=2016-09-01" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1196" + ], + "x-ms-request-id": [ + "463e743e-6f0e-48f0-bb0a-fa1ec43f62ec" + ], + "x-ms-correlation-request-id": [ + "463e743e-6f0e-48f0-bb0a-fa1ec43f62ec" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183327Z:463e743e-6f0e-48f0-bb0a-fa1ec43f62ec" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:33:26 GMT" + ], + "Content-Length": [ + "589" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-tests-rollout/providers/Microsoft.Resources/deployments/adm-powershell-tests-rollout\",\r\n \"name\": \"adm-powershell-tests-rollout\",\r\n \"properties\": {\r\n \"templateHash\": \"2632689978983367544\",\r\n \"mode\": \"Incremental\",\r\n \"provisioningState\": \"Accepted\",\r\n \"timestamp\": \"2019-03-15T18:33:26.9077385Z\",\r\n \"duration\": \"PT0.6640605S\",\r\n \"correlationId\": \"463e743e-6f0e-48f0-bb0a-fa1ec43f62ec\",\r\n \"providers\": [\r\n {\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"centralus\"\r\n ]\r\n }\r\n ]\r\n }\r\n ],\r\n \"dependencies\": []\r\n }\r\n}", + "StatusCode": 201 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-tests-rollout/providers/Microsoft.Resources/deployments/adm-powershell-tests-rollout/operationStatuses/08586489320792339250?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlZ3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3RzLXJvbGxvdXQvcHJvdmlkZXJzL01pY3Jvc29mdC5SZXNvdXJjZXMvZGVwbG95bWVudHMvYWRtLXBvd2Vyc2hlbGwtdGVzdHMtcm9sbG91dC9vcGVyYXRpb25TdGF0dXNlcy8wODU4NjQ4OTMyMDc5MjMzOTI1MD9hcGktdmVyc2lvbj0yMDE2LTA5LTAx", + "RequestMethod": "GET", + "RequestBody": "", + "RequestHeaders": { + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-reads": [ + "11996" + ], + "x-ms-request-id": [ + "2134d64c-0c66-40cb-aa7e-dfe946aa11b2" + ], + "x-ms-correlation-request-id": [ + "2134d64c-0c66-40cb-aa7e-dfe946aa11b2" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183357Z:2134d64c-0c66-40cb-aa7e-dfe946aa11b2" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:33:57 GMT" + ], + "Content-Length": [ + "20" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"status\": \"Running\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-tests-rollout/providers/Microsoft.Resources/deployments/adm-powershell-tests-rollout/operationStatuses/08586489320792339250?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlZ3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3RzLXJvbGxvdXQvcHJvdmlkZXJzL01pY3Jvc29mdC5SZXNvdXJjZXMvZGVwbG95bWVudHMvYWRtLXBvd2Vyc2hlbGwtdGVzdHMtcm9sbG91dC9vcGVyYXRpb25TdGF0dXNlcy8wODU4NjQ4OTMyMDc5MjMzOTI1MD9hcGktdmVyc2lvbj0yMDE2LTA5LTAx", + "RequestMethod": "GET", + "RequestBody": "", + "RequestHeaders": { + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-reads": [ + "11995" + ], + "x-ms-request-id": [ + "38fff699-3ab8-4226-bc6d-e79e1084af86" + ], + "x-ms-correlation-request-id": [ + "38fff699-3ab8-4226-bc6d-e79e1084af86" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183427Z:38fff699-3ab8-4226-bc6d-e79e1084af86" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:34:26 GMT" + ], + "Content-Length": [ + "22" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"status\": \"Succeeded\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-tests-rollout/providers/Microsoft.Resources/deployments/adm-powershell-tests-rollout?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlZ3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3RzLXJvbGxvdXQvcHJvdmlkZXJzL01pY3Jvc29mdC5SZXNvdXJjZXMvZGVwbG95bWVudHMvYWRtLXBvd2Vyc2hlbGwtdGVzdHMtcm9sbG91dD9hcGktdmVyc2lvbj0yMDE2LTA5LTAx", + "RequestMethod": "GET", + "RequestBody": "", + "RequestHeaders": { + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-reads": [ + "11994" + ], + "x-ms-request-id": [ + "6484ca22-c603-463a-aee0-4fa0e8f09b43" + ], + "x-ms-correlation-request-id": [ + "6484ca22-c603-463a-aee0-4fa0e8f09b43" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183427Z:6484ca22-c603-463a-aee0-4fa0e8f09b43" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:34:26 GMT" + ], + "Content-Length": [ + "684" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-tests-rollout/providers/Microsoft.Resources/deployments/adm-powershell-tests-rollout\",\r\n \"name\": \"adm-powershell-tests-rollout\",\r\n \"properties\": {\r\n \"templateHash\": \"2632689978983367544\",\r\n \"mode\": \"Incremental\",\r\n \"provisioningState\": \"Succeeded\",\r\n \"timestamp\": \"2019-03-15T18:34:06.080234Z\",\r\n \"duration\": \"PT39.836556S\",\r\n \"correlationId\": \"463e743e-6f0e-48f0-bb0a-fa1ec43f62ec\",\r\n \"providers\": [\r\n {\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"centralus\"\r\n ]\r\n }\r\n ]\r\n }\r\n ],\r\n \"dependencies\": [],\r\n \"outputResources\": [\r\n {\r\n \"id\": \"Microsoft.DeploymentManager/rollouts/adm-powershell-tests-rollout\"\r\n }\r\n ]\r\n }\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-tests-rollout/providers/Microsoft.DeploymentManager/rollouts/adm-powershell-tests-rollout?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3RzLXJvbGxvdXQvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9yb2xsb3V0cy9hZG0tcG93ZXJzaGVsbC10ZXN0cy1yb2xsb3V0P2FwaS12ZXJzaW9uPTIwMTgtMDktMDEtcHJldmlldw==", + "RequestMethod": "GET", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "66302798-7eb2-4c92-9f9c-7f152523b490" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "Retry-After": [ + "120" + ], + "x-ms-client-request-id": [ + "66302798-7eb2-4c92-9f9c-7f152523b490" + ], + "x-ms-correlation-request-id": [ + "b5e402c5-8465-4ef4-9f89-43117e7810e5" + ], + "x-ms-request-id": [ + "b4c0c59e-7745-446e-b5d5-f0fa48eeab2c" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "X-Frame-Options": [ + "DENY" + ], + "x-ms-ratelimit-remaining-subscription-reads": [ + "11993" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183430Z:b5e402c5-8465-4ef4-9f89-43117e7810e5" + ], + "Cache-Control": [ + "no-store, no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:34:29 GMT" + ], + "Location": [ + "https://management.azure.com/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-tests-rollout/providers/Microsoft.DeploymentManager/rollouts/adm-powershell-tests-rollout?api-version=2018-09-01-preview" + ], + "Content-Length": [ + "2165" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"identity\": {\r\n \"type\": \"UserAssigned\",\r\n \"identityIds\": [\r\n \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-sdk-tests/providers/Microsoft.ManagedIdentity/userassignedidentities/admsdktests\"\r\n ]\r\n },\r\n \"properties\": {\r\n \"status\": \"Running\",\r\n \"totalRetryAttempts\": 0,\r\n \"operationInfo\": {\r\n \"retryAttempt\": 0,\r\n \"skipSucceededOnRetry\": false,\r\n \"startTime\": \"2019-03-15T18:33:33.66Z\",\r\n \"lastUpdatedTime\": \"2019-03-15T18:33:33.66Z\"\r\n },\r\n \"services\": [\r\n {\r\n \"name\": \"Contoso_Service\",\r\n \"targetSubscriptionId\": \"53012dcb-5039-4e96-8e6c-5d913da1cdb5\",\r\n \"targetLocation\": \"East US 2\",\r\n \"serviceUnits\": [\r\n {\r\n \"name\": \"Contoso_WebApp\",\r\n \"targetResourceGroup\": \"Contoso_Service\",\r\n \"artifacts\": {},\r\n \"steps\": [\r\n {\r\n \"name\": \"Wait/WaitStep.PreDeploy\",\r\n \"stepGroup\": \"PilotRegion\",\r\n \"status\": \"Running\",\r\n \"operationInfo\": {\r\n \"deploymentName\": \"\",\r\n \"startTime\": \"2019-03-15T18:33:35.936Z\",\r\n \"lastUpdatedTime\": \"2019-03-15T18:33:35.936Z\"\r\n },\r\n \"resourceOperations\": [],\r\n \"messages\": [\r\n {\r\n \"timestamp\": \"2019-03-15T18:33:35.9211223Z\",\r\n \"message\": \"Wait ending at '03/15/2019 18:38:35 UTC', with '5 minutes' remaining.\"\r\n }\r\n ]\r\n }\r\n ]\r\n }\r\n ]\r\n }\r\n ],\r\n \"buildVersion\": \"1.0.0\",\r\n \"targetServiceTopologyId\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests\",\r\n \"artifactSourceId\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/artifactSources/powershell-sdk-tests-functional\",\r\n \"stepGroups\": [\r\n {\r\n \"name\": \"PilotRegion\",\r\n \"deploymentTargetId\": \"/serviceTopologies/powershell-sdk-tests/services/Contoso_Service/serviceUnits/Contoso_WebApp\",\r\n \"preDeploymentSteps\": [\r\n {\r\n \"stepId\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/steps/WaitStep\"\r\n }\r\n ],\r\n \"postDeploymentSteps\": [],\r\n \"dependsOnStepGroups\": []\r\n }\r\n ],\r\n \"provisioningState\": \"Succeeded\"\r\n },\r\n \"type\": \"Microsoft.DeploymentManager/rollouts\",\r\n \"apiVersion\": \"2018-09-01-preview\",\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-tests-rollout/providers/Microsoft.DeploymentManager/rollouts/adm-powershell-tests-rollout\",\r\n \"name\": \"adm-powershell-tests-rollout\",\r\n \"location\": \"Central US\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-tests-rollout/providers/Microsoft.DeploymentManager/rollouts/adm-powershell-tests-rollout?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3RzLXJvbGxvdXQvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9yb2xsb3V0cy9hZG0tcG93ZXJzaGVsbC10ZXN0cy1yb2xsb3V0P2FwaS12ZXJzaW9uPTIwMTgtMDktMDEtcHJldmlldw==", + "RequestMethod": "GET", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "e311e886-482a-45f2-aa8b-2b7b9ca7cb94" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "Retry-After": [ + "120" + ], + "x-ms-client-request-id": [ + "e311e886-482a-45f2-aa8b-2b7b9ca7cb94" + ], + "x-ms-correlation-request-id": [ + "c015ab85-e7cb-4730-8685-dd22c9ffaf9e" + ], + "x-ms-request-id": [ + "b69e6818-7d48-40d3-998e-6832a8ede79a" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "X-Frame-Options": [ + "DENY" + ], + "x-ms-ratelimit-remaining-subscription-reads": [ + "11999" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183634Z:c015ab85-e7cb-4730-8685-dd22c9ffaf9e" + ], + "Cache-Control": [ + "no-store, no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:36:34 GMT" + ], + "Location": [ + "https://management.azure.com/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-tests-rollout/providers/Microsoft.DeploymentManager/rollouts/adm-powershell-tests-rollout?api-version=2018-09-01-preview" + ], + "Content-Length": [ + "2114" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"identity\": {\r\n \"type\": \"UserAssigned\",\r\n \"identityIds\": [\r\n \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-sdk-tests/providers/Microsoft.ManagedIdentity/userassignedidentities/admsdktests\"\r\n ]\r\n },\r\n \"properties\": {\r\n \"status\": \"Canceled\",\r\n \"totalRetryAttempts\": 0,\r\n \"operationInfo\": {\r\n \"retryAttempt\": 0,\r\n \"skipSucceededOnRetry\": false,\r\n \"startTime\": \"2019-03-15T18:33:33.66Z\",\r\n \"endTime\": \"2019-03-15T18:35:40.502Z\",\r\n \"lastUpdatedTime\": \"2019-03-15T18:35:40.502Z\"\r\n },\r\n \"services\": [\r\n {\r\n \"name\": \"Contoso_Service\",\r\n \"targetSubscriptionId\": \"53012dcb-5039-4e96-8e6c-5d913da1cdb5\",\r\n \"targetLocation\": \"East US 2\",\r\n \"serviceUnits\": [\r\n {\r\n \"name\": \"Contoso_WebApp\",\r\n \"targetResourceGroup\": \"Contoso_Service\",\r\n \"artifacts\": {},\r\n \"steps\": [\r\n {\r\n \"name\": \"Wait/WaitStep.PreDeploy\",\r\n \"stepGroup\": \"PilotRegion\",\r\n \"status\": \"Canceled\",\r\n \"operationInfo\": {\r\n \"deploymentName\": \"\",\r\n \"startTime\": \"2019-03-15T18:33:35.936Z\",\r\n \"endTime\": \"2019-03-15T18:35:36.54Z\",\r\n \"lastUpdatedTime\": \"2019-03-15T18:35:36.54Z\"\r\n },\r\n \"resourceOperations\": [],\r\n \"messages\": []\r\n }\r\n ]\r\n }\r\n ]\r\n }\r\n ],\r\n \"buildVersion\": \"1.0.0\",\r\n \"targetServiceTopologyId\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests\",\r\n \"artifactSourceId\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/artifactSources/powershell-sdk-tests-functional\",\r\n \"stepGroups\": [\r\n {\r\n \"name\": \"PilotRegion\",\r\n \"deploymentTargetId\": \"/serviceTopologies/powershell-sdk-tests/services/Contoso_Service/serviceUnits/Contoso_WebApp\",\r\n \"preDeploymentSteps\": [\r\n {\r\n \"stepId\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/steps/WaitStep\"\r\n }\r\n ],\r\n \"postDeploymentSteps\": [],\r\n \"dependsOnStepGroups\": []\r\n }\r\n ],\r\n \"provisioningState\": \"Succeeded\"\r\n },\r\n \"type\": \"Microsoft.DeploymentManager/rollouts\",\r\n \"apiVersion\": \"2018-09-01-preview\",\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-tests-rollout/providers/Microsoft.DeploymentManager/rollouts/adm-powershell-tests-rollout\",\r\n \"name\": \"adm-powershell-tests-rollout\",\r\n \"location\": \"Central US\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-tests-rollout/providers/Microsoft.DeploymentManager/rollouts/adm-powershell-tests-rollout?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3RzLXJvbGxvdXQvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9yb2xsb3V0cy9hZG0tcG93ZXJzaGVsbC10ZXN0cy1yb2xsb3V0P2FwaS12ZXJzaW9uPTIwMTgtMDktMDEtcHJldmlldw==", + "RequestMethod": "GET", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "d2d3c182-6dd2-4d4f-82be-be867cb1b57d" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-failure-cause": [ + "gateway" + ], + "x-ms-request-id": [ + "2454afea-f2ce-484d-b085-cf2ae07e3c5c" + ], + "x-ms-correlation-request-id": [ + "2454afea-f2ce-484d-b085-cf2ae07e3c5c" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183751Z:2454afea-f2ce-484d-b085-cf2ae07e3c5c" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:37:51 GMT" + ], + "Content-Length": [ + "197" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"error\": {\r\n \"code\": \"ResourceNotFound\",\r\n \"message\": \"The Resource 'Microsoft.DeploymentManager/rollouts/adm-powershell-tests-rollout' under resource group 'adm-powershell-tests-rollout' was not found.\"\r\n }\r\n}", + "StatusCode": 404 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-tests-rollout/providers/Microsoft.DeploymentManager/rollouts/adm-powershell-tests-rollout/cancel?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3RzLXJvbGxvdXQvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9yb2xsb3V0cy9hZG0tcG93ZXJzaGVsbC10ZXN0cy1yb2xsb3V0L2NhbmNlbD9hcGktdmVyc2lvbj0yMDE4LTA5LTAxLXByZXZpZXc=", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "45239b23-6bce-4456-b07c-229b1a383d25" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-client-request-id": [ + "45239b23-6bce-4456-b07c-229b1a383d25" + ], + "x-ms-correlation-request-id": [ + "12ab5a9f-6eff-4880-aa72-b11fe4f6b7c6" + ], + "x-ms-request-id": [ + "48c4fdd8-c693-4b6c-8821-64af6f9c7c5b" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "X-Frame-Options": [ + "DENY" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1194" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183432Z:12ab5a9f-6eff-4880-aa72-b11fe4f6b7c6" + ], + "Cache-Control": [ + "no-store, no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:34:31 GMT" + ], + "Location": [ + "https://management.azure.com/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-tests-rollout/providers/Microsoft.DeploymentManager/rollouts/adm-powershell-tests-rollout?api-version=2018-09-01-preview" + ], + "Content-Length": [ + "1539" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"identity\": {\r\n \"type\": \"UserAssigned\",\r\n \"identityIds\": [\r\n \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-sdk-tests/providers/Microsoft.ManagedIdentity/userassignedidentities/admsdktests\"\r\n ]\r\n },\r\n \"properties\": {\r\n \"status\": \"Canceling\",\r\n \"operationInfo\": {\r\n \"retryAttempt\": 0,\r\n \"skipSucceededOnRetry\": false,\r\n \"startTime\": \"2019-03-15T18:33:33.66Z\",\r\n \"lastUpdatedTime\": \"2019-03-15T18:33:33.66Z\"\r\n },\r\n \"buildVersion\": \"1.0.0\",\r\n \"targetServiceTopologyId\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests\",\r\n \"artifactSourceId\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/artifactSources/powershell-sdk-tests-functional\",\r\n \"stepGroups\": [\r\n {\r\n \"name\": \"PilotRegion\",\r\n \"deploymentTargetId\": \"/serviceTopologies/powershell-sdk-tests/services/Contoso_Service/serviceUnits/Contoso_WebApp\",\r\n \"preDeploymentSteps\": [\r\n {\r\n \"stepId\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/steps/WaitStep\"\r\n }\r\n ],\r\n \"postDeploymentSteps\": [],\r\n \"dependsOnStepGroups\": []\r\n }\r\n ],\r\n \"provisioningState\": \"Succeeded\"\r\n },\r\n \"type\": \"Microsoft.DeploymentManager/rollouts\",\r\n \"apiVersion\": \"2018-09-01-preview\",\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-tests-rollout/providers/Microsoft.DeploymentManager/rollouts/adm-powershell-tests-rollout\",\r\n \"name\": \"adm-powershell-tests-rollout\",\r\n \"location\": \"Central US\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-tests-invalidRollout/providers/Microsoft.Resources/deployments/adm-powershell-tests-invalidRollout?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlZ3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3RzLWludmFsaWRSb2xsb3V0L3Byb3ZpZGVycy9NaWNyb3NvZnQuUmVzb3VyY2VzL2RlcGxveW1lbnRzL2FkbS1wb3dlcnNoZWxsLXRlc3RzLWludmFsaWRSb2xsb3V0P2FwaS12ZXJzaW9uPTIwMTYtMDktMDE=", + "RequestMethod": "PUT", + "RequestBody": "{\r\n \"properties\": {\r\n \"template\": {\r\n \"$schema\": \"http://schema.management.azure.com/schemas/2014-04-01-preview/deploymentTemplate.json\",\r\n \"resources\": [\r\n {\r\n \"location\": \"Central US\",\r\n \"apiVersion\": \"2018-09-01-preview\",\r\n \"type\": \"Microsoft.DeploymentManager/rollouts\",\r\n \"name\": \"adm-powershell-tests-invalidRollout\",\r\n \"Identity\": {\r\n \"type\": \"userAssigned\",\r\n \"identityIds\": [\r\n \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-sdk-tests/providers/Microsoft.ManagedIdentity/userassignedidentities/admsdktests\"\r\n ]\r\n },\r\n \"properties\": {\r\n \"buildVersion\": \"1.0.0\",\r\n \"targetServiceTopologyId\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests\",\r\n \"artifactSourceId\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/artifactSources/powershell-sdk-tests-functional\",\r\n \"stepGroups\": [\r\n {\r\n \"name\": \"PilotRegion\",\r\n \"deploymentTargetId\": \"/serviceTopologies/powershell-sdk-tests/services/Contoso_Service/serviceUnits/Contoso_WebApp_Invalid\"\r\n }\r\n ]\r\n }\r\n }\r\n ],\r\n \"contentVersion\": \"1.0.0.0\"\r\n },\r\n \"mode\": \"Incremental\"\r\n }\r\n}", + "RequestHeaders": { + "x-ms-client-request-id": [ + "5e91f836-2875-4e76-9e33-c7b0de7650b2" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Content-Length": [ + "1529" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "Azure-AsyncOperation": [ + "https://management.azure.com/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-tests-invalidRollout/providers/Microsoft.Resources/deployments/adm-powershell-tests-invalidRollout/operationStatuses/08586489318889273941?api-version=2016-09-01" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1199" + ], + "x-ms-request-id": [ + "aaf82471-4ed6-446c-abc9-f1bf98e1261f" + ], + "x-ms-correlation-request-id": [ + "aaf82471-4ed6-446c-abc9-f1bf98e1261f" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183637Z:aaf82471-4ed6-446c-abc9-f1bf98e1261f" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:36:37 GMT" + ], + "Content-Length": [ + "610" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-tests-invalidRollout/providers/Microsoft.Resources/deployments/adm-powershell-tests-invalidRollout\",\r\n \"name\": \"adm-powershell-tests-invalidRollout\",\r\n \"properties\": {\r\n \"templateHash\": \"2146226822224476167\",\r\n \"mode\": \"Incremental\",\r\n \"provisioningState\": \"Accepted\",\r\n \"timestamp\": \"2019-03-15T18:36:37.1222854Z\",\r\n \"duration\": \"PT0.5720758S\",\r\n \"correlationId\": \"aaf82471-4ed6-446c-abc9-f1bf98e1261f\",\r\n \"providers\": [\r\n {\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"centralus\"\r\n ]\r\n }\r\n ]\r\n }\r\n ],\r\n \"dependencies\": []\r\n }\r\n}", + "StatusCode": 201 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-tests-invalidRollout/providers/Microsoft.Resources/deployments/adm-powershell-tests-invalidRollout/operationStatuses/08586489318889273941?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlZ3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3RzLWludmFsaWRSb2xsb3V0L3Byb3ZpZGVycy9NaWNyb3NvZnQuUmVzb3VyY2VzL2RlcGxveW1lbnRzL2FkbS1wb3dlcnNoZWxsLXRlc3RzLWludmFsaWRSb2xsb3V0L29wZXJhdGlvblN0YXR1c2VzLzA4NTg2NDg5MzE4ODg5MjczOTQxP2FwaS12ZXJzaW9uPTIwMTYtMDktMDE=", + "RequestMethod": "GET", + "RequestBody": "", + "RequestHeaders": { + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-reads": [ + "11999" + ], + "x-ms-request-id": [ + "85023268-b86d-41c1-ac35-e6e6eb7d3bdf" + ], + "x-ms-correlation-request-id": [ + "85023268-b86d-41c1-ac35-e6e6eb7d3bdf" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183707Z:85023268-b86d-41c1-ac35-e6e6eb7d3bdf" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:37:06 GMT" + ], + "Content-Length": [ + "20" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"status\": \"Running\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-tests-invalidRollout/providers/Microsoft.Resources/deployments/adm-powershell-tests-invalidRollout/operationStatuses/08586489318889273941?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlZ3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3RzLWludmFsaWRSb2xsb3V0L3Byb3ZpZGVycy9NaWNyb3NvZnQuUmVzb3VyY2VzL2RlcGxveW1lbnRzL2FkbS1wb3dlcnNoZWxsLXRlc3RzLWludmFsaWRSb2xsb3V0L29wZXJhdGlvblN0YXR1c2VzLzA4NTg2NDg5MzE4ODg5MjczOTQxP2FwaS12ZXJzaW9uPTIwMTYtMDktMDE=", + "RequestMethod": "GET", + "RequestBody": "", + "RequestHeaders": { + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-reads": [ + "11998" + ], + "x-ms-request-id": [ + "0b9fc824-4070-4d86-bee7-d4779ff4daae" + ], + "x-ms-correlation-request-id": [ + "0b9fc824-4070-4d86-bee7-d4779ff4daae" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183737Z:0b9fc824-4070-4d86-bee7-d4779ff4daae" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:37:37 GMT" + ], + "Content-Length": [ + "22" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"status\": \"Succeeded\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-tests-invalidRollout/providers/Microsoft.Resources/deployments/adm-powershell-tests-invalidRollout?api-version=2016-09-01", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlZ3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3RzLWludmFsaWRSb2xsb3V0L3Byb3ZpZGVycy9NaWNyb3NvZnQuUmVzb3VyY2VzL2RlcGxveW1lbnRzL2FkbS1wb3dlcnNoZWxsLXRlc3RzLWludmFsaWRSb2xsb3V0P2FwaS12ZXJzaW9uPTIwMTYtMDktMDE=", + "RequestMethod": "GET", + "RequestBody": "", + "RequestHeaders": { + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient/4.1.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-ratelimit-remaining-subscription-reads": [ + "11997" + ], + "x-ms-request-id": [ + "d8930388-fe08-476e-b14a-a25bf701f974" + ], + "x-ms-correlation-request-id": [ + "d8930388-fe08-476e-b14a-a25bf701f974" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183738Z:d8930388-fe08-476e-b14a-a25bf701f974" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:37:37 GMT" + ], + "Content-Length": [ + "714" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-tests-invalidRollout/providers/Microsoft.Resources/deployments/adm-powershell-tests-invalidRollout\",\r\n \"name\": \"adm-powershell-tests-invalidRollout\",\r\n \"properties\": {\r\n \"templateHash\": \"2146226822224476167\",\r\n \"mode\": \"Incremental\",\r\n \"provisioningState\": \"Succeeded\",\r\n \"timestamp\": \"2019-03-15T18:37:33.2725979Z\",\r\n \"duration\": \"PT56.7223883S\",\r\n \"correlationId\": \"aaf82471-4ed6-446c-abc9-f1bf98e1261f\",\r\n \"providers\": [\r\n {\r\n \"namespace\": \"Microsoft.DeploymentManager\",\r\n \"resourceTypes\": [\r\n {\r\n \"resourceType\": \"rollouts\",\r\n \"locations\": [\r\n \"centralus\"\r\n ]\r\n }\r\n ]\r\n }\r\n ],\r\n \"dependencies\": [],\r\n \"outputResources\": [\r\n {\r\n \"id\": \"Microsoft.DeploymentManager/rollouts/adm-powershell-tests-invalidRollout\"\r\n }\r\n ]\r\n }\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-tests-invalidRollout/providers/Microsoft.DeploymentManager/rollouts/adm-powershell-tests-invalidRollout?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3RzLWludmFsaWRSb2xsb3V0L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcm9sbG91dHMvYWRtLXBvd2Vyc2hlbGwtdGVzdHMtaW52YWxpZFJvbGxvdXQ/YXBpLXZlcnNpb249MjAxOC0wOS0wMS1wcmV2aWV3", + "RequestMethod": "GET", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "d3220301-d968-4c81-9917-5fbe420dabbe" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "Retry-After": [ + "120" + ], + "x-ms-client-request-id": [ + "d3220301-d968-4c81-9917-5fbe420dabbe" + ], + "x-ms-correlation-request-id": [ + "fff6bfeb-e793-4aeb-bd21-ec30bc0b129e" + ], + "x-ms-request-id": [ + "b4d1a3ec-e921-46c0-a22c-11c1706f1cde" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "X-Frame-Options": [ + "DENY" + ], + "x-ms-ratelimit-remaining-subscription-reads": [ + "11996" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183742Z:fff6bfeb-e793-4aeb-bd21-ec30bc0b129e" + ], + "Cache-Control": [ + "no-store, no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:37:41 GMT" + ], + "Location": [ + "https://management.azure.com/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-tests-invalidRollout/providers/Microsoft.DeploymentManager/rollouts/adm-powershell-tests-invalidRollout?api-version=2018-09-01-preview" + ], + "Content-Length": [ + "3335" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"identity\": {\r\n \"type\": \"UserAssigned\",\r\n \"identityIds\": [\r\n \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-sdk-tests/providers/Microsoft.ManagedIdentity/userassignedidentities/admsdktests\"\r\n ]\r\n },\r\n \"properties\": {\r\n \"status\": \"Failed\",\r\n \"totalRetryAttempts\": 0,\r\n \"operationInfo\": {\r\n \"retryAttempt\": 0,\r\n \"skipSucceededOnRetry\": false,\r\n \"startTime\": \"2019-03-15T18:36:43.273Z\",\r\n \"endTime\": \"2019-03-15T18:37:28.959Z\",\r\n \"lastUpdatedTime\": \"2019-03-15T18:37:28.959Z\",\r\n \"error\": {\r\n \"message\": \"Rollout failed. See individual resource's 'StatusMessage' property for specific error information. \"\r\n }\r\n },\r\n \"services\": [\r\n {\r\n \"name\": \"Contoso_Service\",\r\n \"targetSubscriptionId\": \"53012dcb-5039-4e96-8e6c-5d913da1cdb5\",\r\n \"targetLocation\": \"East US 2\",\r\n \"serviceUnits\": [\r\n {\r\n \"name\": \"Contoso_WebApp_Invalid\",\r\n \"targetResourceGroup\": \"sdk-net-targetResourceGroup\",\r\n \"deploymentMode\": \"Incremental\",\r\n \"artifacts\": {},\r\n \"steps\": [\r\n {\r\n \"name\": \"Deploy\",\r\n \"stepGroup\": \"PilotRegion\",\r\n \"status\": \"Failed\",\r\n \"operationInfo\": {\r\n \"correlationId\": \"e07db808-bd3f-43cc-a8a3-88d815d5b184\",\r\n \"deploymentName\": \"7AEA3CF171FB48B591CF947147D6C0B40Contoso_WebApp_Invalid\",\r\n \"startTime\": \"2019-03-15T18:36:56.453Z\",\r\n \"endTime\": \"2019-03-15T18:37:28.491Z\",\r\n \"lastUpdatedTime\": \"2019-03-15T18:37:28.491Z\"\r\n },\r\n \"resourceOperations\": [\r\n {\r\n \"ResourceName\": \"AdmDemoNodejsApp\",\r\n \"OperationId\": \"ADE36A175C75BCF5\",\r\n \"ResourceType\": \"Microsoft.Web/sites\",\r\n \"ProvisioningState\": \"Failed\",\r\n \"StatusMessage\": \"{\\r\\n \\\"Code\\\": \\\"Conflict\\\",\\r\\n \\\"Message\\\": \\\"Website with given name AdmDemoNodejsApp already exists.\\\",\\r\\n \\\"Target\\\": null,\\r\\n \\\"Details\\\": [\\r\\n {\\r\\n \\\"Message\\\": \\\"Website with given name AdmDemoNodejsApp already exists.\\\"\\r\\n },\\r\\n {\\r\\n \\\"Code\\\": \\\"Conflict\\\"\\r\\n },\\r\\n {\\r\\n \\\"ErrorEntity\\\": {\\r\\n \\\"ExtendedCode\\\": \\\"54001\\\",\\r\\n \\\"MessageTemplate\\\": \\\"Website with given name {0} already exists.\\\",\\r\\n \\\"Parameters\\\": [\\r\\n \\\"AdmDemoNodejsApp\\\"\\r\\n ],\\r\\n \\\"Code\\\": \\\"Conflict\\\",\\r\\n \\\"Message\\\": \\\"Website with given name AdmDemoNodejsApp already exists.\\\"\\r\\n }\\r\\n }\\r\\n ],\\r\\n \\\"Innererror\\\": null\\r\\n}\",\r\n \"StatusCode\": \"Conflict\"\r\n },\r\n {\r\n \"ResourceName\": \"AdmDemoNodejsAppPlan\",\r\n \"OperationId\": \"412E16101DB6C709\",\r\n \"ResourceType\": \"Microsoft.Web/serverfarms\",\r\n \"ProvisioningState\": \"Succeeded\",\r\n \"StatusMessage\": \"\",\r\n \"StatusCode\": \"OK\"\r\n }\r\n ],\r\n \"messages\": []\r\n }\r\n ]\r\n }\r\n ]\r\n }\r\n ],\r\n \"buildVersion\": \"1.0.0\",\r\n \"targetServiceTopologyId\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests\",\r\n \"artifactSourceId\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/artifactSources/powershell-sdk-tests-functional\",\r\n \"stepGroups\": [\r\n {\r\n \"name\": \"PilotRegion\",\r\n \"deploymentTargetId\": \"/serviceTopologies/powershell-sdk-tests/services/Contoso_Service/serviceUnits/Contoso_WebApp_Invalid\",\r\n \"preDeploymentSteps\": [],\r\n \"postDeploymentSteps\": [],\r\n \"dependsOnStepGroups\": []\r\n }\r\n ],\r\n \"provisioningState\": \"Succeeded\"\r\n },\r\n \"type\": \"Microsoft.DeploymentManager/rollouts\",\r\n \"apiVersion\": \"2018-09-01-preview\",\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-tests-invalidRollout/providers/Microsoft.DeploymentManager/rollouts/adm-powershell-tests-invalidRollout\",\r\n \"name\": \"adm-powershell-tests-invalidRollout\",\r\n \"location\": \"Central US\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-tests-invalidRollout/providers/Microsoft.DeploymentManager/rollouts/adm-powershell-tests-invalidRollout/restart?skipSucceeded=true&api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3RzLWludmFsaWRSb2xsb3V0L3Byb3ZpZGVycy9NaWNyb3NvZnQuRGVwbG95bWVudE1hbmFnZXIvcm9sbG91dHMvYWRtLXBvd2Vyc2hlbGwtdGVzdHMtaW52YWxpZFJvbGxvdXQvcmVzdGFydD9za2lwU3VjY2VlZGVkPXRydWUmYXBpLXZlcnNpb249MjAxOC0wOS0wMS1wcmV2aWV3", + "RequestMethod": "POST", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "cc49b787-d8ef-4fc4-b1a1-d891dffaac49" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "Retry-After": [ + "60" + ], + "x-ms-client-request-id": [ + "cc49b787-d8ef-4fc4-b1a1-d891dffaac49" + ], + "x-ms-correlation-request-id": [ + "483c9317-a8b8-4790-882f-1ef31e03c57d" + ], + "x-ms-request-id": [ + "9a2463d9-2792-4c8b-b830-cf13ab555f12" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "X-Frame-Options": [ + "DENY" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1197" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183745Z:483c9317-a8b8-4790-882f-1ef31e03c57d" + ], + "Cache-Control": [ + "no-store, no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:37:45 GMT" + ], + "Location": [ + "https://management.azure.com/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-tests-invalidRollout/providers/Microsoft.DeploymentManager/rollouts/adm-powershell-tests-invalidRollout?skipSucceeded=true&api-version=2018-09-01-preview" + ], + "Content-Length": [ + "1435" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"identity\": {\r\n \"type\": \"UserAssigned\",\r\n \"identityIds\": [\r\n \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-sdk-tests/providers/Microsoft.ManagedIdentity/userassignedidentities/admsdktests\"\r\n ]\r\n },\r\n \"properties\": {\r\n \"status\": \"Running\",\r\n \"totalRetryAttempts\": 1,\r\n \"operationInfo\": {\r\n \"retryAttempt\": 1,\r\n \"skipSucceededOnRetry\": true,\r\n \"startTime\": \"2019-03-15T18:37:44.373Z\",\r\n \"lastUpdatedTime\": \"2019-03-15T18:37:44.373Z\"\r\n },\r\n \"buildVersion\": \"1.0.0\",\r\n \"targetServiceTopologyId\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests\",\r\n \"artifactSourceId\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/artifactSources/powershell-sdk-tests-functional\",\r\n \"stepGroups\": [\r\n {\r\n \"name\": \"PilotRegion\",\r\n \"deploymentTargetId\": \"/serviceTopologies/powershell-sdk-tests/services/Contoso_Service/serviceUnits/Contoso_WebApp_Invalid\",\r\n \"preDeploymentSteps\": [],\r\n \"postDeploymentSteps\": [],\r\n \"dependsOnStepGroups\": []\r\n }\r\n ],\r\n \"provisioningState\": \"Succeeded\"\r\n },\r\n \"type\": \"Microsoft.DeploymentManager/rollouts\",\r\n \"apiVersion\": \"2018-09-01-preview\",\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-tests-invalidRollout/providers/Microsoft.DeploymentManager/rollouts/adm-powershell-tests-invalidRollout\",\r\n \"name\": \"adm-powershell-tests-invalidRollout\",\r\n \"location\": \"Central US\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-tests-rollout/providers/Microsoft.DeploymentManager/rollouts/adm-powershell-tests-rollout?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3RzLXJvbGxvdXQvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9yb2xsb3V0cy9hZG0tcG93ZXJzaGVsbC10ZXN0cy1yb2xsb3V0P2FwaS12ZXJzaW9uPTIwMTgtMDktMDEtcHJldmlldw==", + "RequestMethod": "DELETE", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "2735c012-f42d-4bc4-932c-12bd600800be" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-client-request-id": [ + "2735c012-f42d-4bc4-932c-12bd600800be" + ], + "x-ms-correlation-request-id": [ + "7afc4d86-620e-4615-9636-785c0f744a1f" + ], + "x-ms-request-id": [ + "fcf319b3-c5ec-4779-9b46-c237804474ec" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "X-Frame-Options": [ + "DENY" + ], + "x-ms-ratelimit-remaining-subscription-deletes": [ + "14999" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183749Z:7afc4d86-620e-4615-9636-785c0f744a1f" + ], + "Cache-Control": [ + "no-store, no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:37:49 GMT" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "", + "StatusCode": 204 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/steps/WaitStep?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9zdGVwcy9XYWl0U3RlcD9hcGktdmVyc2lvbj0yMDE4LTA5LTAxLXByZXZpZXc=", + "RequestMethod": "DELETE", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "572da4c7-491c-4f79-8967-a1d6f31b32e9" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-client-request-id": [ + "572da4c7-491c-4f79-8967-a1d6f31b32e9" + ], + "x-ms-correlation-request-id": [ + "7f0d5226-7dee-4516-9d6d-8314272a9f34" + ], + "x-ms-request-id": [ + "7974d486-9bae-47c9-a329-8b947f2ca52f" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "X-Frame-Options": [ + "DENY" + ], + "x-ms-ratelimit-remaining-subscription-deletes": [ + "14998" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183755Z:7f0d5226-7dee-4516-9d6d-8314272a9f34" + ], + "Cache-Control": [ + "no-store, no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:37:55 GMT" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "null", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/operationResults/30905b59-e548-4c0a-b7d8-9db0e4567238?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlZ3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9vcGVyYXRpb25SZXN1bHRzLzMwOTA1YjU5LWU1NDgtNGMwYS1iN2Q4LTlkYjBlNDU2NzIzOD9hcGktdmVyc2lvbj0yMDE4LTA5LTAxLXByZXZpZXc=", + "RequestMethod": "GET", + "RequestBody": "", + "RequestHeaders": { + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "Retry-After": [ + "30" + ], + "x-ms-client-request-id": [ + "7c031be3-3b47-45b8-9bba-3751429303d5" + ], + "x-ms-correlation-request-id": [ + "e6d0ab61-3df3-40f9-a5f9-437b5bfbdab0" + ], + "x-ms-request-id": [ + "ed141455-6ca9-4d56-8c94-a4a6678c2997" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "X-Frame-Options": [ + "DENY" + ], + "x-ms-ratelimit-remaining-subscription-reads": [ + "11997" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183834Z:e6d0ab61-3df3-40f9-a5f9-437b5bfbdab0" + ], + "Cache-Control": [ + "no-store, no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:38:34 GMT" + ], + "Location": [ + "https://management.azure.com/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service/serviceUnits/Contoso_WebApp?api-version=2018-09-01-preview" + ], + "Content-Length": [ + "106" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"status\": \"Succeeded\",\r\n \"startTime\": \"2019-03-15T18:37:58.432Z\",\r\n \"endTime\": \"2019-03-15T18:38:04.027Z\"\r\n}", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service/serviceUnits/Contoso_WebApp?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9zZXJ2aWNlVG9wb2xvZ2llcy9wb3dlcnNoZWxsLXNkay10ZXN0cy9zZXJ2aWNlcy9Db250b3NvX1NlcnZpY2Uvc2VydmljZVVuaXRzL0NvbnRvc29fV2ViQXBwP2FwaS12ZXJzaW9uPTIwMTgtMDktMDEtcHJldmlldw==", + "RequestMethod": "DELETE", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "3d7e0aae-d301-4ae7-b82e-e80ef818fe91" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-client-request-id": [ + "3d7e0aae-d301-4ae7-b82e-e80ef818fe91" + ], + "x-ms-correlation-request-id": [ + "c2d4976f-a56e-4a56-aa97-bdf323b908d6" + ], + "x-ms-request-id": [ + "19481f3f-44bb-4041-acda-44e9cbe18e75" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "X-Frame-Options": [ + "DENY" + ], + "x-ms-ratelimit-remaining-subscription-deletes": [ + "14997" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183837Z:c2d4976f-a56e-4a56-aa97-bdf323b908d6" + ], + "Cache-Control": [ + "no-store, no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:38:37 GMT" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "null", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service/serviceUnits/Contoso_WebApp_Invalid?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9zZXJ2aWNlVG9wb2xvZ2llcy9wb3dlcnNoZWxsLXNkay10ZXN0cy9zZXJ2aWNlcy9Db250b3NvX1NlcnZpY2Uvc2VydmljZVVuaXRzL0NvbnRvc29fV2ViQXBwX0ludmFsaWQ/YXBpLXZlcnNpb249MjAxOC0wOS0wMS1wcmV2aWV3", + "RequestMethod": "DELETE", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "adfaef8c-fe58-4d05-8175-ce7adb24c1f6" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-client-request-id": [ + "adfaef8c-fe58-4d05-8175-ce7adb24c1f6" + ], + "x-ms-correlation-request-id": [ + "67092faa-a680-4559-b828-28b22428cca3" + ], + "x-ms-request-id": [ + "e71322ee-580c-4600-93a4-730d72f9bc71" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "X-Frame-Options": [ + "DENY" + ], + "x-ms-ratelimit-remaining-subscription-deletes": [ + "14996" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183839Z:67092faa-a680-4559-b828-28b22428cca3" + ], + "Cache-Control": [ + "no-store, no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:38:39 GMT" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "null", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests/services/Contoso_Service?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9zZXJ2aWNlVG9wb2xvZ2llcy9wb3dlcnNoZWxsLXNkay10ZXN0cy9zZXJ2aWNlcy9Db250b3NvX1NlcnZpY2U/YXBpLXZlcnNpb249MjAxOC0wOS0wMS1wcmV2aWV3", + "RequestMethod": "DELETE", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "cb75e0cc-42c0-4f3f-9788-6cf9c486c19c" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-client-request-id": [ + "cb75e0cc-42c0-4f3f-9788-6cf9c486c19c" + ], + "x-ms-correlation-request-id": [ + "82b59bc5-34e4-4670-ab56-d39332d41cc7" + ], + "x-ms-request-id": [ + "94e33020-6aec-4287-aa0f-91ea338c1d46" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "X-Frame-Options": [ + "DENY" + ], + "x-ms-ratelimit-remaining-subscription-deletes": [ + "14995" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183845Z:82b59bc5-34e4-4670-ab56-d39332d41cc7" + ], + "Cache-Control": [ + "no-store, no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:38:44 GMT" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "null", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/artifactSources/powershell-sdk-tests?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9hcnRpZmFjdFNvdXJjZXMvcG93ZXJzaGVsbC1zZGstdGVzdHM/YXBpLXZlcnNpb249MjAxOC0wOS0wMS1wcmV2aWV3", + "RequestMethod": "GET", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "d72e93a5-35d2-4c50-a21b-e0506fd9e4f6" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-failure-cause": [ + "gateway" + ], + "x-ms-request-id": [ + "a716e5aa-d9f6-4ddd-93dd-7e14d39080a5" + ], + "x-ms-correlation-request-id": [ + "a716e5aa-d9f6-4ddd-93dd-7e14d39080a5" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183847Z:a716e5aa-d9f6-4ddd-93dd-7e14d39080a5" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Cache-Control": [ + "no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:38:47 GMT" + ], + "Content-Length": [ + "190" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"error\": {\r\n \"code\": \"ResourceNotFound\",\r\n \"message\": \"The Resource 'Microsoft.DeploymentManager/artifactSources/powershell-sdk-tests' under resource group 'adm-powershell-test-rg' was not found.\"\r\n }\r\n}", + "StatusCode": 404 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/artifactSources/powershell-sdk-tests?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9hcnRpZmFjdFNvdXJjZXMvcG93ZXJzaGVsbC1zZGstdGVzdHM/YXBpLXZlcnNpb249MjAxOC0wOS0wMS1wcmV2aWV3", + "RequestMethod": "PUT", + "RequestBody": "{\r\n \"properties\": {\r\n \"sourceType\": \"AzureStorage\",\r\n \"artifactRoot\": \"builds/1.0.0.0\",\r\n \"authentication\": {\r\n \"type\": \"Sas\",\r\n \"properties\": {\r\n \"sasUri\": \"https://sdktests.blob.core.windows.net/artifacts?sv=2017-07-29&sr=c&sig=cGTh4By%2F%2Fd4%2BkYNAZ8yHjYKB%2FMHcYfIZQXoaDbev1N8%3D&st=2019-03-14T22%3A38%3A46Z&se=2019-03-17T18%3A38%3A46Z&sp=rl\"\r\n }\r\n }\r\n },\r\n \"location\": \"Central US\"\r\n}", + "RequestHeaders": { + "x-ms-client-request-id": [ + "a2fd1a2a-ea96-4ecb-b85e-27a0b57a8ddd" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Content-Length": [ + "427" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-client-request-id": [ + "a2fd1a2a-ea96-4ecb-b85e-27a0b57a8ddd" + ], + "x-ms-correlation-request-id": [ + "4dec6c09-e3b8-4a84-b792-bd853b7c0f24" + ], + "x-ms-request-id": [ + "5ab702ab-5f53-4fab-9a3b-e40a35c18429" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "X-Frame-Options": [ + "DENY" + ], + "x-ms-ratelimit-remaining-subscription-writes": [ + "1195" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183850Z:4dec6c09-e3b8-4a84-b792-bd853b7c0f24" + ], + "Cache-Control": [ + "no-store, no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:38:49 GMT" + ], + "Content-Length": [ + "668" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "{\r\n \"properties\": {\r\n \"sourceType\": \"AzureStorage\",\r\n \"artifactRoot\": \"builds/1.0.0.0\",\r\n \"authentication\": {\r\n \"type\": \"Sas\",\r\n \"properties\": {\r\n \"sasUri\": \"https://sdktests.blob.core.windows.net/artifacts?sv=2017-07-29&sr=c&sig=cGTh4By%2F%2Fd4%2BkYNAZ8yHjYKB%2FMHcYfIZQXoaDbev1N8%3D&st=2019-03-14T22%3A38%3A46Z&se=2019-03-17T18%3A38%3A46Z&sp=rl\"\r\n }\r\n },\r\n \"provisioningState\": \"Succeeded\"\r\n },\r\n \"type\": \"Microsoft.DeploymentManager/artifactSources\",\r\n \"apiVersion\": \"2018-09-01-preview\",\r\n \"id\": \"/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourcegroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/artifactSources/powershell-sdk-tests\",\r\n \"name\": \"powershell-sdk-tests\",\r\n \"location\": \"Central US\"\r\n}", + "StatusCode": 201 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/serviceTopologies/powershell-sdk-tests?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9zZXJ2aWNlVG9wb2xvZ2llcy9wb3dlcnNoZWxsLXNkay10ZXN0cz9hcGktdmVyc2lvbj0yMDE4LTA5LTAxLXByZXZpZXc=", + "RequestMethod": "DELETE", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "49058773-99cf-4c24-84ba-73b1eca485f9" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-client-request-id": [ + "49058773-99cf-4c24-84ba-73b1eca485f9" + ], + "x-ms-correlation-request-id": [ + "37a073e3-d839-4253-a4eb-72d73cd5d693" + ], + "x-ms-request-id": [ + "96cb803b-f65b-4a4a-a3cf-f583868c2e9f" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "X-Frame-Options": [ + "DENY" + ], + "x-ms-ratelimit-remaining-subscription-deletes": [ + "14999" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183854Z:37a073e3-d839-4253-a4eb-72d73cd5d693" + ], + "Cache-Control": [ + "no-store, no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:38:53 GMT" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "null", + "StatusCode": 200 + }, + { + "RequestUri": "/subscriptions/53012dcb-5039-4e96-8e6c-5d913da1cdb5/resourceGroups/adm-powershell-test-rg/providers/Microsoft.DeploymentManager/artifactSources/powershell-sdk-tests-functional?api-version=2018-09-01-preview", + "EncodedRequestUri": "L3N1YnNjcmlwdGlvbnMvNTMwMTJkY2ItNTAzOS00ZTk2LThlNmMtNWQ5MTNkYTFjZGI1L3Jlc291cmNlR3JvdXBzL2FkbS1wb3dlcnNoZWxsLXRlc3QtcmcvcHJvdmlkZXJzL01pY3Jvc29mdC5EZXBsb3ltZW50TWFuYWdlci9hcnRpZmFjdFNvdXJjZXMvcG93ZXJzaGVsbC1zZGstdGVzdHMtZnVuY3Rpb25hbD9hcGktdmVyc2lvbj0yMDE4LTA5LTAxLXByZXZpZXc=", + "RequestMethod": "DELETE", + "RequestBody": "", + "RequestHeaders": { + "x-ms-client-request-id": [ + "913e2b37-69fd-47f5-aaa0-34c5a956971b" + ], + "accept-language": [ + "en-US" + ], + "User-Agent": [ + "FxVersion/4.7.3362.0", + "OSName/Windows10Enterprise", + "OSVersion/6.3.17763", + "Microsoft.Azure.Management.DeploymentManager.AzureDeploymentManagerClient/0.9.0.0" + ] + }, + "ResponseHeaders": { + "Pragma": [ + "no-cache" + ], + "x-ms-client-request-id": [ + "913e2b37-69fd-47f5-aaa0-34c5a956971b" + ], + "x-ms-correlation-request-id": [ + "ab3f024c-15e3-4320-9541-9bd504287026" + ], + "x-ms-request-id": [ + "ce82963c-04fe-4d8e-a4bb-f2262eb842b1" + ], + "Strict-Transport-Security": [ + "max-age=31536000; includeSubDomains" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "X-Frame-Options": [ + "DENY" + ], + "x-ms-ratelimit-remaining-subscription-deletes": [ + "14998" + ], + "x-ms-routing-request-id": [ + "WESTUS2:20190315T183858Z:ab3f024c-15e3-4320-9541-9bd504287026" + ], + "Cache-Control": [ + "no-store, no-cache" + ], + "Date": [ + "Fri, 15 Mar 2019 18:38:57 GMT" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "application/json; charset=utf-8" + ], + "Expires": [ + "-1" + ] + }, + "ResponseBody": "null", + "StatusCode": 200 + } + ], + "Names": {}, + "Variables": { + "SubscriptionId": "53012dcb-5039-4e96-8e6c-5d913da1cdb5" + } +} \ No newline at end of file diff --git a/src/DeploymentManager/Commands.DeploymentManager.Test/packages.config b/src/DeploymentManager/Commands.DeploymentManager.Test/packages.config new file mode 100644 index 000000000000..aa21123b15f6 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager.Test/packages.config @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/DeploymentManager/Commands.DeploymentManager/Az.DeploymentManager.psd1 b/src/DeploymentManager/Commands.DeploymentManager/Az.DeploymentManager.psd1 new file mode 100644 index 000000000000..bffa59102ad5 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Az.DeploymentManager.psd1 @@ -0,0 +1,155 @@ +# +# Module manifest for module 'AzureRM.DeploymentManager' +# +# Generated by: Microsoft Corporation +# +# Generated on: 8/25/2018 +# + +@{ + +# Script module or binary module file associated with this manifest. +# RootModule = '' + +# Version number of this module. +ModuleVersion = '0.2.0' + +# Supported PSEditions +CompatiblePSEditions = 'Core' + +# ID used to uniquely identify this module +GUID = 'caac1590-e859-444f-a9e0-62091c0f5929' + +# Author of this module +Author = 'Microsoft Corporation' + +# Company or vendor of this module +CompanyName = 'Microsoft Corporation' + +# Copyright statement for this module +Copyright = 'Microsoft Corporation. All rights reserved.' + +# Description of the functionality provided by this module +Description = 'PowerShell .Net Core] Microsoft Azure PowerShell - Deployment Manager cmdlets for Azure Resource Manager.' + +# Minimum version of the Windows PowerShell engine required by this module +PowerShellVersion = '5.1' + +# Name of the Windows PowerShell host required by this module +# PowerShellHostName = '' + +# Minimum version of the Windows PowerShell host required by this module +# PowerShellHostVersion = '' + +# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. +# DotNetFrameworkVersion = '' + +# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. +# CLRVersion = '4.0' + +# Processor architecture (None, X86, Amd64) required by this module +# ProcessorArchitecture = '' + +# Modules that must be imported into the global environment prior to importing this module +RequiredModules = @(@{ModuleName = 'Az.Profile'; ModuleVersion = '0.2.0'; }) + +# Assemblies that must be loaded prior to importing this module +RequiredAssemblies = '.\Microsoft.Azure.Management.DeploymentManager.dll' + +# Script files (.ps1) that are run in the caller's environment prior to importing this module. +# ScriptsToProcess = @() + +# Type files (.ps1xml) to be loaded when importing this module +# TypesToProcess = @() + +# Format files (.ps1xml) to be loaded when importing this module +# FormatsToProcess = '.\Microsoft.Azure.Commands.DeploymentManager.format.ps1xml' + +# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess +NestedModules = @('.\Microsoft.Azure.Commands.DeploymentManager.dll') + +# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. +FunctionsToExport = @() + +# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. +CmdletsToExport = 'Get-AzDeploymentManagerArtifactSource', + 'New-AzDeploymentManagerArtifactSource', + 'Set-AzDeploymentManagerArtifactSource', + 'Remove-AzDeploymentManagerArtifactSource', + 'Get-AzDeploymentManagerRollout', + 'Stop-AzDeploymentManagerRollout', + 'Restart-AzDeploymentManagerRollout', + 'Remove-AzDeploymentManagerRollout', + 'New-AzDeploymentManagerServiceTopology', + 'Get-AzDeploymentManagerServiceTopology', + 'Set-AzDeploymentManagerServiceTopology', + 'Remove-AzDeploymentManagerServiceTopology', + 'Get-AzDeploymentManagerService', + 'New-AzDeploymentManagerService', + 'Set-AzDeploymentManagerService', + 'Remove-AzDeploymentManagerService', + 'Get-AzDeploymentManagerServiceUnit', + 'New-AzDeploymentManagerServiceUnit', + 'Set-AzDeploymentManagerServiceUnit', + 'Remove-AzDeploymentManagerServiceUnit', + 'Get-AzDeploymentManagerStep', + 'New-AzDeploymentManagerStep', + 'Set-AzDeploymentManagerStep', + 'Remove-AzDeploymentManagerStep' + +# Variables to export from this module +# VariablesToExport = @() + +# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. +AliasesToExport = @() + +# DSC resources to export from this module +# DscResourcesToExport = @() + +# List of all modules packaged with this module +# ModuleList = @() + +# List of all files packaged with this module +# FileList = @() + +# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. +PrivateData = @{ + + PSData = @{ + + # Tags applied to this module. These help with module discovery in online galleries. + Tags = 'Azure','ResourceManager','ARM','DeploymentManager' + + # A URL to the license for this module. + LicenseUri = 'https://aka.ms/azps-license' + + # A URL to the main website for this project. + ProjectUri = 'https://github.com/Azure/azure-powershell' + + # A URL to an icon representing this module. + # IconUri = '' + + # ReleaseNotes of this module + ReleaseNotes = '* First release for private preview' + + # Prerelease string of this module + Prerelease = 'preview' + + # Flag to indicate whether the module requires explicit user acceptance for install/update + # RequireLicenseAcceptance = $false + + # External dependent modules of this module + # ExternalModuleDependencies = @() + + } # End of PSData hashtable + + } # End of PrivateData hashtable + +# HelpInfo URI of this module +# HelpInfoURI = '' + +# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. +# DefaultCommandPrefix = '' + +} + diff --git a/src/DeploymentManager/Commands.DeploymentManager/AzureRM.DeploymentManager.psd1 b/src/DeploymentManager/Commands.DeploymentManager/AzureRM.DeploymentManager.psd1 new file mode 100644 index 000000000000..8d129dfaf785 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/AzureRM.DeploymentManager.psd1 @@ -0,0 +1,155 @@ +# +# Module manifest for module 'PSGet_AzureRM.DeploymentManager' +# +# Generated by: Microsoft Corporation +# +# Generated on: 10/18/2018 +# + +@{ + +# Script module or binary module file associated with this manifest. +# RootModule = '' + +# Version number of this module. +ModuleVersion = '0.9.2' + +# Supported PSEditions +# CompatiblePSEditions = @() + +# ID used to uniquely identify this module +GUID = 'caac1590-e859-444f-a9e0-62091c0f5929' + +# Author of this module +Author = 'Microsoft Corporation' + +# Company or vendor of this module +CompanyName = 'Microsoft Corporation' + +# Copyright statement for this module +Copyright = 'Microsoft Corporation. All rights reserved.' + +# Description of the functionality provided by this module +Description = 'Microsoft Azure PowerShell - Deployment Manager cmdlets for Azure Resource Manager. Creates and manages Deployment Manager resources in Azure Resource Manager.' + +# Minimum version of the Windows PowerShell engine required by this module +PowerShellVersion = '5.0' + +# Name of the Windows PowerShell host required by this module +# PowerShellHostName = '' + +# Minimum version of the Windows PowerShell host required by this module +# PowerShellHostVersion = '' + +# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. +DotNetFrameworkVersion = '4.5.2' + +# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. +CLRVersion = '4.0' + +# Processor architecture (None, X86, Amd64) required by this module +# ProcessorArchitecture = '' + +# Modules that must be imported into the global environment prior to importing this module +RequiredModules = @(@{ModuleName = 'AzureRM.Profile'; ModuleVersion = '5.6.0'; }) + +# Assemblies that must be loaded prior to importing this module +RequiredAssemblies = '.\Microsoft.Azure.Management.DeploymentManager.dll' + +# Script files (.ps1) that are run in the caller's environment prior to importing this module. +# ScriptsToProcess = @() + +# Type files (.ps1xml) to be loaded when importing this module +# TypesToProcess = @() + +# Format files (.ps1xml) to be loaded when importing this module +# FormatsToProcess = @() + +# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess +NestedModules = @('.\Microsoft.Azure.Commands.DeploymentManager.dll') + +# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. +FunctionsToExport = @() + +# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. +CmdletsToExport = 'Get-AzureRmDeploymentManagerArtifactSource', + 'New-AzureRmDeploymentManagerArtifactSource', + 'Set-AzureRmDeploymentManagerArtifactSource', + 'Remove-AzureRmDeploymentManagerArtifactSource', + 'Get-AzureRmDeploymentManagerRollout', + 'Stop-AzureRmDeploymentManagerRollout', + 'Restart-AzureRmDeploymentManagerRollout', + 'Remove-AzureRmDeploymentManagerRollout', + 'New-AzureRmDeploymentManagerServiceTopology', + 'Get-AzureRmDeploymentManagerServiceTopology', + 'Set-AzureRmDeploymentManagerServiceTopology', + 'Remove-AzureRmDeploymentManagerServiceTopology', + 'Get-AzureRmDeploymentManagerService', + 'New-AzureRmDeploymentManagerService', + 'Set-AzureRmDeploymentManagerService', + 'Remove-AzureRmDeploymentManagerService', + 'Get-AzureRmDeploymentManagerServiceUnit', + 'New-AzureRmDeploymentManagerServiceUnit', + 'Set-AzureRmDeploymentManagerServiceUnit', + 'Remove-AzureRmDeploymentManagerServiceUnit', + 'Get-AzureRmDeploymentManagerStep', + 'New-AzureRmDeploymentManagerStep', + 'Set-AzureRmDeploymentManagerStep', + 'Remove-AzureRmDeploymentManagerStep' + +# Variables to export from this module +# VariablesToExport = @() + +# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. +AliasesToExport = @() + +# DSC resources to export from this module +# DscResourcesToExport = @() + +# List of all modules packaged with this module +# ModuleList = @() + +# List of all files packaged with this module +# FileList = @() + +# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. +PrivateData = @{ + + PSData = @{ + + # Tags applied to this module. These help with module discovery in online galleries. + Tags = 'Azure','ResourceManager','ARM','DeploymentManager' + + # A URL to the license for this module. + LicenseUri = 'https://raw.githubusercontent.com/Azure/azure-powershell/dev/LICENSE.txt' + + # A URL to the main website for this project. + ProjectUri = 'https://github.com/Azure/azure-powershell' + + # A URL to an icon representing this module. + # IconUri = '' + + # ReleaseNotes of this module + ReleaseNotes = '* Fix ArtifactSource command bug' + + # Prerelease string of this module + Prerelease = 'preview' + + # Flag to indicate whether the module requires explicit user acceptance for install/update + # RequireLicenseAcceptance = $false + + # External dependent modules of this module + # ExternalModuleDependencies = @() + + } # End of PSData hashtable + + } # End of PrivateData hashtable + +# HelpInfo URI of this module +# HelpInfoURI = '' + +# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. +# DefaultCommandPrefix = '' + +} + diff --git a/src/DeploymentManager/Commands.DeploymentManager/ChangeLog.md b/src/DeploymentManager/Commands.DeploymentManager/ChangeLog.md new file mode 100644 index 000000000000..c001b2b4c8d9 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/ChangeLog.md @@ -0,0 +1,29 @@ + +## Current Release + +## Version 0.9.2-preview +* Fix ArtifactSource command bug + +## Version 0.9.1-preview +* Enhance the discoverability of information provided by `Get-AzureRmDeploymentManagerRollout` when using the `-Verbose` and `-Error` switch parameters + +## Version 0.9.0-preview +* Add support for creating and managing rollouts and other supporting scenarios. diff --git a/src/DeploymentManager/Commands.DeploymentManager/Client/DeploymentManagerClient.cs b/src/DeploymentManager/Commands.DeploymentManager/Client/DeploymentManagerClient.cs new file mode 100644 index 000000000000..d1760f21e30b --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Client/DeploymentManagerClient.cs @@ -0,0 +1,312 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Client +{ + using System.Collections.Generic; + using System; + using System.Net; + + using Common.Authentication.Abstractions; + using Microsoft.Azure.Commands.Common.Authentication; + using Microsoft.Azure.Commands.DeploymentManager.Models; + using Microsoft.Azure.Management.DeploymentManager; + using Microsoft.Azure.Management.DeploymentManager.Models; + using Microsoft.Azure.Management.Internal.Resources; + using Microsoft.Rest.Azure; + + /// + /// The client that handles all the requests from the commands. + /// + internal class DeploymentManagerClient + { + /// + /// The deployment manager client. + /// + private AzureDeploymentManagerClient _client; + + /// + /// THe resource management client. + /// + private ResourceManagementClient _resourceManagementClient; + + /// + /// Initializes a new instance of the class. + /// + /// The current Azure session context. + internal DeploymentManagerClient(IAzureContext context) + { + this._client = AzureSession.Instance.ClientFactory.CreateArmClient(context, AzureEnvironment.Endpoint.ResourceManager); + this._resourceManagementClient = AzureSession.Instance.ClientFactory.CreateArmClient(context, AzureEnvironment.Endpoint.ResourceManager); + } + + /// + /// Initializes a new instance of the class. + /// + internal DeploymentManagerClient() { } + + /// + /// Gets or sets the logger used for vebose logging. + /// + internal Action VerboseLogger { get; set; } + + /// + /// Gets or sets the logger used to log errors. + /// + internal Action ErrorLogger { get; set; } + + internal PSRollout GetRollout(string resourceGroupName, string rolloutName, int? retryAttempt = null) + { + _resourceManagementClient.Providers.Register("Microsoft.DeploymentManager"); + + var rollout = _client.Rollouts.Get(resourceGroupName, rolloutName, retryAttempt); + return new PSRollout(resourceGroupName, rollout); + } + + internal PSRollout RestartRollout(PSRollout psRollout, bool? skipSucceeded = true) + { + _resourceManagementClient.Providers.Register("Microsoft.DeploymentManager"); + + var rollout = _client.Rollouts.Restart(psRollout.ResourceGroupName, psRollout.Name, skipSucceeded); + return new PSRollout(psRollout.ResourceGroupName, rollout); + } + + internal PSRollout CancelRollout(PSRollout psRollout) + { + _resourceManagementClient.Providers.Register("Microsoft.DeploymentManager"); + + var rollout = _client.Rollouts.Cancel(psRollout.ResourceGroupName, psRollout.Name); + return new PSRollout(psRollout.ResourceGroupName, rollout); + } + + internal bool DeleteRollout(PSRollout psRollout) + { + _resourceManagementClient.Providers.Register("Microsoft.DeploymentManager"); + + var result = _client.Rollouts.DeleteWithHttpMessagesAsync(psRollout.ResourceGroupName, psRollout.Name).GetAwaiter().GetResult(); + return (result.Response.StatusCode == HttpStatusCode.OK || result.Response.StatusCode == HttpStatusCode.NoContent); + } + + internal PSArtifactSource PutArtifactSource(PSArtifactSource psArtifactSource) + { + _resourceManagementClient.Providers.Register("Microsoft.DeploymentManager"); + + var artifactSource =_client.ArtifactSources.CreateOrUpdate( + psArtifactSource.ResourceGroupName, + psArtifactSource.Name, + psArtifactSource.ToSdkType()); + + return new PSArtifactSource(psArtifactSource.ResourceGroupName, artifactSource); + } + + internal bool ArtifactSourceExists(PSArtifactSource psArtifactSource) + { + return DeploymentManagerClient.ResourceExists(psArtifactSource, this.GetArtifactSource); + } + + internal PSArtifactSource GetArtifactSource(PSArtifactSource psArtifactSource) + { + _resourceManagementClient.Providers.Register("Microsoft.DeploymentManager"); + + var artifactSource = _client.ArtifactSources.Get(psArtifactSource.ResourceGroupName, psArtifactSource.Name); + return new PSArtifactSource(psArtifactSource.ResourceGroupName, artifactSource); + } + + internal bool DeleteArtifactSource(PSArtifactSource psArtifactSource) + { + _resourceManagementClient.Providers.Register("Microsoft.DeploymentManager"); + + var result = _client.ArtifactSources.DeleteWithHttpMessagesAsync(psArtifactSource.ResourceGroupName, psArtifactSource.Name).GetAwaiter().GetResult(); + return (result.Response.StatusCode == HttpStatusCode.OK || result.Response.StatusCode == HttpStatusCode.NoContent); + } + + internal PSServiceTopologyResource PutServiceTopology(PSServiceTopologyResource psTopologyResource) + { + _resourceManagementClient.Providers.Register("Microsoft.DeploymentManager"); + + var serviceTopologyResource = _client.ServiceTopologies.CreateOrUpdate( + psTopologyResource.ToSdkType(), + psTopologyResource.ResourceGroupName, + psTopologyResource.Name); + + return new PSServiceTopologyResource(psTopologyResource.ResourceGroupName, serviceTopologyResource); + } + + internal bool ServiceTopologyExists(PSServiceTopologyResource psServiceTopologyResource) + { + return DeploymentManagerClient.ResourceExists(psServiceTopologyResource, this.GetServiceTopology); + } + + internal PSServiceResource PutService(PSServiceResource psServiceResource) + { + _resourceManagementClient.Providers.Register("Microsoft.DeploymentManager"); + + var serviceResource = _client.Services.CreateOrUpdate( + psServiceResource.ResourceGroupName, + psServiceResource.ServiceTopologyName, + psServiceResource.Name, + psServiceResource.ToSdkType()); + + return new PSServiceResource(psServiceResource.ResourceGroupName, psServiceResource.ServiceTopologyName, serviceResource); + } + + internal bool ServiceExists(PSServiceResource psServiceResource) + { + return DeploymentManagerClient.ResourceExists(psServiceResource, this.GetService); + } + + internal PSServiceUnitResource PutServiceUnit( + PSServiceUnitResource psServiceUnitResource) + { + _resourceManagementClient.Providers.Register("Microsoft.DeploymentManager"); + + var serviceUnitResource = _client.ServiceUnits.CreateOrUpdate( + psServiceUnitResource.ResourceGroupName, + psServiceUnitResource.ServiceTopologyName, + psServiceUnitResource.ServiceName, + psServiceUnitResource.Name, + psServiceUnitResource.ToSdkType()); + + return new PSServiceUnitResource( + psServiceUnitResource.ResourceGroupName, + psServiceUnitResource.ServiceTopologyName, + psServiceUnitResource.ServiceName, + serviceUnitResource); + } + + internal bool ServiceUnitExists(PSServiceUnitResource psServiceUnitResource) + { + return DeploymentManagerClient.ResourceExists(psServiceUnitResource, this.GetServiceUnit); + } + + internal PSServiceTopologyResource GetServiceTopology(PSServiceTopologyResource pSServiceTopologyResource) + { + _resourceManagementClient.Providers.Register("Microsoft.DeploymentManager"); + + var serviceTopologyResource = _client.ServiceTopologies.Get(pSServiceTopologyResource.ResourceGroupName, pSServiceTopologyResource.Name); + return new PSServiceTopologyResource(pSServiceTopologyResource.ResourceGroupName, serviceTopologyResource); + } + + internal PSServiceResource GetService(PSServiceResource pSServiceResource) + { + _resourceManagementClient.Providers.Register("Microsoft.DeploymentManager"); + + var serviceResource = _client.Services.Get(pSServiceResource.ResourceGroupName, pSServiceResource.ServiceTopologyName, pSServiceResource.Name); + + return new PSServiceResource( + pSServiceResource.ResourceGroupName, + pSServiceResource.ServiceTopologyName, + serviceResource); + } + + internal PSServiceUnitResource GetServiceUnit(PSServiceUnitResource psServiceUnit) + { + _resourceManagementClient.Providers.Register("Microsoft.DeploymentManager"); + + var serviceUnit = _client.ServiceUnits.Get(psServiceUnit.ResourceGroupName, psServiceUnit.ServiceTopologyName, psServiceUnit.ServiceName, psServiceUnit.Name); + + return new PSServiceUnitResource( + psServiceUnit.ResourceGroupName, + psServiceUnit.ServiceTopologyName, + psServiceUnit.ServiceName, + serviceUnit); + } + + internal bool DeleteServiceTopology(PSServiceTopologyResource psServiceTopologyResource) + { + _resourceManagementClient.Providers.Register("Microsoft.DeploymentManager"); + + var result = _client.ServiceTopologies.DeleteWithHttpMessagesAsync(psServiceTopologyResource.ResourceGroupName, psServiceTopologyResource.Name).GetAwaiter().GetResult(); + return (result.Response.StatusCode == HttpStatusCode.OK || result.Response.StatusCode == HttpStatusCode.NoContent); + } + + internal bool DeleteService(PSServiceResource psServiceResource) + { + _resourceManagementClient.Providers.Register("Microsoft.DeploymentManager"); + + var result = _client.Services.DeleteWithHttpMessagesAsync(psServiceResource.ResourceGroupName, psServiceResource.ServiceTopologyName, psServiceResource.Name).GetAwaiter().GetResult(); + return (result.Response.StatusCode == HttpStatusCode.OK || result.Response.StatusCode == HttpStatusCode.NoContent); + } + + internal bool DeleteServiceUnit(PSServiceUnitResource psServiceUnitResource) + { + _resourceManagementClient.Providers.Register("Microsoft.DeploymentManager"); + + var result = _client.ServiceUnits.DeleteWithHttpMessagesAsync( + psServiceUnitResource.ResourceGroupName, + psServiceUnitResource.ServiceTopologyName, + psServiceUnitResource.ServiceName, + psServiceUnitResource.Name).GetAwaiter().GetResult(); + return (result.Response.StatusCode == HttpStatusCode.OK || result.Response.StatusCode == HttpStatusCode.NoContent); + } + + internal PSStepResource PutStep(PSStepResource psStepResource) + { + _resourceManagementClient.Providers.Register("Microsoft.DeploymentManager"); + + var stepResource = _client.Steps.CreateOrUpdate( + psStepResource.ResourceGroupName, + psStepResource.Name, + psStepResource.ToSdkType()); + + return new PSStepResource(psStepResource.ResourceGroupName, stepResource); + } + + internal bool StepExists(PSStepResource psStepResource) + { + return DeploymentManagerClient.ResourceExists(psStepResource, this.GetStep); + } + + internal PSStepResource GetStep(PSStepResource psStepResource) + { + _resourceManagementClient.Providers.Register("Microsoft.DeploymentManager"); + + var stepResource = _client.Steps.Get(psStepResource.ResourceGroupName, psStepResource.Name); + return new PSStepResource(psStepResource.ResourceGroupName, stepResource); + } + + internal bool DeleteStep(PSStepResource psStepResource) + { + _resourceManagementClient.Providers.Register("Microsoft.DeploymentManager"); + + var result = _client.Steps.DeleteWithHttpMessagesAsync(psStepResource.ResourceGroupName, psStepResource.Name).GetAwaiter().GetResult(); + return (result.Response.StatusCode == HttpStatusCode.OK || result.Response.StatusCode == HttpStatusCode.NoContent); + } + + internal IList GetOperations() + { + _resourceManagementClient.Providers.Register("Microsoft.DeploymentManager"); + + return _client.Operations.Get(); + } + + private static bool ResourceExists(T resourceObject, Func getFunc) where T : PSResource + { + T retrievedServiceResource = null; + try + { + retrievedServiceResource = getFunc(resourceObject); + } + catch (CloudException ex) + { + if (ex.Response.StatusCode == HttpStatusCode.NotFound) + { + return false; + } + } + + return retrievedServiceResource != null; + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands.DeploymentManager.NetCore.csproj b/src/DeploymentManager/Commands.DeploymentManager/Commands.DeploymentManager.NetCore.csproj new file mode 100644 index 000000000000..329aeae67968 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Commands.DeploymentManager.NetCore.csproj @@ -0,0 +1,57 @@ + + + + + + netcoreapp2.0 + Microsoft.Azure.Commands.DeploymentManager + Microsoft.Azure.Commands.DeploymentManager + false + true + true + false + $(ProjectDir)..\..\..\Package\$(Configuration)\ResourceManager\AzureResourceManager\Az.DeploymentManager\ + + + + false + TRACE;DEBUG;NETSTANDARD + + + + true + true + MSSharedLibKey.snk + TRACE;RELEASE;NETSTANDARD;SIGN + + + + + + + + + PreserveNewest + + + + + + true + true + Messages.resx + + + + + + ResXFileCodeGenerator + Messages.Designer.cs + + + + + + + + \ No newline at end of file diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands.DeploymentManager.csproj b/src/DeploymentManager/Commands.DeploymentManager/Commands.DeploymentManager.csproj new file mode 100644 index 000000000000..eb403c8f712e --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Commands.DeploymentManager.csproj @@ -0,0 +1,17 @@ + + + + DeploymentManager + + + + + + $(LegacyAssemblyPrefix)$(PsModuleName) + + + + + + + \ No newline at end of file diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/DeploymentManagerBaseCmdlet.cs b/src/DeploymentManager/Commands.DeploymentManager/Commands/DeploymentManagerBaseCmdlet.cs new file mode 100644 index 000000000000..ae7a537d5ec3 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Commands/DeploymentManagerBaseCmdlet.cs @@ -0,0 +1,65 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Commands +{ + using Microsoft.Azure.Commands.DeploymentManager.Client; + using ResourceManager.Common; + + /// + /// The base class for all the cmdlets. + /// + public abstract class DeploymentManagerBaseCmdlet : AzureRMCmdlet + { + /// + /// The client used to communicate with Azure Deployment Manager. + /// + private DeploymentManagerClient deploymentManagerClient; + + /// + /// The parameter set name to be used when individual properties are given to identify a resource. + /// + protected const string InteractiveParamSetName = "Interactive"; + + /// + /// The parameter set name to be used for parameter set where a resource identifier is provided. + /// + protected const string ResourceIdParamSetName = "ResourceId"; + + /// + /// The parameter set name to be used for parameter set where a resource object is provided. + /// + protected const string InputObjectParamSetName = "InputObject"; + + /// + /// Gets or sets the Azure Deployment Manager client. + /// + internal DeploymentManagerClient DeploymentManagerClient + { + get + { + if (this.deploymentManagerClient == null) + { + this.deploymentManagerClient = new DeploymentManagerClient(DefaultProfile.DefaultContext); + } + + this.deploymentManagerClient.VerboseLogger = WriteVerboseWithTimestamp; + this.deploymentManagerClient.ErrorLogger = WriteErrorWithTimestamp; + return this.deploymentManagerClient; + } + + set { this.deploymentManagerClient = value; } + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/GetArtifactSource.cs b/src/DeploymentManager/Commands.DeploymentManager/Commands/GetArtifactSource.cs new file mode 100644 index 000000000000..6ed0ac8401f3 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Commands/GetArtifactSource.cs @@ -0,0 +1,91 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Commands +{ + using System.Management.Automation; + + using Microsoft.Azure.Commands.DeploymentManager.Models; + using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; + using Microsoft.Azure.Management.Internal.Resources.Utilities.Models; + + [Cmdlet( + VerbsCommon.Get, + ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "DeploymentManagerArtifactSource", + DefaultParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName), + OutputType(typeof(PSArtifactSource))] + public class GetArtifactSource : DeploymentManagerBaseCmdlet + { + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The resource group.")] + [ValidateNotNullOrEmpty] + [ResourceGroupCompleter] + public string ResourceGroupName { get; set; } + + [Parameter( + Position = 1, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the artifact source.")] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.ResourceIdParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The resource identifier.")] + [ValidateNotNullOrEmpty] + public string ResourceId { get; set; } + + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InputObjectParamSetName, + ValueFromPipeline = true, + HelpMessage = "Artifact Source object.")] + [ValidateNotNullOrEmpty] + public PSArtifactSource ArtifactSource { get; set; } + + public override void ExecuteCmdlet() + { + if (this.ArtifactSource != null) + { + this.ResourceGroupName = this.ArtifactSource.ResourceGroupName; + this.Name = this.ArtifactSource.Name; + } + else if (!string.IsNullOrWhiteSpace(this.ResourceId)) + { + var parsedResourceId = new ResourceIdentifier(this.ResourceId); + this.ResourceGroupName = parsedResourceId.ResourceGroupName; + this.Name = parsedResourceId.ResourceName; + } + + var psArtifactSource = new PSArtifactSource() + { + ResourceGroupName = this.ResourceGroupName, + Name = this.Name, + }; + + psArtifactSource = this.DeploymentManagerClient.GetArtifactSource(psArtifactSource); + this.WriteObject(psArtifactSource); + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/GetRollout.cs b/src/DeploymentManager/Commands.DeploymentManager/Commands/GetRollout.cs new file mode 100644 index 000000000000..d357deea8bc8 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Commands/GetRollout.cs @@ -0,0 +1,96 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Commands +{ + using System.Management.Automation; + + using Microsoft.Azure.Commands.DeploymentManager.Models; + using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; + using Microsoft.Azure.Management.Internal.Resources.Utilities.Models; + + [Cmdlet( + VerbsCommon.Get, + ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "DeploymentManagerRollout", + DefaultParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName), + OutputType(typeof(PSRollout))] + public class GetRollout : RolloutCmdletBase + { + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The resource group.")] + [ValidateNotNullOrEmpty] + [ResourceGroupCompleter] + public string ResourceGroupName { get; set; } + + [Parameter( + Position = 1, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the rollout.")] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter( + Position = 2, + Mandatory = false, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The retry attempt of the rollout.")] + [ValidateNotNullOrEmpty] + public int? RetryAttempt { get; set; } + + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.ResourceIdParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The resource identifier.")] + [ValidateNotNullOrEmpty] + public string ResourceId { get; set; } + + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InputObjectParamSetName, + ValueFromPipeline = true, + HelpMessage = "Rollout object.")] + [ValidateNotNullOrEmpty] + public PSRollout Rollout { get; set; } + + public override void ExecuteCmdlet() + { + if (this.Rollout != null) + { + this.ResourceGroupName = this.Rollout.ResourceGroupName; + this.Name = this.Rollout.Name; + } + else if (!string.IsNullOrWhiteSpace(this.ResourceId)) + { + var parsedResourceId = new ResourceIdentifier(this.ResourceId); + this.ResourceGroupName = parsedResourceId.ResourceGroupName; + this.Name = parsedResourceId.ResourceName; + } + + var rollout = this.DeploymentManagerClient.GetRollout(this.ResourceGroupName, this.Name, this.RetryAttempt); + + this.PrintRollout(rollout); + this.WriteObject(rollout); + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/GetService.cs b/src/DeploymentManager/Commands.DeploymentManager/Commands/GetService.cs new file mode 100644 index 000000000000..fd5dbeac0a95 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Commands/GetService.cs @@ -0,0 +1,167 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Commands +{ + using System; + using System.Management.Automation; + using Microsoft.Azure.Commands.DeploymentManager.Models; + using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; + using Microsoft.Azure.Management.Internal.Resources.Utilities.Models; + + [Cmdlet( + VerbsCommon.Get, + ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "DeploymentManagerService", + DefaultParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName), + OutputType(typeof(PSServiceResource))] + public class GetService : DeploymentManagerBaseCmdlet + { + private const string ByServiceTopologyObjectParameterSet = "ByServiceTopologyObject"; + + private const string ByServiceTopologyResourceIdParamSet = "ByServiceTopologyResourceId"; + + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The resource group.")] + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = GetService.ByServiceTopologyObjectParameterSet, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The resource group.")] + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = GetService.ByServiceTopologyResourceIdParamSet, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The resource group.")] + [ValidateNotNullOrEmpty] + [ResourceGroupCompleter] + public string ResourceGroupName { get; set; } + + [Parameter( + Position = 1, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the service topology.")] + [ValidateNotNullOrEmpty] + public string ServiceTopologyName { get; set; } + + [Parameter( + Position = 2, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the service.")] + [Parameter( + Position = 2, + Mandatory = true, + ParameterSetName = GetService.ByServiceTopologyObjectParameterSet, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the service.")] + [Parameter( + Position = 2, + Mandatory = true, + ParameterSetName = GetService.ByServiceTopologyResourceIdParamSet, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the service.")] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.ResourceIdParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The resource identifier.")] + [ValidateNotNullOrEmpty] + public string ResourceId { get; set; } + + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InputObjectParamSetName, + ValueFromPipeline = true, + HelpMessage = "Service object.")] + [ValidateNotNullOrEmpty] + public PSServiceResource Service { get; set; } + + [Parameter( + Position = 1, + Mandatory = true, + ParameterSetName = GetService.ByServiceTopologyObjectParameterSet, + HelpMessage = "The service topology object in which the service should be created.")] + [ValidateNotNullOrEmpty] + public PSServiceTopologyResource ServiceTopology { get; set; } + + [Parameter( + Position = 1, + Mandatory = true, + ParameterSetName = GetService.ByServiceTopologyResourceIdParamSet, + HelpMessage = "The service topology resource identifier in which the service should be created.")] + [ValidateNotNullOrEmpty] + public string ServiceTopologyResourceId { get; set; } + + public override void ExecuteCmdlet() + { + this.ResolveParams(); + var psServiceResource = new PSServiceResource() + { + ResourceGroupName = this.ResourceGroupName, + ServiceTopologyName = this.ServiceTopologyName, + Name = this.Name + }; + + psServiceResource = this.DeploymentManagerClient.GetService(psServiceResource); + this.WriteObject(psServiceResource); + } + + private void ResolveParams() + { + if (this.Service != null) + { + this.ResourceGroupName = this.Service.ResourceGroupName; + this.ServiceTopologyName = this.Service.ServiceTopologyName; + this.Name = this.Service.Name; + } + else if (!string.IsNullOrWhiteSpace(this.ResourceId)) + { + var parsedResourceId = new ResourceIdentifier(this.ResourceId); + this.ResourceGroupName = parsedResourceId.ResourceGroupName; + this.Name = parsedResourceId.ResourceName; + + string[] tokens = parsedResourceId.ParentResource.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); + if (tokens.Length < 2) + { + throw new ArgumentException($"Invalid Service resource identifier: {this.ResourceId}"); + } + + this.ServiceTopologyName = tokens[1]; + } + else if (this.ServiceTopology != null) + { + this.ServiceTopologyName = this.ServiceTopology.Name; + } + else if (!string.IsNullOrWhiteSpace(this.ServiceTopologyResourceId)) + { + var parsedResourceId = new ResourceIdentifier(this.ServiceTopologyResourceId); + this.ServiceTopologyName = parsedResourceId.ResourceName; + } + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/GetServiceTopology.cs b/src/DeploymentManager/Commands.DeploymentManager/Commands/GetServiceTopology.cs new file mode 100644 index 000000000000..266b56d2e102 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Commands/GetServiceTopology.cs @@ -0,0 +1,91 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Commands +{ + using System.Management.Automation; + + using Microsoft.Azure.Commands.DeploymentManager.Models; + using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; + using Microsoft.Azure.Management.Internal.Resources.Utilities.Models; + + [Cmdlet( + VerbsCommon.Get, + ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "DeploymentManagerServiceTopology", + DefaultParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName), + OutputType(typeof(PSServiceTopologyResource))] + public class GetServiceTopology : DeploymentManagerBaseCmdlet + { + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The resource group.")] + [ValidateNotNullOrEmpty] + [ResourceGroupCompleter] + public string ResourceGroupName { get; set; } + + [Parameter( + Position = 1, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the service topology.")] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.ResourceIdParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The resource identifier.")] + [ValidateNotNullOrEmpty] + public string ResourceId { get; set; } + + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InputObjectParamSetName, + ValueFromPipeline = true, + HelpMessage = "Service topology resource object.")] + [ValidateNotNullOrEmpty] + public PSServiceTopologyResource ServiceTopology { get; set; } + + public override void ExecuteCmdlet() + { + if (this.ServiceTopology != null) + { + this.ResourceGroupName = this.ServiceTopology.ResourceGroupName; + this.Name = this.ServiceTopology.Name; + } + else if (!string.IsNullOrWhiteSpace(this.ResourceId)) + { + var parsedResourceId = new ResourceIdentifier(this.ResourceId); + this.ResourceGroupName = parsedResourceId.ResourceGroupName; + this.Name = parsedResourceId.ResourceName; + } + + var psServiceTopologyResource = new PSServiceTopologyResource() + { + ResourceGroupName = this.ResourceGroupName, + Name = this.Name + }; + + psServiceTopologyResource = this.DeploymentManagerClient.GetServiceTopology(psServiceTopologyResource); + this.WriteObject(psServiceTopologyResource); + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/GetServiceUnit.cs b/src/DeploymentManager/Commands.DeploymentManager/Commands/GetServiceUnit.cs new file mode 100644 index 000000000000..5e968b3fca0d --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Commands/GetServiceUnit.cs @@ -0,0 +1,251 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Commands +{ + using System; + using System.Management.Automation; + + using Microsoft.Azure.Commands.DeploymentManager.Models; + using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; + using Microsoft.Azure.Management.Internal.Resources.Utilities.Models; + + [Cmdlet( + VerbsCommon.Get, + ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "DeploymentManagerServiceUnit", + DefaultParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName), + OutputType(typeof(PSServiceUnitResource))] + public class GetServiceUnit : DeploymentManagerBaseCmdlet + { + private const string ByServiceObjectParameterSet = "ByServiceObject"; + private const string ByServiceResourceIdParamSet = "ByServiceResourceId"; + private const string ByTopologyObjectAndServiceNameParameterSet = "ByTopologyObjectAndServiceName"; + private const string ByTopologyResourceIdAndServiceNameParameterSet = "ByTopologyResourceAndServiceName"; + + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The resource group.")] + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = GetServiceUnit.ByServiceObjectParameterSet, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The resource group.")] + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = GetServiceUnit.ByServiceResourceIdParamSet, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The resource group.")] + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = GetServiceUnit.ByTopologyObjectAndServiceNameParameterSet, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The resource group.")] + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = GetServiceUnit.ByTopologyResourceIdAndServiceNameParameterSet, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The resource group.")] + [ValidateNotNullOrEmpty] + [ResourceGroupCompleter] + public string ResourceGroupName { get; set; } + + [Parameter( + Position = 1, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the service topology the service unit is part of.")] + [ValidateNotNullOrEmpty] + public string ServiceTopologyName { get; set; } + + [Parameter( + Position = 2, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the service the service unit is part of.")] + [Parameter( + Position = 2, + Mandatory = true, + ParameterSetName = GetServiceUnit.ByTopologyObjectAndServiceNameParameterSet, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the service the service unit is part of.")] + [Parameter( + Position = 2, + Mandatory = true, + ParameterSetName = GetServiceUnit.ByTopologyResourceIdAndServiceNameParameterSet, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the service the service unit is part of.")] + [ValidateNotNullOrEmpty] + public string ServiceName { get; set; } + + [Parameter( + Position = 3, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the service unit.")] + [Parameter( + Position = 2, + Mandatory = true, + ParameterSetName = GetServiceUnit.ByServiceObjectParameterSet, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the service unit.")] + [Parameter( + Position = 2, + Mandatory = true, + ParameterSetName = GetServiceUnit.ByServiceResourceIdParamSet, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the service unit.")] + [Parameter( + Position = 3, + Mandatory = true, + ParameterSetName = GetServiceUnit.ByTopologyObjectAndServiceNameParameterSet, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the service unit.")] + [Parameter( + Position = 3, + Mandatory = true, + ParameterSetName = GetServiceUnit.ByTopologyResourceIdAndServiceNameParameterSet, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the service unit.")] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.ResourceIdParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The resource identifier.")] + [ValidateNotNullOrEmpty] + public string ResourceId { get; set; } + + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InputObjectParamSetName, + ValueFromPipeline = true, + HelpMessage = "Service unit resource object.")] + [ValidateNotNullOrEmpty] + public PSServiceUnitResource ServiceUnit { get; set; } + + [Parameter( + Position = 1, + Mandatory = true, + ParameterSetName = GetServiceUnit.ByTopologyObjectAndServiceNameParameterSet, + HelpMessage = "The service topology object in which the service unit should be created.")] + [ValidateNotNullOrEmpty] + public PSServiceTopologyResource ServiceTopology { get; set; } + + [Parameter( + Position = 1, + Mandatory = true, + ParameterSetName = GetServiceUnit.ByTopologyResourceIdAndServiceNameParameterSet, + HelpMessage = "The service topology resource identifier in which the service unit should be created.")] + [ValidateNotNullOrEmpty] + public string ServiceTopologyResourceId { get; set; } + + [Parameter( + Position = 1, + Mandatory = true, + ParameterSetName = GetServiceUnit.ByServiceObjectParameterSet, + HelpMessage = "The service object in which the service unit should be created.")] + [ValidateNotNullOrEmpty] + public PSServiceResource Service { get; set; } + + [Parameter( + Position = 1, + Mandatory = true, + ParameterSetName = GetServiceUnit.ByServiceResourceIdParamSet, + HelpMessage = "The service resource identifier in which the service unit should be created.")] + [ValidateNotNullOrEmpty] + public string ServiceResourceId { get; set; } + + public override void ExecuteCmdlet() + { + this.ResolveParameters(); + var psServiceUnitResource = new PSServiceUnitResource() + { + ResourceGroupName = this.ResourceGroupName, + ServiceTopologyName = this.ServiceTopologyName, + ServiceName = this.ServiceName, + Name = this.Name + }; + + var serviceUnitResource = this.DeploymentManagerClient.GetServiceUnit(psServiceUnitResource); + this.WriteObject(serviceUnitResource); + } + + private void ResolveParameters() + { + if (this.ServiceUnit != null) + { + this.ResourceGroupName = this.ServiceUnit.ResourceGroupName; + this.ServiceTopologyName = this.ServiceUnit.ServiceTopologyName; + this.ServiceName = this.ServiceUnit.ServiceName; + this.Name = this.ServiceUnit.Name; + } + else if (!string.IsNullOrWhiteSpace(this.ResourceId)) + { + var parsedResourceId = new ResourceIdentifier(this.ResourceId); + this.ResourceGroupName = parsedResourceId.ResourceGroupName; + this.Name = parsedResourceId.ResourceName; + + string[] tokens = parsedResourceId.ParentResource.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); + if (tokens.Length < 4) + { + throw new ArgumentException($"Invalid Service Unit resource identifier: {this.ResourceId}"); + } + + this.ServiceTopologyName = tokens[1]; + this.ServiceName = tokens[3]; + } + else if (this.Service != null) + { + this.ServiceTopologyName = this.Service.ServiceTopologyName; + this.ServiceName = this.Service.Name; + } + else if (!string.IsNullOrWhiteSpace(this.ServiceResourceId)) + { + var parsedResourceId = new ResourceIdentifier(this.ServiceResourceId); + this.ServiceName = parsedResourceId.ResourceName; + string[] tokens = parsedResourceId.ParentResource.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); + if (tokens.Length < 2) + { + throw new ArgumentException($"Invalid Service resource identifier: {this.ServiceResourceId}"); + } + + this.ServiceTopologyName = tokens[1]; + } + else if (this.ServiceTopology != null) + { + this.ServiceTopologyName = this.ServiceTopology.Name; + } + else if (!string.IsNullOrWhiteSpace(this.ServiceTopologyResourceId)) + { + var parsedResourceId = new ResourceIdentifier(this.ServiceTopologyResourceId); + this.ServiceTopologyName = parsedResourceId.ResourceName; + } + } + + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/GetStep.cs b/src/DeploymentManager/Commands.DeploymentManager/Commands/GetStep.cs new file mode 100644 index 000000000000..d32fbd63fca9 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Commands/GetStep.cs @@ -0,0 +1,91 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Commands +{ + using System.Management.Automation; + + using Microsoft.Azure.Commands.DeploymentManager.Models; + using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; + using Microsoft.Azure.Management.Internal.Resources.Utilities.Models; + + [Cmdlet( + VerbsCommon.Get, + ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "DeploymentManagerStep", + DefaultParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName), + OutputType(typeof(PSStepResource))] + public class GetStep : DeploymentManagerBaseCmdlet + { + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The resource group.")] + [ValidateNotNullOrEmpty] + [ResourceGroupCompleter] + public string ResourceGroupName { get; set; } + + [Parameter( + Position = 1, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the step.")] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.ResourceIdParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The resource identifier.")] + [ValidateNotNullOrEmpty] + public string ResourceId { get; set; } + + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InputObjectParamSetName, + ValueFromPipeline = true, + HelpMessage = "The step resource object.")] + [ValidateNotNullOrEmpty] + public PSStepResource Step { get; set; } + + public override void ExecuteCmdlet() + { + if (this.Step != null) + { + this.ResourceGroupName = this.Step.ResourceGroupName; + this.Name = this.Step.Name; + } + else if (!string.IsNullOrWhiteSpace(this.ResourceId)) + { + var parsedResourceId = new ResourceIdentifier(this.ResourceId); + this.ResourceGroupName = parsedResourceId.ResourceGroupName; + this.Name = parsedResourceId.ResourceName; + } + + var psStepResource = new PSStepResource() + { + ResourceGroupName = this.ResourceGroupName, + Name = this.Name, + }; + + psStepResource = this.DeploymentManagerClient.GetStep(psStepResource); + this.WriteObject(psStepResource); + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/NewArtifactSource.cs b/src/DeploymentManager/Commands.DeploymentManager/Commands/NewArtifactSource.cs new file mode 100644 index 000000000000..00897aba5529 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Commands/NewArtifactSource.cs @@ -0,0 +1,112 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Commands +{ + using System.Collections; + using System.Management.Automation; + + using Microsoft.Azure.Commands.DeploymentManager.Models; + using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; + + [Cmdlet( + VerbsCommon.New, + ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "DeploymentManagerArtifactSource", + SupportsShouldProcess = true), + OutputType(typeof(PSArtifactSource))] + public class NewArtifactSource : DeploymentManagerBaseCmdlet + { + /// + /// The parameter set for SAS-based authentication. + /// + private const string SasUriParamSet = "Sas"; + + [Parameter( + Mandatory = true, + HelpMessage = "The resource group.")] + [ValidateNotNullOrEmpty] + [ResourceGroupCompleter] + public string ResourceGroupName { get; set; } + + [Parameter( + Mandatory = true, + HelpMessage = "The name of the artifact source.")] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter( + Mandatory = true, + HelpMessage = "The location of the resource.")] + [ValidateNotNullOrEmpty] + [LocationCompleter] + public string Location { get; set; } + + [Parameter( + Mandatory = true, + HelpMessage = "The SAS Uri to the Azure storage container where the artifacts are stored.", ParameterSetName = NewArtifactSource.SasUriParamSet)] + [ValidateNotNullOrEmpty] + public string SasUri { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipelineByPropertyName = true, + HelpMessage = "A hash table which represents resource tags.")] + public Hashtable Tag { get; set; } + + [Parameter( + Mandatory = false, + HelpMessage = "The optional directory offset under the storage container for the artifacts.")] + public string ArtifactRoot { get; set; } + + public override void ExecuteCmdlet() + { + if (this.ShouldProcess(this.Name, Messages.CreateArtifactSource)) + { + var psArtifactSource = new PSArtifactSource() + { + ResourceGroupName = this.ResourceGroupName, + Name = this.Name, + Location = this.Location, + SourceType = "AzureStorage", + ArtifactRoot = this.ArtifactRoot, + Authentication = this.GetAuthentication(), + Tags = this.Tag + }; + + if (this.DeploymentManagerClient.ArtifactSourceExists(psArtifactSource)) + { + throw new PSArgumentException(Messages.ArtifactSourceAlreadyExists); + } + + psArtifactSource = this.DeploymentManagerClient.PutArtifactSource(psArtifactSource); + this.WriteObject(psArtifactSource); + } + } + + private PSAuthentication GetAuthentication() + { + switch (this.ParameterSetName) + { + case SasUriParamSet: + return new PSSasAuthentication() + { + SasUri = this.SasUri + }; + + default: + return null; + } + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/NewService.cs b/src/DeploymentManager/Commands.DeploymentManager/Commands/NewService.cs new file mode 100644 index 000000000000..4bef53f7c43e --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Commands/NewService.cs @@ -0,0 +1,133 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Commands +{ + using System.Collections; + using System.Management.Automation; + + using Microsoft.Azure.Commands.DeploymentManager.Models; + using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; + using Microsoft.Azure.Management.Internal.Resources.Utilities.Models; + + [Cmdlet( + VerbsCommon. + New, ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "DeploymentManagerService", + SupportsShouldProcess = true, + DefaultParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName), + OutputType(typeof(PSServiceResource))] + public class NewService : DeploymentManagerBaseCmdlet + { + private const string ByServiceTopologyObjectParameterSet = "ByServiceTopologyObject"; + private const string ByServiceTopologyResourceIdParamSet = "ByServiceTopologyResourceId"; + + [Parameter( + Position = 0, + Mandatory = true, + HelpMessage = "The resource group.")] + [ValidateNotNullOrEmpty] + [ResourceGroupCompleter] + public string ResourceGroupName { get; set; } + + [Parameter( + Position = 1, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + HelpMessage = "The name of the service topology this service belongs to.")] + [ValidateNotNullOrEmpty] + public string ServiceTopologyName { get; set; } + + [Parameter( + Mandatory = true, + HelpMessage = "The name of the service.")] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter( + Mandatory = true, + HelpMessage = "The location of the service resource.")] + [ValidateNotNullOrEmpty] + [LocationCompleter] + public string Location { get; set; } + + [Parameter( + Mandatory = true, + HelpMessage = "Determines the location where resources under the service would be deployed to.")] + [ValidateNotNullOrEmpty] + public string TargetLocation { get; set; } + + [Parameter( + Mandatory = true, + HelpMessage = "Determines the subscription to which resources under the service would be deployed to.")] + [ValidateNotNullOrEmpty] + public string TargetSubscriptionId { get; set; } + + [Parameter( + Position = 1, + Mandatory = true, + ParameterSetName = NewService.ByServiceTopologyObjectParameterSet, + HelpMessage = "The service topology object in which the service should be created.")] + [ValidateNotNullOrEmpty] + public PSServiceTopologyResource ServiceTopology { get; set; } + + [Parameter( + Position = 1, + Mandatory = true, + ParameterSetName = NewService.ByServiceTopologyResourceIdParamSet, + HelpMessage = "The service topology resource identifier in which the service should be created.")] + [ValidateNotNullOrEmpty] + public string ServiceTopologyId { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipelineByPropertyName = true, + HelpMessage = "A hash table which represents resource tags.")] + public Hashtable Tag { get; set; } + + public override void ExecuteCmdlet() + { + if (this.ShouldProcess(this.Name, Messages.CreateService)) + { + if (this.ServiceTopology != null) + { + this.ServiceTopologyName = this.ServiceTopology.Name; + } + else if (!string.IsNullOrWhiteSpace(this.ServiceTopologyId)) + { + var parsedResource = new ResourceIdentifier(this.ServiceTopologyId); + this.ServiceTopologyName = parsedResource.ResourceName; + } + + var serviceResource = new PSServiceResource() + { + ResourceGroupName = this.ResourceGroupName, + Name = this.Name, + Location = this.Location, + TargetSubscriptionId = this.TargetSubscriptionId, + TargetLocation = this.TargetLocation, + ServiceTopologyName = this.ServiceTopologyName, + Tags = this.Tag + }; + + if (this.DeploymentManagerClient.ServiceExists(serviceResource)) + { + throw new PSArgumentException(Messages.ServiceAlreadyExists); + } + + serviceResource = this.DeploymentManagerClient.PutService(serviceResource); + this.WriteObject(serviceResource); + } + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/NewServiceTopology.cs b/src/DeploymentManager/Commands.DeploymentManager/Commands/NewServiceTopology.cs new file mode 100644 index 000000000000..8cb242b0378c --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Commands/NewServiceTopology.cs @@ -0,0 +1,86 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Commands +{ + using System.Collections; + using System.Management.Automation; + + using Microsoft.Azure.Commands.DeploymentManager.Models; + using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; + using Microsoft.Azure.Management.DeploymentManager.Models; + + [Cmdlet( + VerbsCommon.New, + ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "DeploymentManagerServiceTopology", + SupportsShouldProcess = true), + OutputType(typeof(PSServiceTopologyResource))] + public class NewServiceTopology : DeploymentManagerBaseCmdlet + { + [Parameter( + Mandatory = true, + HelpMessage = "The resource group.")] + [ValidateNotNullOrEmpty] + [ResourceGroupCompleter] + public string ResourceGroupName { get; set; } + + [Parameter( + Mandatory = true, + HelpMessage = "The name of the topology.")] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter( + Mandatory = true, + HelpMessage = "The location of the topology.")] + [ValidateNotNullOrEmpty] + [LocationCompleter] + public string Location { get; set; } + + [Parameter( + Mandatory = false, + HelpMessage = "The identifier of the artifact source, where the artifacts that make up the topology are stored.")] + public string ArtifactSourceId { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipelineByPropertyName = true, + HelpMessage = "A hash table which represents resource tags.")] + public Hashtable Tag { get; set; } + + public override void ExecuteCmdlet() + { + if (this.ShouldProcess(this.Name, Messages.CreateServiceTopology)) + { + var topologyResource = new PSServiceTopologyResource() + { + ResourceGroupName = this.ResourceGroupName, + Name = this.Name, + Location = this.Location, + ArtifactSourceId = this.ArtifactSourceId, + Tags = this.Tag + }; + + if (this.DeploymentManagerClient.ServiceTopologyExists(topologyResource)) + { + throw new PSArgumentException(Messages.ServiceTopologyAlreadyExists); + } + + topologyResource = this.DeploymentManagerClient.PutServiceTopology(topologyResource); + + this.WriteObject(topologyResource); + } + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/NewServiceUnit.cs b/src/DeploymentManager/Commands.DeploymentManager/Commands/NewServiceUnit.cs new file mode 100644 index 000000000000..d08508f30f68 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Commands/NewServiceUnit.cs @@ -0,0 +1,227 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Commands +{ + using System; + using System.Collections; + using System.Management.Automation; + + using Microsoft.Azure.Commands.DeploymentManager.Models; + using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; + using Microsoft.Azure.Management.Internal.Resources.Utilities.Models; + + [Cmdlet( + VerbsCommon.New, + ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "DeploymentManagerServiceUnit", + DefaultParameterSetName = NewServiceUnit.ByTopologyAndServiceNamesParameterSet, + SupportsShouldProcess = true), + OutputType(typeof(PSServiceUnitResource))] + public class NewServiceUnit : DeploymentManagerBaseCmdlet + { + private const string IncrementalDeploymentMode = "Incremental"; + private const string CompleteDeploymentMode = "Complete"; + + private const string ByServiceObjectParameterSet = "ByServiceObject"; + private const string ByServiceResourceIdParamSet = "ByServiceResourceId"; + private const string ByTopologyAndServiceNamesParameterSet = "ByTopologyAndServiceNames"; + private const string ByTopologyObjectAndServiceNameParameterSet = "ByTopologyObjectAndServiceName"; + private const string ByTopologyResourceIdAndServiceNameParameterSet = "ByTopologyResourceAndServiceName"; + + [Parameter( + Position = 0, + Mandatory = true, + HelpMessage = "The resource group.")] + [ValidateNotNullOrEmpty] + [ResourceGroupCompleter] + public string ResourceGroupName { get; set; } + + [Parameter( + Position = 1, + Mandatory = true, + ParameterSetName = NewServiceUnit.ByTopologyAndServiceNamesParameterSet, + HelpMessage = "The name of the serivce topology this service unit is a part of.")] + [ValidateNotNullOrEmpty] + public string ServiceTopologyName { get; set; } + + [Parameter( + Position = 2, + Mandatory = true, + ParameterSetName = NewServiceUnit.ByTopologyAndServiceNamesParameterSet, + HelpMessage = "The name of the service this service unit is a part of.")] + [Parameter( + Position = 2, + Mandatory = true, + ParameterSetName = NewServiceUnit.ByTopologyObjectAndServiceNameParameterSet, + HelpMessage = "The name of the service this service unit is a part of.")] + [Parameter( + Position = 2, + Mandatory = true, + ParameterSetName = NewServiceUnit.ByTopologyResourceIdAndServiceNameParameterSet, + HelpMessage = "The name of the service this service unit is a part of.")] + [ValidateNotNullOrEmpty] + public string ServiceName { get; set; } + + [Parameter( + Position = 3, + Mandatory = true, + HelpMessage = "The name of the service unit.")] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter( + Mandatory = true, + HelpMessage = "The location of the service unit resource.")] + [ValidateNotNullOrEmpty] + [LocationCompleter] + public string Location { get; set; } + + [Parameter( + Mandatory = true, + HelpMessage = "Determines the location where resources under the service unit would be deployed to.")] + [ValidateNotNullOrEmpty] + public string TargetResourceGroup { get; set; } + + [Parameter( + Mandatory = true, + HelpMessage = "The deployment mode to use when deploying the resources in the service unit.")] + [ValidateSet(NewServiceUnit.IncrementalDeploymentMode, NewServiceUnit.CompleteDeploymentMode)] + [ValidateNotNullOrEmpty] + public string DeploymentMode { get; set; } + + [Parameter( + Mandatory = false, + HelpMessage = "The SAS Uri to the parameters file. If ArtifactSourceId was referenced in the ServiceTopology, specify relative path using ParametersArtifactSourceRelativePath.")] + public string ParametersUri { get; set; } + + [Parameter( + Mandatory = false, + HelpMessage = "The SAS Uri to the template file. If ArtifactSourceId was referenced in the ServiceTopology, specify relative path using TemplateArtifactSourceRelativePath.")] + public string TemplateUri { get; set; } + + [Parameter( + Mandatory = false, + HelpMessage = "The path to the template file relative to the artifact source. Requires ArtifactSource to be referenced in ServiceTopology.")] + public string TemplateArtifactSourceRelativePath { get; set; } + + [Parameter( + Mandatory = false, + HelpMessage = "The path to the parameters file relative to the artifact source. Requires ArtifactSource to be referenced in ServiceTopology.")] + public string ParametersArtifactSourceRelativePath { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipelineByPropertyName = true, + HelpMessage = "A hash table which represents resource tags.")] + public Hashtable Tag { get; set; } + + [Parameter( + Position = 1, + Mandatory = true, + ParameterSetName = NewServiceUnit.ByTopologyObjectAndServiceNameParameterSet, + HelpMessage = "The service topology object in which the service unit should be created.")] + [ValidateNotNullOrEmpty] + public PSServiceTopologyResource ServiceTopology { get; set; } + + [Parameter( + Position = 1, + Mandatory = true, + ParameterSetName = NewServiceUnit.ByTopologyResourceIdAndServiceNameParameterSet, + HelpMessage = "The service topology resource identifier in which the service unit should be created.")] + [ValidateNotNullOrEmpty] + public string ServiceTopologyResourceId { get; set; } + + [Parameter( + Position = 2, + Mandatory = true, + ParameterSetName = NewServiceUnit.ByServiceObjectParameterSet, + HelpMessage = "The service object in which the service unit should be created.")] + [ValidateNotNullOrEmpty] + public PSServiceResource Service { get; set; } + + [Parameter( + Position = 2, + Mandatory = true, + ParameterSetName = NewServiceUnit.ByServiceResourceIdParamSet, + HelpMessage = "The service resource identifier in which the service unit should be created.")] + [ValidateNotNullOrEmpty] + public string ServiceResourceId { get; set; } + + [Parameter( + Mandatory = false, + HelpMessage = "Run cmdlet in the background")] + public SwitchParameter AsJob { get; set; } + + public override void ExecuteCmdlet() + { + if (this.ShouldProcess(this.Name, Messages.CreateServiceUnit)) + { + this.ResolveParameters(); + var psServiceUnitResource = new PSServiceUnitResource() + { + ResourceGroupName = this.ResourceGroupName, + ServiceTopologyName = this.ServiceTopologyName, + ServiceName = this.ServiceName, + Name = this.Name, + Location = this.Location, + TargetResourceGroup = this.TargetResourceGroup, + DeploymentMode = this.DeploymentMode, + TemplateUri = this.TemplateUri, + ParametersUri = this.ParametersUri, + TemplateArtifactSourceRelativePath = this.TemplateArtifactSourceRelativePath, + ParametersArtifactSourceRelativePath = this.ParametersArtifactSourceRelativePath, + Tags = this.Tag + }; + + if (this.DeploymentManagerClient.ServiceUnitExists(psServiceUnitResource)) + { + throw new PSArgumentException(Messages.ServiceUnitAlreadyExists); + } + + psServiceUnitResource = this.DeploymentManagerClient.PutServiceUnit(psServiceUnitResource); + this.WriteObject(psServiceUnitResource); + } + } + + private void ResolveParameters() + { + if (this.Service != null) + { + this.ServiceTopologyName = this.Service.ServiceTopologyName; + this.ServiceName = this.Service.Name; + } + else if (!string.IsNullOrWhiteSpace(this.ServiceResourceId)) + { + var parsedResourceId = new ResourceIdentifier(this.ServiceResourceId); + this.ServiceName = parsedResourceId.ResourceName; + string[] tokens = parsedResourceId.ParentResource.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); + if (tokens.Length < 2) + { + throw new ArgumentException($"Invalid Service resource identifier: {this.ServiceResourceId}"); + } + + this.ServiceTopologyName = tokens[1]; + } + else if (this.ServiceTopology != null) + { + this.ServiceTopologyName = this.ServiceTopology.Name; + } + else if (!string.IsNullOrWhiteSpace(this.ServiceTopologyResourceId)) + { + var parsedResourceId = new ResourceIdentifier(this.ServiceTopologyResourceId); + this.ServiceTopologyName = parsedResourceId.ResourceName; + } + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/NewStep.cs b/src/DeploymentManager/Commands.DeploymentManager/Commands/NewStep.cs new file mode 100644 index 000000000000..7a3b58eaa749 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Commands/NewStep.cs @@ -0,0 +1,106 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Commands +{ + using System.Collections; + using System.Management.Automation; + + using Microsoft.Azure.Commands.DeploymentManager.Models; + using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; + + [Cmdlet( + VerbsCommon.New, + ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "DeploymentManagerStep", + DefaultParameterSetName = WaitParamSet, + SupportsShouldProcess = true), + OutputType(typeof(PSStepResource))] + public class NewStep : DeploymentManagerBaseCmdlet + { + /// + /// The parameter set for the wait step. + /// + private const string WaitParamSet = "Wait"; + + [Parameter( + Mandatory = true, + HelpMessage = "The resource group.")] + [ValidateNotNullOrEmpty] + [ResourceGroupCompleter] + public string ResourceGroupName { get; set; } + + [Parameter( + Mandatory = true, + HelpMessage = "The name of the step.")] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter( + Mandatory = true, + HelpMessage = "The location of the resource.")] + [ValidateNotNullOrEmpty] + [LocationCompleter] + public string Location { get; set; } + + [Parameter( + Mandatory = true, + HelpMessage = "The duration to wait in ISO 8601 format. E.g.: PT30M, PT1H", ParameterSetName = NewStep.WaitParamSet)] + [ValidateNotNullOrEmpty] + public string Duration { get; set; } + + [Parameter( + Mandatory = false, + ValueFromPipelineByPropertyName = true, + HelpMessage = "A hash table which represents resource tags.")] + public Hashtable Tag { get; set; } + + public override void ExecuteCmdlet() + { + if (this.ShouldProcess(this.Name, Messages.CreateStep)) + { + var psStepResource = new PSStepResource() + { + ResourceGroupName = this.ResourceGroupName, + Name = this.Name, + Location = this.Location, + Tags = this.Tag, + StepProperties = this.GetProperties() + }; + + if (this.DeploymentManagerClient.StepExists(psStepResource)) + { + throw new PSArgumentException(Messages.StepAlreadyExists); + } + + psStepResource = this.DeploymentManagerClient.PutStep(psStepResource); + this.WriteObject(psStepResource); + } + } + + private PSStepProperties GetProperties() + { + switch (this.ParameterSetName) + { + case WaitParamSet: + return new PSWaitStepProperties() + { + Duration = this.Duration + }; + + default: + return null; + } + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveArtifactSource.cs b/src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveArtifactSource.cs new file mode 100644 index 000000000000..ad6096e79651 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveArtifactSource.cs @@ -0,0 +1,120 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Commands +{ + using System.Management.Automation; + + using Microsoft.Azure.Commands.DeploymentManager.Models; + using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; + using Microsoft.Azure.Management.Internal.Resources.Utilities.Models; + + [Cmdlet( + VerbsCommon.Remove, + ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "DeploymentManagerArtifactSource", + SupportsShouldProcess = true, + DefaultParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName), + OutputType(typeof(bool))] + public class RemoveArtifactSource : DeploymentManagerBaseCmdlet + { + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The resource group.")] + [ValidateNotNullOrEmpty] + [ResourceGroupCompleter] + public string ResourceGroupName { get; set; } + + [Parameter( + Position = 1, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the artifact source.")] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.ResourceIdParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The resource identifier.")] + [ValidateNotNullOrEmpty] + public string ResourceId { get; set; } + + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InputObjectParamSetName, + ValueFromPipeline = true, + HelpMessage = "The artifact source to be removed.")] + [ValidateNotNullOrEmpty] + public PSArtifactSource ArtifactSource { get; set; } + + [Parameter( + Mandatory = false, + HelpMessage = "Do not ask for confirmation.")] + public SwitchParameter Force { get; set; } + + [Parameter(Mandatory = false)] + public SwitchParameter PassThru { get; set; } + + public override void ExecuteCmdlet() + { + this.ConfirmAction( + this.Force.IsPresent, + string.Format(Messages.ConfirmRemoveArtifactSource, this.Name), + string.Format(Messages.RemovingArtifactSource, this.Name), + this.Name, + () => + { + var result = this.Delete(); + if (result) + { + this.WriteVerbose(string.Format(Messages.RemovedArtifactSource, this.Name)); + } + + if (this.PassThru) + { + this.WriteObject(result); + } + }); + } + + private bool Delete() + { + if (this.ArtifactSource != null) + { + this.ResourceGroupName = this.ArtifactSource.ResourceGroupName; + this.Name = this.ArtifactSource.Name; + } + else if (!string.IsNullOrWhiteSpace(this.ResourceId)) + { + var parsedResourceId = new ResourceIdentifier(this.ResourceId); + this.ResourceGroupName = parsedResourceId.ResourceGroupName; + this.Name = parsedResourceId.ResourceName; + } + + var artifactSourceToDelete = new PSArtifactSource() + { + ResourceGroupName = this.ResourceGroupName, + Name = this.Name + }; + return this.DeploymentManagerClient.DeleteArtifactSource(artifactSourceToDelete); + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveRollout.cs b/src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveRollout.cs new file mode 100644 index 000000000000..32a859dbdf56 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveRollout.cs @@ -0,0 +1,118 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Commands +{ + using System.Management.Automation; + + using Microsoft.Azure.Commands.DeploymentManager.Models; + using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; + using Microsoft.Azure.Management.Internal.Resources.Utilities.Models; + + [Cmdlet( + VerbsCommon.Remove, + ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "DeploymentManagerRollout", + SupportsShouldProcess = true, + DefaultParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName), + OutputType(typeof(bool))] + public class RemoveRollout : DeploymentManagerBaseCmdlet + { + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The resource group.")] + [ValidateNotNullOrEmpty] + [ResourceGroupCompleter] + public string ResourceGroupName { get; set; } + + [Parameter( + Position = 1, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the rollout.")] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.ResourceIdParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The resource identifier.")] + [ValidateNotNullOrEmpty] + public string ResourceId { get; set; } + + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InputObjectParamSetName, + ValueFromPipeline = true, + HelpMessage = "The resource to be removed.")] + [ValidateNotNullOrEmpty] + public PSRollout Rollout { get; set; } + + [Parameter( + Mandatory = false, + HelpMessage = "Do not ask for confirmation.")] + public SwitchParameter Force { get; set; } + + [Parameter(Mandatory = false)] + public SwitchParameter PassThru { get; set; } + + public override void ExecuteCmdlet() + { + this.ConfirmAction( + this.Force.IsPresent, + string.Format(Messages.ConfirmRemoveRollout, this.Name), + string.Format(Messages.RemovingRollout, this.Name), + this.Name, + () => + { + var result = this.Delete(); + this.WriteVerbose(string.Format(Messages.RemovedRollout, this.Name)); + + if (this.PassThru) + { + this.WriteObject(result); + } + }); + } + + private bool Delete() + { + if (this.Rollout != null) + { + this.ResourceGroupName = this.Rollout.ResourceGroupName; + this.Name = this.Rollout.Name; + } + else if (!string.IsNullOrWhiteSpace(this.ResourceId)) + { + var parsedResourceId = new ResourceIdentifier(this.ResourceId); + this.ResourceGroupName = parsedResourceId.ResourceGroupName; + this.Name = parsedResourceId.ResourceName; + } + + var rolloutToDelete = new PSRollout() + { + ResourceGroupName = this.ResourceGroupName, + Name = this.Name + }; + + return this.DeploymentManagerClient.DeleteRollout(rolloutToDelete); + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveService.cs b/src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveService.cs new file mode 100644 index 000000000000..457be05ce2ee --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveService.cs @@ -0,0 +1,187 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Commands +{ + using System; + using System.Management.Automation; + + using Microsoft.Azure.Commands.DeploymentManager.Models; + using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; + using Microsoft.Azure.Management.Internal.Resources.Utilities.Models; + + [Cmdlet( + VerbsCommon.Remove, + ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "DeploymentManagerService", + SupportsShouldProcess = true, + DefaultParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName), + OutputType(typeof(bool))] + public class RemoveService : DeploymentManagerBaseCmdlet + { + private const string ByServiceTopologyObjectParameterSet = "ByServiceTopologyObject"; + private const string ByServiceTopologyResourceIdParamSet = "ByServiceTopologyResourceId"; + + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The resource group.")] + [ValidateNotNullOrEmpty] + [ResourceGroupCompleter] + public string ResourceGroupName { get; set; } + + [Parameter( + Position = 1, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the service topology.")] + [ValidateNotNullOrEmpty] + public string ServiceTopologyName { get; set; } + + [Parameter( + Position = 2, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the service.")] + [Parameter( + Position = 1, + Mandatory = true, + ParameterSetName = RemoveService.ByServiceTopologyObjectParameterSet, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the service.")] + [Parameter( + Position = 1, + Mandatory = true, + ParameterSetName = RemoveService.ByServiceTopologyResourceIdParamSet, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the service.")] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.ResourceIdParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The resource identifier.")] + [ValidateNotNullOrEmpty] + public string ResourceId { get; set; } + + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InputObjectParamSetName, + ValueFromPipeline = true, + HelpMessage = "Service object.")] + [ValidateNotNullOrEmpty] + public PSServiceResource Service { get; set; } + + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = RemoveService.ByServiceTopologyObjectParameterSet, + HelpMessage = "The service topology object in which the service should be created.")] + [ValidateNotNullOrEmpty] + public PSServiceTopologyResource ServiceTopology { get; set; } + + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = RemoveService.ByServiceTopologyResourceIdParamSet, + HelpMessage = "The service topology resource identifier in which the service should be created.")] + [ValidateNotNullOrEmpty] + public string ServiceTopologyResourceId { get; set; } + + [Parameter( + Mandatory = false, + HelpMessage = "Do not ask for confirmation.")] + public SwitchParameter Force { get; set; } + + [Parameter(Mandatory = false)] + public SwitchParameter PassThru { get; set; } + + public override void ExecuteCmdlet() + { + this.ResolveParams(); + this.ConfirmAction( + this.Force.IsPresent, + string.Format(Messages.ConfirmRemoveService, this.Name), + string.Format(Messages.ConfirmRemoveService, this.Name), + this.Name, + () => + { + var result = this.Delete(); + if (result) + { + this.WriteVerbose(string.Format(Messages.RemovedService, this.Name)); + } + + if (this.PassThru) + { + this.WriteObject(result); + } + }); + } + + private bool Delete() + { + var serviceToDelete = new PSServiceResource() + { + ResourceGroupName = this.ResourceGroupName, + ServiceTopologyName = this.ServiceTopologyName, + Name = this.Name + }; + + return this.DeploymentManagerClient.DeleteService(serviceToDelete); + } + + private void ResolveParams() + { + if (this.Service != null) + { + this.ResourceGroupName = this.Service.ResourceGroupName; + this.ServiceTopologyName = this.Service.ServiceTopologyName; + this.Name = this.Service.Name; + } + else if (!string.IsNullOrWhiteSpace(this.ResourceId)) + { + var parsedResourceId = new ResourceIdentifier(this.ResourceId); + this.ResourceGroupName = parsedResourceId.ResourceGroupName; + this.Name = parsedResourceId.ResourceName; + + string[] tokens = parsedResourceId.ParentResource.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); + if (tokens.Length < 2) + { + throw new ArgumentException($"Invalid Service resource identifier: {this.ResourceId}"); + } + + this.ServiceTopologyName = tokens[1]; + } + else if (this.ServiceTopology != null) + { + this.ResourceGroupName = this.ServiceTopology.ResourceGroupName; + this.ServiceTopologyName = this.ServiceTopology.Name; + } + else if (!string.IsNullOrWhiteSpace(this.ServiceTopologyResourceId)) + { + var parsedResourceId = new ResourceIdentifier(this.ServiceTopologyResourceId); + this.ResourceGroupName = parsedResourceId.ResourceGroupName; + this.ServiceTopologyName = parsedResourceId.ResourceName; + } + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveServiceTopology.cs b/src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveServiceTopology.cs new file mode 100644 index 000000000000..c3fd0a15ec0b --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveServiceTopology.cs @@ -0,0 +1,125 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Commands +{ + using System.Management.Automation; + + using Microsoft.Azure.Commands.DeploymentManager.Models; + using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; + using Microsoft.Azure.Management.Internal.Resources.Utilities.Models; + + [Cmdlet( + VerbsCommon.Remove, + ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "DeploymentManagerServiceTopology", + SupportsShouldProcess = true, + DefaultParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName), + OutputType(typeof(bool))] + public class RemoveServiceTopology : DeploymentManagerBaseCmdlet + { + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The resource group.")] + [ValidateNotNullOrEmpty] + [ResourceGroupCompleter] + public string ResourceGroupName { get; set; } + + [Parameter( + Position = 1, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the service topology.")] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.ResourceIdParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The resource identifier.")] + [ValidateNotNullOrEmpty] + public string ResourceId { get; set; } + + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InputObjectParamSetName, + ValueFromPipeline = true, + HelpMessage = "The resource to be removed.")] + [ValidateNotNullOrEmpty] + public PSServiceTopologyResource ServiceTopology { get; set; } + + [Parameter( + Mandatory = false, + HelpMessage = "Do not ask for confirmation.")] + public SwitchParameter Force { get; set; } + + [Parameter(Mandatory = false)] + public SwitchParameter PassThru { get; set; } + + public override void ExecuteCmdlet() + { + this.ResolveParams(); + this.ConfirmAction( + this.Force.IsPresent, + string.Format(Messages.ConfirmRemoveTopology, this.Name), + string.Format(Messages.RemovingTopology, this.Name), + this.Name, + () => + { + var result = this.Delete(); + if (result) + { + this.WriteVerbose(string.Format(Messages.RemovedTopology, this.Name)); + } + + if (this.PassThru) + { + this.WriteObject(result); + } + }); + } + + private bool Delete() + { + var topologyToDelete = new PSServiceTopologyResource() + { + ResourceGroupName = this.ResourceGroupName, + Name = this.Name + }; + + return this.DeploymentManagerClient.DeleteServiceTopology(topologyToDelete); + } + + private void ResolveParams() + { + if (this.ServiceTopology != null) + { + this.ResourceGroupName = this.ServiceTopology.ResourceGroupName; + this.Name = this.ServiceTopology.Name; + } + else if (!string.IsNullOrWhiteSpace(this.ResourceId)) + { + var parsedResourceId = new ResourceIdentifier(this.ResourceId); + this.ResourceGroupName = parsedResourceId.ResourceGroupName; + this.Name = parsedResourceId.ResourceName; + } + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveServiceUnit.cs b/src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveServiceUnit.cs new file mode 100644 index 000000000000..daf1e6ca2d3d --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveServiceUnit.cs @@ -0,0 +1,261 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Commands +{ + using System; + using System.Management.Automation; + + using Microsoft.Azure.Commands.DeploymentManager.Models; + using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; + using Microsoft.Azure.Management.Internal.Resources.Utilities.Models; + + [Cmdlet( + VerbsCommon.Remove, + ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "DeploymentManagerServiceUnit", + SupportsShouldProcess = true, + DefaultParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName), + OutputType(typeof(bool))] + public class RemoveServiceUnit : DeploymentManagerBaseCmdlet + { + private const string ByServiceObjectParameterSet = "ByServiceObject"; + private const string ByServiceResourceIdParamSet = "ByServiceResourceId"; + private const string ByTopologyObjectAndServiceNameParameterSet = "ByTopologyObjectAndServiceName"; + private const string ByTopologyResourceIdAndServiceNameParameterSet = "ByTopologyResourceAndServiceName"; + + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The resource group.")] + [ValidateNotNullOrEmpty] + [ResourceGroupCompleter] + public string ResourceGroupName { get; set; } + + [Parameter( + Position = 1, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the service topology the service unit is part of.")] + [ValidateNotNullOrEmpty] + public string ServiceTopologyName { get; set; } + + [Parameter( + Position = 2, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the service the service unit is part of.")] + [Parameter( + Position = 2, + Mandatory = true, + ParameterSetName = RemoveServiceUnit.ByTopologyObjectAndServiceNameParameterSet, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the service the service unit is part of.")] + [Parameter( + Position = 2, + Mandatory = true, + ParameterSetName = RemoveServiceUnit.ByTopologyResourceIdAndServiceNameParameterSet, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the service the service unit is part of.")] + [ValidateNotNullOrEmpty] + public string ServiceName { get; set; } + + [Parameter( + Position = 3, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the service unit.")] + [Parameter( + Position = 2, + Mandatory = true, + ParameterSetName = RemoveServiceUnit.ByServiceObjectParameterSet, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the service unit.")] + [Parameter( + Position = 2, + Mandatory = true, + ParameterSetName = RemoveServiceUnit.ByServiceResourceIdParamSet, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the service unit.")] + [Parameter( + Position = 3, + Mandatory = true, + ParameterSetName = RemoveServiceUnit.ByTopologyObjectAndServiceNameParameterSet, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the service unit.")] + [Parameter( + Position = 3, + Mandatory = true, + ParameterSetName = RemoveServiceUnit.ByTopologyResourceIdAndServiceNameParameterSet, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the service unit.")] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.ResourceIdParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The resource identifier.")] + [ValidateNotNullOrEmpty] + public string ResourceId { get; set; } + + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InputObjectParamSetName, + ValueFromPipeline = true, + HelpMessage = "Service unit resource object.")] + [ValidateNotNullOrEmpty] + public PSServiceUnitResource ServiceUnit { get; set; } + + [Parameter( + Position = 1, + Mandatory = true, + ParameterSetName = RemoveServiceUnit.ByTopologyObjectAndServiceNameParameterSet, + HelpMessage = "The service topology object in which the service unit should be created.")] + [ValidateNotNullOrEmpty] + public PSServiceTopologyResource ServiceTopology { get; set; } + + [Parameter( + Position = 1, + Mandatory = true, + ParameterSetName = RemoveServiceUnit.ByTopologyResourceIdAndServiceNameParameterSet, + HelpMessage = "The service topology resource identifier in which the service unit should be created.")] + [ValidateNotNullOrEmpty] + public string ServiceTopologyResourceId { get; set; } + + [Parameter( + Position = 1, + Mandatory = true, + ParameterSetName = RemoveServiceUnit.ByServiceObjectParameterSet, + HelpMessage = "The service object in which the service unit should be created.")] + [ValidateNotNullOrEmpty] + public PSServiceResource Service { get; set; } + + [Parameter( + Position = 1, + Mandatory = true, + ParameterSetName = RemoveServiceUnit.ByServiceResourceIdParamSet, + HelpMessage = "The service resource identifier in which the service unit should be created.")] + [ValidateNotNullOrEmpty] + public string ServiceResourceId { get; set; } + + + [Parameter( + Mandatory = false, + HelpMessage = "Do not ask for confirmation.")] + public SwitchParameter Force { get; set; } + + [Parameter(Mandatory = false)] + public SwitchParameter PassThru { get; set; } + + public override void ExecuteCmdlet() + { + this.ResolveParameters(); + this.ConfirmAction( + this.Force.IsPresent, + string.Format(Messages.ConfirmRemoveServiceUnit, this.Name), + string.Format(Messages.RemovingServiceUnit, this.Name), + this.Name, + () => + { + var result = this.Delete(); + if (result) + { + this.WriteVerbose(string.Format(Messages.RemovedServiceUnit, this.Name)); + } + + if (this.PassThru) + { + this.WriteObject(result); + } + }); + } + + private bool Delete() + { + var serviceUnitToDelete = new PSServiceUnitResource() + { + ResourceGroupName = this.ResourceGroupName, + ServiceTopologyName = this.ServiceTopologyName, + ServiceName = this.ServiceName, + Name = this.Name + }; + + return this.DeploymentManagerClient.DeleteServiceUnit(serviceUnitToDelete); + } + + private void ResolveParameters() + { + if (this.ServiceUnit != null) + { + this.ResourceGroupName = this.ServiceUnit.ResourceGroupName; + this.ServiceTopologyName = this.ServiceUnit.ServiceTopologyName; + this.ServiceName = this.ServiceUnit.ServiceName; + this.Name = this.ServiceUnit.Name; + } + else if (!string.IsNullOrWhiteSpace(this.ResourceId)) + { + var parsedResourceId = new ResourceIdentifier(this.ResourceId); + this.ResourceGroupName = parsedResourceId.ResourceGroupName; + this.Name = parsedResourceId.ResourceName; + + string[] tokens = parsedResourceId.ParentResource.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); + if (tokens.Length < 4) + { + throw new ArgumentException($"Invalid Service Unit resource identifier: {this.ResourceId}"); + } + + this.ServiceTopologyName = tokens[1]; + this.ServiceName = tokens[3]; + } + else if (this.Service != null) + { + this.ResourceGroupName = this.Service.ResourceGroupName; + this.ServiceTopologyName = this.Service.ServiceTopologyName; + this.ServiceName = this.Service.Name; + } + else if (!string.IsNullOrWhiteSpace(this.ServiceResourceId)) + { + var parsedResourceId = new ResourceIdentifier(this.ServiceResourceId); + this.ResourceGroupName = parsedResourceId.ResourceGroupName; + this.ServiceName = parsedResourceId.ResourceName; + string[] tokens = parsedResourceId.ParentResource.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); + if (tokens.Length < 2) + { + throw new ArgumentException($"Invalid Service resource identifier: {this.ResourceId}"); + } + + this.ServiceTopologyName = tokens[1]; + } + else if (this.ServiceTopology != null) + { + this.ResourceGroupName = this.ServiceTopology.ResourceGroupName; + this.ServiceTopologyName = this.ServiceTopology.Name; + } + else if (!string.IsNullOrWhiteSpace(this.ServiceTopologyResourceId)) + { + var parsedResourceId = new ResourceIdentifier(this.ServiceTopologyResourceId); + this.ResourceGroupName = parsedResourceId.ResourceGroupName; + this.ServiceTopologyName = parsedResourceId.ResourceName; + } + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveStep.cs b/src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveStep.cs new file mode 100644 index 000000000000..4bc479461ec7 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveStep.cs @@ -0,0 +1,120 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Commands +{ + using System.Management.Automation; + + using Microsoft.Azure.Commands.DeploymentManager.Models; + using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; + using Microsoft.Azure.Management.Internal.Resources.Utilities.Models; + + [Cmdlet( + VerbsCommon.Remove, + ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "DeploymentManagerStep", + SupportsShouldProcess = true, + DefaultParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName), + OutputType(typeof(bool))] + public class RemoveStep : DeploymentManagerBaseCmdlet + { + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The resource group.")] + [ValidateNotNullOrEmpty] + [ResourceGroupCompleter] + public string ResourceGroupName { get; set; } + + [Parameter( + Position = 1, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the step.")] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.ResourceIdParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The resource identifier.")] + [ValidateNotNullOrEmpty] + public string ResourceId { get; set; } + + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InputObjectParamSetName, + ValueFromPipeline = true, + HelpMessage = "The step to be removed.")] + [ValidateNotNullOrEmpty] + public PSStepResource Step { get; set; } + + [Parameter( + Mandatory = false, + HelpMessage = "Do not ask for confirmation.")] + public SwitchParameter Force { get; set; } + + [Parameter(Mandatory = false)] + public SwitchParameter PassThru { get; set; } + + public override void ExecuteCmdlet() + { + this.ConfirmAction( + this.Force.IsPresent, + string.Format(Messages.ConfirmRemoveStep, this.Name), + string.Format(Messages.RemovingStep, this.Name), + this.Name, + () => + { + var result = this.Delete(); + if (result) + { + this.WriteVerbose(string.Format(Messages.RemovedStep, this.Name)); + } + + if (this.PassThru) + { + this.WriteObject(result); + } + }); + } + + private bool Delete() + { + if (this.Step != null) + { + this.ResourceGroupName = this.Step.ResourceGroupName; + this.Name = this.Step.Name; + } + else if (!string.IsNullOrWhiteSpace(this.ResourceId)) + { + var parsedResourceId = new ResourceIdentifier(this.ResourceId); + this.ResourceGroupName = parsedResourceId.ResourceGroupName; + this.Name = parsedResourceId.ResourceName; + } + + var stepToDelete = new PSStepResource() + { + ResourceGroupName = this.ResourceGroupName, + Name = this.Name + }; + return this.DeploymentManagerClient.DeleteStep(stepToDelete); + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/RestartRollout.cs b/src/DeploymentManager/Commands.DeploymentManager/Commands/RestartRollout.cs new file mode 100644 index 000000000000..a5660709d872 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Commands/RestartRollout.cs @@ -0,0 +1,113 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Commands +{ + using System.Management.Automation; + + using Microsoft.Azure.Commands.DeploymentManager.Models; + using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; + using Microsoft.Azure.Management.Internal.Resources.Utilities.Models; + + [Cmdlet( + VerbsLifecycle.Restart, + ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "DeploymentManagerRollout", + SupportsShouldProcess = true, + DefaultParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName), + OutputType(typeof(PSRollout))] + public class RestartpRollout : DeploymentManagerBaseCmdlet + { + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The resource group.")] + [ValidateNotNullOrEmpty] + [ResourceGroupCompleter] + public string ResourceGroupName { get; set; } + + [Parameter( + Position = 1, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the rollout.")] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.ResourceIdParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The resource identifier.")] + [ValidateNotNullOrEmpty] + public string ResourceId { get; set; } + + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InputObjectParamSetName, + ValueFromPipeline = true, + HelpMessage = "The resource to be removed.")] + [ValidateNotNullOrEmpty] + public PSRollout Rollout { get; set; } + + [Parameter( + Mandatory = false, + HelpMessage = "Skip steps that succeeded in the previous run of the rollout.")] + [ValidateNotNullOrEmpty] + public SwitchParameter SkipSucceeded { get; set; } + + public override void ExecuteCmdlet() + { + this.ConfirmAction( + this.SkipSucceeded.IsPresent, + string.Format(Messages.ConfirmRestartRollout, this.Name), + string.Format(Messages.RestartingRollout, this.Name), + this.Name, + () => + { + var restartedRollout = this.Restart(); + this.WriteVerbose(string.Format(Messages.RestartedRollout, this.Name)); + this.WriteObject(restartedRollout); + }); + } + + private PSRollout Restart() + { + if (this.Rollout != null) + { + this.ResourceGroupName = this.Rollout.ResourceGroupName; + this.Name = this.Rollout.Name; + } + else if (!string.IsNullOrWhiteSpace(this.ResourceId)) + { + var parsedResourceId = new ResourceIdentifier(this.ResourceId); + this.ResourceGroupName = parsedResourceId.ResourceGroupName; + this.Name = parsedResourceId.ResourceName; + } + + var rolloutToRestart = new PSRollout() + { + ResourceGroupName = this.ResourceGroupName, + Name = this.Name + }; + + var restartedRollout = this.DeploymentManagerClient.RestartRollout(rolloutToRestart, this.SkipSucceeded); + return restartedRollout; + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/RolloutCmdletBase.cs b/src/DeploymentManager/Commands.DeploymentManager/Commands/RolloutCmdletBase.cs new file mode 100644 index 000000000000..81efd7580b59 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Commands/RolloutCmdletBase.cs @@ -0,0 +1,352 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Commands +{ + using System; + using System.Collections.Generic; + using System.Globalization; + using System.Linq; + using System.Management.Automation; + using System.Text; + + using Microsoft.Azure.Commands.DeploymentManager.Models; + using Microsoft.Azure.Commands.DeploymentManager.Utilities; + using Microsoft.Azure.Management.DeploymentManager.Models; + + public abstract class RolloutCmdletBase : DeploymentManagerBaseCmdlet + { + private const string FailedStatus = "Failed"; + + private const int NoIndent = 0; + + private const int ServiceUnitIndentFactor = 1; + + private const int StepIndentFactor = 2; + + private const int StepPropertiesIndentFactor = 3; + + private const int ResourceOperationsIndentFactor = 4; + + StringBuilder verboseBuilder = new StringBuilder(); + + StringBuilder errorBuilder = new StringBuilder(); + + protected void PrintError() + { + if (this.errorBuilder.Length > 0) + { + var exception = new Exception(this.errorBuilder.ToString()); + var errorRecord = new ErrorRecord(exception, "RolloutFailed", ErrorCategory.NotSpecified, null); + this.WriteError(errorRecord); + } + } + + protected void PrintRollout(PSRollout rollout) + { + if (rollout != null) + { + verboseBuilder.InvariantAppend(this.FormatRolloutInfoHeader(rollout)); + this.PrintDetails(rollout); + + this.WriteVerbose(verboseBuilder.ToString()); + this.PrintError(); + } + } + + protected static string FormatOperationInfo(PSBaseOperationInfo operationInfo, int indentFactor) + { + string formattedString = string.Empty; + int indentFactorForDetails = indentFactor < int.MaxValue ? indentFactor + 1 : indentFactor; + if (operationInfo != null) + { + StringBuilder sb = new StringBuilder(); + + var rolloutOperationInfo = operationInfo as PSRolloutOperationInfo; + if (rolloutOperationInfo != null) + { + sb.AppendFormatWithLeftIndentAndNewLine(indentFactorForDetails, $"Retry Attempt: {rolloutOperationInfo.RetryAttempt}"); + sb.AppendFormatWithLeftIndentAndNewLine(indentFactorForDetails, $"Skip Succeeded: {rolloutOperationInfo.SkipSucceededOnRetry}"); + } + + var stepOperationInfo = operationInfo as PSStepOperationInfo; + if (stepOperationInfo != null) + { + sb.AppendFormatWithLeftIndentAndNewLineIfNotNull(indentFactorForDetails, "DeploymentName", stepOperationInfo.DeploymentName); + sb.AppendFormatWithLeftIndentAndNewLineIfNotNull(indentFactorForDetails, "CorrelationId", stepOperationInfo.CorrelationId); + } + + if (operationInfo?.StartTime != null && operationInfo.StartTime.HasValue) + { + sb.AppendFormatWithLeftIndentAndNewLine(indentFactorForDetails, $"Start Time: {operationInfo.StartTime.Value.ToLocalTimeForUserDisplay()}"); + } + + if (operationInfo?.EndTime != null && operationInfo.EndTime.HasValue) + { + sb.AppendFormatWithLeftIndentAndNewLine(indentFactorForDetails, $"End Time: {operationInfo.EndTime.Value.ToLocalTimeForUserDisplay()}"); + + if (operationInfo?.StartTime != null && operationInfo.StartTime.HasValue) + { + sb.AppendFormatWithLeftIndentAndNewLine( + indentFactorForDetails, + "Total Duration: {0}", + (operationInfo.EndTime.Value - operationInfo.StartTime.Value).ToDisplayFormat()); + } + } + + sb.InvariantAppend(RolloutCmdletBase.FormatErrorInfo(operationInfo, indentFactorForDetails)); + + formattedString = sb.ToString(); + if (!StringUtilities.IsNullOrWhiteSpace(formattedString)) + { + sb.Clear(); + sb.AppendFormatWithLeftIndentAndNewLine(indentFactor, "Operation Info:"); + formattedString = string.Concat(sb.ToString(), formattedString); + } + } + + return formattedString; + } + + protected void PrintResourceOperations(IList resourceOperations, StringBuilder eb) + { + StringBuilder sb = new StringBuilder(); + + if (resourceOperations != null && resourceOperations.Any()) + { + sb.AppendFormatWithLeftIndentAndNewLine(RolloutCmdletBase.StepPropertiesIndentFactor, "Resource Operations:"); + int i = 0; + foreach (var resourceOperation in resourceOperations) + { + if (resourceOperation.ProvisioningState != null && + resourceOperation.ProvisioningState.Equals(RolloutCmdletBase.FailedStatus, StringComparison.OrdinalIgnoreCase)) + { + verboseBuilder.InvariantAppend(sb.ToString()); + sb.Clear(); + } + + sb.AppendLine(); + sb.AppendFormatWithLeftIndentAndNewLine(RolloutCmdletBase.ResourceOperationsIndentFactor, "Resource Operation {0}:", ++i); + sb.AppendFormatWithLeftIndentAndNewLineIfNotNull(RolloutCmdletBase.ResourceOperationsIndentFactor, "Name", resourceOperation.ResourceName); + sb.AppendFormatWithLeftIndentAndNewLineIfNotNull(RolloutCmdletBase.ResourceOperationsIndentFactor, "Type", resourceOperation.ResourceType); + sb.AppendFormatWithLeftIndentAndNewLineIfNotNull(RolloutCmdletBase.ResourceOperationsIndentFactor, "ProvisioningState", resourceOperation.ProvisioningState); + sb.AppendFormatWithLeftIndentAndNewLineIfNotNull(RolloutCmdletBase.ResourceOperationsIndentFactor, "StatusMessage", resourceOperation.StatusMessage); + sb.AppendFormatWithLeftIndentAndNewLineIfNotNull(RolloutCmdletBase.ResourceOperationsIndentFactor, "StatusCode", resourceOperation.StatusCode); + sb.AppendFormatWithLeftIndentAndNewLineIfNotNull(RolloutCmdletBase.ResourceOperationsIndentFactor, "OperationId", resourceOperation.OperationId); + + if (resourceOperation.ProvisioningState != null && + resourceOperation.ProvisioningState.Equals(RolloutCmdletBase.FailedStatus, StringComparison.OrdinalIgnoreCase)) + { + eb.InvariantAppend(sb.ToString()); + verboseBuilder.InvariantAppend(sb.ToString()); + sb.Clear(); + } + } + } + + verboseBuilder.InvariantAppend(sb.ToString()); + } + + private void PrintDetails(PSRollout rollout) + { + var sb = new StringBuilder(); + if (rollout != null && rollout.Services != null) + { + this.PrintServices(rollout.Services); + } + } + + private void PrintServices(IList services) + { + var sb = new StringBuilder(); + var serviceErrors = new StringBuilder(); + + foreach (var service in services) + { + sb.AppendLine(); + sb.AppendLine(); + sb.InvariantAppend($"Service: {service.Name}"); + sb.AppendFormatWithLeftIndentAndNewLineIfNotNull(RolloutCmdletBase.ServiceUnitIndentFactor, "TargetLocation", service.TargetLocation); + sb.AppendFormatWithLeftIndentAndNewLineIfNotNull(RolloutCmdletBase.ServiceUnitIndentFactor, "TargetSubscriptionId", service.TargetSubscriptionId); + + verboseBuilder.InvariantAppend(sb.ToString()); + sb.Clear(); + + serviceErrors.Clear(); + if (service.ServiceUnits != null) + { + var suErrors = new StringBuilder(); + foreach (var serviceUnit in service.ServiceUnits) + { + suErrors.Clear(); + this.PrintServiceUnits(serviceUnit, suErrors); + + if (suErrors.Length > 0) + { + serviceErrors.AppendLine(); + serviceErrors.AppendFormatWithLeftIndentAndNewLine( + RolloutCmdletBase.ServiceUnitIndentFactor, + $"ServiceUnit: {serviceUnit.Name}"); + serviceErrors.InvariantAppend(suErrors.ToString()); + } + } + } + + if (serviceErrors.Length > 0) + { + this.errorBuilder.AppendLine(); + this.errorBuilder.InvariantAppend($"Service: {service.Name}"); + this.errorBuilder.InvariantAppend(serviceErrors.ToString()); + } + } + } + + private void PrintServiceUnits(PSServiceUnit serviceUnit, StringBuilder eb) + { + StringBuilder sb = new StringBuilder(); + if (serviceUnit != null) + { + sb.AppendLine(); + sb.AppendFormatWithLeftIndentAndNewLine( + RolloutCmdletBase.ServiceUnitIndentFactor, + $"ServiceUnit: {serviceUnit.Name}"); + + sb.AppendFormatWithLeftIndentAndNewLineIfNotNull( + RolloutCmdletBase.StepIndentFactor, + "TargetResourceGroup", + serviceUnit.TargetResourceGroup); + + foreach (var step in serviceUnit.Steps) + { + if (step.Status != null && step.Status.Equals("Failed", StringComparison.OrdinalIgnoreCase)) + { + verboseBuilder.InvariantAppend(sb.ToString()); + sb.Clear(); + } + + sb.AppendLine(); + sb.AppendFormatWithLeftIndentAndNewLine(RolloutCmdletBase.StepIndentFactor, $"Step: {step.Name}"); + sb.AppendFormatWithLeftIndentAndNewLine(RolloutCmdletBase.StepPropertiesIndentFactor, $"Status: {step.Status}"); + sb.AppendFormatWithLeftIndentAndNewLine(RolloutCmdletBase.StepPropertiesIndentFactor, $"StepGroup: {step.StepGroup}"); + + sb.AppendFormatWithLeftIndentAndNewLineIfNotNull( + RolloutCmdletBase.StepPropertiesIndentFactor, + "Message", + RolloutCmdletBase.ActionMessagesToDisplayString(step.Messages)); + + if (step.OperationInfo != null) + { + string formatOperationInfo = RolloutCmdletBase.FormatOperationInfo(step.OperationInfo, RolloutCmdletBase.StepPropertiesIndentFactor); + sb.Append(formatOperationInfo); + } + + if (step.Status != null && step.Status.Equals("Failed", StringComparison.OrdinalIgnoreCase)) + { + verboseBuilder.InvariantAppend(sb.ToString()); + eb.InvariantAppend(sb.ToString()); + } + else + { + verboseBuilder.InvariantAppend(sb.ToString()); + } + + sb.Clear(); + + this.PrintResourceOperations(step.ResourceOperations, eb); + } + } + } + + private string FormatRolloutInfoHeader(PSRollout rollout) + { + StringBuilder sb = new StringBuilder(); + sb.InvariantAppend($"\n\nStatus: {rollout.Status}"); + + if (rollout.Status == RolloutCmdletBase.FailedStatus) + { + verboseBuilder.InvariantAppend(sb.ToString()); + sb.Clear(); + } + + sb.Append(RolloutCmdletBase.FormatRolloutDetails(rollout)); + sb.AppendFormatWithLeftIndentAndNewLineIfNotNull( + RolloutCmdletBase.NoIndent, + "Total Retry Attempts", + rollout.TotalRetryAttempts.HasValue && rollout.TotalRetryAttempts > 0 ? rollout.TotalRetryAttempts.Value.ToString(CultureInfo.InvariantCulture) : null); + + if (rollout.OperationInfo != null) + { + sb.AppendFormatWithLeftIndentAndNewLine(NoIndent, RolloutCmdletBase.FormatOperationInfo(rollout.OperationInfo, RolloutCmdletBase.NoIndent)); + } + + return sb.ToString(); + } + + private static string FormatRolloutDetails(PSRollout rollout) + { + StringBuilder sb = new StringBuilder(); + sb.AppendFormatWithLeftIndentAndNewLineIfNotNull(RolloutCmdletBase.NoIndent, "ArtifactSourceId", rollout.ArtifactSourceId); + sb.AppendFormatWithLeftIndentAndNewLineIfNotNull(RolloutCmdletBase.NoIndent, "BuildVersion", rollout.BuildVersion); + return sb.ToString(); + } + + private static string ActionMessagesToDisplayString(IList messages) + { + if (messages == null || messages.Count == 0) + { + return null; + } + + return string.Join( + Environment.NewLine, + messages.Select( + m => StringUtilities.SafeInvariantFormat( + "{0}{1}", + m.TimeStamp.HasValue ? $"{m.TimeStamp.Value.ToLocalTimeForUserDisplay()}: " : string.Empty, + m.MessageProperty))); + } + + private static string FormatErrorInfo(PSBaseOperationInfo operationInfo, int indentFactor) + { + StringBuilder sb = new StringBuilder(); + if (operationInfo != null && operationInfo.Error != null) + { + sb.AppendFormatWithLeftIndentAndNewLineIfNotNull( + indentFactor, + "Error", + RolloutCmdletBase.AppendError(operationInfo.Error, indentFactor + 1)); + sb.AppendFormatWithLeftIndentAndNewLineIfNotNull( + indentFactor + 1, + "Details", + operationInfo.Error?.Details?.ToList().Select(e => + RolloutCmdletBase.AppendError(e, indentFactor + 2)).ToCommaDelimitedString()); + } + + return sb.ToString(); + } + + private static string AppendError(CloudErrorBody error, int indentFactor) + { + StringBuilder sb = new StringBuilder(); + if (error != null) + { + sb.AppendFormatWithLeftIndentAndNewLineIfNotNull(indentFactor, "Code", error.Code); + sb.AppendFormatWithLeftIndentAndNewLineIfNotNull(indentFactor, "Message", error.Message); + sb.AppendFormatWithLeftIndentAndNewLineIfNotNull(indentFactor, "Target", error.Target); + } + + return sb.ToString(); + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/SetArtifactSource.cs b/src/DeploymentManager/Commands.DeploymentManager/Commands/SetArtifactSource.cs new file mode 100644 index 000000000000..965b6bb3ffb1 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Commands/SetArtifactSource.cs @@ -0,0 +1,47 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Commands +{ + using System.Management.Automation; + + using Microsoft.Azure.Commands.DeploymentManager.Models; + + [Cmdlet( + VerbsCommon.Set, + ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "DeploymentManagerArtifactSource", + SupportsShouldProcess = true, + DefaultParameterSetName = DeploymentManagerBaseCmdlet.InputObjectParamSetName), + OutputType(typeof(PSArtifactSource))] + public class SetArtifactSource : DeploymentManagerBaseCmdlet + { + [Parameter( + Position = 0, + Mandatory = true, + HelpMessage = "The artifact source object.", + ValueFromPipeline = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InputObjectParamSetName)] + [ValidateNotNullOrEmpty] + public PSArtifactSource ArtifactSource { get; set; } + + public override void ExecuteCmdlet() + { + if (this.ShouldProcess(this.ArtifactSource.Name, Messages.UpdateArtifactSource)) + { + var artifactSource = this.DeploymentManagerClient.PutArtifactSource(this.ArtifactSource); + this.WriteObject(artifactSource); + } + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/SetService.cs b/src/DeploymentManager/Commands.DeploymentManager/Commands/SetService.cs new file mode 100644 index 000000000000..1d70c0b88e87 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Commands/SetService.cs @@ -0,0 +1,47 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Commands +{ + using System.Management.Automation; + + using Microsoft.Azure.Commands.DeploymentManager.Models; + + [Cmdlet( + VerbsCommon.Set, + ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "DeploymentManagerService", + SupportsShouldProcess = true, + DefaultParameterSetName = DeploymentManagerBaseCmdlet.InputObjectParamSetName), + OutputType(typeof(PSServiceResource))] + public class SetService : DeploymentManagerBaseCmdlet + { + [Parameter( + Position = 0, + Mandatory = true, + HelpMessage = "The service object.", + ValueFromPipeline = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InputObjectParamSetName)] + [ValidateNotNullOrEmpty] + public PSServiceResource Service { get; set; } + + public override void ExecuteCmdlet() + { + if (this.ShouldProcess(this.Service.Name, Messages.UpdateService)) + { + var serviceResource = this.DeploymentManagerClient.PutService(this.Service); + this.WriteObject(serviceResource); + } + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/SetServiceTopology.cs b/src/DeploymentManager/Commands.DeploymentManager/Commands/SetServiceTopology.cs new file mode 100644 index 000000000000..e40aa08cebef --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Commands/SetServiceTopology.cs @@ -0,0 +1,46 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Commands +{ + using System.Management.Automation; + + using Microsoft.Azure.Commands.DeploymentManager.Models; + + [Cmdlet( + VerbsCommon.Set, + ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "DeploymentManagerServiceTopology", + SupportsShouldProcess = true, + DefaultParameterSetName = DeploymentManagerBaseCmdlet.InputObjectParamSetName), + OutputType(typeof(PSServiceTopologyResource))] + public class SetServiceTopology : DeploymentManagerBaseCmdlet + { + [Parameter( + Position = 0, + Mandatory = true, + ValueFromPipeline = true, + HelpMessage = "The service topology object.")] + [ValidateNotNullOrEmpty] + public PSServiceTopologyResource ServiceTopology { get; set; } + + public override void ExecuteCmdlet() + { + if (this.ShouldProcess(this.ServiceTopology.Name, Messages.UpdateServiceTopology)) + { + var topologyResource = this.DeploymentManagerClient.PutServiceTopology(this.ServiceTopology); + this.WriteObject(topologyResource); + } + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/SetServiceUnit.cs b/src/DeploymentManager/Commands.DeploymentManager/Commands/SetServiceUnit.cs new file mode 100644 index 000000000000..df11c4852876 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Commands/SetServiceUnit.cs @@ -0,0 +1,46 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Commands +{ + using System.Management.Automation; + + using Microsoft.Azure.Commands.DeploymentManager.Models; + + [Cmdlet( + VerbsCommon.Set, + ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "DeploymentManagerServiceUnit", + SupportsShouldProcess = true, + DefaultParameterSetName = DeploymentManagerBaseCmdlet.InputObjectParamSetName), + OutputType(typeof(PSServiceUnitResource))] + public class SetServiceUnit : DeploymentManagerBaseCmdlet + { + [Parameter( + Position = 0, + Mandatory = true, + ValueFromPipeline = true, + HelpMessage = "The service unit object.")] + [ValidateNotNullOrEmpty] + public PSServiceUnitResource ServiceUnit { get; set; } + + public override void ExecuteCmdlet() + { + if (this.ShouldProcess(this.ServiceUnit.Name, Messages.UpdateServiceUnit)) + { + var topologyResource = this.DeploymentManagerClient.PutServiceUnit(this.ServiceUnit); + this.WriteObject(topologyResource); + } + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/SetStep.cs b/src/DeploymentManager/Commands.DeploymentManager/Commands/SetStep.cs new file mode 100644 index 000000000000..bdad4f7a0823 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Commands/SetStep.cs @@ -0,0 +1,47 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Commands +{ + using System.Management.Automation; + + using Microsoft.Azure.Commands.DeploymentManager.Models; + + [Cmdlet( + VerbsCommon.Set, + ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "DeploymentManagerStep", + SupportsShouldProcess = true, + DefaultParameterSetName = DeploymentManagerBaseCmdlet.InputObjectParamSetName), + OutputType(typeof(PSStepResource))] + public class SetStep : DeploymentManagerBaseCmdlet + { + [Parameter( + Position = 0, + Mandatory = true, + HelpMessage = "The step object.", + ValueFromPipeline = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InputObjectParamSetName)] + [ValidateNotNullOrEmpty] + public PSStepResource Step { get; set; } + + public override void ExecuteCmdlet() + { + if (this.ShouldProcess(this.Step.Name, Messages.UpdateStep)) + { + var psStepResource = this.DeploymentManagerClient.PutStep(this.Step); + this.WriteObject(psStepResource); + } + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/StopRollout.cs b/src/DeploymentManager/Commands.DeploymentManager/Commands/StopRollout.cs new file mode 100644 index 000000000000..40c0438425d3 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Commands/StopRollout.cs @@ -0,0 +1,112 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Commands +{ + using System.Management.Automation; + + using Microsoft.Azure.Commands.DeploymentManager.Models; + using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; + using Microsoft.Azure.Management.Internal.Resources.Utilities.Models; + + [Cmdlet( + VerbsLifecycle.Stop, + ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "DeploymentManagerRollout", + SupportsShouldProcess = true, + DefaultParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName), + OutputType(typeof(PSRollout))] + public class StopRollout : DeploymentManagerBaseCmdlet + { + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The resource group.")] + [ValidateNotNullOrEmpty] + [ResourceGroupCompleter] + public string ResourceGroupName { get; set; } + + [Parameter( + Position = 1, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InteractiveParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The name of the rollout.")] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.ResourceIdParamSetName, + ValueFromPipelineByPropertyName = true, + HelpMessage = "The resource identifier.")] + [ValidateNotNullOrEmpty] + public string ResourceId { get; set; } + + [Parameter( + Position = 0, + Mandatory = true, + ParameterSetName = DeploymentManagerBaseCmdlet.InputObjectParamSetName, + ValueFromPipeline = true, + HelpMessage = "The rollout to be removed.")] + [ValidateNotNullOrEmpty] + public PSRollout Rollout { get; set; } + + [Parameter( + Mandatory = false, + HelpMessage = "Do not ask for confirmation.")] + public SwitchParameter Force { get; set; } + + public override void ExecuteCmdlet() + { + this.ConfirmAction( + this.Force.IsPresent, + string.Format(Messages.ConfirmStopRollout, this.Name), + string.Format(Messages.StoppingRollout, this.Name), + this.Name, + () => + { + var canceledRollout = this.Cancel(); + this.WriteVerbose(string.Format(Messages.StoppedRollout, this.Name)); + this.WriteObject(canceledRollout); + }); + } + + private PSRollout Cancel() + { + if (this.Rollout != null) + { + this.ResourceGroupName = this.Rollout.ResourceGroupName; + this.Name = this.Rollout.Name; + } + else if (!string.IsNullOrWhiteSpace(this.ResourceId)) + { + var parsedResourceId = new ResourceIdentifier(this.ResourceId); + this.ResourceGroupName = parsedResourceId.ResourceGroupName; + this.Name = parsedResourceId.ResourceName; + } + + var rolloutToCancel = new PSRollout() + { + ResourceGroupName = this.ResourceGroupName, + Name = this.Name + }; + + var canceledRollout = this.DeploymentManagerClient.CancelRollout(rolloutToCancel); + return canceledRollout; + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/MSSharedLibKey.snk b/src/DeploymentManager/Commands.DeploymentManager/MSSharedLibKey.snk new file mode 100644 index 0000000000000000000000000000000000000000..695f1b38774e839e5b90059bfb7f32df1dff4223 GIT binary patch literal 160 zcmV;R0AK$ABme*efB*oL000060ssI2Bme+XQ$aBR1ONa50098C{E+7Ye`kjtcRG*W zi8#m|)B?I?xgZ^2Sw5D;l4TxtPwG;3)3^j?qDHjEteSTF{rM+4WI`v zCD?tsZ^;k+S&r1&HRMb=j738S=;J$tCKNrc$@P|lZ +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Microsoft.Azure.Commands.DeploymentManager { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Messages { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Messages() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Azure.Commands.DeploymentManager.Messages", typeof(Messages).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to The specified artifact source already exists.. + /// + internal static string ArtifactSourceAlreadyExists { + get { + return ResourceManager.GetString("ArtifactSourceAlreadyExists", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There might be rollouts or topologies referencing the artifact source {0}. Are you sure you want to remove the artifact source?. + /// + internal static string ConfirmRemoveArtifactSource { + get { + return ResourceManager.GetString("ConfirmRemoveArtifactSource", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Are you sure you want to remove the rollout {0}?. + /// + internal static string ConfirmRemoveRollout { + get { + return ResourceManager.GetString("ConfirmRemoveRollout", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Are you sure you want to remove the service {0}?. + /// + internal static string ConfirmRemoveService { + get { + return ResourceManager.GetString("ConfirmRemoveService", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Are you sure you want to remove the service unit {0}?. + /// + internal static string ConfirmRemoveServiceUnit { + get { + return ResourceManager.GetString("ConfirmRemoveServiceUnit", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Are you sure you want to remove the step {0}?. + /// + internal static string ConfirmRemoveStep { + get { + return ResourceManager.GetString("ConfirmRemoveStep", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Are you sure you want to remove the topology {0}?. + /// + internal static string ConfirmRemoveTopology { + get { + return ResourceManager.GetString("ConfirmRemoveTopology", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Are you sure you want to restart the rollout {0} and re-run all the steps from the start? If you want to skip all the steps that succeeded on the previous attempt, enter No and pass the SkipSucceeded parameter.. + /// + internal static string ConfirmRestartRollout { + get { + return ResourceManager.GetString("ConfirmRestartRollout", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Once stopped, a rollout cannot be resumed. Are you sure you want to stop the rollout {0}. + /// + internal static string ConfirmStopRollout { + get { + return ResourceManager.GetString("ConfirmStopRollout", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Create artifact source. + /// + internal static string CreateArtifactSource { + get { + return ResourceManager.GetString("CreateArtifactSource", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Create service. + /// + internal static string CreateService { + get { + return ResourceManager.GetString("CreateService", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Create service topology. + /// + internal static string CreateServiceTopology { + get { + return ResourceManager.GetString("CreateServiceTopology", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Create service unit. + /// + internal static string CreateServiceUnit { + get { + return ResourceManager.GetString("CreateServiceUnit", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Create step. + /// + internal static string CreateStep { + get { + return ResourceManager.GetString("CreateStep", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Removed artifact source {0}.. + /// + internal static string RemovedArtifactSource { + get { + return ResourceManager.GetString("RemovedArtifactSource", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Removed rollout {0}. + /// + internal static string RemovedRollout { + get { + return ResourceManager.GetString("RemovedRollout", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Service {0} deleted.. + /// + internal static string RemovedService { + get { + return ResourceManager.GetString("RemovedService", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Removed service unit {0}. + /// + internal static string RemovedServiceUnit { + get { + return ResourceManager.GetString("RemovedServiceUnit", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Step {0} deleted.. + /// + internal static string RemovedStep { + get { + return ResourceManager.GetString("RemovedStep", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Topology {0} deleted.. + /// + internal static string RemovedTopology { + get { + return ResourceManager.GetString("RemovedTopology", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Removing artifact source {0}. + /// + internal static string RemovingArtifactSource { + get { + return ResourceManager.GetString("RemovingArtifactSource", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Removing rollout {0}. + /// + internal static string RemovingRollout { + get { + return ResourceManager.GetString("RemovingRollout", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Removing service {0}. + /// + internal static string RemovingService { + get { + return ResourceManager.GetString("RemovingService", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Removing service unit {0}. + /// + internal static string RemovingServiceUnit { + get { + return ResourceManager.GetString("RemovingServiceUnit", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Removing step {0}. + /// + internal static string RemovingStep { + get { + return ResourceManager.GetString("RemovingStep", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Removing service topology {0}. + /// + internal static string RemovingTopology { + get { + return ResourceManager.GetString("RemovingTopology", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Rollout {0} restarted.. + /// + internal static string RestartedRollout { + get { + return ResourceManager.GetString("RestartedRollout", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Restarting rollout {0}. + /// + internal static string RestartingRollout { + get { + return ResourceManager.GetString("RestartingRollout", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The specified service already exists.. + /// + internal static string ServiceAlreadyExists { + get { + return ResourceManager.GetString("ServiceAlreadyExists", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The specified service topology already exists.. + /// + internal static string ServiceTopologyAlreadyExists { + get { + return ResourceManager.GetString("ServiceTopologyAlreadyExists", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The specified service unit already exists.. + /// + internal static string ServiceUnitAlreadyExists { + get { + return ResourceManager.GetString("ServiceUnitAlreadyExists", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The specified step already exists.. + /// + internal static string StepAlreadyExists { + get { + return ResourceManager.GetString("StepAlreadyExists", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Rollout {0} stopped.. + /// + internal static string StoppedRollout { + get { + return ResourceManager.GetString("StoppedRollout", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Stopping rollout {0}. + /// + internal static string StoppingRollout { + get { + return ResourceManager.GetString("StoppingRollout", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Template and Parameters paths are required, either both as absolute SAS URIs or both relative paths.. + /// + internal static string TemplateParametersMissing { + get { + return ResourceManager.GetString("TemplateParametersMissing", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Update artifact source. + /// + internal static string UpdateArtifactSource { + get { + return ResourceManager.GetString("UpdateArtifactSource", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Update service. + /// + internal static string UpdateService { + get { + return ResourceManager.GetString("UpdateService", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Update service topology. + /// + internal static string UpdateServiceTopology { + get { + return ResourceManager.GetString("UpdateServiceTopology", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Update service unit. + /// + internal static string UpdateServiceUnit { + get { + return ResourceManager.GetString("UpdateServiceUnit", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Update step. + /// + internal static string UpdateStep { + get { + return ResourceManager.GetString("UpdateStep", resourceCulture); + } + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Messages.resx b/src/DeploymentManager/Commands.DeploymentManager/Messages.resx new file mode 100644 index 000000000000..177da9d4083a --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Messages.resx @@ -0,0 +1,240 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Are you sure you want to remove the rollout {0}? + + + Are you sure you want to restart the rollout {0} and re-run all the steps from the start? If you want to skip all the steps that succeeded on the previous attempt, enter No and pass the SkipSucceeded parameter. + + + Removing artifact source {0} + + + Removed rollout {0} + + + Topology {0} deleted. + + + Service {0} deleted. + + + Removing rollout {0} + + + Removing service topology {0} + + + Removing service {0} + + + Removing service unit {0} + + + There might be rollouts or topologies referencing the artifact source {0}. Are you sure you want to remove the artifact source? + + + Are you sure you want to remove the topology {0}? + + + Are you sure you want to remove the service {0}? + + + Are you sure you want to remove the service unit {0}? + + + Rollout {0} restarted. + + + Restarting rollout {0} + + + Rollout {0} stopped. + + + Once stopped, a rollout cannot be resumed. Are you sure you want to stop the rollout {0} + + + Stopping rollout {0} + + + Template and Parameters paths are required, either both as absolute SAS URIs or both relative paths. + + + Removed artifact source {0}. + + + The specified artifact source already exists. + + + Create artifact source + + + Create service + + + Create service topology + + + Create service unit + + + The specified service already exists. + + + The specified service topology already exists. + + + The specified service unit already exists. + + + Update artifact source + + + Update service + + + Update service topology + + + Update service unit + + + Removed service unit {0} + + + Are you sure you want to remove the step {0}? + + + Create step + + + Step {0} deleted. + + + Removing step {0} + + + The specified step already exists. + + + Update step + + \ No newline at end of file diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/ArtifactSource/PSArtifactSource.cs b/src/DeploymentManager/Commands.DeploymentManager/Models/ArtifactSource/PSArtifactSource.cs new file mode 100644 index 000000000000..708c7e392ef0 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Models/ArtifactSource/PSArtifactSource.cs @@ -0,0 +1,68 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Models +{ + using Microsoft.Azure.Commands.ResourceManager.Common.Tags; + using Microsoft.Azure.Management.DeploymentManager.Models; + + public class PSArtifactSource : PSResource + { + public PSArtifactSource() : base() + { + } + + public PSArtifactSource(string resourceGroupName, ArtifactSource artifactSource) : base(artifactSource) + { + this.ResourceGroupName = resourceGroupName; + this.SourceType = artifactSource.SourceType; + this.ArtifactRoot = artifactSource.ArtifactRoot; + this.Authentication = new PSSasAuthentication((SasAuthentication)artifactSource.Authentication); + } + + /// + /// Gets or sets the resource group to which the service unit belongs. + /// + public string ResourceGroupName { get; set; } + + /// + /// Gets or sets the artifact source type. + /// + public string SourceType { get; set; } + + /// + /// Gets or sets the root folder under which the artifacts are to be found. + /// + public string ArtifactRoot { get; set; } + + /// + /// Gets or sets the authentication information to access the artifact store. + /// + public PSAuthentication Authentication { get; set; } + + internal ArtifactSource ToSdkType() + { + var sasAuthentication = new SasAuthentication(((PSSasAuthentication)this.Authentication)?.SasUri); + return new ArtifactSource( + this.Location, + this.SourceType, + sasAuthentication, + this.Name, + this.Type, + this.Id, + TagsConversionHelper.CreateTagDictionary(this.Tags, validate: true), + this.ArtifactRoot); + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/ArtifactSource/PSAuthentication.cs b/src/DeploymentManager/Commands.DeploymentManager/Models/ArtifactSource/PSAuthentication.cs new file mode 100644 index 000000000000..d46c3a169876 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Models/ArtifactSource/PSAuthentication.cs @@ -0,0 +1,29 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Models +{ + using Microsoft.Azure.Management.DeploymentManager.Models; + + public abstract class PSAuthentication + { + protected PSAuthentication() + { + } + + protected PSAuthentication(Authentication authentication) + { + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/ArtifactSource/PSSasAuthentication.cs b/src/DeploymentManager/Commands.DeploymentManager/Models/ArtifactSource/PSSasAuthentication.cs new file mode 100644 index 000000000000..03b7f4320af6 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Models/ArtifactSource/PSSasAuthentication.cs @@ -0,0 +1,39 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Models +{ + using Microsoft.Azure.Management.DeploymentManager.Models; + + public class PSSasAuthentication : PSAuthentication + { + public PSSasAuthentication() : base() + { + } + + public PSSasAuthentication(SasAuthentication sasAuthentication) : base(sasAuthentication) + { + this.SasUri = sasAuthentication.SasUri; + } + + /// + /// Gets or sets the complete SAS URI to the location of the artifacts. + /// + public string SasUri + { + get; + set; + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/PSIdentity.cs b/src/DeploymentManager/Commands.DeploymentManager/Models/PSIdentity.cs new file mode 100644 index 000000000000..4d6bf804afcc --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Models/PSIdentity.cs @@ -0,0 +1,53 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Models +{ + using System.Collections.Generic; + using Microsoft.Azure.Management.DeploymentManager.Models; + + public class PSIdentity + { + public PSIdentity(Identity identity) + { + this.Type = identity.Type; + this.IdentityIds = identity.IdentityIds; + } + + /// + /// Gets or sets the identity type. + /// + public string Type + { + get; + set; + } + + /// + /// Gets or sets the list of identities. + /// + public IList IdentityIds + { + get; + set; + } + + internal Identity ToSdkType() + { + return new Identity( + type: this.Type, + identityIds: this.IdentityIds); + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSBaseOperationInfo.cs b/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSBaseOperationInfo.cs new file mode 100644 index 000000000000..12aa2e65b62e --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSBaseOperationInfo.cs @@ -0,0 +1,58 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Models +{ + using System; + using Microsoft.Azure.Management.DeploymentManager.Models; + + public class PSBaseOperationInfo + { + public PSBaseOperationInfo( + DateTime? startTime, + DateTime? endTime, + DateTime? lastUpdateTime, + CloudErrorBody error) + { + this.StartTime = startTime; + this.EndTime = endTime; + this.LastUpdatedTime = lastUpdateTime; + this.Error = error; + } + + public DateTime? StartTime + { + get; + private set; + } + + public DateTime? EndTime + { + get; + private set; + } + + public DateTime? LastUpdatedTime + { + get; + private set; + } + + public CloudErrorBody Error + { + get; + set; + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSMessage.cs b/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSMessage.cs new file mode 100644 index 000000000000..755139f977c2 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSMessage.cs @@ -0,0 +1,47 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Models +{ + using System; + using Microsoft.Azure.Management.DeploymentManager.Models; + + public class PSMessage + { + public PSMessage(Message message) + { + this.TimeStamp = message?.TimeStamp; + this.MessageProperty = message?.MessageProperty; + } + + /// + /// Gets time in UTC this message was provided. + /// + public DateTime? TimeStamp + { + get; + private set; + } + + /// + /// Gets the actual message text. + /// + public string MessageProperty + { + get; + private set; + } + + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSResource.cs b/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSResource.cs new file mode 100644 index 000000000000..f54f665e9b01 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSResource.cs @@ -0,0 +1,61 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Models +{ + using System.Collections; + using Microsoft.Azure.Commands.ResourceManager.Common.Tags; + using Microsoft.Azure.Management.DeploymentManager.Models; + + public abstract class PSResource + { + protected PSResource() + { + } + + protected PSResource(TrackedResource trackedResource) + { + this.Name = trackedResource.Name; + this.Type = trackedResource.Type; + this.Id = trackedResource.Id; + this.Location = trackedResource.Location; + this.Tags = TagsConversionHelper.CreateTagHashtable(trackedResource.Tags); + } + + /// + /// Gets or sets the resource name. + /// + public string Name { get; set; } + + /// + /// Gets or sets the resource type. + /// + public string Type { get; set; } + + /// + /// Gets or sets the resource location. + /// + public string Location { get; set; } + + /// + /// Gets or sets the resource Id. + /// + public string Id { get; set; } + + /// + /// Gets or sets the resource tags. + /// + public Hashtable Tags { get; set; } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSResourceOperation.cs b/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSResourceOperation.cs new file mode 100644 index 000000000000..95127fc45caa --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSResourceOperation.cs @@ -0,0 +1,91 @@ +// ---------------------------------------------------------------------------------- +// +// 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 Microsoft.Azure.Management.DeploymentManager.Models; + +namespace Microsoft.Azure.Commands.DeploymentManager.Models +{ + public class PSResourceOperation + { + public PSResourceOperation(ResourceOperation resourceOperation) + { + this.ResourceName = resourceOperation?.ResourceName; + this.OperationId = resourceOperation?.OperationId; + this.ResourceType = resourceOperation?.ResourceType; + this.ProvisioningState = resourceOperation?.ProvisioningState; + this.StatusCode = resourceOperation?.StatusCode; + this.StatusMessage = resourceOperation?.StatusMessage; + } + + /// + /// Gets or sets name of the resource as specified in the artifacts. + /// For ARM resources, this is the name of the resource specified in + /// the template. + /// + public string ResourceName + { + get; + set; + } + + /// + /// Gets unique identifier of the operation. For ARM resources, this is + /// the operationId obtained from ARM service. + /// + public string OperationId + { + get; + private set; + } + + /// + /// Gets or sets type of the resource as specified in the artifacts. + /// For ARM resources, this is the type of the resource specified in + /// the template. + /// + public string ResourceType + { + get; + set; + } + + /// + /// Gets state of the resource deployment. For ARM resources, this is + /// the current provisioning state of the resource. + /// + public string ProvisioningState + { + get; + private set; + } + + /// + /// Gets descriptive information of the resource operation. + /// + public string StatusMessage + { + get; + private set; + } + + /// + /// Gets http status code of the operation. + /// + public string StatusCode + { + get; + private set; + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSRollout.cs b/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSRollout.cs new file mode 100644 index 000000000000..19642e0572de --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSRollout.cs @@ -0,0 +1,122 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Models +{ + using System.Collections.Generic; + using System.Linq; + using Microsoft.Azure.Management.DeploymentManager.Models; + + public class PSRollout : PSResource + { + public PSRollout() : base() + { + } + + public PSRollout(string resourceGroupName, Rollout rollout) : base(rollout) + { + this.ResourceGroupName = resourceGroupName; + this.BuildVersion = rollout.BuildVersion; + this.ArtifactSourceId = rollout.ArtifactSourceId; + this.TargetServiceTopologyId = rollout.TargetServiceTopologyId; + this.Identity = rollout.Identity != null ? new PSIdentity(rollout.Identity) : null; + this.OperationInfo = rollout.OperationInfo != null ? new PSRolloutOperationInfo(rollout.OperationInfo) : null; + this.Status = rollout.Status; + this.TotalRetryAttempts = rollout.TotalRetryAttempts; + this.Services = rollout.Services?.Select(s=> new PSService(s)).ToList(); + } + + /// + /// Gets or sets the resource group to which the service unit belongs. + /// + public string ResourceGroupName { get; set; } + + /// + /// Gets or sets the version of the build being deployed. + /// + public string BuildVersion + { + get; + set; + } + + /// + /// Gets or sets the reference to the ARM resource Id where the payload + /// is located. + /// + public string ArtifactSourceId + { + get; + set; + } + + /// + /// Gets or sets the reference to the ARM resource Id where the payload + /// is located. + /// + public string TargetServiceTopologyId + { + get; + set; + } + + /// + /// Gets or sets the list of steps that define the orchestration. + /// + public string Status + { + get; + private set; + } + + /// + /// Gets the cardinal count of total number of retries performed on the + /// rollout at a given time. + /// + public int? TotalRetryAttempts + { + get; + private set; + } + + /// + /// Gets or sets the identity information for the rollout. + /// + public PSIdentity Identity + { + get; + set; + } + + /// + /// Gets or sets operational information of the rollout. + /// + public PSRolloutOperationInfo OperationInfo + { + get; + set; + } + + /// + /// Gets or sets set of detailed step result information on target + /// resource groups. + /// + public IList Services + { + get; + set; + } + + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSRolloutOperationInfo.cs b/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSRolloutOperationInfo.cs new file mode 100644 index 000000000000..99e4b034408a --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSRolloutOperationInfo.cs @@ -0,0 +1,43 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Models +{ + using Microsoft.Azure.Management.DeploymentManager.Models; + + public class PSRolloutOperationInfo : PSBaseOperationInfo + { + public PSRolloutOperationInfo(RolloutOperationInfo rolloutOperationInfo) : base( + rolloutOperationInfo?.StartTime, + rolloutOperationInfo?.EndTime, + null, + rolloutOperationInfo?.Error) + { + this.RetryAttempt = rolloutOperationInfo.RetryAttempt; + this.SkipSucceededOnRetry = rolloutOperationInfo.SkipSucceededOnRetry; + } + + public int? RetryAttempt + { + get; + set; + } + + public bool? SkipSucceededOnRetry + { + get; + set; + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSRolloutStep.cs b/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSRolloutStep.cs new file mode 100644 index 000000000000..bd83327c09ec --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSRolloutStep.cs @@ -0,0 +1,90 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Models +{ + using System.Collections.Generic; + using System.Linq; + using Microsoft.Azure.Management.DeploymentManager.Models; + + public class PSRolloutStep + { + public PSRolloutStep(RolloutStep rolloutStep) + { + this.Name = rolloutStep.Name; + this.Status = rolloutStep.Status; + this.StepGroup = rolloutStep.StepGroup; + this.OperationInfo = rolloutStep.OperationInfo != null ? new PSStepOperationInfo(rolloutStep.OperationInfo) : null; + this.ResourceOperations = rolloutStep.ResourceOperations?.Select(ro => new PSResourceOperation(ro)).ToList(); + this.Messages = rolloutStep.Messages?.Select(m => new PSMessage(m)).ToList(); + } + + /// + /// Gets or sets name of the step as specified in the rollout + /// specification input artifact. + /// + public string Name + { + get; + set; + } + + /// + /// Gets current state of the step. + /// + public string Status + { + get; + private set; + } + + /// + /// Gets or sets the step group the current step is part of. + /// + public string StepGroup + { + get; + set; + } + + /// + /// Gets detailed information of specific action execution. + /// + public PSStepOperationInfo OperationInfo + { + get; + private set; + } + + /// + /// Gets set of resource operations that were performed on the Azure + /// resource that the action acted upon. + /// + public IList ResourceOperations + { + get; + private set; + } + + /// + /// Gets supplementary informative messages during rollout. + /// + public IList Messages + { + get; + private set; + } + + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSService.cs b/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSService.cs new file mode 100644 index 000000000000..bcefa71dec1d --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSService.cs @@ -0,0 +1,71 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Models +{ + using System.Collections.Generic; + using System.Linq; + using Microsoft.Azure.Management.DeploymentManager.Models; + + public class PSService + { + public PSService(Service service) + { + this.TargetLocation = service.TargetLocation; + this.TargetSubscriptionId = service.TargetSubscriptionId; + this.Name = service.Name; + this.ServiceUnits = service.ServiceUnits?.Select(su => new PSServiceUnit(su)).ToList(); + } + + /// + /// Gets or sets the Azure location to which the resources in the + /// service belong to. + /// + public string TargetLocation + { + get; + set; + } + + /// + /// Gets or sets the subscription to which the resources in the service + /// belong to. + /// + public string TargetSubscriptionId + { + get; + set; + } + + /// + /// Gets or sets name of the service. + /// + public string Name + { + get; + set; + } + + /// + /// Gets or sets the detailed information about the units that make up + /// the service. + /// + public IList ServiceUnits + { + get; + set; + } + + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSServiceUnit.cs b/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSServiceUnit.cs new file mode 100644 index 000000000000..542910e204f5 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSServiceUnit.cs @@ -0,0 +1,114 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Models +{ + using System.Collections.Generic; + using System.Linq; + + using Microsoft.Azure.Management.DeploymentManager.Models; + + public class PSServiceUnit + { + public PSServiceUnit(ServiceUnit serviceUnit) + { + this.Name = serviceUnit.Name; + this.TargetResourceGroup = serviceUnit.TargetResourceGroup; + this.DeploymentMode = serviceUnit.DeploymentMode; + this.ParametersArtifactSourceRelativePath = serviceUnit.Artifacts?.ParametersArtifactSourceRelativePath; + this.ParametersUri = serviceUnit.Artifacts?.ParametersUri; + this.TemplateArtifactSourceRelativePath = serviceUnit.Artifacts?.TemplateArtifactSourceRelativePath; + this.TemplateUri = serviceUnit.Artifacts?.TemplateUri; + this.Steps = serviceUnit.Steps?.Select(s => new PSRolloutStep(s)).ToList(); + } + /// + /// Gets or sets the Azure Resource Group to which the resources in the + /// service unit belong to. + /// + public string TargetResourceGroup + { + get; + set; + } + + /// + /// Gets or sets describes the type of ARM deployment to be performed + /// on the resource. Possible values include: 'Complete', 'Incremental' + /// + public DeploymentMode DeploymentMode + { + get; + set; + } + + /// + /// Gets or sets the full URI of the ARM template file with the SAS + /// token. + /// + public string TemplateUri + { + get; + set; + } + + /// + /// Gets or sets the full URI of the ARM parameters file with the SAS + /// token. + /// + public string ParametersUri + { + get; + set; + } + + /// + /// Gets or sets the path to the ARM template file relative to the + /// artifact store. + /// + public string TemplateArtifactSourceRelativePath + { + get; + set; + } + + /// + /// Gets or sets the path to the ARM parameters file relative to the + /// artifact store. + /// + public string ParametersArtifactSourceRelativePath + { + get; + set; + } + + /// + /// Gets or sets name of the service unit. + /// + public string Name + { + get; + set; + } + + /// + /// Gets or sets detailed step information, if present. + /// + public IList Steps + { + get; + set; + } + + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSStepOperationInfo.cs b/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSStepOperationInfo.cs new file mode 100644 index 000000000000..2609e341ce70 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSStepOperationInfo.cs @@ -0,0 +1,43 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Models +{ + using Microsoft.Azure.Management.DeploymentManager.Models; + + public class PSStepOperationInfo : PSBaseOperationInfo + { + public PSStepOperationInfo(StepOperationInfo stepOperationInfo) : base( + stepOperationInfo?.StartTime, + stepOperationInfo?.EndTime, + stepOperationInfo?.LastUpdatedTime, + stepOperationInfo?.Error) + { + this.DeploymentName = stepOperationInfo?.DeploymentName; + this.CorrelationId = stepOperationInfo?.CorrelationId; + } + + public string DeploymentName + { + get; + private set; + } + + public string CorrelationId + { + get; + private set; + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/ServiceTopology/PSServiceResource.cs b/src/DeploymentManager/Commands.DeploymentManager/Models/ServiceTopology/PSServiceResource.cs new file mode 100644 index 000000000000..814a3b8179b4 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Models/ServiceTopology/PSServiceResource.cs @@ -0,0 +1,69 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Models +{ + using Microsoft.Azure.Commands.ResourceManager.Common.Tags; + using Microsoft.Azure.Management.DeploymentManager.Models; + + public class PSServiceResource : PSResource + { + public PSServiceResource() : base() + { + } + + public PSServiceResource( + string resourceGroup, + string serviceTopologyName, + ServiceResource serviceResource) : base(serviceResource) + { + this.ResourceGroupName = resourceGroup; + this.ServiceTopologyName = serviceTopologyName; + this.TargetSubscriptionId = serviceResource.TargetSubscriptionId; + this.TargetLocation = serviceResource.TargetLocation; + } + + /// + /// Gets or sets the resource group to which the service unit belongs. + /// + public string ResourceGroupName { get; set; } + + /// + /// Gets or sets the service topology the service unit belongs to. + /// + public string ServiceTopologyName { get; set; } + + /// + /// Gets or sets the subscription to which the resources in the topology group should be deployed to. + /// + public string TargetSubscriptionId { get; set; } + + /// + /// Gets or sets the location where the resources in the topology group should be deployed to. + /// + public string TargetLocation { get; set; } + + internal ServiceResource ToSdkType() + { + return new ServiceResource( + location: this.Location, + targetLocation: this.TargetLocation, + targetSubscriptionId: this.TargetSubscriptionId, + id: this.Id, + name: this.Name, + type: this.Type, + tags: TagsConversionHelper.CreateTagDictionary(this.Tags, validate: true)); + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/ServiceTopology/PSServiceTopologyResource.cs b/src/DeploymentManager/Commands.DeploymentManager/Models/ServiceTopology/PSServiceTopologyResource.cs new file mode 100644 index 000000000000..0caa19e178bb --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Models/ServiceTopology/PSServiceTopologyResource.cs @@ -0,0 +1,56 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Models +{ + using Microsoft.Azure.Commands.ResourceManager.Common.Tags; + using Microsoft.Azure.Management.DeploymentManager.Models; + + public class PSServiceTopologyResource : PSResource + { + public PSServiceTopologyResource() : base() + { + } + + public PSServiceTopologyResource( + string resourceGroup, + ServiceTopologyResource topologyResource) : base(topologyResource) + { + this.ResourceGroupName = resourceGroup; + this.ArtifactSourceId = topologyResource.ArtifactSourceId; + } + + /// + /// Gets or sets the resource group to which the service unit belongs. + /// + public string ResourceGroupName { get; set; } + + /// + /// Gets or sets the artifact store that contains the artifacts that + /// make up the topology components. + /// + public string ArtifactSourceId { get; set; } + + internal ServiceTopologyResource ToSdkType() + { + return new ServiceTopologyResource( + location: this.Location, + artifactSourceId: this.ArtifactSourceId, + id: this.Id, + name: this.Name, + type: this.Type, + tags: TagsConversionHelper.CreateTagDictionary(this.Tags, validate: true)); + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/ServiceTopology/PSServiceUnitResource.cs b/src/DeploymentManager/Commands.DeploymentManager/Models/ServiceTopology/PSServiceUnitResource.cs new file mode 100644 index 000000000000..98f201990fb4 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Models/ServiceTopology/PSServiceUnitResource.cs @@ -0,0 +1,111 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Models +{ + using System; + using Microsoft.Azure.Commands.ResourceManager.Common.Tags; + using Microsoft.Azure.Management.DeploymentManager.Models; + + public class PSServiceUnitResource : PSResource + { + public PSServiceUnitResource() : base() + { + } + + public PSServiceUnitResource( + string resourceGroup, + string serviceTopologyName, + string serviceName, + ServiceUnitResource serviceUnitResource) : base(serviceUnitResource) + { + this.ResourceGroupName = resourceGroup; + this.DeploymentMode = serviceUnitResource.DeploymentMode.ToString(); + this.ServiceTopologyName = serviceTopologyName; + this.ServiceName = serviceName; + this.TargetResourceGroup = serviceUnitResource.TargetResourceGroup; + this.TemplateUri = serviceUnitResource.Artifacts.TemplateUri; + this.ParametersUri = serviceUnitResource.Artifacts.ParametersUri; + this.ParametersArtifactSourceRelativePath = serviceUnitResource.Artifacts.ParametersArtifactSourceRelativePath; + this.TemplateArtifactSourceRelativePath = serviceUnitResource.Artifacts.TemplateArtifactSourceRelativePath; + } + + /// + /// Gets or sets the resource group to which the service unit belongs. + /// + public string ResourceGroupName { get; set; } + + /// + /// Gets or sets the service topology the service unit belongs to. + /// + public string ServiceTopologyName { get; set; } + + /// + /// Gets or sets the service the service unit belongs to. + /// + public string ServiceName { get; set; } + + /// + /// Gets or sets the resource group to which the resources in the topology group should be deployed to. + /// + public string TargetResourceGroup { get; set; } + + /// + /// Gets or sets describes the type of ARM deployment to be performed + /// on the resource. Possible values include: 'Complete', 'Incremental' + /// + public string DeploymentMode { get; set; } + + /// + /// Gets or sets the SAS URI of the ARM template. + /// + public string TemplateUri { get; set; } + + /// + /// Gets or sets the SAS URI of the ARM parameters file. + /// + public string ParametersUri { get; set; } + + /// + /// Gets or sets the relative path of the ARM parameters file from the artifact source for this topology. + /// + public string ParametersArtifactSourceRelativePath { get; set; } + + /// + /// Gets or sets the relative path of the ARM template file from the artifact source for this topology. + /// + public string TemplateArtifactSourceRelativePath { get; set; } + + internal ServiceUnitResource ToSdkType() + { + return new ServiceUnitResource( + location: this.Location, + targetResourceGroup: this.TargetResourceGroup, + deploymentMode: (DeploymentMode)Enum.Parse(typeof(DeploymentMode), this.DeploymentMode, ignoreCase: true), + id: this.Id, + name: this.Name, + type: this.Type, + tags: TagsConversionHelper.CreateTagDictionary(this.Tags, validate: true)) + { + Artifacts = new ServiceUnitArtifacts() + { + TemplateUri = this.TemplateUri, + ParametersUri = this.ParametersUri, + TemplateArtifactSourceRelativePath = this.TemplateArtifactSourceRelativePath, + ParametersArtifactSourceRelativePath = this.ParametersArtifactSourceRelativePath + } + }; + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/Steps/PSStepProperties.cs b/src/DeploymentManager/Commands.DeploymentManager/Models/Steps/PSStepProperties.cs new file mode 100644 index 000000000000..14933aa075db --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Models/Steps/PSStepProperties.cs @@ -0,0 +1,31 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Models +{ + using Microsoft.Azure.Management.DeploymentManager.Models; + + public abstract class PSStepProperties + { + protected PSStepProperties() + { + } + + protected PSStepProperties(StepProperties stepProperties) + { + } + + internal abstract StepProperties ToSdkType(); + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/Steps/PSStepResource.cs b/src/DeploymentManager/Commands.DeploymentManager/Models/Steps/PSStepResource.cs new file mode 100644 index 000000000000..049e5bc75d6e --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Models/Steps/PSStepResource.cs @@ -0,0 +1,59 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Models +{ + using Microsoft.Azure.Commands.ResourceManager.Common.Tags; + using Microsoft.Azure.Management.DeploymentManager.Models; + + public class PSStepResource : PSResource + { + public PSStepResource(): base() + { + + } + + public PSStepResource(string resourceGroupName, StepResource stepResource) : base(stepResource) + { + this.ResourceGroupName = resourceGroupName; + this.StepProperties = new PSWaitStepProperties((WaitStepProperties)stepResource.Properties); + } + + /// + /// Gets or sets the resource group to which the service unit belongs. + /// + public string ResourceGroupName { get; set; } + + /// + /// Gets or sets provides the input parameters that correspond to the + /// stepType. + /// + public PSStepProperties StepProperties + { + get; + set; + } + + internal StepResource ToSdkType() + { + return new StepResource( + location: this.Location, + properties: this.StepProperties?.ToSdkType(), + id: this.Id, + name: this.Name, + type: this.Type, + tags: TagsConversionHelper.CreateTagDictionary(this.Tags, validate: true)); + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/Steps/PSWaitStepProperties.cs b/src/DeploymentManager/Commands.DeploymentManager/Models/Steps/PSWaitStepProperties.cs new file mode 100644 index 000000000000..c25f40fe6160 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Models/Steps/PSWaitStepProperties.cs @@ -0,0 +1,37 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Models +{ + using Microsoft.Azure.Management.DeploymentManager.Models; + + public class PSWaitStepProperties : PSStepProperties + { + public PSWaitStepProperties() : base() + { + } + + public PSWaitStepProperties(WaitStepProperties waitStepProperties) : base(waitStepProperties) + { + this.Duration = waitStepProperties.Attributes?.Duration; + } + + public string Duration { get; set; } + + internal override StepProperties ToSdkType() + { + return new WaitStepProperties(new WaitStepAttributes(this.Duration)); + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/Properties/AssemblyInfo.cs b/src/DeploymentManager/Commands.DeploymentManager/Properties/AssemblyInfo.cs new file mode 100644 index 000000000000..2fbcbaabccb6 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("DeploymentManager")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("DeploymentManager")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("f022ed20-7d3b-4bf4-88af-f97cc50484da")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("0.9.1.0")] +[assembly: AssemblyFileVersion("0.9.1.0")] diff --git a/src/DeploymentManager/Commands.DeploymentManager/Utilities/EnumerationUtilities.cs b/src/DeploymentManager/Commands.DeploymentManager/Utilities/EnumerationUtilities.cs new file mode 100644 index 000000000000..895000520d7b --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Utilities/EnumerationUtilities.cs @@ -0,0 +1,48 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Utilities +{ + using System.Collections.Generic; + using System.Globalization; + using System.Linq; + using System.Text; + + internal static class EnumerationUtilities + { + internal static string ToCommaDelimitedString(this IEnumerable items, string delimiter = ", ") + { + StringBuilder builder = new StringBuilder(); + int count = items.Count(); + foreach (T item in items) + { + builder.AppendFormat( + CultureInfo.InvariantCulture, + $"{item}"); + + if (--count != 0) + { + builder.Append(delimiter); + } + } + + if (builder.Length > 0) + { + builder.Append("."); + } + + return builder.ToString(); + } + } +} \ No newline at end of file diff --git a/src/DeploymentManager/Commands.DeploymentManager/Utilities/StringUtilities.cs b/src/DeploymentManager/Commands.DeploymentManager/Utilities/StringUtilities.cs new file mode 100644 index 000000000000..1505ac04c80a --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/Utilities/StringUtilities.cs @@ -0,0 +1,168 @@ +// ---------------------------------------------------------------------------------- +// +// 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. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.Azure.Commands.DeploymentManager.Utilities +{ + using System; + using System.Globalization; + using System.Linq; + using System.Text; + + internal static class StringUtilities + { + private const int DefaultIndentLength = 4; + + internal static string InvariantFormat(string format, params object[] args) + { + if (args.Length > 0) + { + return string.Format( + CultureInfo.InvariantCulture, + format, + args); + } + else + { + return format; + } + } + + internal static string SafeInvariantFormat(string format, params object[] args) + { + const string NullString = ""; + + if (args == null) + { + // When the argument is null replace with an array of one + // containing the null string. + args = new string[] { NullString }; + } + else + { + // Iterate all the args replacing any nulls with the null string. + for (int i = 0; i < args.Length; i++) + { + if (args[i] == null) + { + args[i] = NullString; + } + } + } + + return StringUtilities.InvariantFormat(format, args); + } + + internal static void InvariantAppend( + this StringBuilder builder, + string format, + params object[] args) + { + const string NullString = ""; + + if (args == null) + { + // When the argument is null replace with an array of one + // containing the null string. + args = new string[] { NullString }; + } + else + { + // Iterate all the args replacing any nulls with the null string. + for (int i = 0; i < args.Length; i++) + { + if (args[i] == null) + { + args[i] = NullString; + } + } + } + + if (args.Length > 0) + { + builder.AppendFormat(CultureInfo.InvariantCulture, format, args); + } + else + { + builder.Append(format); + } + } + + internal static bool IsNullOrWhiteSpace(string value) + { + if (string.IsNullOrEmpty(value)) + { + return true; + } + + if (value.Trim().Length == 0) + { + return true; + } + + return false; + } + + internal static string ToLocalTimeForUserDisplay(this DateTime dateTime) + { + return dateTime.ToLocalTime().ToString("G", CultureInfo.InvariantCulture); + } + + internal static string ToDisplayFormat(this TimeSpan timeSpan) + { + var trimmedTimeSpan = new TimeSpan(timeSpan.Days, timeSpan.Hours, timeSpan.Minutes, timeSpan.Seconds); + + return trimmedTimeSpan.ToString(); + } + + internal static void AppendFormatWithLeftIndentAndNewLine(this StringBuilder sb, int indentFactor, string format, params object[] args) + { + string resultString; + + if (args == null || !args.Any()) + { + resultString = format; + } + else + { + resultString = StringUtilities.SafeInvariantFormat(format, args); + } + + if (indentFactor > 0) + { + resultString = resultString.PadLeft(resultString.Length + (StringUtilities.DefaultIndentLength * indentFactor)); + } + + sb.AppendLine(); + sb.Append(resultString); + } + + internal static void AppendFormatWithLeftIndentAndNewLineIfNotNull(this StringBuilder sb, int indentFactor, string name, string value) + { + if (!StringUtilities.IsNullOrWhiteSpace(value)) + { + sb.AppendFormatWithLeftIndentAndNewLine(indentFactor, "{0}: {1}", name, value); + } + } + + internal static string FormatIfNotNull(string name, string value) + { + if (!StringUtilities.IsNullOrWhiteSpace(value)) + { + return StringUtilities.SafeInvariantFormat("{0}: {1}", name, value); + } + + return string.Empty; + } + } +} diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/AzureRM.DeploymentManager.md b/src/DeploymentManager/Commands.DeploymentManager/help/AzureRM.DeploymentManager.md new file mode 100644 index 000000000000..a6d511d13dca --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/help/AzureRM.DeploymentManager.md @@ -0,0 +1,85 @@ +--- +Module Name: AzureRM.DeploymentManager +Module Guid: {{ Update Module Guid }} +Download Help Link: {{ Update Download Link }} +Help Version: {{ Update Help Version }} +Locale: {{ Update Locale }} +--- + +# AzureRM.DeploymentManager Module +## Description +{{Manually Enter Description Here}} + +## AzureRM.DeploymentManager Cmdlets +### [Get-AzureRmDeploymentManagerArtifactSource](Get-AzureRmDeploymentManagerArtifactSource.md) +Gets an artifact source. + +### [Get-AzureRmDeploymentManagerRollout](Get-AzureRmDeploymentManagerRollout.md) +Gets a rollout. + +### [Get-AzureRmDeploymentManagerService](Get-AzureRmDeploymentManagerService.md) +Gets a service in a service topology. + +### [Get-AzureRmDeploymentManagerServiceTopology](Get-AzureRmDeploymentManagerServiceTopology.md) +Gets a service topology. + +### [Get-AzureRmDeploymentManagerServiceUnit](Get-AzureRmDeploymentManagerServiceUnit.md) +Gets a service unit. + +### [Get-AzureRmDeploymentManagerStep](Get-AzureRmDeploymentManagerStep.md) +Gets the deployment step. + +### [New-AzureRmDeploymentManagerArtifactSource](New-AzureRmDeploymentManagerArtifactSource.md) +Creates an artifact source. + +### [New-AzureRmDeploymentManagerService](New-AzureRmDeploymentManagerService.md) +Creates a service in a service topology. + +### [New-AzureRmDeploymentManagerServiceTopology](New-AzureRmDeploymentManagerServiceTopology.md) +Creates a new service topology. + +### [New-AzureRmDeploymentManagerServiceUnit](New-AzureRmDeploymentManagerServiceUnit.md) +Creates a new service unit under a service in a service topology. + +### [New-AzureRmDeploymentManagerStep](New-AzureRmDeploymentManagerStep.md) +Creates a new deployment step. + +### [Remove-AzureRmDeploymentManagerArtifactSource](Remove-AzureRmDeploymentManagerArtifactSource.md) +Deletes an artifact source. + +### [Remove-AzureRmDeploymentManagerRollout](Remove-AzureRmDeploymentManagerRollout.md) +Deletes a rollout. + +### [Remove-AzureRmDeploymentManagerService](Remove-AzureRmDeploymentManagerService.md) +Deletes a service in a service topology. + +### [Remove-AzureRmDeploymentManagerServiceTopology](Remove-AzureRmDeploymentManagerServiceTopology.md) +Deletes a service topology and all its resources. + +### [Remove-AzureRmDeploymentManagerServiceUnit](Remove-AzureRmDeploymentManagerServiceUnit.md) +Deletes the service unit of a service in a service topology. + +### [Remove-AzureRmDeploymentManagerStep](Remove-AzureRmDeploymentManagerStep.md) +Deletes a step. + +### [Restart-AzureRmDeploymentManagerRollout](Restart-AzureRmDeploymentManagerRollout.md) +Restart a failed rollout. + +### [Set-AzureRmDeploymentManagerArtifactSource](Set-AzureRmDeploymentManagerArtifactSource.md) +Updates an artifact source. + +### [Set-AzureRmDeploymentManagerService](Set-AzureRmDeploymentManagerService.md) +Updates a service in service topology. + +### [Set-AzureRmDeploymentManagerServiceTopology](Set-AzureRmDeploymentManagerServiceTopology.md) +Updates the service topology. + +### [Set-AzureRmDeploymentManagerServiceUnit](Set-AzureRmDeploymentManagerServiceUnit.md) +Updates a service unit. + +### [Set-AzureRmDeploymentManagerStep](Set-AzureRmDeploymentManagerStep.md) +Updates a step. + +### [Stop-AzureRmDeploymentManagerRollout](Stop-AzureRmDeploymentManagerRollout.md) +Stops a rollout in progress. + diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerArtifactSource.md b/src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerArtifactSource.md new file mode 100644 index 000000000000..a1f7b056468e --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerArtifactSource.md @@ -0,0 +1,158 @@ +--- +external help file: Microsoft.Azure.Commands.DeploymentManager.dll-Help.xml +Module Name: AzureRM.DeploymentManager +online version: +schema: 2.0.0 +--- + +# Get-AzureRmDeploymentManagerArtifactSource + +## SYNOPSIS +Gets an artifact source. + +## SYNTAX + +### Interactive (Default) +``` +Get-AzureRmDeploymentManagerArtifactSource [-ResourceGroupName] [-Name] + [-DefaultProfile ] [] +``` + +### ResourceId +``` +Get-AzureRmDeploymentManagerArtifactSource [-ResourceId] [-DefaultProfile ] + [] +``` + +### InputObject +``` +Get-AzureRmDeploymentManagerArtifactSource [-ArtifactSource] + [-DefaultProfile ] [] +``` + +## DESCRIPTION +The **Get-AzureRmDeploymentManagerArtifactSource** cmdlet gets an artifact source, and returns an object that represents that artifact source. +Specify the artifact source by its name and resource group name. Alternately, you can provide the ArtifactSource object or the ResourceId. + +You can modify this object locally, and then apply changes to the artifact source by using the Set-AzureRmDeploymentManagerArtifactSource cmdlet. + +## EXAMPLES + +### Example 1: Get an artifact source +```powershell +PS C:\> Get-AzureRmDeploymentManagerArtifactSource -ResourceGroupName "ContosoResourceGroup" -Name "ContosoArtifactSource" +``` + +This command gets an artifact source named ContosoArtifactSource in ContosoResourceGroup. + +### Example 2: Get an artifact source using the resource identifier +```powershell +PS C:\> Get-AzureRmDeploymentManagerArtifactSource -ResourceId "/subscriptions/subscriptionId/resourcegroups/ContosoResourceGroup/providers/Microsoft.DeploymentManager/artifactSources/ContosoArtifactSource" +``` + +This command gets an artifact source named ContosoArtifactSource in ContosoResourceGroup. + +### Example 3: Get an artifact source using an object returned by New-AzureRmDeploymentManagerArtifactSource +```powershell +PS C:\> Get-AzureRmDeploymentManagerArtifactSource -ArtifactSource $artifactSourceObject +``` + +This command gets an artifact source whose name and ResourceGroup match the Name and ResourceGroupName properties of the $artifactSourceObject, respectively. + +## PARAMETERS + +### -ArtifactSource +Artifact Source object. + +```yaml +Type: Microsoft.Azure.Commands.DeploymentManager.Models.PSArtifactSource +Parameter Sets: InputObject +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -DefaultProfile +The credentials, account, tenant, and subscription used for communication with Azure. + +```yaml +Type: Microsoft.Azure.Commands.Common.Authentication.Abstractions.IAzureContextContainer +Parameter Sets: (All) +Aliases: AzureRmContext, AzureCredential + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Name +The name of the artifact source. + +```yaml +Type: System.String +Parameter Sets: Interactive +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -ResourceGroupName +The resource group. + +```yaml +Type: System.String +Parameter Sets: Interactive +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -ResourceId +The resource identifier. + +```yaml +Type: System.String +Parameter Sets: ResourceId +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### None + +## OUTPUTS + +### Microsoft.Azure.Commands.DeploymentManager.Models.PSArtifactSource + +## NOTES + +## RELATED LINKS + +[New-AzureRmDeploymentManagerArtifactSource](./New-AzureRmDeploymentManagerArtifactSource.md) + +[Remove-AzureRmDeploymentManagerArtifactSource](./Remove-AzureRmDeploymentManagerArtifactSource.md) + +[Set-AzureRmDeploymentManagerArtifactSource](./Set-AzureRmDeploymentManagerArtifactSource.md) \ No newline at end of file diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerRollout.md b/src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerRollout.md new file mode 100644 index 000000000000..7c79b07add24 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerRollout.md @@ -0,0 +1,181 @@ +--- +external help file: Microsoft.Azure.Commands.DeploymentManager.dll-Help.xml +Module Name: AzureRM.DeploymentManager +online version: +schema: 2.0.0 +--- + +# Get-AzureRmDeploymentManagerRollout + +## SYNOPSIS +Gets a rollout. + +## SYNTAX + +### Interactive (Default) +``` +Get-AzureRmDeploymentManagerRollout [-ResourceGroupName] [-Name] [[-RetryAttempt] ] + [-DefaultProfile ] [] +``` + +### ResourceId +``` +Get-AzureRmDeploymentManagerRollout [-ResourceId] [-DefaultProfile ] + [] +``` + +### InputObject +``` +Get-AzureRmDeploymentManagerRollout [-Rollout] [-DefaultProfile ] + [] +``` + +## DESCRIPTION +The **Get-AzureRmDeploymentManagerRollout** cmdlet gets a rollout, and returns an object that represents that rollout with all the detailed information on the progress of the rollout. +Specify the rollout by its name and resource group name. Alternately, you can provide the Rollout object or the ResourceId. + +The returned rollout object contains the services, service units and steps that have been deployed and the ones in progress. Those that are yet to be deployed are not in the response. + +## EXAMPLES + +### Example 1 Get the rollout +```powershell +PS C:\> Get-AzureRmDeploymentManagerRollout -ResourceGroupName ContosoResourceGroup -Name ContosoRollout +``` + +This command gets a rollout named ContosoRollout in the ContosoResourceGroup. + +### Example 2 Get and display the rollout details +```powershell +PS C:\> Get-AzureRmDeploymentManagerRollout -ResourceGroupName ContosoResourceGroup -Name ContosoRollout -Verbose +``` + +This command gets a rollout named ContosoRollout in the ContosoResourceGroup. +The -Verbose switch displays all the rollout details hierarchically; showing the Services, the ServiceUnits and the steps under each ServiceUnit and contextual information for each step for a holistic view of the rollout. + +### Example 3: Get a rollout using the resource identifier +```powershell +PS C:\> Get-AzureRmDeploymentManagerRollout -ResourceId "/subscriptions/subscriptionId/resourcegroups/ContosoResourceGroup/providers/Microsoft.DeploymentManager/rollouts/ContosoRollout" +``` + +This command gets a rollout named ContosoRollout in the ContosoResourceGroup. + +### Example 4: Get a rollout using the rollout object. +```powershell +PS C:\> Get-AzureRmDeploymentManagerRollout -Rollout $rolloutObject +``` + +This command gets a rollout whose name and ResourceGroup match the Name and ResourceGroupName properties of the $rolloutObject, respectively. + +## PARAMETERS + +### -DefaultProfile +The credentials, account, tenant, and subscription used for communication with Azure. + +```yaml +Type: Microsoft.Azure.Commands.Common.Authentication.Abstractions.IAzureContextContainer +Parameter Sets: (All) +Aliases: AzureRmContext, AzureCredential + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Name +The name of the rollout. + +```yaml +Type: System.String +Parameter Sets: Interactive +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -ResourceGroupName +The resource group. + +```yaml +Type: System.String +Parameter Sets: Interactive +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -ResourceId +The resource identifier. + +```yaml +Type: System.String +Parameter Sets: ResourceId +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -RetryAttempt +The retry attempt of the rollout. + +```yaml +Type: System.Nullable`1[System.Int32] +Parameter Sets: Interactive +Aliases: + +Required: False +Position: 2 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -Rollout +Rollout object. + +```yaml +Type: Microsoft.Azure.Commands.DeploymentManager.Models.PSRollout +Parameter Sets: InputObject +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### None + +## OUTPUTS + +### Microsoft.Azure.Commands.DeploymentManager.Models.PSRollout + +## NOTES + +## RELATED LINKS + +[Stop-AzureRmDeploymentManagerRollout](./Stop-AzureRmDeploymentManagerRollout.md) + +[Restart-AzureRmDeploymentManagerRollout](./Restart-AzureRmDeploymentManagerRollout.md) + +[Remove-AzureRmDeploymentManagerRollout](./Remove-AzureRmDeploymentManagerRollout.md) \ No newline at end of file diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerService.md b/src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerService.md new file mode 100644 index 000000000000..20c4556fdc85 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerService.md @@ -0,0 +1,215 @@ +--- +external help file: Microsoft.Azure.Commands.DeploymentManager.dll-Help.xml +Module Name: AzureRM.DeploymentManager +online version: +schema: 2.0.0 +--- + +# Get-AzureRmDeploymentManagerService + +## SYNOPSIS +Gets a service in a service topology. + +## SYNTAX + +### Interactive (Default) +``` +Get-AzureRmDeploymentManagerService [-ResourceGroupName] [-ServiceTopologyName] + [-Name] [-DefaultProfile ] [] +``` + +### ByServiceTopologyObject +``` +Get-AzureRmDeploymentManagerService [-ResourceGroupName] [-Name] + [-ServiceTopology] [-DefaultProfile ] [] +``` + +### ByServiceTopologyResourceId +``` +Get-AzureRmDeploymentManagerService [-ResourceGroupName] [-Name] + [-ServiceTopologyResourceId] [-DefaultProfile ] [] +``` + +### ResourceId +``` +Get-AzureRmDeploymentManagerService [-ResourceId] [-DefaultProfile ] + [] +``` + +### InputObject +``` +Get-AzureRmDeploymentManagerService [-Service] [-DefaultProfile ] + [] +``` + +## DESCRIPTION +The **Get-AzureRmDeploymentManagerService** cmdlet gets a service under a service topology, and returns an object that represents that service. +Specify the service by its name, service topology it is in and the resource group name. Alternately, you can provide the Service object or the ResourceId. + +You can modify this object locally, and then apply changes to the service by using the Set-AzureRmDeploymentManagerService cmdlet. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Get-AzureRmDeploymentManagerService -ResourceGroupName ContosoResourceGroup -ServiceTopologyName ContosoServiceTopology -Name ContosoService1 +``` + +This command gets a service named ContosoService1 in a service topology named ContosoServiceTopology in the ContosoResourceGroup. + +### Example 2: Get a service using the resource identifier. +```powershell +PS C:\> Get-AzureRmDeploymentManagerService -ResourceId "/subscriptions/subscriptionId/resourcegroups/ContosoResourceGroup/providers/Microsoft.DeploymentManager/serviceTopologies/ContosoServiceTopology/services/ContosoService1" +``` + +This command gets a service named ContosoService1 in a service topology named ContosoServiceTopology in the ContosoResourceGroup. + +### Example 3: Get a service using the service object. +```powershell +PS C:\> Get-AzureRmDeploymentManagerService -Service $serviceObject +``` + +This command gets a service whose name, service topology name and ResourceGroup match the Name, ServiceTopologyName and ResourceGroupName properties of the $serviceObject, respectively. + +## PARAMETERS + +### -DefaultProfile +The credentials, account, tenant, and subscription used for communication with Azure. + +```yaml +Type: Microsoft.Azure.Commands.Common.Authentication.Abstractions.IAzureContextContainer +Parameter Sets: (All) +Aliases: AzureRmContext, AzureCredential + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Name +The name of the service. + +```yaml +Type: System.String +Parameter Sets: Interactive, ByServiceTopologyObject, ByServiceTopologyResourceId +Aliases: + +Required: True +Position: 2 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -ResourceGroupName +The resource group. + +```yaml +Type: System.String +Parameter Sets: Interactive, ByServiceTopologyObject, ByServiceTopologyResourceId +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -ResourceId +The resource identifier. + +```yaml +Type: System.String +Parameter Sets: ResourceId +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -Service +Service object. + +```yaml +Type: Microsoft.Azure.Commands.DeploymentManager.Models.PSServiceResource +Parameter Sets: InputObject +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -ServiceTopology +The service topology object in which the service should be created. + +```yaml +Type: Microsoft.Azure.Commands.DeploymentManager.Models.PSServiceTopologyResource +Parameter Sets: ByServiceTopologyObject +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ServiceTopologyName +The name of the service topology. + +```yaml +Type: System.String +Parameter Sets: Interactive +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -ServiceTopologyResourceId +The service topology resource identifier in which the service should be created. + +```yaml +Type: System.String +Parameter Sets: ByServiceTopologyResourceId +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### None + +## OUTPUTS + +### Microsoft.Azure.Commands.DeploymentManager.Models.PSServiceResource + +## NOTES + +## RELATED LINKS + +[New-AzureRmDeploymentManagerService](./New-AzureRmDeploymentManagerService.md) + +[Remove-AzureRmDeploymentManagerService](./Remove-AzureRmDeploymentManagerService.md) + +[Set-AzureRmDeploymentManagerService](./Set-AzureRmDeploymentManagerService.md) \ No newline at end of file diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerServiceTopology.md b/src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerServiceTopology.md new file mode 100644 index 000000000000..047ff842b330 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerServiceTopology.md @@ -0,0 +1,158 @@ +--- +external help file: Microsoft.Azure.Commands.DeploymentManager.dll-Help.xml +Module Name: AzureRM.DeploymentManager +online version: +schema: 2.0.0 +--- + +# Get-AzureRmDeploymentManagerServiceTopology + +## SYNOPSIS +Gets a service topology. + +## SYNTAX + +### Interactive (Default) +``` +Get-AzureRmDeploymentManagerServiceTopology [-ResourceGroupName] [-Name] + [-DefaultProfile ] [] +``` + +### ResourceId +``` +Get-AzureRmDeploymentManagerServiceTopology [-ResourceId] [-DefaultProfile ] + [] +``` + +### InputObject +``` +Get-AzureRmDeploymentManagerServiceTopology [-ServiceTopology] + [-DefaultProfile ] [] +``` + +## DESCRIPTION +The **Get-AzureRmDeploymentManagerServiceTopology** cmdlet gets a service topology. + +You can modify this object locally, and then apply changes to the topology by using the Set-AzureRmDeploymentManagerServiceTopology cmdlet. +Specify the service topology by its name and the resource group name. Alternately, you can provide the ServiceTopology object or the ResourceId. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Get-AzureRmDeploymentManagerServiceTopology -ResourceGroupName ContosoResourceGroup -Name ContosoServiceTopology +``` + +This command gets a service topology named ContosoServiceTopology in the ContosoResourceGroup. + +### Example 2: Get a service topology using the resource identifier. +```powershell +PS C:\> Get-AzureRmDeploymentManagerServiceTopology -ResourceId "/subscriptions/subscriptionId/resourcegroups/ContosoResourceGroup/providers/Microsoft.DeploymentManager/serviceTopologies/ContosoServiceTopology" +``` + +This command gets a service topology named ContosoServiceTopology in the ContosoResourceGroup. + +### Example 3: Get a service topology using the service topology object. +```powershell +PS C:\> Get-AzureRmDeploymentManagerService -ServiceTopology $serviceTopologyObject +``` + +This command gets a service topology whose name and ResourceGroup match the Name and ResourceGroupName properties of the $serviceTopologyObject, respectively. + +## PARAMETERS + +### -DefaultProfile +The credentials, account, tenant, and subscription used for communication with Azure. + +```yaml +Type: Microsoft.Azure.Commands.Common.Authentication.Abstractions.IAzureContextContainer +Parameter Sets: (All) +Aliases: AzureRmContext, AzureCredential + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Name +The name of the service topology. + +```yaml +Type: System.String +Parameter Sets: Interactive +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -ResourceGroupName +The resource group. + +```yaml +Type: System.String +Parameter Sets: Interactive +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -ResourceId +The resource identifier. + +```yaml +Type: System.String +Parameter Sets: ResourceId +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -ServiceTopology +Service topology resource object. + +```yaml +Type: Microsoft.Azure.Commands.DeploymentManager.Models.PSServiceTopologyResource +Parameter Sets: InputObject +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### None + +## OUTPUTS + +### Microsoft.Azure.Commands.DeploymentManager.Models.PSServiceTopologyResource + +## NOTES + +## RELATED LINKS + +[New-AzureRmDeploymentManagerServiceTopology](./New-AzureRmDeploymentManagerServiceTopology.md) + +[Remove-AzureRmDeploymentManagerServiceTopology](./Remove-AzureRmDeploymentManagerServiceTopology.md) + +[Set-AzureRmDeploymentManagerServiceTopology](./Set-AzureRmDeploymentManagerServiceTopology.md) \ No newline at end of file diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerServiceUnit.md b/src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerServiceUnit.md new file mode 100644 index 000000000000..dafdb46d4113 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerServiceUnit.md @@ -0,0 +1,273 @@ +--- +external help file: Microsoft.Azure.Commands.DeploymentManager.dll-Help.xml +Module Name: AzureRM.DeploymentManager +online version: +schema: 2.0.0 +--- + +# Get-AzureRmDeploymentManagerServiceUnit + +## SYNOPSIS +Gets a service unit. + +## SYNTAX + +### Interactive (Default) +``` +Get-AzureRmDeploymentManagerServiceUnit [-ResourceGroupName] [-ServiceTopologyName] + [-ServiceName] [-Name] [-DefaultProfile ] [] +``` + +### ByServiceObject +``` +Get-AzureRmDeploymentManagerServiceUnit [-ResourceGroupName] [-Name] + [-Service] [-DefaultProfile ] [] +``` + +### ByServiceResourceId +``` +Get-AzureRmDeploymentManagerServiceUnit [-ResourceGroupName] [-Name] + [-ServiceResourceId] [-DefaultProfile ] [] +``` + +### ByTopologyObjectAndServiceName +``` +Get-AzureRmDeploymentManagerServiceUnit [-ResourceGroupName] [-ServiceName] [-Name] + [-ServiceTopology] [-DefaultProfile ] [] +``` + +### ByTopologyResourceAndServiceName +``` +Get-AzureRmDeploymentManagerServiceUnit [-ResourceGroupName] [-ServiceName] [-Name] + [-ServiceTopologyResourceId] [-DefaultProfile ] [] +``` + +### ResourceId +``` +Get-AzureRmDeploymentManagerServiceUnit [-ResourceId] [-DefaultProfile ] + [] +``` + +### InputObject +``` +Get-AzureRmDeploymentManagerServiceUnit [-ServiceUnit] + [-DefaultProfile ] [] +``` + +## DESCRIPTION +The **Get-AzureRmDeploymentManagerServiceUnit** cmdlet gets a service unit in a service. + +Specify the service unit by its name, the service under which it was defined, the service topology name and the resource group name. Alternately, you can provide the ServiceUnit object or the ResourceId. + +You can modify this object locally, and then apply changes to the service unit by using the Set-AzureRmDeploymentManagerServiceUnit cmdlet. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Get-AzureRmDeploymentManagerServiceUnit -ResourceGroupName ContosoResourceGroup -ServiceTopologyName ContosoServiceTopology -ServiceName ContosoService1 -Name ContosoService1Storage +``` + +This command gets a service unit named ContosoService1Storage under a service ContosoService1 in a service topology named ContosoServiceTopology in the ContosoResourceGroup. + +### Example 2: Get a service unit using the resource identifier. +```powershell +PS C:\> Get-AzureRmDeploymentManagerServiceUnit -ResourceId "/subscriptions/subscriptionId/resourcegroups/ContosoResourceGroup/providers/Microsoft.DeploymentManager/serviceTopologies/ContosoServiceTopology/services/ContosoService1/serviceUnits/ContosoService1Storage" +``` + +This command gets a service unit named ContosoService1Storage under a service ContosoService1 in a service topology named ContosoServiceTopology in the ContosoResourceGroup. + +### Example 3: Get a service unit using the service unit object. +```powershell +PS C:\> Get-AzureRmDeploymentManagerServiceUnit -ServiceUnit $serviceUnitObject +``` + +This command gets a service unit whose name, service name, service topology name and ResourceGroup match the Name, ServiceName, ServiceTopologyName and ResourceGroupName properties of the $serviceUnitObject, respectively. + +## PARAMETERS + +### -DefaultProfile +The credentials, account, tenant, and subscription used for communication with Azure. + +```yaml +Type: Microsoft.Azure.Commands.Common.Authentication.Abstractions.IAzureContextContainer +Parameter Sets: (All) +Aliases: AzureRmContext, AzureCredential + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Name +The name of the service unit. + +```yaml +Type: System.String +Parameter Sets: Interactive, ByServiceObject, ByServiceResourceId, ByTopologyObjectAndServiceName, ByTopologyResourceAndServiceName +Aliases: + +Required: True +Position: 3 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -ResourceGroupName +The resource group. + +```yaml +Type: System.String +Parameter Sets: Interactive, ByServiceObject, ByServiceResourceId, ByTopologyObjectAndServiceName, ByTopologyResourceAndServiceName +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -ResourceId +The resource identifier. + +```yaml +Type: System.String +Parameter Sets: ResourceId +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -Service +The service object in which the service unit should be created. + +```yaml +Type: Microsoft.Azure.Commands.DeploymentManager.Models.PSServiceResource +Parameter Sets: ByServiceObject +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ServiceName +The name of the service the service unit is part of. + +```yaml +Type: System.String +Parameter Sets: Interactive, ByTopologyObjectAndServiceName, ByTopologyResourceAndServiceName +Aliases: + +Required: True +Position: 2 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -ServiceResourceId +The service resource identifier in which the service unit should be created. + +```yaml +Type: System.String +Parameter Sets: ByServiceResourceId +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ServiceTopology +The service topology object in which the service unit should be created. + +```yaml +Type: Microsoft.Azure.Commands.DeploymentManager.Models.PSServiceTopologyResource +Parameter Sets: ByTopologyObjectAndServiceName +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ServiceTopologyName +The name of the service topology the service unit is part of. + +```yaml +Type: System.String +Parameter Sets: Interactive +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -ServiceTopologyResourceId +The service topology resource identifier in which the service unit should be created. + +```yaml +Type: System.String +Parameter Sets: ByTopologyResourceAndServiceName +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ServiceUnit +Service unit resource object. + +```yaml +Type: Microsoft.Azure.Commands.DeploymentManager.Models.PSServiceUnitResource +Parameter Sets: InputObject +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### None + +## OUTPUTS + +### Microsoft.Azure.Commands.DeploymentManager.Models.PSServiceUnitResource + +## NOTES + +## RELATED LINKS + +[New-AzureRmDeploymentManagerServiceUnit](./New-AzureRmDeploymentManagerServiceUnit.md) + +[Remove-AzureRmDeploymentManagerServiceUnit](./Remove-AzureRmDeploymentManagerServiceUnit.md) + +[Set-AzureRmDeploymentManagerServiceUnit](./Set-AzureRmDeploymentManagerServiceUnit.md) \ No newline at end of file diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerStep.md b/src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerStep.md new file mode 100644 index 000000000000..9cdd3d54ef92 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerStep.md @@ -0,0 +1,156 @@ +--- +external help file: Microsoft.Azure.Commands.DeploymentManager.dll-Help.xml +Module Name: AzureRM.DeploymentManager +online version: +schema: 2.0.0 +--- + +# Get-AzureRmDeploymentManagerStep + +## SYNOPSIS +Gets the deployment step. + +## SYNTAX + +### Interactive (Default) +``` +Get-AzureRmDeploymentManagerStep [-ResourceGroupName] [-Name] + [-DefaultProfile ] [] +``` + +### ResourceId +``` +Get-AzureRmDeploymentManagerStep [-ResourceId] [-DefaultProfile ] + [] +``` + +### InputObject +``` +Get-AzureRmDeploymentManagerStep [-Step] [-DefaultProfile ] + [] +``` + +## DESCRIPTION +The **Get-AzureRmDeploymentManagerStep** cmdlet gets a step, and returns an object that represents that step. +Specify the step by its name and resource group name. Alternately, you can provide the Step object or the ResourceId. + +You can modify this object locally, and then apply changes to the artifact source by using the Set-AzureRmDeploymentManagerStep cmdlet. + +## EXAMPLES + +### Example 1: Get a step +```powershell +PS C:\> New-AzureRmDeploymentManagerStep -ResourceGroupName ContosoResourceGroup -Name ContosoService1WaitStep +``` + +This command gets a step named ContosoService1WaitStep in ContosoResourceGroup. + +### Example 2: Get a step using the resource identifier +```powershell +PS C:\> Get-AzureRmDeploymentManagerStep -ResourceId "/subscriptions/subscriptionId/resourcegroups/ContosoResourceGroup/providers/Microsoft.DeploymentManager/steps/ContosoService1WaitStep" +``` + +This command gets a step named ContosoService1WaitStep in ContosoResourceGroup. + +### Example 3: Get a step using an object returned by New-AzureRmDeploymentManagerStep +```powershell +PS C:\> Get-AzureRmDeploymentManagerStep -Step $stepObject +``` + + This command gets a step whose name and ResourceGroup match the Name and ResourceGroupName properties of the $stepObject, respectively. + + +## PARAMETERS + +### -DefaultProfile +The credentials, account, tenant, and subscription used for communication with Azure. + +```yaml +Type: Microsoft.Azure.Commands.Common.Authentication.Abstractions.IAzureContextContainer +Parameter Sets: (All) +Aliases: AzureRmContext, AzureCredential + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Name +The name of the step. + +```yaml +Type: System.String +Parameter Sets: Interactive +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -ResourceGroupName +The resource group. + +```yaml +Type: System.String +Parameter Sets: Interactive +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -ResourceId +The resource identifier. + +```yaml +Type: System.String +Parameter Sets: ResourceId +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -Step +The step resource object. + +```yaml +Type: Microsoft.Azure.Commands.DeploymentManager.Models.PSStepResource +Parameter Sets: InputObject +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. +For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### System.String + +### Microsoft.Azure.Commands.DeploymentManager.Models.PSStepResource + +## OUTPUTS + +### Microsoft.Azure.Commands.DeploymentManager.Models.PSStepResource + +## NOTES + +## RELATED LINKS diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Microsoft.Azure.Commands.DeploymentManager.md b/src/DeploymentManager/Commands.DeploymentManager/help/Microsoft.Azure.Commands.DeploymentManager.md new file mode 100644 index 000000000000..e787e354cfac --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/help/Microsoft.Azure.Commands.DeploymentManager.md @@ -0,0 +1,72 @@ +--- +Module Name: Microsoft.Azure.Commands.DeploymentManager +Module Guid: {{ Update Module Guid }} +Download Help Link: {{ Update Download Link }} +Help Version: {{ Update Help Version }} +Locale: {{ Update Locale }} +--- + +# Microsoft.Azure.Commands.DeploymentManager Module +## Description +{{Manually Enter Description Here}} + +## Microsoft.Azure.Commands.DeploymentManager Cmdlets +### [Get-AzureRmDeploymentManagerArtifactSource](Get-AzureRmDeploymentManagerArtifactSource.md) +Gets an artifact source. + +### [Get-AzureRmDeploymentManagerRollout](Get-AzureRmDeploymentManagerRollout.md) +Gets a rollout. + +### [Get-AzureRmDeploymentManagerService](Get-AzureRmDeploymentManagerService.md) +Gets a service in a service topology. + +### [Get-AzureRmDeploymentManagerServiceTopology](Get-AzureRmDeploymentManagerServiceTopology.md) +Gets a service topology. + +### [Get-AzureRmDeploymentManagerServiceUnit](Get-AzureRmDeploymentManagerServiceUnit.md) +Gets a service unit in a service. + +### [New-AzureRmDeploymentManagerArtifactSource](New-AzureRmDeploymentManagerArtifactSource.md) +Creates a new artifact source. + +### [New-AzureRmDeploymentManagerService](New-AzureRmDeploymentManagerService.md) +Creates a new service in a service topology. + +### [New-AzureRmDeploymentManagerServiceTopology](New-AzureRmDeploymentManagerServiceTopology.md) +Creates a new service topology. + +### [New-AzureRmDeploymentManagerServiceUnit](New-AzureRmDeploymentManagerServiceUnit.md) +Creates a new service unit in a service. + +### [Remove-AzureRmDeploymentManagerArtifactSource](Remove-AzureRmDeploymentManagerArtifactSource.md) +Deletes an artifact source. + +### [Remove-AzureRmDeploymentManagerRollout](Remove-AzureRmDeploymentManagerRollout.md) +Deletes a rollout. + +### [Remove-AzureRmDeploymentManagerService](Remove-AzureRmDeploymentManagerService.md) +Deletes a service in a service topology. + +### [Remove-AzureRmDeploymentManagerServiceTopology](Remove-AzureRmDeploymentManagerServiceTopology.md) +Deletes a service topology. + +### [Remove-AzureRmDeploymentManagerServiceUnit](Remove-AzureRmDeploymentManagerServiceUnit.md) +Deletes a service unit in a service. + +### [Restart-AzureRmDeploymentManagerRollout](Restart-AzureRmDeploymentManagerRollout.md) +Restarts a failed rollout. + +### [Set-AzureRmDeploymentManagerArtifactSource](Set-AzureRmDeploymentManagerArtifactSource.md) +Updates an artifact source. + +### [Set-AzureRmDeploymentManagerService](Set-AzureRmDeploymentManagerService.md) +Updates a service in a topology. + +### [Set-AzureRmDeploymentManagerServiceTopology](Set-AzureRmDeploymentManagerServiceTopology.md) +Updates a service topology. + +### [Set-AzureRmDeploymentManagerServiceUnit](Set-AzureRmDeploymentManagerServiceUnit.md) +Updates a service unit in a service. + +### [Stop-AzureRmDeploymentManagerRollout](Stop-AzureRmDeploymentManagerRollout.md) +Stops a rollout in progress. diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/New-AzureRmDeploymentManagerArtifactSource.md b/src/DeploymentManager/Commands.DeploymentManager/help/New-AzureRmDeploymentManagerArtifactSource.md new file mode 100644 index 000000000000..d11261b74c43 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/help/New-AzureRmDeploymentManagerArtifactSource.md @@ -0,0 +1,194 @@ +--- +external help file: Microsoft.Azure.Commands.DeploymentManager.dll-Help.xml +Module Name: AzureRM.DeploymentManager +online version: +schema: 2.0.0 +--- + +# New-AzureRmDeploymentManagerArtifactSource + +## SYNOPSIS +Creates an artifact source. + +## SYNTAX + +``` +New-AzureRmDeploymentManagerArtifactSource -ResourceGroupName -Name -Location + -SasUri [-Tag ] [-ArtifactRoot ] [-DefaultProfile ] + [-WhatIf] [-Confirm] [] +``` + +## DESCRIPTION +The **New-AzureRmDeploymentManagerArtifactSource** cmdlet creates an artifact source. +Specify the *Name*, *ResourceGroupName* and required properties. + +You can modify the returned object locally and then apply the changes to the artifact source by using the Set-AzureRmDeploymentManagerArtifactSource cmdlet. + +The cmdlet returns an ArtifactSource object that has a ResourceId which can be referenced in the New-AzureRmDeloymentManagerServiceTopology cmdlet so that artifacts required for a ServiceUnit resource, the Template and Parameters files, can be referenced from this location. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> New-AzureRmDeploymentManagerArtifactSource -ResourceGroupName ContosoResourceGroup -Name ContosoArtifactSource -Location "Central US" -SasUri "https://ContosoStorage.blob.core.windows.net/ContosoArtifacts?sasParameters" +``` + +Creates an artifact source in the ContosoResourceGroup with the name ContosoArtifactSource with Central US as the location of the resource. The SasUri property provides an Azure Storage SAS Uri to the storage container where the artifacts are stored. + +## PARAMETERS + +### -ArtifactRoot +The optional directory offset under the storage container for the artifacts. + +```yaml +Type: System.String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -DefaultProfile +The credentials, account, tenant, and subscription used for communication with Azure. + +```yaml +Type: Microsoft.Azure.Commands.Common.Authentication.Abstractions.IAzureContextContainer +Parameter Sets: (All) +Aliases: AzureRmContext, AzureCredential + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Location +The location of the resource. + +```yaml +Type: System.String +Parameter Sets: (All) +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Name +The name of the artifact source. + +```yaml +Type: System.String +Parameter Sets: (All) +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ResourceGroupName +The resource group. + +```yaml +Type: System.String +Parameter Sets: (All) +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -SasUri +The SAS Uri to the Azure storage container where the artifacts are stored. + +```yaml +Type: System.String +Parameter Sets: (All) +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Tag +A hash table which represents resource tags. + +```yaml +Type: System.Collections.Hashtable +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -Confirm +Prompts you for confirmation before running the cmdlet. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: cf + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WhatIf +Shows what would happen if the cmdlet runs. The cmdlet is not run. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: wi + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### None + +## OUTPUTS + +### Microsoft.Azure.Commands.DeploymentManager.Models.PSArtifactSource + +## NOTES + +## RELATED LINKS + +[Get-AzureRmDeploymentManagerArtifactSource](./Get-AzureRmDeploymentManagerArtifactSource.md) + +[Remove-AzureRmDeploymentManagerArtifactSource](./Remove-AzureRmDeploymentManagerArtifactSource.md) + +[Set-AzureRmDeploymentManagerArtifactSource](./Set-AzureRmDeploymentManagerArtifactSource.md) \ No newline at end of file diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/New-AzureRmDeploymentManagerService.md b/src/DeploymentManager/Commands.DeploymentManager/help/New-AzureRmDeploymentManagerService.md new file mode 100644 index 000000000000..2cc98fe3b15b --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/help/New-AzureRmDeploymentManagerService.md @@ -0,0 +1,252 @@ +--- +external help file: Microsoft.Azure.Commands.DeploymentManager.dll-Help.xml +Module Name: AzureRM.DeploymentManager +online version: +schema: 2.0.0 +--- + +# New-AzureRmDeploymentManagerService + +## SYNOPSIS +Creates a service in a service topology. + +## SYNTAX + +### Interactive (Default) +``` +New-AzureRmDeploymentManagerService [-ResourceGroupName] [-ServiceTopologyName] + -Name -Location -TargetLocation -TargetSubscriptionId [-Tag ] + [-DefaultProfile ] [-WhatIf] [-Confirm] [] +``` + +### ByServiceTopologyObject +``` +New-AzureRmDeploymentManagerService [-ResourceGroupName] -Name -Location + -TargetLocation -TargetSubscriptionId [-ServiceTopology] + [-Tag ] [-DefaultProfile ] [-WhatIf] [-Confirm] [] +``` + +### ByServiceTopologyResourceId +``` +New-AzureRmDeploymentManagerService [-ResourceGroupName] -Name -Location + -TargetLocation -TargetSubscriptionId [-ServiceTopologyId] [-Tag ] + [-DefaultProfile ] [-WhatIf] [-Confirm] [] +``` + +## DESCRIPTION +The **New-AzureRmDeploymentManagerService** cmdlet creates a service under a service topology, and returns an object that represents that service. +Specify the service by its name, service topology it is in and the resource group name. + +The cmdlet returns a Service object. You can modify this object locally, and then apply changes to the service by using the Set-AzureRmDeploymentManagerService cmdlet. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> New-AzureRmDeploymentManagerService -ResourceGroupName ContosoResourceGroup -ServiceTopologyName ContosoServiceTopology -Name ContosoService1 -Location "Central US" -TargetLocation "East US" -TargetSubscriptionId XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX +``` + +Creates a new service with name ContosoService1 under service topology ContosoServiceTopology in Resource Group ContosoResourceGroup, in the location Central US. The TargetLocation property indicates that the service ContosoService1 should be deployed to the East US region in the subscription specified. + +## PARAMETERS + +### -DefaultProfile +The credentials, account, tenant, and subscription used for communication with Azure. + +```yaml +Type: Microsoft.Azure.Commands.Common.Authentication.Abstractions.IAzureContextContainer +Parameter Sets: (All) +Aliases: AzureRmContext, AzureCredential + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Location +The location of the service resource. + +```yaml +Type: System.String +Parameter Sets: (All) +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Name +The name of the service. + +```yaml +Type: System.String +Parameter Sets: (All) +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ResourceGroupName +The resource group. + +```yaml +Type: System.String +Parameter Sets: (All) +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ServiceTopology +The service topology object in which the service should be created. + +```yaml +Type: Microsoft.Azure.Commands.DeploymentManager.Models.PSServiceTopologyResource +Parameter Sets: ByServiceTopologyObject +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ServiceTopologyId +The service topology resource identifier in which the service should be created. + +```yaml +Type: System.String +Parameter Sets: ByServiceTopologyResourceId +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ServiceTopologyName +The name of the service topology this service belongs to. + +```yaml +Type: System.String +Parameter Sets: Interactive +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Tag +A hash table which represents resource tags. + +```yaml +Type: System.Collections.Hashtable +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -TargetLocation +Determines the location where resources under the service would be deployed to. + +```yaml +Type: System.String +Parameter Sets: (All) +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -TargetSubscriptionId +Determines the subscription to which resources under the service would be deployed to. + +```yaml +Type: System.String +Parameter Sets: (All) +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Confirm +Prompts you for confirmation before running the cmdlet. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: cf + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WhatIf +Shows what would happen if the cmdlet runs. The cmdlet is not run. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: wi + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### None + +## OUTPUTS + +### Microsoft.Azure.Commands.DeploymentManager.Models.PSServiceResource + +## NOTES + +## RELATED LINKS + +[Get-AzureRmDeploymentManagerService](./Get-AzureRmDeploymentManagerService.md) + +[Remove-AzureRmDeploymentManagerService](./Remove-AzureRmDeploymentManagerService.md) + +[Set-AzureRmDeploymentManagerService](./Set-AzureRmDeploymentManagerService.md) \ No newline at end of file diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/New-AzureRmDeploymentManagerServiceTopology.md b/src/DeploymentManager/Commands.DeploymentManager/help/New-AzureRmDeploymentManagerServiceTopology.md new file mode 100644 index 000000000000..49d35421eb51 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/help/New-AzureRmDeploymentManagerServiceTopology.md @@ -0,0 +1,186 @@ +--- +external help file: Microsoft.Azure.Commands.DeploymentManager.dll-Help.xml +Module Name: AzureRM.DeploymentManager +online version: +schema: 2.0.0 +--- + +# New-AzureRmDeploymentManagerServiceTopology + +## SYNOPSIS +Creates a new service topology. + +## SYNTAX + +``` +New-AzureRmDeploymentManagerServiceTopology -ResourceGroupName -Name -Location + [-ArtifactSourceId ] [-Tag ] [-DefaultProfile ] [-WhatIf] + [-Confirm] [] +``` + +## DESCRIPTION +The **New-AzureRmDeploymentManagerServiceTopology** cmdlet creates a service topology. + +You can modify the returned ServiceTopology object locally, and then apply changes to the topology by using the Set-AzureRmDeploymentManagerServiceTopology cmdlet. +The returned object + +The returned object has a ResourceId field which can be referenced in a rollout resource to indicate that the services declared in this service topology would be deployed in the rollout. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> New-AzureRmDeploymentManagerServiceTopology -ResourceGroupName ContosoResourceGroup -Name ContosoServiceTopology -Location "Central US" -ArtifactSourceId "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/resourcegroups/ContosoResourceGroup/providers/Microsoft.DeploymentManager/artifactSources/ContosoArtifactSource" +``` + +This cmdlet creates a new service topology in the resource group ContosoResourceGroup with the name ContosoServiceTopology and in location Central US. The artifact source ResourceId indicates that the artifacts required for the service unit definitions in this topology need to be read from the specified artifact source. + +### Example 2 +```powershell +PS C:\> New-AzureRmDeploymentManagerServiceTopology -ResourceGroupName ContosoResourceGroup -Name ContosoServiceTopology -Location "Central US" +``` + +This cmdlet creates a new service topology in the resource group ContosoResourceGroup with the name ContosoServiceTopology and in location Central US. The absence of an artifact source reference indicates that the artifacts required for the service unit definitions in this topology would be provided as absolute SAS URIs in the service unit. + +## PARAMETERS + +### -ArtifactSourceId +The identifier of the artifact source, where the artifacts that make up the topology are stored. + +```yaml +Type: System.String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -DefaultProfile +The credentials, account, tenant, and subscription used for communication with Azure. + +```yaml +Type: Microsoft.Azure.Commands.Common.Authentication.Abstractions.IAzureContextContainer +Parameter Sets: (All) +Aliases: AzureRmContext, AzureCredential + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Location +The location of the topology. + +```yaml +Type: System.String +Parameter Sets: (All) +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Name +The name of the topology. + +```yaml +Type: System.String +Parameter Sets: (All) +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ResourceGroupName +The resource group. + +```yaml +Type: System.String +Parameter Sets: (All) +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Tag +A hash table which represents resource tags. + +```yaml +Type: System.Collections.Hashtable +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -Confirm +Prompts you for confirmation before running the cmdlet. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: cf + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WhatIf +Shows what would happen if the cmdlet runs. The cmdlet is not run. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: wi + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### None + +## OUTPUTS + +### Microsoft.Azure.Commands.DeploymentManager.Models.PSServiceTopologyResource + +## NOTES + +## RELATED LINKS + +[Get-AzureRmDeploymentManagerServiceTopology](./Get-AzureRmDeploymentManagerServiceTopology.md) + +[Remove-AzureRmDeploymentManagerServiceTopology](./Remove-AzureRmDeploymentManagerServiceTopology.md) + +[Set-AzureRmDeploymentManagerServiceTopology](./Set-AzureRmDeploymentManagerServiceTopology.md) \ No newline at end of file diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/New-AzureRmDeploymentManagerServiceUnit.md b/src/DeploymentManager/Commands.DeploymentManager/help/New-AzureRmDeploymentManagerServiceUnit.md new file mode 100644 index 000000000000..cc022aa0cf62 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/help/New-AzureRmDeploymentManagerServiceUnit.md @@ -0,0 +1,406 @@ +--- +external help file: Microsoft.Azure.Commands.DeploymentManager.dll-Help.xml +Module Name: AzureRM.DeploymentManager +online version: +schema: 2.0.0 +--- + +# New-AzureRmDeploymentManagerServiceUnit + +## SYNOPSIS +Creates a new service unit under a service in a service topology. + +## SYNTAX + +### ByTopologyAndServiceNames (Default) +``` +New-AzureRmDeploymentManagerServiceUnit [-ResourceGroupName] [-ServiceTopologyName] + [-ServiceName] [-Name] -Location -TargetResourceGroup + -DeploymentMode [-ParametersUri ] [-TemplateUri ] + [-TemplateArtifactSourceRelativePath ] [-ParametersArtifactSourceRelativePath ] + [-Tag ] [-AsJob] [-DefaultProfile ] [-WhatIf] [-Confirm] + [] +``` + +### ByTopologyObjectAndServiceName +``` +New-AzureRmDeploymentManagerServiceUnit [-ResourceGroupName] [-ServiceName] [-Name] + -Location -TargetResourceGroup -DeploymentMode [-ParametersUri ] + [-TemplateUri ] [-TemplateArtifactSourceRelativePath ] + [-ParametersArtifactSourceRelativePath ] [-Tag ] + [-ServiceTopology] [-AsJob] [-DefaultProfile ] [-WhatIf] + [-Confirm] [] +``` + +### ByTopologyResourceAndServiceName +``` +New-AzureRmDeploymentManagerServiceUnit [-ResourceGroupName] [-ServiceName] [-Name] + -Location -TargetResourceGroup -DeploymentMode [-ParametersUri ] + [-TemplateUri ] [-TemplateArtifactSourceRelativePath ] + [-ParametersArtifactSourceRelativePath ] [-Tag ] [-ServiceTopologyResourceId] + [-AsJob] [-DefaultProfile ] [-WhatIf] [-Confirm] [] +``` + +### ByServiceObject +``` +New-AzureRmDeploymentManagerServiceUnit [-ResourceGroupName] [-Name] -Location + -TargetResourceGroup -DeploymentMode [-ParametersUri ] [-TemplateUri ] + [-TemplateArtifactSourceRelativePath ] [-ParametersArtifactSourceRelativePath ] + [-Tag ] [-Service] [-AsJob] [-DefaultProfile ] + [-WhatIf] [-Confirm] [] +``` + +### ByServiceResourceId +``` +New-AzureRmDeploymentManagerServiceUnit [-ResourceGroupName] [-Name] -Location + -TargetResourceGroup -DeploymentMode [-ParametersUri ] [-TemplateUri ] + [-TemplateArtifactSourceRelativePath ] [-ParametersArtifactSourceRelativePath ] + [-Tag ] [-ServiceResourceId] [-AsJob] [-DefaultProfile ] [-WhatIf] + [-Confirm] [] +``` + +## DESCRIPTION +The **New-AzureRmDeploymentManagerServiceUnit** cmdlet creates a service under a service in a service topology, and returns an object that represents that service unit. +Specify the service unit by its name, service name, service topology it is in and the resource group name. + +The cmdlet returns a ServiceUnit object. You can modify this object locally, and then apply changes to the service by using the Set-AzureRmDeploymentManagerService cmdlet. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> New-AzureRmDeploymentManagerServiceUnit -ResourceGroupName ContosoResourceGroup -ServiceTopologyName ContosoServiceTopology -ServiceName ContosoService2 -Name ContosoService2Storage -Location "Central US" -TargetResourceGroup service2ResourceGroup -DeploymentMode Incremental -TemplateArtifactSourceRelativePath "Templates/Service2.Storage.json" -ParametersArtifactSourceRelativePath "Parameters/Service2Storage.Parameters.json" +``` + +This cmdlet creates a new service unit with name ContosoService2Storage in the ContosoResourceGroup under the service ContosoService2 in topology ContosoServiceTopology, in the location Central US. The Template and parameters files are defined as relative paths into the artifact source location referenced in the Service Topology ContosoServiceTopology. The resources defined in this template are to be deployed into the target resource group service2ResourceGroup with the deployment mode set to Incremental. + +### Example 2 +```powershell +PS C:\> New-AzureRmDeploymentManagerServiceUnit -ResourceGroupName ContosoResourceGroup -ServiceTopologyName ContosoServiceTopology1 -ServiceName ContosoService2 -Name ContosoService2Storage -Location "Central US" -TargetResourceGroup service2ResourceGroup -DeploymentMode Complete -TemplateUri "https://ContosoStorage.blob.core.windows.net/ContosoArtifacts/Templates/Service2.Storage.json?sasParameters" -ParametersUri "https://ContosoStorage.blob.core.windows.net/ContosoArtifacts/Parameters/Service2Storage.Parameters.json?sasParameters" +``` + +This cmdlet creates a new service unit with name ContosoService2Storage in the ContosoResourceGroup under the service ContosoService2 in topology ContosoServiceTopology, in the location Central US. The Template and parameters references are provided as SAS Uri's as artifact source ResourceId was not provided in the Service Topology ContosoServiceTopology1. The resources defined in this template are to be deployed into the target resource group service2ResourceGroup with the deployment mode set to Complete. + +## PARAMETERS + +### -AsJob +Run cmdlet in the background + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -DefaultProfile +The credentials, account, tenant, and subscription used for communication with Azure. + +```yaml +Type: Microsoft.Azure.Commands.Common.Authentication.Abstractions.IAzureContextContainer +Parameter Sets: (All) +Aliases: AzureRmContext, AzureCredential + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -DeploymentMode +The deployment mode to use when deploying the resources in the service unit. + +```yaml +Type: System.String +Parameter Sets: (All) +Aliases: +Accepted values: Incremental, Complete + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Location +The location of the service unit resource. + +```yaml +Type: System.String +Parameter Sets: (All) +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Name +The name of the service unit. + +```yaml +Type: System.String +Parameter Sets: (All) +Aliases: + +Required: True +Position: 3 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ParametersArtifactSourceRelativePath +The deployment mode to use when deploying the resources in the service unit. + +```yaml +Type: System.String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ParametersUri +The deployment mode to use when deploying the resources in the service unit. + +```yaml +Type: System.String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ResourceGroupName +The resource group. + +```yaml +Type: System.String +Parameter Sets: (All) +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Service +The service object in which the service unit should be created. + +```yaml +Type: Microsoft.Azure.Commands.DeploymentManager.Models.PSServiceResource +Parameter Sets: ByServiceObject +Aliases: + +Required: True +Position: 2 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ServiceName +The name of the service this service unit is a part of. + +```yaml +Type: System.String +Parameter Sets: ByTopologyAndServiceNames, ByTopologyObjectAndServiceName, ByTopologyResourceAndServiceName +Aliases: + +Required: True +Position: 2 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ServiceResourceId +The service resource identifier in which the service unit should be created. + +```yaml +Type: System.String +Parameter Sets: ByServiceResourceId +Aliases: + +Required: True +Position: 2 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ServiceTopology +The service topology object in which the service unit should be created. + +```yaml +Type: Microsoft.Azure.Commands.DeploymentManager.Models.PSServiceTopologyResource +Parameter Sets: ByTopologyObjectAndServiceName +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ServiceTopologyName +The name of the serivce topology this service unit is a part of. + +```yaml +Type: System.String +Parameter Sets: ByTopologyAndServiceNames +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ServiceTopologyResourceId +The service topology resource identifier in which the service unit should be created. + +```yaml +Type: System.String +Parameter Sets: ByTopologyResourceAndServiceName +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Tag +A hash table which represents resource tags. + +```yaml +Type: System.Collections.Hashtable +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -TargetResourceGroup +Determines the location where resources under the service unit would be deployed to. + +```yaml +Type: System.String +Parameter Sets: (All) +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -TemplateArtifactSourceRelativePath +The deployment mode to use when deploying the resources in the service unit. + +```yaml +Type: System.String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -TemplateUri +The deployment mode to use when deploying the resources in the service unit. + +```yaml +Type: System.String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Confirm +Prompts you for confirmation before running the cmdlet. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: cf + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WhatIf +Shows what would happen if the cmdlet runs. The cmdlet is not run. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: wi + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### None + +## OUTPUTS + +### Microsoft.Azure.Commands.DeploymentManager.Models.PSServiceUnitResource + +## NOTES + +## RELATED LINKS + +[Get-AzureRmDeploymentManagerServiceUnit](./Get-AzureRmDeploymentManagerServiceUnit.md) + +[Remove-AzureRmDeploymentManagerServiceUnit](./Remove-AzureRmDeploymentManagerServiceUnit.md) + +[Set-AzureRmDeploymentManagerServiceUnit](./Set-AzureRmDeploymentManagerServiceUnit.md) \ No newline at end of file diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/New-AzureRmDeploymentManagerStep.md b/src/DeploymentManager/Commands.DeploymentManager/help/New-AzureRmDeploymentManagerStep.md new file mode 100644 index 000000000000..77bc29ff4acc --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/help/New-AzureRmDeploymentManagerStep.md @@ -0,0 +1,174 @@ +--- +external help file: Microsoft.Azure.Commands.DeploymentManager.dll-Help.xml +Module Name: AzureRM.DeploymentManager +online version: +schema: 2.0.0 +--- + +# New-AzureRmDeploymentManagerStep + +## SYNOPSIS +Creates a new deployment step. + +## SYNTAX + +``` +New-AzureRmDeploymentManagerStep -ResourceGroupName -Name -Location + -Duration [-Tag ] [-DefaultProfile ] [-WhatIf] [-Confirm] + [] +``` + +## DESCRIPTION +The **New-AzureRmDeploymentManagerStep** cmdlet creates a deployment step that can be referenced in rollouts. +Specify the *Name*, *ResourceGroupName* and required properties. + +You can modify the returned object locally and then apply the changes to the step by using the Set-AzureRmDeploymentManagerStep cmdlet. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> New-AzureRmDeploymentManagerStep -ResourceGroupName ContosoResourceGroup -Name ContosoService1WaitStep -Location "Central US" -Duration PT20M +``` + +Creates a step in the ContosoResourceGroup with the name ContosoService1WaitStep with Central US as the location of the resource. The Duration property provides the duration the rollout will wait before running the next step. + +## PARAMETERS + +### -DefaultProfile +The credentials, account, tenant, and subscription used for communication with Azure. + +```yaml +Type: Microsoft.Azure.Commands.Common.Authentication.Abstractions.IAzureContextContainer +Parameter Sets: (All) +Aliases: AzureRmContext, AzureCredential + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Duration +The duration to wait in ISO 8601 format. +E.g.: PT30M, PT1H + +```yaml +Type: System.String +Parameter Sets: (All) +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Location +The location of the resource. + +```yaml +Type: System.String +Parameter Sets: (All) +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Name +The name of the step. + +```yaml +Type: System.String +Parameter Sets: (All) +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ResourceGroupName +The resource group. + +```yaml +Type: System.String +Parameter Sets: (All) +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Tag +A hash table which represents resource tags. + +```yaml +Type: System.Collections.Hashtable +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -Confirm +Prompts you for confirmation before running the cmdlet. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: cf + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WhatIf +Shows what would happen if the cmdlet runs. +The cmdlet is not run. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: wi + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. +For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### System.Collections.Hashtable + +## OUTPUTS + +### Microsoft.Azure.Commands.DeploymentManager.Models.PSStepResource + +## NOTES + +## RELATED LINKS diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerArtifactSource.md b/src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerArtifactSource.md new file mode 100644 index 000000000000..770c8d2b000f --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerArtifactSource.md @@ -0,0 +1,217 @@ +--- +external help file: Microsoft.Azure.Commands.DeploymentManager.dll-Help.xml +Module Name: AzureRM.DeploymentManager +online version: +schema: 2.0.0 +--- + +# Remove-AzureRmDeploymentManagerArtifactSource + +## SYNOPSIS +Deletes an artifact source. + +## SYNTAX + +### Interactive (Default) +``` +Remove-AzureRmDeploymentManagerArtifactSource [-ResourceGroupName] [-Name] [-Force] + [-PassThru] [-DefaultProfile ] [-WhatIf] [-Confirm] [] +``` + +### ResourceId +``` +Remove-AzureRmDeploymentManagerArtifactSource [-ResourceId] [-Force] [-PassThru] + [-DefaultProfile ] [-WhatIf] [-Confirm] [] +``` + +### InputObject +``` +Remove-AzureRmDeploymentManagerArtifactSource [-ArtifactSource] [-Force] [-PassThru] + [-DefaultProfile ] [-WhatIf] [-Confirm] [] +``` + +## DESCRIPTION +The **Remove-AzureRmDeploymentManagerArtifactSource** cmdlet deletes an artifact source +Specify the artifact source by its name and resource group name. Alternately, you can provide the ArtifactSource object or the ResourceId. + +## EXAMPLES + +### Example 1: Delete an artifact source +```powershell +PS C:\> Remove-AzureRmDeploymentManagerArtifactSource -ResourceGroupName "ContosoResourceGroup" -Name "ContosoArtifactSource" +``` + +This command deletes an artifact source named ContosoArtifactSource in ContosoResourceGroup. + +### Example 2: Delete an artifact source using the resource identifier +```powershell +PS C:\> Remove-AzureRmDeploymentManagerArtifactSource -ResourceId "/subscriptions/subscriptionId/resourcegroups/ContosoResourceGroup/providers/Microsoft.DeploymentManager/artifactSources/ContosoArtifactSource" +``` + +This command deletes an artifact source named ContosoArtifactSource in ContosoResourceGroup. + +### Example 3: Delete an artifact source using an object +```powershell +PS C:\> Remove-AzureRmDeploymentManagerArtifactSource -ArtifactSource $artifactSourceObject +``` + +This command deletes an artifact source whose name and ResourceGroup match the Name and ResourceGroupName properties of the $artifactSourceObject, respectively. + +## PARAMETERS + +### -ArtifactSource +The artifact store to be removed. + +```yaml +Type: Microsoft.Azure.Commands.DeploymentManager.Models.PSArtifactSource +Parameter Sets: InputObject +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -DefaultProfile +The credentials, account, tenant, and subscription used for communication with Azure. + +```yaml +Type: Microsoft.Azure.Commands.Common.Authentication.Abstractions.IAzureContextContainer +Parameter Sets: (All) +Aliases: AzureRmContext, AzureCredential + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Force +Do not ask for confirmation. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Name +The name of the artifact source. + +```yaml +Type: System.String +Parameter Sets: Interactive +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -PassThru +{{Fill PassThru Description}} + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ResourceGroupName +The resource group. + +```yaml +Type: System.String +Parameter Sets: Interactive +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -ResourceId +The resource identifier. + +```yaml +Type: System.String +Parameter Sets: ResourceId +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -Confirm +Prompts you for confirmation before running the cmdlet. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: cf + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WhatIf +Shows what would happen if the cmdlet runs. +The cmdlet is not run. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: wi + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### Microsoft.Azure.Commands.DeploymentManager.Models.PSArtifactSource + +## OUTPUTS + +### System.Boolean + +## NOTES + +## RELATED LINKS + +[New-AzureRmDeploymentManagerArtifactSource](./New-AzureRmDeploymentManagerArtifactSource.md) + +[Get-AzureRmDeploymentManagerArtifactSource](./Get-AzureRmDeploymentManagerArtifactSource.md) + +[Set-AzureRmDeploymentManagerArtifactSource](./Set-AzureRmDeploymentManagerArtifactSource.md) \ No newline at end of file diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerRollout.md b/src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerRollout.md new file mode 100644 index 000000000000..2ebe94a199bd --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerRollout.md @@ -0,0 +1,217 @@ +--- +external help file: Microsoft.Azure.Commands.DeploymentManager.dll-Help.xml +Module Name: AzureRM.DeploymentManager +online version: +schema: 2.0.0 +--- + +# Remove-AzureRmDeploymentManagerRollout + +## SYNOPSIS +Deletes a rollout. + +## SYNTAX + +### Interactive (Default) +``` +Remove-AzureRmDeploymentManagerRollout [-ResourceGroupName] [-Name] [-Force] [-PassThru] + [-DefaultProfile ] [-WhatIf] [-Confirm] [] +``` + +### ResourceId +``` +Remove-AzureRmDeploymentManagerRollout [-ResourceId] [-Force] [-PassThru] + [-DefaultProfile ] [-WhatIf] [-Confirm] [] +``` + +### InputObject +``` +Remove-AzureRmDeploymentManagerRollout [-Rollout] [-Force] [-PassThru] + [-DefaultProfile ] [-WhatIf] [-Confirm] [] +``` + +## DESCRIPTION +The **Remove-AzureRmDeploymentManagerRollout** cmdlet deletes a rollout in a terminal state. +Specify the rollout by its name and resource group name. Alternately, you can provide the Rollout object or the ResourceId. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Remove-AzureRmDeploymentManagerRollout -ResourceGroupName ContosoResourceGroup -Name ContosoRollout +``` + +This command deletes a rollout named ContosoRollout in the ContosoResourceGroup. + +### Example 2: Delete a rollout using the resource identifier +```powershell +PS C:\> Remove-AzureRmDeploymentManagerRollout -ResourceId "/subscriptions/subscriptionId/resourcegroups/ContosoResourceGroup/providers/Microsoft.DeploymentManager/rollouts/ContosoRollout" +``` + +This command deletes a rollout named ContosoRollout in the ContosoResourceGroup. + +### Example 3: Delete a rollout using the rollout object. +```powershell +PS C:\> Remove-AzureRmDeploymentManagerRollout -Rollout $rolloutObject +``` + +This command deletes a rollout whose name and ResourceGroup match the Name and ResourceGroupName properties of the $rolloutObject, respectively. + +## PARAMETERS + +### -DefaultProfile +The credentials, account, tenant, and subscription used for communication with Azure. + +```yaml +Type: Microsoft.Azure.Commands.Common.Authentication.Abstractions.IAzureContextContainer +Parameter Sets: (All) +Aliases: AzureRmContext, AzureCredential + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Force +Do not ask for confirmation. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Name +The name of the rollout. + +```yaml +Type: System.String +Parameter Sets: Interactive +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -PassThru +{{Fill PassThru Description}} + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ResourceGroupName +The resource group. + +```yaml +Type: System.String +Parameter Sets: Interactive +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -ResourceId +The resource identifier. + +```yaml +Type: System.String +Parameter Sets: ResourceId +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -Rollout +The resource to be removed. + +```yaml +Type: Microsoft.Azure.Commands.DeploymentManager.Models.PSRollout +Parameter Sets: InputObject +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -Confirm +Prompts you for confirmation before running the cmdlet. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: cf + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WhatIf +Shows what would happen if the cmdlet runs. +The cmdlet is not run. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: wi + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### Microsoft.Azure.Commands.DeploymentManager.Models.PSRollout + +## OUTPUTS + +### System.Boolean + +## NOTES + +## RELATED LINKS + +[Get-AzureRmDeploymentManagerRollout](./Get-AzureRmDeploymentManagerRollout.md) + +[Stop-AzureRmDeploymentManagerRollout](./Stop-AzureRmDeploymentManagerRollout.md) + +[Restart-AzureRmDeploymentManagerRollout](./Restart-AzureRmDeploymentManagerRollout.md) \ No newline at end of file diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerService.md b/src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerService.md new file mode 100644 index 000000000000..21f50063acc4 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerService.md @@ -0,0 +1,275 @@ +--- +external help file: Microsoft.Azure.Commands.DeploymentManager.dll-Help.xml +Module Name: AzureRM.DeploymentManager +online version: +schema: 2.0.0 +--- + +# Remove-AzureRmDeploymentManagerService + +## SYNOPSIS +Deletes a service in a service topology. + +## SYNTAX + +### Interactive (Default) +``` +Remove-AzureRmDeploymentManagerService [-ResourceGroupName] [-ServiceTopologyName] + [-Name] [-Force] [-PassThru] [-DefaultProfile ] [-WhatIf] [-Confirm] + [] +``` + +### ByServiceTopologyObject +``` +Remove-AzureRmDeploymentManagerService [-Name] [-ServiceTopology] [-Force] + [-PassThru] [-DefaultProfile ] [-WhatIf] [-Confirm] [] +``` + +### ByServiceTopologyResourceId +``` +Remove-AzureRmDeploymentManagerService [-Name] [-ServiceTopologyResourceId] [-Force] + [-PassThru] [-DefaultProfile ] [-WhatIf] [-Confirm] [] +``` + +### ResourceId +``` +Remove-AzureRmDeploymentManagerService [-ResourceId] [-Force] [-PassThru] + [-DefaultProfile ] [-WhatIf] [-Confirm] [] +``` + +### InputObject +``` +Remove-AzureRmDeploymentManagerService [-Service] [-Force] [-PassThru] + [-DefaultProfile ] [-WhatIf] [-Confirm] [] +``` + +## DESCRIPTION +The **Remove-AzureRmDeploymentManagerService** cmdlet deletes a service under a service topology. +Specify the service by its name, service topology it is in and the resource group name. Alternately, you can provide the Service object or the ResourceId. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Remove-AzureRmDeploymentManagerService -ResourceGroupName ContosoResourceGroup -ServiceTopologyName ContosoServiceTopology -Name ContosoService1 +``` + +This command deletes a service named ContosoService1 in a service topology named ContosoServiceTopology in the ContosoResourceGroup. + +### Example 2: Delete a service using the resource identifier. +```powershell +PS C:\> Remove-AzureRmDeploymentManagerService -ResourceId "/subscriptions/subscriptionId/resourcegroups/ContosoResourceGroup/providers/Microsoft.DeploymentManager/serviceTopologies/ContosoServiceTopology/services/ContosoService1" +``` + +This command deletes a service named ContosoService1 in a service topology named ContosoServiceTopology in the ContosoResourceGroup. + +### Example 3: Delete a service using the service object. +```powershell +PS C:\> Remove-AzureRmDeploymentManagerService -Service $serviceObject +``` + +This command deletes a service whose name, service topology name and ResourceGroup match the Name, ServiceTopologyName and ResourceGroupName properties of the $serviceObject, respectively. + +## PARAMETERS + +### -DefaultProfile +The credentials, account, tenant, and subscription used for communication with Azure. + +```yaml +Type: Microsoft.Azure.Commands.Common.Authentication.Abstractions.IAzureContextContainer +Parameter Sets: (All) +Aliases: AzureRmContext, AzureCredential + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Force +Do not ask for confirmation. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Name +The name of the service. + +```yaml +Type: System.String +Parameter Sets: Interactive, ByServiceTopologyObject, ByServiceTopologyResourceId +Aliases: + +Required: True +Position: 2 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -PassThru +{{Fill PassThru Description}} + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ResourceGroupName +The resource group. + +```yaml +Type: System.String +Parameter Sets: Interactive +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -ResourceId +The resource identifier. + +```yaml +Type: System.String +Parameter Sets: ResourceId +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -Service +The resource to be removed. + +```yaml +Type: Microsoft.Azure.Commands.DeploymentManager.Models.PSServiceResource +Parameter Sets: InputObject +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -ServiceTopology +The service topology object in which the service should be created. + +```yaml +Type: Microsoft.Azure.Commands.DeploymentManager.Models.PSServiceTopologyResource +Parameter Sets: ByServiceTopologyObject +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ServiceTopologyName +The name of the service topology the service belongs to. + +```yaml +Type: System.String +Parameter Sets: Interactive +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -ServiceTopologyResourceId +The service topology resource identifier in which the service should be created. + +```yaml +Type: System.String +Parameter Sets: ByServiceTopologyResourceId +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Confirm +Prompts you for confirmation before running the cmdlet. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: cf + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WhatIf +Shows what would happen if the cmdlet runs. +The cmdlet is not run. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: wi + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### Microsoft.Azure.Commands.DeploymentManager.Models.PSServiceResource + +## OUTPUTS + +### System.Boolean + +## NOTES + +## RELATED LINKS + +[New-AzureRmDeploymentManagerService](./New-AzureRmDeploymentManagerService.md) + +[Get-AzureRmDeploymentManagerService](./Get-AzureRmDeploymentManagerService.md) + +[Set-AzureRmDeploymentManagerService](./Set-AzureRmDeploymentManagerService.md) \ No newline at end of file diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerServiceTopology.md b/src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerServiceTopology.md new file mode 100644 index 000000000000..11ffce09bdf1 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerServiceTopology.md @@ -0,0 +1,218 @@ +--- +external help file: Microsoft.Azure.Commands.DeploymentManager.dll-Help.xml +Module Name: AzureRM.DeploymentManager +online version: +schema: 2.0.0 +--- + +# Remove-AzureRmDeploymentManagerServiceTopology + +## SYNOPSIS +Deletes a service topology and all its resources. + +## SYNTAX + +### Interactive (Default) +``` +Remove-AzureRmDeploymentManagerServiceTopology [-ResourceGroupName] [-Name] [-Force] + [-PassThru] [-DefaultProfile ] [-WhatIf] [-Confirm] [] +``` + +### ResourceId +``` +Remove-AzureRmDeploymentManagerServiceTopology [-ResourceId] [-Force] [-PassThru] + [-DefaultProfile ] [-WhatIf] [-Confirm] [] +``` + +### InputObject +``` +Remove-AzureRmDeploymentManagerServiceTopology [-ServiceTopology] [-Force] + [-PassThru] [-DefaultProfile ] [-WhatIf] [-Confirm] [] +``` + +## DESCRIPTION +The **Remove-AzureRmDeploymentManagerServiceTopology** cmdlet deletes a service topology. + +Specify the service topology by its name and the resource group name. Alternately, you can provide the ServiceTopology object or the ResourceId. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Remove-AzureRmDeploymentManagerServiceTopology -ResourceGroupName ContosoResourceGroup -Name ContosoServiceTopology +``` + +This command deletes a service topology named ContosoServiceTopology in the ContosoResourceGroup. + +### Example 2: Delete a service topology using the resource identifier. +```powershell +PS C:\> Remove-AzureRmDeploymentManagerServiceTopology -ResourceId "/subscriptions/subscriptionId/resourcegroups/ContosoResourceGroup/providers/Microsoft.DeploymentManager/serviceTopologies/ContosoServiceTopology" +``` + +This command deletes a service topology named ContosoServiceTopology in the ContosoResourceGroup. + +### Example 3: Delete a service topology using the service topology object. +```powershell +PS C:\> Remove-AzureRmDeploymentManagerService -ServiceTopology $serviceTopologyObject +``` + +This command deletes a service topology whose name and ResourceGroup match the Name and ResourceGroupName properties of the $serviceTopologyObject, respectively. + +## PARAMETERS + +### -DefaultProfile +The credentials, account, tenant, and subscription used for communication with Azure. + +```yaml +Type: Microsoft.Azure.Commands.Common.Authentication.Abstractions.IAzureContextContainer +Parameter Sets: (All) +Aliases: AzureRmContext, AzureCredential + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Force +Do not ask for confirmation. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Name +The name of the service topology. + +```yaml +Type: System.String +Parameter Sets: Interactive +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -PassThru +{{Fill PassThru Description}} + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ResourceGroupName +The resource group. + +```yaml +Type: System.String +Parameter Sets: Interactive +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -ResourceId +The resource identifier. + +```yaml +Type: System.String +Parameter Sets: ResourceId +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -ServiceTopology +The resource to be removed. + +```yaml +Type: Microsoft.Azure.Commands.DeploymentManager.Models.PSServiceTopologyResource +Parameter Sets: InputObject +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -Confirm +Prompts you for confirmation before running the cmdlet. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: cf + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WhatIf +Shows what would happen if the cmdlet runs. +The cmdlet is not run. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: wi + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### Microsoft.Azure.Commands.DeploymentManager.Models.PSServiceTopologyResource + +## OUTPUTS + +### System.Boolean + +## NOTES + +## RELATED LINKS + +[New-AzureRmDeploymentManagerServiceTopology](./New-AzureRmDeploymentManagerServiceTopology.md) + +[Get-AzureRmDeploymentManagerServiceTopology](./Get-AzureRmDeploymentManagerServiceTopology.md) + +[Set-AzureRmDeploymentManagerServiceTopology](./Set-AzureRmDeploymentManagerServiceTopology.md) \ No newline at end of file diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerServiceUnit.md b/src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerServiceUnit.md new file mode 100644 index 000000000000..9feeaefc3267 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerServiceUnit.md @@ -0,0 +1,335 @@ +--- +external help file: Microsoft.Azure.Commands.DeploymentManager.dll-Help.xml +Module Name: AzureRM.DeploymentManager +online version: +schema: 2.0.0 +--- + +# Remove-AzureRmDeploymentManagerServiceUnit + +## SYNOPSIS +Deletes the service unit of a service in a service topology. + +## SYNTAX + +### Interactive (Default) +``` +Remove-AzureRmDeploymentManagerServiceUnit [-ResourceGroupName] [-ServiceTopologyName] + [-ServiceName] [-Name] [-Force] [-PassThru] [-DefaultProfile ] + [-WhatIf] [-Confirm] [] +``` + +### ByTopologyObjectAndServiceName +``` +Remove-AzureRmDeploymentManagerServiceUnit [-ServiceName] [-Name] + [-ServiceTopology] [-Force] [-PassThru] [-DefaultProfile ] + [-WhatIf] [-Confirm] [] +``` + +### ByTopologyResourceAndServiceName +``` +Remove-AzureRmDeploymentManagerServiceUnit [-ServiceName] [-Name] + [-ServiceTopologyResourceId] [-Force] [-PassThru] [-DefaultProfile ] + [-WhatIf] [-Confirm] [] +``` + +### ByServiceObject +``` +Remove-AzureRmDeploymentManagerServiceUnit [-Name] [-Service] [-Force] [-PassThru] + [-DefaultProfile ] [-WhatIf] [-Confirm] [] +``` + +### ByServiceResourceId +``` +Remove-AzureRmDeploymentManagerServiceUnit [-Name] [-ServiceResourceId] [-Force] [-PassThru] + [-DefaultProfile ] [-WhatIf] [-Confirm] [] +``` + +### ResourceId +``` +Remove-AzureRmDeploymentManagerServiceUnit [-ResourceId] [-Force] [-PassThru] + [-DefaultProfile ] [-WhatIf] [-Confirm] [] +``` + +### InputObject +``` +Remove-AzureRmDeploymentManagerServiceUnit [-ServiceUnit] [-Force] [-PassThru] + [-DefaultProfile ] [-WhatIf] [-Confirm] [] +``` + +## DESCRIPTION +The **Remove-AzureRmDeploymentManagerServiceUnit** cmdlet deletes a service unit in a service. + +Specify the service unit by its name, the service under which it was defined, the service topology name and the resource group name. Alternately, you can provide the ServiceUnit object or the ResourceId. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Remove-AzureRmDeploymentManagerServiceUnit -ResourceGroupName ContosoResourceGroup -ServiceTopologyName ContosoServiceTopology -ServiceName ContosoService1 -Name ContosoService1Storage +``` + +This command deletes a service unit named ContosoService1Storage under a service ContosoService1 in a service topology named ContosoServiceTopology in the ContosoResourceGroup. + +### Example 2: Delete a service unit using the resource identifier. +```powershell +PS C:\> Remove-AzureRmDeploymentManagerServiceUnit -ResourceId "/subscriptions/subscriptionId/resourcegroups/ContosoResourceGroup/providers/Microsoft.DeploymentManager/serviceTopologies/ContosoServiceTopology/services/ContosoService1/serviceUnits/ContosoService1Storage" +``` + +This command gets a service unit named ContosoService1Storage under a service ContosoService1 in a service topology named ContosoServiceTopology in the ContosoResourceGroup. + +### Example 3: Delete a service unit using the service unit object. +```powershell +PS C:\> Remove-AzureRmDeploymentManagerServiceUnit -ServiceUnit $serviceUnitObject +``` + +This command deletes a service unit whose name, service name, service topology name and ResourceGroup match the Name, ServiceName, ServiceTopologyName and ResourceGroupName properties of the $serviceUnitObject, respectively. + +## PARAMETERS + +### -DefaultProfile +The credentials, account, tenant, and subscription used for communication with Azure. + +```yaml +Type: Microsoft.Azure.Commands.Common.Authentication.Abstractions.IAzureContextContainer +Parameter Sets: (All) +Aliases: AzureRmContext, AzureCredential + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Force +Do not ask for confirmation. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Name +The name of the service unit to delete. + +```yaml +Type: System.String +Parameter Sets: Interactive, ByTopologyObjectAndServiceName, ByTopologyResourceAndServiceName, ByServiceObject, ByServiceResourceId +Aliases: + +Required: True +Position: 3 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -PassThru +{{Fill PassThru Description}} + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ResourceGroupName +The resource group. + +```yaml +Type: System.String +Parameter Sets: Interactive +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -ResourceId +The resource identifier. + +```yaml +Type: System.String +Parameter Sets: ResourceId +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -Service +The service object in which the service unit should be created. + +```yaml +Type: Microsoft.Azure.Commands.DeploymentManager.Models.PSServiceResource +Parameter Sets: ByServiceObject +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ServiceName +The name of the service the service unit belongs to. + +```yaml +Type: System.String +Parameter Sets: Interactive, ByTopologyObjectAndServiceName, ByTopologyResourceAndServiceName +Aliases: + +Required: True +Position: 2 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -ServiceResourceId +The service resource identifier in which the service unit should be created. + +```yaml +Type: System.String +Parameter Sets: ByServiceResourceId +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ServiceTopology +The service topology object in which the service unit should be created. + +```yaml +Type: Microsoft.Azure.Commands.DeploymentManager.Models.PSServiceTopologyResource +Parameter Sets: ByTopologyObjectAndServiceName +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ServiceTopologyName +The name of the service topology the service unit belongs to. + +```yaml +Type: System.String +Parameter Sets: Interactive +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -ServiceTopologyResourceId +The service topology resource identifier in which the service unit should be created. + +```yaml +Type: System.String +Parameter Sets: ByTopologyResourceAndServiceName +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ServiceUnit +The resource to be removed. + +```yaml +Type: Microsoft.Azure.Commands.DeploymentManager.Models.PSServiceUnitResource +Parameter Sets: InputObject +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -Confirm +Prompts you for confirmation before running the cmdlet. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: cf + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WhatIf +Shows what would happen if the cmdlet runs. +The cmdlet is not run. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: wi + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### Microsoft.Azure.Commands.DeploymentManager.Models.PSServiceUnitResource + +## OUTPUTS + +### System.Boolean + +## NOTES + +## RELATED LINKS + +[New-AzureRmDeploymentManagerServiceUnit](./New-AzureRmDeploymentManagerServiceUnit.md) + +[Get-AzureRmDeploymentManagerServiceUnit](./Get-AzureRmDeploymentManagerServiceUnit.md) + +[Set-AzureRmDeploymentManagerServiceUnit](./Set-AzureRmDeploymentManagerServiceUnit.md) \ No newline at end of file diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerStep.md b/src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerStep.md new file mode 100644 index 000000000000..1a22fe32e55c --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerStep.md @@ -0,0 +1,213 @@ +--- +external help file: Microsoft.Azure.Commands.DeploymentManager.dll-Help.xml +Module Name: AzureRM.DeploymentManager +online version: +schema: 2.0.0 +--- + +# Remove-AzureRmDeploymentManagerStep + +## SYNOPSIS +Deletes a step. + +## SYNTAX + +### Interactive (Default) +``` +Remove-AzureRmDeploymentManagerStep [-ResourceGroupName] [-Name] [-Force] [-PassThru] + [-DefaultProfile ] [-WhatIf] [-Confirm] [] +``` + +### ResourceId +``` +Remove-AzureRmDeploymentManagerStep [-ResourceId] [-Force] [-PassThru] + [-DefaultProfile ] [-WhatIf] [-Confirm] [] +``` + +### InputObject +``` +Remove-AzureRmDeploymentManagerStep [-Step] [-Force] [-PassThru] + [-DefaultProfile ] [-WhatIf] [-Confirm] [] +``` + +## DESCRIPTION +The **Remove-AzureRmDeploymentManagerStep** cmdlet deletes a step. +Specify the step by its name and the resource group name. Alternately, you can provide the Step object or the ResourceId. + +## EXAMPLES +### Example 1: Remove a step +```powershell +PS C:\> Remove-AzureRmDeploymentManagerStep -ResourceGroupName ContosoResourceGroup -Name ContosoService1WaitStep +``` + +This command deletes a step named ContosoService1WaitStep in ContosoResourceGroup. + +### Example 2: Remove a step using the resource identifier +```powershell +PS C:\> Remove-AzureRmDeploymentManagerStep -ResourceId "/subscriptions/subscriptionId/resourcegroups/ContosoResourceGroup/providers/Microsoft.DeploymentManager/steps/ContosoService1WaitStep" +``` + +This command deletes a step named ContosoService1WaitStep in ContosoResourceGroup. + +### Example 3: Remove a step using an object returned by New-AzureRmDeploymentManagerStep +```powershell +PS C:\> Remove-AzureRmDeploymentManagerStep -Step $stepObject +``` + + This command deletes a step whose name and ResourceGroup match the Name and ResourceGroupName properties of the $stepObject, respectively. + +## PARAMETERS + +### -DefaultProfile +The credentials, account, tenant, and subscription used for communication with Azure. + +```yaml +Type: Microsoft.Azure.Commands.Common.Authentication.Abstractions.IAzureContextContainer +Parameter Sets: (All) +Aliases: AzureRmContext, AzureCredential + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Force +Do not ask for confirmation. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Name +The name of the step. + +```yaml +Type: System.String +Parameter Sets: Interactive +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -PassThru +{{Fill PassThru Description}} + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ResourceGroupName +The resource group. + +```yaml +Type: System.String +Parameter Sets: Interactive +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -ResourceId +The resource identifier. + +```yaml +Type: System.String +Parameter Sets: ResourceId +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -Step +The step to be removed. + +```yaml +Type: Microsoft.Azure.Commands.DeploymentManager.Models.PSStepResource +Parameter Sets: InputObject +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -Confirm +Prompts you for confirmation before running the cmdlet. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: cf + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WhatIf +Shows what would happen if the cmdlet runs. +The cmdlet is not run. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: wi + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. +For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### System.String + +### Microsoft.Azure.Commands.DeploymentManager.Models.PSStepResource + +## OUTPUTS + +### System.Boolean + +## NOTES + +## RELATED LINKS diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Restart-AzureRmDeploymentManagerRollout.md b/src/DeploymentManager/Commands.DeploymentManager/help/Restart-AzureRmDeploymentManagerRollout.md new file mode 100644 index 000000000000..d5df0e7fdfe1 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/help/Restart-AzureRmDeploymentManagerRollout.md @@ -0,0 +1,203 @@ +--- +external help file: Microsoft.Azure.Commands.DeploymentManager.dll-Help.xml +Module Name: AzureRM.DeploymentManager +online version: +schema: 2.0.0 +--- + +# Restart-AzureRmDeploymentManagerRollout + +## SYNOPSIS +Restart a failed rollout. + +## SYNTAX + +### Interactive (Default) +``` +Restart-AzureRmDeploymentManagerRollout [-ResourceGroupName] [-Name] [-SkipSucceeded] + [-DefaultProfile ] [-WhatIf] [-Confirm] [] +``` + +### ResourceId +``` +Restart-AzureRmDeploymentManagerRollout [-ResourceId] [-SkipSucceeded] + [-DefaultProfile ] [-WhatIf] [-Confirm] [] +``` + +### InputObject +``` +Restart-AzureRmDeploymentManagerRollout [-Rollout] [-SkipSucceeded] + [-DefaultProfile ] [-WhatIf] [-Confirm] [] +``` + +## DESCRIPTION +The **Restart-AzureRmDeploymentManagerRollout** cmdlet restarts a failed rollout, and returns an object that represents that rollout with all the detailed information on the progress of the rollout. +Specify the rollout by its name and resource group name. Alternately, you can provide the Rollout object or the ResourceId. +Optional parameter SkipSucceeded allows you to skip all the succeeded steps in the previous run of the rollout. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Restart-AzureRmDeploymentManagerRollout -ResourceGroupName ContosoResourceGroup -Name ContosoRollout -SkipSucceeded +``` + +This command restarts a rollout named ContosoRollout in the ContosoResourceGroup. The SkipSucceeded flag indicates that all the steps that already ran successfully should be skipped and the rollout should continue execution from where it last failed. + +### Example 2: Restart a rollout using the resource identifier +```powershell +PS C:\> Restart-AzureRmDeploymentManagerRollout -ResourceId "/subscriptions/subscriptionId/resourcegroups/ContosoResourceGroup/providers/Microsoft.DeploymentManager/rollouts/ContosoRollout" +``` + +This command restarts a rollout named ContosoRollout in the ContosoResourceGroup. + +### Example 3: Restart a rollout using the rollout object. +```powershell +PS C:\> Get-AzureRmDeploymentManagerRollout -Rollout $rolloutObject +``` + +This command restarts a rollout whose name and ResourceGroup match the Name and ResourceGroupName properties of the $rolloutObject, respectively. + +## PARAMETERS + +### -DefaultProfile +The credentials, account, tenant, and subscription used for communication with Azure. + +```yaml +Type: Microsoft.Azure.Commands.Common.Authentication.Abstractions.IAzureContextContainer +Parameter Sets: (All) +Aliases: AzureRmContext, AzureCredential + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Name +The name of the rollout. + +```yaml +Type: System.String +Parameter Sets: Interactive +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -ResourceGroupName +The resource group. + +```yaml +Type: System.String +Parameter Sets: Interactive +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -ResourceId +The resource identifier. + +```yaml +Type: System.String +Parameter Sets: ResourceId +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -Rollout +The resource to be removed. + +```yaml +Type: Microsoft.Azure.Commands.DeploymentManager.Models.PSRollout +Parameter Sets: InputObject +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -SkipSucceeded +Skip steps that succeeded in the previous run of the rollout. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Confirm +Prompts you for confirmation before running the cmdlet. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: cf + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WhatIf +Shows what would happen if the cmdlet runs. +The cmdlet is not run. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: wi + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### Microsoft.Azure.Commands.DeploymentManager.Models.PSRollout + +## OUTPUTS + +### Microsoft.Azure.Commands.DeploymentManager.Models.PSRollout + +## NOTES + +## RELATED LINKS + +[Get-AzureRmDeploymentManagerRollout](./Get-AzureRmDeploymentManagerRollout.md) + +[Stop-AzureRmDeploymentManagerRollout](./Stop-AzureRmDeploymentManagerRollout.md) + +[Remove-AzureRmDeploymentManagerRollout](./Remove-AzureRmDeploymentManagerRollout.md) \ No newline at end of file diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Set-AzureRmDeploymentManagerArtifactSource.md b/src/DeploymentManager/Commands.DeploymentManager/help/Set-AzureRmDeploymentManagerArtifactSource.md new file mode 100644 index 000000000000..5c92fdc72bde --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/help/Set-AzureRmDeploymentManagerArtifactSource.md @@ -0,0 +1,115 @@ +--- +external help file: Microsoft.Azure.Commands.DeploymentManager.dll-Help.xml +Module Name: AzureRM.DeploymentManager +online version: +schema: 2.0.0 +--- + +# Set-AzureRmDeploymentManagerArtifactSource + +## SYNOPSIS +Updates an artifact source. + +## SYNTAX + +``` +Set-AzureRmDeploymentManagerArtifactSource [-ArtifactSource] + [-DefaultProfile ] [-WhatIf] [-Confirm] [] +``` + +## DESCRIPTION +The **Set-AzureRmDeploymentManagerArtifactSource** cmdlet updates an artifact source with the specified artifact source object. +The cmdlet returns the updated ArtifactSource object. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Get-AzureRmDeploymentManagerArtifactSource -ArtifactSource $artifactSourceObject +``` + +This command updates an artifact source whose name and ResourceGroup match the Name and ResourceGroupName properties of the $artifactSourceObject, respectively. +The artifact source would be updated to the properties set in the $artifactSourceObject. + +## PARAMETERS + +### -ArtifactSource +The artifact source object. + +```yaml +Type: Microsoft.Azure.Commands.DeploymentManager.Models.PSArtifactSource +Parameter Sets: (All) +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -DefaultProfile +The credentials, account, tenant, and subscription used for communication with Azure. + +```yaml +Type: Microsoft.Azure.Commands.Common.Authentication.Abstractions.IAzureContextContainer +Parameter Sets: (All) +Aliases: AzureRmContext, AzureCredential + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Confirm +Prompts you for confirmation before running the cmdlet. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: cf + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WhatIf +Shows what would happen if the cmdlet runs. The cmdlet is not run. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: wi + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### Microsoft.Azure.Commands.DeploymentManager.Models.PSArtifactSource + +## OUTPUTS + +### Microsoft.Azure.Commands.DeploymentManager.Models.PSArtifactSource + +## NOTES + +## RELATED LINKS + +[New-AzureRmDeploymentManagerArtifactSource](./New-AzureRmDeploymentManagerArtifactSource.md) + +[Get-AzureRmDeploymentManagerArtifactSource](./Get-AzureRmDeploymentManagerArtifactSource.md) + +[Remove-AzureRmDeploymentManagerArtifactSource](./Remove-AzureRmDeploymentManagerArtifactSource.md) \ No newline at end of file diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Set-AzureRmDeploymentManagerService.md b/src/DeploymentManager/Commands.DeploymentManager/help/Set-AzureRmDeploymentManagerService.md new file mode 100644 index 000000000000..52db945cb337 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/help/Set-AzureRmDeploymentManagerService.md @@ -0,0 +1,115 @@ +--- +external help file: Microsoft.Azure.Commands.DeploymentManager.dll-Help.xml +Module Name: AzureRM.DeploymentManager +online version: +schema: 2.0.0 +--- + +# Set-AzureRmDeploymentManagerService + +## SYNOPSIS +Updates a service in service topology. + +## SYNTAX + +``` +Set-AzureRmDeploymentManagerService [-Service] [-DefaultProfile ] + [-WhatIf] [-Confirm] [] +``` + +## DESCRIPTION +The **Set-AzureRmDeploymentManagerService** cmdlet updates a service with the specified service object. +The cmdlet returns the updated service object. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Set-AzureRmDeploymentManagerService -Service $serviceObject +``` + +This command updates a service whose name, service topology name and ResourceGroup match the Name, ServiceTopologyName and ResourceGroupName properties of the $serviceObject, respectively. +The service would be updated to the properties set in the $serviceObject. + +## PARAMETERS + +### -DefaultProfile +The credentials, account, tenant, and subscription used for communication with Azure. + +```yaml +Type: Microsoft.Azure.Commands.Common.Authentication.Abstractions.IAzureContextContainer +Parameter Sets: (All) +Aliases: AzureRmContext, AzureCredential + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Service +The service object. + +```yaml +Type: Microsoft.Azure.Commands.DeploymentManager.Models.PSServiceResource +Parameter Sets: (All) +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -Confirm +Prompts you for confirmation before running the cmdlet. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: cf + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WhatIf +Shows what would happen if the cmdlet runs. The cmdlet is not run. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: wi + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### Microsoft.Azure.Commands.DeploymentManager.Models.PSServiceResource + +## OUTPUTS + +### Microsoft.Azure.Commands.DeploymentManager.Models.PSServiceResource + +## NOTES + +## RELATED LINKS + +[New-AzureRmDeploymentManagerService](./New-AzureRmDeploymentManagerService.md) + +[Get-AzureRmDeploymentManagerService](./Set-AzureRmDeploymentManagerService.md) + +[Remove-AzureRmDeploymentManagerService](./Remove-AzureRmDeploymentManagerService.md) \ No newline at end of file diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Set-AzureRmDeploymentManagerServiceTopology.md b/src/DeploymentManager/Commands.DeploymentManager/help/Set-AzureRmDeploymentManagerServiceTopology.md new file mode 100644 index 000000000000..504533ebc1be --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/help/Set-AzureRmDeploymentManagerServiceTopology.md @@ -0,0 +1,115 @@ +--- +external help file: Microsoft.Azure.Commands.DeploymentManager.dll-Help.xml +Module Name: AzureRM.DeploymentManager +online version: +schema: 2.0.0 +--- + +# Set-AzureRmDeploymentManagerServiceTopology + +## SYNOPSIS +Updates the service topology. + +## SYNTAX + +``` +Set-AzureRmDeploymentManagerServiceTopology [-ServiceTopology] + [-DefaultProfile ] [-WhatIf] [-Confirm] [] +``` + +## DESCRIPTION +The **Set-AzureRmDeploymentManagerServiceTopology** cmdlet updates a service topology with the specified service topology object. +The cmdlet returns the updated service topology object. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Set-AzureRmDeploymentManagerService -ServiceTopology $serviceTopologyObject +``` + +This command updates a service topology whose name and ResourceGroup match the Name and ResourceGroupName properties of the $serviceTopologyObject, respectively. +The command returns the updated service topology object. + +## PARAMETERS + +### -DefaultProfile +The credentials, account, tenant, and subscription used for communication with Azure. + +```yaml +Type: Microsoft.Azure.Commands.Common.Authentication.Abstractions.IAzureContextContainer +Parameter Sets: (All) +Aliases: AzureRmContext, AzureCredential + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ServiceTopology +The service topology object. + +```yaml +Type: Microsoft.Azure.Commands.DeploymentManager.Models.PSServiceTopologyResource +Parameter Sets: (All) +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -Confirm +Prompts you for confirmation before running the cmdlet. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: cf + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WhatIf +Shows what would happen if the cmdlet runs. The cmdlet is not run. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: wi + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### Microsoft.Azure.Commands.DeploymentManager.Models.PSServiceTopologyResource + +## OUTPUTS + +### Microsoft.Azure.Commands.DeploymentManager.Models.PSServiceTopologyResource + +## NOTES + +## RELATED LINKS + +[New-AzureRmDeploymentManagerServiceTopology](./New-AzureRmDeploymentManagerServiceTopology.md) + +[Get-AzureRmDeploymentManagerServiceTopology](./Set-AzureRmDeploymentManagerServiceTopology.md) + +[Remove-AzureRmDeploymentManagerServiceTopology](./Remove-AzureRmDeploymentManagerServiceTopology.md) \ No newline at end of file diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Set-AzureRmDeploymentManagerServiceUnit.md b/src/DeploymentManager/Commands.DeploymentManager/help/Set-AzureRmDeploymentManagerServiceUnit.md new file mode 100644 index 000000000000..2e5858adb7cf --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/help/Set-AzureRmDeploymentManagerServiceUnit.md @@ -0,0 +1,115 @@ +--- +external help file: Microsoft.Azure.Commands.DeploymentManager.dll-Help.xml +Module Name: AzureRM.DeploymentManager +online version: +schema: 2.0.0 +--- + +# Set-AzureRmDeploymentManagerServiceUnit + +## SYNOPSIS +Updates a service unit. + +## SYNTAX + +``` +Set-AzureRmDeploymentManagerServiceUnit [-ServiceUnit] + [-DefaultProfile ] [-WhatIf] [-Confirm] [] +``` + +## DESCRIPTION +The **Set-AzureRmDeploymentManagerServiceUnit** cmdlet updates a service unit with the specified service unit object. +The cmdlet returns the updated service unit object. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Set-AzureRmDeploymentManagerServiceUnit -ServiceUnit $serviceUnitObject +``` + +This command updates a service unit whose name, service name, service topology name and ResourceGroup match the Name, ServiceName, ServiceTopologyName and ResourceGroupName properties of the $serviceUnitObject, respectively. +The command returns the updated service unit object. + +## PARAMETERS + +### -DefaultProfile +The credentials, account, tenant, and subscription used for communication with Azure. + +```yaml +Type: Microsoft.Azure.Commands.Common.Authentication.Abstractions.IAzureContextContainer +Parameter Sets: (All) +Aliases: AzureRmContext, AzureCredential + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ServiceUnit +The service unit object. + +```yaml +Type: Microsoft.Azure.Commands.DeploymentManager.Models.PSServiceUnitResource +Parameter Sets: (All) +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -Confirm +Prompts you for confirmation before running the cmdlet. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: cf + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WhatIf +Shows what would happen if the cmdlet runs. The cmdlet is not run. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: wi + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### Microsoft.Azure.Commands.DeploymentManager.Models.PSServiceUnitResource + +## OUTPUTS + +### Microsoft.Azure.Commands.DeploymentManager.Models.PSServiceUnitResource + +## NOTES + +## RELATED LINKS + +[New-AzureRmDeploymentManagerServiceUnit](./New-AzureRmDeploymentManagerServiceUnit.md) + +[Get-AzureRmDeploymentManagerServiceUnit](./Set-AzureRmDeploymentManagerServiceUnit.md) + +[Remove-AzureRmDeploymentManagerServiceUnit](./Remove-AzureRmDeploymentManagerServiceUnit.md) \ No newline at end of file diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Set-AzureRmDeploymentManagerStep.md b/src/DeploymentManager/Commands.DeploymentManager/help/Set-AzureRmDeploymentManagerStep.md new file mode 100644 index 000000000000..b8d7aecbd676 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/help/Set-AzureRmDeploymentManagerStep.md @@ -0,0 +1,111 @@ +--- +external help file: Microsoft.Azure.Commands.DeploymentManager.dll-Help.xml +Module Name: AzureRM.DeploymentManager +online version: +schema: 2.0.0 +--- + +# Set-AzureRmDeploymentManagerStep + +## SYNOPSIS +Updates a step. + +## SYNTAX + +``` +Set-AzureRmDeploymentManagerStep [-Step] [-DefaultProfile ] [-WhatIf] + [-Confirm] [] +``` + +## DESCRIPTION +The **Set-AzureRmDeploymentManagerStep** cmdlet updates a step with the specified step object. +The cmdlet returns the updated step object. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Set-AzureRmDeploymentManagerStep -Step $stepObject +``` + +This command updates a step whose name and ResourceGroup match the Name and ResourceGroupName properties of the $stepObject, respectively. +The step would be updated to the properties set in the $stepObject. + +## PARAMETERS + +### -DefaultProfile +The credentials, account, tenant, and subscription used for communication with Azure. + +```yaml +Type: Microsoft.Azure.Commands.Common.Authentication.Abstractions.IAzureContextContainer +Parameter Sets: (All) +Aliases: AzureRmContext, AzureCredential + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Step +The step object. + +```yaml +Type: Microsoft.Azure.Commands.DeploymentManager.Models.PSStepResource +Parameter Sets: (All) +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -Confirm +Prompts you for confirmation before running the cmdlet. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: cf + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WhatIf +Shows what would happen if the cmdlet runs. +The cmdlet is not run. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: wi + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. +For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### Microsoft.Azure.Commands.DeploymentManager.Models.PSStepResource + +## OUTPUTS + +### Microsoft.Azure.Commands.DeploymentManager.Models.PSStepResource + +## NOTES + +## RELATED LINKS diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Stop-AzureRmDeploymentManagerRollout.md b/src/DeploymentManager/Commands.DeploymentManager/help/Stop-AzureRmDeploymentManagerRollout.md new file mode 100644 index 000000000000..9644de644e8b --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/help/Stop-AzureRmDeploymentManagerRollout.md @@ -0,0 +1,203 @@ +--- +external help file: Microsoft.Azure.Commands.DeploymentManager.dll-Help.xml +Module Name: AzureRM.DeploymentManager +online version: +schema: 2.0.0 +--- + +# Stop-AzureRmDeploymentManagerRollout + +## SYNOPSIS +Stops a rollout in progress. + +## SYNTAX + +### Interactive (Default) +``` +Stop-AzureRmDeploymentManagerRollout [-ResourceGroupName] [-Name] [-Force] + [-DefaultProfile ] [-WhatIf] [-Confirm] [] +``` + +### ResourceId +``` +Stop-AzureRmDeploymentManagerRollout [-ResourceId] [-Force] [-DefaultProfile ] + [-WhatIf] [-Confirm] [] +``` + +### InputObject +``` +Stop-AzureRmDeploymentManagerRollout [-Rollout] [-Force] [-DefaultProfile ] + [-WhatIf] [-Confirm] [] +``` + +## DESCRIPTION +The **Stop-AzureRmDeploymentManagerRollout** cmdlet stops a rollout in progress and returns an object that represents the current state of the rollout. +Specify the rollout by its name and resource group name. Alternately, you can provide the Rollout object or the ResourceId. + +Note that once a rollout is stopped, it cannot be resumed or restarted. You can only create a new rollout. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Stop-AzureRmDeploymentManagerRollout -ResourceGroupName ContosoResourceGroup -Name ContosoRollout -SkipSucceeded +``` + +This command stops a rollout named ContosoRollout in the ContosoResourceGroup. + +### Example 2: Stop a rollout using the resource identifier +```powershell +PS C:\> Restart-AzureRmDeploymentManagerRollout -ResourceId "/subscriptions/subscriptionId/resourcegroups/ContosoResourceGroup/providers/Microsoft.DeploymentManager/rollouts/ContosoRollout" +``` + +This command stops a rollout named ContosoRollout in the ContosoResourceGroup. + +### Example 3: Stop a rollout using the rollout object. +```powershell +PS C:\> Get-AzureRmDeploymentManagerRollout -Rollout $rolloutObject +``` + +This command stops a rollout whose name and ResourceGroup match the Name and ResourceGroupName properties of the $rolloutObject, respectively. + +## PARAMETERS + +### -DefaultProfile +The credentials, account, tenant, and subscription used for communication with Azure. + +```yaml +Type: Microsoft.Azure.Commands.Common.Authentication.Abstractions.IAzureContextContainer +Parameter Sets: (All) +Aliases: AzureRmContext, AzureCredential + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Force +Do not ask for confirmation. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Name +The name of the rollout. + +```yaml +Type: System.String +Parameter Sets: Interactive +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -ResourceGroupName +The resource group. + +```yaml +Type: System.String +Parameter Sets: Interactive +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -ResourceId +The resource identifier. + +```yaml +Type: System.String +Parameter Sets: ResourceId +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -Rollout +The resource to be removed. + +```yaml +Type: Microsoft.Azure.Commands.DeploymentManager.Models.PSRollout +Parameter Sets: InputObject +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -Confirm +Prompts you for confirmation before running the cmdlet. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: cf + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WhatIf +Shows what would happen if the cmdlet runs. The cmdlet is not run. + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: wi + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### Microsoft.Azure.Commands.DeploymentManager.Models.PSRollout + +## OUTPUTS + +### Microsoft.Azure.Commands.DeploymentManager.Models.PSRollout + +## NOTES + +## RELATED LINKS + +[Get-AzureRmDeploymentManagerRollout](./Get-AzureRmDeploymentManagerRollout.md) + +[Restart-AzureRmDeploymentManagerRollout](./Restart-AzureRmDeploymentManagerRollout.md) + +[Remove-AzureRmDeploymentManagerRollout](./Remove-AzureRmDeploymentManagerRollout.md) \ No newline at end of file diff --git a/src/DeploymentManager/Commands.DeploymentManager/packages.config b/src/DeploymentManager/Commands.DeploymentManager/packages.config new file mode 100644 index 000000000000..5fdd11befcf1 --- /dev/null +++ b/src/DeploymentManager/Commands.DeploymentManager/packages.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/DeploymentManager/DeploymentManager.sln b/src/DeploymentManager/DeploymentManager.sln new file mode 100644 index 000000000000..23e95f95bedd --- /dev/null +++ b/src/DeploymentManager/DeploymentManager.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28010.2003 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Commands.DeploymentManager", "Commands.DeploymentManager\Commands.DeploymentManager.csproj", "{F022ED20-7D3B-4BF4-88AF-F97CC50484DA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Commands.DeploymentManager.Test", "Commands.DeploymentManager.Test\Commands.DeploymentManager.Test.csproj", "{4AE5705F-62CF-461D-B72E-DD9DCD9B3609}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F022ED20-7D3B-4BF4-88AF-F97CC50484DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F022ED20-7D3B-4BF4-88AF-F97CC50484DA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F022ED20-7D3B-4BF4-88AF-F97CC50484DA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F022ED20-7D3B-4BF4-88AF-F97CC50484DA}.Release|Any CPU.Build.0 = Release|Any CPU + {4AE5705F-62CF-461D-B72E-DD9DCD9B3609}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4AE5705F-62CF-461D-B72E-DD9DCD9B3609}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4AE5705F-62CF-461D-B72E-DD9DCD9B3609}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4AE5705F-62CF-461D-B72E-DD9DCD9B3609}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {C50F967F-CC90-485A-AEED-2886F3D3066E} + EndGlobalSection +EndGlobal diff --git a/src/DeploymentManager/NuGet.Config b/src/DeploymentManager/NuGet.Config new file mode 100644 index 000000000000..2de911013532 --- /dev/null +++ b/src/DeploymentManager/NuGet.Config @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/DeploymentManager/documentation/current-breaking-changes.md b/src/DeploymentManager/documentation/current-breaking-changes.md new file mode 100644 index 000000000000..0f0cb267c941 --- /dev/null +++ b/src/DeploymentManager/documentation/current-breaking-changes.md @@ -0,0 +1,41 @@ + + +## Current Breaking Changes \ No newline at end of file diff --git a/src/DeploymentManager/documentation/upcoming-breaking-changes.md b/src/DeploymentManager/documentation/upcoming-breaking-changes.md new file mode 100644 index 000000000000..e01c405de7a3 --- /dev/null +++ b/src/DeploymentManager/documentation/upcoming-breaking-changes.md @@ -0,0 +1,28 @@ + + +# Upcoming Breaking Changes \ No newline at end of file From caaeaf0a8f8c99bd87f0bfd369d214470893c833 Mon Sep 17 00:00:00 2001 From: Devesh Guha Oleti Muni Date: Fri, 15 Mar 2019 15:30:40 -0700 Subject: [PATCH 029/141] Add nuget pkg to localfeed --- ...ement.DeploymentManager.0.9.0-preview.nupkg | Bin 0 -> 121877 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tools/LocalFeed/Microsoft.Azure.Management.DeploymentManager.0.9.0-preview.nupkg diff --git a/tools/LocalFeed/Microsoft.Azure.Management.DeploymentManager.0.9.0-preview.nupkg b/tools/LocalFeed/Microsoft.Azure.Management.DeploymentManager.0.9.0-preview.nupkg new file mode 100644 index 0000000000000000000000000000000000000000..ab519b1b55cfe1f20d12c4a7653014783c61019c GIT binary patch literal 121877 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

27(pfOD}c5ZBCK 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

  • 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 VmaL#J5FCsH#K`JT1B^Kf_z$5V4t)Rs literal 0 HcmV?d00001 From c222120a59dd6e7ab8e84032faaeced2b759d1b2 Mon Sep 17 00:00:00 2001 From: Devesh Guha Oleti Muni Date: Fri, 15 Mar 2019 18:08:52 -0700 Subject: [PATCH 030/141] Fix directory structure --- ...ands.DeploymentManager.Test.Netcore.csproj | 47 ------ .../AzureRM.DeploymentManager.psd1 | 155 ------------------ .../Commands.DeploymentManager.NetCore.csproj | 57 ------- .../DeploymentManager.Test.csproj} | 2 +- .../MSSharedLibKey.snk | Bin .../Properties/AssemblyInfo.cs | 0 .../ScenarioTests/CreateRollout.json | 0 .../CreateRollout_FailureRollout.json | 0 .../DeploymentManagerController.cs | 4 +- .../ScenarioTests/DeploymentManagerTests.cs | 2 +- .../ScenarioTests/DeploymentManagerTests.ps1 | 80 ++++----- .../EndToEndFunctionalTests.json | 0 .../packages.config | 0 src/DeploymentManager/DeploymentManager.sln | 36 +++- .../Az.DeploymentManager.psd1 | 8 +- .../ChangeLog.md | 0 .../Client/DeploymentManagerClient.cs | 0 .../Commands/DeploymentManagerBaseCmdlet.cs | 0 .../Commands/GetArtifactSource.cs | 0 .../Commands/GetRollout.cs | 0 .../Commands/GetService.cs | 0 .../Commands/GetServiceTopology.cs | 0 .../Commands/GetServiceUnit.cs | 0 .../Commands/GetStep.cs | 0 .../Commands/NewArtifactSource.cs | 0 .../Commands/NewService.cs | 0 .../Commands/NewServiceTopology.cs | 0 .../Commands/NewServiceUnit.cs | 0 .../Commands/NewStep.cs | 0 .../Commands/RemoveArtifactSource.cs | 0 .../Commands/RemoveRollout.cs | 0 .../Commands/RemoveService.cs | 0 .../Commands/RemoveServiceTopology.cs | 0 .../Commands/RemoveServiceUnit.cs | 0 .../Commands/RemoveStep.cs | 0 .../Commands/RestartRollout.cs | 0 .../Commands/RolloutCmdletBase.cs | 0 .../Commands/SetArtifactSource.cs | 0 .../Commands/SetService.cs | 0 .../Commands/SetServiceTopology.cs | 0 .../Commands/SetServiceUnit.cs | 0 .../Commands/SetStep.cs | 0 .../Commands/StopRollout.cs | 0 .../DeploymentManager.csproj} | 0 .../MSSharedLibKey.snk | Bin .../Messages.Designer.cs | 0 .../Messages.resx | 0 .../Models/ArtifactSource/PSArtifactSource.cs | 0 .../Models/ArtifactSource/PSAuthentication.cs | 0 .../ArtifactSource/PSSasAuthentication.cs | 0 .../Models/PSIdentity.cs | 0 .../Models/Rollout/PSBaseOperationInfo.cs | 0 .../Models/Rollout/PSMessage.cs | 0 .../Models/Rollout/PSResource.cs | 0 .../Models/Rollout/PSResourceOperation.cs | 0 .../Models/Rollout/PSRollout.cs | 0 .../Models/Rollout/PSRolloutOperationInfo.cs | 0 .../Models/Rollout/PSRolloutStep.cs | 0 .../Models/Rollout/PSService.cs | 0 .../Models/Rollout/PSServiceUnit.cs | 0 .../Models/Rollout/PSStepOperationInfo.cs | 0 .../ServiceTopology/PSServiceResource.cs | 0 .../PSServiceTopologyResource.cs | 0 .../ServiceTopology/PSServiceUnitResource.cs | 0 .../Models/Steps/PSStepProperties.cs | 0 .../Models/Steps/PSStepResource.cs | 0 .../Models/Steps/PSWaitStepProperties.cs | 0 .../Properties/AssemblyInfo.cs | 0 .../Utilities/EnumerationUtilities.cs | 0 .../Utilities/StringUtilities.cs | 0 .../help/AzureRM.DeploymentManager.md | 0 ...-AzureRmDeploymentManagerArtifactSource.md | 0 .../Get-AzureRmDeploymentManagerRollout.md | 0 .../Get-AzureRmDeploymentManagerService.md | 0 ...AzureRmDeploymentManagerServiceTopology.md | 0 ...Get-AzureRmDeploymentManagerServiceUnit.md | 0 .../help/Get-AzureRmDeploymentManagerStep.md | 0 ...rosoft.Azure.Commands.DeploymentManager.md | 0 ...-AzureRmDeploymentManagerArtifactSource.md | 0 .../New-AzureRmDeploymentManagerService.md | 0 ...AzureRmDeploymentManagerServiceTopology.md | 0 ...New-AzureRmDeploymentManagerServiceUnit.md | 0 .../help/New-AzureRmDeploymentManagerStep.md | 0 ...-AzureRmDeploymentManagerArtifactSource.md | 0 .../Remove-AzureRmDeploymentManagerRollout.md | 0 .../Remove-AzureRmDeploymentManagerService.md | 0 ...AzureRmDeploymentManagerServiceTopology.md | 0 ...ove-AzureRmDeploymentManagerServiceUnit.md | 0 .../Remove-AzureRmDeploymentManagerStep.md | 0 ...Restart-AzureRmDeploymentManagerRollout.md | 0 ...-AzureRmDeploymentManagerArtifactSource.md | 0 .../Set-AzureRmDeploymentManagerService.md | 0 ...AzureRmDeploymentManagerServiceTopology.md | 0 ...Set-AzureRmDeploymentManagerServiceUnit.md | 0 .../help/Set-AzureRmDeploymentManagerStep.md | 0 .../Stop-AzureRmDeploymentManagerRollout.md | 0 .../packages.config | 0 ...ment.DeploymentManager.0.9.0-preview.nupkg | Bin 121877 -> 125643 bytes 98 files changed, 82 insertions(+), 309 deletions(-) delete mode 100644 src/DeploymentManager/Commands.DeploymentManager.Test/Commands.DeploymentManager.Test.Netcore.csproj delete mode 100644 src/DeploymentManager/Commands.DeploymentManager/AzureRM.DeploymentManager.psd1 delete mode 100644 src/DeploymentManager/Commands.DeploymentManager/Commands.DeploymentManager.NetCore.csproj rename src/DeploymentManager/{Commands.DeploymentManager.Test/Commands.DeploymentManager.Test.csproj => DeploymentManager.Test/DeploymentManager.Test.csproj} (83%) rename src/DeploymentManager/{Commands.DeploymentManager.Test => DeploymentManager.Test}/MSSharedLibKey.snk (100%) rename src/DeploymentManager/{Commands.DeploymentManager.Test => DeploymentManager.Test}/Properties/AssemblyInfo.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager.Test => DeploymentManager.Test}/ScenarioTests/CreateRollout.json (100%) rename src/DeploymentManager/{Commands.DeploymentManager.Test => DeploymentManager.Test}/ScenarioTests/CreateRollout_FailureRollout.json (100%) rename src/DeploymentManager/{Commands.DeploymentManager.Test => DeploymentManager.Test}/ScenarioTests/DeploymentManagerController.cs (97%) rename src/DeploymentManager/{Commands.DeploymentManager.Test => DeploymentManager.Test}/ScenarioTests/DeploymentManagerTests.cs (96%) rename src/DeploymentManager/{Commands.DeploymentManager.Test => DeploymentManager.Test}/ScenarioTests/DeploymentManagerTests.ps1 (71%) rename src/DeploymentManager/{Commands.DeploymentManager.Test => DeploymentManager.Test}/SessionRecords/Microsoft.Azure.Commands.DeploymentManager.Test.ScenarioTests.DeploymentManagerTests/EndToEndFunctionalTests.json (100%) rename src/DeploymentManager/{Commands.DeploymentManager.Test => DeploymentManager.Test}/packages.config (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Az.DeploymentManager.psd1 (96%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/ChangeLog.md (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Client/DeploymentManagerClient.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Commands/DeploymentManagerBaseCmdlet.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Commands/GetArtifactSource.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Commands/GetRollout.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Commands/GetService.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Commands/GetServiceTopology.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Commands/GetServiceUnit.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Commands/GetStep.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Commands/NewArtifactSource.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Commands/NewService.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Commands/NewServiceTopology.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Commands/NewServiceUnit.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Commands/NewStep.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Commands/RemoveArtifactSource.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Commands/RemoveRollout.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Commands/RemoveService.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Commands/RemoveServiceTopology.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Commands/RemoveServiceUnit.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Commands/RemoveStep.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Commands/RestartRollout.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Commands/RolloutCmdletBase.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Commands/SetArtifactSource.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Commands/SetService.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Commands/SetServiceTopology.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Commands/SetServiceUnit.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Commands/SetStep.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Commands/StopRollout.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager/Commands.DeploymentManager.csproj => DeploymentManager/DeploymentManager.csproj} (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/MSSharedLibKey.snk (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Messages.Designer.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Messages.resx (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Models/ArtifactSource/PSArtifactSource.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Models/ArtifactSource/PSAuthentication.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Models/ArtifactSource/PSSasAuthentication.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Models/PSIdentity.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Models/Rollout/PSBaseOperationInfo.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Models/Rollout/PSMessage.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Models/Rollout/PSResource.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Models/Rollout/PSResourceOperation.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Models/Rollout/PSRollout.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Models/Rollout/PSRolloutOperationInfo.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Models/Rollout/PSRolloutStep.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Models/Rollout/PSService.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Models/Rollout/PSServiceUnit.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Models/Rollout/PSStepOperationInfo.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Models/ServiceTopology/PSServiceResource.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Models/ServiceTopology/PSServiceTopologyResource.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Models/ServiceTopology/PSServiceUnitResource.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Models/Steps/PSStepProperties.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Models/Steps/PSStepResource.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Models/Steps/PSWaitStepProperties.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Properties/AssemblyInfo.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Utilities/EnumerationUtilities.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/Utilities/StringUtilities.cs (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/help/AzureRM.DeploymentManager.md (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/help/Get-AzureRmDeploymentManagerArtifactSource.md (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/help/Get-AzureRmDeploymentManagerRollout.md (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/help/Get-AzureRmDeploymentManagerService.md (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/help/Get-AzureRmDeploymentManagerServiceTopology.md (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/help/Get-AzureRmDeploymentManagerServiceUnit.md (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/help/Get-AzureRmDeploymentManagerStep.md (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/help/Microsoft.Azure.Commands.DeploymentManager.md (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/help/New-AzureRmDeploymentManagerArtifactSource.md (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/help/New-AzureRmDeploymentManagerService.md (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/help/New-AzureRmDeploymentManagerServiceTopology.md (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/help/New-AzureRmDeploymentManagerServiceUnit.md (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/help/New-AzureRmDeploymentManagerStep.md (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/help/Remove-AzureRmDeploymentManagerArtifactSource.md (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/help/Remove-AzureRmDeploymentManagerRollout.md (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/help/Remove-AzureRmDeploymentManagerService.md (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/help/Remove-AzureRmDeploymentManagerServiceTopology.md (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/help/Remove-AzureRmDeploymentManagerServiceUnit.md (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/help/Remove-AzureRmDeploymentManagerStep.md (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/help/Restart-AzureRmDeploymentManagerRollout.md (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/help/Set-AzureRmDeploymentManagerArtifactSource.md (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/help/Set-AzureRmDeploymentManagerService.md (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/help/Set-AzureRmDeploymentManagerServiceTopology.md (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/help/Set-AzureRmDeploymentManagerServiceUnit.md (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/help/Set-AzureRmDeploymentManagerStep.md (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/help/Stop-AzureRmDeploymentManagerRollout.md (100%) rename src/DeploymentManager/{Commands.DeploymentManager => DeploymentManager}/packages.config (100%) diff --git a/src/DeploymentManager/Commands.DeploymentManager.Test/Commands.DeploymentManager.Test.Netcore.csproj b/src/DeploymentManager/Commands.DeploymentManager.Test/Commands.DeploymentManager.Test.Netcore.csproj deleted file mode 100644 index 295d7c82544b..000000000000 --- a/src/DeploymentManager/Commands.DeploymentManager.Test/Commands.DeploymentManager.Test.Netcore.csproj +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - netcoreapp2.1;netcoreapp2.0;net472 - Microsoft.Azure.Commands.RedisCache.Test - Microsoft.Azure.Commands.RedisCache.Test - false - true - - false - - - - false - TRACE;DEBUG;NETSTANDARD - - - - true - true - MSSharedLibKey.snk - TRACE;RELEASE;NETSTANDARD;SIGN - - - - - - - - - - ..\..\..\Package\$(Configuration)\ResourceManager\AzureResourceManager\Az.RedisCache\Microsoft.Azure.Commands.RedisCache.dll - - - - - - PreserveNewest - - - PreserveNewest - - - - \ No newline at end of file diff --git a/src/DeploymentManager/Commands.DeploymentManager/AzureRM.DeploymentManager.psd1 b/src/DeploymentManager/Commands.DeploymentManager/AzureRM.DeploymentManager.psd1 deleted file mode 100644 index 8d129dfaf785..000000000000 --- a/src/DeploymentManager/Commands.DeploymentManager/AzureRM.DeploymentManager.psd1 +++ /dev/null @@ -1,155 +0,0 @@ -# -# Module manifest for module 'PSGet_AzureRM.DeploymentManager' -# -# Generated by: Microsoft Corporation -# -# Generated on: 10/18/2018 -# - -@{ - -# Script module or binary module file associated with this manifest. -# RootModule = '' - -# Version number of this module. -ModuleVersion = '0.9.2' - -# Supported PSEditions -# CompatiblePSEditions = @() - -# ID used to uniquely identify this module -GUID = 'caac1590-e859-444f-a9e0-62091c0f5929' - -# Author of this module -Author = 'Microsoft Corporation' - -# Company or vendor of this module -CompanyName = 'Microsoft Corporation' - -# Copyright statement for this module -Copyright = 'Microsoft Corporation. All rights reserved.' - -# Description of the functionality provided by this module -Description = 'Microsoft Azure PowerShell - Deployment Manager cmdlets for Azure Resource Manager. Creates and manages Deployment Manager resources in Azure Resource Manager.' - -# Minimum version of the Windows PowerShell engine required by this module -PowerShellVersion = '5.0' - -# Name of the Windows PowerShell host required by this module -# PowerShellHostName = '' - -# Minimum version of the Windows PowerShell host required by this module -# PowerShellHostVersion = '' - -# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. -DotNetFrameworkVersion = '4.5.2' - -# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. -CLRVersion = '4.0' - -# Processor architecture (None, X86, Amd64) required by this module -# ProcessorArchitecture = '' - -# Modules that must be imported into the global environment prior to importing this module -RequiredModules = @(@{ModuleName = 'AzureRM.Profile'; ModuleVersion = '5.6.0'; }) - -# Assemblies that must be loaded prior to importing this module -RequiredAssemblies = '.\Microsoft.Azure.Management.DeploymentManager.dll' - -# Script files (.ps1) that are run in the caller's environment prior to importing this module. -# ScriptsToProcess = @() - -# Type files (.ps1xml) to be loaded when importing this module -# TypesToProcess = @() - -# Format files (.ps1xml) to be loaded when importing this module -# FormatsToProcess = @() - -# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess -NestedModules = @('.\Microsoft.Azure.Commands.DeploymentManager.dll') - -# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. -FunctionsToExport = @() - -# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. -CmdletsToExport = 'Get-AzureRmDeploymentManagerArtifactSource', - 'New-AzureRmDeploymentManagerArtifactSource', - 'Set-AzureRmDeploymentManagerArtifactSource', - 'Remove-AzureRmDeploymentManagerArtifactSource', - 'Get-AzureRmDeploymentManagerRollout', - 'Stop-AzureRmDeploymentManagerRollout', - 'Restart-AzureRmDeploymentManagerRollout', - 'Remove-AzureRmDeploymentManagerRollout', - 'New-AzureRmDeploymentManagerServiceTopology', - 'Get-AzureRmDeploymentManagerServiceTopology', - 'Set-AzureRmDeploymentManagerServiceTopology', - 'Remove-AzureRmDeploymentManagerServiceTopology', - 'Get-AzureRmDeploymentManagerService', - 'New-AzureRmDeploymentManagerService', - 'Set-AzureRmDeploymentManagerService', - 'Remove-AzureRmDeploymentManagerService', - 'Get-AzureRmDeploymentManagerServiceUnit', - 'New-AzureRmDeploymentManagerServiceUnit', - 'Set-AzureRmDeploymentManagerServiceUnit', - 'Remove-AzureRmDeploymentManagerServiceUnit', - 'Get-AzureRmDeploymentManagerStep', - 'New-AzureRmDeploymentManagerStep', - 'Set-AzureRmDeploymentManagerStep', - 'Remove-AzureRmDeploymentManagerStep' - -# Variables to export from this module -# VariablesToExport = @() - -# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. -AliasesToExport = @() - -# DSC resources to export from this module -# DscResourcesToExport = @() - -# List of all modules packaged with this module -# ModuleList = @() - -# List of all files packaged with this module -# FileList = @() - -# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. -PrivateData = @{ - - PSData = @{ - - # Tags applied to this module. These help with module discovery in online galleries. - Tags = 'Azure','ResourceManager','ARM','DeploymentManager' - - # A URL to the license for this module. - LicenseUri = 'https://raw.githubusercontent.com/Azure/azure-powershell/dev/LICENSE.txt' - - # A URL to the main website for this project. - ProjectUri = 'https://github.com/Azure/azure-powershell' - - # A URL to an icon representing this module. - # IconUri = '' - - # ReleaseNotes of this module - ReleaseNotes = '* Fix ArtifactSource command bug' - - # Prerelease string of this module - Prerelease = 'preview' - - # Flag to indicate whether the module requires explicit user acceptance for install/update - # RequireLicenseAcceptance = $false - - # External dependent modules of this module - # ExternalModuleDependencies = @() - - } # End of PSData hashtable - - } # End of PrivateData hashtable - -# HelpInfo URI of this module -# HelpInfoURI = '' - -# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. -# DefaultCommandPrefix = '' - -} - diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands.DeploymentManager.NetCore.csproj b/src/DeploymentManager/Commands.DeploymentManager/Commands.DeploymentManager.NetCore.csproj deleted file mode 100644 index 329aeae67968..000000000000 --- a/src/DeploymentManager/Commands.DeploymentManager/Commands.DeploymentManager.NetCore.csproj +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - netcoreapp2.0 - Microsoft.Azure.Commands.DeploymentManager - Microsoft.Azure.Commands.DeploymentManager - false - true - true - false - $(ProjectDir)..\..\..\Package\$(Configuration)\ResourceManager\AzureResourceManager\Az.DeploymentManager\ - - - - false - TRACE;DEBUG;NETSTANDARD - - - - true - true - MSSharedLibKey.snk - TRACE;RELEASE;NETSTANDARD;SIGN - - - - - - - - - PreserveNewest - - - - - - true - true - Messages.resx - - - - - - ResXFileCodeGenerator - Messages.Designer.cs - - - - - - - - \ No newline at end of file diff --git a/src/DeploymentManager/Commands.DeploymentManager.Test/Commands.DeploymentManager.Test.csproj b/src/DeploymentManager/DeploymentManager.Test/DeploymentManager.Test.csproj similarity index 83% rename from src/DeploymentManager/Commands.DeploymentManager.Test/Commands.DeploymentManager.Test.csproj rename to src/DeploymentManager/DeploymentManager.Test/DeploymentManager.Test.csproj index 6274590f685d..88ee732f6b7c 100644 --- a/src/DeploymentManager/Commands.DeploymentManager.Test/Commands.DeploymentManager.Test.csproj +++ b/src/DeploymentManager/DeploymentManager.Test/DeploymentManager.Test.csproj @@ -15,7 +15,7 @@ - + \ No newline at end of file diff --git a/src/DeploymentManager/Commands.DeploymentManager.Test/MSSharedLibKey.snk b/src/DeploymentManager/DeploymentManager.Test/MSSharedLibKey.snk similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager.Test/MSSharedLibKey.snk rename to src/DeploymentManager/DeploymentManager.Test/MSSharedLibKey.snk diff --git a/src/DeploymentManager/Commands.DeploymentManager.Test/Properties/AssemblyInfo.cs b/src/DeploymentManager/DeploymentManager.Test/Properties/AssemblyInfo.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager.Test/Properties/AssemblyInfo.cs rename to src/DeploymentManager/DeploymentManager.Test/Properties/AssemblyInfo.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager.Test/ScenarioTests/CreateRollout.json b/src/DeploymentManager/DeploymentManager.Test/ScenarioTests/CreateRollout.json similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager.Test/ScenarioTests/CreateRollout.json rename to src/DeploymentManager/DeploymentManager.Test/ScenarioTests/CreateRollout.json diff --git a/src/DeploymentManager/Commands.DeploymentManager.Test/ScenarioTests/CreateRollout_FailureRollout.json b/src/DeploymentManager/DeploymentManager.Test/ScenarioTests/CreateRollout_FailureRollout.json similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager.Test/ScenarioTests/CreateRollout_FailureRollout.json rename to src/DeploymentManager/DeploymentManager.Test/ScenarioTests/CreateRollout_FailureRollout.json diff --git a/src/DeploymentManager/Commands.DeploymentManager.Test/ScenarioTests/DeploymentManagerController.cs b/src/DeploymentManager/DeploymentManager.Test/ScenarioTests/DeploymentManagerController.cs similarity index 97% rename from src/DeploymentManager/Commands.DeploymentManager.Test/ScenarioTests/DeploymentManagerController.cs rename to src/DeploymentManager/DeploymentManager.Test/ScenarioTests/DeploymentManagerController.cs index 1080d4415adc..208970e9ffc0 100644 --- a/src/DeploymentManager/Commands.DeploymentManager.Test/ScenarioTests/DeploymentManagerController.cs +++ b/src/DeploymentManager/DeploymentManager.Test/ScenarioTests/DeploymentManagerController.cs @@ -20,11 +20,11 @@ using System.IO; using System.Linq; using TestEnvironmentFactory = Microsoft.Rest.ClientRuntime.Azure.TestFramework.TestEnvironmentFactory; -using Microsoft.Azure.Management.Storage; using System.Collections.Generic; using System.Diagnostics; -using Microsoft.Azure.ServiceManagemenet.Common.Models; using Microsoft.Azure.Management.DeploymentManager; +using Microsoft.Azure.Management.Storage.Version2017_10_01; +using Microsoft.Azure.ServiceManagement.Common.Models; namespace Microsoft.Azure.Commands.DeploymentManager.Test.ScenarioTests { diff --git a/src/DeploymentManager/Commands.DeploymentManager.Test/ScenarioTests/DeploymentManagerTests.cs b/src/DeploymentManager/DeploymentManager.Test/ScenarioTests/DeploymentManagerTests.cs similarity index 96% rename from src/DeploymentManager/Commands.DeploymentManager.Test/ScenarioTests/DeploymentManagerTests.cs rename to src/DeploymentManager/DeploymentManager.Test/ScenarioTests/DeploymentManagerTests.cs index 0ac587f2fa5e..c686812bfe0d 100644 --- a/src/DeploymentManager/Commands.DeploymentManager.Test/ScenarioTests/DeploymentManagerTests.cs +++ b/src/DeploymentManager/DeploymentManager.Test/ScenarioTests/DeploymentManagerTests.cs @@ -14,9 +14,9 @@ namespace Microsoft.Azure.Commands.DeploymentManager.Test.ScenarioTests { + using Microsoft.Azure.ServiceManagement.Common.Models; using Microsoft.WindowsAzure.Commands.ScenarioTest; using Microsoft.WindowsAzure.Commands.Test.Utilities.Common; - using ServiceManagemenet.Common.Models; using Xunit; using Xunit.Abstractions; diff --git a/src/DeploymentManager/Commands.DeploymentManager.Test/ScenarioTests/DeploymentManagerTests.ps1 b/src/DeploymentManager/DeploymentManager.Test/ScenarioTests/DeploymentManagerTests.ps1 similarity index 71% rename from src/DeploymentManager/Commands.DeploymentManager.Test/ScenarioTests/DeploymentManagerTests.ps1 rename to src/DeploymentManager/DeploymentManager.Test/ScenarioTests/DeploymentManagerTests.ps1 index da983a7b8f07..06efe00c1383 100644 --- a/src/DeploymentManager/Commands.DeploymentManager.Test/ScenarioTests/DeploymentManagerTests.ps1 +++ b/src/DeploymentManager/DeploymentManager.Test/ScenarioTests/DeploymentManagerTests.ps1 @@ -13,7 +13,7 @@ function Test-EndToEndFunctionalTests $location = "Central US" # Create resource group - $resourceGroup = New-AzureRmResourceGroup -Name $resourceGroupName -Location $location + $resourceGroup = New-AzResourceGroup -Name $resourceGroupName -Location $location Assert-NotNull $resourceGroup "Created resource group is null." $artifactSource = New-ArtifactSource $resourceGroupName $artifactSourceName @@ -21,12 +21,12 @@ function Test-EndToEndFunctionalTests # Test all service topology and rollout operation Test-ServiceTopology $resourceGroupName $location $artifactSource $updatedArtifactSourceName $subscriptionId - Remove-AzureRmDeploymentManagerArtifactSource -ResourceGroupName $resourceGroupName -Name $artifactSourceName -Force + Remove-AzDeploymentManagerArtifactSource -ResourceGroupName $resourceGroupName -Name $artifactSourceName -Force $getArtifactSource = $null try { - $getArtifactSource = Get-AzureRmDeploymentManagerArtifactSource -ResourceGroupName $resourceGroupName -Name $artifactSourceName + $getArtifactSource = Get-AzDeploymentManagerArtifactSource -ResourceGroupName $resourceGroupName -Name $artifactSourceName } catch { @@ -50,9 +50,9 @@ function Test-ServiceTopology $serviceTopologyName = "powershell-sdk-tests" - $serviceTopology = New-AzureRmDeploymentManagerServiceTopology -ResourceGroupName $resourceGroupName -Location $location -Name $serviceTopologyName -ArtifactSourceId $artifactSource.Id + $serviceTopology = New-AzDeploymentManagerServiceTopology -ResourceGroupName $resourceGroupName -Location $location -Name $serviceTopologyName -ArtifactSourceId $artifactSource.Id Validate-Topology $serviceTopology $resourceGroupName $location $serviceTopologyName $artifactSource.Id - $getResponse = Get-AzureRmDeploymentManagerServiceTopology -ResourceGroupName $resourceGroupName -Name $serviceTopologyName + $getResponse = Get-AzDeploymentManagerServiceTopology -ResourceGroupName $resourceGroupName -Name $serviceTopologyName Validate-Topology $getResponse $resourceGroupName $location $serviceTopologyName $artifactSource.Id @@ -63,15 +63,15 @@ function Test-ServiceTopology $updatedArtifactSource = New-ArtifactSource $resourceGroupName $updatedArtifactSourceName $getResponse.ArtifactSourceId = $updatedArtifactSource.Id - $updatedServiceTopology = Set-AzureRmDeploymentManagerServiceTopology $getResponse + $updatedServiceTopology = Set-AzDeploymentManagerServiceTopology $getResponse Validate-Topology $updatedServiceTopology $resourceGroupName $location $serviceTopologyName $updatedArtifactSource.Id # Test Set-ServiceTopology - Remove-AzureRmDeploymentManagerServiceTopology -ResourceGroupName $resourceGroupName -Name $serviceTopologyName -Force + Remove-AzDeploymentManagerServiceTopology -ResourceGroupName $resourceGroupName -Name $serviceTopologyName -Force $getResponse = $null try { - $getResponse = Get-AzureRmDeploymentManagerServiceTopology -ResourceGroupName $resourceGroupName -Name $serviceTopologyName + $getResponse = Get-AzDeploymentManagerServiceTopology -ResourceGroupName $resourceGroupName -Name $serviceTopologyName } catch { @@ -113,11 +113,11 @@ function Test-Service $targetLocation = "East US 2" $targetSubscriptionId = "53012dcb-5039-4e96-8e6c-5d913da1cdb5" - $service = New-AzureRmDeploymentManagerService -ResourceGroupName $resourceGroupName -Location $location -Name $serviceName -ServiceTopology $serviceTopology -TargetLocation $targetLocation -TargetSubscriptionId $targetSubscriptionId + $service = New-AzDeploymentManagerService -ResourceGroupName $resourceGroupName -Location $location -Name $serviceName -ServiceTopology $serviceTopology -TargetLocation $targetLocation -TargetSubscriptionId $targetSubscriptionId Validate-Service $service $resourceGroupName $location $serviceTopology.Name $serviceName $targetLocation $targetSubscriptionId - $getResponse = Get-AzureRmDeploymentManagerService -ResourceGroupName $resourceGroupName -Name $serviceName -ServiceTopologyName $serviceTopology.Name + $getResponse = Get-AzDeploymentManagerService -ResourceGroupName $resourceGroupName -Name $serviceName -ServiceTopologyName $serviceTopology.Name Validate-Service $getResponse $resourceGroupName $location $serviceTopology.Name $serviceName $targetLocation $targetSubscriptionId @@ -126,18 +126,18 @@ function Test-Service # Test Set-Service $getResponse.TargetSubscriptionId = "1e591dc1-b014-4754-b53b-58b67bcab1cd" - $updatedService = Set-AzureRmDeploymentManagerService $getResponse + $updatedService = Set-AzDeploymentManagerService $getResponse Validate-Service $updatedService $resourceGroupName $location $serviceTopologyName $serviceName $targetLocation $getResponse.TargetSubscriptionId # Test Remove-Service - Remove-AzureRmDeploymentManagerService -ResourceGroupName $resourceGroupName -Name $serviceName -ServiceTopologyName $serviceTopology.Name -Force + Remove-AzDeploymentManagerService -ResourceGroupName $resourceGroupName -Name $serviceName -ServiceTopologyName $serviceTopology.Name -Force $getResponse = $null try { - $getResponse = Get-AzureRmDeploymentManagerService -ResourceGroupName $resourceGroupName -Name $serviceName -ServiceTopologyName $serviceTopology.Name + $getResponse = Get-AzDeploymentManagerService -ResourceGroupName $resourceGroupName -Name $serviceName -ServiceTopologyName $serviceTopology.Name } catch { @@ -185,7 +185,7 @@ function Test-ServiceUnit $parametersArtifactSourceRelativePath = "Parameters/WebApp.Parameters.json" $templateArtifactSourceRelativePath = "Templates/WebApp.Template.json" - $serviceUnit = New-AzureRmDeploymentManagerServiceUnit ` + $serviceUnit = New-AzDeploymentManagerServiceUnit ` -ResourceGroupName $resourceGroupName ` -Location $location ` -ServiceTopology $serviceTopology ` @@ -198,7 +198,7 @@ function Test-ServiceUnit Validate-ServiceUnit $serviceUnit $resourceGroupName $location $serviceTopology.Name $service.Name $serviceUnitName $targetResourceGroup $deploymentMode $templateArtifactSourceRelativePath $parametersArtifactSourceRelativePath - $getResponse = Get-AzureRmDeploymentManagerServiceUnit ` + $getResponse = Get-AzDeploymentManagerServiceUnit ` -ResourceGroupName $resourceGroupName ` -ServiceTopologyName $serviceTopology.Name ` -ServiceName $serviceName ` @@ -211,7 +211,7 @@ function Test-ServiceUnit $invalidParametersArtifactSourceRelativePath = "Parameters/WebApp.Invalid.Parameters.json" $invalidServiceUnitName = "Contoso_WebApp_Invalid" - $invalidServiceUnit = New-AzureRmDeploymentManagerServiceUnit ` + $invalidServiceUnit = New-AzDeploymentManagerServiceUnit ` -ResourceGroupName $resourceGroupName ` -Location $location ` -ServiceTopology $serviceTopology ` @@ -231,20 +231,20 @@ function Test-ServiceUnit $getResponse.ParametersArtifactSourceRelativePath = "Parameters/WebApp.Parameters.Dup.json" $getResponse.TemplateArtifactSourceRelativePath = "Templates/WebApp.Template.Dup.json" - $updatedServiceUnit = Set-AzureRmDeploymentManagerServiceUnit $getResponse + $updatedServiceUnit = Set-AzDeploymentManagerServiceUnit $getResponse Validate-ServiceUnit $updatedServiceUnit $resourceGroupName $location $serviceTopology.Name $service.Name $serviceUnitName $targetResourceGroup $getResponse.DeploymentMode $getResponse.TemplateArtifactSourceRelativePath $getResponse.ParametersArtifactSourceRelativePath # Test Remove-ServiceUnit - Remove-AzureRmDeploymentManagerServiceUnit -ResourceGroupName $resourceGroupName -ServiceTopologyName $serviceTopology.Name -ServiceName $service.Name -Name $serviceUnitName -Force + Remove-AzDeploymentManagerServiceUnit -ResourceGroupName $resourceGroupName -ServiceTopologyName $serviceTopology.Name -ServiceName $service.Name -Name $serviceUnitName -Force # Remove second service unit created for failure rollout case - Remove-AzureRmDeploymentManagerServiceUnit -ResourceGroupName $resourceGroupName -ServiceTopologyName $serviceTopology.Name -ServiceName $service.Name -Name $invalidServiceUnitName -Force + Remove-AzDeploymentManagerServiceUnit -ResourceGroupName $resourceGroupName -ServiceTopologyName $serviceTopology.Name -ServiceName $service.Name -Name $invalidServiceUnitName -Force $getResponse = $null try { - $getResponse = Get-AzureRmDeploymentManagerServiceUnit -ResourceGroupName $resourceGroupName -ServiceTopologyName $serviceTopology.Name -ServiceName $service.Name -Name $serviceUnitName + $getResponse = Get-AzDeploymentManagerServiceUnit -ResourceGroupName $resourceGroupName -ServiceTopologyName $serviceTopology.Name -ServiceName $service.Name -Name $serviceUnitName } catch { @@ -294,10 +294,10 @@ function Test-Steps $duration = "PT5M" $updatedDuration = "PT10M" - $step = New-AzureRmDeploymentManagerStep -Name $stepName -ResourceGroupName $resourceGroupName -Location $location -Duration $duration + $step = New-AzDeploymentManagerStep -Name $stepName -ResourceGroupName $resourceGroupName -Location $location -Duration $duration Validate-Step $step $stepName $location $resourceGroupName $duration - $getResponse = Get-AzureRmDeploymentManagerStep -ResourceGroupName $resourceGroupName -Name $stepName + $getResponse = Get-AzDeploymentManagerStep -ResourceGroupName $resourceGroupName -Name $stepName Validate-Step $getResponse $stepName $location $resourceGroupName $duration Test-Rollout $resourceGroupName $location $serviceTopology $artifactSource $serviceUnit @@ -305,16 +305,16 @@ function Test-Steps # Test Set-Step $getResponse.StepProperties.Duration = $updatedDuration - $updatedStep = Set-AzureRmDeploymentManagerStep $getResponse + $updatedStep = Set-AzDeploymentManagerStep $getResponse Validate-Step $updatedStep $stepName $location $resourceGroupName $updatedDuration # Test Remove-Step - Remove-AzureRmDeploymentManagerStep -ResourceGroupName $resourceGroupName -Name $stepName -Force + Remove-AzDeploymentManagerStep -ResourceGroupName $resourceGroupName -Name $stepName -Force $getResponse = $null try { - $getResponse = Get-AzureRmDeploymentManagerStep -ResourceGroupName $resourceGroupName -Name $stepName + $getResponse = Get-AzDeploymentManagerStep -ResourceGroupName $resourceGroupName -Name $stepName } catch { @@ -355,38 +355,38 @@ function Test-Rollout $rolloutName = "adm-powershell-tests-rollout" $failedRolloutName = "adm-powershell-tests-invalidRollout" - New-AzureRmResourceGroup -Name $rolloutName -Location $location - New-AzureRmResourceGroup -Name $failedRolloutName -Location $location + New-AzResourceGroup -Name $rolloutName -Location $location + New-AzResourceGroup -Name $failedRolloutName -Location $location - $deployment = New-AzureRmResourceGroupDeployment -Name $rolloutName -ResourceGroupName $rolloutName -TemplateFile ".\ScenarioTests\CreateRollout.json" + $deployment = New-AzResourceGroupDeployment -Name $rolloutName -ResourceGroupName $rolloutName -TemplateFile ".\ScenarioTests\CreateRollout.json" - $getResponse = Get-AzureRmDeploymentManagerRollout -ResourceGroupName $rolloutName -Name $rolloutName + $getResponse = Get-AzDeploymentManagerRollout -ResourceGroupName $rolloutName -Name $rolloutName Validate-Rollout $getResponse $rolloutName $location $rolloutName @('Running') $serviceTopology $artifactSource # Test Stop-Rollout - $canceledRollout = Stop-AzureRmDeploymentManagerRollout -Rollout $getResponse -Force + $canceledRollout = Stop-AzDeploymentManagerRollout -Rollout $getResponse -Force Validate-Rollout $canceledRollout $rolloutName $location $rolloutName @('Canceling', 'Canceled') $serviceTopology $artifactSource # Wait for rollout to finish while ($canceledRollout.Status -eq "Canceling") { Start-TestSleep 120000 - $canceledRollout = Get-AzureRmDeploymentManagerRollout -ResourceGroupName $rolloutName -Name $rolloutName + $canceledRollout = Get-AzDeploymentManagerRollout -ResourceGroupName $rolloutName -Name $rolloutName } Assert-AreEqual "Canceled" $canceledRollout.Status - $failedDeployment = New-AzureRmResourceGroupDeployment -Name $failedRolloutName -ResourceGroupName $failedRolloutName -TemplateFile ".\ScenarioTests\CreateRollout_FailureRollout.json" + $failedDeployment = New-AzResourceGroupDeployment -Name $failedRolloutName -ResourceGroupName $failedRolloutName -TemplateFile ".\ScenarioTests\CreateRollout_FailureRollout.json" $ErrorActionPreference = "SilentlyContinue" $Error.Clear() - $failedRollout = Get-AzureRmDeploymentManagerRollout -ResourceGroupName $failedRolloutName -Name $failedRolloutName 2>$null + $failedRollout = Get-AzDeploymentManagerRollout -ResourceGroupName $failedRolloutName -Name $failedRolloutName 2>$null # Wait for the invalid rollout to fail while ($failedRollout.Status -eq "Running") { Start-TestSleep 60000 - $failedRollout = Get-AzureRmDeploymentManagerRollout -ResourceGroupName $failedRolloutName -Name $failedRolloutName 2>$null + $failedRollout = Get-AzDeploymentManagerRollout -ResourceGroupName $failedRolloutName -Name $failedRolloutName 2>$null } $Error.Clear() @@ -395,11 +395,11 @@ function Test-Rollout # Write-Verbose "Completed assert on failed rollout. Restarting rollout" - $restartRollout = Restart-AzureRmDeploymentManagerRollout -ResourceGroupName $failedRolloutName -Name $failedRolloutName -SkipSucceeded + $restartRollout = Restart-AzDeploymentManagerRollout -ResourceGroupName $failedRolloutName -Name $failedRolloutName -SkipSucceeded Validate-Rollout $restartRollout $failedRolloutName $location $failedRolloutName @('Running') $serviceTopology $artifactSource $true 1 - Remove-AzureRmDeploymentManagerRollout -ResourceGroupName $rolloutName -Name $rolloutName -Force - $getResponse = Get-AzureRmDeploymentManagerRollout -ResourceGroupName $rolloutName -Name $rolloutName + Remove-AzDeploymentManagerRollout -ResourceGroupName $rolloutName -Name $rolloutName -Force + $getResponse = Get-AzDeploymentManagerRollout -ResourceGroupName $rolloutName -Name $rolloutName Assert-Null $getResponse } @@ -442,7 +442,7 @@ function New-ArtifactSource $sasKeyForContainer = "" Get-SasForContainer $storageAccountResourceGroup $storageAccountName $containerName ([ref]$sasKeyForContainer) - $artifactSource = New-AzureRmDeploymentManagerArtifactSource -ResourceGroupName $resourceGroupName -Name $artifactSourceName -Location $location -SasUri $sasKeyForContainer -ArtifactRoot $artifactRoot + $artifactSource = New-AzDeploymentManagerArtifactSource -ResourceGroupName $resourceGroupName -Name $artifactSourceName -Location $location -SasUri $sasKeyForContainer -ArtifactRoot $artifactRoot Assert-AreEqual $artifactSourceName $artifactSource.Name Assert-AreEqual $resourceGroupName $artifactSource.ResourceGroupName @@ -465,10 +465,10 @@ function Get-SasForContainer if ([Microsoft.Azure.Test.HttpRecorder.HttpMockServer]::Mode -ne [Microsoft.Azure.Test.HttpRecorder.HttpRecorderMode]::Playback) { # Get storage account context - $storageAccountContext = New-AzureStorageContext -StorageAccountName $storageName -StorageAccountKey (Get-AzureRmStorageAccountKey -ResourceGroupName $resourceGroupName -Name $storageName).Value[0] + $storageAccountContext = New-AzStorageContext -StorageAccountName $storageName -StorageAccountKey (Get-AzStorageAccountKey -ResourceGroupName $resourceGroupName -Name $storageName).Value[0] # Get SAS token for container - $sasKeyForContainer.Value = New-AzureStorageContainerSASToken -Name $storageContainerName -Permission "rl" -StartTime ([System.DateTime]::Now).AddHours(-20) -ExpiryTime ([System.DateTime]::Now).AddHours(48) -Context $storageAccountContext -FullUri + $sasKeyForContainer.Value = New-AzStorageContainerSASToken -Name $storageContainerName -Permission "rl" -StartTime ([System.DateTime]::Now).AddHours(-20) -ExpiryTime ([System.DateTime]::Now).AddHours(48) -Context $storageAccountContext -FullUri } else { diff --git a/src/DeploymentManager/Commands.DeploymentManager.Test/SessionRecords/Microsoft.Azure.Commands.DeploymentManager.Test.ScenarioTests.DeploymentManagerTests/EndToEndFunctionalTests.json b/src/DeploymentManager/DeploymentManager.Test/SessionRecords/Microsoft.Azure.Commands.DeploymentManager.Test.ScenarioTests.DeploymentManagerTests/EndToEndFunctionalTests.json similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager.Test/SessionRecords/Microsoft.Azure.Commands.DeploymentManager.Test.ScenarioTests.DeploymentManagerTests/EndToEndFunctionalTests.json rename to src/DeploymentManager/DeploymentManager.Test/SessionRecords/Microsoft.Azure.Commands.DeploymentManager.Test.ScenarioTests.DeploymentManagerTests/EndToEndFunctionalTests.json diff --git a/src/DeploymentManager/Commands.DeploymentManager.Test/packages.config b/src/DeploymentManager/DeploymentManager.Test/packages.config similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager.Test/packages.config rename to src/DeploymentManager/DeploymentManager.Test/packages.config diff --git a/src/DeploymentManager/DeploymentManager.sln b/src/DeploymentManager/DeploymentManager.sln index 23e95f95bedd..1d97877fa551 100644 --- a/src/DeploymentManager/DeploymentManager.sln +++ b/src/DeploymentManager/DeploymentManager.sln @@ -3,9 +3,21 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.28010.2003 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Commands.DeploymentManager", "Commands.DeploymentManager\Commands.DeploymentManager.csproj", "{F022ED20-7D3B-4BF4-88AF-F97CC50484DA}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DeploymentManager", "DeploymentManager\DeploymentManager.csproj", "{F022ED20-7D3B-4BF4-88AF-F97CC50484DA}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Commands.DeploymentManager.Test", "Commands.DeploymentManager.Test\Commands.DeploymentManager.Test.csproj", "{4AE5705F-62CF-461D-B72E-DD9DCD9B3609}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{1AA03B6B-C412-4D54-A8bE-FAA02234662B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DeploymentManager.Test", "DeploymentManager.Test\DeploymentManager.Test.csproj", "{4AE5705F-62CF-461D-B72E-DD9DCD9B3609}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Accounts", "..\Accounts\Accounts\Accounts.csproj", "{142D7B0B-388A-4CEB-A228-7F6D423C5C2E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Authentication", "..\Accounts\Authentication\Authentication.csproj", "{FF81DC73-B8EC-4082-8841-4FBF2B16E7CE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Authentication.ResourceManager", "..\Accounts\Authentication.ResourceManager\Authentication.ResourceManager.csproj", "{3E016018-D65D-4336-9F64-17DA97783AD0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ScenarioTest.ResourceManager", "..\..\tools\ScenarioTest.ResourceManager\ScenarioTest.ResourceManager.csproj", "{F83FBA8D-732D-437C-A0E2-02E45B01E123}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestFx", "..\..\tools\TestFx\TestFx.csproj", "{BC80A1D0-FFA4-43D9-AA74-799F5CB54B58}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -21,6 +33,26 @@ Global {4AE5705F-62CF-461D-B72E-DD9DCD9B3609}.Debug|Any CPU.Build.0 = Debug|Any CPU {4AE5705F-62CF-461D-B72E-DD9DCD9B3609}.Release|Any CPU.ActiveCfg = Release|Any CPU {4AE5705F-62CF-461D-B72E-DD9DCD9B3609}.Release|Any CPU.Build.0 = Release|Any CPU + {142D7B0B-388A-4CEB-A228-7F6D423C5C2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {142D7B0B-388A-4CEB-A228-7F6D423C5C2E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {142D7B0B-388A-4CEB-A228-7F6D423C5C2E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {142D7B0B-388A-4CEB-A228-7F6D423C5C2E}.Release|Any CPU.Build.0 = Release|Any CPU + {FF81DC73-B8EC-4082-8841-4FBF2B16E7CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FF81DC73-B8EC-4082-8841-4FBF2B16E7CE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FF81DC73-B8EC-4082-8841-4FBF2B16E7CE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FF81DC73-B8EC-4082-8841-4FBF2B16E7CE}.Release|Any CPU.Build.0 = Release|Any CPU + {3E016018-D65D-4336-9F64-17DA97783AD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3E016018-D65D-4336-9F64-17DA97783AD0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3E016018-D65D-4336-9F64-17DA97783AD0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3E016018-D65D-4336-9F64-17DA97783AD0}.Release|Any CPU.Build.0 = Release|Any CPU + {F83FBA8D-732D-437C-A0E2-02E45B01E123}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F83FBA8D-732D-437C-A0E2-02E45B01E123}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F83FBA8D-732D-437C-A0E2-02E45B01E123}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F83FBA8D-732D-437C-A0E2-02E45B01E123}.Release|Any CPU.Build.0 = Release|Any CPU + {BC80A1D0-FFA4-43D9-AA74-799F5CB54B58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BC80A1D0-FFA4-43D9-AA74-799F5CB54B58}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BC80A1D0-FFA4-43D9-AA74-799F5CB54B58}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BC80A1D0-FFA4-43D9-AA74-799F5CB54B58}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/DeploymentManager/Commands.DeploymentManager/Az.DeploymentManager.psd1 b/src/DeploymentManager/DeploymentManager/Az.DeploymentManager.psd1 similarity index 96% rename from src/DeploymentManager/Commands.DeploymentManager/Az.DeploymentManager.psd1 rename to src/DeploymentManager/DeploymentManager/Az.DeploymentManager.psd1 index bffa59102ad5..32df8e918e3f 100644 --- a/src/DeploymentManager/Commands.DeploymentManager/Az.DeploymentManager.psd1 +++ b/src/DeploymentManager/DeploymentManager/Az.DeploymentManager.psd1 @@ -15,7 +15,7 @@ ModuleVersion = '0.2.0' # Supported PSEditions -CompatiblePSEditions = 'Core' +CompatiblePSEditions = 'Core', 'Desktop' # ID used to uniquely identify this module GUID = 'caac1590-e859-444f-a9e0-62091c0f5929' @@ -42,7 +42,7 @@ PowerShellVersion = '5.1' # PowerShellHostVersion = '' # Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. -# DotNetFrameworkVersion = '' +DotNetFrameworkVersion = '4.7.2' # Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. # CLRVersion = '4.0' @@ -51,7 +51,7 @@ PowerShellVersion = '5.1' # ProcessorArchitecture = '' # Modules that must be imported into the global environment prior to importing this module -RequiredModules = @(@{ModuleName = 'Az.Profile'; ModuleVersion = '0.2.0'; }) +RequiredModules = @(@{ModuleName = 'Az.Accounts'; ModuleVersion = '1.4.0'; }) # Assemblies that must be loaded prior to importing this module RequiredAssemblies = '.\Microsoft.Azure.Management.DeploymentManager.dll' @@ -66,7 +66,7 @@ RequiredAssemblies = '.\Microsoft.Azure.Management.DeploymentManager.dll' # FormatsToProcess = '.\Microsoft.Azure.Commands.DeploymentManager.format.ps1xml' # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess -NestedModules = @('.\Microsoft.Azure.Commands.DeploymentManager.dll') +NestedModules = @('.\Microsoft.Azure.PowerShell.Cmdlets.DeploymentManager.dll') # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. FunctionsToExport = @() diff --git a/src/DeploymentManager/Commands.DeploymentManager/ChangeLog.md b/src/DeploymentManager/DeploymentManager/ChangeLog.md similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/ChangeLog.md rename to src/DeploymentManager/DeploymentManager/ChangeLog.md diff --git a/src/DeploymentManager/Commands.DeploymentManager/Client/DeploymentManagerClient.cs b/src/DeploymentManager/DeploymentManager/Client/DeploymentManagerClient.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Client/DeploymentManagerClient.cs rename to src/DeploymentManager/DeploymentManager/Client/DeploymentManagerClient.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/DeploymentManagerBaseCmdlet.cs b/src/DeploymentManager/DeploymentManager/Commands/DeploymentManagerBaseCmdlet.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Commands/DeploymentManagerBaseCmdlet.cs rename to src/DeploymentManager/DeploymentManager/Commands/DeploymentManagerBaseCmdlet.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/GetArtifactSource.cs b/src/DeploymentManager/DeploymentManager/Commands/GetArtifactSource.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Commands/GetArtifactSource.cs rename to src/DeploymentManager/DeploymentManager/Commands/GetArtifactSource.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/GetRollout.cs b/src/DeploymentManager/DeploymentManager/Commands/GetRollout.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Commands/GetRollout.cs rename to src/DeploymentManager/DeploymentManager/Commands/GetRollout.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/GetService.cs b/src/DeploymentManager/DeploymentManager/Commands/GetService.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Commands/GetService.cs rename to src/DeploymentManager/DeploymentManager/Commands/GetService.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/GetServiceTopology.cs b/src/DeploymentManager/DeploymentManager/Commands/GetServiceTopology.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Commands/GetServiceTopology.cs rename to src/DeploymentManager/DeploymentManager/Commands/GetServiceTopology.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/GetServiceUnit.cs b/src/DeploymentManager/DeploymentManager/Commands/GetServiceUnit.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Commands/GetServiceUnit.cs rename to src/DeploymentManager/DeploymentManager/Commands/GetServiceUnit.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/GetStep.cs b/src/DeploymentManager/DeploymentManager/Commands/GetStep.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Commands/GetStep.cs rename to src/DeploymentManager/DeploymentManager/Commands/GetStep.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/NewArtifactSource.cs b/src/DeploymentManager/DeploymentManager/Commands/NewArtifactSource.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Commands/NewArtifactSource.cs rename to src/DeploymentManager/DeploymentManager/Commands/NewArtifactSource.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/NewService.cs b/src/DeploymentManager/DeploymentManager/Commands/NewService.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Commands/NewService.cs rename to src/DeploymentManager/DeploymentManager/Commands/NewService.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/NewServiceTopology.cs b/src/DeploymentManager/DeploymentManager/Commands/NewServiceTopology.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Commands/NewServiceTopology.cs rename to src/DeploymentManager/DeploymentManager/Commands/NewServiceTopology.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/NewServiceUnit.cs b/src/DeploymentManager/DeploymentManager/Commands/NewServiceUnit.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Commands/NewServiceUnit.cs rename to src/DeploymentManager/DeploymentManager/Commands/NewServiceUnit.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/NewStep.cs b/src/DeploymentManager/DeploymentManager/Commands/NewStep.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Commands/NewStep.cs rename to src/DeploymentManager/DeploymentManager/Commands/NewStep.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveArtifactSource.cs b/src/DeploymentManager/DeploymentManager/Commands/RemoveArtifactSource.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveArtifactSource.cs rename to src/DeploymentManager/DeploymentManager/Commands/RemoveArtifactSource.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveRollout.cs b/src/DeploymentManager/DeploymentManager/Commands/RemoveRollout.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveRollout.cs rename to src/DeploymentManager/DeploymentManager/Commands/RemoveRollout.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveService.cs b/src/DeploymentManager/DeploymentManager/Commands/RemoveService.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveService.cs rename to src/DeploymentManager/DeploymentManager/Commands/RemoveService.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveServiceTopology.cs b/src/DeploymentManager/DeploymentManager/Commands/RemoveServiceTopology.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveServiceTopology.cs rename to src/DeploymentManager/DeploymentManager/Commands/RemoveServiceTopology.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveServiceUnit.cs b/src/DeploymentManager/DeploymentManager/Commands/RemoveServiceUnit.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveServiceUnit.cs rename to src/DeploymentManager/DeploymentManager/Commands/RemoveServiceUnit.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveStep.cs b/src/DeploymentManager/DeploymentManager/Commands/RemoveStep.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Commands/RemoveStep.cs rename to src/DeploymentManager/DeploymentManager/Commands/RemoveStep.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/RestartRollout.cs b/src/DeploymentManager/DeploymentManager/Commands/RestartRollout.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Commands/RestartRollout.cs rename to src/DeploymentManager/DeploymentManager/Commands/RestartRollout.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/RolloutCmdletBase.cs b/src/DeploymentManager/DeploymentManager/Commands/RolloutCmdletBase.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Commands/RolloutCmdletBase.cs rename to src/DeploymentManager/DeploymentManager/Commands/RolloutCmdletBase.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/SetArtifactSource.cs b/src/DeploymentManager/DeploymentManager/Commands/SetArtifactSource.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Commands/SetArtifactSource.cs rename to src/DeploymentManager/DeploymentManager/Commands/SetArtifactSource.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/SetService.cs b/src/DeploymentManager/DeploymentManager/Commands/SetService.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Commands/SetService.cs rename to src/DeploymentManager/DeploymentManager/Commands/SetService.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/SetServiceTopology.cs b/src/DeploymentManager/DeploymentManager/Commands/SetServiceTopology.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Commands/SetServiceTopology.cs rename to src/DeploymentManager/DeploymentManager/Commands/SetServiceTopology.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/SetServiceUnit.cs b/src/DeploymentManager/DeploymentManager/Commands/SetServiceUnit.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Commands/SetServiceUnit.cs rename to src/DeploymentManager/DeploymentManager/Commands/SetServiceUnit.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/SetStep.cs b/src/DeploymentManager/DeploymentManager/Commands/SetStep.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Commands/SetStep.cs rename to src/DeploymentManager/DeploymentManager/Commands/SetStep.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands/StopRollout.cs b/src/DeploymentManager/DeploymentManager/Commands/StopRollout.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Commands/StopRollout.cs rename to src/DeploymentManager/DeploymentManager/Commands/StopRollout.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Commands.DeploymentManager.csproj b/src/DeploymentManager/DeploymentManager/DeploymentManager.csproj similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Commands.DeploymentManager.csproj rename to src/DeploymentManager/DeploymentManager/DeploymentManager.csproj diff --git a/src/DeploymentManager/Commands.DeploymentManager/MSSharedLibKey.snk b/src/DeploymentManager/DeploymentManager/MSSharedLibKey.snk similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/MSSharedLibKey.snk rename to src/DeploymentManager/DeploymentManager/MSSharedLibKey.snk diff --git a/src/DeploymentManager/Commands.DeploymentManager/Messages.Designer.cs b/src/DeploymentManager/DeploymentManager/Messages.Designer.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Messages.Designer.cs rename to src/DeploymentManager/DeploymentManager/Messages.Designer.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Messages.resx b/src/DeploymentManager/DeploymentManager/Messages.resx similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Messages.resx rename to src/DeploymentManager/DeploymentManager/Messages.resx diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/ArtifactSource/PSArtifactSource.cs b/src/DeploymentManager/DeploymentManager/Models/ArtifactSource/PSArtifactSource.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Models/ArtifactSource/PSArtifactSource.cs rename to src/DeploymentManager/DeploymentManager/Models/ArtifactSource/PSArtifactSource.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/ArtifactSource/PSAuthentication.cs b/src/DeploymentManager/DeploymentManager/Models/ArtifactSource/PSAuthentication.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Models/ArtifactSource/PSAuthentication.cs rename to src/DeploymentManager/DeploymentManager/Models/ArtifactSource/PSAuthentication.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/ArtifactSource/PSSasAuthentication.cs b/src/DeploymentManager/DeploymentManager/Models/ArtifactSource/PSSasAuthentication.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Models/ArtifactSource/PSSasAuthentication.cs rename to src/DeploymentManager/DeploymentManager/Models/ArtifactSource/PSSasAuthentication.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/PSIdentity.cs b/src/DeploymentManager/DeploymentManager/Models/PSIdentity.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Models/PSIdentity.cs rename to src/DeploymentManager/DeploymentManager/Models/PSIdentity.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSBaseOperationInfo.cs b/src/DeploymentManager/DeploymentManager/Models/Rollout/PSBaseOperationInfo.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSBaseOperationInfo.cs rename to src/DeploymentManager/DeploymentManager/Models/Rollout/PSBaseOperationInfo.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSMessage.cs b/src/DeploymentManager/DeploymentManager/Models/Rollout/PSMessage.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSMessage.cs rename to src/DeploymentManager/DeploymentManager/Models/Rollout/PSMessage.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSResource.cs b/src/DeploymentManager/DeploymentManager/Models/Rollout/PSResource.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSResource.cs rename to src/DeploymentManager/DeploymentManager/Models/Rollout/PSResource.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSResourceOperation.cs b/src/DeploymentManager/DeploymentManager/Models/Rollout/PSResourceOperation.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSResourceOperation.cs rename to src/DeploymentManager/DeploymentManager/Models/Rollout/PSResourceOperation.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSRollout.cs b/src/DeploymentManager/DeploymentManager/Models/Rollout/PSRollout.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSRollout.cs rename to src/DeploymentManager/DeploymentManager/Models/Rollout/PSRollout.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSRolloutOperationInfo.cs b/src/DeploymentManager/DeploymentManager/Models/Rollout/PSRolloutOperationInfo.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSRolloutOperationInfo.cs rename to src/DeploymentManager/DeploymentManager/Models/Rollout/PSRolloutOperationInfo.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSRolloutStep.cs b/src/DeploymentManager/DeploymentManager/Models/Rollout/PSRolloutStep.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSRolloutStep.cs rename to src/DeploymentManager/DeploymentManager/Models/Rollout/PSRolloutStep.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSService.cs b/src/DeploymentManager/DeploymentManager/Models/Rollout/PSService.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSService.cs rename to src/DeploymentManager/DeploymentManager/Models/Rollout/PSService.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSServiceUnit.cs b/src/DeploymentManager/DeploymentManager/Models/Rollout/PSServiceUnit.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSServiceUnit.cs rename to src/DeploymentManager/DeploymentManager/Models/Rollout/PSServiceUnit.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSStepOperationInfo.cs b/src/DeploymentManager/DeploymentManager/Models/Rollout/PSStepOperationInfo.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Models/Rollout/PSStepOperationInfo.cs rename to src/DeploymentManager/DeploymentManager/Models/Rollout/PSStepOperationInfo.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/ServiceTopology/PSServiceResource.cs b/src/DeploymentManager/DeploymentManager/Models/ServiceTopology/PSServiceResource.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Models/ServiceTopology/PSServiceResource.cs rename to src/DeploymentManager/DeploymentManager/Models/ServiceTopology/PSServiceResource.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/ServiceTopology/PSServiceTopologyResource.cs b/src/DeploymentManager/DeploymentManager/Models/ServiceTopology/PSServiceTopologyResource.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Models/ServiceTopology/PSServiceTopologyResource.cs rename to src/DeploymentManager/DeploymentManager/Models/ServiceTopology/PSServiceTopologyResource.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/ServiceTopology/PSServiceUnitResource.cs b/src/DeploymentManager/DeploymentManager/Models/ServiceTopology/PSServiceUnitResource.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Models/ServiceTopology/PSServiceUnitResource.cs rename to src/DeploymentManager/DeploymentManager/Models/ServiceTopology/PSServiceUnitResource.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/Steps/PSStepProperties.cs b/src/DeploymentManager/DeploymentManager/Models/Steps/PSStepProperties.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Models/Steps/PSStepProperties.cs rename to src/DeploymentManager/DeploymentManager/Models/Steps/PSStepProperties.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/Steps/PSStepResource.cs b/src/DeploymentManager/DeploymentManager/Models/Steps/PSStepResource.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Models/Steps/PSStepResource.cs rename to src/DeploymentManager/DeploymentManager/Models/Steps/PSStepResource.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Models/Steps/PSWaitStepProperties.cs b/src/DeploymentManager/DeploymentManager/Models/Steps/PSWaitStepProperties.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Models/Steps/PSWaitStepProperties.cs rename to src/DeploymentManager/DeploymentManager/Models/Steps/PSWaitStepProperties.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Properties/AssemblyInfo.cs b/src/DeploymentManager/DeploymentManager/Properties/AssemblyInfo.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Properties/AssemblyInfo.cs rename to src/DeploymentManager/DeploymentManager/Properties/AssemblyInfo.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Utilities/EnumerationUtilities.cs b/src/DeploymentManager/DeploymentManager/Utilities/EnumerationUtilities.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Utilities/EnumerationUtilities.cs rename to src/DeploymentManager/DeploymentManager/Utilities/EnumerationUtilities.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/Utilities/StringUtilities.cs b/src/DeploymentManager/DeploymentManager/Utilities/StringUtilities.cs similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/Utilities/StringUtilities.cs rename to src/DeploymentManager/DeploymentManager/Utilities/StringUtilities.cs diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/AzureRM.DeploymentManager.md b/src/DeploymentManager/DeploymentManager/help/AzureRM.DeploymentManager.md similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/help/AzureRM.DeploymentManager.md rename to src/DeploymentManager/DeploymentManager/help/AzureRM.DeploymentManager.md diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerArtifactSource.md b/src/DeploymentManager/DeploymentManager/help/Get-AzureRmDeploymentManagerArtifactSource.md similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerArtifactSource.md rename to src/DeploymentManager/DeploymentManager/help/Get-AzureRmDeploymentManagerArtifactSource.md diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerRollout.md b/src/DeploymentManager/DeploymentManager/help/Get-AzureRmDeploymentManagerRollout.md similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerRollout.md rename to src/DeploymentManager/DeploymentManager/help/Get-AzureRmDeploymentManagerRollout.md diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerService.md b/src/DeploymentManager/DeploymentManager/help/Get-AzureRmDeploymentManagerService.md similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerService.md rename to src/DeploymentManager/DeploymentManager/help/Get-AzureRmDeploymentManagerService.md diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerServiceTopology.md b/src/DeploymentManager/DeploymentManager/help/Get-AzureRmDeploymentManagerServiceTopology.md similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerServiceTopology.md rename to src/DeploymentManager/DeploymentManager/help/Get-AzureRmDeploymentManagerServiceTopology.md diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerServiceUnit.md b/src/DeploymentManager/DeploymentManager/help/Get-AzureRmDeploymentManagerServiceUnit.md similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerServiceUnit.md rename to src/DeploymentManager/DeploymentManager/help/Get-AzureRmDeploymentManagerServiceUnit.md diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerStep.md b/src/DeploymentManager/DeploymentManager/help/Get-AzureRmDeploymentManagerStep.md similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/help/Get-AzureRmDeploymentManagerStep.md rename to src/DeploymentManager/DeploymentManager/help/Get-AzureRmDeploymentManagerStep.md diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Microsoft.Azure.Commands.DeploymentManager.md b/src/DeploymentManager/DeploymentManager/help/Microsoft.Azure.Commands.DeploymentManager.md similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/help/Microsoft.Azure.Commands.DeploymentManager.md rename to src/DeploymentManager/DeploymentManager/help/Microsoft.Azure.Commands.DeploymentManager.md diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/New-AzureRmDeploymentManagerArtifactSource.md b/src/DeploymentManager/DeploymentManager/help/New-AzureRmDeploymentManagerArtifactSource.md similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/help/New-AzureRmDeploymentManagerArtifactSource.md rename to src/DeploymentManager/DeploymentManager/help/New-AzureRmDeploymentManagerArtifactSource.md diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/New-AzureRmDeploymentManagerService.md b/src/DeploymentManager/DeploymentManager/help/New-AzureRmDeploymentManagerService.md similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/help/New-AzureRmDeploymentManagerService.md rename to src/DeploymentManager/DeploymentManager/help/New-AzureRmDeploymentManagerService.md diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/New-AzureRmDeploymentManagerServiceTopology.md b/src/DeploymentManager/DeploymentManager/help/New-AzureRmDeploymentManagerServiceTopology.md similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/help/New-AzureRmDeploymentManagerServiceTopology.md rename to src/DeploymentManager/DeploymentManager/help/New-AzureRmDeploymentManagerServiceTopology.md diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/New-AzureRmDeploymentManagerServiceUnit.md b/src/DeploymentManager/DeploymentManager/help/New-AzureRmDeploymentManagerServiceUnit.md similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/help/New-AzureRmDeploymentManagerServiceUnit.md rename to src/DeploymentManager/DeploymentManager/help/New-AzureRmDeploymentManagerServiceUnit.md diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/New-AzureRmDeploymentManagerStep.md b/src/DeploymentManager/DeploymentManager/help/New-AzureRmDeploymentManagerStep.md similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/help/New-AzureRmDeploymentManagerStep.md rename to src/DeploymentManager/DeploymentManager/help/New-AzureRmDeploymentManagerStep.md diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerArtifactSource.md b/src/DeploymentManager/DeploymentManager/help/Remove-AzureRmDeploymentManagerArtifactSource.md similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerArtifactSource.md rename to src/DeploymentManager/DeploymentManager/help/Remove-AzureRmDeploymentManagerArtifactSource.md diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerRollout.md b/src/DeploymentManager/DeploymentManager/help/Remove-AzureRmDeploymentManagerRollout.md similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerRollout.md rename to src/DeploymentManager/DeploymentManager/help/Remove-AzureRmDeploymentManagerRollout.md diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerService.md b/src/DeploymentManager/DeploymentManager/help/Remove-AzureRmDeploymentManagerService.md similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerService.md rename to src/DeploymentManager/DeploymentManager/help/Remove-AzureRmDeploymentManagerService.md diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerServiceTopology.md b/src/DeploymentManager/DeploymentManager/help/Remove-AzureRmDeploymentManagerServiceTopology.md similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerServiceTopology.md rename to src/DeploymentManager/DeploymentManager/help/Remove-AzureRmDeploymentManagerServiceTopology.md diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerServiceUnit.md b/src/DeploymentManager/DeploymentManager/help/Remove-AzureRmDeploymentManagerServiceUnit.md similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerServiceUnit.md rename to src/DeploymentManager/DeploymentManager/help/Remove-AzureRmDeploymentManagerServiceUnit.md diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerStep.md b/src/DeploymentManager/DeploymentManager/help/Remove-AzureRmDeploymentManagerStep.md similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/help/Remove-AzureRmDeploymentManagerStep.md rename to src/DeploymentManager/DeploymentManager/help/Remove-AzureRmDeploymentManagerStep.md diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Restart-AzureRmDeploymentManagerRollout.md b/src/DeploymentManager/DeploymentManager/help/Restart-AzureRmDeploymentManagerRollout.md similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/help/Restart-AzureRmDeploymentManagerRollout.md rename to src/DeploymentManager/DeploymentManager/help/Restart-AzureRmDeploymentManagerRollout.md diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Set-AzureRmDeploymentManagerArtifactSource.md b/src/DeploymentManager/DeploymentManager/help/Set-AzureRmDeploymentManagerArtifactSource.md similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/help/Set-AzureRmDeploymentManagerArtifactSource.md rename to src/DeploymentManager/DeploymentManager/help/Set-AzureRmDeploymentManagerArtifactSource.md diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Set-AzureRmDeploymentManagerService.md b/src/DeploymentManager/DeploymentManager/help/Set-AzureRmDeploymentManagerService.md similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/help/Set-AzureRmDeploymentManagerService.md rename to src/DeploymentManager/DeploymentManager/help/Set-AzureRmDeploymentManagerService.md diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Set-AzureRmDeploymentManagerServiceTopology.md b/src/DeploymentManager/DeploymentManager/help/Set-AzureRmDeploymentManagerServiceTopology.md similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/help/Set-AzureRmDeploymentManagerServiceTopology.md rename to src/DeploymentManager/DeploymentManager/help/Set-AzureRmDeploymentManagerServiceTopology.md diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Set-AzureRmDeploymentManagerServiceUnit.md b/src/DeploymentManager/DeploymentManager/help/Set-AzureRmDeploymentManagerServiceUnit.md similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/help/Set-AzureRmDeploymentManagerServiceUnit.md rename to src/DeploymentManager/DeploymentManager/help/Set-AzureRmDeploymentManagerServiceUnit.md diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Set-AzureRmDeploymentManagerStep.md b/src/DeploymentManager/DeploymentManager/help/Set-AzureRmDeploymentManagerStep.md similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/help/Set-AzureRmDeploymentManagerStep.md rename to src/DeploymentManager/DeploymentManager/help/Set-AzureRmDeploymentManagerStep.md diff --git a/src/DeploymentManager/Commands.DeploymentManager/help/Stop-AzureRmDeploymentManagerRollout.md b/src/DeploymentManager/DeploymentManager/help/Stop-AzureRmDeploymentManagerRollout.md similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/help/Stop-AzureRmDeploymentManagerRollout.md rename to src/DeploymentManager/DeploymentManager/help/Stop-AzureRmDeploymentManagerRollout.md diff --git a/src/DeploymentManager/Commands.DeploymentManager/packages.config b/src/DeploymentManager/DeploymentManager/packages.config similarity index 100% rename from src/DeploymentManager/Commands.DeploymentManager/packages.config rename to src/DeploymentManager/DeploymentManager/packages.config diff --git a/tools/LocalFeed/Microsoft.Azure.Management.DeploymentManager.0.9.0-preview.nupkg b/tools/LocalFeed/Microsoft.Azure.Management.DeploymentManager.0.9.0-preview.nupkg index ab519b1b55cfe1f20d12c4a7653014783c61019c..109160c72dbb11c04c49aee8bc869aa74c43167d 100644 GIT binary patch delta 101365 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 delta 97641 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