mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-02-16 17:25:58 +00:00
MongoClient Feature Flag (#1073)
Adding a feature flag for Mongo Client that allows a user to specify a mongo endpoint and an API so that users can test specific APIs locally. Example: https://localhost:1234/hostedExplorer.html?feature.mongoproxyendpoint=https://localhost:12901&feature.mongoProxyAPIs=createDocument|readDocument The above link says to test APIs createDocument and readDocument on https://localhost:12901 Co-authored-by: artrejo <ato9000@users.noreply.github.com> Co-authored-by: Asier Isayas <aisayas@microsoft.com>
This commit is contained in:
parent
7e4f030547
commit
d10f3c69f1
@ -3,8 +3,9 @@ import { resetConfigContext, updateConfigContext } from "../ConfigContext";
|
||||
import { DatabaseAccount } from "../Contracts/DataModels";
|
||||
import { Collection } from "../Contracts/ViewModels";
|
||||
import DocumentId from "../Explorer/Tree/DocumentId";
|
||||
import { extractFeatures } from "../Platform/Hosted/extractFeatures";
|
||||
import { updateUserContext } from "../UserContext";
|
||||
import { deleteDocument, getEndpoint, queryDocuments, readDocument, updateDocument } from "./MongoProxyClient";
|
||||
import { deleteDocument, getEndpoint, getFeatureEndpointOrDefault, queryDocuments, readDocument, updateDocument } from "./MongoProxyClient";
|
||||
|
||||
const databaseId = "testDB";
|
||||
|
||||
@ -246,4 +247,32 @@ describe("MongoProxyClient", () => {
|
||||
expect(endpoint).toEqual("https://main.documentdb.ext.azure.com/api/guest/mongo/explorer");
|
||||
});
|
||||
});
|
||||
describe("getFeatureEndpointOrDefault", () => {
|
||||
beforeEach(() => {
|
||||
resetConfigContext();
|
||||
updateConfigContext({
|
||||
BACKEND_ENDPOINT: "https://main.documentdb.ext.azure.com",
|
||||
});
|
||||
const params = new URLSearchParams({
|
||||
"feature.mongoProxyEndpoint": "https://localhost:12901",
|
||||
"feature.mongoProxyAPIs": "readDocument|createDocument",
|
||||
});
|
||||
const features = extractFeatures(params);
|
||||
updateUserContext({
|
||||
authType: AuthType.AAD,
|
||||
features: features
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it("returns a local endpoint", () => {
|
||||
const endpoint = getFeatureEndpointOrDefault("readDocument");
|
||||
expect(endpoint).toEqual("https://localhost:12901/api/mongo/explorer");
|
||||
});
|
||||
|
||||
it("returns a production endpoint", () => {
|
||||
const endpoint = getFeatureEndpointOrDefault("deleteDocument");
|
||||
expect(endpoint).toEqual("https://main.documentdb.ext.azure.com/api/mongo/explorer");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -6,6 +6,7 @@ import * as DataModels from "../Contracts/DataModels";
|
||||
import { MessageTypes } from "../Contracts/ExplorerContracts";
|
||||
import { Collection } from "../Contracts/ViewModels";
|
||||
import DocumentId from "../Explorer/Tree/DocumentId";
|
||||
import { hasFlag } from "../Platform/Hosted/extractFeatures";
|
||||
import { userContext } from "../UserContext";
|
||||
import { logConsoleError } from "../Utils/NotificationConsoleUtils";
|
||||
import { ApiType, HttpHeaders, HttpStatusCodes } from "./Constants";
|
||||
@ -78,7 +79,7 @@ export function queryDocuments(
|
||||
: "",
|
||||
};
|
||||
|
||||
const endpoint = getEndpoint() || "";
|
||||
const endpoint = getFeatureEndpointOrDefault("resourcelist") || "";
|
||||
|
||||
const headers = {
|
||||
...defaultHeaders,
|
||||
@ -141,7 +142,8 @@ export function readDocument(
|
||||
: "",
|
||||
};
|
||||
|
||||
const endpoint = getEndpoint();
|
||||
const endpoint = getFeatureEndpointOrDefault("readDocument");
|
||||
|
||||
return window
|
||||
.fetch(`${endpoint}?${queryString.stringify(params)}`, {
|
||||
method: "GET",
|
||||
@ -181,7 +183,7 @@ export function createDocument(
|
||||
pk: collection && collection.partitionKey && !collection.partitionKey.systemKey ? partitionKeyProperty : "",
|
||||
};
|
||||
|
||||
const endpoint = getEndpoint();
|
||||
const endpoint = getFeatureEndpointOrDefault("createDocument");
|
||||
|
||||
return window
|
||||
.fetch(`${endpoint}/resourcelist?${queryString.stringify(params)}`, {
|
||||
@ -225,7 +227,7 @@ export function updateDocument(
|
||||
? documentId.partitionKeyProperty
|
||||
: "",
|
||||
};
|
||||
const endpoint = getEndpoint();
|
||||
const endpoint = getFeatureEndpointOrDefault("updateDocument");
|
||||
|
||||
return window
|
||||
.fetch(`${endpoint}?${queryString.stringify(params)}`, {
|
||||
@ -266,7 +268,7 @@ export function deleteDocument(databaseId: string, collection: Collection, docum
|
||||
? documentId.partitionKeyProperty
|
||||
: "",
|
||||
};
|
||||
const endpoint = getEndpoint();
|
||||
const endpoint = getFeatureEndpointOrDefault("deleteDocument");;
|
||||
|
||||
return window
|
||||
.fetch(`${endpoint}?${queryString.stringify(params)}`, {
|
||||
@ -309,7 +311,7 @@ export function createMongoCollectionWithProxy(
|
||||
autoPilotThroughput: params.autoPilotMaxThroughput?.toString(),
|
||||
};
|
||||
|
||||
const endpoint = getEndpoint();
|
||||
const endpoint = getFeatureEndpointOrDefault("createCollectionWithProxy");
|
||||
|
||||
return window
|
||||
.fetch(
|
||||
@ -333,8 +335,13 @@ export function createMongoCollectionWithProxy(
|
||||
});
|
||||
}
|
||||
|
||||
export function getEndpoint(): string {
|
||||
let url = (configContext.MONGO_BACKEND_ENDPOINT || configContext.BACKEND_ENDPOINT) + "/api/mongo/explorer";
|
||||
export function getFeatureEndpointOrDefault(feature: string): string {
|
||||
return (hasFlag(userContext.features.mongoProxyAPIs, feature)) ? getEndpoint(userContext.features.mongoProxyEndpoint) : getEndpoint();
|
||||
}
|
||||
|
||||
export function getEndpoint(customEndpoint?: string): string {
|
||||
let url = customEndpoint ? customEndpoint : (configContext.MONGO_BACKEND_ENDPOINT || configContext.BACKEND_ENDPOINT);
|
||||
url += "/api/mongo/explorer";
|
||||
|
||||
if (userContext.authType === AuthType.EncryptedToken) {
|
||||
url = url.replace("api/mongo", "api/guest/mongo");
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { extractFeatures } from "./extractFeatures";
|
||||
import { extractFeatures, hasFlag } from "./extractFeatures";
|
||||
|
||||
describe("extractFeatures", () => {
|
||||
it("correctly detects feature flags in a case insensitive manner", () => {
|
||||
@ -14,9 +14,24 @@ describe("extractFeatures", () => {
|
||||
});
|
||||
|
||||
const features = extractFeatures(params);
|
||||
|
||||
expect(features.notebookServerUrl).toBe(url);
|
||||
expect(features.notebookServerToken).toBe(token);
|
||||
expect(features.enableNotebooks).toBe(notebooksEnabled);
|
||||
});
|
||||
});
|
||||
|
||||
describe("hasFlag", () => {
|
||||
it("correctly determines if value has flag", () => {
|
||||
const desiredFlag = "readDocument";
|
||||
|
||||
const singleFlagValue = "readDocument";
|
||||
const multipleFlagValues = "readDocument|createDocument";
|
||||
const differentFlagValue = "createDocument";
|
||||
|
||||
expect(hasFlag(singleFlagValue, desiredFlag)).toBe(true);
|
||||
expect(hasFlag(multipleFlagValues, desiredFlag)).toBe(true);
|
||||
expect(hasFlag(differentFlagValue, desiredFlag)).toBe(false);
|
||||
expect(hasFlag(multipleFlagValues, undefined)).toBe(false);
|
||||
expect(hasFlag(undefined, desiredFlag)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
@ -29,6 +29,8 @@ export type Features = {
|
||||
readonly pr?: string;
|
||||
readonly showMinRUSurvey: boolean;
|
||||
readonly ttl90Days: boolean;
|
||||
readonly mongoProxyEndpoint: string;
|
||||
readonly mongoProxyAPIs: string;
|
||||
readonly notebooksTemporarilyDown: boolean;
|
||||
};
|
||||
|
||||
@ -63,6 +65,8 @@ export function extractFeatures(given = new URLSearchParams(window.location.sear
|
||||
enableKoResourceTree: "true" === get("enablekoresourcetree"),
|
||||
executeSproc: "true" === get("dataexplorerexecutesproc"),
|
||||
hostedDataExplorer: "true" === get("hosteddataexplorerenabled"),
|
||||
mongoProxyEndpoint: get("mongoproxyendpoint"),
|
||||
mongoProxyAPIs: get("mongoproxyapis"),
|
||||
junoEndpoint: get("junoendpoint"),
|
||||
livyEndpoint: get("livyendpoint"),
|
||||
notebookBasePath: get("notebookbasepath"),
|
||||
@ -80,3 +84,12 @@ export function extractFeatures(given = new URLSearchParams(window.location.sear
|
||||
phoenix: "true" === get("phoenix"),
|
||||
};
|
||||
}
|
||||
|
||||
export function hasFlag(flags: string, desiredFlag: string): boolean {
|
||||
if (!flags || !desiredFlag) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const features = flags.split("|");
|
||||
return features.find((feature) => feature === desiredFlag) ? true : false;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user