Source code for operators.superset.add_superset_db_connection
from typing import Any, Dict, Optional
from airflow.exceptions import AirflowException
from airflow.models import BaseOperator
from airflow.utils.decorators import apply_defaults
[docs]
class AddSupersetDbConnectionOperator(BaseOperator):
"""Create a new database connection in Superset via the REST API.
:param database_name: Display label shown in the Superset UI. This is
NOT the actual database name connected to — the real DB is determined
entirely by the ``sqlalchemy_uri``. Free-form; spaces allowed.
:type database_name: str
:param sqlalchemy_uri: SQLAlchemy URI for the database connection.
:type sqlalchemy_uri: str
:param expose_in_sqllab: Whether to expose the database in SQL Lab.
:type expose_in_sqllab: bool
:param allow_ctas: Whether to allow CTAS statements.
:type allow_ctas: bool
:param allow_cvas: Whether to allow CVAS statements.
:type allow_cvas: bool
:param allow_dml: Whether to allow DML statements.
:type allow_dml: bool
:param extra: Optional dict merged into the Superset payload (e.g.
``{"masked_encrypted_extra": "..."}`` or ``{"extra": "..."}``).
:type extra: dict
:param conn_id: Airflow connection id for the Superset instance.
:type conn_id: str
:param base_url: Optional full URL override for the Superset API (e.g.
``"https://dap-tx.bead.example.com"``). When provided, overrides the
connection's host/schema.
:type base_url: str
:param timeout: HTTP request timeout in seconds.
:type timeout: int
:param owner_email: Optional canonical Ready email (e.g.
``majid@ready.net``). When set, resolves to a single Superset
user and adds them to the DB's owner list alongside the API
user. DAP stores emails with a per-tenant ``+<uuid>`` suffix;
this resolver matches both shapes. Important when the API user
is going to be disabled later in the run — the resolved
end-user is what keeps DAP's owner-based visibility filter
from hiding the DB from listings post-disable.
:type owner_email: str
"""
template_fields = (
"database_name",
"sqlalchemy_uri",
"extra",
"conn_id",
"base_url",
"owner_email",
)
ui_color = "#fce4ec"
@apply_defaults
def __init__(
self,
database_name: str,
sqlalchemy_uri: str,
expose_in_sqllab: bool = True,
allow_ctas: bool = False,
allow_cvas: bool = False,
allow_dml: bool = False,
extra: Optional[Dict[str, Any]] = None,
conn_id: str = "superset_default",
base_url: Optional[str] = None,
timeout: int = 30,
owner_email: Optional[str] = None,
*args,
**kwargs,
):
super().__init__(*args, **kwargs)
self.database_name = database_name
self.sqlalchemy_uri = sqlalchemy_uri
self.expose_in_sqllab = expose_in_sqllab
self.allow_ctas = allow_ctas
self.allow_cvas = allow_cvas
self.allow_dml = allow_dml
self.extra = extra
self.conn_id = conn_id
self.base_url = base_url
self.timeout = timeout
self.owner_email = owner_email
[docs]
def execute(self, context) -> Dict[str, Any]:
from hooks.superset_hook import SupersetHook
if not self.database_name:
raise AirflowException("Missing required field: database_name")
if not self.sqlalchemy_uri:
raise AirflowException("Missing required field: sqlalchemy_uri")
hook = SupersetHook(
conn_id=self.conn_id, base_url=self.base_url, timeout=self.timeout
)
extra_owners = []
if self.owner_email:
user = hook.find_user_by_email(self.owner_email)
extra_owners.append(int(user["id"]))
self.log.info(
"Resolved owner_email '%s' to Superset user id=%s email=%s",
self.owner_email, extra_owners[0], user.get("email"),
)
self.log.info("Adding Superset database connection '%s'", self.database_name)
result = hook.add_db_connection(
database_name=self.database_name,
sqlalchemy_uri=self.sqlalchemy_uri,
expose_in_sqllab=self.expose_in_sqllab,
allow_ctas=self.allow_ctas,
allow_cvas=self.allow_cvas,
allow_dml=self.allow_dml,
extra=self.extra,
owners=extra_owners or None,
)
self.log.info("Add database result: %s", result)
return result