Changes to client-side azure resource filtering (#18274)
* slight refactoring * swapping azure logic to client-side filtering
This commit is contained in:
Родитель
15800ea6f3
Коммит
4371cc4567
|
@ -5,9 +5,19 @@
|
|||
|
||||
import * as vscode from "vscode";
|
||||
import { l10n } from "vscode";
|
||||
import { ConnectionDialogWebviewState } from "../sharedInterfaces/connectionDialog";
|
||||
import { getErrorMessage } from "../utils/utils";
|
||||
import { VSCodeAzureSubscriptionProvider } from "@microsoft/vscode-azext-azureauth";
|
||||
import {
|
||||
AzureSqlServerInfo,
|
||||
ConnectionDialogWebviewState,
|
||||
} from "../sharedInterfaces/connectionDialog";
|
||||
import { getErrorMessage, listAllIterator } from "../utils/utils";
|
||||
import {
|
||||
AzureSubscription,
|
||||
VSCodeAzureSubscriptionProvider,
|
||||
} from "@microsoft/vscode-azext-azureauth";
|
||||
import {
|
||||
GenericResourceExpanded,
|
||||
ResourceManagementClient,
|
||||
} from "@azure/arm-resources";
|
||||
|
||||
export const azureSubscriptionFilterConfigKey =
|
||||
"azureResourceGroups.selectedSubscriptions";
|
||||
|
@ -97,3 +107,76 @@ export async function getQuickPickItems(
|
|||
|
||||
return quickPickItems;
|
||||
}
|
||||
|
||||
const serverResourceType = "Microsoft.Sql/servers";
|
||||
const databaseResourceType = "Microsoft.Sql/servers/databases";
|
||||
const elasticPoolsResourceType = "Microsoft.Sql/servers/elasticpools";
|
||||
|
||||
export async function fetchServersFromAzure(
|
||||
sub: AzureSubscription,
|
||||
): Promise<AzureSqlServerInfo[]> {
|
||||
const result: AzureSqlServerInfo[] = [];
|
||||
const client = new ResourceManagementClient(
|
||||
sub.credential,
|
||||
sub.subscriptionId,
|
||||
);
|
||||
|
||||
// for some subscriptions, supplying a `resourceType eq 'Microsoft.Sql/servers/databases'` filter to list() causes an error:
|
||||
// > invalid filter in query string 'resourceType eq "Microsoft.Sql/servers/databases'"
|
||||
// no idea why, so we're fetching all resources and filtering them ourselves
|
||||
|
||||
const resources = await listAllIterator<GenericResourceExpanded>(
|
||||
client.resources.list(),
|
||||
);
|
||||
|
||||
const servers = resources.filter((r) => r.type === serverResourceType);
|
||||
const databases = resources.filter(
|
||||
(r) =>
|
||||
r.type === databaseResourceType ||
|
||||
r.type === elasticPoolsResourceType,
|
||||
);
|
||||
|
||||
for (const server of servers) {
|
||||
result.push({
|
||||
server: server.name,
|
||||
databases: [],
|
||||
location: server.location,
|
||||
resourceGroup: extractFromResourceId(server.id, "resourceGroups"),
|
||||
subscription: `${sub.name} (${sub.subscriptionId})`,
|
||||
});
|
||||
}
|
||||
|
||||
for (const database of databases) {
|
||||
const serverName = extractFromResourceId(database.id, "servers");
|
||||
const server = result.find((s) => s.server === serverName);
|
||||
if (server) {
|
||||
server.databases.push(
|
||||
database.name.substring(serverName.length + 1),
|
||||
); // database.name is in the form 'serverName/databaseName', so we need to remove the server name and slash
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function extractFromResourceId(
|
||||
resourceId: string,
|
||||
property: string,
|
||||
): string | undefined {
|
||||
if (!property.endsWith("/")) {
|
||||
property += "/";
|
||||
}
|
||||
|
||||
let startIndex = resourceId.indexOf(property);
|
||||
|
||||
if (startIndex === -1) {
|
||||
return undefined;
|
||||
} else {
|
||||
startIndex += property.length;
|
||||
}
|
||||
|
||||
return resourceId.substring(
|
||||
startIndex,
|
||||
resourceId.indexOf("/", startIndex),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ import * as vscode from "vscode";
|
|||
|
||||
import {
|
||||
AuthenticationType,
|
||||
AzureSqlServerInfo,
|
||||
AzureSubscriptionInfo,
|
||||
ConnectionDialogFormItemSpec,
|
||||
ConnectionDialogReducers,
|
||||
|
@ -25,10 +24,6 @@ import {
|
|||
FormItemSpec,
|
||||
FormItemType,
|
||||
} from "../reactviews/common/forms/form";
|
||||
import {
|
||||
GenericResourceExpanded,
|
||||
ResourceManagementClient,
|
||||
} from "@azure/arm-resources";
|
||||
import {
|
||||
ConnectionDialog as Loc,
|
||||
refreshTokenLabel,
|
||||
|
@ -36,9 +31,10 @@ import {
|
|||
import {
|
||||
azureSubscriptionFilterConfigKey,
|
||||
confirmVscodeAzureSignin,
|
||||
fetchServersFromAzure,
|
||||
promptForAzureSubscriptionFilter,
|
||||
} from "./azureHelper";
|
||||
import { getErrorMessage, listAllIterator } from "../utils/utils";
|
||||
import { getErrorMessage } from "../utils/utils";
|
||||
|
||||
import { ApiStatus } from "../sharedInterfaces/webview";
|
||||
import { AzureController } from "../azure/azureController";
|
||||
|
@ -1255,7 +1251,7 @@ export class ConnectionDialogWebviewController extends ReactWebviewPanelControll
|
|||
);
|
||||
|
||||
try {
|
||||
const servers = await this.fetchServersFromAzure(azSub);
|
||||
const servers = await fetchServersFromAzure(azSub);
|
||||
state.azureServers.push(...servers);
|
||||
stateSub.loaded = true;
|
||||
this.updateState();
|
||||
|
@ -1292,74 +1288,4 @@ export class ConnectionDialogWebviewController extends ReactWebviewPanelControll
|
|||
return rv;
|
||||
}, new Map<K, V[]>());
|
||||
}
|
||||
|
||||
private async fetchServersFromAzure(
|
||||
sub: AzureSubscription,
|
||||
): Promise<AzureSqlServerInfo[]> {
|
||||
const result: AzureSqlServerInfo[] = [];
|
||||
const client = new ResourceManagementClient(
|
||||
sub.credential,
|
||||
sub.subscriptionId,
|
||||
);
|
||||
const servers = await listAllIterator<GenericResourceExpanded>(
|
||||
client.resources.list({
|
||||
filter: "resourceType eq 'Microsoft.Sql/servers'",
|
||||
}),
|
||||
);
|
||||
const databasesPromise = listAllIterator<GenericResourceExpanded>(
|
||||
client.resources.list({
|
||||
filter: "resourceType eq 'Microsoft.Sql/servers/databases'",
|
||||
}),
|
||||
);
|
||||
|
||||
for (const server of servers) {
|
||||
result.push({
|
||||
server: server.name,
|
||||
databases: [],
|
||||
location: server.location,
|
||||
resourceGroup: this.extractFromResourceId(
|
||||
server.id,
|
||||
"resourceGroups",
|
||||
),
|
||||
subscription: `${sub.name} (${sub.subscriptionId})`,
|
||||
});
|
||||
}
|
||||
|
||||
for (const database of await databasesPromise) {
|
||||
const serverName = this.extractFromResourceId(
|
||||
database.id,
|
||||
"servers",
|
||||
);
|
||||
const server = result.find((s) => s.server === serverName);
|
||||
if (server) {
|
||||
server.databases.push(
|
||||
database.name.substring(serverName.length + 1),
|
||||
); // database.name is in the form 'serverName/databaseName', so we need to remove the server name and slash
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private extractFromResourceId(
|
||||
resourceId: string,
|
||||
property: string,
|
||||
): string | undefined {
|
||||
if (!property.endsWith("/")) {
|
||||
property += "/";
|
||||
}
|
||||
|
||||
let startIndex = resourceId.indexOf(property);
|
||||
|
||||
if (startIndex === -1) {
|
||||
return undefined;
|
||||
} else {
|
||||
startIndex += property.length;
|
||||
}
|
||||
|
||||
return resourceId.substring(
|
||||
startIndex,
|
||||
resourceId.indexOf("/", startIndex),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,6 +79,7 @@ export const AzureBrowsePage = () => {
|
|||
setSubscriptions(subs.sort());
|
||||
|
||||
if (!selectedSubscription && subs.length === 1) {
|
||||
setSubscriptionValue(subs[0]);
|
||||
setSelectedSubscription(subs[0]);
|
||||
}
|
||||
}, [context.state.azureSubscriptions]);
|
||||
|
|
Загрузка…
Ссылка в новой задаче