Skip to content

Commit 63dcad4

Browse files
authored
Merge pull request #8258 from romayalon/romy-refactor-config-dir
NC | ConfigFS Refactoring
2 parents 55d87ae + b0e7360 commit 63dcad4

20 files changed

+945
-747
lines changed

src/cmd/manage_nsfs.js

Lines changed: 78 additions & 127 deletions
Large diffs are not rendered by default.

src/manage_nsfs/diagnose.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ const ManageCLIResponse = require('../manage_nsfs/manage_nsfs_cli_responses').Ma
1515
* manage_diagnose_operations handles cli diagnose operations
1616
* @param {string} action
1717
* @param {Object} user_input
18-
* @param {Object} global_config
18+
* @param {import('../sdk/config_fs').ConfigFS} config_fs
1919
* @returns {Promise<Void>}
2020
*/
21-
async function manage_diagnose_operations(action, user_input, global_config) {
21+
async function manage_diagnose_operations(action, user_input, config_fs) {
2222
switch (action) {
2323
case DIAGNOSE_ACTIONS.HEALTH:
24-
await health.get_health_status(user_input, global_config);
24+
await health.get_health_status(user_input, config_fs);
2525
break;
2626
case DIAGNOSE_ACTIONS.GATHER_LOGS:
2727
await gather_logs();

src/manage_nsfs/health.js

Lines changed: 68 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
'use strict';
33

44
const dbg = require('../util/debug_module')(__filename);
5-
const path = require('path');
65
const _ = require('lodash');
76
const P = require('../util/promise');
87
const config = require('../../config');
@@ -11,6 +10,7 @@ const nb_native = require('../util/nb_native');
1110
const native_fs_utils = require('../util/native_fs_utils');
1211
const { read_stream_join } = require('../util/buffer_utils');
1312
const { make_https_request } = require('../util/http_utils');
13+
const { JSON_SUFFIX } = require('../sdk/config_fs');
1414
const { TYPES } = require('./manage_nsfs_constants');
1515
const { get_boolean_or_string_value, throw_cli_error, write_stdout_response } = require('./manage_nsfs_cli_utils');
1616
const { ManageCLIResponse } = require('./manage_nsfs_cli_responses');
@@ -87,9 +87,9 @@ process.env.AWS_SDK_JS_SUPPRESS_MAINTENANCE_MODE_MESSAGE = '1';
8787
class NSFSHealth {
8888
constructor(options) {
8989
this.https_port = options.https_port;
90-
this.config_root = options.config_root;
9190
this.all_account_details = options.all_account_details;
9291
this.all_bucket_details = options.all_bucket_details;
92+
this.config_fs = options.config_fs;
9393
}
9494

9595
/**
@@ -116,8 +116,8 @@ class NSFSHealth {
116116
const service_health = service_status !== 'active' || pid === '0' || response_code !== 'RUNNING' ? 'NOTOK' : 'OK';
117117

118118
const error_code = await this.get_error_code(service_status, pid, response_code);
119-
if (this.all_bucket_details) bucket_details = await this.get_bucket_status(this.config_root);
120-
if (this.all_account_details) account_details = await this.get_account_status(this.config_root);
119+
if (this.all_bucket_details) bucket_details = await this.get_bucket_status();
120+
if (this.all_account_details) account_details = await this.get_account_status();
121121
const health = {
122122
service_name: NOOBAA_SERVICE,
123123
status: service_health,
@@ -306,38 +306,48 @@ class NSFSHealth {
306306
};
307307
}
308308

309-
async get_bucket_status(config_root) {
310-
const bucket_details = await this.get_storage_status(config_root, TYPES.BUCKET, this.all_bucket_details);
309+
async get_bucket_status() {
310+
const bucket_details = await this.get_storage_status(TYPES.BUCKET, this.all_bucket_details);
311311
return bucket_details;
312312
}
313313

314-
async get_account_status(config_root) {
315-
const account_details = await this.get_storage_status(config_root, TYPES.ACCOUNT, this.all_account_details);
314+
async get_account_status() {
315+
const account_details = await this.get_storage_status(TYPES.ACCOUNT, this.all_account_details);
316316
return account_details;
317317
}
318318

319-
async get_storage_status(config_root, type, all_details) {
320-
const fs_context = this.get_root_fs_context();
321-
const config_root_type_path = this.get_config_path(config_root, type);
319+
async get_storage_status(type, all_details) {
322320
const invalid_storages = [];
323321
const valid_storages = [];
324322
//check for account and buckets dir paths
325-
try {
326-
await nb_native().fs.stat(fs_context, config_root_type_path);
327-
} catch (err) {
328-
dbg.log1(`Config root path missing ${type} folder in ${config_root_type_path}`);
323+
let config_root_type_exists;
324+
let config_dir_path;
325+
if (type === TYPES.BUCKET) {
326+
config_dir_path = this.config_fs.buckets_dir_path;
327+
config_root_type_exists = await this.config_fs.validate_config_dir_exists(config_dir_path);
328+
} else if (type === TYPES.ACCOUNT) {
329+
// TODO - handle iam accounts when directory structure changes - read_account_by_id
330+
config_dir_path = this.config_fs.accounts_dir_path;
331+
config_root_type_exists = await this.config_fs.validate_config_dir_exists(config_dir_path);
332+
}
333+
// TODO - this is not a good handling for that - we need to take it to an upper level
334+
if (!config_root_type_exists) {
335+
dbg.log1(`Config directory type - ${type} is missing, ${config_dir_path}`);
329336
return {
330337
invalid_storages: invalid_storages,
331338
valid_storages: valid_storages
332339
};
333340
}
334-
const entries = await nb_native().fs.readdir(fs_context, config_root_type_path);
335-
const config_files = entries.filter(entree => !native_fs_utils.isDirectory(entree) && entree.name.endsWith('.json'));
341+
342+
const entries = type === TYPES.BUCKET ?
343+
await this.config_fs.list_buckets() :
344+
await this.config_fs.list_root_accounts();
345+
346+
const config_files = entries.filter(entree => !native_fs_utils.isDirectory(entree) && entree.name.endsWith(JSON_SUFFIX));
336347
for (const config_file of config_files) {
337348
// config_file get data or push error
338-
const config_file_path = path.join(config_root_type_path, config_file.name);
339349
const { config_data = undefined, err_obj = undefined } =
340-
await get_config_file_data(fs_context, config_file_path, config_file.name);
350+
await this.get_config_file_data_or_error_object(type, config_file.name);
341351
if (!config_data && err_obj) {
342352
invalid_storages.push(err_obj.invalid_storage);
343353
continue;
@@ -351,9 +361,10 @@ class NSFSHealth {
351361
config_data.nsfs_account_config.new_buckets_path;
352362

353363
if (type === TYPES.ACCOUNT) {
364+
const config_file_path = this.config_fs.get_account_path_by_name(config_file.name);
354365
res = await is_new_buckets_path_valid(config_file_path, config_data, storage_path);
355366
} else if (type === TYPES.BUCKET) {
356-
res = await is_bucket_storage_path_exists(fs_context, config_data, storage_path);
367+
res = await is_bucket_storage_path_exists(this.config_fs.fs_context, config_data, storage_path);
357368
}
358369
if (all_details && res.valid_storage) {
359370
valid_storages.push(res.valid_storage);
@@ -367,21 +378,52 @@ class NSFSHealth {
367378
};
368379
}
369380

370-
get_config_path(config_root, type) {
371-
return path.join(config_root, type === TYPES.BUCKET ? '/buckets' : '/accounts');
381+
/**
382+
* get_config_file_data_or_error_object return an object containing config_data or err_obj if error occurred
383+
* @param {string} type
384+
* @param {string} config_file_name
385+
* @returns {Promise<object>}
386+
*/
387+
async get_config_file_data_or_error_object(type, config_file_name) {
388+
let config_data;
389+
let err_obj;
390+
try {
391+
config_data = type === TYPES.BUCKET ?
392+
await this.config_fs.get_bucket_by_name(config_file_name) :
393+
// TODO - should be changed to id when moving to new structure for supporting iam accounts
394+
await this.config_fs.get_account_by_name(config_file_name);
395+
} catch (err) {
396+
let err_code;
397+
const config_file_path = type === TYPES.BUCKET ?
398+
await this.config_fs.get_bucket_path_by_name(config_file_name) :
399+
// TODO - should be changed to id when moving to new structure for supporting iam accounts
400+
await this.config_fs.get_account_path_by_name(config_file_name);
401+
402+
if (err.code === 'ENOENT') {
403+
dbg.log1(`Error: Config file path should be a valid path`, config_file_path, err);
404+
err_code = health_errors.MISSING_CONFIG.error_code;
405+
} else {
406+
dbg.log1('Error: while accessing the config file: ', config_file_path, err);
407+
err_code = health_errors.INVALID_CONFIG.error_code;
408+
}
409+
err_obj = get_invalid_object(config_file_name, config_file_path, undefined, err_code);
410+
}
411+
return {
412+
config_data,
413+
err_obj
414+
};
372415
}
373416
}
374417

375-
async function get_health_status(argv, global_config) {
418+
async function get_health_status(argv, config_fs) {
376419
try {
377-
const config_root = global_config.config_root;
378420
const https_port = Number(argv.https_port) || config.ENDPOINT_SSL_PORT;
379421
const deployment_type = argv.deployment_type || 'nc';
380422
const all_account_details = get_boolean_or_string_value(argv.all_account_details);
381423
const all_bucket_details = get_boolean_or_string_value(argv.all_bucket_details);
382424

383425
if (deployment_type === 'nc') {
384-
const health = new NSFSHealth({ https_port, config_root, all_account_details, all_bucket_details });
426+
const health = new NSFSHealth({ https_port, all_account_details, all_bucket_details, config_fs });
385427
const health_status = await health.nc_nsfs_health();
386428
write_stdout_response(ManageCLIResponse.HealthStatus, health_status);
387429
} else {
@@ -432,6 +474,7 @@ async function is_new_buckets_path_valid(config_file_path, config_data, new_buck
432474
}
433475

434476
try {
477+
await nb_native().fs.stat(account_fs_context, new_buckets_path);
435478
const accessible = await native_fs_utils.is_dir_rw_accessible(account_fs_context, new_buckets_path);
436479
if (!accessible) {
437480
const new_err = new Error('ACCESS DENIED');
@@ -452,36 +495,6 @@ async function is_new_buckets_path_valid(config_file_path, config_data, new_buck
452495
return res_obj;
453496
}
454497

455-
/**
456-
* get_config_file_data return an object containing config_data or err_obj if error occurred
457-
* @param {nb.NativeFSContext} fs_context
458-
* @param {string} config_file_path
459-
* @param {string} config_file_name
460-
* @returns {Promise<object>}
461-
*/
462-
async function get_config_file_data(fs_context, config_file_path, config_file_name) {
463-
let config_data;
464-
let err_obj;
465-
try {
466-
const { data } = await nb_native().fs.readFile(fs_context, config_file_path);
467-
config_data = JSON.parse(data.toString());
468-
} catch (err) {
469-
let err_code;
470-
if (err.code === 'ENOENT') {
471-
dbg.log1(`Error: Config file path should be a valid path`, config_file_path, err);
472-
err_code = health_errors.MISSING_CONFIG.error_code;
473-
} else {
474-
dbg.log1('Error: while accessing the config file: ', config_file_path, err);
475-
err_code = health_errors.INVALID_CONFIG.error_code;
476-
}
477-
err_obj = get_invalid_object(config_file_name, config_file_path, undefined, err_code);
478-
}
479-
return {
480-
config_data,
481-
err_obj
482-
};
483-
}
484-
485498
/**
486499
* is_bucket_storage_path_exists checks if the underlying storage path of a bucket exists
487500
* @param {nb.NativeFSContext} fs_context

src/manage_nsfs/manage_nsfs_cli_utils.js

Lines changed: 3 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33

44
const dbg = require('../util/debug_module')(__filename);
55
const _ = require('lodash');
6-
const path = require('path');
7-
const config = require('../../config');
86
const nb_native = require('../util/nb_native');
97
const native_fs_utils = require('../util/native_fs_utils');
108
const ManageCLIError = require('../manage_nsfs/manage_nsfs_cli_errors').ManageCLIError;
@@ -15,36 +13,6 @@ const { BOOLEAN_STRING_VALUES } = require('../manage_nsfs/manage_nsfs_constants'
1513
const NoobaaEvent = require('../manage_nsfs/manage_nsfs_events_utils').NoobaaEvent;
1614
const mongo_utils = require('../util/mongo_utils');
1715

18-
/**
19-
* @param {object} global_config
20-
*/
21-
async function check_and_create_config_dirs(global_config) {
22-
const pre_req_dirs = [
23-
global_config.config_root,
24-
global_config.buckets_dir_path,
25-
global_config.accounts_dir_path,
26-
global_config.access_keys_dir_path,
27-
];
28-
29-
if (config.NSFS_GLACIER_LOGS_ENABLED) {
30-
pre_req_dirs.push(config.NSFS_GLACIER_LOGS_DIR);
31-
}
32-
33-
for (const dir_path of pre_req_dirs) {
34-
try {
35-
const fs_context = native_fs_utils.get_process_fs_context(global_config.config_root_backend);
36-
const dir_exists = await native_fs_utils.is_path_exists(fs_context, dir_path);
37-
if (dir_exists) {
38-
dbg.log1('nsfs.check_and_create_config_dirs: config dir exists:', dir_path);
39-
} else {
40-
await native_fs_utils._create_path(dir_path, fs_context, config.BASE_MODE_CONFIG_DIR);
41-
dbg.log1('nsfs.check_and_create_config_dirs: config dir was created:', dir_path);
42-
}
43-
} catch (err) {
44-
dbg.log1('nsfs.check_and_create_config_dirs: could not create pre requisite path', dir_path);
45-
}
46-
}
47-
}
4816

4917
function throw_cli_error(error, detail, event_arg) {
5018
const error_event = NSFS_CLI_ERROR_EVENT_MAP[error.code];
@@ -66,56 +34,15 @@ function write_stdout_response(response_code, detail, event_arg) {
6634
});
6735
}
6836

69-
function get_config_file_path(config_type_path, file_name) {
70-
return path.join(config_type_path, file_name + '.json');
71-
}
72-
73-
function get_symlink_config_file_path(config_type_path, file_name) {
74-
return path.join(config_type_path, file_name + '.symlink');
75-
}
76-
77-
/**
78-
* get_config_data will read a config file and return its content
79-
* while omitting secrets if show_secrets flag was not provided
80-
* @param {string} config_root_backend
81-
* @param {string} config_file_path
82-
* @param {boolean} [show_secrets]
83-
*/
84-
async function get_config_data(config_root_backend, config_file_path, show_secrets = false) {
85-
const fs_context = native_fs_utils.get_process_fs_context(config_root_backend);
86-
const { data } = await nb_native().fs.readFile(fs_context, config_file_path);
87-
const config_data = _.omit(JSON.parse(data.toString()), show_secrets ? [] : ['access_keys']);
88-
return config_data;
89-
}
90-
91-
/**
92-
* get_config_data_if_exists will read a config file and return its content
93-
* while omitting secrets if show_secrets flag was not provided
94-
* if the config file was deleted (encounter ENOENT error) - continue (returns undefined)
95-
* @param {string} config_root_backend
96-
* @param {string} config_file_path
97-
* @param {boolean} [show_secrets]
98-
*/
99-
async function get_config_data_if_exists(config_root_backend, config_file_path, show_secrets = false) {
100-
try {
101-
const config_data = await get_config_data(config_root_backend, config_file_path, show_secrets);
102-
return config_data;
103-
} catch (err) {
104-
dbg.warn('get_config_data_if_exists: with config_file_path', config_file_path, 'got an error', err);
105-
if (err.code !== 'ENOENT') throw err;
106-
}
107-
}
108-
10937
/**
11038
* get_bucket_owner_account will return the account of the bucket_owner
11139
* otherwise it would throw an error
112-
* @param {object} global_config
40+
* @param {import('../sdk/config_fs').ConfigFS} config_fs
11341
* @param {string} bucket_owner
11442
*/
115-
async function get_bucket_owner_account(global_config, bucket_owner) {
116-
const account_config_path = get_config_file_path(global_config.accounts_dir_path, bucket_owner);
43+
async function get_bucket_owner_account(config_fs, bucket_owner) {
11744
try {
118-
const account = await get_config_data(global_config.config_root_backend, account_config_path);
45+
const account = await config_fs.get_account_by_name(bucket_owner);
11946
return account;
12047
} catch (err) {
12148
if (err.code === 'ENOENT') {
@@ -206,15 +133,10 @@ function check_root_account_owns_user(root_account, account) {
206133
// EXPORTS
207134
exports.throw_cli_error = throw_cli_error;
208135
exports.write_stdout_response = write_stdout_response;
209-
exports.get_config_file_path = get_config_file_path;
210-
exports.get_symlink_config_file_path = get_symlink_config_file_path;
211136
exports.get_boolean_or_string_value = get_boolean_or_string_value;
212-
exports.get_config_data = get_config_data;
213137
exports.get_bucket_owner_account = get_bucket_owner_account;
214138
exports.get_options_from_file = get_options_from_file;
215139
exports.has_access_keys = has_access_keys;
216140
exports.generate_id = generate_id;
217141
exports.set_debug_level = set_debug_level;
218142
exports.check_root_account_owns_user = check_root_account_owns_user;
219-
exports.get_config_data_if_exists = get_config_data_if_exists;
220-
exports.check_and_create_config_dirs = check_and_create_config_dirs;

src/manage_nsfs/manage_nsfs_constants.js

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,6 @@ const DIAGNOSE_ACTIONS = {
3030
METRICS: 'metrics'
3131
};
3232

33-
const CONFIG_SUBDIRS = {
34-
ACCOUNTS: 'accounts',
35-
BUCKETS: 'buckets',
36-
ACCESS_KEYS: 'access_keys'
37-
};
3833

3934
const CONFIG_ROOT_FLAG = 'config_root';
4035
const CLI_MUTUAL_OPTIONS = new Set([CONFIG_ROOT_FLAG, 'config_root_backend', 'debug']);
@@ -139,7 +134,6 @@ exports.TYPES = TYPES;
139134
exports.ACTIONS = ACTIONS;
140135
exports.GLACIER_ACTIONS = GLACIER_ACTIONS;
141136
exports.DIAGNOSE_ACTIONS = DIAGNOSE_ACTIONS;
142-
exports.CONFIG_SUBDIRS = CONFIG_SUBDIRS;
143137
exports.VALID_OPTIONS = VALID_OPTIONS;
144138
exports.OPTION_TYPE = OPTION_TYPE;
145139
exports.FROM_FILE = FROM_FILE;

0 commit comments

Comments
 (0)