diff --git a/ESSArch_Core/cli/main.py b/ESSArch_Core/cli/main.py index 6ef6e346e..d6cefc2dd 100644 --- a/ESSArch_Core/cli/main.py +++ b/ESSArch_Core/cli/main.py @@ -40,13 +40,29 @@ def _loaddata(*fixture_labels): @cli.command() @initialize -def migrate(): +@click.option('--plan', is_flag=True, default=False, help='Do not actually apply migrations.') +def migrate(plan): click.secho('Applying database migrations:', fg='green') dj_call_command( 'migrate', interactive=False, verbosity=1, + plan=plan, + ) + + +@cli.command() +@initialize +@click.option('--dry-run', is_flag=True, default=False, help='Do not actually collect static files.') +def collectstatic(dry_run): + click.secho('Collect static files:', fg='green') + + dj_call_command( + 'collectstatic', + interactive=False, + verbosity=1, + dry_run=dry_run, ) @@ -106,13 +122,82 @@ def install(ctx, data_directory): if data_directory is None: data_directory = click.prompt('Data directory', default='/ESSArch/data', type=click.Path()) ctx.invoke(create_data_directories, path=data_directory) + ctx.invoke(collectstatic) ctx.invoke(migrate) _loaddata('countries_data', 'languages_data',) from ESSArch_Core.install.install_default_config import ( - installDefaultConfiguration, + installDefaultEventTypes, + installDefaultFeatures, + installDefaultParameters, + installDefaultPaths, + installDefaultSite, + installDefaultStorageMethods, + installDefaultStorageMethodTargetRelations, + installDefaultStoragePolicies, + installDefaultStorageTargets, + installDefaultUsers, + installPipelines, + installSearchIndices, + ) + installDefaultFeatures() + installDefaultEventTypes() + installDefaultParameters() + installDefaultSite() + installDefaultUsers() + installDefaultPaths() + installDefaultStoragePolicies() + installDefaultStorageMethods() + installDefaultStorageTargets() + installDefaultStorageMethodTargetRelations() + installPipelines() + installSearchIndices() + + +@cli.command() +@initialize +@click.option('-q/--quiet', default=False, is_eager=True, expose_value=False, callback=deactivate_prompts) +@click.option('--data-directory', type=click.Path(), + default=None, help=f'Example: {DEFAULT_DATA_DIR}') +@click.option('--dry-run/--no-dry-run', default=True, help='Run in dry-run mode by default.') +@click.option('--update-existing', is_flag=True, default=False, + help='Update existing configuration to defaults (requires --no-dry-run).') +@click.option('--remove-extra', is_flag=True, default=False, + help='Remove extra configuration not part of defaults (requires --no-dry-run).') +@click.option('-y', '--yes', is_flag=True, help='Skip confirmation prompts.') +@click.pass_context +def upgrade(ctx, data_directory, dry_run, update_existing, remove_extra, yes): + _check() + + if remove_extra and dry_run: + raise click.UsageError( + '--remove-extra requires --no-dry-run' + ) + + if not dry_run and not yes: + click.confirm( + 'This will apply changes to the system. Continue?', + abort=True, + ) + + if data_directory and not dry_run: + ctx.invoke(create_data_directories, path=data_directory) + + ctx.invoke(collectstatic, dry_run=dry_run) + ctx.invoke(migrate, plan=dry_run) + if not dry_run: + _loaddata('countries_data', 'languages_data',) + + from ESSArch_Core.install.install_default_config import ( + installDefaultEventTypes, + installDefaultParameters, + installDefaultPaths, + installDefaultRoles, ) - installDefaultConfiguration() + installDefaultEventTypes(dry_run=dry_run, update_existing=update_existing, remove_extra=remove_extra) + installDefaultParameters(dry_run=dry_run, update_existing=update_existing, remove_extra=remove_extra) + installDefaultPaths(dry_run=dry_run, update_existing=update_existing, remove_extra=remove_extra) + installDefaultRoles(dry_run=dry_run, remove_extra=remove_extra) @click.option('-P', '--pool', default='prefork', diff --git a/ESSArch_Core/cli/tests/test_main.py b/ESSArch_Core/cli/tests/test_main.py index fe17e125a..032ae9a25 100644 --- a/ESSArch_Core/cli/tests/test_main.py +++ b/ESSArch_Core/cli/tests/test_main.py @@ -20,7 +20,7 @@ def test_migrate(self): with mock.patch('ESSArch_Core.cli.main.dj_call_command') as cmd: result = runner.invoke(migrate) - cmd.assert_called_once_with('migrate', interactive=False, verbosity=1) + cmd.assert_called_once_with('migrate', interactive=False, verbosity=1, plan=False) self.assertEqual(result.exit_code, 0) def test_devserver(self): diff --git a/ESSArch_Core/install/install_default_config.py b/ESSArch_Core/install/install_default_config.py index f5e92e31e..0494359ff 100644 --- a/ESSArch_Core/install/install_default_config.py +++ b/ESSArch_Core/install/install_default_config.py @@ -110,7 +110,7 @@ def installDefaultFeatures(): return -def sync_event_types(event_definitions, dry_run=False, remove_extra=False): +def sync_event_types(event_definitions, dry_run=False, update_existing=False, remove_extra=False): """ Sync EventType objects. @@ -200,13 +200,13 @@ def sync_event_types(event_definitions, dry_run=False, remove_extra=False): if changes: click.secho( - f" [~] {'Would update' if dry_run else 'Updated'}: {code}", + f" [~] {'Would update' if (dry_run or not update_existing) else 'Updated'}: {code}", fg="yellow", ) for field, (old, new) in changes.items(): click.echo(f" - {field}: '{old}' → '{new}'") - if not dry_run: + if not (dry_run or not update_existing): for field, (_, new) in changes.items(): setattr(obj, field, new) obj.save() @@ -250,7 +250,7 @@ def sync_event_types(event_definitions, dry_run=False, remove_extra=False): click.secho("\nEvent type sync complete.", fg="green") -def installDefaultEventTypes(dry_run=False, remove_extra=False): +def installDefaultEventTypes(dry_run=False, update_existing=False, remove_extra=False): click.echo("Installing event types...") ip_cat = EventType.CATEGORY_INFORMATION_PACKAGE @@ -340,7 +340,7 @@ def installDefaultEventTypes(dry_run=False, remove_extra=False): 'AccessAid delivery': {'eventType': 50772, 'category': ip_cat}, } - sync_event_types(event_definitions, dry_run=dry_run, remove_extra=remove_extra) + sync_event_types(event_definitions, dry_run=dry_run, update_existing=update_existing, remove_extra=remove_extra) return 0 @@ -1161,7 +1161,7 @@ def installDefaultRoles(dry_run=False, remove_extra=False): role_administrator, role_system_administrator) -def sync_parameters(parameter_definitions, dry_run=False, remove_extra=False): +def sync_parameters(parameter_definitions, dry_run=False, update_existing=False, remove_extra=False): """ Sync Parameter objects. @@ -1240,12 +1240,12 @@ def sync_parameters(parameter_definitions, dry_run=False, remove_extra=False): if current_value != desired_value: click.secho( - f" [~] {'Would update' if dry_run else 'Updated'}: {key}", + f" [~] {'Would update' if (dry_run or not update_existing) else 'Updated'}: {key}", fg="yellow", ) click.echo(f" - value: '{current_value}' → '{desired_value}'") - if not dry_run: + if not (dry_run or not update_existing): obj.value = desired_value obj.save() @@ -1288,7 +1288,7 @@ def sync_parameters(parameter_definitions, dry_run=False, remove_extra=False): click.secho("\nParameter sync complete.", fg="green") -def installDefaultParameters(dry_run=False, remove_extra=False): +def installDefaultParameters(dry_run=False, update_existing=False, remove_extra=False): click.echo("Installing parameters...") site_name = 'Site-X' @@ -1304,7 +1304,7 @@ def installDefaultParameters(dry_run=False, remove_extra=False): 'medium_location': 'Media_%s' % site_name, } - sync_parameters(parameter_definitions, dry_run=dry_run, remove_extra=remove_extra) + sync_parameters(parameter_definitions, dry_run=dry_run, update_existing=update_existing, remove_extra=remove_extra) return 0 @@ -1449,7 +1449,7 @@ def installDefaultUsers(): return 0 -def sync_paths(path_definitions, dry_run=False, remove_extra=False): +def sync_paths(path_definitions, dry_run=False, update_existing=False, remove_extra=False): """ Sync cmPath objects. @@ -1528,12 +1528,12 @@ def sync_paths(path_definitions, dry_run=False, remove_extra=False): if current_value != desired_value: click.secho( - f" [~] {'Would update' if dry_run else 'Updated'}: {key}", + f" [~] {'Would update' if (dry_run or not update_existing) else 'Updated'}: {key}", fg="yellow", ) click.echo(f" - value: '{current_value}' → '{desired_value}'") - if not dry_run: + if not (dry_run or not update_existing): obj.value = desired_value obj.save() @@ -1576,7 +1576,7 @@ def sync_paths(path_definitions, dry_run=False, remove_extra=False): click.secho("\nPath sync complete.", fg="green") -def installDefaultPaths(dry_run=False, remove_extra=False): +def installDefaultPaths(dry_run=False, update_existing=False, remove_extra=False): click.echo("Installing paths...") path_definitions = { @@ -1599,7 +1599,7 @@ def installDefaultPaths(dry_run=False, remove_extra=False): 'export': (Path(settings.DATA_DIR) / 'export').as_posix(), } - sync_paths(path_definitions, dry_run=dry_run, remove_extra=remove_extra) + sync_paths(path_definitions, dry_run=dry_run, update_existing=update_existing, remove_extra=remove_extra) return 0