Skip to main content

Dagster & Tableau (Component)

Beta feature

This feature is considered in a beta stage. It is still being tested and may change. For more information, see the API lifecycle stages documentation.

The dagster-tableau library provides a TableauComponent which can be used to easily represent Tableau workbooks, sheets, dashboards, and data sources as assets in Dagster.

info

TableauComponent is a state-backed component, which fetches and caches Tableau workspace metadata. For information on managing component state, see Configuring state-backed components.

1. Prepare a Dagster project

To begin, you'll need a Dagster project. You can use an existing components-ready project or create a new one:

uvx create-dagster project my-project && cd my-project/src

Activate the project virtual environment:

source ../.venv/bin/activate

Finally, add the dagster-tableau library to the project:

uv add dagster-tableau

2. Scaffold a Tableau component definition

Now that you have a Dagster project, you can scaffold a Tableau component definition:

dg scaffold defs dagster_tableau.TableauComponent tableau_ingest
Creating defs at /.../my-project/src/my_project/defs/tableau_ingest.

The dg scaffold defs call will generate a defs.yaml file:

tree my_project/defs
my_project/defs
├── __init__.py
└── tableau_ingest
└── defs.yaml

2 directories, 2 files

3. Configure your Tableau workspace

Update the defs.yaml file with your Tableau workspace connection details. You'll need to provide your connected app credentials and site information. For more information on creating a connected app, see the Tableau documentation.

The configuration depends on whether you're using Tableau Cloud or Tableau Server:

For Tableau Cloud, set type: cloud and provide your pod_name:

my_project/defs/tableau_ingest/defs.yaml
type: dagster_tableau.TableauComponent

attributes:
workspace:
type: cloud
connected_app_client_id: "{{ env.TABLEAU_CONNECTED_APP_CLIENT_ID }}"
connected_app_secret_id: "{{ env.TABLEAU_CONNECTED_APP_SECRET_ID }}"
connected_app_secret_value: "{{ env.TABLEAU_CONNECTED_APP_SECRET_VALUE }}"
username: "{{ env.TABLEAU_USERNAME }}"
site_name: "{{ env.TABLEAU_SITE_NAME }}"
pod_name: "{{ env.TABLEAU_POD_NAME }}"
dg list defs
┏━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Section ┃ Definitions ┃
┡━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ Assets │ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┓ │
│ │ ┃ Key ┃ Group ┃ Deps ┃ Kinds ┃ Description ┃ │
│ │ ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━┩ │
│ │ │ superstore_datasource │ default │ │ live │ │ │
│ │ │ │ │ │ published datasource │ │ │
│ │ │ │ │ │ tableau │ │ │
│ │ ├─────────────────────────────────────────┼─────────┼──────┼──────────────────────┼─────────────┤ │
│ │ │ test_workbook/dashboard/dashboard_sales │ default │ │ dashboard │ │ │
│ │ │ │ │ │ tableau │ │ │
│ │ ├─────────────────────────────────────────┼─────────┼──────┼──────────────────────┼─────────────┤ │
│ │ │ test_workbook/sheet/sales │ default │ │ sheet │ │ │
│ │ │ │ │ │ tableau │ │ │
│ │ └─────────────────────────────────────────┴─────────┴──────┴──────────────────────┴─────────────┘ │
└─────────┴───────────────────────────────────────────────────────────────────────────────────────────────────┘

4. Customize Tableau asset metadata

You can customize the metadata and grouping of Tableau assets using the translation key:

my_project/defs/tableau_ingest/defs.yaml
type: dagster_tableau.TableauComponent

attributes:
workspace:
type: cloud
connected_app_client_id: "{{ env.TABLEAU_CONNECTED_APP_CLIENT_ID }}"
connected_app_secret_id: "{{ env.TABLEAU_CONNECTED_APP_SECRET_ID }}"
connected_app_secret_value: "{{ env.TABLEAU_CONNECTED_APP_SECRET_VALUE }}"
username: "{{ env.TABLEAU_USERNAME }}"
site_name: "{{ env.TABLEAU_SITE_NAME }}"
pod_name: "{{ env.TABLEAU_POD_NAME }}"
translation:
group_name: tableau_data
description: "Tableau {{ data.content_type.value }}: {{ data.properties.name }}"
dg list defs
┏━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Section ┃ Definitions ┃
┡━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ Assets │ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┓ │
│ │ ┃ Key ┃ Group ┃ Deps ┃ Kinds ┃ Description ┃ │
│ │ ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━┩ │
│ │ │ superstore_datasource │ tableau_data │ │ live │ Tableau │ │
│ │ │ │ │ │ published │ data_source: │ │
│ │ │ │ │ │ datasource │ superstore_datas… │ │
│ │ │ │ │ │ tableau │ │ │
│ │ ├─────────────────────────────────────────┼──────────────┼──────┼────────────────────┼───────────────────┤ │
│ │ │ test_workbook/dashboard/dashboard_sales │ tableau_data │ │ dashboard │ Tableau │ │
│ │ │ │ │ │ tableau │ dashboard: │ │
│ │ │ │ │ │ │ dashboard_sales │ │
│ │ ├─────────────────────────────────────────┼──────────────┼──────┼────────────────────┼───────────────────┤ │
│ │ │ test_workbook/sheet/sales │ tableau_data │ │ sheet │ Tableau sheet: │ │
│ │ │ │ │ │ tableau │ sales │ │
│ │ └─────────────────────────────────────────┴──────────────┴──────┴────────────────────┴───────────────────┘ │
└─────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

Customize specific data types

You may also specify distinct translation behavior for specific data types. For example, you can add a tag to all sheets:

my_project/defs/tableau_ingest/defs.yaml
type: dagster_tableau.TableauComponent

attributes:
workspace:
type: cloud
connected_app_client_id: "{{ env.TABLEAU_CONNECTED_APP_CLIENT_ID }}"
connected_app_secret_id: "{{ env.TABLEAU_CONNECTED_APP_SECRET_ID }}"
connected_app_secret_value: "{{ env.TABLEAU_CONNECTED_APP_SECRET_VALUE }}"
username: "{{ env.TABLEAU_USERNAME }}"
site_name: "{{ env.TABLEAU_SITE_NAME }}"
pod_name: "{{ env.TABLEAU_POD_NAME }}"
translation:
for_sheet:
tags:
is_sheet: "true"
dg list defs --columns name,kinds,tags
┏━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Section ┃ Definitions ┃
┡━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ Assets │ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ │
│ │ ┃ Key ┃ Kinds ┃ Tags ┃ │
│ │ ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩ │
│ │ │ superstore_datasource │ live │ "dagster-tableau/asset_type"="data_s… │ │
│ │ │ │ published datasource │ "dagster/storage_kind"="tableau" │ │
│ │ │ │ tableau │ │ │
│ │ ├─────────────────────────────────────────┼──────────────────────┼───────────────────────────────────────┤ │
│ │ │ test_workbook/dashboard/dashboard_sales │ dashboard │ "dagster-tableau/asset_type"="dashbo… │ │
│ │ │ │ tableau │ "dagster/storage_kind"="tableau" │ │
│ │ ├─────────────────────────────────────────┼──────────────────────┼───────────────────────────────────────┤ │
│ │ │ test_workbook/sheet/sales │ sheet │ "dagster-tableau/asset_type"="sheet" │ │
│ │ │ │ tableau │ "dagster/storage_kind"="tableau" │ │
│ │ │ │ │ "is_sheet"="true" │ │
│ │ └─────────────────────────────────────────┴──────────────────────┴───────────────────────────────────────┘ │
└─────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────┘