Skip to content

Commit

Permalink
Merge pull request #423 from vscheuber/main
Browse files Browse the repository at this point in the history
Homogenized encoding of variable values, added tests for variable ops…
  • Loading branch information
vscheuber authored Jul 5, 2024
2 parents 88c5d32 + 5c0e6b9 commit d177609
Show file tree
Hide file tree
Showing 35 changed files with 4,235 additions and 465 deletions.
21 changes: 11 additions & 10 deletions src/api/cloud/VariablesApi.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import * as VariablesApi from './VariablesApi';
import { autoSetupPolly, filterRecording } from '../../utils/AutoSetupPolly';
import { state } from '../../index';
import { encode } from '../../utils/Base64Utils';

const ctx = autoSetupPolly();

Expand Down Expand Up @@ -60,7 +61,7 @@ async function stageVariable(variable: TestVariable, create = true) {
try {
await VariablesApi.putVariable({
variableId: variable.name,
value: variable.value,
valueBase64: encode(variable.value),
description: variable.description,
expressionType: variable.type,
state,
Expand Down Expand Up @@ -240,7 +241,7 @@ describe('VariablesApi', () => {
test(`1: Create new variable with default type (string): ${var4.name} - success`, async () => {
const response = await VariablesApi.putVariable({
variableId: var4.name,
value: var4.value,
valueBase64: encode(var4.value),
description: var4.description,
expressionType: var4.type,
state,
Expand All @@ -251,7 +252,7 @@ describe('VariablesApi', () => {
test(`2: Create new string variable (explicit type): ${var5.name} - success`, async () => {
const response = await VariablesApi.putVariable({
variableId: var5.name,
value: var5.value,
valueBase64: encode(var5.value),
description: var5.description,
expressionType: var5.type,
state,
Expand All @@ -262,7 +263,7 @@ describe('VariablesApi', () => {
test(`3: Create new array variable: ${var6.name} - success`, async () => {
const response = await VariablesApi.putVariable({
variableId: var6.name,
value: var6.value,
valueBase64: encode(var6.value),
description: var6.description,
expressionType: var6.type,
state,
Expand All @@ -284,7 +285,7 @@ describe('VariablesApi', () => {
test(`5: Create new bool variable: ${var8.name} - success`, async () => {
const response = await VariablesApi.putVariable({
variableId: var8.name,
value: var8.value,
valueBase64: encode(var8.value),
description: var8.description,
expressionType: var8.type,
state,
Expand All @@ -295,7 +296,7 @@ describe('VariablesApi', () => {
test(`6: Create new int variable: ${var9.name} - success`, async () => {
const response = await VariablesApi.putVariable({
variableId: var9.name,
value: var9.value,
valueBase64: encode(var9.value),
description: var9.description,
expressionType: var9.type,
state,
Expand All @@ -306,7 +307,7 @@ describe('VariablesApi', () => {
test(`7: Create new keyvaluelist variable: ${var10.name} - success`, async () => {
const response = await VariablesApi.putVariable({
variableId: var10.name,
value: var10.value,
valueBase64: encode(var10.value),
description: var10.description,
expressionType: var10.type,
state,
Expand All @@ -317,7 +318,7 @@ describe('VariablesApi', () => {
test(`8: Create new list variable: ${var11.name} - success`, async () => {
const response = await VariablesApi.putVariable({
variableId: var11.name,
value: var11.value,
valueBase64: encode(var11.value),
description: var11.description,
expressionType: var11.type,
state,
Expand All @@ -328,7 +329,7 @@ describe('VariablesApi', () => {
test(`9: Create new number variable: ${var12.name} - success`, async () => {
const response = await VariablesApi.putVariable({
variableId: var12.name,
value: var12.value,
valueBase64: encode(var12.value),
description: var12.description,
expressionType: var12.type,
state,
Expand All @@ -339,7 +340,7 @@ describe('VariablesApi', () => {
test(`10: Create new object variable: ${var13.name} - success`, async () => {
const response = await VariablesApi.putVariable({
variableId: var13.name,
value: var13.value,
valueBase64: encode(var13.value),
description: var13.description,
expressionType: var13.type,
state,
Expand Down
12 changes: 6 additions & 6 deletions src/api/cloud/VariablesApi.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import util from 'util';

import { State } from '../../shared/State';
import { encode } from '../../utils/Base64Utils';
import { getHostBaseUrl } from '../../utils/ForgeRockUtils';
import { IdObjectSkeletonInterface, PagedResult } from '../ApiTypes';
import { generateEnvApi } from '../BaseApi';
Expand Down Expand Up @@ -52,7 +51,8 @@ export type VariableExpressionType =
* Variable object skeleton
*/
export type VariableSkeleton = IdObjectSkeletonInterface & {
valueBase64: string;
valueBase64?: string;
value?: string;
description?: string;
loaded?: boolean;
lastChangedBy?: string;
Expand Down Expand Up @@ -111,25 +111,25 @@ export async function getVariable({
/**
* Create or update variable by id/name
* @param {string} variableId variable id/name
* @param {string} value variable value
* @param {string} valueBase64 base64-encoded variable value
* @param {string} description variable description
* @returns {Promise<unknown>} a promise that resolves to a variable object
*/
export async function putVariable({
variableId,
value,
valueBase64,
description = '',
expressionType = 'string',
state,
}: {
variableId: string;
value: string;
valueBase64: string;
description?: string;
expressionType?: VariableExpressionType;
state: State;
}): Promise<VariableSkeleton> {
const variableData: VariableSkeleton = {
valueBase64: encode(value),
valueBase64,
description,
expressionType,
};
Expand Down
4 changes: 2 additions & 2 deletions src/ops/ConfigOps.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ describe('ConfigOps', () => {
test('1: Export everything with string arrays, decoding variables, including journey coordinates and default scripts', async () => {
// Set deployment type to cloud since it is necessary for exporting applications correctly. It does this automatically when recording the mock, but not when running the test after recording
state.setDeploymentType(Constants.CLOUD_DEPLOYMENT_TYPE_KEY);
const response = await ConfigOps.exportFullConfiguration({ options: { useStringArrays: true, noDecode: false, coords: true, includeDefault: true }, state });
const response = await ConfigOps.exportFullConfiguration({ options: { useStringArrays: true, noDecode: false, coords: true, includeDefault: true, includeActiveValues: false }, state });
expect(response).toMatchSnapshot({
meta: expect.any(Object)
});
Expand All @@ -65,7 +65,7 @@ describe('ConfigOps', () => {
test('2: Export everything without string arrays, decoding variables, excluding journey coordinates and default scripts', async () => {
// Set deployment type to cloud since it is necessary for exporting applications correctly. It does this automatically when recording the mock, but not when running the test after recording
state.setDeploymentType(Constants.CLOUD_DEPLOYMENT_TYPE_KEY);
const response = await ConfigOps.exportFullConfiguration({ options: { useStringArrays: false, noDecode: true, coords: false, includeDefault: false }, state });
const response = await ConfigOps.exportFullConfiguration({ options: { useStringArrays: false, noDecode: true, coords: false, includeDefault: false, includeActiveValues: false }, state });
expect(response).toMatchSnapshot({
meta: expect.any(Object)
});
Expand Down
80 changes: 74 additions & 6 deletions src/ops/ConfigOps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ import {
exportCirclesOfTrust,
importCirclesOfTrust,
} from './CirclesOfTrustOps';
import { exportSecrets } from './cloud/SecretsOps';
import { exportVariables } from './cloud/VariablesOps';
import { exportSecrets, importSecrets } from './cloud/SecretsOps';
import { exportVariables, importVariables } from './cloud/VariablesOps';
import {
EmailTemplateSkeleton,
exportEmailTemplates,
Expand Down Expand Up @@ -97,6 +97,7 @@ export default (state: State): Config => {
noDecode: false,
coords: true,
includeDefault: false,
includeActiveValues: true,
},
collectErrors: Error[]
) {
Expand All @@ -111,6 +112,7 @@ export default (state: State): Config => {
global: false,
realm: false,
includeDefault: false,
includeActiveValues: true,
},
collectErrors: Error[]
) {
Expand Down Expand Up @@ -144,6 +146,14 @@ export interface FullExportOptions {
* Include default scripts in export if true
*/
includeDefault: boolean;
/**
* Include active and loaded secret values
*/
includeActiveValues: boolean;
/**
* Host URL of target environment to encrypt secret values for
*/
target?: string;
}

/**
Expand Down Expand Up @@ -174,6 +184,14 @@ export interface FullImportOptions {
* Include default scripts in import if true
*/
includeDefault: boolean;
/**
* Include active secret values
*/
includeActiveValues: boolean;
/**
* Host URL of source environment to decrypt secret values from
*/
source?: string;
}

export interface FullExportInterface {
Expand Down Expand Up @@ -214,6 +232,8 @@ export async function exportFullConfiguration({
noDecode: false,
coords: true,
includeDefault: false,
includeActiveValues: true,
target: '',
},
collectErrors,
state,
Expand All @@ -228,7 +248,14 @@ export async function exportFullConfiguration({
throwErrors = false;
errors = collectErrors;
}
const { useStringArrays, noDecode, coords, includeDefault } = options;
const {
useStringArrays,
noDecode,
coords,
includeDefault,
includeActiveValues,
target,
} = options;
const stateObj = { state };
//Export saml2 providers and circle of trusts
let saml = (
Expand Down Expand Up @@ -341,7 +368,11 @@ export async function exportFullConfiguration({
)
)?.script,
secrets: (
await exportOrImportWithErrorHandling(exportSecrets, stateObj, errors)
await exportOrImportWithErrorHandling(
exportSecrets,
{ options: { includeActiveValues, target }, state },
errors
)
)?.secrets,
service: {
...(
Expand Down Expand Up @@ -409,6 +440,8 @@ export async function importFullConfiguration({
global: false,
realm: false,
includeDefault: false,
includeActiveValues: true,
source: '',
},
collectErrors,
state,
Expand All @@ -431,13 +464,48 @@ export async function importFullConfiguration({
global,
realm,
includeDefault,
includeActiveValues,
source,
} = options;
const indicatorId = createProgressIndicator({
total: 16,
total: 18,
message: 'Importing everything...',
state,
});
// Order of imports matter here since we want dependencies to be imported first. For example, journeys depend on a lot of things, so they are last, and many things depend on scripts, so they are first.
// Order of imports matter here since we want dependencies to be imported first. For example, journeys depend on a lot of things, so they are last, and many things depend on scripts, which depend on variables and secrets, so they are first.
updateProgressIndicator({
id: indicatorId,
message: `Importing Secrets...`,
state,
});
await exportOrImportWithErrorHandling(
importSecrets,
{
importData,
options: {
includeActiveValues,
source,
},
state,
},
errors
);
updateProgressIndicator({
id: indicatorId,
message: `Importing Variables...`,
state,
});
await exportOrImportWithErrorHandling(
importVariables,
{
importData,
options: {
includeActiveValues,
},
state,
},
errors
);
updateProgressIndicator({
id: indicatorId,
message: `Importing Scripts...`,
Expand Down
Loading

0 comments on commit d177609

Please sign in to comment.