Skip to content

Commit

Permalink
chore: replace selenium user with fixed user (#31844)
Browse files Browse the repository at this point in the history
  • Loading branch information
villebro authored Jan 22, 2025
1 parent 1d6423e commit 7482b20
Show file tree
Hide file tree
Showing 25 changed files with 304 additions and 215 deletions.
1 change: 1 addition & 0 deletions UPDATING.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ assists people when migrating to a new version.

## Next

- [31844](https://github.com/apache/superset/pull/31844) The `ALERT_REPORTS_EXECUTE_AS` and `THUMBNAILS_EXECUTE_AS` config parameters have been renamed to `ALERT_REPORTS_EXECUTORS` and `THUMBNAILS_EXECUTORS` respectively. A new config flag `CACHE_WARMUP_EXECUTORS` has also been introduced to be able to control which user is used to execute cache warmup tasks. Finally, the config flag `THUMBNAILS_SELENIUM_USER` has been removed. To use a fixed executor for async tasks, use the new `FixedExecutor` class. See the config and docs for more info on setting up different executor profiles.
- [31894](https://github.com/apache/superset/pull/31894) Domain sharding is deprecated in favor of HTTP2. The `SUPERSET_WEBSERVER_DOMAINS` configuration will be removed in the next major version (6.0)
- [31774](https://github.com/apache/superset/pull/31774): Fixes the spelling of the `USE-ANALAGOUS-COLORS` feature flag. Please update any scripts/configuration item to use the new/corrected `USE-ANALOGOUS-COLORS` flag spelling.
- [31582](https://github.com/apache/superset/pull/31582) Removed the legacy Area, Bar, Event Flow, Heatmap, Histogram, Line, Sankey, and Sankey Loop charts. They were all automatically migrated to their ECharts counterparts with the exception of the Event Flow and Sankey Loop charts which were removed as they were not actively maintained and not widely used. If you were using the Event Flow or Sankey Loop charts, you will need to find an alternative solution.
Expand Down
5 changes: 2 additions & 3 deletions docs/docs/configuration/alerts-reports.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -177,10 +177,9 @@ By default, Alerts and Reports are executed as the owner of the alert/report obj
just change the config as follows (`admin` in this example):

```python
from superset.tasks.types import ExecutorType
from superset.tasks.types import FixedExecutor

THUMBNAIL_SELENIUM_USER = 'admin'
ALERT_REPORTS_EXECUTE_AS = [ExecutorType.SELENIUM]
ALERT_REPORTS_EXECUTORS = [FixedExecutor("admin")]
```

Please refer to `ExecutorType` in the codebase for other executor types.
Expand Down
7 changes: 2 additions & 5 deletions docs/docs/configuration/cache.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,9 @@ By default thumbnails are rendered per user, and will fall back to the Selenium
To always render thumbnails as a fixed user (`admin` in this example), use the following configuration:

```python
from superset.tasks.types import ExecutorType
from superset.tasks.types import FixedExecutor

THUMBNAIL_SELENIUM_USER = "admin"
THUMBNAIL_EXECUTE_AS = [ExecutorType.SELENIUM]
THUMBNAIL_EXECUTORS = [FixedExecutor("admin")]
```


Expand Down Expand Up @@ -130,8 +129,6 @@ def init_thumbnail_cache(app: Flask) -> S3Cache:


THUMBNAIL_CACHE_CONFIG = init_thumbnail_cache
# Async selenium thumbnail task will use the following user
THUMBNAIL_SELENIUM_USER = "Admin"
```

Using the above example cache keys for dashboards will be `superset_thumb__dashboard__{ID}`. You can
Expand Down
2 changes: 1 addition & 1 deletion superset-frontend/src/components/ListViewCard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ interface CardProps {
subtitle?: ReactNode;
url?: string;
linkComponent?: ComponentType<LinkProps>;
imgURL?: string;
imgURL?: string | null;
imgFallbackURL?: string;
imgPosition?: BackgroundPosition;
description: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ const AddSliceCard: FC<{
lastModified?: string;
sliceName: string;
style?: CSSProperties;
thumbnailUrl?: string;
thumbnailUrl?: string | null;
visType: string;
}> = ({
datasourceUrl,
Expand Down
2 changes: 1 addition & 1 deletion superset-frontend/src/types/Dashboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export interface Dashboard {
slug?: string | null;
url: string;
dashboard_title: string;
thumbnail_url: string;
thumbnail_url: string | null;
published: boolean;
css?: string | null;
json_metadata?: string | null;
Expand Down
2 changes: 1 addition & 1 deletion superset/commands/report/alert.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ def _execute_query(self) -> pd.DataFrame:
)

executor, username = get_executor( # pylint: disable=unused-variable
executor_types=app.config["ALERT_REPORTS_EXECUTE_AS"],
executors=app.config["ALERT_REPORTS_EXECUTORS"],
model=self._report_schedule,
)
user = security_manager.find_user(username)
Expand Down
8 changes: 4 additions & 4 deletions superset/commands/report/execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ def _get_screenshots(self) -> list[bytes]:
:raises: ReportScheduleScreenshotFailedError
"""
_, username = get_executor(
executor_types=app.config["ALERT_REPORTS_EXECUTE_AS"],
executors=app.config["ALERT_REPORTS_EXECUTORS"],
model=self._report_schedule,
)
user = security_manager.find_user(username)
Expand Down Expand Up @@ -360,7 +360,7 @@ def _get_pdf(self) -> bytes:
def _get_csv_data(self) -> bytes:
url = self._get_url(result_format=ChartDataResultFormat.CSV)
_, username = get_executor(
executor_types=app.config["ALERT_REPORTS_EXECUTE_AS"],
executors=app.config["ALERT_REPORTS_EXECUTORS"],
model=self._report_schedule,
)
user = security_manager.find_user(username)
Expand Down Expand Up @@ -389,7 +389,7 @@ def _get_embedded_data(self) -> pd.DataFrame:
"""
url = self._get_url(result_format=ChartDataResultFormat.JSON)
_, username = get_executor(
executor_types=app.config["ALERT_REPORTS_EXECUTE_AS"],
executors=app.config["ALERT_REPORTS_EXECUTORS"],
model=self._report_schedule,
)
user = security_manager.find_user(username)
Expand Down Expand Up @@ -859,7 +859,7 @@ def run(self) -> None:
if not self._model:
raise ReportScheduleExecuteUnexpectedError()
_, username = get_executor(
executor_types=app.config["ALERT_REPORTS_EXECUTE_AS"],
executors=app.config["ALERT_REPORTS_EXECUTORS"],
model=self._model,
)
user = security_manager.find_user(username)
Expand Down
41 changes: 29 additions & 12 deletions superset/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -689,32 +689,46 @@ class D3TimeFormat(TypedDict, total=False):
# This is merely a default
EXTRA_SEQUENTIAL_COLOR_SCHEMES: list[dict[str, Any]] = []

# User used to execute cache warmup tasks
# By default, the cache is warmed up using the primary owner. To fall back to using
# a fixed user (admin in this example), use the following configuration:
#
# from superset.tasks.types import ExecutorType, FixedExecutor
#
# CACHE_WARMUP_EXECUTORS = [ExecutorType.OWNER, FixedExecutor("admin")]
CACHE_WARMUP_EXECUTORS = [ExecutorType.OWNER]

# ---------------------------------------------------
# Thumbnail config (behind feature flag)
# ---------------------------------------------------
# By default, thumbnails are rendered per user, and will fall back to the Selenium
# user for anonymous users. Similar to Alerts & Reports, thumbnails
# can be configured to always be rendered as a fixed user. See
# `superset.tasks.types.ExecutorType` for a full list of executor options.
# To always use a fixed user account, use the following configuration:
# THUMBNAIL_EXECUTE_AS = [ExecutorType.SELENIUM]
THUMBNAIL_SELENIUM_USER: str | None = "admin"
THUMBNAIL_EXECUTE_AS = [ExecutorType.CURRENT_USER, ExecutorType.SELENIUM]
# To always use a fixed user account (admin in this example, use the following
# configuration:
#
# from superset.tasks.types import ExecutorType, FixedExecutor
#
# THUMBNAIL_EXECUTORS = [FixedExecutor("admin")]
THUMBNAIL_EXECUTORS = [ExecutorType.CURRENT_USER]

# By default, thumbnail digests are calculated based on various parameters in the
# chart/dashboard metadata, and in the case of user-specific thumbnails, the
# username. To specify a custom digest function, use the following config parameters
# to define callbacks that receive
# 1. the model (dashboard or chart)
# 2. the executor type (e.g. ExecutorType.SELENIUM)
# 2. the executor type (e.g. ExecutorType.FIXED_USER)
# 3. the executor's username (note, this is the executor as defined by
# `THUMBNAIL_EXECUTE_AS`; the executor is only equal to the currently logged in
# `THUMBNAIL_EXECUTORS`; the executor is only equal to the currently logged in
# user if the executor type is equal to `ExecutorType.CURRENT_USER`)
# and return the final digest string:
THUMBNAIL_DASHBOARD_DIGEST_FUNC: (
None | (Callable[[Dashboard, ExecutorType, str], str])
Callable[[Dashboard, ExecutorType, str], str | None] | None
) = None
THUMBNAIL_CHART_DIGEST_FUNC: Callable[[Slice, ExecutorType, str], str] | None = None
THUMBNAIL_CHART_DIGEST_FUNC: Callable[[Slice, ExecutorType, str], str | None] | None = (
None
)

THUMBNAIL_CACHE_CONFIG: CacheConfig = {
"CACHE_TYPE": "NullCache",
Expand Down Expand Up @@ -1421,16 +1435,19 @@ def EMAIL_HEADER_MUTATOR( # pylint: disable=invalid-name,unused-argument # noq
#
# To first try to execute as the creator in the owners list (if present), then fall
# back to the creator, then the last modifier in the owners list (if present), then the
# last modifier, then an owner and finally `THUMBNAIL_SELENIUM_USER`, set as follows:
# ALERT_REPORTS_EXECUTE_AS = [
# last modifier, then an owner and finally the "admin" user, set as follows:
#
# from superset.tasks.types import ExecutorType, FixedExecutor
#
# ALERT_REPORTS_EXECUTORS = [
# ExecutorType.CREATOR_OWNER,
# ExecutorType.CREATOR,
# ExecutorType.MODIFIER_OWNER,
# ExecutorType.MODIFIER,
# ExecutorType.OWNER,
# ExecutorType.SELENIUM,
# FixedExecutor("admin"),
# ]
ALERT_REPORTS_EXECUTE_AS: list[ExecutorType] = [ExecutorType.OWNER]
ALERT_REPORTS_EXECUTORS: list[ExecutorType] = [ExecutorType.OWNER]
# if ALERT_REPORTS_WORKING_TIME_OUT_KILL is True, set a celery hard timeout
# Equal to working timeout + ALERT_REPORTS_WORKING_TIME_OUT_LAG
ALERT_REPORTS_WORKING_TIME_OUT_LAG = int(timedelta(seconds=10).total_seconds())
Expand Down
2 changes: 1 addition & 1 deletion superset/dashboards/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ class DashboardGetResponseSchema(Schema):
dashboard_title = fields.String(
metadata={"description": dashboard_title_description}
)
thumbnail_url = fields.String()
thumbnail_url = fields.String(allow_none=True)
published = fields.Boolean()
css = fields.String(metadata={"description": css_description})
json_metadata = fields.String(metadata={"description": json_metadata_description})
Expand Down
9 changes: 6 additions & 3 deletions superset/models/dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,16 +225,19 @@ def dashboard_link(self) -> Markup:
return Markup(f'<a href="{self.url}">{title}</a>')

@property
def digest(self) -> str:
def digest(self) -> str | None:
return get_dashboard_digest(self)

@property
def thumbnail_url(self) -> str:
def thumbnail_url(self) -> str | None:
"""
Returns a thumbnail URL with a HEX digest. We want to avoid browser cache
if the dashboard has changed
"""
return f"/api/v1/dashboard/{self.id}/thumbnail/{self.digest}/"
if digest := self.digest:
return f"/api/v1/dashboard/{self.id}/thumbnail/{digest}/"

return None

@property
def changed_by_name(self) -> str:
Expand Down
9 changes: 6 additions & 3 deletions superset/models/slice.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,16 +247,19 @@ def data(self) -> dict[str, Any]:
}

@property
def digest(self) -> str:
def digest(self) -> str | None:
return get_chart_digest(self)

@property
def thumbnail_url(self) -> str:
def thumbnail_url(self) -> str | None:
"""
Returns a thumbnail URL with a HEX digest. We want to avoid browser cache
if the dashboard has changed
"""
return f"/api/v1/chart/{self.id}/thumbnail/{self.digest}/"
if digest := self.digest:
return f"/api/v1/chart/{self.id}/thumbnail/{digest}/"

return None

@property
def json_data(self) -> str:
Expand Down
Loading

0 comments on commit 7482b20

Please sign in to comment.