diff --git a/src/hdx_cli/cli_interface/common/undecorated_click_commands.py b/src/hdx_cli/cli_interface/common/undecorated_click_commands.py index 193164c..3a8a6dc 100644 --- a/src/hdx_cli/cli_interface/common/undecorated_click_commands.py +++ b/src/hdx_cli/cli_interface/common/undecorated_click_commands.py @@ -183,6 +183,8 @@ def _get_dotted_key_from_dict(dotted_key, the_dict): val = the_dict[key_path[0]] if len(key_path) > 1: for key_piece in key_path[1:]: + if val is None: + return KeyAbsent() val = val[key_piece] return val @@ -327,16 +329,13 @@ def _settings_update(resource: Dict[str, Any], value: Any): "Update resource and return it with updated_data" key_parts = key.split('.') - if len(key_parts) == 1: - resource[key_parts[0]] = json.loads(value) - return resource the_value = None try: the_value = json.loads(value) except json.JSONDecodeError: the_value = value - resource_key = resource[key_parts[0]] - for k in key_parts[1:-1]: + resource_key = resource + for k in key_parts[0:-1]: resource_key = resource_key[k] resource_key[key_parts[-1]] = the_value diff --git a/src/hdx_cli/cli_interface/storage/commands.py b/src/hdx_cli/cli_interface/storage/commands.py index b9b1554..ebca2fa 100644 --- a/src/hdx_cli/cli_interface/storage/commands.py +++ b/src/hdx_cli/cli_interface/storage/commands.py @@ -7,7 +7,7 @@ dynamic_confirmation_prompt) from ...library_api.common.context import ProfileUserContext from ...library_api.common.logging import get_logger -from ..common.undecorated_click_commands import basic_create_with_body_from_string +from ..common.undecorated_click_commands import basic_create_with_body_from_string, basic_create_from_dict_body from ..common.undecorated_click_commands import basic_delete, basic_settings from ..common.rest_operations import (list_ as command_list, show as command_show) @@ -16,8 +16,8 @@ @click.group(help="Storage-related operations") -@click.option('--storage', 'storage_name', help='Perform operation on the passed storage.', - metavar='STORAGENAME', default=None) +@click.option('--storage', 'storage_name', metavar='STORAGENAME', default=None, + help='Perform operation on the passed storage.') @click.pass_context def storage(ctx: click.Context, storage_name): @@ -29,19 +29,52 @@ def storage(ctx: click.Context, storagename=storage_name) -@click.command(help='Create storage.') -@click.argument('storage_filename') +@click.command(help='Create storage. You can either specify a settings file using' + 'the -f or --settings-filename option, or provide the storage ' + 'configuration directly using the -p, -n, -r, and -c options.') @click.argument('storage_name') +@click.option('-f', '--settings-filename', default=None, required=False, + help='Filename containing storage configuration settings.') +@click.option('-p', '--bucket-path', default=None, required=False, + help='Path to the storage bucket.') +@click.option('-n', '--bucket-name', default=None, required=False, + help='Name of the storage bucket.') +@click.option('-r', '--region', default=None, required=False, + help='Region for the storage bucket.') +@click.option('-c', '--cloud', default=None, required=False, + help='Type of cloud storage (e.g., aws, gcp).') @click.pass_context @report_error_and_exit(exctype=Exception) def create(ctx: click.Context, - storage_filename: str, - storage_name: str): + storage_name: str, + settings_filename: str, + bucket_path: str, + bucket_name: str, + region: str, + cloud: str): + if not settings_filename and not all((bucket_path, bucket_name, region, cloud)): + raise click.BadParameter("You must specify either a settings file or the bucket path, name, region, and cloud.") + user_profile = ctx.parent.obj.get('usercontext') resource_path = ctx.parent.obj.get('resource_path') - with open(storage_filename, "r", encoding="utf-8") as file: - basic_create_with_body_from_string(user_profile, resource_path, - storage_name, file.read()) + + if settings_filename: + with open(settings_filename, "r", encoding="utf-8") as file: + basic_create_with_body_from_string(user_profile, + resource_path, + storage_name, + file.read()) + else: + storage_settings_list = [('bucket_path', bucket_path), + ('bucket_name', bucket_name), + ('region', region), + ('cloud', cloud)] + body = { + 'name': storage_name, + 'settings': {key: value for key, value in storage_settings_list} + } + basic_create_from_dict_body(user_profile, resource_path, body) + logger.info(f'Created storage {storage_name}') @@ -52,9 +85,8 @@ def create(ctx: click.Context, @click.command(help='Delete resource.') -@click.option('--disable-confirmation-prompt', - is_flag=True, - help='Suppress confirmation to delete resource.', show_default=True, default=False) +@click.option('--disable-confirmation-prompt', is_flag=True, show_default=True, default=False, + help='Suppress confirmation to delete resource.') @click.argument('resource_name') @click.pass_context @report_error_and_exit(exctype=Exception)