src/common/details/azcli/AzCliConsoleGui_SubscriptionPicker.cs (154 lines of code) (raw):
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.md file in the project root for full license information.
//
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Net;
using Azure.AI.Details.Common.CLI.ConsoleGui;
namespace Azure.AI.Details.Common.CLI
{
public partial class AzCliConsoleGui
{
public static string GetSubscriptionUserName(string subscriptionId)
{
if (_subscriptionIdToUserName.TryGetValue(subscriptionId, out var userName))
{
return userName;
}
return null;
}
public static async Task<string> PickSubscriptionIdAsync(bool allowInteractiveLogin, bool allowInteractivePickSubscription, string subscriptionFilter = null)
{
if (Guid.TryParse(subscriptionFilter, out var subscriptionId))
{
return subscriptionId.ToString();
}
var subscription = await PickSubscriptionAsync(allowInteractiveLogin, allowInteractivePickSubscription, subscriptionFilter);
return subscription.Id;
}
public static async Task<AzCli.SubscriptionInfo> PickSubscriptionAsync(bool allowInteractiveLogin, bool allowInteractivePickSubscription, string subscriptionFilter = null)
{
var subscription = await FindSubscriptionAsync(allowInteractiveLogin, allowInteractivePickSubscription, subscriptionFilter);
if (subscription == null)
{
throw new ApplicationException($"CANCELED: No subscription selected.");
}
await AzCli.SetAccount(subscription.Value.Id);
return subscription.Value;
}
public static async Task<AzCli.SubscriptionInfo?> ValidateSubscriptionAsync(bool allowInteractiveLogin, string subscriptionId)
{
var allSubscriptions = await LoginHelpers.GetResponseOnLogin(allowInteractiveLogin, "subscription", AzCli.ListAccounts, " SUBSCRIPTION");
var subscription = allSubscriptions
.Payload
.FirstOrDefault(subs => string.Equals(subs.Id, subscriptionId, StringComparison.OrdinalIgnoreCase));
bool found = !string.IsNullOrWhiteSpace(subscription.Id);
if (found)
{
Console.WriteLine($"{subscription.Name} ({subscription.Id})");
CacheSubscriptionUserName(subscription);
return subscription;
}
else
{
ConsoleHelpers.WriteLineWithHighlight($"`#e_;WARNING: Could not find subscription {subscriptionId}!`");
return null;
}
}
private static async Task<AzCli.SubscriptionInfo?> FindSubscriptionAsync(bool allowInteractiveLogin, bool allowInteractivePickSubscription, string subscriptionFilter = null, string subscriptionLabel = "Subscription")
{
Console.Write($"\r{subscriptionLabel}: *** Loading choices ***");
var response = await AzCli.ListAccounts();
var noOutput = string.IsNullOrEmpty(response.Output.StdOutput);
var hasError = !string.IsNullOrEmpty(response.Output.StdError);
var hasErrorNotFound = hasError && (response.Output.StdError.Contains(" not ") || response.Output.StdError.Contains("No such file"));
Console.Write($"\r{subscriptionLabel}: ");
if (noOutput && hasError && hasErrorNotFound)
{
throw new ApplicationException("*** Please install the Azure CLI - https://aka.ms/azcli ***\n\nNOTE: If it's already installed ensure it's in the system PATH and working (try: `az account list`)");
}
else if (noOutput && hasError)
{
throw new ApplicationException($"*** ERROR: Loading subscriptions ***\n{response.Output.StdError}");
}
var needLogin = response.Output.StdError != null && LoginHelpers.HasLoginError(response.Output.StdError);
if (needLogin)
{
response = await LoginHelpers.AttemptLogin(allowInteractiveLogin, subscriptionLabel);
}
var subscriptions = response.Payload
.Where(x => MatchSubscriptionFilter(x, subscriptionFilter))
.OrderBy(x => x.Name)
.ToArray();
if (subscriptions.Count() == 0)
{
string error = response.Payload.Count() > 0
? "No matching subscriptions found"
: "No subscriptions found";
ConsoleHelpers.WriteLineError($"*** {error} ***");
throw new ApplicationException(error);
}
else if (subscriptions.Count() == 1)
{
var subscription = subscriptions[0];
DisplayNameAndId(subscription);
CacheSubscriptionUserName(subscription);
return subscription;
}
else if (!allowInteractivePickSubscription)
{
string error = "More than 1 subscription found";
ConsoleHelpers.WriteLineError($"*** { error } ***");
Console.WriteLine();
DisplaySubscriptions(subscriptions, " ");
throw new ApplicationException(error);
}
return ListBoxPickSubscription(subscriptions);
}
private static AzCli.SubscriptionInfo? ListBoxPickSubscription(AzCli.SubscriptionInfo[] subscriptions)
{
var list = subscriptions.Select(x => x.Name).ToArray();
var defaultIndex = subscriptions.Select((x, i) => new { x, i }).Where(x => x.x.IsDefault).Select(x => x.i).FirstOrDefault();
var picked = ListBoxPicker.PickIndexOf(list, defaultIndex);
if (picked < 0)
{
throw new OperationCanceledException("User canceled");
}
var subscription = subscriptions[picked];
DisplayNameAndId(subscription);
CacheSubscriptionUserName(subscription);
return subscription;
}
private static bool MatchSubscriptionFilter(AzCli.SubscriptionInfo subscription, string subscriptionFilter)
{
if (subscriptionFilter == null || subscription.Id == subscriptionFilter)
{
return true;
}
var name = subscription.Name.ToLower();
return name.Contains(subscriptionFilter) || StringHelpers.ContainsAllCharsInOrder(name, subscriptionFilter);
}
private static void DisplaySubscriptions(AzCli.SubscriptionInfo[] subscriptions, string prefix = "")
{
foreach (var subscription in subscriptions)
{
Console.Write(prefix);
DisplayNameAndId(subscription);
CacheSubscriptionUserName(subscription);
}
}
private static void DisplayNameAndId(AzCli.SubscriptionInfo subscription)
{
Console.Write($"{subscription.Name} ({subscription.Id})");
Console.WriteLine(new string(' ', 20));
}
private static void CacheSubscriptionUserName(AzCli.SubscriptionInfo subscription)
{
_subscriptionIdToUserName[subscription.Id] = subscription.UserName;
}
private static Dictionary<string, string> _subscriptionIdToUserName = new Dictionary<string, string>();
}
}