Skip to content

Add an UriHandler to handle external requests to open/attach a specific account and open the Query Editor #2635

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 52 commits into from
May 7, 2025

Conversation

sevoku
Copy link
Member

@sevoku sevoku commented Mar 29, 2025

This PR adds a UriHandler with following features:

  • Reveal an existing account in the Azure Resources tree
  • Attach the account to the Workspace if it is not an Azure Resource
  • Open the Query editor for the specified Collection/Container if available

Following parameters are supported (with dependencies):

  • resourceId: The full Azure Resource Id of the account
    • Pattern:vscode://ms-azuretools.vscode-cosmosdb?resourceId=[accountResourceId]
  • cs: The NoSQL/Mongo Connection String (For NoSQL optionally with or without the AccountKey parameter, AccountEndpoint is enough to authenticate with EntraID RBAC)
    • Optional Parameters (required to reveal the account in Azure Resources, will create an Attached Workspace Item otherwise)
      • subscriptionId: Azure Subscription ID
      • resourceGroup: Azure Resource Group Name (required for cs)
      • tenantId: Id of the tenant the resource belongs to (TODO: not yet implemented!)
    • Pattern:
      vscode://ms-azuretools.vscode-cosmosdb?subscriptionId=[subscriptionId]&resourceGroup=[resourceGroupName]&cs=AccountEndpoint=[connectionString]
  • (optional) required to open the Query Editor:
    • database: Database Name
    • container: Container/Collection Name
    • Pattern: vscode://ms-azuretools.vscode-cosmosdb?resourceId=[accountResourceId]&database=[databaseName]&container=[containerName]

IMPORTANT: parameters – especially cs – must be encoded using encodeURIComponent()!

Examples:

vscode://ms-azuretools.vscode-cosmosdb?resourceId=/subscriptions/b15d5cd6-bff3-48c1-8d58-25eeb753034b/resourceGroups/my-resource-group/providers/Microsoft.DocumentDB/databaseAccounts/my-cosmosdb-account&database=Shop&container=Products
vscode://ms-azuretools.vscode-cosmosdb?subscriptionId=b15d5cd6-bff3-48c1-8d58-25eeb753034b&resourceGroup=my-resource-group&database=Shop&container=Products&cs=AccountEndpoint=https://cosmos.documents.azure.com:443/

Dependency Updates:

  • Updated activation events in package.json to include onView:azureResourceGroups and onUri.
  • Updated @microsoft/vscode-azext-utils to version 2.6.6. [1]

Function Enhancements:

  • Enhanced openNoSqlQueryEditor function to handle different input types and added a helper function to extract connections from container nodes in src/commands/openNoSqlQueryEditor/openNoSqlQueryEditor.ts.

Cosmos DB Connection Handling:

  • Added accountName getter to ParsedConnectionString class in src/ParsedConnectionString.ts.
  • Improved error handling and parsing logic in parseCosmosDBConnectionString and ParsedCosmosDBConnectionString classes in src/cosmosdb/cosmosDBConnectionStrings.ts. [1] [2]
  • Added support for handling connection strings in getAccountInfo function in src/tree/cosmosdb/AccountInfo.ts.

Miscellaneous:

  • Registered a global URI handler in src/extension.ts to handle URIs.

TODO:

Fixes #2532
Fixes partially #2620

sevoku added 7 commits March 29, 2025 11:08
This also allows attaching Cosmos DB accounts without an account key, Entra ID will be used instead automatically.
and extract the account name from the endpoint with ParsedCosmosDBConnectionString
…odes and by providing an existing NoSqlQueryConnection directly
…extension

Based on given parameters:
* Reveal a matching account node in the Azure Tree
* Attach the account if it is not an Azure resource
* Open the Query editor for a given collection
sevoku added 3 commits April 3, 2025 11:15
To enable TreeView.reveal we need all elements to have nested Ids separated by '/'.
Emulators were stored with their connection string as Id which can have '/' in it breaking
the convention. This changes emulators to always have a compatible Id and a unified
structure.
@sevoku sevoku force-pushed the dev/sevoku/open-from-url branch from 6f71d5f to 8663850 Compare April 3, 2025 14:33
tnaum-ms and others added 9 commits April 7, 2025 21:37
…CachedBranchDataProvider

- Introduced BaseCachedBranchDataProvider as a common base class for caching tree data.
- Updated CosmosDBBranchDataProvider to utilize the new base class, simplifying the implementation and enhancing caching logic.
- Refactored MongoVCoreBranchDataProvider to extend BaseCachedBranchDataProvider, improving code reuse and maintainability.
- Simplified CosmosDBWorkspaceBranchDataProvider and ClustersWorkspaceBranchDataProvider by extending BaseCachedBranchDataProvider, reducing boilerplate code and enhancing clarity.
- Removed redundant caching logic and event emitters in favor of the base class's functionality.
The tree item is still being used, but a tree node search is performed internally. It's something that will be removed entirely in future releases as it's not bein used for an essential feature.
@sevoku sevoku marked this pull request as ready for review April 25, 2025 13:41
@sevoku sevoku requested a review from a team as a code owner April 25, 2025 13:41
Copy link
Collaborator

@tnaum-ms tnaum-ms left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've read all files, left comments. I will test saving/deleting connections in the workspace as I'm worried about it.
I suggested a change to the handling of the contextValue in the BaseCachedBranchDataProvider.

* @returns The extracted MongoDB resource ID
* @throws Error if the ID is not a valid workspace resource ID
*
* @remarks Long-term solution would be to avoid '/' characters within individual ID segments.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not used anymore 6c1311f, however in theory Attached Mongo accounts could still have an "/" in their IDs because we use parsedCS.username + '@' + parsedCS.redact().toString() fir id here:

id: parsedCS.username + '@' + parsedCS.redact().toString(),

@tnaum-ms: can't we change that to use just the username@hostname:port instead of the full redacted string? I don't see any point in having all the other optional parameters being part of the ID.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sevoku I'm on it today. This is correct, it doesn't have to be the connection string. The rationale behind it was that the connection string can contain a database name so the current solution was the quick one. However, I'll improve it.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed here:

const hashedCS = randomUtils.getPseudononymousStringHash(connectionString, 'hex').substring(0, 24);
const storageId = `storageId-${parsedCS.hosts.join('_')}-${hashedCS}`;
const storageItem: StorageItem = {
id: storageId,
name: label,
properties: { isEmulator: false, api },
secrets: [connectionString],
};

matching migration code is in place as well, so that now all entries are consistent.

@tnaum-ms
Copy link
Collaborator

tnaum-ms commented Apr 29, 2025

I tried out creating/listing/deleting connections. I discovered only one failing scenario:

  • create a MongoDB account in the workspace from a connections string mongodb://usd:asdf@test.com
  • attempt to delete it

It will show the 'deleting' UI (aka the tree view node id is correct), but the actual entry won't be deleted (very likely due to incorrect workspace name or the id doesn't match the one in storage).

@sevoku I can track it down / fix it sometime tomorrow in case you won't have time.

@sevoku sevoku force-pushed the dev/sevoku/open-from-url branch from fa5419c to 4ac800b Compare April 30, 2025 12:33
@tnaum-ms
Copy link
Collaborator

tnaum-ms commented May 2, 2025

I tried out creating/listing/deleting connections. I discovered only one failing scenario:

  • create a MongoDB account in the workspace from a connections string mongodb://usd:asdf@test.com
  • attempt to delete it

✅ The issue no longer occurs.

@tnaum-ms
Copy link
Collaborator

tnaum-ms commented May 2, 2025

@sevoku I looked at the BaseCachedBranchDataProvider implementation and its role/function. Caching seems to be more the 'how it works', but the actual role of the class is different.

To get there faster, I asked Copilot to come up with some suggestions, for you to choose from :)


Here are three better name suggestions that more accurately reflect the class's purpose:

BaseNavigableBranchDataProvider
Emphasizes the navigation capabilities (getParent, findNodeById, findChildById) that are the core functionality needed by VS Code's tree view system.

BaseHierarchicalBranchDataProvider
Focuses on the parent-child relationship management that enables tree traversal while also acknowledging the resource-based nature of the tree elements.

BaseStructuredBranchDataProvider
This name focuses on the class providing the underlying structure and relationships for the tree data, including caching and navigation capabilities.

@tnaum-ms tnaum-ms requested a review from Copilot May 2, 2025 11:29
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces a new URI handler along with several changes to support external requests for opening/attaching Cosmos DB accounts and launching the Query Editor. Key changes include:

  • Adding a storageId property and related type/interfaces for attached accounts and tree elements.
  • Refactoring account information and connection string parsing to support both attached accounts and connection string inputs.
  • Updating various branch data providers and commands (including removal, query editor, and emulator connections) to integrate these new concepts.

Reviewed Changes

Copilot reviewed 30 out of 32 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/tree/workspace-view/cosmosdb/CosmosDBAttachedAccountModel.ts Added storageId to the attached account model.
src/tree/workspace-api/SharedWorkspaceResourceProvider.ts Introduced helper methods for extracting workspace resource IDs.
src/tree/documentdb/ClusterModel.ts Added a new AttachedClusterModel type.
src/tree/cosmosdb/CosmosDBAccountAttachedResourceItem.ts Implemented storageId getter for attached account resource items.
src/tree/cosmosdb/AccountInfo.ts Refactored getAccountInfo to account for both attached accounts and connection string inputs.
src/tree/azure-resources-view/documentdb/mongo-vcore/MongoVCoreBranchDataProvider.ts Refactored to extend BaseCachedBranchDataProvider and removed redundant events.
src/tree/azure-resources-view/cosmosdb/CosmosDBBranchDataProvider.ts Refactored resource item creation and updated refresh to throw an error for unsupported cases.
src/tree/TreeElementWithStorageId.ts Added a new type and type guard for tree elements with storage IDs.
src/services/storageService.ts Updated to ensure the correct storage id is used when reading items from storage.
src/extension.ts Registered a global URI handler.
src/cosmosdb/cosmosDBConnectionStrings.ts Updated connection string parsing to use the URL constructor and include the port explicitly.
src/cosmosdb/cosmosDBConnectionStrings.test.ts Adjusted tests to account for the new connection string validation.
src/commands/removeConnection/removeConnection.ts Updated deletion logic and type usage for connection removal.
src/commands/openNoSqlQueryEditor/openNoSqlQueryEditor.ts Extended support to handle NoSqlQueryConnection inputs along with tree nodes.
src/commands/openCollectionView/openCollectionView.ts Updated parameters for opening a collection view.
src/commands/newEmulatorConnection/ExecuteStep.ts Utilized emulator utility functions for label and unique id generation.
src/commands/newConnection/MongoExecuteStep.ts Integrated pseudonymous hashing for storage id generation.
src/ParsedConnectionString.ts Added an accountName getter which returns the account identifier.
Files not reviewed (2)
  • l10n/bundle.l10n.json: Language not supported
  • package.json: Language not supported
Comments suppressed due to low confidence (2)

src/commands/removeConnection/removeConnection.ts:100

  • [nitpick] The confirmation logic within the showDeleting callback appears somewhat convoluted. Consider simplifying this flow by acquiring the confirmation result first before proceeding with deletion actions to improve readability.
if (!confirmed) { throw new UserCancelledError(); }

src/ParsedConnectionString.ts:25

  • [nitpick] The getter 'accountName' simply returns 'accountId', which may be redundant. Consider consolidating these properties for clarity and to avoid potential confusion.
public get accountName(): string { return this.accountId; }

tnaum-ms
tnaum-ms previously approved these changes May 2, 2025
@sevoku sevoku requested review from bk201- and tnaum-ms May 7, 2025 09:57
@sevoku sevoku merged commit a968251 into main May 7, 2025
2 checks passed
@sevoku sevoku deleted the dev/sevoku/open-from-url branch May 7, 2025 10:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support opening the Query Editor from outside (Portal, Fabric) using registerUriHandler
3 participants