diff --git a/docs/non_containerized_NSFS.md b/docs/non_containerized_NSFS.md index 296a58d083..02cde97a3f 100644 --- a/docs/non_containerized_NSFS.md +++ b/docs/non_containerized_NSFS.md @@ -474,24 +474,43 @@ NSFS management CLI run will create both accounts, access_keys, and buckets dire Using `from_file` flag: - For account and bucket creation users can also pass account or bucket values in JSON file (hereinafter referred to as "options JSON file") instead of passing them in CLI as arguments using flags. - General use: -``` + +```bash sudo node src/cmd/manage_nsfs account add --config_root ../standalon/config_root --from_file sudo node src/cmd/manage_nsfs bucket add --config_root ../standalon/config_root --from_file ``` -- The options are key-value, where the key is the same as suggested flags. For example: -create JSON file for account: + +- The options are key-value, where the key is the same as suggested flags, for example: + +(1) Create JSON file for account + ```json -// JSON file of key-value options for creating an account { "name": "account-1001", "uid": 1001, "gid": 1001, - "new_buckets_path": "/tmp/nsfs_root1/my-bucket" + "new_buckets_path": "/tmp/nsfs_root1" } ``` + +```bash +sudo node src/cmd/manage_nsfs account add --config_root ../standalon/config_root --from_file ``` -sudo node src/cmd/manage_nsfs account add --config_root ../standalon/config_root --from_file + +(2) Create JSON file for bucket: + +```json +{ + "name": "account-1001-bucket-1", + "owner": "account-1001", + "path": "/tmp/nsfs_root1/account-1001-bucket-1" +} ``` + +``` +sudo node src/cmd/manage_nsfs bucket add --config_root ../standalon/config_root --from_file +``` + - When using `from_file` flag the details about the account/bucket should be only inside the options JSON file. - The JSON config file and JSON options file of account are different! diff --git a/src/cmd/manage_nsfs.js b/src/cmd/manage_nsfs.js index acb1adc97f..eb46442adb 100644 --- a/src/cmd/manage_nsfs.js +++ b/src/cmd/manage_nsfs.js @@ -103,9 +103,7 @@ async function main(argv = minimist(process.argv.slice(2))) { if (type === TYPES.ACCOUNT) { await account_management(action, user_input); } else if (type === TYPES.BUCKET) { - // GAP - from-file in bucket - const path_to_json_options = argv.from_file ? String(argv.from_file) : ''; - await bucket_management(argv, path_to_json_options); + await bucket_management(action, user_input); } else if (type === TYPES.IP_WHITELIST) { await whitelist_ips_management(argv); } else if (type === TYPES.GLACIER) { @@ -124,50 +122,44 @@ async function main(argv = minimist(process.argv.slice(2))) { } } -async function bucket_management(argv, from_file) { - const action = argv._[1] || ''; - const data = await fetch_bucket_data(argv, from_file); - await manage_bucket_operations(action, data, argv); +async function bucket_management(action, user_input) { + const data = await fetch_bucket_data(action, user_input); + await manage_bucket_operations(action, data, user_input); } // in name and new_name we allow type number, hence convert it to string -async function fetch_bucket_data(argv, from_file) { - const action = argv._[1] || ''; - let data; - if (from_file) { - const fs_context = native_fs_utils.get_process_fs_context(); - const raw_data = (await nb_native().fs.readFile(fs_context, from_file)).data; - data = JSON.parse(raw_data.toString()); - // GAP - from-file is not validated - } - if (!data) { +async function fetch_bucket_data(action, user_input) { + let data = { // added undefined values to keep the order the properties when printing the data object - data = { - _id: undefined, - name: _.isUndefined(argv.name) ? undefined : String(argv.name), - owner_account: undefined, - system_owner: argv.owner, // GAP - needs to be the system_owner (currently it is the account name) - bucket_owner: argv.owner, - wide: _.isUndefined(argv.wide) ? undefined : get_boolean_or_string_value(argv.wide), - tag: undefined, // if we would add the option to tag a bucket using CLI, this should be changed - versioning: action === ACTIONS.ADD ? 'DISABLED' : undefined, - creation_date: action === ACTIONS.ADD ? new Date().toISOString() : undefined, - path: argv.path, - should_create_underlying_storage: action === ACTIONS.ADD ? false : undefined, - new_name: _.isUndefined(argv.new_name) ? undefined : String(argv.new_name), - fs_backend: _.isUndefined(argv.fs_backend) ? config.NSFS_NC_STORAGE_BACKEND : String(argv.fs_backend) + _id: undefined, + name: _.isUndefined(user_input.name) ? undefined : String(user_input.name), + owner_account: undefined, + system_owner: user_input.owner, // GAP - needs to be the system_owner (currently it is the account name) + bucket_owner: user_input.owner, + wide: _.isUndefined(user_input.wide) ? undefined : get_boolean_or_string_value(user_input.wide), + tag: undefined, // if we would add the option to tag a bucket using CLI, this should be changed + versioning: action === ACTIONS.ADD ? 'DISABLED' : undefined, + creation_date: action === ACTIONS.ADD ? new Date().toISOString() : undefined, + path: user_input.path, + should_create_underlying_storage: action === ACTIONS.ADD ? false : undefined, + new_name: _.isUndefined(user_input.new_name) ? undefined : String(user_input.new_name), + fs_backend: _.isUndefined(user_input.fs_backend) ? config.NSFS_NC_STORAGE_BACKEND : String(user_input.fs_backend) }; - } - if (argv.bucket_policy !== undefined) { - // bucket_policy deletion speficied with empty string '' - if (argv.bucket_policy === '') { - data.s3_policy = ''; - } else { - data.s3_policy = JSON.parse(argv.bucket_policy.toString()); + if (user_input.bucket_policy !== undefined) { + if (typeof user_input.bucket_policy === 'string') { + // bucket_policy deletion specified with empty string '' + if (user_input.bucket_policy === '') { + data.s3_policy = ''; + } else { + data.s3_policy = JSON.parse(user_input.bucket_policy.toString()); + } + } else { // it is object type + data.s3_policy = user_input.bucket_policy; } } if (action === ACTIONS.UPDATE || action === ACTIONS.DELETE) { + // @ts-ignore data = _.omitBy(data, _.isUndefined); data = await fetch_existing_bucket_data(data); } @@ -316,7 +308,7 @@ async function delete_bucket(data) { write_stdout_response(ManageCLIResponse.BucketDeleted, '', {bucket: data.name}); } -async function manage_bucket_operations(action, data, argv) { +async function manage_bucket_operations(action, data, user_input) { if (action === ACTIONS.ADD) { await add_bucket(data); } else if (action === ACTIONS.STATUS) { @@ -326,7 +318,7 @@ async function manage_bucket_operations(action, data, argv) { } else if (action === ACTIONS.DELETE) { await delete_bucket(data); } else if (action === ACTIONS.LIST) { - const bucket_filters = _.pick(argv, LIST_BUCKET_FILTERS); + const bucket_filters = _.pick(user_input, LIST_BUCKET_FILTERS); const buckets = await list_config_files(TYPES.BUCKET, buckets_dir_path, data.wide, undefined, bucket_filters); write_stdout_response(ManageCLIResponse.BucketList, buckets); } else { @@ -847,7 +839,7 @@ async function validate_input_types(type, action, argv) { // currently we use from_file only in add action const path_to_json_options = argv.from_file ? String(argv.from_file) : ''; - if (type === TYPES.ACCOUNT && action === ACTIONS.ADD && path_to_json_options) { + if ((type === TYPES.ACCOUNT || type === TYPES.BUCKET) && action === ACTIONS.ADD && path_to_json_options) { const input_options_with_data_from_file = await get_options_from_file(path_to_json_options); const input_options_from_file = Object.keys(input_options_with_data_from_file); if (input_options_from_file.includes(FROM_FILE)) { @@ -894,16 +886,18 @@ function validate_no_extra_options(type, action, input_options, is_options_from_ valid_options = VALID_OPTIONS.bucket_options[action]; } else if (type === TYPES.ACCOUNT) { valid_options = VALID_OPTIONS.account_options[action]; - if (is_options_from_file) { - valid_options.delete('from_file'); - valid_options.delete('config_root'); - valid_options.delete('config_root_backend'); - } } else if (type === TYPES.GLACIER) { valid_options = VALID_OPTIONS.glacier_options[action]; } else { valid_options = VALID_OPTIONS.whitelist_options; } + + if (is_options_from_file) { + valid_options.delete('from_file'); + valid_options.delete('config_root'); + valid_options.delete('config_root_backend'); + } + const invalid_input_options = input_options.filter(element => !valid_options.has(element)); if (invalid_input_options.length > 0) { const type_and_action = type === TYPES.IP_WHITELIST ? type : `${type} ${action}`; @@ -933,6 +927,10 @@ function validate_options_type_by_value(input_options_with_data) { if (['allow_bucket_creation', 'regenerate', 'wide', 'show_secrets'].includes(option) && validate_boolean_string_value(value)) { continue; } + // special case for bucket_policy (from_file) + if (option === 'bucket_policy' && type_of_value === 'object') { + continue; + } const details = `type of flag ${option} should be ${type_of_option}`; throw_cli_error(ManageCLIError.InvalidArgumentType, details); } diff --git a/src/test/unit_tests/jest_tests/test_nc_nsfs_account_cli.test.js b/src/test/unit_tests/jest_tests/test_nc_nsfs_account_cli.test.js index 6ad7d22353..ad2678c94d 100644 --- a/src/test/unit_tests/jest_tests/test_nc_nsfs_account_cli.test.js +++ b/src/test/unit_tests/jest_tests/test_nc_nsfs_account_cli.test.js @@ -970,7 +970,7 @@ describe('manage nsfs cli account flow', () => { // write the json_file_options const path_to_option_json_file_name = await create_json_account_options(path_to_json_account_options_dir, account_options); const command_flags = {config_root, from_file: path_to_option_json_file_name}; - // create tha account and check the details + // create the account and check the details await exec_manage_cli(type, action, command_flags); // compare the details const account = await read_config_file(config_root, CONFIG_SUBDIRS.ACCOUNTS, name); @@ -984,7 +984,7 @@ describe('manage nsfs cli account flow', () => { // write the json_file_options const path_to_option_json_file_name = await create_json_account_options(path_to_json_account_options_dir, account_options); const command_flags = {config_root, from_file: path_to_option_json_file_name}; - // create tha account and check the details + // create the account and check the details await exec_manage_cli(type, action, command_flags); // compare the details const account = await read_config_file(config_root, CONFIG_SUBDIRS.ACCOUNTS, name); @@ -1002,7 +1002,7 @@ describe('manage nsfs cli account flow', () => { // write the json_file_options const path_to_option_json_file_name = await create_json_account_options(path_to_json_account_options_dir, account_options); const command_flags = {config_root, from_file: path_to_option_json_file_name}; - // create tha account and check the details + // create the account const res = await exec_manage_cli(type, action, command_flags); expect(JSON.parse(res.stdout).error.code).toBe(ManageCLIError.AccountAccessKeyFlagComplexity.code); }); @@ -1014,7 +1014,7 @@ describe('manage nsfs cli account flow', () => { // write the json_file_options const path_to_option_json_file_name = await create_json_account_options(path_to_json_account_options_dir, account_options); const command_flags = {config_root, from_file: path_to_option_json_file_name, name }; // name should be in file only - // create tha account and check the details + // create the account const res = await exec_manage_cli(type, action, command_flags); expect(JSON.parse(res.stdout).error.code).toBe(ManageCLIError.InvalidArgument.code); }); @@ -1026,7 +1026,7 @@ describe('manage nsfs cli account flow', () => { // write the json_file_options const path_to_option_json_file_name = await create_json_account_options(path_to_json_account_options_dir, account_options); const command_flags = {config_root, from_file: path_to_option_json_file_name}; - // create tha account and check the details + // create the account const res = await exec_manage_cli(type, action, command_flags); expect(JSON.parse(res.stdout).error.code).toBe(ManageCLIError.InvalidArgument.code); }); @@ -1038,7 +1038,7 @@ describe('manage nsfs cli account flow', () => { // write the json_file_options const path_to_option_json_file_name = await create_json_account_options(path_to_json_account_options_dir, account_options); const command_flags = {config_root, from_file: path_to_option_json_file_name}; - // create tha account and check the details + // create the account const res = await exec_manage_cli(type, action, command_flags); expect(JSON.parse(res.stdout).error.code).toBe(ManageCLIError.InvalidArgument.code); }); @@ -1050,7 +1050,7 @@ describe('manage nsfs cli account flow', () => { // write the json_file_options const path_to_option_json_file_name = await create_json_account_options(path_to_json_account_options_dir, account_options); const command_flags = {config_root, from_file: path_to_option_json_file_name}; - // create tha account and check the details + // create the account const res = await exec_manage_cli(type, action, command_flags); expect(JSON.parse(res.stdout).error.code).toBe(ManageCLIError.InvalidArgument.code); }); @@ -1062,7 +1062,7 @@ describe('manage nsfs cli account flow', () => { // write the json_file_options const path_to_option_json_file_name = await create_json_account_options(path_to_json_account_options_dir, account_options); const command_flags = {config_root, from_file: path_to_option_json_file_name}; - // create tha account and check the details + // create the account const res = await exec_manage_cli(type, action, command_flags); expect(JSON.parse(res.stdout).error.code).toBe(ManageCLIError.InvalidArgumentType.code); }); @@ -1085,7 +1085,7 @@ describe('manage nsfs cli account flow', () => { await fs.promises.writeFile(path_to_option_json_file_name, content); // write the json_file_options const command_flags = {config_root, from_file: path_to_option_json_file_name}; - // create tha account + // create the account await exec_manage_cli(type, action, command_flags); // compare the details const res = await exec_manage_cli(type, action, command_flags); diff --git a/src/test/unit_tests/jest_tests/test_nc_nsfs_bucket_cli.test.js b/src/test/unit_tests/jest_tests/test_nc_nsfs_bucket_cli.test.js index 44d43158be..83095ba69f 100644 --- a/src/test/unit_tests/jest_tests/test_nc_nsfs_bucket_cli.test.js +++ b/src/test/unit_tests/jest_tests/test_nc_nsfs_bucket_cli.test.js @@ -5,11 +5,13 @@ // disabling init_rand_seed as it takes longer than the actual test execution process.env.DISABLE_INIT_RANDOM_SEED = "true"; +const fs = require('fs'); const path = require('path'); const os_util = require('../../../util/os_utils'); const fs_utils = require('../../../util/fs_utils'); const config_module = require('../../../../config'); -const { set_path_permissions_and_owner, TMP_PATH } = require('../../system_tests/test_utils'); +const nb_native = require('../../../util/nb_native'); +const { set_path_permissions_and_owner, TMP_PATH, generate_s3_policy } = require('../../system_tests/test_utils'); const { ACTIONS, TYPES, CONFIG_SUBDIRS } = require('../../../manage_nsfs/manage_nsfs_constants'); const { get_process_fs_context, is_path_exists } = require('../../../util/native_fs_utils'); const ManageCLIError = require('../../../manage_nsfs/manage_nsfs_cli_errors').ManageCLIError; @@ -17,17 +19,13 @@ const ManageCLIError = require('../../../manage_nsfs/manage_nsfs_cli_errors').Ma const tmp_fs_path = path.join(TMP_PATH, 'test_bucketspace_fs'); const DEFAULT_FS_CONFIG = get_process_fs_context(); -let bucket_storage_path; -let bucket_temp_dir_path; - - // eslint-disable-next-line max-lines-per-function describe('manage nsfs cli bucket flow', () => { describe('cli create bucket', () => { const config_root = path.join(tmp_fs_path, 'config_root_manage_nsfs'); const root_path = path.join(tmp_fs_path, 'root_path_manage_nsfs/'); - bucket_storage_path = path.join(tmp_fs_path, 'root_path_manage_nsfs', 'bucket1'); + const bucket_storage_path = path.join(tmp_fs_path, 'root_path_manage_nsfs', 'bucket1'); const account_defaults = { name: 'account_test', @@ -85,7 +83,8 @@ describe('manage nsfs cli bucket flow', () => { describe('cli delete bucket', () => { const config_root = path.join(tmp_fs_path, 'config_root_manage_nsfs2'); const root_path = path.join(tmp_fs_path, 'root_path_manage_nsfs2/'); - bucket_storage_path = path.join(tmp_fs_path, 'root_path_manage_nsfs2', 'bucket1'); + const bucket_storage_path = path.join(tmp_fs_path, 'root_path_manage_nsfs2', 'bucket1'); + let bucket_temp_dir_path; const account_name = 'account_test'; const account_defaults = { @@ -165,6 +164,171 @@ describe('manage nsfs cli bucket flow', () => { }); }); +describe('cli create bucket using from_file', () => { + const type = TYPES.BUCKET; + const config_root = path.join(tmp_fs_path, 'config_root_manage_nsfs3'); + const root_path = path.join(tmp_fs_path, 'root_path_manage_nsfs3/'); + const bucket_storage_path = path.join(tmp_fs_path, 'root_path_manage_nsfs3', 'bucket1'); + const path_to_json_bucket_options_dir = path.join(tmp_fs_path, 'options'); + + const account_name = 'account_test'; + const account_defaults = { + name: account_name, + new_buckets_path: `${root_path}new_buckets_path_user1/`, + uid: 1001, + gid: 1001, + }; + + const bucket_defaults = { + name: 'bucket1', + owner: account_name, + path: bucket_storage_path, + }; + + beforeEach(async () => { + await fs_utils.create_fresh_path(`${config_root}/${CONFIG_SUBDIRS.BUCKETS}`); + await fs_utils.create_fresh_path(root_path); + await fs_utils.create_fresh_path(bucket_storage_path); + await fs_utils.create_fresh_path(path_to_json_bucket_options_dir); + const action = ACTIONS.ADD; + // account add + const { new_buckets_path: account_path } = account_defaults; + const account_options = { config_root, ...account_defaults }; + await fs_utils.create_fresh_path(account_path); + await fs_utils.file_must_exist(account_path); + await set_path_permissions_and_owner(account_path, account_options, 0o700); + await exec_manage_cli(TYPES.ACCOUNT, action, account_options); + }); + + afterEach(async () => { + await fs_utils.folder_delete(`${config_root}`); + await fs_utils.folder_delete(`${root_path}`); + await fs_utils.folder_delete(`${path_to_json_bucket_options_dir}`); + }); + + it('cli create bucket using from_file with required options', async () => { + const action = ACTIONS.ADD; + const bucket_options = { name: bucket_defaults.name, owner: bucket_defaults.owner, path: bucket_defaults.path }; + // write the json_file_options + const path_to_option_json_file_name = await create_json_bucket_options(path_to_json_bucket_options_dir, bucket_options); + const command_flags = {config_root, from_file: path_to_option_json_file_name}; + // create tha bucket and check the details + await exec_manage_cli(type, action, command_flags); + // compare the details + const bucket = await read_config_file(config_root, CONFIG_SUBDIRS.BUCKETS, bucket_defaults.name); + assert_bucket(bucket, bucket_options); + }); + + it('cli create bucket using from_file with optional options (fs_backend)', async () => { + const action = ACTIONS.ADD; + const fs_backend = 'GPFS'; + const bucket_options = { name: bucket_defaults.name, owner: bucket_defaults.owner, path: bucket_defaults.path, + fs_backend: fs_backend }; + // write the json_file_options + const path_to_option_json_file_name = await create_json_bucket_options(path_to_json_bucket_options_dir, bucket_options); + const command_flags = {config_root, from_file: path_to_option_json_file_name}; + // create tha bucket and check the details + await exec_manage_cli(type, action, command_flags); + // compare the details + const bucket = await read_config_file(config_root, CONFIG_SUBDIRS.BUCKETS, bucket_defaults.name); + assert_bucket(bucket, bucket_options); + expect(bucket.fs_backend).toEqual(bucket_options.fs_backend); + }); + + it('cli create bucket using from_file with optional options (bucket_policy)', async () => { + const action = ACTIONS.ADD; + const bucket_policy = generate_s3_policy('*', bucket_defaults.name, ['s3:*']).policy; + const bucket_options = { name: bucket_defaults.name, owner: bucket_defaults.owner, path: bucket_defaults.path, + bucket_policy: bucket_policy }; + // write the json_file_options + const path_to_option_json_file_name = await create_json_bucket_options(path_to_json_bucket_options_dir, bucket_options); + const command_flags = {config_root, from_file: path_to_option_json_file_name}; + // create tha bucket and check the details + await exec_manage_cli(type, action, command_flags); + // compare the details + const bucket = await read_config_file(config_root, CONFIG_SUBDIRS.BUCKETS, bucket_defaults.name); + assert_bucket(bucket, bucket_options); + expect(bucket.bucket_policy).toEqual(bucket_options.s3_policy); + }); + + it('should fail - cli create bucket using from_file with additional flags (name)', async () => { + const action = ACTIONS.ADD; + const name = bucket_defaults.name; + // write the json_file_options + const path_to_option_json_file_name = await create_json_bucket_options(path_to_json_bucket_options_dir, bucket_defaults); + const command_flags = {config_root, from_file: path_to_option_json_file_name, name }; // name should be in file only + const res = await exec_manage_cli(type, action, command_flags); + expect(JSON.parse(res.stdout).error.code).toBe(ManageCLIError.InvalidArgument.code); + }); + + it('should fail - cli create bucket using from_file with invalid option (lala) in the file', async () => { + const action = ACTIONS.ADD; + const bucket_options = { name: bucket_defaults.name, owner: bucket_defaults.owner, path: bucket_defaults.path, lala: 'lala'}; // lala invalid option + // write the json_file_options + const path_to_option_json_file_name = await create_json_bucket_options(path_to_json_bucket_options_dir, bucket_options); + const command_flags = {config_root, from_file: path_to_option_json_file_name }; + const res = await exec_manage_cli(type, action, command_flags); + expect(JSON.parse(res.stdout).error.code).toBe(ManageCLIError.InvalidArgument.code); + }); + + it('should fail - cli create bucket using from_file with invalid option (creation_date) in the file', async () => { + const action = ACTIONS.ADD; + const bucket_options = { name: bucket_defaults.name, owner: bucket_defaults.owner, path: bucket_defaults.path, + creation_date: new Date().toISOString()}; // creation_date invalid option (user cannot set it) + // write the json_file_options + const path_to_option_json_file_name = await create_json_bucket_options(path_to_json_bucket_options_dir, bucket_options); + const command_flags = {config_root, from_file: path_to_option_json_file_name }; + const res = await exec_manage_cli(type, action, command_flags); + expect(JSON.parse(res.stdout).error.code).toBe(ManageCLIError.InvalidArgument.code); + }); + + it('should fail - cli create bucket using from_file with from_file inside the JSON file', async () => { + const action = ACTIONS.ADD; + const bucket_options = { name: bucket_defaults.name, owner: bucket_defaults.owner, path: bucket_defaults.path, + from_file: 'blabla' }; //from_file inside options JSON file + // write the json_file_options + const path_to_option_json_file_name = await create_json_bucket_options(path_to_json_bucket_options_dir, bucket_options); + const command_flags = {config_root, from_file: path_to_option_json_file_name }; + const res = await exec_manage_cli(type, action, command_flags); + expect(JSON.parse(res.stdout).error.code).toBe(ManageCLIError.InvalidArgument.code); + }); + + it('should fail - cli create bucket using from_file with invalid option type (in the file)', async () => { + const action = ACTIONS.ADD; + const bucket_options = { name: bucket_defaults.name, owner: 1234, path: bucket_defaults.path }; // owner should be string (not number) + // write the json_file_options + const path_to_option_json_file_name = await create_json_bucket_options(path_to_json_bucket_options_dir, bucket_options); + const command_flags = {config_root, from_file: path_to_option_json_file_name }; + const res = await exec_manage_cli(type, action, command_flags); + expect(JSON.parse(res.stdout).error.code).toBe(ManageCLIError.InvalidArgumentType.code); + }); + + it('should fail - cli create bucket using from_file with invalid path', async () => { + const action = ACTIONS.ADD; + const command_flags = {config_root, from_file: 'blabla'}; //invalid path + const res = await exec_manage_cli(type, action, command_flags); + expect(JSON.parse(res.stdout).error.code).toBe(ManageCLIError.InvalidFilePath.code); + }); + + it('should fail - cli create bucket using from_file with invalid JSON file', async () => { + const action = ACTIONS.ADD; + const bucket_options = { name: bucket_defaults.name, owner: bucket_defaults.owner, path: bucket_defaults.path }; + // write invalid json_file_options + const option_json_file_name = `${bucket_options.name}_options.json`; + const path_to_option_json_file_name = path.join(path_to_json_bucket_options_dir, option_json_file_name); + const content = JSON.stringify(bucket_options) + 'blabla'; // invalid JSON + await fs.promises.writeFile(path_to_option_json_file_name, content); + // write the json_file_options + const command_flags = {config_root, from_file: path_to_option_json_file_name}; + // create tha bucket + await exec_manage_cli(type, action, command_flags); + // compare the details + const res = await exec_manage_cli(type, action, command_flags); + expect(JSON.parse(res.stdout).error.code).toBe(ManageCLIError.InvalidJSONFile.code); + }); + +}); + /** * exec_manage_cli will get the flags for the cli and runs the cli with it's flags * @param {string} type @@ -194,3 +358,40 @@ async function exec_manage_cli(type, action, options) { return res; } +/** + * read_config_file will read the config files + * @param {string} config_root + * @param {string} schema_dir + * @param {string} config_file_name the name of the config file + * @param {boolean} [is_symlink] a flag to set the suffix as a symlink instead of json + */ +async function read_config_file(config_root, schema_dir, config_file_name, is_symlink) { + const config_path = path.join(config_root, schema_dir, config_file_name + (is_symlink ? '.symlink' : '.json')); + const { data } = await nb_native().fs.readFile(DEFAULT_FS_CONFIG, config_path); + const config = JSON.parse(data.toString()); + return config; +} + +/** + * create_json_bucket_options would create a JSON file with the options (key-value) inside file + * @param {string} path_to_json_bucket_options_dir + * @param {object} bucket_options + */ +async function create_json_bucket_options(path_to_json_bucket_options_dir, bucket_options) { + const option_json_file_name = `${bucket_options.name}_options.json`; + const path_to_option_json_file_name = path.join(path_to_json_bucket_options_dir, option_json_file_name); + const content = JSON.stringify(bucket_options); + await fs.promises.writeFile(path_to_option_json_file_name, content); + return path_to_option_json_file_name; +} + +/** + * assert_bucket will verify the fields of the buckets (only required fields) + * @param {object} bucket + * @param {object} bucket_options + */ +function assert_bucket(bucket, bucket_options) { + expect(bucket.name).toEqual(bucket_options.name); + expect(bucket.bucket_owner).toEqual(bucket_options.owner); + expect(bucket.path).toEqual(bucket_options.path); +}