|
| 1 | +# Transferring Dashboards across Environments |
| 2 | + |
| 3 | +In this document, we will discuss how to transfer dashboards across Superset hosting environments with the goal of heading towards an API call to automate the process. |
| 4 | + |
| 5 | +Current process is limited to dashboards with all datasets based on a single database connection. |
| 6 | + |
| 7 | +## Short Version |
| 8 | + |
| 9 | +Assuming you want to transfer a dashboard from Env1 to Env2. |
| 10 | + |
| 11 | +You will need the following: |
| 12 | +- a Env1 Dashboard Export Zip file |
| 13 | +- a Env2 Database config export yaml |
| 14 | +- a Env2 schema to point your datasets to |
| 15 | + |
| 16 | +Assuming your API env for ruby is setup for your target superset environment. |
| 17 | +( ie using API creds for Env2 for this example ) |
| 18 | + |
| 19 | +```ruby |
| 20 | + |
| 21 | +new_import_zip = Superset::Services::ImportDashboardAcrossEnvironments.new( |
| 22 | + dashboard_export_zip: 'path_to/dashboard_101_export_20241010.zip', |
| 23 | + target_database_yaml_file: 'path_to/env2_db_config.yaml', |
| 24 | + target_database_schema: 'acme', |
| 25 | + ).perform |
| 26 | + |
| 27 | +# now import the adjusted zip to the target superset env |
| 28 | +Superset::Dashboard::Import.new(source_zip_file: new_import_file).perform |
| 29 | + |
| 30 | +``` |
| 31 | + |
| 32 | +## Background |
| 33 | + |
| 34 | +A common practice is to set up infrastructure to deploy multiple Superset environments. For example, a simple setup might be: |
| 35 | +- Local development environment for testing version upgrades and feature exploration |
| 36 | +- Staging Superset environment for testing in a production-like environment |
| 37 | +- Production Superset environment that requires a higher level of stability and uptime |
| 38 | + |
| 39 | +For the above example, the Superset staging environment often holds connections to staging databases, and the Superset production environment will hold connections to the production databases. |
| 40 | + |
| 41 | +In the event where the database schema structure for the local development, staging, and production databases are exactly the same, dashboards can be replicated and transferred across Superset hosting environments. |
| 42 | + |
| 43 | +That process does require some manual updating of the exported YAML files before importing them into the target environment. Also required is some understanding of the underlying dashboard export structure and how the object UUIDs work and relate to each other, especially in the context of databases and datasets. |
| 44 | + |
| 45 | +## Dashboard Export/Import within the Same Environment |
| 46 | + |
| 47 | +This is a fairly straightforward process. |
| 48 | + |
| 49 | +There are multiple methods for exporting a dashboard: |
| 50 | +- Export from the dashboard list page in the GUI |
| 51 | +- Export via the Superset API |
| 52 | +- Export via the Superset CLI |
| 53 | + |
| 54 | +Each export method will result in a zip file that contains a set of YAML files as per this list below, which is an export of customized version of the test Sales dashboard from the default example dashboards. |
| 55 | + |
| 56 | +Test fixture is: https://github.com/rdytech/superset-client/blob/develop/spec/fixtures/dashboard_18_export_20240322.zip |
| 57 | + |
| 58 | +``` |
| 59 | +└── dashboard_export_20240321T214117 |
| 60 | + ├── charts |
| 61 | + │ ├── Boy_Name_Cloud_53920.yaml |
| 62 | + │ ├── Names_Sorted_by_Num_in_California_53929.yaml |
| 63 | + │ ├── Number_of_Girls_53930.yaml |
| 64 | + │ ├── Pivot_Table_53931.yaml |
| 65 | + │ └── Top_10_Girl_Name_Share_53921.yaml |
| 66 | + ├── dashboards |
| 67 | + │ └── Birth_Names_18.yaml |
| 68 | + ├── databases |
| 69 | + │ └── examples.yaml |
| 70 | + ├── datasets |
| 71 | + │ └── examples |
| 72 | + │ └── birth_names.yaml |
| 73 | + └── metadata.yaml |
| 74 | +``` |
| 75 | + |
| 76 | +Each of the above YAML files holds UUID values for the primary object and any related objects. |
| 77 | + |
| 78 | +- Database YAMLs hold the database connection string as well as a UUID for the database |
| 79 | +- Dataset YAMLs have their own UUID as well as a reference to the database UUID |
| 80 | +- Chart YAMLs have their own UUID as well as a reference to their dataset UUID |
| 81 | + |
| 82 | +Example of the database YAML file: |
| 83 | + |
| 84 | +``` |
| 85 | +cat databases/examples.yaml |
| 86 | +database_name: examples |
| 87 | +sqlalchemy_uri: postgresql+psycopg2://superset:XXXXXXXXXX@superset-host:5432/superset |
| 88 | +cache_timeout: null |
| 89 | +expose_in_sqllab: true |
| 90 | +allow_run_async: true |
| 91 | +allow_ctas: true |
| 92 | +allow_cvas: true |
| 93 | +allow_dml: true |
| 94 | +allow_file_upload: true |
| 95 | +extra: |
| 96 | + metadata_params: {} |
| 97 | + engine_params: {} |
| 98 | + metadata_cache_timeout: {} |
| 99 | + schemas_allowed_for_file_upload: |
| 100 | + - examples |
| 101 | + allows_virtual_table_explore: true |
| 102 | +uuid: a2dc77af-e654-49bb-b321-40f6b559a1ee |
| 103 | +version: 1.0.0 |
| 104 | +``` |
| 105 | + |
| 106 | +If we grep the database/examples.yaml we can see the UUID of the database. |
| 107 | + |
| 108 | +``` |
| 109 | +grep -r uuid databases/ |
| 110 | + databases/examples.yaml:uuid: a2dc77af-e654-49bb-b321-40f6b559a1ee |
| 111 | +
|
| 112 | +``` |
| 113 | + |
| 114 | +Now if we look at the UUID values in the datasets, you will see both the dataset UUID and the reference to the database UUID. |
| 115 | + |
| 116 | +``` |
| 117 | +grep -r uuid datasets |
| 118 | +datasets/examples/birth_names.yaml:uuid: 283f5023-0814-40f6-b12d-96f6a86b984f |
| 119 | +datasets/examples/birth_names.yaml:database_uuid: a2dc77af-e654-49bb-b321-40f6b559a1ee |
| 120 | +``` |
| 121 | + |
| 122 | +If the above dashboard zip file `dashboard_18_export_20240322.zip` was imported as is to the same superset environment as it was exported from, this would mean all UUID's would already exist in superset and these objects would be found and updated with the imported zip data. |
| 123 | + |
| 124 | +If the above zip file was imported as is to a different target Superset environment, it would fail as there would be no matching database UUID entry in that target Superset environment. |
| 125 | + |
| 126 | +**Key Point:** When importing a dashboard to a different Superset environment than the original environment, the database configuration in the zip export must exist in the target Superset environment and all datasets must point to the database config. |
| 127 | + |
| 128 | +## Migrate a Dashboard to a Different Superset Environment |
| 129 | + |
| 130 | +With the above knowledge, we can now think about how to migrate dashboards between Superset environments. |
| 131 | + |
| 132 | +Each Superset object is given a UUID. Within the exported dashboard files, we are primarily concerned with: |
| 133 | +- Replacing the staging database configuration with the production configuration |
| 134 | +- Updating all staging datasets to point to the new production database UUID |
| 135 | + |
| 136 | +Given we have a request to 'transfer' a dashboard across to a different environment, say staging to production, how would we then proceed? |
| 137 | + |
| 138 | +With the condition that the database in staging and production are structurally exactly the same schema, from the above discussion on UUIDs, you can then see that if we want to import a staging dashboard export into the production environment, we will need to perform the following steps: |
| 139 | + |
| 140 | +1. Export the staging dashboard and unzip |
| 141 | +2. Note the staging database UUIDs in the `databases/` directory |
| 142 | +3. Get a copy of the production database YAML configuration file |
| 143 | +4. In the exported dashboard files, replace the staging database YAML with the production YAML |
| 144 | +5. In the dataset YAML files, replace all instances of the previously noted staging database UUID with the new production UUID |
| 145 | +6. Zip the files and import them to the production environment |
| 146 | + |
| 147 | +The process above assumes that whoever is migrating the dashboard has a copy of the target database YAML files so that in steps 3 and 4 we can then replace the staging database YAML with the production one. |
| 148 | + |
| 149 | +## Requirements |
| 150 | + |
| 151 | +The overall process requires the following: |
| 152 | +- The source dashboard zip file |
| 153 | +- The target Superset environment database YAML file |
| 154 | +- Ability to copy and manipulate the source dashboard zip file |
| 155 | +- The ability to import via API to the target Superset environment |
| 156 | + |
| 157 | + |
| 158 | +## Gotchas! |
| 159 | + |
| 160 | +Migrating a dashboard once to a new target environment, database, schema will result in: |
| 161 | +- Creating a new dashboard with the UUID from the import zip |
| 162 | +- Creating a new set of charts with their UUIDs from the import zip |
| 163 | +- Creating a new set of datasets with their UUIDs from the import zip |
| 164 | + |
| 165 | +Migrating the same dashboard a second time to the same target environment, database, but different schema will NOT create a new dashboard. |
| 166 | + |
| 167 | +It will attempt to update the same dashboard as the UUID for the dashboard has not changed. It will also NOT change any of the datasets to the new schema. This appears to be a limitation of the import process, which may lead to some confusing results. |
| 168 | + |
| 169 | +## References |
| 170 | + |
| 171 | +Some helpful references relating to cross-environment workflows: |
| 172 | +- [Managing Content Across Workspaces](https://docs.preset.io/docs/managing-content-across-workspaces) |
| 173 | +- [Superset Slack AI Explanation](https://apache-superset.slack.com/archives/C072KSLBTC1/p1722382347022689) |
0 commit comments