Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Mapping Command #403

Merged
merged 1 commit into from
Jul 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading