Skip to content
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
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@
"@modelcontextprotocol/client": "^2.0.0",
"@modelcontextprotocol/node": "^2.0.0",
"@modelcontextprotocol/server": "^2.0.0",
"@rockcarver/frodo-lib": "4.3.3",
"@rockcarver/frodo-lib": "4.4.0",
"@types/colors": "^1.2.1",
"@types/fs-extra": "^11.0.1",
"@types/jest": "^29.2.3",
Expand Down
65 changes: 64 additions & 1 deletion src/cli/FrodoCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { frodo, FrodoError, state } from '@rockcarver/frodo-lib';
import { RetryStrategy } from '@rockcarver/frodo-lib/types/api/BaseApi.js';
import { AddHelpTextContext, Argument, Command, Help, Option } from 'commander';
import fs from 'fs';
import propertiesReader from 'properties-reader';

import {
cleanupProgressIndicators,
Expand Down Expand Up @@ -427,6 +428,19 @@ function cloneArgument(argument: Argument): Argument {
return cloned;
}

/**
* Option that collects repeated values into an array.
*/
export class ListOption extends Option {
constructor(flags: string, description?: string) {
super(flags, description);
this.argParser((value: string, previous: string[] = []) => {
previous.push(value);
return previous;
}).default([]);
}
}

export const hostArgument = new Argument(
'[host]',
'AM base URL, e.g.: https://cdk.iam.example.com/am. To use a connection profile, just specify a unique substring or alias.'
Expand Down Expand Up @@ -523,6 +537,22 @@ const directoryOption = withHelpGroup(
RUNTIME_OPTIONS_HEADING
);

const envOption = withHelpGroup(
new ListOption(
'-E, --env <key=value>',
'Set an environment variable for placeholder resolution. May be specified multiple times. Overrides values from --env-file.'
),
RUNTIME_OPTIONS_HEADING
);

const envFileOption = withHelpGroup(
new ListOption(
'--env-file <file>',
'Read environment variables from a file for placeholder resolution. May be specified multiple times; later files override earlier ones.'
),
RUNTIME_OPTIONS_HEADING
);

const insecureOption = withHelpGroup(
new Option(
'-k, --insecure',
Expand Down Expand Up @@ -631,6 +661,8 @@ const defaultOpts = [
flushCacheOption,
retryOption,
useRealmPrefixOnManagedObjects,
envOption,
envFileOption,
];

/**
Expand Down Expand Up @@ -715,6 +747,31 @@ const stateMap = {
[retryOption.attributeName()]: (strategy: RetryStrategy) => {
state.setAxiosRetryStrategy(strategy);
},
[envFileOption.attributeName()]: (files: string[]) => {
for (const filePath of files) {
try {
propertiesReader(filePath).each((key: string, value: string) => {
state.setEnv(key, value);
});
} catch (error) {
throw new FrodoError(`Error parsing env file ${filePath}`, error);
}
}
},
[envOption.attributeName()]: (envs: string[]) => {
for (const env of envs) {
const separatorIndex = env.indexOf('=');
if (separatorIndex < 0) {
throw new FrodoError(
`Invalid env format; expected "key=value" but got "${env}"`
);
}
state.setEnv(
env.substring(0, separatorIndex),
env.substring(separatorIndex + 1)
);
}
},
};

/**
Expand Down Expand Up @@ -2449,7 +2506,13 @@ export class FrodoCommand extends FrodoStubCommand {
}

// handle options
for (const [k, v] of Object.entries(options)) {
for (const [k, v] of Object.entries(options).sort(([k1], [k2]) => {
if (k1 === envFileOption.attributeName()) return -1;
if (k2 === envFileOption.attributeName()) return 1;
if (k1 === envOption.attributeName()) return -1;
if (k2 === envOption.attributeName()) return 1;
return 0;
})) {
// handle only default options
if (Object.keys(stateMap).includes(k)) {
debugMessage(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export default function setup() {

if (await getTokens(false, true, deploymentTypes)) {
verboseMessage('Exporting config entity access-config');
const outcome = await configManagerExportAccessConfig(options.envFile);
const outcome = await configManagerExportAccessConfig();
if (!outcome) process.exitCode = 1;
}
// unrecognized combination of options or no options
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export default function setup() {

if (await getTokens(false, true, deploymentTypes)) {
verboseMessage('Exporting config entity audit');
const outcome = await configManagerExportAudit(options.envFile);
const outcome = await configManagerExportAudit();
if (!outcome) process.exitCode = 1;
}
// unrecognized combination of options or no options
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export default function setup() {

if (await getTokens(false, true, deploymentTypes)) {
verboseMessage('Exporting config entity kba-config');
const outcome = await configManagerExportKbaConfig(options.envFile);
const outcome = await configManagerExportKbaConfig();
if (!outcome) process.exitCode = 1;
}
// unrecognized combination of options or no options
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export default function setup() {

if (await getTokens(false, true, deploymentTypes)) {
verboseMessage('Exporting config entity remote-servers');
const outcome = await configManagerExportRemoteServers(options.envFile);
const outcome = await configManagerExportRemoteServers();
if (!outcome) process.exitCode = 1;
}
// unrecognized combination of options or no options
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export default function setup() {

if (await getTokens(false, true, deploymentTypes)) {
verboseMessage('Exporting config entity ui-configuration');
const outcome = await configManagerExportUiConfig(options.envFile);
const outcome = await configManagerExportUiConfig();
if (!outcome) process.exitCode = 1;
}
// unrecognized combination of options or no options
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { frodo } from '@rockcarver/frodo-lib';
import { Option } from 'commander';

import { configManagerImportVariables } from '../../../configManagerOps/FrConfigVariableOps';
import { getTokens } from '../../../ops/AuthenticateOps';
import { verboseMessage } from '../../../utils/Console';
import { FrodoCommand } from '../../FrodoCommand';

const { CLOUD_DEPLOYMENT_TYPE_KEY } = frodo.utils.constants;

const deploymentTypes = [CLOUD_DEPLOYMENT_TYPE_KEY];

export default function setup() {
const program = new FrodoCommand(
'frodo config-manager push variables',
[],
deploymentTypes
);
program
.description('Import variables.')
.addOption(
new Option(
'-n, --name <name>',
'Variable name; import only the specified variable. If omitted, all variables are imported.'
)
)

.action(async (host, realm, user, password, options, command) => {
command.handleDefaultArgsAndOpts(
host,
realm,
user,
password,
options,
command
);
const getTokensIsSuccessful = await getTokens(
false,
true,
deploymentTypes
);
if (!getTokensIsSuccessful) process.exit(1);
verboseMessage('Importing variables');
const outcome = await configManagerImportVariables(options.name);
if (!outcome) process.exitCode = 1;
});
return program;
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import ServiceObjects from './config-manager-push-service-objects';
import TermsAndConditions from './config-manager-push-terms-and-conditions';
import Themes from './config-manager-push-themes';
import UiConfig from './config-manager-push-ui-config';
import Variables from './config-manager-push-variables';

export default function setup() {
const program = new FrodoStubCommand('push').description(
Expand Down Expand Up @@ -60,6 +61,7 @@ export default function setup() {
program.addCommand(CSP().name('csp'));
program.addCommand(Restart().name('restart'));
program.addCommand(Journeys().name('journeys'));
program.addCommand(Variables().name('variables'));

return program;
}
6 changes: 1 addition & 5 deletions src/cli/idm/idm-export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,10 @@ export default function setup() {
)
.addOption(
new Option(
'-E, --entities-file [entities-file]',
'-e, --entities-file [entities-file]',
'Name of the entity file. Ignored with -i.'
)
)
.addOption(new Option('-e, --env-file [envfile]', 'Name of the env file.'))
.addOption(
new Option(
'-a, --all',
Expand Down Expand Up @@ -99,7 +98,6 @@ export default function setup() {
const outcome = await exportConfigEntityToFile(
options.entityId,
options.file,
options.envFile,
options.metadata,
options.extract
);
Expand All @@ -115,7 +113,6 @@ export default function setup() {
const outcome = await exportAllConfigEntitiesToFile(
options.file,
options.entitiesFile,
options.envFile,
options.metadata
);
if (!outcome) process.exitCode = 1;
Expand All @@ -140,7 +137,6 @@ export default function setup() {
);
const outcome = await exportAllConfigEntitiesToFiles(
options.entitiesFile,
options.envFile,
options.metadata,
options.extract
);
Expand Down
17 changes: 5 additions & 12 deletions src/cli/idm/idm-import.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,10 @@ export default function setup() {
.addOption(new Option('-f, --file [file]', 'Import file. Ignored with -A.'))
.addOption(
new Option(
'-E, --entities-file [entities-file]',
'-e, --entities-file [entities-file]',
'Name of the entity file. Ignored with -i.'
)
)
.addOption(new Option('-e, --env-file [envfile]', 'Name of the env file.'))
.addOption(
new Option(
'-a, --all',
Expand Down Expand Up @@ -103,8 +102,7 @@ export default function setup() {
);
const outcome = await importConfigEntityByIdFromFile(
options.entityId,
options.file,
options.envFile
options.file
);
if (!outcome) process.exitCode = 1;
}
Expand All @@ -119,8 +117,7 @@ export default function setup() {
);
const outcome = await importAllConfigEntitiesFromFile(
options.file,
options.entitiesFile,
options.envFile
options.entitiesFile
);
if (!outcome) process.exitCode = 1;
}
Expand All @@ -132,10 +129,7 @@ export default function setup() {
verboseMessage(
`Importing first object${envMessage}${fileMessage}...`
);
const outcome = await importFirstConfigEntityFromFile(
options.file,
options.envFile
);
const outcome = await importFirstConfigEntityFromFile(options.file);
if (!outcome) process.exitCode = 1;
}
// require --directory -D for all-separate functions
Expand All @@ -156,8 +150,7 @@ export default function setup() {
`Importing IDM configuration objects${entitiesMessage}${envMessage}${directoryMessage}`
);
const outcome = await importAllConfigEntitiesFromFiles(
options.entitiesFile,
options.envFile
options.entitiesFile
);
if (!outcome) process.exitCode = 1;
}
Expand Down
4 changes: 0 additions & 4 deletions src/cli/idm/idm-schema-object-export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ export default function setup() {
'Export file if -x or -a are included. Ignored with -A.'
)
)
.addOption(new Option('-e, --env-file [envfile]', 'Name of the env file.'))
.addOption(
new Option(
'-N, --no-metadata',
Expand Down Expand Up @@ -93,7 +92,6 @@ export default function setup() {
const outcome = await exportManagedObjectToFile(
options.individualObject,
options.file,
options.envFile,
options.extract
);
if (!outcome) process.exitCode = 1;
Expand All @@ -108,7 +106,6 @@ export default function setup() {
const outcome = await exportConfigEntityToFile(
'managed',
options.file,
options.envFile,
options.metadata,
false
);
Expand All @@ -124,7 +121,6 @@ export default function setup() {
const outcome = await exportConfigEntityToFile(
'managed',
options.file,
options.envFile,
options.metadata,
true
);
Expand Down
Loading
Loading