diff --git a/src/commands/aws/parameterstore/bulk-create/bulk-create.ts b/src/commands/aws/parameterstore/bulk-create/bulk-create.ts new file mode 100644 index 0000000..4c84608 --- /dev/null +++ b/src/commands/aws/parameterstore/bulk-create/bulk-create.ts @@ -0,0 +1,175 @@ +import { GluegunMenuToolbox } from '@lenne.tech/gluegun-menu'; +import chalk = require('chalk'); +import { defaultMenuSettings } from '../../../../globals'; +const { Select } = require('enquirer'); + +module.exports = { + name: 'bulk-create', + alias: ['bc'], + description: 'Bulk create parameters from JSON file (a ps bc)', + hidden: false, + run: async (toolbox: GluegunMenuToolbox) => { + const { prompt, system, strings, print, filesystem } = toolbox; + + // Get JSON file path + const filePathResponse = await prompt.ask({ + type: 'input', + name: 'path', + message: 'Path to JSON file:', + validate: (value) => { + if (!value) return 'File path is required'; + return true; + }, + }); + + const filePath = filePathResponse.path; + + // Read and parse JSON file + let parameters: { [key: string]: string }; + try { + const fileContent = await filesystem.read(filePath); + if (!fileContent) { + print.error(chalk.red(`File not found: ${filePath}`)); + return; + } + parameters = JSON.parse(fileContent); + + if (typeof parameters !== 'object' || Array.isArray(parameters)) { + print.error(chalk.red('JSON file must contain a key-value object')); + return; + } + + const paramCount = Object.keys(parameters).length; + if (paramCount === 0) { + print.error(chalk.red('JSON file contains no parameters')); + return; + } + + print.info(chalk.blue(`Found ${paramCount} parameter(s) in file`)); + } catch (error) { + print.error( + chalk.red(`Failed to read or parse JSON file: ${error.message}`), + ); + return; + } + + // Statistics tracking + let createdCount = 0; + let skippedCount = 0; + let failedCount = 0; + let cancelledAll = false; + + // Process each parameter + for (const [name, value] of Object.entries(parameters)) { + if (cancelledAll) { + break; + } + + print.newline(); + print.info(chalk.cyan(`Processing parameter: ${chalk.yellow(name)}`)); + + // Check if parameter already exists + try { + const checkResult = JSON.parse( + strings.trim( + await system.run( + `aws ssm get-parameter --name "${name}" --with-decryption`, + ), + ), + ); + + if (checkResult.Parameter) { + print.warning( + chalk.yellow(`Parameter "${name}" already exists. Skipping...`), + ); + skippedCount++; + continue; + } + } catch (error) { + // If the parameter doesn't exist, AWS CLI will throw an error + if (!error.message.includes('ParameterNotFound')) { + print.error( + chalk.red(`Error checking parameter "${name}": ${error.message}`), + ); + failedCount++; + continue; + } + // Parameter doesn't exist, continue with creation flow + } + + // Ask if parameter should be secure + const secureParameter = await prompt.confirm( + `Should ${chalk.yellow(name)} be a secure parameter?`, + ); + + const parameterType = secureParameter ? 'SecureString' : 'String'; + + // Show the AWS CLI command + const awsCommand = `aws ssm put-parameter --name "${name}" --value "${value}" --type ${parameterType}`; + print.info(chalk.gray(`Command: ${awsCommand}`)); + + // Ask for confirmation with Yes/No/Skip options + const selectPrompt = new Select({ + name: 'action', + message: `Create ${chalk.yellow(name)} with value ${chalk.green(value)} as ${chalk.red(parameterType)}?`, + choices: [ + { name: 'yes', message: 'Yes' }, + { name: 'skip', message: 'Skip (continue to next)' }, + { name: 'no', message: 'No (cancel all)' }, + ], + }); + + let action: string; + try { + action = await selectPrompt.run(); + } catch (error) { + // User cancelled (Ctrl+C) + print.info(chalk.yellow('\nOperation cancelled by user')); + cancelledAll = true; + break; + } + + if (action === 'yes') { + // Create the parameter + try { + await system.run( + `aws ssm put-parameter --name "${name}" --value "${value}" --type ${parameterType}`, + ); + print.success( + chalk.green( + `✓ Parameter "${name}" created successfully as ${parameterType}`, + ), + ); + createdCount++; + } catch (error) { + print.error( + chalk.red( + `✗ Failed to create parameter "${name}": ${error.message}`, + ), + ); + failedCount++; + } + } else if (action === 'skip') { + print.info(chalk.yellow(`Skipped parameter "${name}"`)); + skippedCount++; + } else if (action === 'no') { + print.info(chalk.yellow('Cancelled all remaining operations')); + cancelledAll = true; + break; + } + } + + // Display summary + print.newline(); + print.info(chalk.cyan('=== Summary ===')); + print.info(`${chalk.green('Created:')} ${createdCount}`); + print.info(`${chalk.yellow('Skipped:')} ${skippedCount}`); + if (failedCount > 0) { + print.info(`${chalk.red('Failed:')} ${failedCount}`); + } + + if (toolbox.fromMenu()) { + await toolbox.menu.showMenu('aws parameterstore', defaultMenuSettings); + } + }, +};