Changes to client-side azure resource filtering (#18274)

* slight refactoring

* swapping azure logic to client-side filtering
This commit is contained in:
Benjin Dubishar 2024-10-18 10:26:04 -07:00 коммит произвёл GitHub
Родитель 15800ea6f3
Коммит 4371cc4567
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
3 изменённых файлов: 90 добавлений и 80 удалений

Просмотреть файл

@ -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]);