Skip to content

Commit

Permalink
Add mapping command and sub-commands. Add ability to separate sync.js…
Browse files Browse the repository at this point in the history
…on mappings in idm/config exports. Update file extraction. Update tests.
  • Loading branch information
phalestrivir committed Jul 9, 2024
1 parent a2e7558 commit 7e0cf9c
Show file tree
Hide file tree
Showing 176 changed files with 297,125 additions and 425,851 deletions.
2 changes: 2 additions & 0 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import idp from './cli/idp/idp';
import info from './cli/info/info';
import journey from './cli/journey/journey';
import log from './cli/log/log';
import mapping from './cli/mapping/mapping';
import oauth from './cli/oauth/oauth';
import realm from './cli/realm/realm';
import saml from './cli/saml/saml';
Expand Down Expand Up @@ -68,6 +69,7 @@ const { initTokenCache } = frodo.cache;
program.addCommand(info());
program.addCommand(journey());
program.addCommand(log());
program.addCommand(mapping());
program.addCommand(oauth());
program.addCommand(realm());
program.addCommand(saml());
Expand Down
7 changes: 7 additions & 0 deletions src/cli/config/config-export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ export default function setup() {
'Export all scripts including the default scripts.'
)
)
.addOption(
new Option(
'-s, --separate-mappings',
'Export sync.json mappings separately in their own directory. Ignored with -a.'
)
)
.addOption(
new Option(
'--include-active-values',
Expand Down Expand Up @@ -138,6 +144,7 @@ export default function setup() {
verboseMessage('Exporting everything to separate files...');
const outcome = await exportEverythingToFiles(
options.extract,
options.separateMappings,
options.metadata,
{
useStringArrays: options.useStringArrays,
Expand Down
26 changes: 22 additions & 4 deletions src/cli/idm/idm-export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,12 @@ export default function setup() {
'Config entity name. E.g. "managed", "sync", "provisioner-<connector-name>", etc.'
)
)
.addOption(new Option('-f, --file [file]', 'Export file. Ignored with -A.'))
.addOption(
new Option(
'-f, --file [file]',
'Export file (or directory name if exporting mappings separately). Ignored with -A.'
)
)
.addOption(
new Option(
'-E, --entities-file [entities-file]',
Expand All @@ -47,6 +52,12 @@ export default function setup() {
'Export all IDM configuration objects into separate JSON files in directory -D. Ignored with -N, and -a.'
)
)
.addOption(
new Option(
'-s, --separate-mappings',
'Export sync.json mappings separately in their own directory.'
)
)
.action(
// implement command logic inside action handler
async (host, realm, user, password, options, command) => {
Expand All @@ -61,7 +72,11 @@ export default function setup() {
// export by id/name
if (options.name && (await getTokens())) {
verboseMessage(`Exporting object "${options.name}"...`);
const outcome = await exportConfigEntity(options.name, options.file);
const outcome = await exportConfigEntity(
options.name,
options.file,
options.separateMappings
);
if (!outcome) process.exitCode = 1;
}
// require --directory -D for all-separate functions
Expand Down Expand Up @@ -89,7 +104,8 @@ export default function setup() {
);
const outcome = await exportAllConfigEntities(
options.entitiesFile,
options.envFile
options.envFile,
options.separateMappings
);
if (!outcome) process.exitCode = 1;
await warnAboutOfflineConnectorServers();
Expand All @@ -99,7 +115,9 @@ export default function setup() {
verboseMessage(
`Exporting all IDM configuration objects into separate files in ${state.getDirectory()}...`
);
const outcome = await exportAllRawConfigEntities();
const outcome = await exportAllRawConfigEntities(
options.separateMappings
);
if (!outcome) process.exitCode = 1;
await warnAboutOfflineConnectorServers();
}
Expand Down
72 changes: 72 additions & 0 deletions src/cli/mapping/mapping-delete.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { Option } from 'commander';

import { getTokens } from '../../ops/AuthenticateOps';
import { deleteMapping, deleteMappings } from '../../ops/MappingOps';
import { printMessage, verboseMessage } from '../../utils/Console';
import { FrodoCommand } from '../FrodoCommand';

export default function setup() {
const program = new FrodoCommand('frodo mapping delete');

program
.description('Delete IDM mappings.')
.addOption(
new Option(
'-i, --mapping-id <mapping-id>',
'Mapping id. If specified, -a is ignored.'
)
)
.addOption(
new Option(
'-c, --connector-id <connector-id>',
'Connector id. If specified, limits mappings to that particular connector; Ignored with -i.'
)
)
.addOption(
new Option(
'-t, --managed-object-type <managed-object-type>',
'Managed object type. If specified, limits mappings to that particular managed object type. Ignored with -i.'
)
)
.addOption(new Option('-a, --all', 'Delete all mappings. Ignored with -i.'))
.action(
// implement command logic inside action handler
async (host, realm, user, password, options, command) => {
command.handleDefaultArgsAndOpts(
host,
realm,
user,
password,
options,
command
);
// delete by id/name
if (options.mappingId && (await getTokens())) {
verboseMessage(`Deleting mapping ${options.mappingId}...`);
const outcome = await deleteMapping(options.mappingId);
if (!outcome) process.exitCode = 1;
}
// --all -a
else if (options.all && (await getTokens())) {
verboseMessage(`Deleting all mappings...`);
const outcome = await deleteMappings(
options.connectorId,
options.managedObjectType
);
if (!outcome) process.exitCode = 1;
}
// unrecognized combination of options or no options
else {
printMessage(
'Unrecognized combination of options or no options...',
'error'
);
program.help();
process.exitCode = 1;
}
}
// end command logic inside action handler
);

return program;
}
123 changes: 123 additions & 0 deletions src/cli/mapping/mapping-export.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import { Option } from 'commander';

import { getTokens } from '../../ops/AuthenticateOps';
import {
exportMappingsToFile,
exportMappingsToFiles,
exportMappingToFile,
} from '../../ops/MappingOps';
import { printMessage, verboseMessage } from '../../utils/Console';
import { FrodoCommand } from '../FrodoCommand';

export default function setup() {
const program = new FrodoCommand('frodo mapping export');

program
.description('Export IDM mappings.')
.addOption(
new Option(
'-i, --mapping-id <mapping-id>',
'Mapping id. If specified, -a is ignored.'
)
)
.addOption(
new Option(
'-c, --connector-id <connector-id>',
'Connector id. If specified, limits mappings to that particular connector; Ignored with -i.'
)
)
.addOption(
new Option(
'-t, --managed-object-type <managed-object-type>',
'Managed object type. If specified, limits mappings to that particular managed object type. Ignored with -i.'
)
)
.addOption(new Option('-f, --file <file>', 'Export file. Ignored with -A.'))
.addOption(new Option('-a, --all', 'Export all mappings. Ignored with -i.'))
.addOption(
new Option(
'-A, --all-separate',
'Export all mappings into separate JSON files in directory -D. Ignored with -i and -a.'
)
)
.addOption(
new Option(
'-N, --no-metadata',
'Does not include metadata in the export file.'
)
)
.addOption(
new Option('--no-deps', 'Do not include any dependencies in export.')
)
.addOption(
new Option(
'--use-string-arrays',
'Where applicable, use string arrays to store multi-line text (e.g. scripts).'
).default(false, 'off')
)
.action(
// implement command logic inside action handler
async (host, realm, user, password, options, command) => {
command.handleDefaultArgsAndOpts(
host,
realm,
user,
password,
options,
command
);
// export by id/name
if (options.mappingId && (await getTokens())) {
verboseMessage(`Exporting mapping ${options.mappingId}...`);
const outcome = await exportMappingToFile(
options.mappingId,
options.file,
options.metadata,
{
deps: options.deps,
useStringArrays: options.useStringArrays,
}
);
if (!outcome) process.exitCode = 1;
}
// --all -a
else if (options.all && (await getTokens())) {
verboseMessage(`Exporting all mappings to a single file...`);
const outcome = await exportMappingsToFile(
options.file,
options.metadata,
{
connectorId: options.connectorId,
moType: options.managedObjectType,
deps: options.deps,
useStringArrays: options.useStringArrays,
}
);
if (!outcome) process.exitCode = 1;
}
// --all-separate -A
else if (options.allSeparate && (await getTokens())) {
verboseMessage('Exporting all mappings to separate files...');
const outcome = await exportMappingsToFiles(options.metadata, {
connectorId: options.connectorId,
moType: options.managedObjectType,
deps: options.deps,
useStringArrays: options.useStringArrays,
});
if (!outcome) process.exitCode = 1;
}
// unrecognized combination of options or no options
else {
printMessage(
'Unrecognized combination of options or no options...',
'error'
);
program.help();
process.exitCode = 1;
}
}
// end command logic inside action handler
);

return program;
}
101 changes: 101 additions & 0 deletions src/cli/mapping/mapping-import.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { Option } from 'commander';

import { getTokens } from '../../ops/AuthenticateOps';
import {
importFirstMappingFromFile,
importMappingFromFile,
importMappingsFromFile,
importMappingsFromFiles,
} from '../../ops/MappingOps';
import { printMessage, verboseMessage } from '../../utils/Console';
import { FrodoCommand } from '../FrodoCommand';

export default function setup() {
const program = new FrodoCommand('frodo mapping import');

program
.description('Import IDM mappings.')
.addOption(
new Option(
'-i, --mapping-id <mapping-id>',
'Mapping id. If specified, only one mapping is imported and the options -a and -A are ignored.'
)
)
.addOption(new Option('-f, --file <file>', 'Name of the file to import'))
.addOption(
new Option(
'-a, --all',
'Import all mappings from single file. Ignored with -i.'
)
)
.addOption(
new Option(
'-A, --all-separate',
'Import all mappings from separate files (*.sync.json or *.mapping.json) in the current directory. Ignored with -i and -a.'
)
)
.addOption(new Option('--no-deps', 'Do not include any dependencies.'))
.action(
// implement command logic inside action handler
async (host, realm, user, password, options, command) => {
command.handleDefaultArgsAndOpts(
host,
realm,
user,
password,
options,
command
);
// import by id/name
if (options.mappingId && (await getTokens())) {
verboseMessage(`Importing mapping ${options.mappingId}...`);
const outcome = await importMappingFromFile(
options.mappingId,
options.file,
{
deps: options.deps,
}
);
if (!outcome) process.exitCode = 1;
}
// --all -a
else if (options.all && options.file && (await getTokens())) {
verboseMessage(
`Importing all mappings from a single file (${options.file})...`
);
const outcome = await importMappingsFromFile(options.file, {
deps: options.deps,
});
if (!outcome) process.exitCode = 1;
}
// --all-separate -A
else if (options.allSeparate && (await getTokens())) {
verboseMessage('Importing all mappings from separate files...');
const outcome = await importMappingsFromFiles({
deps: options.deps,
});
if (!outcome) process.exitCode = 1;
}
// import first mapping in file
else if (options.file && (await getTokens())) {
verboseMessage('Importing first mapping in file...');
const outcome = await importFirstMappingFromFile(options.file, {
deps: options.deps,
});
if (!outcome) process.exitCode = 1;
}
// unrecognized combination of options or no options
else {
printMessage(
'Unrecognized combination of options or no options...',
'error'
);
program.help();
process.exitCode = 1;
}
}
// end command logic inside action handler
);

return program;
}
Loading

0 comments on commit 7e0cf9c

Please sign in to comment.