Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add database dropdown to dashboard import #10118

Merged
merged 6 commits into from Jul 5, 2020

Conversation

mistercrunch
Copy link
Member

Screen Shot 2020-06-20 at 8 45 56 AM

Currently, when importing a database from a JSON file, the process
looks at the database name from the source (the info is in the file)
and matches the datasources to that name. If no database by that name
exists, it simply fails.

With this PR, we add a database dropdown that allows the user to specify
which databases the datasources should target as the get upserted.

I want to stress that the code in this area is not in a great shape,
and that the challenge of serializing/deser the nested objects is
challenging, but that there should be a much better way to do this.
One of the improvement (out of scope for this PR) that would allow to
simplify those import/export would be to use UUIDs for
importable/exportable objects.

Another identified issue is the indirections between
utils/import_expor_{model}.py on top of {Model}.import_object. Not
addressing that here.

Next topic is the MVC stuff. Decided to stick with it for now as this is
more of a [obious missing feat:] than a rewrite.

SUMMARY

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

TEST PLAN

ADDITIONAL INFORMATION

  • Has associated issue:
  • Changes UI
  • Requires DB Migration.
  • Confirm DB Migration upgrade and downgrade tested.
  • Introduces new feature or API
  • Removes existing feature or API

@@ -42,7 +43,9 @@ class FlashProvider extends React.PureComponent<Props> {
flashMessages.forEach(message => {
const [type, text] = message;
const flash = flashObj[type];
this.props[flash](text);
if (this.props[flash]) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caught this bug as bycatch, this fails for the commonly used "alert" flashes.

@@ -311,6 +311,10 @@ def alter_positions(
# copy slices object as Slice.import_slice will mutate the slice
# and will remove the existing dashboard - slice association
slices = copy(dashboard_to_import.slices)

# Clearing the slug to avoid conflicts
dashboard_to_import.slug = None
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was raising when loading the same dashboard (with a slug) twice. Currently the authority on whether to insert or update is the remote_id and didn't want to tangle the slug into that. Imported dashboards loose their slugs. We could lookup whether there will be a conflict or not and keep the slug / suffix it, but for now I'm just fixing this bug.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing the slug might be unexpected behavior for the end user. I wonder if we should raise an alert toast if the slug has been removed until we figure out a more permanent solution?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So let's say I raise Slug already exists! user should do what? Go to change the slug from the source and re-export? I feel like we'd need to wizard that up and be like "Want to overwrite or create a new one?". Currently it'd be hard to do that.

I guess the form could offer "overwrite based on slug" checkbox or similar... ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TBH this is one of those things where it'd be really valuable to get usage statistics on how much slugs are used, how often slugged dashboards are exported + the slug is expected to work upon import. My guess is not so often, but who knows. But for the time being I'm comfortable with clearing the slug to avoid getting errors on repeated imports (idempotency FTW).

Copy link
Member Author

@mistercrunch mistercrunch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some PR notes

superset/utils/log.py Show resolved Hide resolved
@mistercrunch mistercrunch force-pushed the import_dash branch 4 times, most recently from 701e892 to 1005537 Compare June 20, 2020 19:35
@mistercrunch mistercrunch marked this pull request as ready for review June 20, 2020 21:26
@eugeniamz
Copy link

Do you think that doing this will resolve the issue that if Dashboard to import is using legacy Druid Driver?

@mistercrunch
Copy link
Member Author

@eugeniamz we're more heading towards deprecation at this time, I'd rather help people migrate off the legacy connector and onto SQL druid than investing in that direction.

In theory we could make the dropdown include databases + druid clusters, but that's one more thing to untangle/deprecate...

Copy link
Member

@villebro villebro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few comments.

superset/connectors/sqla/models.py Show resolved Hide resolved
@@ -311,6 +311,10 @@ def alter_positions(
# copy slices object as Slice.import_slice will mutate the slice
# and will remove the existing dashboard - slice association
slices = copy(dashboard_to_import.slices)

# Clearing the slug to avoid conflicts
dashboard_to_import.slug = None
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing the slug might be unexpected behavior for the end user. I wonder if we should raise an alert toast if the slug has been removed until we figure out a more permanent solution?

sesh = current_app.appbuilder.get_session
sesh.bulk_save_objects(logs)
sesh.commit()
except Exception as ex: # pylint: disable=broad-except
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

except SQLAlchemyError as ex:

@mistercrunch
Copy link
Member Author

mistercrunch commented Jun 24, 2020

@dpgaspar @villebro , addressed most comments. Clearly export/import needs more attention, but this tackles important shortcoming of lacking the ability to target a database, and fixes the slug bug.

About next step, I think we'll need:

  • uuid as the authority for upsert logic
  • add a try-to-update VS insert new checkbox option
  • uuids relationships where possible so we don't need all this lookup logic!

@@ -311,6 +311,10 @@ def alter_positions(
# copy slices object as Slice.import_slice will mutate the slice
# and will remove the existing dashboard - slice association
slices = copy(dashboard_to_import.slices)

# Clearing the slug to avoid conflicts
dashboard_to_import.slug = None
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TBH this is one of those things where it'd be really valuable to get usage statistics on how much slugs are used, how often slugged dashboards are exported + the slug is expected to work upon import. My guess is not so often, but who knows. But for the time being I'm comfortable with clearing the slug to avoid getting errors on repeated imports (idempotency FTW).

@willbarrett
Copy link
Member

FYI @mistercrunch this needs a rebase.

Currently, when importing a database from a JSON file, the process
looks at the database name from the source (the info is in the file)
and matches the datasources to that name. If no database by that name
exists, it simply fails.

With this PR, we add a database dropdown that allows the user to specify
which databases the datasources should target as the get upserted.

I want to stress that the code in this area is not in a great shape,
and that the challenge of serializing/deser the nested objects is
challenging, but that there should be a much better way to do this.
One of the improvement (out of scope for this PR) that would allow to
simplify those import/export would be to use UUIDs for
importable/exportable objects.

Another identified issue is the indirections between
`utils/import_expor_{model}.py` on top of `{Model}.import_object`. Not
addressing that here.

Next topic is the MVC stuff. Decided to stick with it for now as this is
more of a [obious missing feat:] than a rewrite.
@mistercrunch mistercrunch merged commit 2314aad into apache:master Jul 5, 2020
@mistercrunch mistercrunch deleted the import_dash branch July 5, 2020 22:08
auxten pushed a commit to auxten/incubator-superset that referenced this pull request Nov 20, 2020
* feat: add database dropdown to dashboard import

Currently, when importing a database from a JSON file, the process
looks at the database name from the source (the info is in the file)
and matches the datasources to that name. If no database by that name
exists, it simply fails.

With this PR, we add a database dropdown that allows the user to specify
which databases the datasources should target as the get upserted.

I want to stress that the code in this area is not in a great shape,
and that the challenge of serializing/deser the nested objects is
challenging, but that there should be a much better way to do this.
One of the improvement (out of scope for this PR) that would allow to
simplify those import/export would be to use UUIDs for
importable/exportable objects.

Another identified issue is the indirections between
`utils/import_expor_{model}.py` on top of `{Model}.import_object`. Not
addressing that here.

Next topic is the MVC stuff. Decided to stick with it for now as this is
more of a [obious missing feat:] than a rewrite.

* isort \!? 0%^$%Y$&?%$^?%0^?

* fix tests

* pre-committing to py3.6

* address dpgaspar's comments

* revert isort
@mistercrunch mistercrunch added 🏷️ bot A label used by `supersetbot` to keep track of which PR where auto-tagged with release labels 🚢 0.37.0 labels Mar 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🏷️ bot A label used by `supersetbot` to keep track of which PR where auto-tagged with release labels size/L v0.37 🚢 0.37.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants