diff --git a/README.md b/README.md index 10eba79f50..d4952cd5de 100644 --- a/README.md +++ b/README.md @@ -427,12 +427,25 @@ databricks labs ucx validate-external-locations ``` Once the [`assessment` workflow](#assessment-workflow) finished successfully, [storage credentials](#migrate-credentials-command) are configured, -run this command to ensure the relevant Unity Catalog external locations are created if they are missing. +run this command to validate and report the missing Unity Catalog external locations to be created. This command validates and provides mapping to external tables to external locations, also as Terraform configurations. [[back to top](#databricks-labs-ucx)] + +## `migrate-locations` command + +```text +databricks labs ucx migrate-locations +``` + +Once the [`assessment` workflow](#assessment-workflow) finished successfully, and [storage credentials](#migrate-credentials-command) are configured, +run this command to have Unity Catalog external locations created. The candidate locations to be created are extracted from guess_external_locations +task in the assessment job. You can run `validate_external_locations` command to check the candidate locations. + +[[back to top](#databricks-labs-ucx)] + ## `create-table-mapping` command ```text diff --git a/labs.yml b/labs.yml index bb92770f41..0783b9f9fd 100644 --- a/labs.yml +++ b/labs.yml @@ -133,3 +133,6 @@ commands: flags: - name: workspace_ids description: List of workspace IDs to create account groups from. + + - name: migrate_locations + description: Create UC external locations based on the output of guess_external_locations assessment task. \ No newline at end of file diff --git a/src/databricks/labs/ucx/cli.py b/src/databricks/labs/ucx/cli.py index 18a6c0d9f0..515f5e0254 100644 --- a/src/databricks/labs/ucx/cli.py +++ b/src/databricks/labs/ucx/cli.py @@ -14,6 +14,7 @@ from databricks.labs.ucx.assessment.aws import AWSResourcePermissions from databricks.labs.ucx.azure.access import AzureResourcePermissions from databricks.labs.ucx.azure.credentials import ServicePrincipalMigration +from databricks.labs.ucx.azure.locations import ExternalLocationsMigration from databricks.labs.ucx.config import WorkspaceConfig from databricks.labs.ucx.framework.crawlers import StatementExecutionBackend from databricks.labs.ucx.hive_metastore import ExternalLocations, TablesCrawler @@ -344,5 +345,22 @@ def create_uber_principal(w: WorkspaceClient, subscription_id: str): return +@ucx.command +def migrate_locations(w: WorkspaceClient): + """This command creates UC external locations. The candidate locations to be created are extracted from guess_external_locations + task in the assessment job. You can run validate_external_locations command to check the candidate locations. Please make sure + the credentials haven migrated before running this command. The command will only create the locations that have corresponded UC Storage Credentials. + """ + if w.config.is_azure: + logger.info("Running migrate_locations for Azure") + installation = Installation.current(w, 'ucx') + service_principal_migration = ExternalLocationsMigration.for_cli(w, installation) + service_principal_migration.run() + if w.config.is_aws: + logger.error("migrate_locations is not yet supported in AWS") + if w.config.is_gcp: + logger.error("migrate_locations is not yet supported in GCP") + + if __name__ == "__main__": ucx() diff --git a/tests/unit/test_cli.py b/tests/unit/test_cli.py index 3187b0a79e..b34f46d43b 100644 --- a/tests/unit/test_cli.py +++ b/tests/unit/test_cli.py @@ -18,6 +18,7 @@ installations, manual_workspace_info, migrate_credentials, + migrate_locations, move, open_remote_config, principal_prefix_access, @@ -357,3 +358,27 @@ def test_create_master_principal(ws): with patch("databricks.labs.blueprint.tui.Prompts.question", return_value=True): with pytest.raises(ValueError): create_uber_principal(ws, subscription_id="12") + + +def test_migrate_locations_azure(ws): + ws.config.is_azure = True + ws.config.is_aws = False + ws.config.is_gcp = False + migrate_locations(ws) + ws.external_locations.list.assert_called() + + +def test_migrate_locations_aws(ws, caplog): + ws.config.is_azure = False + ws.config.is_aws = True + ws.config.is_gcp = False + migrate_locations(ws) + assert "migrate_locations is not yet supported in AWS" in caplog.messages + + +def test_migrate_locations_gcp(ws, caplog): + ws.config.is_azure = False + ws.config.is_aws = False + ws.config.is_gcp = True + migrate_locations(ws) + assert "migrate_locations is not yet supported in GCP" in caplog.messages