Skip to content

Commit 663aa42

Browse files
author
Maddie Clayton
authored
Merge pull request Azure#6137 from cormacpayne/populate-contexts
Populate context list when no previous context found
2 parents c6ac71b + 3ba9c7f commit 663aa42

File tree

7 files changed

+186
-52
lines changed

7 files changed

+186
-52
lines changed

src/ResourceManager/Profile/ChangeLog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
- Additional information about change #1
1919
-->
2020
## Current Release
21+
* Create a context for each subscription when running `Connect-AzureRmAccount` with no previous context
2122

2223
## Version 5.2.0
2324
* Added the following three values to the telemetry:

src/ResourceManager/Profile/Commands.Profile.Test/LoginCmdletTests.cs

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
using Microsoft.Azure.Commands.Common.Authentication.Abstractions;
3232
using Microsoft.Azure.Commands.ResourceManager.Common;
3333
using Microsoft.Azure.Commands.ScenarioTest;
34+
using System.Linq;
3435

3536
namespace Microsoft.Azure.Commands.Profile.Test
3637
{
@@ -327,7 +328,7 @@ public void LoginWithCredentialParameterAndMSA()
327328
"For more information, please refer to http://go.microsoft.com/fwlink/?linkid=331007&clcid=0x409 " +
328329
"for more information about the difference between an organizational account and a Microsoft account.",
329330
ex.Message);
330-
}
331+
}
331332
}
332333

333334
[Fact]
@@ -353,6 +354,43 @@ public void LoginWithAccessToken()
353354
Assert.NotNull(AzureRmProfileProvider.Instance.Profile.DefaultContext);
354355
}
355356

357+
[Fact]
358+
[Trait(Category.RunType, Category.LiveOnly)]
359+
public void LoginPopulatesContextList()
360+
{
361+
// Before running this test, make sure to clear the contexts on your machine by removing the following two files:
362+
// - %APPDATA%/Windows Azure Powershell/AzureRmContext.json
363+
// - %APPDATA%/Windows Azure Powershell/AzureRmContextSettings.json
364+
// This will clear all existing contexts on your machine so that this test can re-populate the list with a context for each subscription
365+
366+
var cmdlt = new ConnectAzureRmAccountCommand();
367+
// Setup
368+
cmdlt.CommandRuntime = commandRuntimeMock;
369+
370+
// Act
371+
cmdlt.InvokeBeginProcessing();
372+
cmdlt.ExecuteCmdlet();
373+
cmdlt.InvokeEndProcessing();
374+
375+
var profile = AzureRmProfileProvider.Instance.Profile as AzureRmProfile;
376+
Assert.NotNull(profile);
377+
Assert.NotNull(profile.Contexts);
378+
Assert.NotNull(profile.Subscriptions);
379+
Assert.True(profile.Contexts.Count > 1);
380+
Assert.True(profile.Subscriptions.Count() > 1);
381+
Assert.Equal(profile.Subscriptions.Count(), profile.Contexts.Count);
382+
383+
foreach (var sub in profile.Subscriptions)
384+
{
385+
var contextName = string.Format("{0} - {1}", sub.Name, sub.Id);
386+
Assert.True(profile.Contexts.ContainsKey(contextName));
387+
var context = profile.Contexts[contextName];
388+
Assert.NotNull(context);
389+
Assert.Equal(sub.Id, context.Subscription.Id);
390+
Assert.Equal(sub.GetTenant(), context.Tenant.Id);
391+
}
392+
}
393+
356394
[Fact]
357395
[Trait(Category.AcceptanceType, Category.CheckIn)]
358396
public void ThrowOnUnknownEnvironment()

src/ResourceManager/Profile/Commands.Profile/Account/ConnectAzureRmAccount.cs

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public class ConnectAzureRmAccountCommand : AzureContextModificationCmdlet, IMod
5050
[Alias("EnvironmentName")]
5151
[ValidateNotNullOrEmpty]
5252
public string Environment { get; set; }
53-
53+
5454
#if !NETSTANDARD
5555
[Parameter(ParameterSetName = UserParameterSet,
5656
Mandatory = false, HelpMessage = "Optional credential", Position = 0)]
@@ -59,35 +59,35 @@ public class ConnectAzureRmAccountCommand : AzureContextModificationCmdlet, IMod
5959
Mandatory = true, HelpMessage = "Credential")]
6060
public PSCredential Credential { get; set; }
6161

62-
[Parameter(ParameterSetName = ServicePrincipalCertificateParameterSet,
62+
[Parameter(ParameterSetName = ServicePrincipalCertificateParameterSet,
6363
Mandatory = true, HelpMessage = "Certificate Hash (Thumbprint)")]
6464
public string CertificateThumbprint { get; set; }
65-
66-
[Parameter(ParameterSetName = ServicePrincipalCertificateParameterSet,
65+
66+
[Parameter(ParameterSetName = ServicePrincipalCertificateParameterSet,
6767
Mandatory = true, HelpMessage = "SPN")]
6868
public string ApplicationId { get; set; }
6969

70-
[Parameter(ParameterSetName = ServicePrincipalParameterSet,
70+
[Parameter(ParameterSetName = ServicePrincipalParameterSet,
7171
Mandatory = true)]
72-
[Parameter(ParameterSetName = ServicePrincipalCertificateParameterSet,
72+
[Parameter(ParameterSetName = ServicePrincipalCertificateParameterSet,
7373
Mandatory = true)]
7474
public SwitchParameter ServicePrincipal { get; set; }
75-
76-
[Parameter(ParameterSetName = UserParameterSet,
75+
76+
[Parameter(ParameterSetName = UserParameterSet,
7777
Mandatory = false, HelpMessage = "Optional tenant name or ID")]
78-
[Parameter(ParameterSetName = ServicePrincipalParameterSet,
78+
[Parameter(ParameterSetName = ServicePrincipalParameterSet,
7979
Mandatory = true, HelpMessage = "Tenant name or ID")]
80-
[Parameter(ParameterSetName = AccessTokenParameterSet,
80+
[Parameter(ParameterSetName = AccessTokenParameterSet,
8181
Mandatory = false, HelpMessage = "Tenant name or ID")]
82-
[Parameter(ParameterSetName = ServicePrincipalCertificateParameterSet,
82+
[Parameter(ParameterSetName = ServicePrincipalCertificateParameterSet,
8383
Mandatory = true, HelpMessage = "Tenant name or ID")]
8484
[Parameter(ParameterSetName = ManagedServiceParameterSet,
8585
Mandatory = false, HelpMessage = "Optional tenant name or ID")]
8686
[Alias("Domain")]
8787
[ValidateNotNullOrEmpty]
8888
public string TenantId { get; set; }
89-
90-
[Parameter(ParameterSetName = AccessTokenParameterSet,
89+
90+
[Parameter(ParameterSetName = AccessTokenParameterSet,
9191
Mandatory = true, HelpMessage = "AccessToken for Azure Resource Manager")]
9292
[ValidateNotNullOrEmpty]
9393
public string AccessToken { get; set; }
@@ -101,8 +101,8 @@ public class ConnectAzureRmAccountCommand : AzureContextModificationCmdlet, IMod
101101
Mandatory = false, HelpMessage = "AccessToken for KeyVault Service")]
102102
[ValidateNotNullOrEmpty]
103103
public string KeyVaultAccessToken { get; set; }
104-
105-
[Parameter(ParameterSetName = AccessTokenParameterSet,
104+
105+
[Parameter(ParameterSetName = AccessTokenParameterSet,
106106
Mandatory = true, HelpMessage = "Account Id for access token")]
107107
[Parameter(ParameterSetName = ManagedServiceParameterSet,
108108
Mandatory = false, HelpMessage = "Account Id for managed service. Can be a managed service resource Id, or the associated client id. To use the SyatemAssigned identity, leave this field blank.")]
@@ -148,6 +148,9 @@ public class ConnectAzureRmAccountCommand : AzureContextModificationCmdlet, IMod
148148
Mandatory = false, HelpMessage = "Skip validation for access token")]
149149
public SwitchParameter SkipValidation { get; set; }
150150

151+
[Parameter(Mandatory = false, HelpMessage = "Skips context population if no contexts are found.")]
152+
public SwitchParameter SkipContextPopulation { get; set; }
153+
151154
[Parameter(Mandatory = false, HelpMessage = "Overwrite the existing context with the same name, if any.")]
152155
public SwitchParameter Force { get; set; }
153156

@@ -214,8 +217,8 @@ public override void ExecuteCmdlet()
214217
builder.Port = ManagedServicePort;
215218
builder.Path = "/oauth2/token";
216219

217-
string msiSecret = this.IsBound(nameof(ManagedServiceSecret))
218-
? ManagedServiceSecret.ConvertToString()
220+
string msiSecret = this.IsBound(nameof(ManagedServiceSecret))
221+
? ManagedServiceSecret.ConvertToString()
219222
: System.Environment.GetEnvironmentVariable(MSISecretVariable);
220223

221224
string suppliedUri = this.IsBound(nameof(ManagedServiceHostName))
@@ -226,7 +229,7 @@ public override void ExecuteCmdlet()
226229
{
227230
azureAccount.SetProperty(AzureAccount.Property.MSILoginSecret, msiSecret);
228231
}
229-
232+
230233
if (!string.IsNullOrWhiteSpace(suppliedUri))
231234
{
232235
azureAccount.SetProperty(AzureAccount.Property.MSILoginUri, suppliedUri);
@@ -255,7 +258,7 @@ public override void ExecuteCmdlet()
255258
{
256259
azureAccount.Id = ApplicationId;
257260
}
258-
261+
259262
if (!string.IsNullOrWhiteSpace(CertificateThumbprint))
260263
{
261264
azureAccount.SetThumbprint(CertificateThumbprint);
@@ -284,7 +287,8 @@ public override void ExecuteCmdlet()
284287
password,
285288
SkipValidation,
286289
(s) => WriteWarning(s),
287-
name));
290+
name,
291+
!this.SkipContextPopulation.IsPresent));
288292
});
289293
}
290294
}
@@ -330,7 +334,7 @@ public void OnImport()
330334
#if DEBUG
331335
}
332336
#endif
333-
337+
334338
bool autoSaveEnabled = AzureSession.Instance.ARMContextSaveMode == ContextSaveMode.CurrentUser;
335339
var autosaveVariable = System.Environment.GetEnvironmentVariable(AzureProfileConstants.AzureAutosaveVariable);
336340
bool localAutosave;

src/ResourceManager/Profile/Commands.Profile/Models/RMProfileClient.cs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,8 @@ public AzureRmProfile Login(
109109
SecureString password,
110110
bool skipValidation,
111111
Action<string> promptAction,
112-
string name = null)
112+
string name = null,
113+
bool shouldPopulateContextList = true)
113114
{
114115
IAzureSubscription newSubscription = null;
115116
IAzureTenant newTenant = null;
@@ -226,6 +227,7 @@ public AzureRmProfile Login(
226227
}
227228
}
228229

230+
shouldPopulateContextList &= _profile.DefaultContext?.Account == null;
229231
if (newSubscription == null)
230232
{
231233
if (subscriptionId != null)
@@ -260,6 +262,35 @@ public AzureRmProfile Login(
260262
}
261263

262264
_profile.DefaultContext.TokenCache = _cache;
265+
if (shouldPopulateContextList)
266+
{
267+
var defaultContext = _profile.DefaultContext;
268+
var subscriptions = ListSubscriptions(tenantId).Take(25);
269+
foreach (var subscription in subscriptions)
270+
{
271+
IAzureTenant tempTenant = new AzureTenant()
272+
{
273+
Id = subscription.GetProperty(AzureSubscription.Property.Tenants)
274+
};
275+
276+
var tempContext = new AzureContext(subscription, account, environment, tempTenant);
277+
tempContext.TokenCache = _cache;
278+
string tempName = null;
279+
if (!_profile.TryGetContextName(tempContext, out tempName))
280+
{
281+
WriteWarningMessage(string.Format(Resources.CannotGetContextName, subscription.Id));
282+
continue;
283+
}
284+
285+
if (!_profile.TrySetContext(tempName, tempContext))
286+
{
287+
WriteWarningMessage(string.Format(Resources.CannotCreateContext, subscription.Id));
288+
}
289+
}
290+
291+
_profile.TrySetDefaultContext(defaultContext);
292+
_profile.TryRemoveContext("Default");
293+
}
263294

264295
return _profile.ToProfile();
265296
}

src/ResourceManager/Profile/Commands.Profile/Properties/Resources.Designer.cs

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/ResourceManager/Profile/Commands.Profile/Properties/Resources.resx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,4 +406,12 @@
406406
<data name="RunLoginCmdlet" xml:space="preserve">
407407
<value>Run Connect-AzureRmAccount to login.</value>
408408
</data>
409+
<data name="CannotCreateContext" xml:space="preserve">
410+
<value>Cannot create a context for subscription with id '{0}'.</value>
411+
<comment>{0} = subscription id</comment>
412+
</data>
413+
<data name="CannotGetContextName" xml:space="preserve">
414+
<value>Unable to get context name for subscription with id '{0}'.</value>
415+
<comment>{0} = subscription id</comment>
416+
</data>
409417
</root>

0 commit comments

Comments
 (0)