diff --git a/README.md b/README.md index 083b0c1..a3a68c2 100644 --- a/README.md +++ b/README.md @@ -48,10 +48,12 @@ To run the feature-toggle-node **locally**, you need to provide the following en Environment variables example: ``` -"FT_SERVER_ENDPOINT": "http://unleash.herokuapp.com", -"WS_BASE_URL": "https://cfsubaccount-workspaces-ws-id.region.applicationstudio.cloud.sap", +"FT_SERVER_ENDPOINT": "http://unleash.herokuapp.com", "USER_NAME": "user@hotmail.com", "FT_CLIENT_REFRESH_INTERVAL": "6s", +"TENANT_ID" : "b5c05535-9495-4050-9d68-4356d0d34136", +"TENANT_NAME": "cfsubaccount" // subaccount, +"WORKSPACE_ID": "workspaces-ws-x66m6", "SHOW_LOG": "true", ``` diff --git a/src/appstudio_context.ts b/src/appstudio_context.ts index 1c66fc7..62129b8 100644 --- a/src/appstudio_context.ts +++ b/src/appstudio_context.ts @@ -2,12 +2,11 @@ import { Context as appstudioContext } from "unleash-client/lib/context"; import { getEnv } from "./utils"; const USER_NAME = "USER_NAME"; -const WS_BASE_URL = "WS_BASE_URL"; const LANDSCAPE_ENVIRONMENT = "LANDSCAPE_ENVIRONMENT"; const LANDSCAPE_NAME = "LANDSCAPE_NAME"; const TENANT_ID = "TENANT_ID"; - -const fullFormatWsBaseUrl = "Expected format: https://-workspaces-ws-../"; +const SUB_ACCOUNT = "TENANT_NAME"; +const WORKSPACE_ID = "WORKSPACE_ID"; export interface AppStudioMultiContext extends appstudioContext { currentEnvironment: string; //app @@ -19,52 +18,34 @@ export interface AppStudioMultiContext extends appstudioContext { currentTenantId: string; } -function extractCfSubAccountAndWs(wsBaseUrlString: string, context: AppStudioMultiContext): void { - // Example - sub account with hyphen - // https://consumer-trial-workspaces-ws-9gzgq.eu10.trial.applicationstudio.cloud.sap/ - // consumer-trial: the cf sub account - // ws-9gzgq: the WS - - const regex = new RegExp("^(https:)\\S*(-workspaces-ws-)\\S*", "g"); - if (!regex.test(wsBaseUrlString)) { - throw new Error(`Feature toggle env WS_BASE_URL is NOT in the correct format. ${fullFormatWsBaseUrl}`); - } - - // make wsBaseUrlString: [consumer-trial, ws-9gzgq.eu10.trial.applicationstudio.cloud.sap/] - const splitByWorkspaces = wsBaseUrlString.substr(8).split("-workspaces-"); - context.currentCfSubAccount = splitByWorkspaces[0]; // sub account: "consumer-trial" - - // turn ws-9gzgq.eu10.trial.applicationstudio.cloud.sap/ to [ws-9gzgq, eu10,trial, ...] - const splitDotArray = splitByWorkspaces[1].split("."); - - context.currentWs = splitDotArray[0]; // workspace: ws-n8vmz +function getEnvWithNotFoundError(envVar: string): string { + return getEnv(envVar, `Feature toggle env ${envVar} was NOT found in the environment variables`); } export function createContextObject(): AppStudioMultiContext { // get the user name from the env - const userName = getEnv(USER_NAME, "Feature toggle env USER_NAME was NOT found in the environment variables"); + const userName = getEnvWithNotFoundError(USER_NAME); // get the environment from the env - const environment = getEnv(LANDSCAPE_ENVIRONMENT, "Feature toggle env LANDSCAPE_ENVIRONMENT was NOT found in the environment variables"); + const environment = getEnvWithNotFoundError(LANDSCAPE_ENVIRONMENT); // get the landscape from the env - const landscape = getEnv(LANDSCAPE_NAME, "Feature toggle env LANDSCAPE_NAME was NOT found in the environment variables"); + const landscape = getEnvWithNotFoundError(LANDSCAPE_NAME); + // get the tenant id from the env + const tenantId = getEnvWithNotFoundError(TENANT_ID); // get the tenant id from the env - const tenantId = getEnv(TENANT_ID, "Feature toggle env TENANT_ID was NOT found in the environment variables"); + const subAccount = getEnvWithNotFoundError(SUB_ACCOUNT); + // get WORKSPACE_ID env + const ws = getEnvWithNotFoundError(WORKSPACE_ID); // Create the context const context: AppStudioMultiContext = { currentEnvironment: environment, currentInfrastructure: "", currentLandscape: landscape, - currentCfSubAccount: "", // will be added in the next function + currentCfSubAccount: subAccount, currentUser: userName, - currentWs: "", // will be added in the next function + currentWs: ws, currentTenantId: tenantId, }; - // get the WS and SubAccount from WS_BASE_URL env - const wsBaseUrlString = getEnv(WS_BASE_URL, "Feature toggle env WS_BASE_URL was NOT found in the environment variables"); - // Extract the WS and cluster and save in the context - extractCfSubAccountAndWs(wsBaseUrlString, context); - return context; } diff --git a/test/context_manager.spec.ts b/test/context_manager.spec.ts index 7e92024..9869c98 100644 --- a/test/context_manager.spec.ts +++ b/test/context_manager.spec.ts @@ -8,10 +8,12 @@ describe("Test context manager", () => { const extensionNameA = "aaa"; const extensionNameB = "bbb"; - const USER = "koko@sap.com"; - const ENVIRONMENT = "prod"; - const LANDSCAPE = "eu10"; - const TENANTID = "111-a11-111"; + const user = "koko@sap.com"; + const env = "prod"; + const landscape = "eu10"; + const tenantId = "111-a11-111"; + const subAccount = "azureconseu"; + const ws = "workspaces-ws-n8vmz"; let contextMap; afterEach(() => { @@ -20,151 +22,117 @@ describe("Test context manager", () => { beforeEach(() => { sinon.stub(process, "env").value({ - WS_BASE_URL: "https://azureconseu-workspaces-ws-n8vmz.eu20.applicationstudio.cloud.sap/", - USER_NAME: USER, - LANDSCAPE_ENVIRONMENT: ENVIRONMENT, - LANDSCAPE_NAME: LANDSCAPE, - TENANT_ID: TENANTID, + USER_NAME: user, + LANDSCAPE_ENVIRONMENT: env, + LANDSCAPE_NAME: landscape, + TENANT_ID: tenantId, + TENANT_NAME: subAccount, + WORKSPACE_ID: ws, }); contextMap = new Map(); }); - function testNoEnvError(extensionName: string, contextMap: Map, errorMessage: string): void { - expect(() => { - contextManager.getContextFromMap(extensionName, contextMap); - }).to.throw(errorMessage); - } + describe("getContext cache", () => { + it("return the same instance from cache", () => { + // create context - NOT in cache -> create a new one + const contextACreated = contextManager.getContext(extensionNameA); + // create context - in cache -> only get from cache + const contextAFromCache = contextManager.getContext(extensionNameA); - it("Test getContext - positive flow", () => { - // create context - NOT in cache -> create a new one - const contextACreated = contextManager.getContext(extensionNameA); - // create context - in cache -> only get from cache - const contextAFromCache = contextManager.getContext(extensionNameA); - - // same instance, ref compare - expect(contextACreated === contextAFromCache).to.be.true; - }); - - it("Test getContext - not fetching from cache when when using different extensions names", () => { - // create context - NOT in cache -> create a new one - const contextACreated = contextManager.getContextFromMap(extensionNameA, contextMap); - // create context - NOT in cache -> create a new one - const contextBCreated = contextManager.getContextFromMap(extensionNameB, contextMap); - - // NOT same instance, ref compare - expect(contextACreated === contextBCreated).to.be.false; - }); - - it("Test context - getContext - getting the expected context values - positive flow", () => { - //WS_BASE_URL: "https://azureconseu-workspaces-ws-n8vmz.eu20.applicationstudio.cloud.sap/", - - const expectedContext: AppStudioMultiContext = { - currentEnvironment: ENVIRONMENT, - currentInfrastructure: "", - currentLandscape: LANDSCAPE, - currentCfSubAccount: "azureconseu", - currentUser: USER, - currentWs: "ws-n8vmz", - currentTenantId: TENANTID, - }; - - // create context - NOT in cache -> create a new one - const contextA: AppStudioMultiContext = contextManager.getContextFromMap(extensionNameA, contextMap); - - expect(contextA).to.deep.equal(expectedContext); - }); - - it("Test context - getContext - getting the expected context values - positive flow", () => { - sinon.stub(process, "env").value({ - WS_BASE_URL: "https://consumer-trial-workspaces-ws-9gzgq.eu10.trial.applicationstudio.cloud.sap/", - USER_NAME: USER, - LANDSCAPE_ENVIRONMENT: ENVIRONMENT, - LANDSCAPE_NAME: LANDSCAPE, - TENANT_ID: TENANTID, + // same instance, ref compare + expect(contextACreated === contextAFromCache).to.be.true; }); - const expectedContext: AppStudioMultiContext = { - currentEnvironment: ENVIRONMENT, - currentInfrastructure: "", - currentLandscape: LANDSCAPE, - currentCfSubAccount: "consumer-trial", - currentUser: USER, - currentWs: "ws-9gzgq", - currentTenantId: TENANTID, - }; - - // create context - NOT in cache -> create a new one - const contextA = contextManager.getContextFromMap(extensionNameA, contextMap); + it("return different instances from cache when when using different extensions names", () => { + // create context - NOT in cache -> create a new one + const contextACreated = contextManager.getContextFromMap(extensionNameA, contextMap); + // create context - NOT in cache -> create a new one + const contextBCreated = contextManager.getContextFromMap(extensionNameB, contextMap); - expect(contextA).to.deep.equal(expectedContext); + // NOT same instance, ref compare + expect(contextACreated === contextBCreated).to.be.false; + }); }); - it("Test context - getContext - getting error for lack of '-workspaces-ws-' in WS_BASE_URL - negative flow", () => { - sinon.stub(process, "env").value({ - WS_BASE_URL: "https://azureconseun8vmz.eu20", - USER_NAME: USER, - LANDSCAPE_ENVIRONMENT: ENVIRONMENT, - LANDSCAPE_NAME: LANDSCAPE, - TENANT_ID: TENANTID, + describe("getContextFromMap", () => { + function testNoEnvError(extensionName: string, contextMap: Map, errorMessage: string): void { + expect(() => { + contextManager.getContextFromMap(extensionName, contextMap); + }).to.throw(errorMessage); + } + + it("getting the expected context values", () => { + const expectedContext: AppStudioMultiContext = { + currentEnvironment: env, + currentInfrastructure: "", + currentLandscape: landscape, + currentCfSubAccount: subAccount, + currentUser: user, + currentWs: ws, + currentTenantId: tenantId, + }; + + // create context - NOT in cache -> create a new one + const contextA: AppStudioMultiContext = contextManager.getContextFromMap(extensionNameA, contextMap); + + expect(contextA).to.deep.equal(expectedContext); }); - testNoEnvError(extensionNameA, contextMap, `Feature toggle env WS_BASE_URL is NOT in the correct format. Expected format: https://-workspaces-ws-../`); - }); + it("getting error for no WORKSPACE_ID environment variable", () => { + sinon.stub(process, "env").value({ + USER_NAME: user, + LANDSCAPE_ENVIRONMENT: env, + LANDSCAPE_NAME: landscape, + TENANT_ID: tenantId, + TENANT_NAME: subAccount, + }); - it("Test context - getContext - getting error for when using http instead of https in WS_BASE_URL - negative flow", () => { - sinon.stub(process, "env").value({ - WS_BASE_URL: "http://azureconseu-workspaces-ws-n8vmz.eu20.applicationstudio.cloud.sap/", - USER_NAME: USER, - LANDSCAPE_ENVIRONMENT: ENVIRONMENT, - LANDSCAPE_NAME: LANDSCAPE, - TENANT_ID: TENANTID, + testNoEnvError(extensionNameA, contextMap, "Feature toggle env WORKSPACE_ID was NOT found in the environment variables"); }); - testNoEnvError(extensionNameA, contextMap, `Feature toggle env WS_BASE_URL is NOT in the correct format. Expected format: https://-workspaces-ws-../`); - }); + it("getting error for no TENANT_NAME environment variable", () => { + sinon.stub(process, "env").value({ + USER_NAME: user, + LANDSCAPE_ENVIRONMENT: env, + LANDSCAPE_NAME: landscape, + TENANT_ID: tenantId, + }); - it("Test context - getContext - getting error for no WS_BASE_URL env parameter - negative flow", () => { - sinon.stub(process, "env").value({ - USER_NAME: USER, - LANDSCAPE_ENVIRONMENT: ENVIRONMENT, - LANDSCAPE_NAME: LANDSCAPE, - TENANT_ID: TENANTID, + testNoEnvError(extensionNameA, contextMap, "Feature toggle env TENANT_NAME was NOT found in the environment variables"); }); - testNoEnvError(extensionNameA, contextMap, "Feature toggle env WS_BASE_URL was NOT found in the environment variables"); - }); + it("getting error for no USER_NAME environment variable", () => { + sinon.stub(process, "env").value({}); - it("Test context - getContext - getting error for no USER_NAME env parameter - negative flow", () => { - sinon.stub(process, "env").value({}); + testNoEnvError(extensionNameA, contextMap, "Feature toggle env USER_NAME was NOT found in the environment variables"); + }); - testNoEnvError(extensionNameA, contextMap, "Feature toggle env USER_NAME was NOT found in the environment variables"); - }); + it("getting error for no LANDSCAPE_ENVIRONMENT environment variable", () => { + sinon.stub(process, "env").value({ + USER_NAME: user, + }); - it("Test context - getContext - getting error for no LANDSCAPE_ENVIRONMENT env parameter - negative flow", () => { - sinon.stub(process, "env").value({ - USER_NAME: USER, + testNoEnvError(extensionNameA, contextMap, "Feature toggle env LANDSCAPE_ENVIRONMENT was NOT found in the environment variables"); }); - testNoEnvError(extensionNameA, contextMap, "Feature toggle env LANDSCAPE_ENVIRONMENT was NOT found in the environment variables"); - }); + it("getting error for no TENANT_ID environment variable", () => { + sinon.stub(process, "env").value({ + USER_NAME: user, + LANDSCAPE_ENVIRONMENT: env, + LANDSCAPE_NAME: landscape, + }); - it("Test context - getContext - getting error for no LANDSCAPE_NAME env parameter - negative flow", () => { - sinon.stub(process, "env").value({ - USER_NAME: USER, - LANDSCAPE_ENVIRONMENT: ENVIRONMENT, + testNoEnvError(extensionNameA, contextMap, "Feature toggle env TENANT_ID was NOT found in the environment variables"); }); - testNoEnvError(extensionNameA, contextMap, "Feature toggle env LANDSCAPE_NAME was NOT found in the environment variables"); - }); + it("getting error for no LANDSCAPE_NAME environment variable", () => { + sinon.stub(process, "env").value({ + USER_NAME: user, + LANDSCAPE_ENVIRONMENT: env, + }); - it("Test context - getContext - getting error for no TENANT_ID env parameter - negative flow", () => { - sinon.stub(process, "env").value({ - USER_NAME: USER, - LANDSCAPE_ENVIRONMENT: ENVIRONMENT, - LANDSCAPE_NAME: LANDSCAPE, + testNoEnvError(extensionNameA, contextMap, "Feature toggle env LANDSCAPE_NAME was NOT found in the environment variables"); }); - - testNoEnvError(extensionNameA, contextMap, "Feature toggle env TENANT_ID was NOT found in the environment variables"); }); });