Skip to content

Commit

Permalink
BlobContainerFS core logic (#1227)
Browse files Browse the repository at this point in the history
* BlobContainerFS core logic

* Throw correct type of errors

* Support data plane AAD authentication

* Refactor credential usage

* Missing type

* Comment clarification

* Fix HNS key credential

* Remove console.log

* Suppress error from stats and explain why

* Trim blob related methods from AzureStorageFS, fix editBlob command

* Remove unnecessary try catch

* No magic var name

* Refactor account extension deps

* Use Node 16.x in CI

* Update vscode engine and dev package

* Suppress error display for stat and readFile

* Use blob exclusive telemetry id

* Fixup

* Revert changes to old FS provider

* Use old FS provider for attached accounts

* Use old FS provider in editBlob for attached accounts

* Make helper method for getting subscriptions

* Remove unused things

---------

Co-authored-by: Alex Weininger <alex.weininger@live.com>
  • Loading branch information
JasonYeMSFT and alexweininger committed Apr 7, 2023
1 parent 51885c6 commit d8e348b
Show file tree
Hide file tree
Showing 10 changed files with 902 additions and 10,153 deletions.
10,260 changes: 116 additions & 10,144 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"preview": true,
"activationEvents": [
"onFileSystem:azurestorage",
"onFileSystem:azurestorageblob",
"onCommand:azureStorage.openInFileExplorer",
"onCommand:azureStorage.deployStaticWebsite",
"onCommand:azureStorage.configureStaticWebsite",
Expand Down Expand Up @@ -848,6 +849,7 @@
"@azure/arm-storage-profile-2020-09-01-hybrid": "^2.0.0",
"@azure/data-tables": "^13.0.0",
"@azure/storage-blob": "^12.1.1",
"@azure/storage-file-datalake": "^12.1.1",
"@azure/storage-file-share": "^12.1.1",
"@azure/storage-queue": "^12.7.0",
"@microsoft/vscode-azext-azureappservice": "^0.7.0",
Expand Down
93 changes: 93 additions & 0 deletions src/AzureAccountExtension.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import type { Subscription } from '@azure/arm-resources-subscriptions';
import { TokenCredential } from '@azure/core-auth';
import { Environment } from '@azure/ms-rest-azure-env';
import type { TokenCredentialsBase } from '@azure/ms-rest-nodeauth';
import { apiUtils } from '@microsoft/vscode-azext-utils';
import { ReadStream } from 'fs';
import * as vscode from 'vscode';
import { CancellationToken, Event, Progress, Terminal } from 'vscode';


export type AzureLoginStatus = 'Initializing' | 'LoggingIn' | 'LoggedIn' | 'LoggedOut';

export interface AzureAccountExtensionApi {
readonly apiVersion: string;
readonly status: AzureLoginStatus;
readonly filters: AzureResourceFilter[];
readonly sessions: AzureSession[];
readonly subscriptions: AzureAccountSubscription[];
readonly onStatusChanged: Event<AzureLoginStatus>;
readonly onFiltersChanged: Event<void>;
readonly onSessionsChanged: Event<void>;
readonly onSubscriptionsChanged: Event<void>;
readonly waitForFilters: () => Promise<boolean>;
readonly waitForLogin: () => Promise<boolean>;
readonly waitForSubscriptions: () => Promise<boolean>;
createCloudShell(os: 'Linux' | 'Windows'): CloudShell;
}

export interface AzureSession {
readonly environment: Environment;
readonly userId: string;
readonly tenantId: string;

/**
* The credentials object for azure-sdk-for-js modules https://github.com/azure/azure-sdk-for-js
*/
readonly credentials2: TokenCredentialsBase & TokenCredential;
}

export interface AzureAccountSubscription {
readonly session: AzureSession;
readonly subscription: Subscription;
}

export type AzureResourceFilter = AzureAccountSubscription;

export type CloudShellStatus = 'Connecting' | 'Connected' | 'Disconnected';

export interface UploadOptions {
contentLength?: number;
progress?: Progress<{ message?: string; increment?: number }>;
token?: CancellationToken;
}

export interface CloudShell {
readonly status: CloudShellStatus;
readonly onStatusChanged: Event<CloudShellStatus>;
readonly waitForConnection: () => Promise<boolean>;
readonly terminal: Promise<Terminal>;
readonly session: Promise<AzureSession>;
readonly uploadFile: (filename: string, stream: ReadStream, options?: UploadOptions) => Promise<void>;
}

export async function getAzureAccountExtensionApi(): Promise<AzureAccountExtensionApi> {
const extension = vscode.extensions.getExtension<apiUtils.AzureExtensionApiProvider>('ms-vscode.azure-account');

if (extension) {
if (!extension.isActive) {
await extension.activate();
}

let azureAccountApi: AzureAccountExtensionApi | undefined;
if ('getApi' in extension.exports) {
azureAccountApi = extension.exports.getApi<AzureAccountExtensionApi>('1');
} else {
// support versions of the Azure Account extension <0.10.0
azureAccountApi = extension.exports as unknown as AzureAccountExtensionApi;
}

if (azureAccountApi) {
await azureAccountApi.waitForSubscriptions();
}

return azureAccountApi;
}

throw new Error("Unable to get Azure Account extension API.");
}
9 changes: 9 additions & 0 deletions src/AzureStorageFS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ type AzureStorageBlobTreeItem = BlobTreeItem | BlobDirectoryTreeItem | BlobConta
type AzureStorageTreeItem = AzureStorageFileTreeItem | AzureStorageBlobTreeItem;
type AzureStorageDirectoryTreeItem = DirectoryTreeItem | FileShareTreeItem | BlobDirectoryTreeItem | BlobContainerTreeItem;

/**
* @deprecated Use BlobContainerFS as FileSystemProvider for blob containers.
* @todo: Implement FileShareFS as FileSystemProvider for file shares.
* @todo: Support attached storage accounts in BlobContainerFS and FileShareFS
*/
export class AzureStorageFS implements vscode.FileSystemProvider, vscode.TextDocumentContentProvider {
private _emitter: vscode.EventEmitter<vscode.FileChangeEvent[]> = new vscode.EventEmitter<vscode.FileChangeEvent[]>();
private _bufferedEvents: vscode.FileChangeEvent[] = [];
Expand All @@ -38,6 +43,10 @@ export class AzureStorageFS implements vscode.FileSystemProvider, vscode.TextDoc
private _queryCache: Map<string, { query: string, invalid?: boolean }> = new Map<string, { query: string, invalid?: boolean }>(); // Key: rootName
readonly onDidChangeFile: vscode.Event<vscode.FileChangeEvent[]> = this._emitter.event;

static isAttachedAccount(treeItem: BlobContainerTreeItem | FileShareTreeItem | BlobTreeItem): boolean {
return treeItem.fullId.startsWith("/attachedStorageAccounts/");
}

static idToUri(resourceId: string, filePath?: string): vscode.Uri {
let idRegExp: RegExp;
if (resourceId.startsWith('/attachedStorageAccounts')) {
Expand Down

0 comments on commit d8e348b

Please sign in to comment.