mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-22 18:32:00 +00:00
Merge branch 'master' into replace-codemirror-with-monaco
This commit is contained in:
@@ -41,6 +41,7 @@ module.exports = {
|
|||||||
"@typescript-eslint/no-extraneous-class": "error",
|
"@typescript-eslint/no-extraneous-class": "error",
|
||||||
"no-null/no-null": "error",
|
"no-null/no-null": "error",
|
||||||
"@typescript-eslint/no-explicit-any": "error",
|
"@typescript-eslint/no-explicit-any": "error",
|
||||||
"prefer-arrow/prefer-arrow-functions": ["error", { allowStandaloneDeclarations: true }]
|
"prefer-arrow/prefer-arrow-functions": ["error", { allowStandaloneDeclarations: true }],
|
||||||
|
eqeqeq: "error"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
24
package-lock.json
generated
24
package-lock.json
generated
@@ -5,13 +5,14 @@
|
|||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@azure/cosmos": {
|
"@azure/cosmos": {
|
||||||
"version": "3.7.4",
|
"version": "3.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/@azure/cosmos/-/cosmos-3.7.4.tgz",
|
"resolved": "https://registry.npmjs.org/@azure/cosmos/-/cosmos-3.9.0.tgz",
|
||||||
"integrity": "sha512-IbSEadapQDajSCXj7gUc8OklkOd/oAY4w7XBLHouWc4iKQTtntb2DmGjhrbh2W5Ku+pmBSr1GTApCjQ55iIjlQ==",
|
"integrity": "sha512-SA+QB54I8Dvg/ZolHpsEDLK/sbSB9sFmSU1ElnMTFw88TVik+LYHq4o/srU2TY6Gr1BketjPmgLVEqrmnRvjkw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/debug": "^4.1.4",
|
"@types/debug": "^4.1.4",
|
||||||
"debug": "^4.1.1",
|
"debug": "^4.1.1",
|
||||||
"fast-json-stable-stringify": "^2.0.0",
|
"fast-json-stable-stringify": "^2.0.0",
|
||||||
|
"jsbi": "^3.1.3",
|
||||||
"node-abort-controller": "^1.0.4",
|
"node-abort-controller": "^1.0.4",
|
||||||
"node-fetch": "^2.6.0",
|
"node-fetch": "^2.6.0",
|
||||||
"os-name": "^3.1.0",
|
"os-name": "^3.1.0",
|
||||||
@@ -22,14 +23,14 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tslib": {
|
"tslib": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz",
|
||||||
"integrity": "sha512-lTqkx847PI7xEDYJntxZH89L2/aXInsyF2luSafe/+0fHOMjlBNXdH6th7f70qxLDhul7KZK0zC8V5ZIyHl0/g=="
|
"integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ=="
|
||||||
},
|
},
|
||||||
"uuid": {
|
"uuid": {
|
||||||
"version": "8.2.0",
|
"version": "8.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.0.tgz",
|
||||||
"integrity": "sha512-CYpGiFTUrmI6OBMkAdjSDM0k5h8SkkiTP4WAjQgDgNB1S3Ou9VBEvr6q0Kv2H1mMk7IWfxYGpMH5sd5AvcIV2Q=="
|
"integrity": "sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ=="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -20204,6 +20205,11 @@
|
|||||||
"esprima": "^4.0.0"
|
"esprima": "^4.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"jsbi": {
|
||||||
|
"version": "3.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/jsbi/-/jsbi-3.1.3.tgz",
|
||||||
|
"integrity": "sha512-nBJqA0C6Qns+ZxurbEoIR56wyjiUszpNy70FHvxO5ervMoCbZVE3z3kxr5nKGhlxr/9MhKTSUBs7cAwwuf3g9w=="
|
||||||
|
},
|
||||||
"jsbn": {
|
"jsbn": {
|
||||||
"version": "0.1.1",
|
"version": "0.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"description": "Cosmos Explorer",
|
"description": "Cosmos Explorer",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@azure/cosmos": "3.7.4",
|
"@azure/cosmos": "3.9.0",
|
||||||
"@azure/cosmos-language-service": "0.0.4",
|
"@azure/cosmos-language-service": "0.0.4",
|
||||||
"@jupyterlab/services": "4.2.0",
|
"@jupyterlab/services": "4.2.0",
|
||||||
"@jupyterlab/terminal": "1.2.1",
|
"@jupyterlab/terminal": "1.2.1",
|
||||||
|
|||||||
@@ -134,6 +134,7 @@ export class Features {
|
|||||||
public static readonly enableAutoPilotV2 = "enableautopilotv2";
|
public static readonly enableAutoPilotV2 = "enableautopilotv2";
|
||||||
public static readonly ttl90Days = "ttl90days";
|
public static readonly ttl90Days = "ttl90days";
|
||||||
public static readonly enableRightPanelV2 = "enablerightpanelv2";
|
public static readonly enableRightPanelV2 = "enablerightpanelv2";
|
||||||
|
public static readonly enableSDKoperations = "enablesdkoperations";
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AfecFeatures {
|
export class AfecFeatures {
|
||||||
|
|||||||
@@ -6,15 +6,13 @@ import * as ViewModels from "../Contracts/ViewModels";
|
|||||||
import Q from "q";
|
import Q from "q";
|
||||||
import {
|
import {
|
||||||
ConflictDefinition,
|
ConflictDefinition,
|
||||||
ContainerDefinition,
|
|
||||||
ContainerResponse,
|
|
||||||
DatabaseResponse,
|
|
||||||
FeedOptions,
|
FeedOptions,
|
||||||
ItemDefinition,
|
ItemDefinition,
|
||||||
PartitionKeyDefinition,
|
PartitionKeyDefinition,
|
||||||
QueryIterator,
|
QueryIterator,
|
||||||
Resource,
|
Resource,
|
||||||
TriggerDefinition
|
TriggerDefinition,
|
||||||
|
OfferDefinition
|
||||||
} from "@azure/cosmos";
|
} from "@azure/cosmos";
|
||||||
import { ContainerRequest } from "@azure/cosmos/dist-esm/client/Container/ContainerRequest";
|
import { ContainerRequest } from "@azure/cosmos/dist-esm/client/Container/ContainerRequest";
|
||||||
import { client } from "./CosmosClient";
|
import { client } from "./CosmosClient";
|
||||||
@@ -202,23 +200,6 @@ export function getPartitionKeyHeader(partitionKeyDefinition: DataModels.Partiti
|
|||||||
return [partitionKeyValue];
|
return [partitionKeyValue];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function updateCollection(
|
|
||||||
databaseId: string,
|
|
||||||
collectionId: string,
|
|
||||||
newCollection: DataModels.Collection,
|
|
||||||
options: any = {}
|
|
||||||
): Q.Promise<DataModels.Collection> {
|
|
||||||
return Q(
|
|
||||||
client()
|
|
||||||
.database(databaseId)
|
|
||||||
.container(collectionId)
|
|
||||||
.replace(newCollection as ContainerDefinition, options)
|
|
||||||
.then(async (response: ContainerResponse) => {
|
|
||||||
return refreshCachedResources().then(() => response.resource as DataModels.Collection);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function updateDocument(
|
export function updateDocument(
|
||||||
collection: ViewModels.CollectionBase,
|
collection: ViewModels.CollectionBase,
|
||||||
documentId: DocumentId,
|
documentId: DocumentId,
|
||||||
@@ -244,7 +225,8 @@ export function updateOffer(
|
|||||||
return Q(
|
return Q(
|
||||||
client()
|
client()
|
||||||
.offer(offer.id)
|
.offer(offer.id)
|
||||||
.replace(newOffer, options)
|
// TODO Remove casting when SDK types are fixed (https://github.com/Azure/azure-sdk-for-js/issues/10660)
|
||||||
|
.replace((newOffer as unknown) as OfferDefinition, options)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
return Promise.all([refreshCachedOffers(), refreshCachedResources()]).then(() => response.resource);
|
return Promise.all([refreshCachedOffers(), refreshCachedResources()]).then(() => response.resource);
|
||||||
})
|
})
|
||||||
@@ -454,6 +436,10 @@ export function readCollectionQuotaInfo(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function readOffers(options: any): Q.Promise<DataModels.Offer[]> {
|
export function readOffers(options: any): Q.Promise<DataModels.Offer[]> {
|
||||||
|
if (options.isServerless) {
|
||||||
|
return Q([]); // Reading offers is not supported for serverless accounts
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (configContext.platform === Platform.Portal) {
|
if (configContext.platform === Platform.Portal) {
|
||||||
return sendCachedDataMessage<DataModels.Offer[]>(MessageTypes.AllOffers, [
|
return sendCachedDataMessage<DataModels.Offer[]>(MessageTypes.AllOffers, [
|
||||||
@@ -469,6 +455,13 @@ export function readOffers(options: any): Q.Promise<DataModels.Offer[]> {
|
|||||||
.offers.readAll()
|
.offers.readAll()
|
||||||
.fetchAll()
|
.fetchAll()
|
||||||
.then(response => response.resources)
|
.then(response => response.resources)
|
||||||
|
.catch(error => {
|
||||||
|
// This should be removed when we can correctly identify if an account is serverless when connected using connection string too.
|
||||||
|
if (error.message.includes("Reading or replacing offers is not supported for serverless accounts")) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -550,26 +543,6 @@ export function getOrCreateDatabaseAndCollection(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createDatabase(
|
|
||||||
request: DataModels.CreateDatabaseRequest,
|
|
||||||
options: any
|
|
||||||
): Q.Promise<DataModels.Database> {
|
|
||||||
var deferred = Q.defer<DataModels.Database>();
|
|
||||||
|
|
||||||
_createDatabase(request, options).then(
|
|
||||||
(createdDatabase: DataModels.Database) => {
|
|
||||||
refreshCachedOffers().then(() => {
|
|
||||||
deferred.resolve(createdDatabase);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
_createDatabaseError => {
|
|
||||||
deferred.reject(_createDatabaseError);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
return deferred.promise;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function refreshCachedOffers(): Q.Promise<void> {
|
export function refreshCachedOffers(): Q.Promise<void> {
|
||||||
if (configContext.platform === Platform.Portal) {
|
if (configContext.platform === Platform.Portal) {
|
||||||
return sendCachedDataMessage(MessageTypes.RefreshOffers, []);
|
return sendCachedDataMessage(MessageTypes.RefreshOffers, []);
|
||||||
@@ -598,33 +571,3 @@ export function queryConflicts(
|
|||||||
.conflicts.query(query, options);
|
.conflicts.query(query, options);
|
||||||
return Q(documentsIterator);
|
return Q(documentsIterator);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _createDatabase(request: DataModels.CreateDatabaseRequest, options: any = {}): Q.Promise<DataModels.Database> {
|
|
||||||
const { databaseId, databaseLevelThroughput, offerThroughput, autoPilot, hasAutoPilotV2FeatureFlag } = request;
|
|
||||||
const createBody: DatabaseRequest = { id: databaseId };
|
|
||||||
const databaseOptions: any = options && _.omit(options, "sharedOfferThroughput");
|
|
||||||
// TODO: replace when SDK support autopilot
|
|
||||||
const initialHeaders = autoPilot
|
|
||||||
? !hasAutoPilotV2FeatureFlag
|
|
||||||
? {
|
|
||||||
[Constants.HttpHeaders.autoPilotThroughputSDK]: JSON.stringify({ maxThroughput: autoPilot.maxThroughput })
|
|
||||||
}
|
|
||||||
: {
|
|
||||||
[Constants.HttpHeaders.autoPilotTier]: autoPilot.autopilotTier
|
|
||||||
}
|
|
||||||
: undefined;
|
|
||||||
if (!!databaseLevelThroughput) {
|
|
||||||
if (autoPilot) {
|
|
||||||
databaseOptions.initialHeaders = initialHeaders;
|
|
||||||
}
|
|
||||||
createBody.throughput = offerThroughput;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Q(
|
|
||||||
client()
|
|
||||||
.databases.create(createBody, databaseOptions)
|
|
||||||
.then((response: DatabaseResponse) => {
|
|
||||||
return refreshCachedResources(databaseOptions).then(() => response.resource);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -266,42 +266,6 @@ export function readDocument(collection: ViewModels.CollectionBase, documentId:
|
|||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function updateCollection(
|
|
||||||
databaseId: string,
|
|
||||||
collection: ViewModels.Collection,
|
|
||||||
newCollection: DataModels.Collection
|
|
||||||
): Q.Promise<DataModels.Collection> {
|
|
||||||
var deferred = Q.defer<any>();
|
|
||||||
const id = NotificationConsoleUtils.logConsoleMessage(
|
|
||||||
ConsoleDataType.InProgress,
|
|
||||||
`Updating container ${collection.id()}`
|
|
||||||
);
|
|
||||||
DataAccessUtilityBase.updateCollection(databaseId, collection.id(), newCollection)
|
|
||||||
.then(
|
|
||||||
(replacedCollection: DataModels.Collection) => {
|
|
||||||
NotificationConsoleUtils.logConsoleMessage(
|
|
||||||
ConsoleDataType.Info,
|
|
||||||
`Successfully updated container ${collection.id()}`
|
|
||||||
);
|
|
||||||
deferred.resolve(replacedCollection);
|
|
||||||
},
|
|
||||||
(error: any) => {
|
|
||||||
NotificationConsoleUtils.logConsoleMessage(
|
|
||||||
ConsoleDataType.Error,
|
|
||||||
`Failed to update container ${collection.id()}: ${JSON.stringify(error)}`
|
|
||||||
);
|
|
||||||
Logger.logError(JSON.stringify(error), "UpdateCollection", error.code);
|
|
||||||
sendNotificationForError(error);
|
|
||||||
deferred.reject(error);
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.finally(() => {
|
|
||||||
NotificationConsoleUtils.clearInProgressMessageWithId(id);
|
|
||||||
});
|
|
||||||
|
|
||||||
return deferred.promise;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function updateDocument(
|
export function updateDocument(
|
||||||
collection: ViewModels.CollectionBase,
|
collection: ViewModels.CollectionBase,
|
||||||
documentId: DocumentId,
|
documentId: DocumentId,
|
||||||
@@ -926,36 +890,3 @@ export function getOrCreateDatabaseAndCollection(
|
|||||||
|
|
||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createDatabase(
|
|
||||||
request: DataModels.CreateDatabaseRequest,
|
|
||||||
options: any = {}
|
|
||||||
): Q.Promise<DataModels.Database> {
|
|
||||||
const deferred: Q.Deferred<DataModels.Database> = Q.defer<DataModels.Database>();
|
|
||||||
const id = NotificationConsoleUtils.logConsoleMessage(
|
|
||||||
ConsoleDataType.InProgress,
|
|
||||||
`Creating a new database ${request.databaseId}`
|
|
||||||
);
|
|
||||||
|
|
||||||
DataAccessUtilityBase.createDatabase(request, options)
|
|
||||||
.then(
|
|
||||||
(database: DataModels.Database) => {
|
|
||||||
NotificationConsoleUtils.logConsoleMessage(
|
|
||||||
ConsoleDataType.Info,
|
|
||||||
`Successfully created database ${request.databaseId}`
|
|
||||||
);
|
|
||||||
deferred.resolve(database);
|
|
||||||
},
|
|
||||||
(error: any) => {
|
|
||||||
NotificationConsoleUtils.logConsoleMessage(
|
|
||||||
ConsoleDataType.Error,
|
|
||||||
`Error while creating database ${request.databaseId}:\n ${JSON.stringify(error)}`
|
|
||||||
);
|
|
||||||
sendNotificationForError(error);
|
|
||||||
deferred.reject(error);
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.finally(() => NotificationConsoleUtils.clearInProgressMessageWithId(id));
|
|
||||||
|
|
||||||
return deferred.promise;
|
|
||||||
}
|
|
||||||
|
|||||||
250
src/Common/dataAccess/createDatabase.ts
Normal file
250
src/Common/dataAccess/createDatabase.ts
Normal file
@@ -0,0 +1,250 @@
|
|||||||
|
import * as DataModels from "../../Contracts/DataModels";
|
||||||
|
import { AuthType } from "../../AuthType";
|
||||||
|
import { DatabaseResponse } from "@azure/cosmos";
|
||||||
|
import { DatabaseRequest } from "@azure/cosmos/dist-esm/client/Database/DatabaseRequest";
|
||||||
|
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
||||||
|
import { RequestOptions } from "@azure/cosmos/dist-esm";
|
||||||
|
import {
|
||||||
|
SqlDatabaseCreateUpdateParameters,
|
||||||
|
CreateUpdateOptions
|
||||||
|
} from "../../Utils/arm/generatedClients/2020-04-01/types";
|
||||||
|
import { client } from "../CosmosClient";
|
||||||
|
import { createUpdateSqlDatabase, getSqlDatabase } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
||||||
|
import {
|
||||||
|
createUpdateCassandraKeyspace,
|
||||||
|
getCassandraKeyspace
|
||||||
|
} from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources";
|
||||||
|
import {
|
||||||
|
createUpdateMongoDBDatabase,
|
||||||
|
getMongoDBDatabase
|
||||||
|
} from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
|
||||||
|
import {
|
||||||
|
createUpdateGremlinDatabase,
|
||||||
|
getGremlinDatabase
|
||||||
|
} from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources";
|
||||||
|
import { logConsoleProgress, logConsoleError, logConsoleInfo } from "../../Utils/NotificationConsoleUtils";
|
||||||
|
import { logError } from "../Logger";
|
||||||
|
import { refreshCachedOffers, refreshCachedResources } from "../DataAccessUtilityBase";
|
||||||
|
import { sendNotificationForError } from "./sendNotificationForError";
|
||||||
|
import { userContext } from "../../UserContext";
|
||||||
|
|
||||||
|
export async function createDatabase(params: DataModels.CreateDatabaseParams): Promise<DataModels.Database> {
|
||||||
|
let database: DataModels.Database;
|
||||||
|
const clearMessage = logConsoleProgress(`Creating a new database ${params.databaseId}`);
|
||||||
|
try {
|
||||||
|
if (
|
||||||
|
window.authType === AuthType.AAD &&
|
||||||
|
!userContext.useSDKOperations &&
|
||||||
|
userContext.defaultExperience !== DefaultAccountExperienceType.Table
|
||||||
|
) {
|
||||||
|
database = await createDatabaseWithARM(params);
|
||||||
|
} else {
|
||||||
|
database = await createDatabaseWithSDK(params);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
logConsoleError(`Error while creating database ${params.databaseId}:\n ${error.message}`);
|
||||||
|
logError(JSON.stringify(error), "CreateDatabase", error.code);
|
||||||
|
sendNotificationForError(error);
|
||||||
|
clearMessage();
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
logConsoleInfo(`Successfully created database ${params.databaseId}`);
|
||||||
|
await refreshCachedResources();
|
||||||
|
await refreshCachedOffers();
|
||||||
|
clearMessage();
|
||||||
|
return database;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createDatabaseWithARM(params: DataModels.CreateDatabaseParams): Promise<DataModels.Database> {
|
||||||
|
const defaultExperience = userContext.defaultExperience;
|
||||||
|
switch (defaultExperience) {
|
||||||
|
case DefaultAccountExperienceType.DocumentDB:
|
||||||
|
return createSqlDatabase(params);
|
||||||
|
case DefaultAccountExperienceType.MongoDB:
|
||||||
|
return createMongoDatabase(params);
|
||||||
|
case DefaultAccountExperienceType.Cassandra:
|
||||||
|
return createCassandraKeyspace(params);
|
||||||
|
case DefaultAccountExperienceType.Graph:
|
||||||
|
return createGremlineDatabase(params);
|
||||||
|
default:
|
||||||
|
throw new Error(`Unsupported default experience type: ${defaultExperience}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createSqlDatabase(params: DataModels.CreateDatabaseParams): Promise<DataModels.Database> {
|
||||||
|
try {
|
||||||
|
const getResponse = await getSqlDatabase(
|
||||||
|
userContext.subscriptionId,
|
||||||
|
userContext.resourceGroup,
|
||||||
|
userContext.databaseAccount.name,
|
||||||
|
params.databaseId
|
||||||
|
);
|
||||||
|
if (getResponse && getResponse.properties && getResponse.properties.resource) {
|
||||||
|
throw new Error(`Create database failed: database with id ${params.databaseId} already exists`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (error.code !== "NotFound") {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const options: CreateUpdateOptions = constructRpOptions(params);
|
||||||
|
const rpPayload: SqlDatabaseCreateUpdateParameters = {
|
||||||
|
properties: {
|
||||||
|
resource: {
|
||||||
|
id: params.databaseId
|
||||||
|
},
|
||||||
|
options
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const createResponse = await createUpdateSqlDatabase(
|
||||||
|
userContext.subscriptionId,
|
||||||
|
userContext.resourceGroup,
|
||||||
|
userContext.databaseAccount.name,
|
||||||
|
params.databaseId,
|
||||||
|
rpPayload
|
||||||
|
);
|
||||||
|
return createResponse && (createResponse.properties.resource as DataModels.Database);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createMongoDatabase(params: DataModels.CreateDatabaseParams): Promise<DataModels.Database> {
|
||||||
|
try {
|
||||||
|
const getResponse = await getMongoDBDatabase(
|
||||||
|
userContext.subscriptionId,
|
||||||
|
userContext.resourceGroup,
|
||||||
|
userContext.databaseAccount.name,
|
||||||
|
params.databaseId
|
||||||
|
);
|
||||||
|
if (getResponse && getResponse.properties && getResponse.properties.resource) {
|
||||||
|
throw new Error(`Create database failed: database with id ${params.databaseId} already exists`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (error.code !== "NotFound") {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const options: CreateUpdateOptions = constructRpOptions(params);
|
||||||
|
const rpPayload: SqlDatabaseCreateUpdateParameters = {
|
||||||
|
properties: {
|
||||||
|
resource: {
|
||||||
|
id: params.databaseId
|
||||||
|
},
|
||||||
|
options
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const createResponse = await createUpdateMongoDBDatabase(
|
||||||
|
userContext.subscriptionId,
|
||||||
|
userContext.resourceGroup,
|
||||||
|
userContext.databaseAccount.name,
|
||||||
|
params.databaseId,
|
||||||
|
rpPayload
|
||||||
|
);
|
||||||
|
return createResponse && (createResponse.properties.resource as DataModels.Database);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createCassandraKeyspace(params: DataModels.CreateDatabaseParams): Promise<DataModels.Database> {
|
||||||
|
try {
|
||||||
|
const getResponse = await getCassandraKeyspace(
|
||||||
|
userContext.subscriptionId,
|
||||||
|
userContext.resourceGroup,
|
||||||
|
userContext.databaseAccount.name,
|
||||||
|
params.databaseId
|
||||||
|
);
|
||||||
|
if (getResponse?.properties?.resource) {
|
||||||
|
throw new Error(`Create database failed: database with id ${params.databaseId} already exists`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (error.code !== "NotFound") {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const options: CreateUpdateOptions = constructRpOptions(params);
|
||||||
|
const rpPayload: SqlDatabaseCreateUpdateParameters = {
|
||||||
|
properties: {
|
||||||
|
resource: {
|
||||||
|
id: params.databaseId
|
||||||
|
},
|
||||||
|
options
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const createResponse = await createUpdateCassandraKeyspace(
|
||||||
|
userContext.subscriptionId,
|
||||||
|
userContext.resourceGroup,
|
||||||
|
userContext.databaseAccount.name,
|
||||||
|
params.databaseId,
|
||||||
|
rpPayload
|
||||||
|
);
|
||||||
|
return createResponse && (createResponse.properties.resource as DataModels.Database);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createGremlineDatabase(params: DataModels.CreateDatabaseParams): Promise<DataModels.Database> {
|
||||||
|
try {
|
||||||
|
const getResponse = await getGremlinDatabase(
|
||||||
|
userContext.subscriptionId,
|
||||||
|
userContext.resourceGroup,
|
||||||
|
userContext.databaseAccount.name,
|
||||||
|
params.databaseId
|
||||||
|
);
|
||||||
|
if (getResponse && getResponse.properties && getResponse.properties.resource) {
|
||||||
|
throw new Error(`Create database failed: database with id ${params.databaseId} already exists`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (error.code !== "NotFound") {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const options: CreateUpdateOptions = constructRpOptions(params);
|
||||||
|
const rpPayload: SqlDatabaseCreateUpdateParameters = {
|
||||||
|
properties: {
|
||||||
|
resource: {
|
||||||
|
id: params.databaseId
|
||||||
|
},
|
||||||
|
options
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const createResponse = await createUpdateGremlinDatabase(
|
||||||
|
userContext.subscriptionId,
|
||||||
|
userContext.resourceGroup,
|
||||||
|
userContext.databaseAccount.name,
|
||||||
|
params.databaseId,
|
||||||
|
rpPayload
|
||||||
|
);
|
||||||
|
return createResponse && (createResponse.properties.resource as DataModels.Database);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createDatabaseWithSDK(params: DataModels.CreateDatabaseParams): Promise<DataModels.Database> {
|
||||||
|
const createBody: DatabaseRequest = { id: params.databaseId };
|
||||||
|
const databaseOptions: RequestOptions = {};
|
||||||
|
// TODO: replace when SDK support autopilot
|
||||||
|
if (params.databaseLevelThroughput) {
|
||||||
|
if (params.autoPilotMaxThroughput) {
|
||||||
|
createBody.maxThroughput = params.autoPilotMaxThroughput;
|
||||||
|
} else {
|
||||||
|
createBody.throughput = params.offerThroughput;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const response: DatabaseResponse = await client().databases.create(createBody, databaseOptions);
|
||||||
|
return response.resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
function constructRpOptions(params: DataModels.CreateDatabaseParams): CreateUpdateOptions {
|
||||||
|
if (!params.databaseLevelThroughput) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.autoPilotMaxThroughput) {
|
||||||
|
return {
|
||||||
|
autoscaleSettings: {
|
||||||
|
maxThroughput: params.autoPilotMaxThroughput
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
throughput: params.offerThroughput
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@ import { refreshCachedResources } from "../DataAccessUtilityBase";
|
|||||||
export async function deleteCollection(databaseId: string, collectionId: string): Promise<void> {
|
export async function deleteCollection(databaseId: string, collectionId: string): Promise<void> {
|
||||||
const clearMessage = logConsoleProgress(`Deleting container ${collectionId}`);
|
const clearMessage = logConsoleProgress(`Deleting container ${collectionId}`);
|
||||||
try {
|
try {
|
||||||
if (window.authType === AuthType.AAD) {
|
if (window.authType === AuthType.AAD && !userContext.useSDKOperations) {
|
||||||
await deleteCollectionWithARM(databaseId, collectionId);
|
await deleteCollectionWithARM(databaseId, collectionId);
|
||||||
} else {
|
} else {
|
||||||
await client()
|
await client()
|
||||||
|
|||||||
@@ -15,7 +15,11 @@ export async function deleteDatabase(databaseId: string): Promise<void> {
|
|||||||
const clearMessage = logConsoleProgress(`Deleting database ${databaseId}`);
|
const clearMessage = logConsoleProgress(`Deleting database ${databaseId}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (window.authType === AuthType.AAD) {
|
if (
|
||||||
|
window.authType === AuthType.AAD &&
|
||||||
|
userContext.defaultExperience !== DefaultAccountExperienceType.Table &&
|
||||||
|
!userContext.useSDKOperations
|
||||||
|
) {
|
||||||
await deleteDatabaseWithARM(databaseId);
|
await deleteDatabaseWithARM(databaseId);
|
||||||
} else {
|
} else {
|
||||||
await client()
|
await client()
|
||||||
|
|||||||
@@ -16,7 +16,12 @@ export async function readCollections(databaseId: string): Promise<DataModels.Co
|
|||||||
let collections: DataModels.Collection[];
|
let collections: DataModels.Collection[];
|
||||||
const clearMessage = logConsoleProgress(`Querying containers for database ${databaseId}`);
|
const clearMessage = logConsoleProgress(`Querying containers for database ${databaseId}`);
|
||||||
try {
|
try {
|
||||||
if (window.authType === AuthType.AAD) {
|
if (
|
||||||
|
window.authType === AuthType.AAD &&
|
||||||
|
!userContext.useSDKOperations &&
|
||||||
|
userContext.defaultExperience !== DefaultAccountExperienceType.MongoDB &&
|
||||||
|
userContext.defaultExperience !== DefaultAccountExperienceType.Table
|
||||||
|
) {
|
||||||
collections = await readCollectionsWithARM(databaseId);
|
collections = await readCollectionsWithARM(databaseId);
|
||||||
} else {
|
} else {
|
||||||
const sdkResponse = await client()
|
const sdkResponse = await client()
|
||||||
|
|||||||
@@ -15,7 +15,13 @@ export async function readDatabases(): Promise<DataModels.Database[]> {
|
|||||||
let databases: DataModels.Database[];
|
let databases: DataModels.Database[];
|
||||||
const clearMessage = logConsoleProgress(`Querying databases`);
|
const clearMessage = logConsoleProgress(`Querying databases`);
|
||||||
try {
|
try {
|
||||||
if (window.authType === AuthType.AAD) {
|
if (
|
||||||
|
window.authType === AuthType.AAD &&
|
||||||
|
!userContext.useSDKOperations &&
|
||||||
|
userContext.defaultExperience !== DefaultAccountExperienceType.MongoDB &&
|
||||||
|
userContext.defaultExperience !== DefaultAccountExperienceType.Table &&
|
||||||
|
userContext.defaultExperience !== DefaultAccountExperienceType.Cassandra
|
||||||
|
) {
|
||||||
databases = await readDatabasesWithARM();
|
databases = await readDatabasesWithARM();
|
||||||
} else {
|
} else {
|
||||||
const sdkResponse = await client()
|
const sdkResponse = await client()
|
||||||
|
|||||||
225
src/Common/dataAccess/updateCollection.ts
Normal file
225
src/Common/dataAccess/updateCollection.ts
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
import { AuthType } from "../../AuthType";
|
||||||
|
import { Collection } from "../../Contracts/DataModels";
|
||||||
|
import { ContainerDefinition } from "@azure/cosmos";
|
||||||
|
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
||||||
|
import {
|
||||||
|
ExtendedResourceProperties,
|
||||||
|
SqlContainerCreateUpdateParameters,
|
||||||
|
SqlContainerResource
|
||||||
|
} from "../../Utils/arm/generatedClients/2020-04-01/types";
|
||||||
|
import { RequestOptions } from "@azure/cosmos/dist-esm";
|
||||||
|
import { client } from "../CosmosClient";
|
||||||
|
import { createUpdateSqlContainer, getSqlContainer } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
||||||
|
import {
|
||||||
|
createUpdateCassandraTable,
|
||||||
|
getCassandraTable
|
||||||
|
} from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources";
|
||||||
|
import {
|
||||||
|
createUpdateMongoDBCollection,
|
||||||
|
getMongoDBCollection
|
||||||
|
} from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
|
||||||
|
import {
|
||||||
|
createUpdateGremlinGraph,
|
||||||
|
getGremlinGraph
|
||||||
|
} from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources";
|
||||||
|
import { createUpdateTable, getTable } from "../../Utils/arm/generatedClients/2020-04-01/tableResources";
|
||||||
|
import { logConsoleError, logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||||
|
import { logError } from "../Logger";
|
||||||
|
import { refreshCachedResources } from "../DataAccessUtilityBase";
|
||||||
|
import { sendNotificationForError } from "./sendNotificationForError";
|
||||||
|
import { userContext } from "../../UserContext";
|
||||||
|
|
||||||
|
export async function updateCollection(
|
||||||
|
databaseId: string,
|
||||||
|
collectionId: string,
|
||||||
|
newCollection: Collection,
|
||||||
|
options: RequestOptions = {}
|
||||||
|
): Promise<Collection> {
|
||||||
|
let collection: Collection;
|
||||||
|
const clearMessage = logConsoleProgress(`Updating container ${collectionId}`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (
|
||||||
|
window.authType === AuthType.AAD &&
|
||||||
|
userContext.defaultExperience !== DefaultAccountExperienceType.MongoDB &&
|
||||||
|
userContext.defaultExperience !== DefaultAccountExperienceType.Table
|
||||||
|
) {
|
||||||
|
collection = await updateCollectionWithARM(databaseId, collectionId, newCollection);
|
||||||
|
} else {
|
||||||
|
const sdkResponse = await client()
|
||||||
|
.database(databaseId)
|
||||||
|
.container(collectionId)
|
||||||
|
.replace(newCollection as ContainerDefinition, options);
|
||||||
|
collection = sdkResponse.resource as Collection;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
logConsoleError(`Failed to update container ${collectionId}: ${JSON.stringify(error)}`);
|
||||||
|
logError(JSON.stringify(error), "UpdateCollection", error.code);
|
||||||
|
sendNotificationForError(error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
logConsoleInfo(`Successfully updated container ${collectionId}`);
|
||||||
|
clearMessage();
|
||||||
|
await refreshCachedResources();
|
||||||
|
return collection;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateCollectionWithARM(
|
||||||
|
databaseId: string,
|
||||||
|
collectionId: string,
|
||||||
|
newCollection: Collection
|
||||||
|
): Promise<Collection> {
|
||||||
|
const subscriptionId = userContext.subscriptionId;
|
||||||
|
const resourceGroup = userContext.resourceGroup;
|
||||||
|
const accountName = userContext.databaseAccount.name;
|
||||||
|
const defaultExperience = userContext.defaultExperience;
|
||||||
|
|
||||||
|
switch (defaultExperience) {
|
||||||
|
case DefaultAccountExperienceType.DocumentDB:
|
||||||
|
return updateSqlContainer(databaseId, collectionId, subscriptionId, resourceGroup, accountName, newCollection);
|
||||||
|
case DefaultAccountExperienceType.MongoDB:
|
||||||
|
return updateMongoDBCollection(
|
||||||
|
databaseId,
|
||||||
|
collectionId,
|
||||||
|
subscriptionId,
|
||||||
|
resourceGroup,
|
||||||
|
accountName,
|
||||||
|
newCollection
|
||||||
|
);
|
||||||
|
case DefaultAccountExperienceType.Cassandra:
|
||||||
|
return updateCassandraTable(databaseId, collectionId, subscriptionId, resourceGroup, accountName, newCollection);
|
||||||
|
case DefaultAccountExperienceType.Graph:
|
||||||
|
return updateGremlinGraph(databaseId, collectionId, subscriptionId, resourceGroup, accountName, newCollection);
|
||||||
|
case DefaultAccountExperienceType.Table:
|
||||||
|
return updateTable(collectionId, subscriptionId, resourceGroup, accountName, newCollection);
|
||||||
|
default:
|
||||||
|
throw new Error(`Unsupported default experience type: ${defaultExperience}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateSqlContainer(
|
||||||
|
databaseId: string,
|
||||||
|
collectionId: string,
|
||||||
|
subscriptionId: string,
|
||||||
|
resourceGroup: string,
|
||||||
|
accountName: string,
|
||||||
|
newCollection: Collection
|
||||||
|
): Promise<Collection> {
|
||||||
|
const getResponse = await getSqlContainer(subscriptionId, resourceGroup, accountName, databaseId, collectionId);
|
||||||
|
if (getResponse && getResponse.properties && getResponse.properties.resource) {
|
||||||
|
getResponse.properties.resource = newCollection as SqlContainerResource & ExtendedResourceProperties;
|
||||||
|
const updateResponse = await createUpdateSqlContainer(
|
||||||
|
subscriptionId,
|
||||||
|
resourceGroup,
|
||||||
|
accountName,
|
||||||
|
databaseId,
|
||||||
|
collectionId,
|
||||||
|
getResponse as SqlContainerCreateUpdateParameters
|
||||||
|
);
|
||||||
|
return updateResponse && (updateResponse.properties.resource as Collection);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(`Sql container to update does not exist. Database id: ${databaseId} Collection id: ${collectionId}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateMongoDBCollection(
|
||||||
|
databaseId: string,
|
||||||
|
collectionId: string,
|
||||||
|
subscriptionId: string,
|
||||||
|
resourceGroup: string,
|
||||||
|
accountName: string,
|
||||||
|
newCollection: Collection
|
||||||
|
): Promise<Collection> {
|
||||||
|
const getResponse = await getMongoDBCollection(subscriptionId, resourceGroup, accountName, databaseId, collectionId);
|
||||||
|
if (getResponse && getResponse.properties && getResponse.properties.resource) {
|
||||||
|
getResponse.properties.resource = newCollection as SqlContainerResource & ExtendedResourceProperties;
|
||||||
|
const updateResponse = await createUpdateMongoDBCollection(
|
||||||
|
subscriptionId,
|
||||||
|
resourceGroup,
|
||||||
|
accountName,
|
||||||
|
databaseId,
|
||||||
|
collectionId,
|
||||||
|
getResponse as SqlContainerCreateUpdateParameters
|
||||||
|
);
|
||||||
|
return updateResponse && (updateResponse.properties.resource as Collection);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(
|
||||||
|
`MongoDB collection to update does not exist. Database id: ${databaseId} Collection id: ${collectionId}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateCassandraTable(
|
||||||
|
databaseId: string,
|
||||||
|
collectionId: string,
|
||||||
|
subscriptionId: string,
|
||||||
|
resourceGroup: string,
|
||||||
|
accountName: string,
|
||||||
|
newCollection: Collection
|
||||||
|
): Promise<Collection> {
|
||||||
|
const getResponse = await getCassandraTable(subscriptionId, resourceGroup, accountName, databaseId, collectionId);
|
||||||
|
if (getResponse && getResponse.properties && getResponse.properties.resource) {
|
||||||
|
getResponse.properties.resource = newCollection as SqlContainerResource & ExtendedResourceProperties;
|
||||||
|
const updateResponse = await createUpdateCassandraTable(
|
||||||
|
subscriptionId,
|
||||||
|
resourceGroup,
|
||||||
|
accountName,
|
||||||
|
databaseId,
|
||||||
|
collectionId,
|
||||||
|
getResponse as SqlContainerCreateUpdateParameters
|
||||||
|
);
|
||||||
|
return updateResponse && (updateResponse.properties.resource as Collection);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(
|
||||||
|
`Cassandra table to update does not exist. Database id: ${databaseId} Collection id: ${collectionId}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateGremlinGraph(
|
||||||
|
databaseId: string,
|
||||||
|
collectionId: string,
|
||||||
|
subscriptionId: string,
|
||||||
|
resourceGroup: string,
|
||||||
|
accountName: string,
|
||||||
|
newCollection: Collection
|
||||||
|
): Promise<Collection> {
|
||||||
|
const getResponse = await getGremlinGraph(subscriptionId, resourceGroup, accountName, databaseId, collectionId);
|
||||||
|
if (getResponse && getResponse.properties && getResponse.properties.resource) {
|
||||||
|
getResponse.properties.resource = newCollection as SqlContainerResource & ExtendedResourceProperties;
|
||||||
|
const updateResponse = await createUpdateGremlinGraph(
|
||||||
|
subscriptionId,
|
||||||
|
resourceGroup,
|
||||||
|
accountName,
|
||||||
|
databaseId,
|
||||||
|
collectionId,
|
||||||
|
getResponse as SqlContainerCreateUpdateParameters
|
||||||
|
);
|
||||||
|
return updateResponse && (updateResponse.properties.resource as Collection);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(`Gremlin graph to update does not exist. Database id: ${databaseId} Collection id: ${collectionId}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateTable(
|
||||||
|
collectionId: string,
|
||||||
|
subscriptionId: string,
|
||||||
|
resourceGroup: string,
|
||||||
|
accountName: string,
|
||||||
|
newCollection: Collection
|
||||||
|
): Promise<Collection> {
|
||||||
|
const getResponse = await getTable(subscriptionId, resourceGroup, accountName, collectionId);
|
||||||
|
if (getResponse && getResponse.properties && getResponse.properties.resource) {
|
||||||
|
getResponse.properties.resource = newCollection as SqlContainerResource & ExtendedResourceProperties;
|
||||||
|
const updateResponse = await createUpdateTable(
|
||||||
|
subscriptionId,
|
||||||
|
resourceGroup,
|
||||||
|
accountName,
|
||||||
|
collectionId,
|
||||||
|
getResponse as SqlContainerCreateUpdateParameters
|
||||||
|
);
|
||||||
|
return updateResponse && (updateResponse.properties.resource as Collection);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(`Table to update does not exist. Table id: ${collectionId}`);
|
||||||
|
}
|
||||||
@@ -80,12 +80,20 @@ export async function initializeConfiguration(): Promise<ConfigContext> {
|
|||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Allow override of any config value with URL query parameters
|
// Allow override of platform value with URL query parameter
|
||||||
const params = new URLSearchParams(window.location.search);
|
const params = new URLSearchParams(window.location.search);
|
||||||
params.forEach((value, key) => {
|
if (params.has("platform")) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
const platform = params.get("platform");
|
||||||
(configContext as any)[key] = value;
|
switch (platform) {
|
||||||
});
|
default:
|
||||||
|
console.log("Invalid platform query parameter given, ignoring");
|
||||||
|
break;
|
||||||
|
case Platform.Portal:
|
||||||
|
case Platform.Hosted:
|
||||||
|
case Platform.Emulator:
|
||||||
|
updateConfigContext({ platform });
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("No configuration file found using defaults");
|
console.log("No configuration file found using defaults");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -153,7 +153,14 @@ export interface KeyResource {
|
|||||||
Token: string;
|
Token: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IndexingPolicy {}
|
export interface IndexingPolicy {
|
||||||
|
automatic: boolean;
|
||||||
|
indexingMode: string;
|
||||||
|
includedPaths: any;
|
||||||
|
excludedPaths: any;
|
||||||
|
compositeIndexes?: any;
|
||||||
|
spatialIndexes?: any;
|
||||||
|
}
|
||||||
|
|
||||||
export interface PartitionKey {
|
export interface PartitionKey {
|
||||||
paths: string[];
|
paths: string[];
|
||||||
@@ -320,12 +327,11 @@ export interface AutoPilotOfferSettings {
|
|||||||
targetMaxThroughput?: number;
|
targetMaxThroughput?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CreateDatabaseRequest {
|
export interface CreateDatabaseParams {
|
||||||
|
autoPilotMaxThroughput?: number;
|
||||||
databaseId: string;
|
databaseId: string;
|
||||||
databaseLevelThroughput?: boolean;
|
databaseLevelThroughput?: boolean;
|
||||||
offerThroughput?: number;
|
offerThroughput?: number;
|
||||||
autoPilot?: AutoPilotCreationSettings;
|
|
||||||
hasAutoPilotV2FeatureFlag?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SharedThroughputRange {
|
export interface SharedThroughputRange {
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ import { BindingHandlersRegisterer } from "../Bindings/BindingHandlersRegisterer
|
|||||||
import { BrowseQueriesPane } from "./Panes/BrowseQueriesPane";
|
import { BrowseQueriesPane } from "./Panes/BrowseQueriesPane";
|
||||||
import { CassandraAPIDataClient, TableDataClient, TablesAPIDataClient } from "./Tables/TableDataClient";
|
import { CassandraAPIDataClient, TableDataClient, TablesAPIDataClient } from "./Tables/TableDataClient";
|
||||||
import { CommandBarComponentAdapter } from "./Menus/CommandBar/CommandBarComponentAdapter";
|
import { CommandBarComponentAdapter } from "./Menus/CommandBar/CommandBarComponentAdapter";
|
||||||
import { configContext } from "../ConfigContext";
|
import { configContext, updateConfigContext } from "../ConfigContext";
|
||||||
import { ConsoleData, ConsoleDataType } from "./Menus/NotificationConsole/NotificationConsoleComponent";
|
import { ConsoleData, ConsoleDataType } from "./Menus/NotificationConsole/NotificationConsoleComponent";
|
||||||
import { decryptJWTToken, getAuthorizationHeader } from "../Utils/AuthorizationUtils";
|
import { decryptJWTToken, getAuthorizationHeader } from "../Utils/AuthorizationUtils";
|
||||||
import { DefaultExperienceUtility } from "../Shared/DefaultExperienceUtility";
|
import { DefaultExperienceUtility } from "../Shared/DefaultExperienceUtility";
|
||||||
@@ -975,6 +975,10 @@ export default class Explorer {
|
|||||||
this.sparkClusterConnectionInfo.valueHasMutated();
|
this.sparkClusterConnectionInfo.valueHasMutated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.isFeatureEnabled(Constants.Features.enableSDKoperations)) {
|
||||||
|
updateUserContext({ useSDKOperations: true });
|
||||||
|
}
|
||||||
|
|
||||||
featureSubcription.dispose();
|
featureSubcription.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1475,11 +1479,7 @@ export default class Explorer {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.isServerlessEnabled()) {
|
const offerPromise: Q.Promise<DataModels.Offer[]> = readOffers({ isServerless: this.isServerlessEnabled() });
|
||||||
// Serverless accounts don't support offers call
|
|
||||||
refreshDatabases();
|
|
||||||
} else {
|
|
||||||
const offerPromise: Q.Promise<DataModels.Offer[]> = readOffers();
|
|
||||||
this._setLoadingStatusText("Fetching offers...");
|
this._setLoadingStatusText("Fetching offers...");
|
||||||
offerPromise.then(
|
offerPromise.then(
|
||||||
(offers: DataModels.Offer[]) => {
|
(offers: DataModels.Offer[]) => {
|
||||||
@@ -1506,7 +1506,6 @@ export default class Explorer {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
return deferred.promise.then(
|
return deferred.promise.then(
|
||||||
() => {
|
() => {
|
||||||
@@ -1954,12 +1953,17 @@ export default class Explorer {
|
|||||||
|
|
||||||
this._importExplorerConfigComplete = true;
|
this._importExplorerConfigComplete = true;
|
||||||
|
|
||||||
|
updateConfigContext({
|
||||||
|
ARM_ENDPOINT: this.armEndpoint()
|
||||||
|
});
|
||||||
|
|
||||||
updateUserContext({
|
updateUserContext({
|
||||||
authorizationToken,
|
authorizationToken,
|
||||||
masterKey,
|
masterKey,
|
||||||
databaseAccount
|
databaseAccount,
|
||||||
|
resourceGroup: inputs.resourceGroup,
|
||||||
|
subscriptionId: inputs.subscriptionId
|
||||||
});
|
});
|
||||||
updateUserContext({ resourceGroup: inputs.resourceGroup, subscriptionId: inputs.subscriptionId });
|
|
||||||
TelemetryProcessor.traceSuccess(
|
TelemetryProcessor.traceSuccess(
|
||||||
Action.LoadDatabaseAccount,
|
Action.LoadDatabaseAccount,
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -92,6 +92,11 @@ describe("getPkIdFromDocumentId", () => {
|
|||||||
expect(GraphExplorer.getPkIdFromDocumentId(doc, "mypk")).toEqual("[234, 'id']");
|
expect(GraphExplorer.getPkIdFromDocumentId(doc, "mypk")).toEqual("[234, 'id']");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should create pkid pair from partitioned graph (pk as boolean)", () => {
|
||||||
|
const doc = createFakeDoc({ id: "id", mypk: true });
|
||||||
|
expect(GraphExplorer.getPkIdFromDocumentId(doc, "mypk")).toEqual("[true, 'id']");
|
||||||
|
});
|
||||||
|
|
||||||
it("should create pkid pair from partitioned graph (pk as valid array value)", () => {
|
it("should create pkid pair from partitioned graph (pk as valid array value)", () => {
|
||||||
const doc = createFakeDoc({ id: "id", mypk: [{ id: "someid", _value: "pkvalue" }] });
|
const doc = createFakeDoc({ id: "id", mypk: [{ id: "someid", _value: "pkvalue" }] });
|
||||||
expect(GraphExplorer.getPkIdFromDocumentId(doc, "mypk")).toEqual("['pkvalue', 'id']");
|
expect(GraphExplorer.getPkIdFromDocumentId(doc, "mypk")).toEqual("['pkvalue', 'id']");
|
||||||
|
|||||||
@@ -1371,7 +1371,7 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
|
|||||||
|
|
||||||
if (collectionPartitionKeyProperty && d.hasOwnProperty(collectionPartitionKeyProperty)) {
|
if (collectionPartitionKeyProperty && d.hasOwnProperty(collectionPartitionKeyProperty)) {
|
||||||
let pk = (d as any)[collectionPartitionKeyProperty];
|
let pk = (d as any)[collectionPartitionKeyProperty];
|
||||||
if (typeof pk !== "string" && typeof pk !== "number") {
|
if (typeof pk !== "string" && typeof pk !== "number" && typeof pk !== "boolean") {
|
||||||
if (Array.isArray(pk) && pk.length > 0) {
|
if (Array.isArray(pk) && pk.length > 0) {
|
||||||
// pk is [{ id: 'id', _value: 'value' }]
|
// pk is [{ id: 'id', _value: 'value' }]
|
||||||
pk = pk[0]["_value"];
|
pk = pk[0]["_value"];
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstan
|
|||||||
import { AddDbUtilities } from "../../Shared/AddDatabaseUtility";
|
import { AddDbUtilities } from "../../Shared/AddDatabaseUtility";
|
||||||
import { CassandraAPIDataClient } from "../Tables/TableDataClient";
|
import { CassandraAPIDataClient } from "../Tables/TableDataClient";
|
||||||
import { ContextualPaneBase } from "./ContextualPaneBase";
|
import { ContextualPaneBase } from "./ContextualPaneBase";
|
||||||
|
import { createDatabase } from "../../Common/dataAccess/createDatabase";
|
||||||
import { PlatformType } from "../../PlatformType";
|
import { PlatformType } from "../../PlatformType";
|
||||||
import { refreshCachedOffers, refreshCachedResources, createDatabase } from "../../Common/DocumentClientUtilityBase";
|
|
||||||
import { userContext } from "../../UserContext";
|
import { userContext } from "../../UserContext";
|
||||||
|
|
||||||
export default class AddDatabasePane extends ContextualPaneBase {
|
export default class AddDatabasePane extends ContextualPaneBase {
|
||||||
@@ -304,76 +304,23 @@ export default class AddDatabasePane extends ContextualPaneBase {
|
|||||||
this.formErrors("");
|
this.formErrors("");
|
||||||
this.isExecuting(true);
|
this.isExecuting(true);
|
||||||
|
|
||||||
const createDatabaseParameters: DataModels.RpParameters = {
|
const createDatabaseParams: DataModels.CreateDatabaseParams = {
|
||||||
db: addDatabasePaneStartMessage.database.id,
|
autoPilotMaxThroughput: this.maxAutoPilotThroughputSet(),
|
||||||
st: addDatabasePaneStartMessage.database.shared,
|
databaseId: addDatabasePaneStartMessage.database.id,
|
||||||
offerThroughput: addDatabasePaneStartMessage.offerThroughput,
|
databaseLevelThroughput: addDatabasePaneStartMessage.database.shared,
|
||||||
sid: userContext.subscriptionId,
|
offerThroughput: addDatabasePaneStartMessage.offerThroughput
|
||||||
rg: userContext.resourceGroup,
|
|
||||||
dba: addDatabasePaneStartMessage.databaseAccountName
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const autopilotSettings = this._getAutopilotSettings();
|
createDatabase(createDatabaseParams).then(
|
||||||
|
(database: DataModels.Database) => {
|
||||||
if (this.container.isPreferredApiCassandra()) {
|
this._onCreateDatabaseSuccess(offerThroughput, startKey);
|
||||||
this._createKeyspace(createDatabaseParameters, autopilotSettings, startKey);
|
},
|
||||||
} else if (this.container.isPreferredApiMongoDB() && EnvironmentUtility.isAadUser()) {
|
(reason: any) => {
|
||||||
this._createMongoDatabase(createDatabaseParameters, autopilotSettings, startKey);
|
this._onCreateDatabaseFailure(reason, offerThroughput, reason);
|
||||||
} else if (this.container.isPreferredApiGraph() && EnvironmentUtility.isAadUser()) {
|
|
||||||
this._createGremlinDatabase(createDatabaseParameters, autopilotSettings, startKey);
|
|
||||||
} else if (this.container.isPreferredApiDocumentDB() && EnvironmentUtility.isAadUser()) {
|
|
||||||
this._createSqlDatabase(createDatabaseParameters, autopilotSettings, startKey);
|
|
||||||
} else {
|
|
||||||
this._createDatabase(offerThroughput, startKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private _createSqlDatabase(
|
|
||||||
createDatabaseParameters: DataModels.RpParameters,
|
|
||||||
autoPilotSettings: DataModels.RpOptions,
|
|
||||||
startKey: number
|
|
||||||
) {
|
|
||||||
AddDbUtilities.createSqlDatabase(this.container.armEndpoint(), createDatabaseParameters, autoPilotSettings).then(
|
|
||||||
() => {
|
|
||||||
Promise.all([refreshCachedOffers(), refreshCachedResources()]).then(() => {
|
|
||||||
this._onCreateDatabaseSuccess(createDatabaseParameters.offerThroughput, startKey);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _createMongoDatabase(
|
|
||||||
createDatabaseParameters: DataModels.RpParameters,
|
|
||||||
autoPilotSettings: DataModels.RpOptions,
|
|
||||||
startKey: number
|
|
||||||
) {
|
|
||||||
AddDbUtilities.createMongoDatabaseWithARM(
|
|
||||||
this.container.armEndpoint(),
|
|
||||||
createDatabaseParameters,
|
|
||||||
autoPilotSettings
|
|
||||||
).then(() => {
|
|
||||||
Promise.all([refreshCachedOffers(), refreshCachedResources()]).then(() => {
|
|
||||||
this._onCreateDatabaseSuccess(createDatabaseParameters.offerThroughput, startKey);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private _createGremlinDatabase(
|
|
||||||
createDatabaseParameters: DataModels.RpParameters,
|
|
||||||
autoPilotSettings: DataModels.RpOptions,
|
|
||||||
startKey: number
|
|
||||||
) {
|
|
||||||
AddDbUtilities.createGremlinDatabase(
|
|
||||||
this.container.armEndpoint(),
|
|
||||||
createDatabaseParameters,
|
|
||||||
autoPilotSettings
|
|
||||||
).then(() => {
|
|
||||||
Promise.all([refreshCachedOffers(), refreshCachedResources()]).then(() => {
|
|
||||||
this._onCreateDatabaseSuccess(createDatabaseParameters.offerThroughput, startKey);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public resetData() {
|
public resetData() {
|
||||||
this.databaseId("");
|
this.databaseId("");
|
||||||
this.databaseCreateNewShared(this.getSharedThroughputDefault());
|
this.databaseCreateNewShared(this.getSharedThroughputDefault());
|
||||||
@@ -396,72 +343,6 @@ export default class AddDatabasePane extends ContextualPaneBase {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _createDatabase(offerThroughput: number, telemetryStartKey: number): void {
|
|
||||||
const autoPilot: DataModels.AutoPilotCreationSettings = this._isAutoPilotSelectedAndWhatTier();
|
|
||||||
const createRequest: DataModels.CreateDatabaseRequest = {
|
|
||||||
databaseId: this.databaseId().trim(),
|
|
||||||
offerThroughput,
|
|
||||||
databaseLevelThroughput: this.databaseCreateNewShared(),
|
|
||||||
autoPilot,
|
|
||||||
hasAutoPilotV2FeatureFlag: this.hasAutoPilotV2FeatureFlag()
|
|
||||||
};
|
|
||||||
createDatabase(createRequest).then(
|
|
||||||
(database: DataModels.Database) => {
|
|
||||||
this._onCreateDatabaseSuccess(offerThroughput, telemetryStartKey);
|
|
||||||
},
|
|
||||||
(reason: any) => {
|
|
||||||
this._onCreateDatabaseFailure(reason, offerThroughput, reason);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private _createKeyspace(
|
|
||||||
createDatabaseParameters: DataModels.RpParameters,
|
|
||||||
autoPilotSettings: DataModels.RpOptions,
|
|
||||||
startKey: number
|
|
||||||
): void {
|
|
||||||
if (EnvironmentUtility.isAadUser()) {
|
|
||||||
this._createKeyspaceUsingRP(this.container.armEndpoint(), createDatabaseParameters, autoPilotSettings, startKey);
|
|
||||||
} else {
|
|
||||||
this._createKeyspaceUsingProxy(createDatabaseParameters.offerThroughput, startKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private _createKeyspaceUsingProxy(offerThroughput: number, telemetryStartKey: number): void {
|
|
||||||
const provisionThroughputQueryPart: string = this.databaseCreateNewShared()
|
|
||||||
? `AND cosmosdb_provisioned_throughput=${offerThroughput}`
|
|
||||||
: "";
|
|
||||||
const createKeyspaceQuery: string = `CREATE KEYSPACE ${this.databaseId().trim()} WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 3 } ${provisionThroughputQueryPart};`;
|
|
||||||
(this.container.tableDataClient as CassandraAPIDataClient)
|
|
||||||
.createKeyspace(
|
|
||||||
this.container.databaseAccount().properties.cassandraEndpoint,
|
|
||||||
this.container.databaseAccount().id,
|
|
||||||
this.container,
|
|
||||||
createKeyspaceQuery
|
|
||||||
)
|
|
||||||
.then(
|
|
||||||
() => {
|
|
||||||
this._onCreateDatabaseSuccess(offerThroughput, telemetryStartKey);
|
|
||||||
},
|
|
||||||
(reason: any) => {
|
|
||||||
this._onCreateDatabaseFailure(reason, offerThroughput, telemetryStartKey);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private _createKeyspaceUsingRP(
|
|
||||||
armEndpoint: string,
|
|
||||||
createKeyspaceParameters: DataModels.RpParameters,
|
|
||||||
autoPilotSettings: DataModels.RpOptions,
|
|
||||||
startKey: number
|
|
||||||
): void {
|
|
||||||
AddDbUtilities.createCassandraKeyspace(armEndpoint, createKeyspaceParameters, autoPilotSettings).then(() => {
|
|
||||||
Promise.all([refreshCachedOffers(), refreshCachedResources()]).then(() => {
|
|
||||||
this._onCreateDatabaseSuccess(createKeyspaceParameters.offerThroughput, startKey);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private _onCreateDatabaseSuccess(offerThroughput: number, startKey: number): void {
|
private _onCreateDatabaseSuccess(offerThroughput: number, startKey: number): void {
|
||||||
this.isExecuting(false);
|
this.isExecuting(false);
|
||||||
this.close();
|
this.close();
|
||||||
@@ -582,20 +463,6 @@ export default class AddDatabasePane extends ContextualPaneBase {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _getAutopilotSettings(): DataModels.RpOptions {
|
|
||||||
if (
|
|
||||||
(!this.hasAutoPilotV2FeatureFlag() && this.isAutoPilotSelected() && this.maxAutoPilotThroughputSet()) ||
|
|
||||||
(this.hasAutoPilotV2FeatureFlag() && this.isAutoPilotSelected() && this.selectedAutoPilotTier())
|
|
||||||
) {
|
|
||||||
return !this.hasAutoPilotV2FeatureFlag()
|
|
||||||
? {
|
|
||||||
[Constants.HttpHeaders.autoPilotThroughput]: { maxThroughput: this.maxAutoPilotThroughputSet() * 1 }
|
|
||||||
}
|
|
||||||
: { [Constants.HttpHeaders.autoPilotTier]: this.selectedAutoPilotTier().toString() };
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _updateThroughputLimitByDatabase() {
|
private _updateThroughputLimitByDatabase() {
|
||||||
const throughputDefaults = this.container.collectionCreationDefaults.throughput;
|
const throughputDefaults = this.container.collectionCreationDefaults.throughput;
|
||||||
this.throughput(throughputDefaults.shared);
|
this.throughput(throughputDefaults.shared);
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export interface GenericRightPaneProps {
|
|||||||
onSubmit: () => void;
|
onSubmit: () => void;
|
||||||
submitButtonText: string;
|
submitButtonText: string;
|
||||||
title: string;
|
title: string;
|
||||||
isSubmitButtonVisible?: boolean;
|
isSubmitButtonHidden?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GenericRightPaneState {
|
export interface GenericRightPaneState {
|
||||||
@@ -108,7 +108,7 @@ export class GenericRightPaneComponent extends React.Component<GenericRightPaneP
|
|||||||
<div className="paneFooter">
|
<div className="paneFooter">
|
||||||
<div className="leftpanel-okbut">
|
<div className="leftpanel-okbut">
|
||||||
<PrimaryButton
|
<PrimaryButton
|
||||||
style={{ visibility: this.props.isSubmitButtonVisible ? "visible" : "hidden" }}
|
style={{ visibility: this.props.isSubmitButtonHidden ? "hidden" : "visible" }}
|
||||||
ariaLabel="Submit"
|
ariaLabel="Submit"
|
||||||
title="Submit"
|
title="Submit"
|
||||||
onClick={this.props.onSubmit}
|
onClick={this.props.onSubmit}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ export class PublishNotebookPaneAdapter implements ReactAdapter {
|
|||||||
submitButtonText: "Publish",
|
submitButtonText: "Publish",
|
||||||
onClose: () => this.close(),
|
onClose: () => this.close(),
|
||||||
onSubmit: () => this.submit(),
|
onSubmit: () => this.submit(),
|
||||||
isSubmitButtonVisible: this.isCodeOfConductAccepted
|
isSubmitButtonHidden: !this.isCodeOfConductAccepted
|
||||||
};
|
};
|
||||||
|
|
||||||
const publishNotebookPaneProps: PublishNotebookPaneProps = {
|
const publishNotebookPaneProps: PublishNotebookPaneProps = {
|
||||||
|
|||||||
@@ -285,7 +285,7 @@ export class PublishNotebookPaneComponent extends React.Component<PublishNoteboo
|
|||||||
<GalleryCardComponent
|
<GalleryCardComponent
|
||||||
data={{
|
data={{
|
||||||
id: undefined,
|
id: undefined,
|
||||||
name: this.props.notebookName,
|
name: this.state.notebookName,
|
||||||
description: this.state.notebookDescription,
|
description: this.state.notebookDescription,
|
||||||
gitSha: undefined,
|
gitSha: undefined,
|
||||||
tags: this.state.notebookTags.split(","),
|
tags: this.state.notebookTags.split(","),
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ export class UploadItemsPaneAdapter implements ReactAdapter {
|
|||||||
formErrorDetail: this.formErrorDetail,
|
formErrorDetail: this.formErrorDetail,
|
||||||
id: "uploaditemspane",
|
id: "uploaditemspane",
|
||||||
isExecuting: this.isExecuting,
|
isExecuting: this.isExecuting,
|
||||||
isSubmitButtonVisible: true,
|
|
||||||
title: "Upload Items",
|
title: "Upload Items",
|
||||||
submitButtonText: "Upload",
|
submitButtonText: "Upload",
|
||||||
onClose: () => this.close(),
|
onClose: () => this.close(),
|
||||||
|
|||||||
@@ -147,6 +147,30 @@ export default class NotebookTabV2 extends TabsBase {
|
|||||||
const cellCodeType = "code";
|
const cellCodeType = "code";
|
||||||
const cellMarkdownType = "markdown";
|
const cellMarkdownType = "markdown";
|
||||||
const cellRawType = "raw";
|
const cellRawType = "raw";
|
||||||
|
|
||||||
|
const saveButtonChildren = [];
|
||||||
|
if (this.container.notebookManager?.gitHubOAuthService.isLoggedIn()) {
|
||||||
|
saveButtonChildren.push({
|
||||||
|
iconName: "Copy",
|
||||||
|
onCommandClick: () => this.copyNotebook(),
|
||||||
|
commandButtonLabel: copyToLabel,
|
||||||
|
hasPopup: false,
|
||||||
|
disabled: false,
|
||||||
|
ariaLabel: copyToLabel
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.container.isGalleryPublishEnabled()) {
|
||||||
|
saveButtonChildren.push({
|
||||||
|
iconName: "PublishContent",
|
||||||
|
onCommandClick: async () => await this.publishToGallery(),
|
||||||
|
commandButtonLabel: publishLabel,
|
||||||
|
hasPopup: false,
|
||||||
|
disabled: false,
|
||||||
|
ariaLabel: publishLabel
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
let buttons: CommandButtonComponentProps[] = [
|
let buttons: CommandButtonComponentProps[] = [
|
||||||
{
|
{
|
||||||
iconSrc: SaveIcon,
|
iconSrc: SaveIcon,
|
||||||
@@ -156,8 +180,7 @@ export default class NotebookTabV2 extends TabsBase {
|
|||||||
hasPopup: false,
|
hasPopup: false,
|
||||||
disabled: false,
|
disabled: false,
|
||||||
ariaLabel: saveLabel,
|
ariaLabel: saveLabel,
|
||||||
children: this.container.isGalleryPublishEnabled()
|
children: saveButtonChildren.length && [
|
||||||
? [
|
|
||||||
{
|
{
|
||||||
iconName: "Save",
|
iconName: "Save",
|
||||||
onCommandClick: () => this.notebookComponentAdapter.notebookSave(),
|
onCommandClick: () => this.notebookComponentAdapter.notebookSave(),
|
||||||
@@ -166,24 +189,8 @@ export default class NotebookTabV2 extends TabsBase {
|
|||||||
disabled: false,
|
disabled: false,
|
||||||
ariaLabel: saveLabel
|
ariaLabel: saveLabel
|
||||||
},
|
},
|
||||||
{
|
...saveButtonChildren
|
||||||
iconName: "Copy",
|
|
||||||
onCommandClick: () => this.copyNotebook(),
|
|
||||||
commandButtonLabel: copyToLabel,
|
|
||||||
hasPopup: false,
|
|
||||||
disabled: false,
|
|
||||||
ariaLabel: copyToLabel
|
|
||||||
},
|
|
||||||
{
|
|
||||||
iconName: "PublishContent",
|
|
||||||
onCommandClick: async () => await this.publishToGallery(),
|
|
||||||
commandButtonLabel: publishLabel,
|
|
||||||
hasPopup: false,
|
|
||||||
disabled: false,
|
|
||||||
ariaLabel: publishLabel
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
: undefined
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
iconSrc: null,
|
iconSrc: null,
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import Database from "../Tree/Database";
|
|||||||
import Explorer from "../Explorer";
|
import Explorer from "../Explorer";
|
||||||
import SettingsTab from "../Tabs/SettingsTab";
|
import SettingsTab from "../Tabs/SettingsTab";
|
||||||
import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent";
|
import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent";
|
||||||
|
import { IndexingPolicies } from "../../Shared/Constants";
|
||||||
|
|
||||||
describe("Settings tab", () => {
|
describe("Settings tab", () => {
|
||||||
const baseCollection: DataModels.Collection = {
|
const baseCollection: DataModels.Collection = {
|
||||||
@@ -16,7 +17,7 @@ describe("Settings tab", () => {
|
|||||||
mode: DataModels.ConflictResolutionMode.LastWriterWins,
|
mode: DataModels.ConflictResolutionMode.LastWriterWins,
|
||||||
conflictResolutionPath: "/_ts"
|
conflictResolutionPath: "/_ts"
|
||||||
},
|
},
|
||||||
indexingPolicy: {},
|
indexingPolicy: IndexingPolicies.SharedDatabaseDefault,
|
||||||
_rid: "",
|
_rid: "",
|
||||||
_self: "",
|
_self: "",
|
||||||
_etag: "",
|
_etag: "",
|
||||||
@@ -51,7 +52,7 @@ describe("Settings tab", () => {
|
|||||||
defaultTtl: 200,
|
defaultTtl: 200,
|
||||||
partitionKey: null,
|
partitionKey: null,
|
||||||
conflictResolutionPolicy: null,
|
conflictResolutionPolicy: null,
|
||||||
indexingPolicy: {},
|
indexingPolicy: IndexingPolicies.SharedDatabaseDefault,
|
||||||
_rid: "",
|
_rid: "",
|
||||||
_self: "",
|
_self: "",
|
||||||
_etag: "",
|
_etag: "",
|
||||||
@@ -345,7 +346,6 @@ describe("Settings tab", () => {
|
|||||||
|
|
||||||
const offer: DataModels.Offer = null;
|
const offer: DataModels.Offer = null;
|
||||||
const defaultTtl = 200;
|
const defaultTtl = 200;
|
||||||
const indexingPolicy = {};
|
|
||||||
const database = new Database(explorer, baseDatabase, null);
|
const database = new Database(explorer, baseDatabase, null);
|
||||||
const conflictResolutionPolicy = {
|
const conflictResolutionPolicy = {
|
||||||
mode: DataModels.ConflictResolutionMode.LastWriterWins,
|
mode: DataModels.ConflictResolutionMode.LastWriterWins,
|
||||||
@@ -367,7 +367,7 @@ describe("Settings tab", () => {
|
|||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
conflictResolutionPolicy: conflictResolutionPolicy,
|
conflictResolutionPolicy: conflictResolutionPolicy,
|
||||||
indexingPolicy: indexingPolicy,
|
indexingPolicy: IndexingPolicies.SharedDatabaseDefault,
|
||||||
_rid: "",
|
_rid: "",
|
||||||
_self: "",
|
_self: "",
|
||||||
_etag: "",
|
_etag: "",
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ import { Action } from "../../Shared/Telemetry/TelemetryConstants";
|
|||||||
import { PlatformType } from "../../PlatformType";
|
import { PlatformType } from "../../PlatformType";
|
||||||
import { RequestOptions } from "@azure/cosmos/dist-esm";
|
import { RequestOptions } from "@azure/cosmos/dist-esm";
|
||||||
import Explorer from "../Explorer";
|
import Explorer from "../Explorer";
|
||||||
import { updateOffer, updateCollection } from "../../Common/DocumentClientUtilityBase";
|
import { updateOffer } from "../../Common/DocumentClientUtilityBase";
|
||||||
|
import { updateCollection } from "../../Common/dataAccess/updateCollection";
|
||||||
import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent";
|
import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent";
|
||||||
import { userContext } from "../../UserContext";
|
import { userContext } from "../../UserContext";
|
||||||
import { updateOfferThroughputBeyondLimit } from "../../Common/dataAccess/updateOfferThroughputBeyondLimit";
|
import { updateOfferThroughputBeyondLimit } from "../../Common/dataAccess/updateOfferThroughputBeyondLimit";
|
||||||
@@ -1009,8 +1010,7 @@ export default class SettingsTab extends TabsBase implements ViewModels.WaitsFor
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public onSaveClick = (): Q.Promise<any> => {
|
public onSaveClick = async (): Promise<any> => {
|
||||||
let promises: Q.Promise<void>[] = [];
|
|
||||||
this.isExecutionError(false);
|
this.isExecutionError(false);
|
||||||
|
|
||||||
this.isExecuting(true);
|
this.isExecuting(true);
|
||||||
@@ -1023,6 +1023,7 @@ export default class SettingsTab extends TabsBase implements ViewModels.WaitsFor
|
|||||||
|
|
||||||
const newCollectionAttributes: any = {};
|
const newCollectionAttributes: any = {};
|
||||||
|
|
||||||
|
try {
|
||||||
if (this.shouldUpdateCollection()) {
|
if (this.shouldUpdateCollection()) {
|
||||||
let defaultTtl: number;
|
let defaultTtl: number;
|
||||||
switch (this.timeToLive()) {
|
switch (this.timeToLive()) {
|
||||||
@@ -1064,9 +1065,18 @@ export default class SettingsTab extends TabsBase implements ViewModels.WaitsFor
|
|||||||
newCollectionAttributes.conflictResolutionPolicy = conflictResolutionChanges;
|
newCollectionAttributes.conflictResolutionPolicy = conflictResolutionChanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
const newCollection: DataModels.Collection = _.extend({}, this.collection.rawDataModel, newCollectionAttributes);
|
const newCollection: DataModels.Collection = _.extend(
|
||||||
const updateCollectionPromise = updateCollection(this.collection.databaseId, this.collection, newCollection).then(
|
{},
|
||||||
(updatedCollection: DataModels.Collection) => {
|
this.collection.rawDataModel,
|
||||||
|
newCollectionAttributes
|
||||||
|
);
|
||||||
|
const updatedCollection: DataModels.Collection = await updateCollection(
|
||||||
|
this.collection.databaseId,
|
||||||
|
this.collection.id(),
|
||||||
|
newCollection
|
||||||
|
);
|
||||||
|
|
||||||
|
if (updatedCollection) {
|
||||||
this.collection.rawDataModel = updatedCollection;
|
this.collection.rawDataModel = updatedCollection;
|
||||||
this.collection.defaultTtl(updatedCollection.defaultTtl);
|
this.collection.defaultTtl(updatedCollection.defaultTtl);
|
||||||
this.collection.analyticalStorageTtl(updatedCollection.analyticalStorageTtl);
|
this.collection.analyticalStorageTtl(updatedCollection.analyticalStorageTtl);
|
||||||
@@ -1076,9 +1086,6 @@ export default class SettingsTab extends TabsBase implements ViewModels.WaitsFor
|
|||||||
this.collection.changeFeedPolicy(updatedCollection.changeFeedPolicy);
|
this.collection.changeFeedPolicy(updatedCollection.changeFeedPolicy);
|
||||||
this.collection.geospatialConfig(updatedCollection.geospatialConfig);
|
this.collection.geospatialConfig(updatedCollection.geospatialConfig);
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
|
||||||
promises.push(updateCollectionPromise);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -1150,8 +1157,8 @@ export default class SettingsTab extends TabsBase implements ViewModels.WaitsFor
|
|||||||
throughput: newThroughput,
|
throughput: newThroughput,
|
||||||
offerIsRUPerMinuteThroughputEnabled: isRUPerMinuteThroughputEnabled
|
offerIsRUPerMinuteThroughputEnabled: isRUPerMinuteThroughputEnabled
|
||||||
};
|
};
|
||||||
const updateOfferBeyondLimitPromise = updateOfferThroughputBeyondLimit(requestPayload).then(
|
|
||||||
() => {
|
await updateOfferThroughputBeyondLimit(requestPayload);
|
||||||
this.collection.offer().content.offerThroughput = originalThroughputValue;
|
this.collection.offer().content.offerThroughput = originalThroughputValue;
|
||||||
this.throughput(originalThroughputValue);
|
this.throughput(originalThroughputValue);
|
||||||
this.notificationStatusInfo(
|
this.notificationStatusInfo(
|
||||||
@@ -1165,43 +1172,13 @@ export default class SettingsTab extends TabsBase implements ViewModels.WaitsFor
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
this.throughput.valueHasMutated(); // force component re-render
|
this.throughput.valueHasMutated(); // force component re-render
|
||||||
},
|
|
||||||
(error: any) => {
|
|
||||||
TelemetryProcessor.traceFailure(
|
|
||||||
Action.UpdateSettings,
|
|
||||||
{
|
|
||||||
databaseAccountName: this.container.databaseAccount().name,
|
|
||||||
databaseName: this.collection && this.collection.databaseId,
|
|
||||||
collectionName: this.collection && this.collection.id(),
|
|
||||||
defaultExperience: this.container.defaultExperience(),
|
|
||||||
dataExplorerArea: Constants.Areas.Tab,
|
|
||||||
tabTitle: this.tabTitle(),
|
|
||||||
error: error
|
|
||||||
},
|
|
||||||
startKey
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
promises.push(Q(updateOfferBeyondLimitPromise));
|
|
||||||
} else {
|
} else {
|
||||||
const updateOfferPromise = updateOffer(this.collection.offer(), newOffer, headerOptions).then(
|
const updatedOffer: DataModels.Offer = await updateOffer(this.collection.offer(), newOffer, headerOptions);
|
||||||
(updatedOffer: DataModels.Offer) => {
|
|
||||||
this.collection.offer(updatedOffer);
|
this.collection.offer(updatedOffer);
|
||||||
this.collection.offer.valueHasMutated();
|
this.collection.offer.valueHasMutated();
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
|
||||||
promises.push(updateOfferPromise);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (promises.length === 0) {
|
|
||||||
this.isExecuting(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Q.all(promises)
|
|
||||||
.then(
|
|
||||||
() => {
|
|
||||||
this.container.isRefreshingExplorer(false);
|
this.container.isRefreshingExplorer(false);
|
||||||
this._setBaseline();
|
this._setBaseline();
|
||||||
this.collection.readSettings();
|
this.collection.readSettings();
|
||||||
@@ -1216,24 +1193,26 @@ export default class SettingsTab extends TabsBase implements ViewModels.WaitsFor
|
|||||||
},
|
},
|
||||||
startKey
|
startKey
|
||||||
);
|
);
|
||||||
},
|
} catch (error) {
|
||||||
(reason: any) => {
|
|
||||||
this.container.isRefreshingExplorer(false);
|
this.container.isRefreshingExplorer(false);
|
||||||
this.isExecutionError(true);
|
this.isExecutionError(true);
|
||||||
console.error(reason);
|
console.error(error);
|
||||||
TelemetryProcessor.traceFailure(
|
TelemetryProcessor.traceFailure(
|
||||||
Action.UpdateSettings,
|
Action.UpdateSettings,
|
||||||
{
|
{
|
||||||
databaseAccountName: this.container.databaseAccount().name,
|
databaseAccountName: this.container.databaseAccount().name,
|
||||||
|
databaseName: this.collection && this.collection.databaseId,
|
||||||
|
collectionName: this.collection && this.collection.id(),
|
||||||
defaultExperience: this.container.defaultExperience(),
|
defaultExperience: this.container.defaultExperience(),
|
||||||
dataExplorerArea: Constants.Areas.Tab,
|
dataExplorerArea: Constants.Areas.Tab,
|
||||||
tabTitle: this.tabTitle()
|
tabTitle: this.tabTitle(),
|
||||||
|
error: error
|
||||||
},
|
},
|
||||||
startKey
|
startKey
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
)
|
|
||||||
.finally(() => this.isExecuting(false));
|
this.isExecuting(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
public onRevertClick = (): Q.Promise<any> => {
|
public onRevertClick = (): Q.Promise<any> => {
|
||||||
|
|||||||
@@ -648,7 +648,9 @@ export default class Collection implements ViewModels.Collection {
|
|||||||
});
|
});
|
||||||
// TODO: Use the collection entity cache to get quota info
|
// TODO: Use the collection entity cache to get quota info
|
||||||
const quotaInfoPromise: Q.Promise<DataModels.CollectionQuotaInfo> = readCollectionQuotaInfo(this);
|
const quotaInfoPromise: Q.Promise<DataModels.CollectionQuotaInfo> = readCollectionQuotaInfo(this);
|
||||||
const offerInfoPromise: Q.Promise<DataModels.Offer[]> = readOffers();
|
const offerInfoPromise: Q.Promise<DataModels.Offer[]> = readOffers({
|
||||||
|
isServerless: this.container.isServerlessEnabled()
|
||||||
|
});
|
||||||
Q.all([quotaInfoPromise, offerInfoPromise]).then(
|
Q.all([quotaInfoPromise, offerInfoPromise]).then(
|
||||||
() => {
|
() => {
|
||||||
this.container.isRefreshingExplorer(false);
|
this.container.isRefreshingExplorer(false);
|
||||||
@@ -657,9 +659,7 @@ export default class Collection implements ViewModels.Collection {
|
|||||||
const quotaInfo = _.omit(quotaInfoWithUniqueKeyPolicy, "uniqueKeyPolicy");
|
const quotaInfo = _.omit(quotaInfoWithUniqueKeyPolicy, "uniqueKeyPolicy");
|
||||||
|
|
||||||
const collectionOffer = this._getOfferForCollection(offerInfoPromise.valueOf(), collectionDataModel);
|
const collectionOffer = this._getOfferForCollection(offerInfoPromise.valueOf(), collectionDataModel);
|
||||||
const isDatabaseShared = this.getDatabase() && this.getDatabase().isDatabaseShared();
|
if (!collectionOffer) {
|
||||||
const isServerless = this.container.isServerlessEnabled();
|
|
||||||
if ((isDatabaseShared || isServerless) && !collectionOffer) {
|
|
||||||
this.quotaInfo(quotaInfo);
|
this.quotaInfo(quotaInfo);
|
||||||
TelemetryProcessor.traceSuccess(
|
TelemetryProcessor.traceSuccess(
|
||||||
Action.LoadOffers,
|
Action.LoadOffers,
|
||||||
|
|||||||
@@ -123,10 +123,6 @@ export default class Database implements ViewModels.Database {
|
|||||||
|
|
||||||
public readSettings(): Q.Promise<void> {
|
public readSettings(): Q.Promise<void> {
|
||||||
const deferred: Q.Deferred<void> = Q.defer<void>();
|
const deferred: Q.Deferred<void> = Q.defer<void>();
|
||||||
if (this.container.isServerlessEnabled()) {
|
|
||||||
deferred.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.container.isRefreshingExplorer(true);
|
this.container.isRefreshingExplorer(true);
|
||||||
const databaseDataModel: DataModels.Database = <DataModels.Database>{
|
const databaseDataModel: DataModels.Database = <DataModels.Database>{
|
||||||
id: this.id(),
|
id: this.id(),
|
||||||
@@ -138,7 +134,9 @@ export default class Database implements ViewModels.Database {
|
|||||||
defaultExperience: this.container.defaultExperience()
|
defaultExperience: this.container.defaultExperience()
|
||||||
});
|
});
|
||||||
|
|
||||||
const offerInfoPromise: Q.Promise<DataModels.Offer[]> = readOffers();
|
const offerInfoPromise: Q.Promise<DataModels.Offer[]> = readOffers({
|
||||||
|
isServerless: this.container.isServerlessEnabled()
|
||||||
|
});
|
||||||
Q.all([offerInfoPromise]).then(
|
Q.all([offerInfoPromise]).then(
|
||||||
() => {
|
() => {
|
||||||
this.container.isRefreshingExplorer(false);
|
this.container.isRefreshingExplorer(false);
|
||||||
@@ -147,6 +145,11 @@ export default class Database implements ViewModels.Database {
|
|||||||
offerInfoPromise.valueOf(),
|
offerInfoPromise.valueOf(),
|
||||||
databaseDataModel
|
databaseDataModel
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!databaseOffer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
readOffer(databaseOffer).then((offerDetail: DataModels.OfferWithHeaders) => {
|
readOffer(databaseOffer).then((offerDetail: DataModels.OfferWithHeaders) => {
|
||||||
const offerThroughputInfo: DataModels.OfferThroughputInfo = {
|
const offerThroughputInfo: DataModels.OfferThroughputInfo = {
|
||||||
minimumRUForCollection:
|
minimumRUForCollection:
|
||||||
|
|||||||
@@ -546,8 +546,13 @@ export class ResourceTreeAdapter implements ReactAdapter {
|
|||||||
(activeTab as any).notebookPath() === item.path
|
(activeTab as any).notebookPath() === item.path
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
contextMenu: createFileContextMenu
|
contextMenu: createFileContextMenu && this.createFileContextMenu(item),
|
||||||
? [
|
data: item
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private createFileContextMenu(item: NotebookContentItem): TreeNodeMenuItem[] {
|
||||||
|
let items: TreeNodeMenuItem[] = [
|
||||||
{
|
{
|
||||||
label: "Rename",
|
label: "Rename",
|
||||||
iconSrc: NotebookIcon,
|
iconSrc: NotebookIcon,
|
||||||
@@ -577,10 +582,14 @@ export class ResourceTreeAdapter implements ReactAdapter {
|
|||||||
iconSrc: NotebookIcon,
|
iconSrc: NotebookIcon,
|
||||||
onClick: () => this.container.downloadFile(item)
|
onClick: () => this.container.downloadFile(item)
|
||||||
}
|
}
|
||||||
]
|
];
|
||||||
: undefined,
|
|
||||||
data: item
|
// "Copy to ..." isn't needed if github locations are not available
|
||||||
};
|
if (!this.container.notebookManager?.gitHubOAuthService.isLoggedIn()) {
|
||||||
|
items = items.filter(item => item.label !== "Copy to ...");
|
||||||
|
}
|
||||||
|
|
||||||
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
private copyNotebook = async (item: NotebookContentItem) => {
|
private copyNotebook = async (item: NotebookContentItem) => {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { MessageTypes } from "../Contracts/ExplorerContracts";
|
|||||||
import * as NotificationConsoleUtils from "../Utils/NotificationConsoleUtils";
|
import * as NotificationConsoleUtils from "../Utils/NotificationConsoleUtils";
|
||||||
import { ResourceProviderClient } from "../ResourceProvider/ResourceProviderClient";
|
import { ResourceProviderClient } from "../ResourceProvider/ResourceProviderClient";
|
||||||
import { userContext } from "../UserContext";
|
import { userContext } from "../UserContext";
|
||||||
|
import { createUpdateCassandraKeyspace } from "../Utils/arm/generatedClients/2020-04-01/cassandraResources";
|
||||||
|
|
||||||
export class AddDbUtilities {
|
export class AddDbUtilities {
|
||||||
// todo - remove any
|
// todo - remove any
|
||||||
@@ -47,7 +48,6 @@ export class AddDbUtilities {
|
|||||||
|
|
||||||
// todo - remove any
|
// todo - remove any
|
||||||
public static async createCassandraKeyspace(
|
public static async createCassandraKeyspace(
|
||||||
armEndpoint: string,
|
|
||||||
params: DataModels.RpParameters,
|
params: DataModels.RpParameters,
|
||||||
rpOptions: DataModels.RpOptions
|
rpOptions: DataModels.RpOptions
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
@@ -70,9 +70,11 @@ export class AddDbUtilities {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await AddDbUtilities.getRpClient<DataModels.CreateDatabaseWithRpResponse>(armEndpoint).putAsync(
|
await createUpdateCassandraKeyspace(
|
||||||
AddDbUtilities._getCassandraKeyspaceUri(params),
|
userContext.subscriptionId,
|
||||||
DataExplorerConstants.ArmApiVersions.publicVersion,
|
userContext.resourceGroup,
|
||||||
|
userContext.databaseAccount?.name,
|
||||||
|
params.db,
|
||||||
rpPayloadToCreateKeyspace
|
rpPayloadToCreateKeyspace
|
||||||
);
|
);
|
||||||
} catch (reason) {
|
} catch (reason) {
|
||||||
@@ -159,10 +161,7 @@ export class AddDbUtilities {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static _handleCreationError(reason: any, params: DataModels.RpParameters, dbType: string = "database") {
|
private static _handleCreationError(reason: any, params: DataModels.RpParameters, dbType: string = "database") {
|
||||||
NotificationConsoleUtils.logConsoleMessage(
|
NotificationConsoleUtils.logConsoleError(`Error creating ${dbType}: ${JSON.stringify(reason)}, Payload: ${params}`);
|
||||||
ConsoleDataType.Error,
|
|
||||||
`Error creating ${dbType}: ${JSON.stringify(reason)}, Payload: ${params}`
|
|
||||||
);
|
|
||||||
if (reason.status === HttpStatusCodes.Forbidden) {
|
if (reason.status === HttpStatusCodes.Forbidden) {
|
||||||
sendMessage({ type: MessageTypes.ForbiddenError });
|
sendMessage({ type: MessageTypes.ForbiddenError });
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -114,13 +114,17 @@ export default class TelemetryProcessor {
|
|||||||
return validTimestamp;
|
return validTimestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static getData(data?: any): any {
|
private static getData(data: any = {}): any {
|
||||||
|
if (typeof data === "string") {
|
||||||
|
data = { message: data };
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
// TODO: Need to `any` here since the window imports Explorer which can't be in strict mode yet
|
// TODO: Need to `any` here since the window imports Explorer which can't be in strict mode yet
|
||||||
authType: (window as any).authType,
|
authType: (window as any).authType,
|
||||||
subscriptionId: userContext.subscriptionId,
|
subscriptionId: userContext.subscriptionId,
|
||||||
platform: configContext.platform,
|
platform: configContext.platform,
|
||||||
...(data ? data : [])
|
env: process.env.NODE_ENV,
|
||||||
|
...data
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ interface UserContext {
|
|||||||
authorizationToken?: string;
|
authorizationToken?: string;
|
||||||
resourceToken?: string;
|
resourceToken?: string;
|
||||||
defaultExperience?: DefaultAccountExperienceType;
|
defaultExperience?: DefaultAccountExperienceType;
|
||||||
|
useSDKOperations?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const userContext: Readonly<UserContext> = {} as const;
|
const userContext: Readonly<UserContext> = {} as const;
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export async function createUpdateCassandraKeyspace(
|
|||||||
body: Types.CassandraKeyspaceCreateUpdateParameters
|
body: Types.CassandraKeyspaceCreateUpdateParameters
|
||||||
): Promise<Types.CassandraKeyspaceGetResults | void> {
|
): Promise<Types.CassandraKeyspaceGetResults | void> {
|
||||||
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/cassandraKeyspaces/${keyspaceName}`;
|
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/cassandraKeyspaces/${keyspaceName}`;
|
||||||
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body: JSON.stringify(body) });
|
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Deletes an existing Azure Cosmos DB Cassandra keyspace. */
|
/* Deletes an existing Azure Cosmos DB Cassandra keyspace. */
|
||||||
@@ -73,7 +73,7 @@ export async function updateCassandraKeyspaceThroughput(
|
|||||||
body: Types.ThroughputSettingsUpdateParameters
|
body: Types.ThroughputSettingsUpdateParameters
|
||||||
): Promise<Types.ThroughputSettingsGetResults | void> {
|
): Promise<Types.ThroughputSettingsGetResults | void> {
|
||||||
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/cassandraKeyspaces/${keyspaceName}/throughputSettings/default`;
|
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/cassandraKeyspaces/${keyspaceName}/throughputSettings/default`;
|
||||||
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body: JSON.stringify(body) });
|
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Migrate an Azure Cosmos DB Cassandra Keyspace from manual throughput to autoscale */
|
/* Migrate an Azure Cosmos DB Cassandra Keyspace from manual throughput to autoscale */
|
||||||
@@ -131,7 +131,7 @@ export async function createUpdateCassandraTable(
|
|||||||
body: Types.CassandraTableCreateUpdateParameters
|
body: Types.CassandraTableCreateUpdateParameters
|
||||||
): Promise<Types.CassandraTableGetResults | void> {
|
): Promise<Types.CassandraTableGetResults | void> {
|
||||||
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/cassandraKeyspaces/${keyspaceName}/tables/${tableName}`;
|
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/cassandraKeyspaces/${keyspaceName}/tables/${tableName}`;
|
||||||
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body: JSON.stringify(body) });
|
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Deletes an existing Azure Cosmos DB Cassandra table. */
|
/* Deletes an existing Azure Cosmos DB Cassandra table. */
|
||||||
@@ -168,7 +168,7 @@ export async function updateCassandraTableThroughput(
|
|||||||
body: Types.ThroughputSettingsUpdateParameters
|
body: Types.ThroughputSettingsUpdateParameters
|
||||||
): Promise<Types.ThroughputSettingsGetResults | void> {
|
): Promise<Types.ThroughputSettingsGetResults | void> {
|
||||||
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/cassandraKeyspaces/${keyspaceName}/tables/${tableName}/throughputSettings/default`;
|
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/cassandraKeyspaces/${keyspaceName}/tables/${tableName}/throughputSettings/default`;
|
||||||
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body: JSON.stringify(body) });
|
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Migrate an Azure Cosmos DB Cassandra table from manual throughput to autoscale */
|
/* Migrate an Azure Cosmos DB Cassandra table from manual throughput to autoscale */
|
||||||
|
|||||||
@@ -27,13 +27,7 @@ export async function update(
|
|||||||
body: Types.DatabaseAccountUpdateParameters
|
body: Types.DatabaseAccountUpdateParameters
|
||||||
): Promise<Types.DatabaseAccountGetResults> {
|
): Promise<Types.DatabaseAccountGetResults> {
|
||||||
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}`;
|
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}`;
|
||||||
return armRequest({
|
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PATCH", apiVersion, body });
|
||||||
host: configContext.ARM_ENDPOINT,
|
|
||||||
path,
|
|
||||||
method: "PATCH",
|
|
||||||
apiVersion,
|
|
||||||
body: JSON.stringify(body)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Creates or updates an Azure Cosmos DB database account. The "Update" method is preferred when performing updates on an account. */
|
/* Creates or updates an Azure Cosmos DB database account. The "Update" method is preferred when performing updates on an account. */
|
||||||
@@ -44,7 +38,7 @@ export async function createOrUpdate(
|
|||||||
body: Types.DatabaseAccountCreateUpdateParameters
|
body: Types.DatabaseAccountCreateUpdateParameters
|
||||||
): Promise<Types.DatabaseAccountGetResults> {
|
): Promise<Types.DatabaseAccountGetResults> {
|
||||||
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}`;
|
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}`;
|
||||||
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body: JSON.stringify(body) });
|
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Deletes an existing Azure Cosmos DB database account. */
|
/* Deletes an existing Azure Cosmos DB database account. */
|
||||||
@@ -61,7 +55,7 @@ export async function failoverPriorityChange(
|
|||||||
body: Types.FailoverPolicies
|
body: Types.FailoverPolicies
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/failoverPriorityChange`;
|
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/failoverPriorityChange`;
|
||||||
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "POST", apiVersion, body: JSON.stringify(body) });
|
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "POST", apiVersion, body });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lists all the Azure Cosmos DB database accounts available under the subscription. */
|
/* Lists all the Azure Cosmos DB database accounts available under the subscription. */
|
||||||
@@ -107,7 +101,7 @@ export async function offlineRegion(
|
|||||||
body: Types.RegionForOnlineOffline
|
body: Types.RegionForOnlineOffline
|
||||||
): Promise<void | Types.ErrorResponse> {
|
): Promise<void | Types.ErrorResponse> {
|
||||||
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/offlineRegion`;
|
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/offlineRegion`;
|
||||||
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "POST", apiVersion, body: JSON.stringify(body) });
|
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "POST", apiVersion, body });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Online the specified region for the specified Azure Cosmos DB database account. */
|
/* Online the specified region for the specified Azure Cosmos DB database account. */
|
||||||
@@ -118,7 +112,7 @@ export async function onlineRegion(
|
|||||||
body: Types.RegionForOnlineOffline
|
body: Types.RegionForOnlineOffline
|
||||||
): Promise<void | Types.ErrorResponse> {
|
): Promise<void | Types.ErrorResponse> {
|
||||||
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/onlineRegion`;
|
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/onlineRegion`;
|
||||||
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "POST", apiVersion, body: JSON.stringify(body) });
|
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "POST", apiVersion, body });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lists the read-only access keys for the specified Azure Cosmos DB database account. */
|
/* Lists the read-only access keys for the specified Azure Cosmos DB database account. */
|
||||||
@@ -149,7 +143,7 @@ export async function regenerateKey(
|
|||||||
body: Types.DatabaseAccountRegenerateKeyParameters
|
body: Types.DatabaseAccountRegenerateKeyParameters
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/regenerateKey`;
|
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/regenerateKey`;
|
||||||
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "POST", apiVersion, body: JSON.stringify(body) });
|
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "POST", apiVersion, body });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Checks that the Azure Cosmos DB account name already exists. A valid account name may contain only lowercase letters, numbers, and the '-' character, and must be between 3 and 50 characters. */
|
/* Checks that the Azure Cosmos DB account name already exists. A valid account name may contain only lowercase letters, numbers, and the '-' character, and must be between 3 and 50 characters. */
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export async function createUpdateGremlinDatabase(
|
|||||||
body: Types.GremlinDatabaseCreateUpdateParameters
|
body: Types.GremlinDatabaseCreateUpdateParameters
|
||||||
): Promise<Types.GremlinDatabaseGetResults | void> {
|
): Promise<Types.GremlinDatabaseGetResults | void> {
|
||||||
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/gremlinDatabases/${databaseName}`;
|
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/gremlinDatabases/${databaseName}`;
|
||||||
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body: JSON.stringify(body) });
|
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Deletes an existing Azure Cosmos DB Gremlin database. */
|
/* Deletes an existing Azure Cosmos DB Gremlin database. */
|
||||||
@@ -73,7 +73,7 @@ export async function updateGremlinDatabaseThroughput(
|
|||||||
body: Types.ThroughputSettingsUpdateParameters
|
body: Types.ThroughputSettingsUpdateParameters
|
||||||
): Promise<Types.ThroughputSettingsGetResults | void> {
|
): Promise<Types.ThroughputSettingsGetResults | void> {
|
||||||
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/gremlinDatabases/${databaseName}/throughputSettings/default`;
|
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/gremlinDatabases/${databaseName}/throughputSettings/default`;
|
||||||
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body: JSON.stringify(body) });
|
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Migrate an Azure Cosmos DB Gremlin database from manual throughput to autoscale */
|
/* Migrate an Azure Cosmos DB Gremlin database from manual throughput to autoscale */
|
||||||
@@ -131,7 +131,7 @@ export async function createUpdateGremlinGraph(
|
|||||||
body: Types.GremlinGraphCreateUpdateParameters
|
body: Types.GremlinGraphCreateUpdateParameters
|
||||||
): Promise<Types.GremlinGraphGetResults | void> {
|
): Promise<Types.GremlinGraphGetResults | void> {
|
||||||
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/gremlinDatabases/${databaseName}/graphs/${graphName}`;
|
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/gremlinDatabases/${databaseName}/graphs/${graphName}`;
|
||||||
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body: JSON.stringify(body) });
|
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Deletes an existing Azure Cosmos DB Gremlin graph. */
|
/* Deletes an existing Azure Cosmos DB Gremlin graph. */
|
||||||
@@ -168,7 +168,7 @@ export async function updateGremlinGraphThroughput(
|
|||||||
body: Types.ThroughputSettingsUpdateParameters
|
body: Types.ThroughputSettingsUpdateParameters
|
||||||
): Promise<Types.ThroughputSettingsGetResults | void> {
|
): Promise<Types.ThroughputSettingsGetResults | void> {
|
||||||
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/gremlinDatabases/${databaseName}/graphs/${graphName}/throughputSettings/default`;
|
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/gremlinDatabases/${databaseName}/graphs/${graphName}/throughputSettings/default`;
|
||||||
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body: JSON.stringify(body) });
|
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Migrate an Azure Cosmos DB Gremlin graph from manual throughput to autoscale */
|
/* Migrate an Azure Cosmos DB Gremlin graph from manual throughput to autoscale */
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export async function createUpdateMongoDBDatabase(
|
|||||||
body: Types.MongoDBDatabaseCreateUpdateParameters
|
body: Types.MongoDBDatabaseCreateUpdateParameters
|
||||||
): Promise<Types.MongoDBDatabaseGetResults | void> {
|
): Promise<Types.MongoDBDatabaseGetResults | void> {
|
||||||
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/mongodbDatabases/${databaseName}`;
|
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/mongodbDatabases/${databaseName}`;
|
||||||
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body: JSON.stringify(body) });
|
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Deletes an existing Azure Cosmos DB MongoDB database. */
|
/* Deletes an existing Azure Cosmos DB MongoDB database. */
|
||||||
@@ -73,7 +73,7 @@ export async function updateMongoDBDatabaseThroughput(
|
|||||||
body: Types.ThroughputSettingsUpdateParameters
|
body: Types.ThroughputSettingsUpdateParameters
|
||||||
): Promise<Types.ThroughputSettingsGetResults | void> {
|
): Promise<Types.ThroughputSettingsGetResults | void> {
|
||||||
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/mongodbDatabases/${databaseName}/throughputSettings/default`;
|
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/mongodbDatabases/${databaseName}/throughputSettings/default`;
|
||||||
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body: JSON.stringify(body) });
|
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Migrate an Azure Cosmos DB MongoDB database from manual throughput to autoscale */
|
/* Migrate an Azure Cosmos DB MongoDB database from manual throughput to autoscale */
|
||||||
@@ -131,7 +131,7 @@ export async function createUpdateMongoDBCollection(
|
|||||||
body: Types.MongoDBCollectionCreateUpdateParameters
|
body: Types.MongoDBCollectionCreateUpdateParameters
|
||||||
): Promise<Types.MongoDBCollectionGetResults | void> {
|
): Promise<Types.MongoDBCollectionGetResults | void> {
|
||||||
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/mongodbDatabases/${databaseName}/collections/${collectionName}`;
|
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/mongodbDatabases/${databaseName}/collections/${collectionName}`;
|
||||||
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body: JSON.stringify(body) });
|
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Deletes an existing Azure Cosmos DB MongoDB Collection. */
|
/* Deletes an existing Azure Cosmos DB MongoDB Collection. */
|
||||||
@@ -168,7 +168,7 @@ export async function updateMongoDBCollectionThroughput(
|
|||||||
body: Types.ThroughputSettingsUpdateParameters
|
body: Types.ThroughputSettingsUpdateParameters
|
||||||
): Promise<Types.ThroughputSettingsGetResults | void> {
|
): Promise<Types.ThroughputSettingsGetResults | void> {
|
||||||
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/mongodbDatabases/${databaseName}/collections/${collectionName}/throughputSettings/default`;
|
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/mongodbDatabases/${databaseName}/collections/${collectionName}/throughputSettings/default`;
|
||||||
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body: JSON.stringify(body) });
|
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Migrate an Azure Cosmos DB MongoDB collection from manual throughput to autoscale */
|
/* Migrate an Azure Cosmos DB MongoDB collection from manual throughput to autoscale */
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export async function createUpdateSqlDatabase(
|
|||||||
body: Types.SqlDatabaseCreateUpdateParameters
|
body: Types.SqlDatabaseCreateUpdateParameters
|
||||||
): Promise<Types.SqlDatabaseGetResults | void> {
|
): Promise<Types.SqlDatabaseGetResults | void> {
|
||||||
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/sqlDatabases/${databaseName}`;
|
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/sqlDatabases/${databaseName}`;
|
||||||
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body: JSON.stringify(body) });
|
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Deletes an existing Azure Cosmos DB SQL database. */
|
/* Deletes an existing Azure Cosmos DB SQL database. */
|
||||||
@@ -73,7 +73,7 @@ export async function updateSqlDatabaseThroughput(
|
|||||||
body: Types.ThroughputSettingsUpdateParameters
|
body: Types.ThroughputSettingsUpdateParameters
|
||||||
): Promise<Types.ThroughputSettingsGetResults | void> {
|
): Promise<Types.ThroughputSettingsGetResults | void> {
|
||||||
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/sqlDatabases/${databaseName}/throughputSettings/default`;
|
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/sqlDatabases/${databaseName}/throughputSettings/default`;
|
||||||
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body: JSON.stringify(body) });
|
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Migrate an Azure Cosmos DB SQL database from manual throughput to autoscale */
|
/* Migrate an Azure Cosmos DB SQL database from manual throughput to autoscale */
|
||||||
@@ -131,7 +131,7 @@ export async function createUpdateSqlContainer(
|
|||||||
body: Types.SqlContainerCreateUpdateParameters
|
body: Types.SqlContainerCreateUpdateParameters
|
||||||
): Promise<Types.SqlContainerGetResults | void> {
|
): Promise<Types.SqlContainerGetResults | void> {
|
||||||
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/sqlDatabases/${databaseName}/containers/${containerName}`;
|
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/sqlDatabases/${databaseName}/containers/${containerName}`;
|
||||||
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body: JSON.stringify(body) });
|
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Deletes an existing Azure Cosmos DB SQL container. */
|
/* Deletes an existing Azure Cosmos DB SQL container. */
|
||||||
@@ -168,7 +168,7 @@ export async function updateSqlContainerThroughput(
|
|||||||
body: Types.ThroughputSettingsUpdateParameters
|
body: Types.ThroughputSettingsUpdateParameters
|
||||||
): Promise<Types.ThroughputSettingsGetResults | void> {
|
): Promise<Types.ThroughputSettingsGetResults | void> {
|
||||||
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/sqlDatabases/${databaseName}/containers/${containerName}/throughputSettings/default`;
|
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/sqlDatabases/${databaseName}/containers/${containerName}/throughputSettings/default`;
|
||||||
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body: JSON.stringify(body) });
|
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Migrate an Azure Cosmos DB SQL container from manual throughput to autoscale */
|
/* Migrate an Azure Cosmos DB SQL container from manual throughput to autoscale */
|
||||||
@@ -231,7 +231,7 @@ export async function createUpdateSqlStoredProcedure(
|
|||||||
body: Types.SqlStoredProcedureCreateUpdateParameters
|
body: Types.SqlStoredProcedureCreateUpdateParameters
|
||||||
): Promise<Types.SqlStoredProcedureGetResults | void> {
|
): Promise<Types.SqlStoredProcedureGetResults | void> {
|
||||||
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/sqlDatabases/${databaseName}/containers/${containerName}/storedProcedures/${storedProcedureName}`;
|
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/sqlDatabases/${databaseName}/containers/${containerName}/storedProcedures/${storedProcedureName}`;
|
||||||
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body: JSON.stringify(body) });
|
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Deletes an existing Azure Cosmos DB SQL storedProcedure. */
|
/* Deletes an existing Azure Cosmos DB SQL storedProcedure. */
|
||||||
@@ -283,7 +283,7 @@ export async function createUpdateSqlUserDefinedFunction(
|
|||||||
body: Types.SqlUserDefinedFunctionCreateUpdateParameters
|
body: Types.SqlUserDefinedFunctionCreateUpdateParameters
|
||||||
): Promise<Types.SqlUserDefinedFunctionGetResults | void> {
|
): Promise<Types.SqlUserDefinedFunctionGetResults | void> {
|
||||||
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/sqlDatabases/${databaseName}/containers/${containerName}/userDefinedFunctions/${userDefinedFunctionName}`;
|
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/sqlDatabases/${databaseName}/containers/${containerName}/userDefinedFunctions/${userDefinedFunctionName}`;
|
||||||
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body: JSON.stringify(body) });
|
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Deletes an existing Azure Cosmos DB SQL userDefinedFunction. */
|
/* Deletes an existing Azure Cosmos DB SQL userDefinedFunction. */
|
||||||
@@ -335,7 +335,7 @@ export async function createUpdateSqlTrigger(
|
|||||||
body: Types.SqlTriggerCreateUpdateParameters
|
body: Types.SqlTriggerCreateUpdateParameters
|
||||||
): Promise<Types.SqlTriggerGetResults | void> {
|
): Promise<Types.SqlTriggerGetResults | void> {
|
||||||
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/sqlDatabases/${databaseName}/containers/${containerName}/triggers/${triggerName}`;
|
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/sqlDatabases/${databaseName}/containers/${containerName}/triggers/${triggerName}`;
|
||||||
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body: JSON.stringify(body) });
|
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Deletes an existing Azure Cosmos DB SQL trigger. */
|
/* Deletes an existing Azure Cosmos DB SQL trigger. */
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export async function createUpdateTable(
|
|||||||
body: Types.TableCreateUpdateParameters
|
body: Types.TableCreateUpdateParameters
|
||||||
): Promise<Types.TableGetResults | void> {
|
): Promise<Types.TableGetResults | void> {
|
||||||
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/tables/${tableName}`;
|
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/tables/${tableName}`;
|
||||||
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body: JSON.stringify(body) });
|
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Deletes an existing Azure Cosmos DB Table. */
|
/* Deletes an existing Azure Cosmos DB Table. */
|
||||||
@@ -73,7 +73,7 @@ export async function updateTableThroughput(
|
|||||||
body: Types.ThroughputSettingsUpdateParameters
|
body: Types.ThroughputSettingsUpdateParameters
|
||||||
): Promise<Types.ThroughputSettingsGetResults | void> {
|
): Promise<Types.ThroughputSettingsGetResults | void> {
|
||||||
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/tables/${tableName}/throughputSettings/default`;
|
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/tables/${tableName}/throughputSettings/default`;
|
||||||
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body: JSON.stringify(body) });
|
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Migrate an Azure Cosmos DB Table from manual throughput to autoscale */
|
/* Migrate an Azure Cosmos DB Table from manual throughput to autoscale */
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -6,15 +6,9 @@ Instead, generate ARM clients that consume this function with stricter typing.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import promiseRetry, { AbortError } from "p-retry";
|
import promiseRetry, { AbortError } from "p-retry";
|
||||||
|
import { ErrorResponse } from "./generatedClients/2020-04-01/types";
|
||||||
import { userContext } from "../../UserContext";
|
import { userContext } from "../../UserContext";
|
||||||
|
|
||||||
interface ErrorResponse {
|
|
||||||
error: {
|
|
||||||
code: string;
|
|
||||||
message: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ARMError extends Error {
|
interface ARMError extends Error {
|
||||||
code: string;
|
code: string;
|
||||||
}
|
}
|
||||||
@@ -40,8 +34,8 @@ export async function armRequest<T>({ host, path, apiVersion, method, body: requ
|
|||||||
});
|
});
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const errorResponse = (await response.json()) as ErrorResponse;
|
const errorResponse = (await response.json()) as ErrorResponse;
|
||||||
const error = new Error(errorResponse.error?.message) as ARMError;
|
const error = new Error(errorResponse.message) as ARMError;
|
||||||
error.code = errorResponse.error.code;
|
error.code = errorResponse.code;
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,8 +78,8 @@ async function getOperationStatus(operationStatusUrl: string) {
|
|||||||
});
|
});
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const errorResponse = (await response.json()) as ErrorResponse;
|
const errorResponse = (await response.json()) as ErrorResponse;
|
||||||
const error = new Error(errorResponse.error?.message) as ARMError;
|
const error = new Error(errorResponse.message) as ARMError;
|
||||||
error.code = errorResponse.error.code;
|
error.code = errorResponse.code;
|
||||||
throw new AbortError(error);
|
throw new AbortError(error);
|
||||||
}
|
}
|
||||||
const body = (await response.json()) as OperationResponse;
|
const body = (await response.json()) as OperationResponse;
|
||||||
|
|||||||
@@ -102,31 +102,31 @@ interface Property {
|
|||||||
}[];
|
}[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const propertyToType = (property: Property, prop: string) => {
|
const propertyToType = (property: Property, prop: string, required: boolean) => {
|
||||||
if (property) {
|
if (property) {
|
||||||
if (property.allOf) {
|
if (property.allOf) {
|
||||||
outputTypes.push(`
|
outputTypes.push(`
|
||||||
/* ${property.description || "undocumented"} */
|
/* ${property.description || "undocumented"} */
|
||||||
${property.readOnly ? "readonly " : ""}${prop}: ${property.allOf
|
${property.readOnly ? "readonly " : ""}${prop}${
|
||||||
.map((allof: { $ref: string }) => refToType(allof.$ref))
|
required ? "" : "?"
|
||||||
.join(" & ")}`);
|
}: ${property.allOf.map((allof: { $ref: string }) => refToType(allof.$ref)).join(" & ")}`);
|
||||||
} else if (property.$ref) {
|
} else if (property.$ref) {
|
||||||
const type = refToType(property.$ref);
|
const type = refToType(property.$ref);
|
||||||
outputTypes.push(`
|
outputTypes.push(`
|
||||||
/* ${property.description || "undocumented"} */
|
/* ${property.description || "undocumented"} */
|
||||||
${property.readOnly ? "readonly " : ""}${prop}: ${type}
|
${property.readOnly ? "readonly " : ""}${prop}${required ? "" : "?"}: ${type}
|
||||||
`);
|
`);
|
||||||
} else if (property.type === "array") {
|
} else if (property.type === "array") {
|
||||||
const type = refToType(property.items.$ref);
|
const type = refToType(property.items.$ref);
|
||||||
outputTypes.push(`
|
outputTypes.push(`
|
||||||
/* ${property.description || "undocumented"} */
|
/* ${property.description || "undocumented"} */
|
||||||
${property.readOnly ? "readonly " : ""}${prop}: ${type}[]
|
${property.readOnly ? "readonly " : ""}${prop}${required ? "" : "?"}: ${type}[]
|
||||||
`);
|
`);
|
||||||
} else if (property.type === "object") {
|
} else if (property.type === "object") {
|
||||||
const type = refToType(property.$ref);
|
const type = refToType(property.$ref);
|
||||||
outputTypes.push(`
|
outputTypes.push(`
|
||||||
/* ${property.description || "undocumented"} */
|
/* ${property.description || "undocumented"} */
|
||||||
${property.readOnly ? "readonly " : ""}${prop}: ${type}
|
${property.readOnly ? "readonly " : ""}${prop}${required ? "" : "?"}: ${type}
|
||||||
`);
|
`);
|
||||||
} else {
|
} else {
|
||||||
if (property.type === undefined) {
|
if (property.type === undefined) {
|
||||||
@@ -135,7 +135,7 @@ const propertyToType = (property: Property, prop: string) => {
|
|||||||
}
|
}
|
||||||
outputTypes.push(`
|
outputTypes.push(`
|
||||||
/* ${property.description || "undocumented"} */
|
/* ${property.description || "undocumented"} */
|
||||||
${property.readOnly ? "readonly " : ""}${prop}: ${
|
${property.readOnly ? "readonly " : ""}${prop}${required ? "" : "?"}: ${
|
||||||
propertyMap[property.type] ? propertyMap[property.type] : property.type
|
propertyMap[property.type] ? propertyMap[property.type] : property.type
|
||||||
}`);
|
}`);
|
||||||
}
|
}
|
||||||
@@ -166,7 +166,7 @@ async function main() {
|
|||||||
}
|
}
|
||||||
for (const prop in schema.definitions[definition].properties) {
|
for (const prop in schema.definitions[definition].properties) {
|
||||||
const property = schema.definitions[definition].properties[prop];
|
const property = schema.definitions[definition].properties[prop];
|
||||||
propertyToType(property, prop);
|
propertyToType(property, prop, schema.definitions[definition].required?.includes(prop));
|
||||||
}
|
}
|
||||||
outputTypes.push(`}`);
|
outputTypes.push(`}`);
|
||||||
outputTypes.push("\n\n");
|
outputTypes.push("\n\n");
|
||||||
@@ -245,7 +245,7 @@ async function main() {
|
|||||||
) : Promise<${responseType(operation, "Types")}> {
|
) : Promise<${responseType(operation, "Types")}> {
|
||||||
const path = \`${path.replace(/{/g, "${")}\`
|
const path = \`${path.replace(/{/g, "${")}\`
|
||||||
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "${method.toLocaleUpperCase()}", apiVersion, ${
|
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "${method.toLocaleUpperCase()}", apiVersion, ${
|
||||||
bodyParameter ? "body: JSON.stringify(body)" : ""
|
bodyParameter ? "body" : ""
|
||||||
} })
|
} })
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
|
|||||||
Reference in New Issue
Block a user