Skip to content

Commit

Permalink
Merge branch 'main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
hund030 authored Jan 10, 2025
2 parents fb55b89 + a6ce3bb commit ec73d8c
Show file tree
Hide file tree
Showing 16 changed files with 1,277 additions and 11,744 deletions.
26 changes: 25 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,30 @@
# Change Log

## Unreleased
## 0.10.2 - 2025-01-09

## Fixed
* [[1369]](https://github.com/microsoft/vscode-azurestorage/issues/1369) Could not find $web blob container when deploying to static website via Azure Storage

## 0.10.1 - 2024-12-31

### Fixed
* [[4335]](https://github.com/microsoft/vscode-azurefunctions/issues/4355) Fixed issue that impacted Azure Function deployment due to tree items not being found if the account id had a slash in it.


## 0.10.0 - 2024-12-30

### What's new

#### Accounts & Tenants view
This view allows user to manage their accounts and tenants. By checking and unchecking tenants, subscriptions within the Resources view and subscription filter will be filtered out.

<img width = "900" alt = "Accounts & Tenants view" src = "https://github.com/user-attachments/assets/d34c1f79-fb21-46f9-af3a-cbb109ba0414">

### Added
* [[869]](https://github.com/microsoft/vscode-azureresourcegroups/pull/869) Accounts & Tenants view
* [[926]](https://github.com/microsoft/vscode-azureresourcegroups/pull/926) Shortcut to switching to sovereign clouds
* [[979]](https://github.com/microsoft/vscode-azureresourcegroups/pull/979) An "Add account" button

## 0.9.9 - 2024-11-05
# Fixed
* Minor fixes for VS Code for the Web - Azure
Expand Down
12,878 changes: 1,173 additions & 11,705 deletions NOTICE.html

Large diffs are not rendered by default.

18 changes: 9 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "vscode-azureresourcegroups",
"displayName": "Azure Resources",
"description": "%azureResourceGroups.description%",
"version": "0.9.9",
"version": "0.10.3-alpha",
"publisher": "ms-azuretools",
"icon": "resources/resourceGroup.png",
"aiKey": "0c6ae279ed8443289764825290e4f9e2-1a736e7c-1324-4338-be46-fc2a58ae4d14-7255",
Expand Down Expand Up @@ -537,6 +537,10 @@
{
"command": "azureTenantsView.addAccount",
"when": "never"
},
{
"command": "azureTenantsView.signInToTenant",
"when": "never"
}
],
"azureResourceGroups.groupBy": [
Expand Down Expand Up @@ -788,7 +792,7 @@
"@azure/arm-resources": "^5.2.0",
"@azure/arm-resources-profile-2020-09-01-hybrid": "^2.1.0",
"@azure/ms-rest-js": "^2.7.0",
"@microsoft/vscode-azext-azureauth": "^4.0.0",
"@microsoft/vscode-azext-azureauth": "^4.0.3",
"@microsoft/vscode-azext-azureutils": "^3.1.1",
"@microsoft/vscode-azext-utils": "^2.5.12",
"buffer": "^6.0.3",
Expand Down
3 changes: 2 additions & 1 deletion src/commands/createResourceGroup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { window } from 'vscode';
import { AzureSubscription } from '../../api/src/index';
import { ext } from '../extensionVariables';
import { SubscriptionItem } from '../tree/azure/SubscriptionItem';
import { getAccountAndTenantPrefix } from '../tree/azure/idPrefix';
import { createActivityContext } from '../utils/activityUtils';
import { localize } from '../utils/localize';

Expand Down Expand Up @@ -37,5 +38,5 @@ export async function createResourceGroup(context: IActionContext, node?: Subscr
if (!wizardContext.suppressNotification) {
void window.showInformationMessage(localize('createdRg', 'Created resource group "{0}".', newResourceGroupName));
}
ext.azureTreeState.notifyChildrenChanged(`/subscriptions/${subscription.subscriptionId}`);
ext.azureTreeState.notifyChildrenChanged(`${getAccountAndTenantPrefix(subscription)}/subscriptions/${subscription.subscriptionId}`);
}
5 changes: 3 additions & 2 deletions src/commands/deleteResourceGroup/v2/deleteResourceGroupV2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { AzureResource, AzureSubscription } from '../../../../api/src/index';
import { createResourceGroup } from '../../../api/DefaultAzureResourceProvider';
import { ext } from '../../../extensionVariables';
import { isResourceGroupGroupingItem, ResourceGroupGroupingItem } from '../../../tree/azure/grouping/ResourceGroupGroupingItem';
import { getAccountAndTenantPrefix } from '../../../tree/azure/idPrefix';
import { createActivityContext } from '../../../utils/activityUtils';
import { createResourceClient } from '../../../utils/azureClients';
import { localize } from '../../../utils/localize';
Expand Down Expand Up @@ -111,7 +112,7 @@ async function deleteResourceGroups(context: IActionContext, subscription: Azure
}
}

void ext.azureTreeState.runWithTemporaryDescription(rg.id, localize('deleting', 'Deleting...'), async () => {
void ext.azureTreeState.runWithTemporaryDescription(`${getAccountAndTenantPrefix(rg.subscription)}${rg.id}`, localize('deleting', 'Deleting...'), async () => {
const wizard = new AzureWizard<DeleteResourceGroupContext>({
subscription: createSubscriptionContext(subscription),
resourceGroupToDelete: rg.name,
Expand All @@ -123,7 +124,7 @@ async function deleteResourceGroups(context: IActionContext, subscription: Azure
});

await wizard.execute();
ext.azureTreeState.notifyChildrenChanged(`/subscriptions/${rg.subscription.subscriptionId}`);
ext.azureTreeState.notifyChildrenChanged(`${getAccountAndTenantPrefix(rg.subscription)}/subscriptions/${rg.subscription.subscriptionId}`);
});
}
}
16 changes: 4 additions & 12 deletions src/tree/BranchDataItemCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { isAzExtTreeItem } from '@microsoft/vscode-azext-utils';
import { ResourceModelBase } from 'api/src/resources/base';
import { BranchDataItemWrapper } from './BranchDataItemWrapper';
import { ResourceGroupsItem } from './ResourceGroupsItem';
Expand All @@ -29,17 +28,14 @@ export class BranchDataItemCache {
return this.branchItemToResourceGroupsItemCache.get(branchItem);
}

getItemForBranchItemById(branchItem: ResourceModelBase): ResourceGroupsItem | undefined {
const id = this.getIdForBranchItem(branchItem);
if (!id) {
return undefined;
}
getItemForBranchItemById(id: string): ResourceGroupsItem | undefined {
const cachedBranchItem = this.idToBranchItemCache.get(id);
return cachedBranchItem ? this.branchItemToResourceGroupsItemCache.get(cachedBranchItem) : undefined;
}

createOrGetItem<T extends BranchDataItemWrapper>(branchItem: ResourceModelBase, createItem: () => T): T {
const cachedItem = this.getItemForBranchItemById(branchItem) as T | undefined;
createOrGetItem<T extends BranchDataItemWrapper>(branchItem: ResourceModelBase, createItem: () => T, id: string): T {
const itemId = id ?? this.getIdForBranchItem(branchItem);
const cachedItem = this.getItemForBranchItemById(itemId) as T | undefined;
if (cachedItem) {
cachedItem.branchItem = branchItem;
this.addBranchItem(branchItem, cachedItem);
Expand All @@ -49,10 +45,6 @@ export class BranchDataItemCache {
}

private getIdForBranchItem(branchItem: ResourceModelBase): string | undefined {
if (isAzExtTreeItem(branchItem)) {
return branchItem.fullId;
}

return branchItem.id;
}
}
19 changes: 18 additions & 1 deletion src/tree/BranchDataItemWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,17 @@ import { isAzExtTreeItem } from '@microsoft/vscode-azext-utils';
import { v4 as uuidv4 } from "uuid";
import * as vscode from 'vscode';
import { AzureResourceModel, BranchDataProvider, ResourceBase, ResourceModelBase, ViewPropertiesModel, Wrapper } from '../../api/src/index';
import { DefaultAzureResourceBranchDataProvider } from './azure/DefaultAzureResourceBranchDataProvider';
import { BranchDataItemCache } from './BranchDataItemCache';
import { ResourceGroupsItem } from './ResourceGroupsItem';
import { DefaultAzureResourceBranchDataProvider } from './azure/DefaultAzureResourceBranchDataProvider';

export type BranchDataItemOptions = {
contextValues?: string[];
defaultId?: string;
defaults?: vscode.TreeItem;
portalUrl?: vscode.Uri;
viewProperties?: ViewPropertiesModel;
idPrefix?: string;
};

function appendContextValues(originalValues: string | undefined, optionsValues: string[] | undefined, extraValues: string[] | undefined): string {
Expand Down Expand Up @@ -49,6 +50,7 @@ export class BranchDataItemWrapper implements ResourceGroupsItem, Wrapper {
} else {
this.id = this.branchItem.id ?? this?.options?.defaultId ?? uuidv4();
}
this.id = createBranchItemId(this.id, this.options?.idPrefix);
}

public readonly id: string;
Expand All @@ -69,12 +71,18 @@ export class BranchDataItemWrapper implements ResourceGroupsItem, Wrapper {
factory(child, this.branchDataProvider, {
portalUrl: (child as AzureResourceModel).portalUrl,
viewProperties: (child as AzureResourceModel).viewProperties,
// recursively prefix child items with the account and tenant id
// this ensures that items provided by branch data providers are prefixed
idPrefix: this.options?.idPrefix,
})
);
}

async getTreeItem(): Promise<vscode.TreeItem> {
const treeItem = await this.branchDataProvider.getTreeItem(this.branchItem);
// set the id of the tree item to the id of the branch item
// we do this because the branch item has already modified the item's id (see constructor)
treeItem.id = this.id;

const contextValue = appendContextValues(treeItem.contextValue, this.options?.contextValues, this.getExtraContextValues());

Expand Down Expand Up @@ -119,5 +127,14 @@ export function createBranchDataItemFactory(itemCache: BranchDataItemCache): Bra
itemCache.createOrGetItem(
branchItem,
() => new BranchDataItemWrapper(branchItem, branchDataProvider, itemCache, options),
createBranchItemId(branchItem.id, options?.idPrefix),
)
}

function createBranchItemId(id?: string, prefix?: string): string {
if (prefix?.endsWith('/') && id?.startsWith('/')) {
return `${prefix}${id.substring(1)}`;
} else {
return `${prefix ?? ''}${id}`;
}
}
12 changes: 9 additions & 3 deletions src/tree/ResourceTreeDataProviderBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ export abstract class ResourceTreeDataProviderBase extends vscode.Disposable imp
for (const child of children) {
if (child.id.toLowerCase() === id.toLowerCase()) {
return child;
} else if (removePrefix(child.id.toLowerCase()) === id.toLowerCase()) {
return child;
} else if (this.isAncestorOf(child, id)) {
element = child;
continue outerLoop;
Expand All @@ -123,10 +125,14 @@ export abstract class ResourceTreeDataProviderBase extends vscode.Disposable imp
}

protected isAncestorOf(element: ResourceGroupsItem, id: string): boolean {
// remove accounts/<accountId>/tenant/<tenantId> from the beginning of the id
const elementId = element.id.replace(/\/accounts\/[^/]+\/tenants\/[^/]+\//i, '/').toLowerCase() + '/';
return id.toLowerCase().startsWith(elementId);
// remove accounts / <accountId>/tenant/<tenantId> from the beginning of the id
const elementId = removePrefix(element.id) + '/';
return id.toLowerCase().startsWith(elementId.toLowerCase());
}

protected abstract onGetChildren(element?: ResourceGroupsItem | undefined): Promise<ResourceGroupsItem[] | null | undefined>;
}

function removePrefix(id: string): string {
return id.replace(/\/accounts\/.+\/tenants\/[^/]+\//i, '/')
}
5 changes: 5 additions & 0 deletions src/tree/TreeItemState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export class TreeItemStateStore implements vscode.Disposable {

/**
* Notify a resource that its children have changed.
*
* @param id id needs to include the account and tenant id
*/
notifyChildrenChanged(id: string): void {
this.onDidUpdateStateEmitter.fire(id);
Expand All @@ -51,6 +53,9 @@ export class TreeItemStateStore implements vscode.Disposable {
});
}

/**
* @param id id needs to include the account and tenant id
*/
async runWithTemporaryDescription<T = void>(id: string, description: string, callback: () => Promise<T>): Promise<T> {
let result: T;
this.update(id, { ...this.getState(id), temporaryDescription: description, spinner: true });
Expand Down
6 changes: 4 additions & 2 deletions src/tree/azure/AzureResourceItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { createPortalUrl } from '../../utils/v2/createPortalUrl';
import { BranchDataItemCache } from '../BranchDataItemCache';
import { BranchDataItemOptions, BranchDataItemWrapper } from '../BranchDataItemWrapper';
import { ResourceGroupsItem } from '../ResourceGroupsItem';
import { getAccountAndTenantPrefix } from './idPrefix';

export class AzureResourceItem<T extends AzureResource> extends BranchDataItemWrapper {
constructor(
Expand All @@ -27,7 +28,7 @@ export class AzureResourceItem<T extends AzureResource> extends BranchDataItemWr
}

override readonly portalUrl: Uri;
readonly id = this.resource.id;
readonly id = `${getAccountAndTenantPrefix(this.resource.subscription)}${this.resource.id}`;
readonly tagsModel = new ResourceTags(this.resource);

override async getParent(): Promise<ResourceGroupsItem | undefined> {
Expand Down Expand Up @@ -57,6 +58,7 @@ export function createResourceItemFactory<T extends AzureResource>(itemCache: Br
return (resource, branchItem, branchDataProvider, parent, options) =>
itemCache.createOrGetItem(
branchItem,
() => new AzureResourceItem(resource, branchItem, branchDataProvider, itemCache, parent, options)
() => new AzureResourceItem(resource, branchItem, branchDataProvider, itemCache, parent, options),
`${getAccountAndTenantPrefix(resource.subscription)}${resource.id}`,
);
}
5 changes: 3 additions & 2 deletions src/tree/azure/SubscriptionItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { callWithTelemetryAndErrorHandling, createSubscriptionContext, IActionContext, ISubscriptionContext, nonNullValueAndProp } from "@microsoft/vscode-azext-utils";
import { callWithTelemetryAndErrorHandling, createSubscriptionContext, IActionContext, ISubscriptionContext } from "@microsoft/vscode-azext-utils";
import * as vscode from "vscode";
import { AzureSubscription } from "../../../api/src/index";
import { AzureResourceProviderManager } from "../../api/ResourceProviderManagers";
Expand All @@ -13,6 +13,7 @@ import { createPortalUrl } from "../../utils/v2/createPortalUrl";
import { ResourceGroupsItem } from "../ResourceGroupsItem";
import { ResourceGroupsTreeContext } from "../ResourceGroupsTreeContext";
import { AzureResourceGroupingManager } from "./grouping/AzureResourceGroupingManager";
import { getAccountAndTenantPrefix } from "./idPrefix";

export class SubscriptionItem implements ResourceGroupsItem {
constructor(
Expand All @@ -28,7 +29,7 @@ export class SubscriptionItem implements ResourceGroupsItem {
...subscription
};

this.id = `/accounts/${nonNullValueAndProp(subscription.account, 'id')}/tenants/${subscription.tenantId}/subscriptions/${subscription.subscriptionId}`;
this.id = `${getAccountAndTenantPrefix(this.subscription)}/subscriptions/${subscription.subscriptionId}`;
this.description = description ? description : '';

this.portalUrl = createPortalUrl(this.subscription, `/subscriptions/${this.subscription.subscriptionId}`);
Expand Down
7 changes: 5 additions & 2 deletions src/tree/azure/grouping/GroupingItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { ResourceGroupsItem } from '../../ResourceGroupsItem';
import { ResourceGroupsTreeContext } from '../../ResourceGroupsTreeContext';
import { BranchDataProviderFactory } from '../AzureResourceBranchDataProviderManager';
import { ResourceItemFactory } from '../AzureResourceItem';
import { getAccountAndTenantPrefix } from '../idPrefix';
import { GroupingItemFactoryOptions } from './GroupingItemFactory';

export class GroupingItem implements ResourceGroupsItem {
Expand Down Expand Up @@ -56,7 +57,7 @@ export class GroupingItem implements ResourceGroupsItem {
} : undefined;

if (this.context?.subscription) {
this.id = `/subscriptions/${this.context?.subscriptionContext.subscriptionId}/account/${this.context?.subscription.account?.id}/groupings/${this.label}`;
this.id = `${getAccountAndTenantPrefix(this.context?.subscription)}/subscriptions/${this.context?.subscriptionContext.subscriptionId}/groupings/${this.label}`;
} else {
// favorites groups don't always have a subscription
this.id = `/groupings/${this.label}`;
Expand Down Expand Up @@ -119,7 +120,9 @@ export class GroupingItem implements ResourceGroupsItem {
viewProperties: resourceItem.viewProperties ?? {
label: resource.name,
data: resource.raw
}
},
// prefix child items with the account and tenant id
idPrefix: getAccountAndTenantPrefix(resource.subscription),
};

items.push(this.resourceItemFactory(resource, resourceItem, branchDataProvider, this, options));
Expand Down
Loading

0 comments on commit ec73d8c

Please sign in to comment.